feat: 更新错误处理机制,增强词法分析器和解析器的错误报告功能
This commit is contained in:
@@ -2,13 +2,35 @@ use crate::lexer::Token;
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum RuntimeError {
|
pub enum RuntimeError {
|
||||||
|
LexError { message: String, line: usize, column: usize },
|
||||||
ParseError { message: String, token: Token },
|
ParseError { message: String, token: Token },
|
||||||
RuntimeError { message: String, token: Option<Token> },
|
RuntimeError { message: String, token: Option<Token> },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl RuntimeError {
|
||||||
|
pub fn lex(message: impl Into<String>, line: usize, column: usize) -> Self {
|
||||||
|
RuntimeError::LexError {
|
||||||
|
message: message.into(),
|
||||||
|
line,
|
||||||
|
column,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse(message: impl Into<String>, token: Token) -> Self {
|
||||||
|
RuntimeError::ParseError {
|
||||||
|
message: message.into(),
|
||||||
|
token,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for RuntimeError {
|
impl std::fmt::Display for RuntimeError {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
|
RuntimeError::LexError { message, line, column } => {
|
||||||
|
write!(f, "[Lex Error] {} at line {}, column {}", message, line, column)
|
||||||
|
}
|
||||||
RuntimeError::ParseError { message, token } => {
|
RuntimeError::ParseError { message, token } => {
|
||||||
write!(f, "[Parse Error] {} at line {}, column {}", message, token.line, token.column)
|
write!(f, "[Parse Error] {} at line {}, column {}", message, token.line, token.column)
|
||||||
}
|
}
|
||||||
|
|||||||
+27
-12
@@ -1,6 +1,7 @@
|
|||||||
// src/lexer/lexer.rs
|
// src/lexer/lexer.rs
|
||||||
|
|
||||||
use super::{Token, TokenKind};
|
use super::{Token, TokenKind};
|
||||||
|
use crate::error::RuntimeError;
|
||||||
|
|
||||||
pub struct Lexer {
|
pub struct Lexer {
|
||||||
src: Vec<char>,
|
src: Vec<char>,
|
||||||
@@ -19,11 +20,12 @@ impl Lexer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tokenize(mut self) -> Vec<Token> {
|
pub fn tokenize(mut self) -> (Vec<Token>, Vec<RuntimeError>) {
|
||||||
let mut tokens = Vec::new();
|
let mut tokens = Vec::new();
|
||||||
|
let mut errors = Vec::new();
|
||||||
|
|
||||||
while !self.is_at_end() {
|
while !self.is_at_end() {
|
||||||
if let Some(token) = self.next_token() {
|
if let Some(token) = self.next_token(&mut errors) {
|
||||||
tokens.push(token);
|
tokens.push(token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -34,10 +36,10 @@ impl Lexer {
|
|||||||
column: self.column,
|
column: self.column,
|
||||||
});
|
});
|
||||||
|
|
||||||
tokens
|
(tokens, errors)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_token(&mut self) -> Option<Token> {
|
fn next_token(&mut self, errors: &mut Vec<RuntimeError>) -> Option<Token> {
|
||||||
self.skip_whitespace();
|
self.skip_whitespace();
|
||||||
|
|
||||||
if self.is_at_end() {
|
if self.is_at_end() {
|
||||||
@@ -140,7 +142,8 @@ impl Lexer {
|
|||||||
if self.match_char('&') {
|
if self.match_char('&') {
|
||||||
TokenKind::AndAnd
|
TokenKind::AndAnd
|
||||||
} else {
|
} else {
|
||||||
panic!("Unexpected '&' at {}:{}", line, column);
|
errors.push(RuntimeError::lex("Unexpected '&'. Did you mean '&&'?", line, column));
|
||||||
|
return None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,11 +151,12 @@ impl Lexer {
|
|||||||
if self.match_char('|') {
|
if self.match_char('|') {
|
||||||
TokenKind::OrOr
|
TokenKind::OrOr
|
||||||
} else {
|
} else {
|
||||||
panic!("Unexpected '|' at {}:{}", line, column);
|
errors.push(RuntimeError::lex("Unexpected '|'. Did you mean '||'?", line, column));
|
||||||
|
return None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
'"' => return Some(self.string_literal(line, column)),
|
'"' => return self.string_literal(line, column, errors),
|
||||||
|
|
||||||
c if c.is_ascii_digit() => {
|
c if c.is_ascii_digit() => {
|
||||||
return Some(self.number_literal(c, line, column));
|
return Some(self.number_literal(c, line, column));
|
||||||
@@ -163,7 +167,12 @@ impl Lexer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
panic!("Unexpected character '{}' at {}:{}", c, line, column);
|
errors.push(RuntimeError::lex(
|
||||||
|
format!("Unexpected character '{}'", c),
|
||||||
|
line,
|
||||||
|
column,
|
||||||
|
));
|
||||||
|
return None;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -215,7 +224,12 @@ impl Lexer {
|
|||||||
self.current >= self.src.len()
|
self.current >= self.src.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn string_literal(&mut self, line: usize, column: usize) -> Token {
|
fn string_literal(
|
||||||
|
&mut self,
|
||||||
|
line: usize,
|
||||||
|
column: usize,
|
||||||
|
errors: &mut Vec<RuntimeError>,
|
||||||
|
) -> Option<Token> {
|
||||||
let mut value = String::new();
|
let mut value = String::new();
|
||||||
|
|
||||||
while !self.is_at_end() && self.peek() != '"' {
|
while !self.is_at_end() && self.peek() != '"' {
|
||||||
@@ -223,16 +237,17 @@ impl Lexer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if self.is_at_end() {
|
if self.is_at_end() {
|
||||||
panic!("Unterminated string at {}:{}", line, column);
|
errors.push(RuntimeError::lex("Unterminated string literal", line, column));
|
||||||
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.advance(); // consume closing "
|
self.advance(); // consume closing "
|
||||||
|
|
||||||
Token {
|
Some(Token {
|
||||||
kind: TokenKind::String(value),
|
kind: TokenKind::String(value),
|
||||||
line,
|
line,
|
||||||
column,
|
column,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn number_literal(&mut self, first: char, line: usize, column: usize) -> Token {
|
fn number_literal(&mut self, first: char, line: usize, column: usize) -> Token {
|
||||||
|
|||||||
+30
-5
@@ -7,21 +7,37 @@ mod error;
|
|||||||
use lexer::Lexer;
|
use lexer::Lexer;
|
||||||
use parser::Parser;
|
use parser::Parser;
|
||||||
use interpreter::Interpreter;
|
use interpreter::Interpreter;
|
||||||
|
use error::RuntimeError;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::io::stdin;
|
use std::io::stdin;
|
||||||
use std::io::stdout;
|
use std::io::stdout;
|
||||||
|
|
||||||
|
fn print_errors(errors: &[RuntimeError]) {
|
||||||
|
for err in errors {
|
||||||
|
eprintln!("{}", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn run_file(src: String) {
|
fn run_file(src: String) {
|
||||||
let tokens = Lexer::new(&src).tokenize();
|
let (tokens, lex_errors) = Lexer::new(&src).tokenize();
|
||||||
|
if !lex_errors.is_empty() {
|
||||||
|
print_errors(&lex_errors);
|
||||||
|
std::process::exit(65);
|
||||||
|
}
|
||||||
|
|
||||||
let mut parser = Parser::new(tokens);
|
let mut parser = Parser::new(tokens);
|
||||||
let stmts = parser.parse();
|
let (stmts, parse_errors) = parser.parse();
|
||||||
|
if !parse_errors.is_empty() {
|
||||||
|
print_errors(&parse_errors);
|
||||||
|
std::process::exit(65);
|
||||||
|
}
|
||||||
|
|
||||||
let mut interpreter = Interpreter::new();
|
let mut interpreter = Interpreter::new();
|
||||||
if let Err(e) = interpreter.interpret(stmts) {
|
if let Err(e) = interpreter.interpret(stmts) {
|
||||||
eprintln!("Error: {}", e);
|
eprintln!("Error: {}", e);
|
||||||
std::process::exit(1);
|
std::process::exit(70);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,9 +77,18 @@ fn run_repl() {
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
let tokens = Lexer::new(line).tokenize();
|
let (tokens, lex_errors) = Lexer::new(line).tokenize();
|
||||||
|
if !lex_errors.is_empty() {
|
||||||
|
print_errors(&lex_errors);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
let mut parser = Parser::new(tokens);
|
let mut parser = Parser::new(tokens);
|
||||||
let stmts = parser.parse();
|
let (stmts, parse_errors) = parser.parse();
|
||||||
|
if !parse_errors.is_empty() {
|
||||||
|
print_errors(&parse_errors);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if let Err(e) = interpreter.interpret(stmts) {
|
if let Err(e) = interpreter.interpret(stmts) {
|
||||||
eprintln!("Error: {}", e);
|
eprintln!("Error: {}", e);
|
||||||
|
|||||||
+161
-138
@@ -12,17 +12,24 @@ impl Parser {
|
|||||||
Self { tokens, current: 0 }
|
Self { tokens, current: 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(&mut self) -> Vec<Stmt> {
|
pub fn parse(&mut self) -> (Vec<Stmt>, Vec<RuntimeError>) {
|
||||||
let mut statements = Vec::new();
|
let mut statements = Vec::new();
|
||||||
|
let mut errors = Vec::new();
|
||||||
|
|
||||||
while !self.is_at_end() {
|
while !self.is_at_end() {
|
||||||
statements.push(self.declaration());
|
match self.declaration() {
|
||||||
|
Ok(stmt) => statements.push(stmt),
|
||||||
|
Err(err) => {
|
||||||
|
errors.push(err);
|
||||||
|
self.synchronize();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
statements
|
(statements, errors)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn declaration(&mut self) -> Stmt {
|
fn declaration(&mut self) -> Result<Stmt, RuntimeError> {
|
||||||
if self.match_kind(&[TokenKind::Let]) {
|
if self.match_kind(&[TokenKind::Let]) {
|
||||||
self.let_declaration()
|
self.let_declaration()
|
||||||
} else if self.match_kind(&[TokenKind::Fn]) {
|
} else if self.match_kind(&[TokenKind::Fn]) {
|
||||||
@@ -32,7 +39,7 @@ impl Parser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn statement(&mut self) -> Stmt {
|
fn statement(&mut self) -> Result<Stmt, RuntimeError> {
|
||||||
if self.match_kind(&[TokenKind::If]) {
|
if self.match_kind(&[TokenKind::If]) {
|
||||||
self.if_statement()
|
self.if_statement()
|
||||||
} else if self.match_kind(&[TokenKind::While]) {
|
} else if self.match_kind(&[TokenKind::While]) {
|
||||||
@@ -46,161 +53,161 @@ impl Parser {
|
|||||||
} else if self.match_kind(&[TokenKind::Return]) {
|
} else if self.match_kind(&[TokenKind::Return]) {
|
||||||
self.return_statement()
|
self.return_statement()
|
||||||
} else if self.match_kind(&[TokenKind::LeftBrace]) {
|
} else if self.match_kind(&[TokenKind::LeftBrace]) {
|
||||||
Stmt::Block(self.block())
|
Ok(Stmt::Block(self.block()?))
|
||||||
} else {
|
} else {
|
||||||
self.expression_statement()
|
self.expression_statement()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn let_declaration(&mut self) -> Stmt {
|
fn let_declaration(&mut self) -> Result<Stmt, RuntimeError> {
|
||||||
let name = self.consume_ident("Expected variable name.").unwrap();
|
let name = self.consume_ident("Expected variable name.")?;
|
||||||
self.consume(TokenKind::Equal, "Expected '=' after variable name.").unwrap();
|
self.consume(TokenKind::Equal, "Expected '=' after variable name.")?;
|
||||||
let initializer = self.expression();
|
let initializer = self.expression()?;
|
||||||
self.match_kind(&[TokenKind::Semicolon]); // 分号可选
|
self.match_kind(&[TokenKind::Semicolon]); // 分号可选
|
||||||
|
|
||||||
Stmt::Let { name, initializer }
|
Ok(Stmt::Let { name, initializer })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fn_declaration(&mut self) -> Stmt {
|
fn fn_declaration(&mut self) -> Result<Stmt, RuntimeError> {
|
||||||
let name = self.consume_ident("Expected function name.").unwrap();
|
let name = self.consume_ident("Expected function name.")?;
|
||||||
self.consume(TokenKind::LeftParen, "Expected '(' after function name.").unwrap();
|
self.consume(TokenKind::LeftParen, "Expected '(' after function name.")?;
|
||||||
|
|
||||||
let mut params = Vec::new();
|
let mut params = Vec::new();
|
||||||
if !self.check(&TokenKind::RightParen) {
|
if !self.check(&TokenKind::RightParen) {
|
||||||
loop {
|
loop {
|
||||||
params.push(self.consume_ident("Expected parameter name.").unwrap());
|
params.push(self.consume_ident("Expected parameter name.")?);
|
||||||
if !self.match_kind(&[TokenKind::Comma]) {
|
if !self.match_kind(&[TokenKind::Comma]) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.consume(TokenKind::RightParen, "Expected ')' after parameters.").unwrap();
|
self.consume(TokenKind::RightParen, "Expected ')' after parameters.")?;
|
||||||
self.consume(TokenKind::LeftBrace, "Expected '{' before function body.").unwrap();
|
self.consume(TokenKind::LeftBrace, "Expected '{' before function body.")?;
|
||||||
let body = self.block();
|
let body = self.block()?;
|
||||||
|
|
||||||
Stmt::Function { name, params, body }
|
Ok(Stmt::Function { name, params, body })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lambda_expr(&mut self) -> Expr {
|
fn lambda_expr(&mut self) -> Result<Expr, RuntimeError> {
|
||||||
self.consume(TokenKind::LeftParen, "Expected '(' after 'fn'.").unwrap();
|
self.consume(TokenKind::LeftParen, "Expected '(' after 'fn'.")?;
|
||||||
let mut params = Vec::new();
|
let mut params = Vec::new();
|
||||||
if !self.check(&TokenKind::RightParen) {
|
if !self.check(&TokenKind::RightParen) {
|
||||||
loop {
|
loop {
|
||||||
params.push(self.consume_ident("Expected parameter name.").unwrap());
|
params.push(self.consume_ident("Expected parameter name.")?);
|
||||||
if !self.match_kind(&[TokenKind::Comma]) {
|
if !self.match_kind(&[TokenKind::Comma]) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.consume(TokenKind::RightParen, "Expected ')' after parameters.").unwrap();
|
self.consume(TokenKind::RightParen, "Expected ')' after parameters.")?;
|
||||||
self.consume(TokenKind::LeftBrace, "Expected '{' before function body.").unwrap();
|
self.consume(TokenKind::LeftBrace, "Expected '{' before function body.")?;
|
||||||
let body = self.block();
|
let body = self.block()?;
|
||||||
Expr::Lambda { params, body }
|
Ok(Expr::Lambda { params, body })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn if_statement(&mut self) -> Stmt {
|
fn if_statement(&mut self) -> Result<Stmt, RuntimeError> {
|
||||||
self.consume(TokenKind::LeftParen, "Expected '(' after 'if'.").unwrap();
|
self.consume(TokenKind::LeftParen, "Expected '(' after 'if'.")?;
|
||||||
let condition = self.expression();
|
let condition = self.expression()?;
|
||||||
self.consume(TokenKind::RightParen, "Expected ')' after condition.").unwrap();
|
self.consume(TokenKind::RightParen, "Expected ')' after condition.")?;
|
||||||
|
|
||||||
let then_branch = Box::new(self.statement());
|
let then_branch = Box::new(self.statement()?);
|
||||||
let else_branch = if self.match_kind(&[TokenKind::Else]) {
|
let else_branch = if self.match_kind(&[TokenKind::Else]) {
|
||||||
Some(Box::new(self.statement()))
|
Some(Box::new(self.statement()?))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
Stmt::If { condition, then_branch, else_branch }
|
Ok(Stmt::If { condition, then_branch, else_branch })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn while_statement(&mut self) -> Stmt {
|
fn while_statement(&mut self) -> Result<Stmt, RuntimeError> {
|
||||||
self.consume(TokenKind::LeftParen, "Expected '(' after 'while'.").unwrap();
|
self.consume(TokenKind::LeftParen, "Expected '(' after 'while'.")?;
|
||||||
let condition = self.expression();
|
let condition = self.expression()?;
|
||||||
self.consume(TokenKind::RightParen, "Expected ')' after condition.").unwrap();
|
self.consume(TokenKind::RightParen, "Expected ')' after condition.")?;
|
||||||
|
|
||||||
let body = Box::new(self.statement());
|
let body = Box::new(self.statement()?);
|
||||||
Stmt::While { condition, body }
|
Ok(Stmt::While { condition, body })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn for_statement(&mut self) -> Stmt {
|
fn for_statement(&mut self) -> Result<Stmt, RuntimeError> {
|
||||||
self.consume(TokenKind::LeftParen, "Expected '(' after 'for'.").unwrap();
|
self.consume(TokenKind::LeftParen, "Expected '(' after 'for'.")?;
|
||||||
let initializer = if self.match_kind(&[TokenKind::Semicolon]) {
|
let initializer = if self.match_kind(&[TokenKind::Semicolon]) {
|
||||||
None
|
None
|
||||||
} else if self.match_kind(&[TokenKind::Let]) {
|
} else if self.match_kind(&[TokenKind::Let]) {
|
||||||
Some(self.let_declaration())
|
Some(self.let_declaration()?)
|
||||||
} else {
|
} else {
|
||||||
Some(self.expression_statement())
|
Some(self.expression_statement()?)
|
||||||
};
|
};
|
||||||
|
|
||||||
let condition = if !self.check(&TokenKind::Semicolon) {
|
let condition = if !self.check(&TokenKind::Semicolon) {
|
||||||
Some(self.expression())
|
Some(self.expression()?)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
self.consume(TokenKind::Semicolon, "Expected ';' after loop condition.").unwrap();
|
self.consume(TokenKind::Semicolon, "Expected ';' after loop condition.")?;
|
||||||
let step = if !self.check(&TokenKind::RightParen) {
|
let step = if !self.check(&TokenKind::RightParen) {
|
||||||
Some(self.expression())
|
Some(self.expression()?)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
self.consume(TokenKind::RightParen, "Expected ')' after for clauses.").unwrap();
|
self.consume(TokenKind::RightParen, "Expected ')' after for clauses.")?;
|
||||||
let body = Box::new(self.statement());
|
let body = Box::new(self.statement()?);
|
||||||
|
|
||||||
Stmt::For {
|
Ok(Stmt::For {
|
||||||
initializer: initializer.map(Box::new),
|
initializer: initializer.map(Box::new),
|
||||||
condition,
|
condition,
|
||||||
step,
|
step,
|
||||||
body
|
body
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn break_statement(&mut self) -> Stmt {
|
fn break_statement(&mut self) -> Result<Stmt, RuntimeError> {
|
||||||
self.match_kind(&[TokenKind::Semicolon]); // 分号可选
|
self.match_kind(&[TokenKind::Semicolon]); // 分号可选
|
||||||
Stmt::Break
|
Ok(Stmt::Break)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn continue_statement(&mut self) -> Stmt {
|
fn continue_statement(&mut self) -> Result<Stmt, RuntimeError> {
|
||||||
self.match_kind(&[TokenKind::Semicolon]); // 分号可选
|
self.match_kind(&[TokenKind::Semicolon]); // 分号可选
|
||||||
Stmt::Continue
|
Ok(Stmt::Continue)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn return_statement(&mut self) -> Stmt {
|
fn return_statement(&mut self) -> Result<Stmt, RuntimeError> {
|
||||||
let value = if !self.check(&TokenKind::Semicolon) && !self.check(&TokenKind::RightBrace) {
|
let value = if !self.check(&TokenKind::Semicolon) && !self.check(&TokenKind::RightBrace) {
|
||||||
Some(self.expression())
|
Some(self.expression()?)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
self.match_kind(&[TokenKind::Semicolon]); // 分号可选
|
self.match_kind(&[TokenKind::Semicolon]); // 分号可选
|
||||||
Stmt::Return(value)
|
Ok(Stmt::Return(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn block(&mut self) -> Vec<Stmt> {
|
fn block(&mut self) -> Result<Vec<Stmt>, RuntimeError> {
|
||||||
let mut statements = Vec::new();
|
let mut statements = Vec::new();
|
||||||
|
|
||||||
while !self.check(&TokenKind::RightBrace) && !self.is_at_end() {
|
while !self.check(&TokenKind::RightBrace) && !self.is_at_end() {
|
||||||
statements.push(self.declaration());
|
statements.push(self.declaration()?);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.consume(TokenKind::RightBrace, "Expected '}' after block.").unwrap();
|
self.consume(TokenKind::RightBrace, "Expected '}' after block.")?;
|
||||||
statements
|
Ok(statements)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expression_statement(&mut self) -> Stmt {
|
fn expression_statement(&mut self) -> Result<Stmt, RuntimeError> {
|
||||||
let expr = self.expression();
|
let expr = self.expression()?;
|
||||||
self.match_kind(&[TokenKind::Semicolon]); // 分号可选
|
self.match_kind(&[TokenKind::Semicolon]); // 分号可选
|
||||||
Stmt::ExprStmt(expr)
|
Ok(Stmt::ExprStmt(expr))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expression(&mut self) -> Expr {
|
fn expression(&mut self) -> Result<Expr, RuntimeError> {
|
||||||
self.assignment()
|
self.assignment()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assignment(&mut self) -> Expr {
|
fn assignment(&mut self) -> Result<Expr, RuntimeError> {
|
||||||
let expr = self.logical_or();
|
let expr = self.logical_or()?;
|
||||||
|
|
||||||
let op = if self.match_kind(&[TokenKind::Equal]) {
|
let op = if self.match_kind(&[TokenKind::Equal]) {
|
||||||
Some(AssignOp::Equal)
|
Some(AssignOp::Equal)
|
||||||
@@ -219,23 +226,23 @@ impl Parser {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if let Some(op) = op {
|
if let Some(op) = op {
|
||||||
let value = self.assignment();
|
let value = self.assignment()?;
|
||||||
return match expr {
|
return match expr {
|
||||||
Expr::Variable(name) => Expr::Assign { name, op, value: Box::new(value) },
|
Expr::Variable(name) => Ok(Expr::Assign { name, op, value: Box::new(value) }),
|
||||||
Expr::Get { object, name } => Expr::Set { object, name, op, value: Box::new(value) },
|
Expr::Get { object, name } => Ok(Expr::Set { object, name, op, value: Box::new(value) }),
|
||||||
Expr::IndexGet { array, index } => Expr::IndexSet { array, index, op, value: Box::new(value) },
|
Expr::IndexGet { array, index } => Ok(Expr::IndexSet { array, index, op, value: Box::new(value) }),
|
||||||
_ => panic!("Invalid assignment target."),
|
_ => Err(RuntimeError::parse("Invalid assignment target.", self.previous().clone())),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
expr
|
Ok(expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn logical_or(&mut self) -> Expr {
|
fn logical_or(&mut self) -> Result<Expr, RuntimeError> {
|
||||||
let mut expr = self.logical_and();
|
let mut expr = self.logical_and()?;
|
||||||
|
|
||||||
while self.match_kind(&[TokenKind::OrOr]) {
|
while self.match_kind(&[TokenKind::OrOr]) {
|
||||||
let right = self.logical_and();
|
let right = self.logical_and()?;
|
||||||
expr = Expr::Logical {
|
expr = Expr::Logical {
|
||||||
left: Box::new(expr),
|
left: Box::new(expr),
|
||||||
op: LogicalOp::Or,
|
op: LogicalOp::Or,
|
||||||
@@ -243,14 +250,14 @@ impl Parser {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
expr
|
Ok(expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn logical_and(&mut self) -> Expr {
|
fn logical_and(&mut self) -> Result<Expr, RuntimeError> {
|
||||||
let mut expr = self.equality();
|
let mut expr = self.equality()?;
|
||||||
|
|
||||||
while self.match_kind(&[TokenKind::AndAnd]) {
|
while self.match_kind(&[TokenKind::AndAnd]) {
|
||||||
let right = self.equality();
|
let right = self.equality()?;
|
||||||
expr = Expr::Logical {
|
expr = Expr::Logical {
|
||||||
left: Box::new(expr),
|
left: Box::new(expr),
|
||||||
op: LogicalOp::And,
|
op: LogicalOp::And,
|
||||||
@@ -258,11 +265,11 @@ impl Parser {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
expr
|
Ok(expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn equality(&mut self) -> Expr {
|
fn equality(&mut self) -> Result<Expr, RuntimeError> {
|
||||||
let mut expr = self.comparison();
|
let mut expr = self.comparison()?;
|
||||||
|
|
||||||
while self.match_kind(&[TokenKind::EqualEqual, TokenKind::BangEqual]) {
|
while self.match_kind(&[TokenKind::EqualEqual, TokenKind::BangEqual]) {
|
||||||
let op = match self.previous().kind {
|
let op = match self.previous().kind {
|
||||||
@@ -270,7 +277,7 @@ impl Parser {
|
|||||||
TokenKind::BangEqual => BinaryOp::NotEqual,
|
TokenKind::BangEqual => BinaryOp::NotEqual,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
let right = self.comparison();
|
let right = self.comparison()?;
|
||||||
expr = Expr::Binary {
|
expr = Expr::Binary {
|
||||||
left: Box::new(expr),
|
left: Box::new(expr),
|
||||||
op,
|
op,
|
||||||
@@ -278,11 +285,11 @@ impl Parser {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
expr
|
Ok(expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn comparison(&mut self) -> Expr {
|
fn comparison(&mut self) -> Result<Expr, RuntimeError> {
|
||||||
let mut expr = self.term();
|
let mut expr = self.term()?;
|
||||||
|
|
||||||
while self.match_kind(&[TokenKind::Greater, TokenKind::GreaterEqual, TokenKind::Less, TokenKind::LessEqual]) {
|
while self.match_kind(&[TokenKind::Greater, TokenKind::GreaterEqual, TokenKind::Less, TokenKind::LessEqual]) {
|
||||||
let op = match self.previous().kind {
|
let op = match self.previous().kind {
|
||||||
@@ -292,7 +299,7 @@ impl Parser {
|
|||||||
TokenKind::LessEqual => BinaryOp::LessEqual,
|
TokenKind::LessEqual => BinaryOp::LessEqual,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
let right = self.term();
|
let right = self.term()?;
|
||||||
expr = Expr::Binary {
|
expr = Expr::Binary {
|
||||||
left: Box::new(expr),
|
left: Box::new(expr),
|
||||||
op,
|
op,
|
||||||
@@ -300,11 +307,11 @@ impl Parser {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
expr
|
Ok(expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn term(&mut self) -> Expr {
|
fn term(&mut self) -> Result<Expr, RuntimeError> {
|
||||||
let mut expr = self.factor();
|
let mut expr = self.factor()?;
|
||||||
|
|
||||||
while self.match_kind(&[TokenKind::Plus, TokenKind::Minus]) {
|
while self.match_kind(&[TokenKind::Plus, TokenKind::Minus]) {
|
||||||
let op = match self.previous().kind {
|
let op = match self.previous().kind {
|
||||||
@@ -312,7 +319,7 @@ impl Parser {
|
|||||||
TokenKind::Minus => BinaryOp::Sub,
|
TokenKind::Minus => BinaryOp::Sub,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
let right = self.factor();
|
let right = self.factor()?;
|
||||||
expr = Expr::Binary {
|
expr = Expr::Binary {
|
||||||
left: Box::new(expr),
|
left: Box::new(expr),
|
||||||
op,
|
op,
|
||||||
@@ -320,11 +327,11 @@ impl Parser {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
expr
|
Ok(expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn factor(&mut self) -> Expr {
|
fn factor(&mut self) -> Result<Expr, RuntimeError> {
|
||||||
let mut expr = self.unary();
|
let mut expr = self.unary()?;
|
||||||
|
|
||||||
while self.match_kind(&[TokenKind::Star, TokenKind::Slash, TokenKind::Percent]) {
|
while self.match_kind(&[TokenKind::Star, TokenKind::Slash, TokenKind::Percent]) {
|
||||||
let op = match self.previous().kind {
|
let op = match self.previous().kind {
|
||||||
@@ -333,7 +340,7 @@ impl Parser {
|
|||||||
TokenKind::Percent => BinaryOp::Mod,
|
TokenKind::Percent => BinaryOp::Mod,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
let right = self.unary();
|
let right = self.unary()?;
|
||||||
expr = Expr::Binary {
|
expr = Expr::Binary {
|
||||||
left: Box::new(expr),
|
left: Box::new(expr),
|
||||||
op,
|
op,
|
||||||
@@ -341,54 +348,54 @@ impl Parser {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
expr
|
Ok(expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unary(&mut self) -> Expr {
|
fn unary(&mut self) -> Result<Expr, RuntimeError> {
|
||||||
if self.match_kind(&[TokenKind::Bang, TokenKind::Minus]) {
|
if self.match_kind(&[TokenKind::Bang, TokenKind::Minus]) {
|
||||||
let op = match self.previous().kind {
|
let op = match self.previous().kind {
|
||||||
TokenKind::Bang => UnaryOp::Not,
|
TokenKind::Bang => UnaryOp::Not,
|
||||||
TokenKind::Minus => UnaryOp::Negate,
|
TokenKind::Minus => UnaryOp::Negate,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
let right = self.unary();
|
let right = self.unary()?;
|
||||||
return Expr::Unary {
|
return Ok(Expr::Unary {
|
||||||
op,
|
op,
|
||||||
right: Box::new(right),
|
right: Box::new(right),
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
self.call()
|
self.call()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(&mut self) -> Expr {
|
fn call(&mut self) -> Result<Expr, RuntimeError> {
|
||||||
let mut expr = self.primary();
|
let mut expr = self.primary()?;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
if self.match_kind(&[TokenKind::LeftParen]) {
|
if self.match_kind(&[TokenKind::LeftParen]) {
|
||||||
let mut arguments = Vec::new();
|
let mut arguments = Vec::new();
|
||||||
if !self.check(&TokenKind::RightParen) {
|
if !self.check(&TokenKind::RightParen) {
|
||||||
loop {
|
loop {
|
||||||
arguments.push(self.expression());
|
arguments.push(self.expression()?);
|
||||||
if !self.match_kind(&[TokenKind::Comma]) {
|
if !self.match_kind(&[TokenKind::Comma]) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.consume(TokenKind::RightParen, "Expected ')' after arguments.").unwrap();
|
self.consume(TokenKind::RightParen, "Expected ')' after arguments.")?;
|
||||||
expr = Expr::Call {
|
expr = Expr::Call {
|
||||||
callee: Box::new(expr),
|
callee: Box::new(expr),
|
||||||
arguments,
|
arguments,
|
||||||
};
|
};
|
||||||
} else if self.match_kind(&[TokenKind::Dot]) {
|
} else if self.match_kind(&[TokenKind::Dot]) {
|
||||||
let name = self.consume_ident("Expected property name after '.'.").unwrap();
|
let name = self.consume_ident("Expected property name after '.'.")?;
|
||||||
expr = Expr::Get {
|
expr = Expr::Get {
|
||||||
object: Box::new(expr),
|
object: Box::new(expr),
|
||||||
name,
|
name,
|
||||||
};
|
};
|
||||||
} else if self.match_kind(&[TokenKind::LeftBracket]) {
|
} else if self.match_kind(&[TokenKind::LeftBracket]) {
|
||||||
let index = self.expression();
|
let index = self.expression()?;
|
||||||
self.consume(TokenKind::RightBracket, "Expected ']' after index.").unwrap();
|
self.consume(TokenKind::RightBracket, "Expected ']' after index.")?;
|
||||||
expr = Expr::IndexGet {
|
expr = Expr::IndexGet {
|
||||||
array: Box::new(expr),
|
array: Box::new(expr),
|
||||||
index: Box::new(index),
|
index: Box::new(index),
|
||||||
@@ -398,39 +405,39 @@ impl Parser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
expr
|
Ok(expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn primary(&mut self) -> Expr {
|
fn primary(&mut self) -> Result<Expr, RuntimeError> {
|
||||||
// 布尔值
|
// 布尔值
|
||||||
if self.match_kind(&[TokenKind::True]) {
|
if self.match_kind(&[TokenKind::True]) {
|
||||||
return Expr::Literal(Literal::Bool(true));
|
return Ok(Expr::Literal(Literal::Bool(true)));
|
||||||
}
|
}
|
||||||
if self.match_kind(&[TokenKind::False]) {
|
if self.match_kind(&[TokenKind::False]) {
|
||||||
return Expr::Literal(Literal::Bool(false));
|
return Ok(Expr::Literal(Literal::Bool(false)));
|
||||||
}
|
}
|
||||||
if self.match_kind(&[TokenKind::Nil]) {
|
if self.match_kind(&[TokenKind::Nil]) {
|
||||||
return Expr::Literal(Literal::Nil);
|
return Ok(Expr::Literal(Literal::Nil));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 数字
|
// 数字
|
||||||
if let TokenKind::Number(n) = self.peek().kind {
|
if let TokenKind::Number(n) = self.peek().kind {
|
||||||
self.advance();
|
self.advance();
|
||||||
return Expr::Literal(Literal::Number(n));
|
return Ok(Expr::Literal(Literal::Number(n)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 字符串
|
// 字符串
|
||||||
if let TokenKind::String(s) = &self.peek().kind {
|
if let TokenKind::String(s) = &self.peek().kind {
|
||||||
let s = s.clone();
|
let s = s.clone();
|
||||||
self.advance();
|
self.advance();
|
||||||
return Expr::Literal(Literal::String(s));
|
return Ok(Expr::Literal(Literal::String(s)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 标识符(变量)
|
// 标识符(变量)
|
||||||
if let TokenKind::Identifier(name) = &self.peek().kind {
|
if let TokenKind::Identifier(name) = &self.peek().kind {
|
||||||
let name = name.clone();
|
let name = name.clone();
|
||||||
self.advance();
|
self.advance();
|
||||||
return Expr::Variable(name);
|
return Ok(Expr::Variable(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 匿名函数(闭包): fn(params) { body }
|
// 匿名函数(闭包): fn(params) { body }
|
||||||
@@ -440,9 +447,9 @@ impl Parser {
|
|||||||
|
|
||||||
// 括号表达式
|
// 括号表达式
|
||||||
if self.match_kind(&[TokenKind::LeftParen]) {
|
if self.match_kind(&[TokenKind::LeftParen]) {
|
||||||
let expr = self.expression();
|
let expr = self.expression()?;
|
||||||
self.consume(TokenKind::RightParen, "Expected ')' after expression.").unwrap();
|
self.consume(TokenKind::RightParen, "Expected ')' after expression.")?;
|
||||||
return expr;
|
return Ok(expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.match_kind(&[TokenKind::LeftBrace]) {
|
if self.match_kind(&[TokenKind::LeftBrace]) {
|
||||||
@@ -453,7 +460,7 @@ impl Parser {
|
|||||||
return self.array_literal();
|
return self.array_literal();
|
||||||
}
|
}
|
||||||
|
|
||||||
panic!("Expected expression at line {}", self.peek().line);
|
Err(RuntimeError::parse("Expected expression.", self.peek().clone()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn match_kind(&mut self, kinds: &[TokenKind]) -> bool {
|
fn match_kind(&mut self, kinds: &[TokenKind]) -> bool {
|
||||||
@@ -471,10 +478,7 @@ impl Parser {
|
|||||||
self.advance();
|
self.advance();
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(RuntimeError::ParseError {
|
Err(RuntimeError::parse(msg, self.peek().clone()))
|
||||||
message: msg.to_string(),
|
|
||||||
token: self.peek().clone(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -485,10 +489,7 @@ impl Parser {
|
|||||||
self.advance();
|
self.advance();
|
||||||
Ok(name)
|
Ok(name)
|
||||||
}
|
}
|
||||||
_ => Err(RuntimeError::ParseError {
|
_ => Err(RuntimeError::parse(msg, self.peek().clone())),
|
||||||
message: msg.to_string(),
|
|
||||||
token: self.peek().clone(),
|
|
||||||
}),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -519,34 +520,56 @@ impl Parser {
|
|||||||
&self.tokens[self.current - 1]
|
&self.tokens[self.current - 1]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn object_literal(&mut self) -> Expr {
|
fn object_literal(&mut self) -> Result<Expr, RuntimeError> {
|
||||||
let mut properties = Vec::new();
|
let mut properties = Vec::new();
|
||||||
if !self.check(&TokenKind::RightBrace) {
|
if !self.check(&TokenKind::RightBrace) {
|
||||||
loop {
|
loop {
|
||||||
let name = self.consume_ident("Expected property name in object literal").unwrap();
|
let name = self.consume_ident("Expected property name in object literal")?;
|
||||||
self.consume(TokenKind::Colon, "Expected ':' after property name in object literal").unwrap();
|
self.consume(TokenKind::Colon, "Expected ':' after property name in object literal")?;
|
||||||
let value = self.expression();
|
let value = self.expression()?;
|
||||||
properties.push((name, value));
|
properties.push((name, value));
|
||||||
if !self.match_kind(&[TokenKind::Comma]) {
|
if !self.match_kind(&[TokenKind::Comma]) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.consume(TokenKind::RightBrace, "Expected '}' after object literal").unwrap();
|
self.consume(TokenKind::RightBrace, "Expected '}' after object literal")?;
|
||||||
Expr::ObjectLiteral { properties }
|
Ok(Expr::ObjectLiteral { properties })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn array_literal(&mut self) -> Expr {
|
fn array_literal(&mut self) -> Result<Expr, RuntimeError> {
|
||||||
let mut elements = Vec::new();
|
let mut elements = Vec::new();
|
||||||
if !self.check(&TokenKind::RightBracket) {
|
if !self.check(&TokenKind::RightBracket) {
|
||||||
loop {
|
loop {
|
||||||
elements.push(self.expression());
|
elements.push(self.expression()?);
|
||||||
if !self.match_kind(&[TokenKind::Comma]) {
|
if !self.match_kind(&[TokenKind::Comma]) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.consume(TokenKind::RightBracket, "Expected ']' after array literal").unwrap();
|
self.consume(TokenKind::RightBracket, "Expected ']' after array literal")?;
|
||||||
Expr::ArrayLiteral { elements }
|
Ok(Expr::ArrayLiteral { elements })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn synchronize(&mut self) {
|
||||||
|
while !self.is_at_end() {
|
||||||
|
if self.current > 0 && matches!(self.previous().kind, TokenKind::Semicolon) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
match self.peek().kind {
|
||||||
|
TokenKind::Let
|
||||||
|
| TokenKind::Fn
|
||||||
|
| TokenKind::If
|
||||||
|
| TokenKind::While
|
||||||
|
| TokenKind::For
|
||||||
|
| TokenKind::Return
|
||||||
|
| TokenKind::Break
|
||||||
|
| TokenKind::Continue => return,
|
||||||
|
_ => {
|
||||||
|
self.advance();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user