Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ Added a warning for unnecessary `let` bindings where a variable is
bound and immediately returned (e.g. `let x = foo() x` can be
simplified to `foo()`), with an autofix.

## Parsing

Fixed a parser panic on malformed tuple literals such as `(,{` where
the parser failed to make forward progress after recovering from an
invalid element.

## Commands

Added :load to evaluate all definitions in a file and switch to that
Expand Down
10 changes: 6 additions & 4 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -266,10 +266,12 @@ fn parse_tuple_literal_or_parentheses(

let start_idx = tokens.idx;
exprs.push(parse_expression(tokens, id_gen, diagnostics));
assert!(
tokens.idx > start_idx,
"The parser should always make forward progress."
);
if tokens.idx == start_idx {
// `parse_expression` could not consume any tokens and
// has already emitted a diagnostic. Stop collecting
// tuple elements to avoid an infinite loop.
break;
}
}

let close_paren = require_token(tokens, diagnostics, ")");
Expand Down
47 changes: 47 additions & 0 deletions src/test_files/parser/tuple_no_progress.gdn
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
(,{

// args: dump-ast
// expected stdout:
// TupleLiteral(
// [
// Expression {
// position: Position { ... },
// expr_: Invalid,
// value_is_used: true,
// id: SyntaxId(0),
// },
// Expression {
// position: Position { ... },
// expr_: Invalid,
// value_is_used: true,
// id: SyntaxId(1),
// },
// ],
// )
// Block(
// Block {
// open_brace: Position { ... },
// exprs: [],
// close_brace: Position { ... },
// },
// )

// expected stderr:
// Error: Parse error: Expected an expression after this.
// --| src/test_files/parser/tuple_no_progress.gdn:1:1
// 1| (,{
// | ^
// 2|
// 3| // args: dump-ast
// Error: Parse error: Expected an expression after this.
// --| src/test_files/parser/tuple_no_progress.gdn:1:2
// 1| (,{
// 2| ^
// 3| // args: dump-ast
// Error: Parse error: Expected `)` after this.
// --| src/test_files/parser/tuple_no_progress.gdn:1:2
// 1| (,{
// 2| ^
// 3| // args: dump-ast
// Parse error (incomplete input): Expected `}`, but got EOF.

Loading