Skip to content
This repository was archived by the owner on Mar 12, 2025. It is now read-only.

Commit 446f828

Browse files
committed
1.1.0
1 parent b303104 commit 446f828

File tree

6 files changed

+359
-260
lines changed

6 files changed

+359
-260
lines changed

GiraffeInterpreter/src/lib.rs

+247-239
Large diffs are not rendered by default.

GiraffeLanguage/Cargo.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ edition = "2021"
77
GiraffeInterpreter ={ path = "../GiraffeInterpreter"}
88
GiraffeLexer = { path = "../GiraffeLexer" }
99
GiraffeAST = { path = "../GiraffeAST"}
10-
GiraffeParser ={ path = "../GiraffeParser"}
10+
GiraffeParser ={ path = "../GiraffeParser"}
11+
colored = "2.0"

GiraffeLanguage/src/main.rs

+47-4
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,50 @@
11
use std::env;
22
use std::fs;
3+
use colored::*;
34
use std::process;
45
use GiraffeLexer::Lexer;
56
use GiraffeParser::Parser;
67
use GiraffeInterpreter::interpret;
78

9+
10+
fn print_error(title: &str, details: &[(&str, String)], filename: &str, line: usize, column: usize) {
11+
let absolute_path = match fs::canonicalize(filename) {
12+
Ok(path) => path.display().to_string(),
13+
Err(_) => filename.to_string(),
14+
};
15+
16+
eprintln!("{}", format!("error: {}", title).red().bold());
17+
18+
eprintln!(" --> {}:{}:{}", absolute_path, line, column);
19+
eprintln!(" |");
20+
21+
for (label, value) in details {
22+
eprintln!("{} {}", label.green().bold(), value);
23+
}
24+
25+
eprintln!(" |");
26+
eprintln!(" | ^");
27+
eprintln!();
28+
}
29+
830
fn main() {
931
let args: Vec<String> = env::args().collect();
1032
if args.len() < 2 {
11-
eprintln!("Usage: {} <filename>", args[0]);
33+
eprintln!("{}", "Использование: <filename>".red().bold());
1234
process::exit(1);
1335
}
1436

1537
let filename = &args[1];
1638
let source_code = match fs::read_to_string(filename) {
1739
Ok(content) => content,
1840
Err(err) => {
19-
eprintln!("Ошибка при чтении файла {}: {}", filename, err);
41+
print_error(
42+
"Ошибка при чтении файла",
43+
&[("Детали", err.to_string())],
44+
filename,
45+
0,
46+
0,
47+
);
2048
process::exit(1);
2149
}
2250
};
@@ -31,12 +59,27 @@ fn main() {
3159
if let Ok(program) = program {
3260
interpret(program);
3361
} else {
34-
eprintln!("Ошибка при парсинге программы!");
62+
let error_token = parser.get_current_token();
63+
print_error(
64+
"Ошибка при парсинге программы",
65+
&[
66+
("Найденное значение", error_token.value.clone())
67+
],
68+
filename,
69+
error_token.line,
70+
error_token.column,
71+
);
3572
process::exit(1);
3673
}
3774
},
3875
Err(err) => {
39-
eprintln!("Ошибка токенизации: {:?}", err);
76+
print_error(
77+
"Ошибка токенизации",
78+
&[("Детали", format!("{:?}", err))],
79+
filename,
80+
0,
81+
0,
82+
);
4083
process::exit(1);
4184
}
4285
}

GiraffeLexer/src/lib.rs

