Fix bugs with parenthesized expression parsing (#3505)
This commit is contained in:
parent
9646a132a8
commit
0aa9254356
@ -746,7 +746,7 @@ fn code_primary(p: &mut Parser, atomic: bool) {
|
||||
|
||||
SyntaxKind::LeftBrace => code_block(p),
|
||||
SyntaxKind::LeftBracket => content_block(p),
|
||||
SyntaxKind::LeftParen => expr_with_paren(p),
|
||||
SyntaxKind::LeftParen => expr_with_paren(p, atomic),
|
||||
SyntaxKind::Dollar => equation(p),
|
||||
SyntaxKind::Let => let_binding(p),
|
||||
SyntaxKind::Set => set_rule(p),
|
||||
@ -1020,13 +1020,16 @@ fn return_stmt(p: &mut Parser) {
|
||||
}
|
||||
|
||||
/// An expression that starts with a parenthesis.
|
||||
fn expr_with_paren(p: &mut Parser) {
|
||||
fn expr_with_paren(p: &mut Parser, atomic: bool) {
|
||||
// If we've seen this position before and have a memoized result, just use
|
||||
// it. See below for more explanation about this memoization.
|
||||
let start = p.current_start();
|
||||
if let Some((range, end_point)) = p.memo.get(&start) {
|
||||
p.nodes.extend(p.memo_arena[range.clone()].iter().cloned());
|
||||
p.restore(end_point.clone());
|
||||
if let Some((range, end_point)) = p.memo.get(&start).cloned() {
|
||||
// Restore the end point first, so that it doesn't truncate our freshly
|
||||
// pushed nodes. If the current length of `p.nodes` doesn't match what
|
||||
// we had in the memoized run, this might otherwise happen.
|
||||
p.restore(end_point);
|
||||
p.nodes.extend(p.memo_arena[range].iter().cloned());
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1038,6 +1041,9 @@ fn expr_with_paren(p: &mut Parser) {
|
||||
// these are the most likely things. We can handle all of those in a single
|
||||
// pass.
|
||||
let kind = parenthesized_or_array_or_dict(p);
|
||||
if atomic {
|
||||
return;
|
||||
}
|
||||
|
||||
// If, however, '=>' or '=' follows, we must backtrack and reparse as either
|
||||
// a parameter list or a destructuring. To be able to do that, we created a
|
||||
@ -1553,6 +1559,7 @@ impl<'s> Parser<'s> {
|
||||
self.skip();
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn eat_and_get(&mut self) -> &mut SyntaxNode {
|
||||
let offset = self.nodes.len();
|
||||
self.save();
|
||||
@ -1622,6 +1629,7 @@ impl<'s> Parser<'s> {
|
||||
m.0 > 0 && self.nodes[m.0 - 1].kind().is_error()
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn post_process(&mut self, m: Marker) -> impl Iterator<Item = &mut SyntaxNode> {
|
||||
self.nodes[m.0..]
|
||||
.iter_mut()
|
||||
@ -1762,6 +1770,7 @@ impl<'s> Parser<'s> {
|
||||
|
||||
/// Consume the given closing delimiter or produce an error for the matching
|
||||
/// opening delimiter at `open`.
|
||||
#[track_caller]
|
||||
fn expect_closing_delimiter(&mut self, open: Marker, kind: SyntaxKind) {
|
||||
if !self.eat_if(kind) {
|
||||
self.nodes[open.0].convert_to_error("unclosed delimiter");
|
||||
|
@ -84,3 +84,15 @@
|
||||
// Here, `a` is not duplicate, where it was previously identified as one.
|
||||
#let f((a: b), (c,), a) = (a, b, c)
|
||||
#test(f((a: 1), (2,), 3), (3, 1, 2))
|
||||
|
||||
---
|
||||
// Ensure that we can't have non-atomic closures.
|
||||
#let x = 1
|
||||
#let c = [#(x) => (1, 2)]
|
||||
#test(c.children.last(), [(1, 2)]))
|
||||
|
||||
---
|
||||
// Ensure that we can't have non-atomic destructuring.
|
||||
#let x = 1
|
||||
#let c = [#() = ()]
|
||||
#test(c.children.last(), [()])
|
||||
|
Loading…
x
Reference in New Issue
Block a user