Skip to content

Commit

Permalink
parser(error): refactor error handling
Browse files Browse the repository at this point in the history
  • Loading branch information
chanbengz committed Dec 7, 2024
1 parent fb79e74 commit e1c97bb
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 59 deletions.
95 changes: 38 additions & 57 deletions src/parser/src/grammar.lalrpop
Original file line number Diff line number Diff line change
Expand Up @@ -74,23 +74,22 @@ ArgList: Vec<Box<tree::CompExpr>> = {
}

VarDecs: Vec<tree::Variable> = {
<l:@L> <mut v:VarDecs> "," <e:VarDec?> <r:@R> => match e {
None => {
if v.len() != 0 {
let error = ErrorRecovery {
error: ParseError::User {
error: LexicalError::MissingLexeme(Span {
source: source.to_string(),
start: l,
end: r
}, "variable name".to_string())
}, dropped_tokens: Vec::new(),
};
errors.push(error);
}
v
},
Some(e) => { v.push(e); v }
VarDecs "," <l:@L> ! <r:@R> => {
let error = ErrorRecovery {
error: ParseError::User {
error: LexicalError::MissingLexeme(Span {
source: source.to_string(),
start: l,
end: r
}, "variable name".to_string())
}, dropped_tokens: Vec::new(),
};
errors.push(error);
Vec::new()
},
<l:@L> <mut v:VarDecs> "," <e:VarDec> <r:@R> => {
v.push(e);
v
},
<e:VarDec> => vec![e],
}
Expand Down Expand Up @@ -419,7 +418,7 @@ OpenExpr: tree::Expr = {
error: LexicalError::MissingLexeme(Span {
source: source.to_string(),
start: l,
end: r
end: l + 1
}, "opening parenthesis '('".to_string())
},
dropped_tokens: Vec::new(),
Expand All @@ -434,35 +433,14 @@ OpenExpr: tree::Expr = {
error: LexicalError::MissingLexeme(Span {
source: source.to_string(),
start: l,
end: r
end: l + 1
}, "closing parenthesis ')'".to_string())
},
dropped_tokens: Vec::new(),
};
errors.push(error);
tree::Expr::Error
},

// TODO:remove this
<l:@L> <error:!> <r:@R> => match &error.error {
ParseError::UnrecognizedToken { token, expected } => {
if token.1 == Token::KeywordElse {
let error = ErrorRecovery {
error: ParseError::User {
error: LexicalError::StatementError(Span {
source: source.to_string(),
start: l,
end: r
}, "no 'if' before 'else'".to_string())
},
dropped_tokens: Vec::new(),
};
errors.push(error);
}
tree::Expr::Error
},
_ => tree::Expr::Error
},
}

CloseExpr: tree::Expr = {
Expand Down Expand Up @@ -552,14 +530,14 @@ CloseExpr: tree::Expr = {
errors.push(error);
tree::Expr::Error
},
! <l:@L> "=" CompExpr? ";" <r:@R> => {
<l:@R> ! <r:@R> <expr:CloseExpr> => {
let error = ErrorRecovery {
error: ParseError::User {
error: LexicalError::StatementError(Span {
source: source.to_string(),
start: l,
end: r
}, "Unexpected statement".to_string())
}, "No 'if' before 'else'".to_string())
},
dropped_tokens: Vec::new(),
};
Expand Down Expand Up @@ -608,23 +586,11 @@ WhileExpr: tree::Expr = {

ForExpr: tree::Expr = {
"for" "(" <init:VarManagement?> ";" <cond:CondExpr?> ";" <update:VarManagement?> ")" "{" <body:Body> "}" => {
let init = match init {
Some(init) => init,
None => tree::Expr::VarManagement(Vec::new())
};
let cond = match cond {
Some(cond) => cond,
None => Box::new(tree::CondExpr::Bool(true))
};
let update = match update {
Some(update) => update,
None => tree::Expr::VarManagement(Vec::new())
};
tree::Expr::Loop(
tree::Loop::ForExpr(
Box::new(init),
cond,
Box::new(update),
init.map(Box::new).unwrap_or(Box::new(tree::Expr::VarManagement(Vec::new()))),
cond.unwrap_or(Box::new(tree::CondExpr::Bool(true))),
update.map(Box::new).unwrap_or(Box::new(tree::Expr::VarManagement(Vec::new()))),
body
)
)
Expand Down Expand Up @@ -786,6 +752,21 @@ VarDec: tree::Variable = {
errors.push(error);
tree::Variable::Error
},

! <l:@L> "=" CompExpr <r:@R> => {
let error = ErrorRecovery {
error: ParseError::User {
error: LexicalError::StatementError(Span {
source: source.to_string(),
start: l,
end: r
}, "Unexpected statement".to_string())
},
dropped_tokens: Vec::new(),
};
errors.push(error);
tree::Variable::Error
},
}

StructDec: tree::Variable = {
Expand Down
2 changes: 1 addition & 1 deletion src/parser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ mod tests {
Parser::BodyParser => assert_eq!(format!("{}", BodyParser::new().parse(&mut errors, file_path, lexer).unwrap()), expected),
Parser::ProgramParser => {
let result = ProgramParser::new().parse(&mut errors, file_path, lexer)
.unwrap_or_else(|_| panic!("Failed to parse file: {}", file_path));
.unwrap_or_else(|e| panic!("Failed to parse file: {}\n{}", file_path, e));
if errors.len() > 0 {
let mut error_str = Vec::new();
for error in &errors {
Expand Down
2 changes: 1 addition & 1 deletion src/test/phase1/extra/test_1_s08.out
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Error type B at Line 11: no 'if' before 'else'
Error type B at Line 11: No 'if' before 'else'

0 comments on commit e1c97bb

Please sign in to comment.