Browse Source

fix the parser for most case

Tamo 1 year ago
parent
commit
0486487d4c
1 changed files with 36 additions and 12 deletions
  1. 36 12
      numbat/src/parser.rs

+ 36 - 12
numbat/src/parser.rs

@@ -305,7 +305,22 @@ impl<'a> Parser<'a> {
                 TokenKind::Eof => {
                     break;
                 }
-                _ => {}
+                TokenKind::Equal => {
+                    errors.push(ParseError {
+                        kind: ParseErrorKind::TrailingEqualSign(
+                            self.last().unwrap().lexeme.clone(),
+                        ),
+                        span: self.peek().span,
+                    });
+                    self.recover_from_error();
+                }
+                _ => {
+                    errors.push(ParseError {
+                        kind: ParseErrorKind::TrailingCharacters(self.peek().lexeme.clone()),
+                        span: self.peek().span,
+                    });
+                    self.recover_from_error();
+                }
             }
         }
 
@@ -546,22 +561,31 @@ impl<'a> Parser<'a> {
                 None
             };
 
-            let body = if self.match_exact(TokenKind::Equal).is_none() {
-                None
+            let (body, local_variables) = if self.match_exact(TokenKind::Equal).is_none() {
+                (None, vec![])
             } else {
                 self.skip_empty_lines();
-                Some(self.expression()?)
-            };
+                let body = self.expression()?;
 
-            let mut local_variables = Vec::new();
-            self.skip_empty_lines();
-            if self.match_exact(TokenKind::Where).is_some() {
+                // After parsing the `where` statement we have eaten all
+                // the newlines. We're not supposed to do that.
+                // We'll resume the parser to where we were at before doing that.
+                let mut step_back_to = self.current;
+
+                let mut local_variables = Vec::new();
                 self.skip_empty_lines();
-                while let Ok(local_variable) = self.parse_variable() {
-                    local_variables.push(local_variable);
+                if self.match_exact(TokenKind::Where).is_some() {
+                    step_back_to = self.current;
                     self.skip_empty_lines();
+                    while let Ok(local_variable) = self.parse_variable() {
+                        local_variables.push(local_variable);
+                        step_back_to = self.current;
+                        self.skip_empty_lines();
+                    }
                 }
-            }
+                self.current = step_back_to;
+                (Some(body), local_variables)
+            };
 
             if decorator::contains_aliases(&self.decorator_stack) {
                 return Err(ParseError {
@@ -3275,7 +3299,7 @@ mod tests {
             assert_eq(tamo + cool == 80)
             30m"), @r###"
         Successfully parsed:
-        DefineVariable { identifier_span: Span { start: SourceCodePositition { byte: 17, line: 2, position: 17 }, end: SourceCodePositition { byte: 21, line: 2, position: 21 }, code_source_id: 0 }, identifier: "cool", expr: Scalar(Span { start: SourceCodePositition { byte: 24, line: 2, position: 24 }, end: SourceCodePositition { byte: 26, line: 2, position: 26 }, code_source_id: 0 }, Number(50.0)), type_annotation: None, decorators: [] }
+        DefineVariable(DefineVariable { identifier_span: Span { start: SourceCodePositition { byte: 17, line: 2, position: 17 }, end: SourceCodePositition { byte: 21, line: 2, position: 21 }, code_source_id: 0 }, identifier: "cool", expr: Scalar(Span { start: SourceCodePositition { byte: 24, line: 2, position: 24 }, end: SourceCodePositition { byte: 26, line: 2, position: 26 }, code_source_id: 0 }, Number(50.0)), type_annotation: None, decorators: [] })
         ProcedureCall(Span { start: SourceCodePositition { byte: 68, line: 4, position: 13 }, end: SourceCodePositition { byte: 77, line: 4, position: 22 }, code_source_id: 0 }, AssertEq, [BinaryOperator { op: Equal, lhs: BinaryOperator { op: Add, lhs: Identifier(Span { start: SourceCodePositition { byte: 78, line: 4, position: 23 }, end: SourceCodePositition { byte: 82, line: 4, position: 27 }, code_source_id: 0 }, "tamo"), rhs: Identifier(Span { start: SourceCodePositition { byte: 85, line: 4, position: 30 }, end: SourceCodePositition { byte: 89, line: 4, position: 34 }, code_source_id: 0 }, "cool"), span_op: Some(Span { start: SourceCodePositition { byte: 83, line: 4, position: 28 }, end: SourceCodePositition { byte: 84, line: 4, position: 29 }, code_source_id: 0 }) }, rhs: Scalar(Span { start: SourceCodePositition { byte: 93, line: 4, position: 38 }, end: SourceCodePositition { byte: 95, line: 4, position: 40 }, code_source_id: 0 }, Number(80.0)), span_op: Some(Span { start: SourceCodePositition { byte: 90, line: 4, position: 35 }, end: SourceCodePositition { byte: 92, line: 4, position: 37 }, code_source_id: 0 }) }])
         Expression(BinaryOperator { op: Mul, lhs: Scalar(Span { start: SourceCodePositition { byte: 109, line: 5, position: 13 }, end: SourceCodePositition { byte: 111, line: 5, position: 15 }, code_source_id: 0 }, Number(30.0)), rhs: Identifier(Span { start: SourceCodePositition { byte: 111, line: 5, position: 15 }, end: SourceCodePositition { byte: 112, line: 5, position: 16 }, code_source_id: 0 }, "m"), span_op: None })
         Errors encountered: