|
@@ -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:
|