Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/parser/src/grammar/expressions.rs')
-rw-r--r--crates/parser/src/grammar/expressions.rs33
1 files changed, 25 insertions, 8 deletions
diff --git a/crates/parser/src/grammar/expressions.rs b/crates/parser/src/grammar/expressions.rs
index e99c111d39..52a08c4fb1 100644
--- a/crates/parser/src/grammar/expressions.rs
+++ b/crates/parser/src/grammar/expressions.rs
@@ -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);
}