[fine] More resilience

We don't lose function declarations and whatnot, although we get lost
with broken return types.
This commit is contained in:
John Doty 2024-01-31 07:46:20 -08:00
parent 93c9dcd13b
commit 7f30d0ccc3
3 changed files with 98 additions and 39 deletions

View file

@ -480,10 +480,6 @@ impl<'a> CParser<'a> {
});
}
fn synchronize(&mut self) {
if self.panic {}
}
fn build_tree(self) -> (SyntaxTree<'a>, Lines) {
let mut events = self.events;
let mut stack = Vec::new();
@ -551,7 +547,15 @@ fn file(p: &mut CParser) {
// the right-brace that a block would end with.)
p.advance_with_error("unbalanced '}'");
}
_ => statement(p),
_ => {
if !statement(p) {
if p.at_any(STATEMENT_RECOVERY) {
break;
} else {
p.advance_with_error("expected statement");
}
}
}
}
}
p.end(m, TreeKind::File);
@ -715,19 +719,35 @@ fn type_parameter(p: &mut CParser) {
p.end(m, TreeKind::TypeParameter);
}
const STATEMENT_RECOVERY: &[TokenKind] = &[
TokenKind::RightBrace,
TokenKind::Fun,
TokenKind::LeftBrace,
TokenKind::Let,
TokenKind::Return,
TokenKind::For,
TokenKind::Class,
];
fn block(p: &mut CParser) {
let m = p.start();
p.expect_start(TokenKind::LeftBrace);
while !p.at(TokenKind::RightBrace) && !p.eof() {
statement(p);
if !statement(p) {
if p.at_any(STATEMENT_RECOVERY) {
break;
} else {
p.advance_with_error("expected statement");
}
}
}
p.expect(TokenKind::RightBrace, "expect '}' to end a block");
p.end(m, TreeKind::Block);
}
fn statement(p: &mut CParser) {
fn statement(p: &mut CParser) -> bool {
match p.peek() {
TokenKind::Fun => function(p),
TokenKind::LeftBrace => block(p),
@ -739,8 +759,16 @@ fn statement(p: &mut CParser) {
// require a semicolon at the end if it's all by itself.
TokenKind::If => statement_if(p),
_ => statement_expression(p),
_ => {
if p.at(TokenKind::Semicolon) || p.at_any(EXPRESSION_FIRST) {
statement_expression(p)
} else {
return false;
}
}
}
true
}
fn statement_if(p: &mut CParser) {
@ -758,7 +786,9 @@ fn statement_let(p: &mut CParser) {
p.expect_start(TokenKind::Let);
p.expect(TokenKind::Identifier, "expected a name for the variable");
p.expect(TokenKind::Equal, "expected a '=' after the variable name");
expression(p);
if p.at_any(EXPRESSION_FIRST) {
expression(p);
}
if !p.at(TokenKind::RightBrace) {
p.expect(TokenKind::Semicolon, "expect ';' to end a let statement");
}
@ -770,8 +800,10 @@ fn statement_return(p: &mut CParser) {
let m = p.start();
p.expect_start(TokenKind::Return);
// TODO: Make expression optional if we're returning ()
expression(p);
if p.at_any(EXPRESSION_FIRST) {
// TODO: Make expression optional if we're returning ()
expression(p);
}
if !p.at(TokenKind::RightBrace) {
p.expect(TokenKind::Semicolon, "expect ';' to end a return statement");
}
@ -788,8 +820,12 @@ fn statement_for(p: &mut CParser) {
"expected an identifier for the loop variable",
);
p.expect(TokenKind::In, "expect an 'in' after the loop variable");
expression(p);
block(p);
if p.at_any(EXPRESSION_FIRST) {
expression(p);
}
if p.at(TokenKind::LeftBrace) {
block(p);
}
p.end(m, TreeKind::ForStatement);
}
@ -797,7 +833,7 @@ fn statement_for(p: &mut CParser) {
fn statement_expression(p: &mut CParser) {
let m = p.start();
if !p.at(TokenKind::RightBrace) && !p.at(TokenKind::Semicolon) {
if p.at_any(EXPRESSION_FIRST) {
expression(p);
}
if !p.at(TokenKind::RightBrace) {
@ -810,6 +846,21 @@ fn statement_expression(p: &mut CParser) {
p.end(m, TreeKind::ExpressionStatement);
}
const EXPRESSION_FIRST: &[TokenKind] = &[
TokenKind::Number,
TokenKind::String,
TokenKind::True,
TokenKind::False,
TokenKind::LeftParen,
TokenKind::Bang,
TokenKind::Minus,
TokenKind::If,
TokenKind::Identifier,
TokenKind::Selff,
TokenKind::LeftBracket,
TokenKind::New,
];
fn expression(p: &mut CParser) {
expression_with_power(p, 0)
}
@ -840,7 +891,9 @@ fn infix_power(token: TokenKind) -> Option<(u8, u8)> {
}
fn expression_with_power(p: &mut CParser, minimum_power: u8) {
let mut expr = prefix_expression(p);
let Some(mut expr) = prefix_expression(p) else {
return;
};
while p.at(TokenKind::LeftParen) {
let m = p.start_before(expr);
argument_list(p);
@ -877,7 +930,11 @@ fn argument_list(p: &mut CParser) {
p.expect_start(TokenKind::LeftParen);
while !p.at(TokenKind::RightParen) && !p.eof() {
argument(p);
if p.at_any(EXPRESSION_FIRST) {
argument(p);
} else {
break;
}
}
p.expect(
TokenKind::RightParen,
@ -898,8 +955,8 @@ fn argument(p: &mut CParser) {
p.end(m, TreeKind::Argument);
}
fn prefix_expression(p: &mut CParser) -> MarkClosed {
match p.peek() {
fn prefix_expression(p: &mut CParser) -> Option<MarkClosed> {
let result = match p.peek() {
TokenKind::Number => literal(p),
TokenKind::String => literal(p),
TokenKind::True => literal(p),
@ -919,8 +976,12 @@ fn prefix_expression(p: &mut CParser) -> MarkClosed {
TokenKind::New => object_constructor(p),
_ => p.advance_with_error("expected an expression"),
}
_ => {
assert!(!p.at_any(EXPRESSION_FIRST));
return None;
}
};
Some(result)
}
fn literal(p: &mut CParser) -> MarkClosed {
@ -995,7 +1056,11 @@ fn list_constructor(p: &mut CParser) -> MarkClosed {
p.expect_start(TokenKind::LeftBracket);
while !p.at(TokenKind::RightBracket) && !p.eof() {
list_constructor_element(p);
if p.at_any(EXPRESSION_FIRST) {
list_constructor_element(p);
} else {
break;
}
}
p.expect(
TokenKind::RightBracket,