fix parser to match abnf conditional

This commit is contained in:
gluax 2021-06-30 22:20:06 -07:00
parent d4aaac6577
commit eee9cfc1be
8 changed files with 55 additions and 5 deletions

View File

@ -453,7 +453,7 @@ identifier = letter *( letter / digit / "_" ) ; but not a keyword or aleo1...
; A package name consists of one or more segments separated by single dashes,
; where each segment is a non-empty sequence of lowercase letters and digits.
package-name = 1*( lowercase-letter / digit )
package-name = 1*lowercase-letter
*( "-" 1*( lowercase-letter / digit ) )
; Annotations have names, which are identifiers immediately preceded by `@`.
@ -962,7 +962,7 @@ assert-call = %s"assert" "(" expression ")"
print-function = %s"debug" / %s"error" / %s"log"
print-arguments = "(" [ string-literal *( "," expression ) ] ")"
print-arguments = "(" string-literal *( "," expression ) ")"
print-call = print-function print-arguments
@ -1020,7 +1020,7 @@ member-function-declaration = function-declaration
; this may be relaxed after the backward compatibility is removed,
; allowing member variables and member functions to be intermixed.
circuit-declaration = *annotation %s"circuit" identifier
circuit-declaration = %s"circuit" identifier
"{" [ member-variable-declarations ]
*member-function-declaration "}"

View File

@ -100,6 +100,10 @@ impl SyntaxError {
)
}
pub fn unexpected_statement(got: String, expected: &str, span: &Span) -> Self {
Self::new_from_span(format!("expected '{}', got '{}'", expected, got.to_string()), span)
}
pub fn unexpected_str(got: &Token, expected: &str, span: &Span) -> Self {
Self::new_from_span(format!("expected '{}', got '{}'", expected, got.to_string()), span)
}

View File

@ -102,11 +102,20 @@ impl ParserContext {
let end_span;
let arguments = if self.eat(Token::LeftParen).is_some() {
let mut args = Vec::new();
let mut comma = false;
loop {
if let Some(end) = self.eat(Token::RightParen) {
if comma {
return Err(SyntaxError::unexpected(
&Token::RightParen,
&[Token::Ident("identifier".into()), Token::Int("number".into())],
&end.span,
));
}
end_span = end.span;
break;
}
comma = false;
if let Some(ident) = self.eat_identifier() {
args.push(ident.name);
} else if let Some((int, _)) = self.eat_int() {
@ -115,10 +124,11 @@ impl ParserContext {
let token = self.peek()?;
return Err(SyntaxError::unexpected_str(&token.token, "ident or int", &token.span));
}
if self.eat(Token::Comma).is_none() {
if self.eat(Token::Comma).is_none() && !comma {
end_span = self.expect(Token::RightParen)?;
break;
}
comma = true;
}
args
} else {

View File

@ -185,7 +185,17 @@ impl ParserContext {
self.fuzzy_struct_state = false;
let body = self.parse_block()?;
let next = if self.eat(Token::Else).is_some() {
Some(Box::new(self.parse_statement()?))
let s = self.parse_statement()?;
match s {
Statement::Block(_) | Statement::Conditional(_) => Some(Box::new(s)),
s => {
return Err(SyntaxError::unexpected_statement(
s.to_string(),
"Block or Conditional",
s.span(),
));
}
}
} else {
None
};

View File

@ -0,0 +1,5 @@
---
namespace: Parse
expectation: Fail
outputs:
- " --> test:3:12\n |\n 3 | @test(test,)\n | ^\n |\n = expected 'identifier', 'number' -- got ')'"

View File

@ -0,0 +1,5 @@
---
namespace: Parse
expectation: Fail
outputs:
- " --> test:3:18\n |\n 3 | import foo as bar;\n | ^\n |\n = expected '.' -- got ';'"

View File

@ -0,0 +1,9 @@
/*
namespace: Parse
expectation: Fail
*/
@test(test,)
function x() {
return ();
}

View File

@ -0,0 +1,7 @@
/*
namespace: Parse
expectation: Fail
*/
import foo as bar;
import *;