[fine] Working on parser resilience
This commit is contained in:
parent
11cb7199e9
commit
741a729f8d
5 changed files with 129 additions and 1 deletions
|
|
@ -395,6 +395,15 @@ impl<'a> CParser<'a> {
|
||||||
// eprintln!("{}: {}: {}", self.current.start, self.current, msg);
|
// eprintln!("{}: {}: {}", self.current.start, self.current, msg);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
fn at_any(&self, kinds: &[TokenKind]) -> bool {
|
||||||
|
for kind in kinds {
|
||||||
|
if self.at(*kind) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
fn at(&self, kind: TokenKind) -> bool {
|
fn at(&self, kind: TokenKind) -> bool {
|
||||||
self.peek() == kind
|
self.peek() == kind
|
||||||
}
|
}
|
||||||
|
|
@ -586,6 +595,8 @@ fn field_decl(p: &mut CParser) {
|
||||||
p.end(m, TreeKind::FieldDecl);
|
p.end(m, TreeKind::FieldDecl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const PARAM_LIST_RECOVERY: &[TokenKind] = &[TokenKind::Arrow, TokenKind::LeftBrace, TokenKind::Fun];
|
||||||
|
|
||||||
fn param_list(p: &mut CParser) {
|
fn param_list(p: &mut CParser) {
|
||||||
let m = p.start();
|
let m = p.start();
|
||||||
|
|
||||||
|
|
@ -594,7 +605,10 @@ fn param_list(p: &mut CParser) {
|
||||||
if p.at(TokenKind::Identifier) {
|
if p.at(TokenKind::Identifier) {
|
||||||
parameter(p);
|
parameter(p);
|
||||||
} else {
|
} else {
|
||||||
break;
|
if p.at_any(PARAM_LIST_RECOVERY) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
p.advance_with_error("expected parameter");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.expect(TokenKind::RightParen, "expect ')' to end a parameter list");
|
p.expect(TokenKind::RightParen, "expect ')' to end a parameter list");
|
||||||
|
|
|
||||||
4
fine/tests/errors/resilience/README.md
Normal file
4
fine/tests/errors/resilience/README.md
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
These tests all produce errors in their parse, but the point is that
|
||||||
|
the trees are kinda as best as we can get.
|
||||||
|
|
||||||
|
See e.g. https://matklad.github.io/2023/05/21/resilient-ll-parsing-tutorial.html
|
||||||
53
fine/tests/errors/resilience/function_extra_comma.fine
Normal file
53
fine/tests/errors/resilience/function_extra_comma.fine
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
fun f1(x: f64,
|
||||||
|
|
||||||
|
fun f2(x: f64,, z: f64) {}
|
||||||
|
|
||||||
|
fun f3() {}
|
||||||
|
|
||||||
|
// @concrete:
|
||||||
|
// | File
|
||||||
|
// | FunctionDecl
|
||||||
|
// | Fun:'"fun"'
|
||||||
|
// | Identifier:'"f1"'
|
||||||
|
// | ParamList
|
||||||
|
// | LeftParen:'"("'
|
||||||
|
// | Parameter
|
||||||
|
// | Identifier:'"x"'
|
||||||
|
// | Colon:'":"'
|
||||||
|
// | TypeExpression
|
||||||
|
// | Identifier:'"f64"'
|
||||||
|
// | Comma:'","'
|
||||||
|
// | Error:'"Error at 'fun': expect ')' to end a parameter list"'
|
||||||
|
// | FunctionDecl
|
||||||
|
// | Fun:'"fun"'
|
||||||
|
// | Identifier:'"f2"'
|
||||||
|
// | ParamList
|
||||||
|
// | LeftParen:'"("'
|
||||||
|
// | Parameter
|
||||||
|
// | Identifier:'"x"'
|
||||||
|
// | Colon:'":"'
|
||||||
|
// | TypeExpression
|
||||||
|
// | Identifier:'"f64"'
|
||||||
|
// | Comma:'","'
|
||||||
|
// | Error
|
||||||
|
// | Error:'"Error at ',': expected parameter"'
|
||||||
|
// | Comma:'","'
|
||||||
|
// | Parameter
|
||||||
|
// | Identifier:'"z"'
|
||||||
|
// | Colon:'":"'
|
||||||
|
// | TypeExpression
|
||||||
|
// | Identifier:'"f64"'
|
||||||
|
// | RightParen:'")"'
|
||||||
|
// | Block
|
||||||
|
// | LeftBrace:'"{"'
|
||||||
|
// | RightBrace:'"}"'
|
||||||
|
// | FunctionDecl
|
||||||
|
// | Fun:'"fun"'
|
||||||
|
// | Identifier:'"f3"'
|
||||||
|
// | ParamList
|
||||||
|
// | LeftParen:'"("'
|
||||||
|
// | RightParen:'")"'
|
||||||
|
// | Block
|
||||||
|
// | LeftBrace:'"{"'
|
||||||
|
// | RightBrace:'"}"'
|
||||||
|
//
|
||||||
57
fine/tests/errors/resilience/incomplete_function.fine
Normal file
57
fine/tests/errors/resilience/incomplete_function.fine
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
fun fib_rec(f1: f64,
|
||||||
|
|
||||||
|
fun fib(n: f64) -> f64 {
|
||||||
|
fib_rec(1, 1, n)
|
||||||
|
}
|
||||||
|
|
||||||
|
// @concrete:
|
||||||
|
// | File
|
||||||
|
// | FunctionDecl
|
||||||
|
// | Fun:'"fun"'
|
||||||
|
// | Identifier:'"fib_rec"'
|
||||||
|
// | ParamList
|
||||||
|
// | LeftParen:'"("'
|
||||||
|
// | Parameter
|
||||||
|
// | Identifier:'"f1"'
|
||||||
|
// | Colon:'":"'
|
||||||
|
// | TypeExpression
|
||||||
|
// | Identifier:'"f64"'
|
||||||
|
// | Comma:'","'
|
||||||
|
// | Error:'"Error at 'fun': expect ')' to end a parameter list"'
|
||||||
|
// | FunctionDecl
|
||||||
|
// | Fun:'"fun"'
|
||||||
|
// | Identifier:'"fib"'
|
||||||
|
// | ParamList
|
||||||
|
// | LeftParen:'"("'
|
||||||
|
// | Parameter
|
||||||
|
// | Identifier:'"n"'
|
||||||
|
// | Colon:'":"'
|
||||||
|
// | TypeExpression
|
||||||
|
// | Identifier:'"f64"'
|
||||||
|
// | RightParen:'")"'
|
||||||
|
// | ReturnType
|
||||||
|
// | Arrow:'"->"'
|
||||||
|
// | TypeExpression
|
||||||
|
// | Identifier:'"f64"'
|
||||||
|
// | Block
|
||||||
|
// | LeftBrace:'"{"'
|
||||||
|
// | ExpressionStatement
|
||||||
|
// | CallExpression
|
||||||
|
// | Identifier
|
||||||
|
// | Identifier:'"fib_rec"'
|
||||||
|
// | ArgumentList
|
||||||
|
// | LeftParen:'"("'
|
||||||
|
// | Argument
|
||||||
|
// | LiteralExpression
|
||||||
|
// | Number:'"1"'
|
||||||
|
// | Comma:'","'
|
||||||
|
// | Argument
|
||||||
|
// | LiteralExpression
|
||||||
|
// | Number:'"1"'
|
||||||
|
// | Comma:'","'
|
||||||
|
// | Argument
|
||||||
|
// | Identifier
|
||||||
|
// | Identifier:'"n"'
|
||||||
|
// | RightParen:'")"'
|
||||||
|
// | RightBrace:'"}"'
|
||||||
|
//
|
||||||
Loading…
Add table
Add a link
Reference in a new issue