fix: Recover from missing argument in call expressions
Previously, when parsing an argument list with a missing argument (e.g., `(a, , b)` in `foo(a, , b)`), the parser would stop upon an unexpected token (at the second comma in the example), resulting in an incorrect parse tree. This commit improves error handling in such cases, ensuring a more accurate parse tree is built.
This commit is contained in:
parent
bcc8a09a0d
commit
e865d45904
@ -631,20 +631,6 @@ fn foo() {
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn extraneous_comma() {
|
||||
check(
|
||||
r#"
|
||||
fn foo() {
|
||||
bar(,);
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
fn foo () {__ra_fixup ;}
|
||||
"#]],
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fixup_if_1() {
|
||||
check(
|
||||
|
@ -611,6 +611,7 @@ fn cast_expr(p: &mut Parser<'_>, lhs: CompletedMarker) -> CompletedMarker {
|
||||
// foo(bar::);
|
||||
// foo(bar:);
|
||||
// foo(bar+);
|
||||
// foo(a, , b);
|
||||
// }
|
||||
fn arg_list(p: &mut Parser<'_>) {
|
||||
assert!(p.at(T!['(']));
|
||||
@ -619,14 +620,30 @@ fn arg_list(p: &mut Parser<'_>) {
|
||||
// fn main() {
|
||||
// foo(#[attr] 92)
|
||||
// }
|
||||
delimited(
|
||||
p,
|
||||
T!['('],
|
||||
T![')'],
|
||||
T![,],
|
||||
EXPR_FIRST.union(ATTRIBUTE_FIRST),
|
||||
|p: &mut Parser<'_>| expr(p).is_some(),
|
||||
);
|
||||
p.bump(T!['(']);
|
||||
while !p.at(T![')']) && !p.at(EOF) {
|
||||
if p.at(T![,]) {
|
||||
// Recover if an argument is missing and only got a delimiter,
|
||||
// e.g. `(a, , b)`.
|
||||
p.error("expected expression");
|
||||
p.bump(T![,]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if expr(p).is_none() {
|
||||
break;
|
||||
}
|
||||
if !p.at(T![,]) {
|
||||
if p.at_ts(EXPR_FIRST.union(ATTRIBUTE_FIRST)) {
|
||||
p.error(format!("expected {:?}", T![,]));
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
p.bump(T![,]);
|
||||
}
|
||||
}
|
||||
p.expect(T![')']);
|
||||
m.complete(p, ARG_LIST);
|
||||
}
|
||||
|
||||
|
@ -68,6 +68,32 @@ SOURCE_FILE
|
||||
PLUS "+"
|
||||
R_PAREN ")"
|
||||
SEMICOLON ";"
|
||||
WHITESPACE "\n "
|
||||
EXPR_STMT
|
||||
CALL_EXPR
|
||||
PATH_EXPR
|
||||
PATH
|
||||
PATH_SEGMENT
|
||||
NAME_REF
|
||||
IDENT "foo"
|
||||
ARG_LIST
|
||||
L_PAREN "("
|
||||
PATH_EXPR
|
||||
PATH
|
||||
PATH_SEGMENT
|
||||
NAME_REF
|
||||
IDENT "a"
|
||||
COMMA ","
|
||||
WHITESPACE " "
|
||||
COMMA ","
|
||||
WHITESPACE " "
|
||||
PATH_EXPR
|
||||
PATH
|
||||
PATH_SEGMENT
|
||||
NAME_REF
|
||||
IDENT "b"
|
||||
R_PAREN ")"
|
||||
SEMICOLON ";"
|
||||
WHITESPACE "\n"
|
||||
R_CURLY "}"
|
||||
WHITESPACE "\n"
|
||||
@ -75,3 +101,4 @@ error 25: expected identifier
|
||||
error 39: expected COMMA
|
||||
error 39: expected expression
|
||||
error 55: expected expression
|
||||
error 68: expected expression
|
||||
|
@ -2,4 +2,5 @@ fn main() {
|
||||
foo(bar::);
|
||||
foo(bar:);
|
||||
foo(bar+);
|
||||
foo(a, , b);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user