+27-10
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,17 @@ pub enum TokenType {
5151
pub struct Token {
5252
pub token_type: TokenType,
5353
pub value: String,
54+
pub line: usize,
55+
pub column: usize,
5456
}
5557

5658
impl Token {
57-
pub fn new(token_type: TokenType, value: &str) -> Self {
59+
pub fn new(token_type: TokenType, value: &str, line: usize, column: usize) -> Self {
5860
Token {
5961
token_type,
6062
value: value.to_string(),
63+
line,
64+
column,
6165
}
6266
}
6367
}
@@ -74,7 +78,7 @@ impl Lexer {
7478
for kw in &[
7579
"const", "func", "var", "if", "elif", "else", "while", "for",
7680
"continue", "break", "return", "is", "in", "and", "or", "not",
77-
"try", "handle", "finally"
81+
"try", "handle", "finally", "get"
7882
] {
7983
keywords.insert(kw.to_string(), TokenType::KEYWORD);
8084
}
@@ -155,38 +159,51 @@ impl Lexer {
155159
let mut tokens = Vec::new();
156160
let mut position = 0;
157161
let code_len = code.len();
162+
163+
let mut line = 1;
164+
let mut column = 1;
158165

159166
while position < code_len {
160167
let slice = &code[position..];
161168
let mut matched = false;
162169

163170
for (regex, token_type_opt) in &self.regex_patterns {
164171
if let Some(mat) = regex.find(slice) {
165-
// Благодаря якорю, совпадение должно начинаться с 0
166172
if mat.start() != 0 {
167173
continue;
168174
}
169175
let value = &slice[mat.start()..mat.end()];
170-
// Если шаблон возвращает None – пропускаем (например, пробелы)
176+
171177
if let Some(token_type) = token_type_opt {
172-
tokens.push(Token::new(token_type.clone(), value));
178+
tokens.push(Token::new(token_type.clone(), value, line, column));
173179
}
180+
181+
for ch in value.chars() {
182+
if ch == '\n' {
183+
line += 1;
184+
column = 1;
185+
} else {
186+
column += 1;
187+
}
188+
}
189+
174190
position += mat.end();
175191
matched = true;
176192
break;
177193
}
178194
}
179195

180196
if !matched {
197+
let err_char = code[position..].chars().next().unwrap();
181198
return Err(format!(
182-
"Нераспознанный символ на позиции {}: '{}'",
183-
position,
184-
&code[position..].chars().next().unwrap()
199+
"Нераспознанный символ на позиции {} (line {}, column {}): '{}'",
200+
position, line, column, err_char
185201
));
186202
}
187203
}
188204

189-
tokens.push(Token::new(TokenType::EOF, "EOF"));
205+
// Добавляем токен EOF с текущими координатами
206+
tokens.push(Token::new(TokenType::EOF, "EOF", line, column));
190207
Ok(tokens)
191208
}
192-
}
209+
}

GiraffeParser/src/lib.rs

+28-5
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,25 @@
11
use GiraffeAST::*;
22
use GiraffeLexer::{Token, TokenType};
3-
use std::collections::HashMap;
43
use ordered_float::OrderedFloat;
54

65

76
/// Структура парсера, содержащая список токенов и текущую позицию в них.
87
pub struct Parser {
98
tokens: Vec<Token>,
109
pos: usize,
10+
code_line: usize,
11+
code_pos: usize,
1112
}
1213

1314
impl Parser {
1415
/// Создаёт новый парсер на основе вектора токенов.
1516
pub fn new(tokens: Vec<Token>) -> Self {
16-
Parser { tokens, pos: 0 }
17+
Parser {
18+
tokens,
19+
pos: 0,
20+
code_pos: 0,
21+
code_line: 1,
22+
}
1723
}
1824

1925
/// Возвращает текущий токен.
@@ -24,9 +30,13 @@ impl Parser {
2430
/// Переходит к следующему токену.
2531
fn advance(&mut self) {
2632
if self.pos < self.tokens.len() {
33+
let token = &self.tokens[self.pos];
34+
self.code_line = token.line;
35+
self.code_pos = token.column;
36+
2737
self.pos += 1;
2838
}
29-
}
39+
}
3040

3141
/// Проверяет, достигнут ли конец входного потока.
3242
fn is_at_end(&self) -> bool {
@@ -154,9 +164,10 @@ impl Parser {
154164
if self.peek_token_is(TokenType::OPERATOR, Some("=")) {
155165
self.parse_assignment()
156166
} else {
157-
Err(format!("Неожиданный идентификатор: {}", token.value))
167+
let expr = self.parse_expression()?;
168+
Ok(Statement::ExpressionStatement(expr))
158169
}
159-
}
170+
}
160171
_ => Err(format!("Неожиданный токен в операторе: {:?}", token)),
161172
}
162173
}
@@ -788,4 +799,16 @@ impl Parser {
788799
let token = self.current();
789800
token.token_type == TokenType::KEYWORD && token.value == kw
790801
}
802+
803+
// =========================================================================
804+
// Вспомогательные функции для составления ошибок
805+
// =========================================================================
806+
807+
pub fn get_current_position(&self) -> usize {
808+
return self.pos;
809+
}
810+
811+
pub fn get_current_token(&self) -> Token {
812+
return self.tokens[self.pos].clone();
813+
}
791814
}

TODO.md

+8-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@
1919
- [x] `TryHandleStatement` (try-catch-finally)
2020
- [x] `ReturnStatement` (возврат значений из функций)
2121
- [x] `Break/Continue` (выход из цикла)
22+
- [ ] Диапазоны (range для цикла for)
23+
24+
- [ ] Модули
25+
- [ ] Импорты (`.gfe` файлы)
26+
- [ ] API интерпритатора для библиотек
27+
- [ ] IO библиотека
28+
2229

2330
- [x] **Обработка выражений** (`Expression`)
2431
- [x] Литералы (`Literal`)
@@ -36,7 +43,7 @@
3643
- [x] Логические операции (`&&`, `||`)
3744

3845
#### **3. Ошибки**
39-
- [?] Вывод ошибок в понятном формате (`Error(String)`)
46+
- [x] Вывод ошибок в понятном формате (`Error(String)`)
4047
- [ ] Поддержка исключений (`TryHandleStatement`)
4148

4249
#### **4. Дополнительно**

0 commit comments

Comments
 (0)