From f2e82942dfc8ed544e82578a13c540084c4eae77 Mon Sep 17 00:00:00 2001 From: John Doty Date: Mon, 29 Jan 2024 10:04:47 -0800 Subject: [PATCH] [fine] Some resilience, a design improvement for iterator --- fine/src/parser.rs | 24 +++++++++++++++---- fine/tests/expression/alternates.fine | 6 ++++- .../expression/errors/broken_conditional.fine | 1 - .../expression/errors/wild_member_access.fine | 6 ++++- 4 files changed, 29 insertions(+), 8 deletions(-) diff --git a/fine/src/parser.rs b/fine/src/parser.rs index e8bd273d..374260b7 100644 --- a/fine/src/parser.rs +++ b/fine/src/parser.rs @@ -318,6 +318,7 @@ struct CParser<'a> { current: Token<'a>, fuel: Cell, events: Vec>, + panic: bool, } impl<'a> CParser<'a> { @@ -327,6 +328,7 @@ impl<'a> CParser<'a> { current: Token::new(TokenKind::EOF, 0, ""), fuel: Cell::new(256), events: Vec::new(), + panic: false, }; parser.current = parser.tokens.next(); parser.skip_ephemera(); @@ -412,6 +414,7 @@ impl<'a> CParser<'a> { fn eat(&mut self, kind: TokenKind) -> bool { if self.at(kind) { + self.panic = false; // Check self.advance(); true } else { @@ -454,6 +457,11 @@ impl<'a> CParser<'a> { where T: Into, { + if self.panic { + return; + } + self.panic = true; + let message: String = message.into(); let mut final_message = "Error ".to_string(); @@ -472,6 +480,10 @@ 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(); @@ -599,21 +611,23 @@ fn field_decl(p: &mut CParser) { p.end(m, TreeKind::FieldDecl); } -const PARAM_LIST_RECOVERY: &[TokenKind] = &[TokenKind::Arrow, TokenKind::LeftBrace, TokenKind::Fun]; +const PARAM_LIST_RECOVERY: &[TokenKind] = &[ + TokenKind::Arrow, + TokenKind::LeftBrace, + TokenKind::Fun, + TokenKind::RightParen, +]; fn param_list(p: &mut CParser) { let m = p.start(); p.expect_start(TokenKind::LeftParen); - while !p.at(TokenKind::RightParen) && !p.eof() { + while !p.at_any(PARAM_LIST_RECOVERY) && !p.eof() { if p.at(TokenKind::Identifier) { parameter(p); } else if p.at(TokenKind::Selff) { self_parameter(p); } else { - if p.at_any(PARAM_LIST_RECOVERY) { - break; - } p.advance_with_error("expected parameter"); } } diff --git a/fine/tests/expression/alternates.fine b/fine/tests/expression/alternates.fine index 8ee2ebb4..79304484 100644 --- a/fine/tests/expression/alternates.fine +++ b/fine/tests/expression/alternates.fine @@ -83,16 +83,20 @@ fun more_examples(weapon: MeleeWeapon or RangedWeapon) -> f64 or () { } // Some fun with iterators +class Finished {} +let FINISHED = new Finished {} class Iterator { current: f64; - fun next(self) -> f64 or () { + fun next(self) -> f64 or Finished { if self.current < 10 { let result = self.current; self.current = self.current + 1; return result; } + + FINISHED } } diff --git a/fine/tests/expression/errors/broken_conditional.fine b/fine/tests/expression/errors/broken_conditional.fine index 84efd0cb..dbcfe35c 100644 --- a/fine/tests/expression/errors/broken_conditional.fine +++ b/fine/tests/expression/errors/broken_conditional.fine @@ -5,4 +5,3 @@ fun test() { // NOTE: These errors should be better // @expect-errors: // | 2:10: Error at 'true': expected a block after `if` -// | 2:15: Error at '{': expect ';' to end an expression statement diff --git a/fine/tests/expression/errors/wild_member_access.fine b/fine/tests/expression/errors/wild_member_access.fine index 649b6f2d..f1c47c2d 100644 --- a/fine/tests/expression/errors/wild_member_access.fine +++ b/fine/tests/expression/errors/wild_member_access.fine @@ -11,8 +11,12 @@ fun test() { // We need to make sure things are parsed correctly. // // TODO: Better parser recovery will improve the specifics of the errors. +// +// TODO: This is parsed wrong; the `{` is consumed after the '.' and it +// should instead be ignored. This is the "greedy" expression parsing that +// matklad talks about in his resilient parser article. +// // @expect-errors: // | 7:12: Error at '{': expected an expression -// | 7:13: Error at 'let': expect ';' to end a let statement // | 7:26: cannot find value foo here // | 8:0: Error at '}': unbalanced '}'