Skip to content

Commit 1df4886

Browse files
gabrielhnfAlonely0
authored andcommitted
parser: handle chained array indexing in parse_place and add tests
1 parent ad6ba45 commit 1df4886

2 files changed

Lines changed: 61 additions & 6 deletions

File tree

parser/src/pratt.rs

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -382,15 +382,30 @@ impl<'a, 'b> Pratt<'a, 'b> {
382382
}
383383
tok if tok.is_place() => {
384384
let expr = self.parse_lhs(lex, 0)?;
385-
if lex.consume(&Token::OpenBracket) {
385+
if lex.peek_is(&Token::OpenBracket) {
386386
let Expr::Leaf(Atom::Variable(var)) = expr else {
387387
return Err(ParsingError::OperatorExpectsVariable(start..lex.span().end));
388388
};
389-
let expr =
390-
self.parse_expression(lex, ArrayOperator::Index.binding_power().1)?;
391-
let index = self.parse_comma_expr(lex, expr)?;
392-
lex.expect(&Token::ClosedBracket, ParsingError::UnclosedArrayAccess)?;
393-
return Ok(Place::Index(var, index));
389+
390+
let index = self.parse_index_exprs(lex, ArrayOperator::Index)?;
391+
392+
if !lex.peek_is(&Token::OpenBracket) {
393+
return Ok(Place::Index(var, index));
394+
}
395+
396+
let mut lhs = Expr::node(
397+
ExprNode::ArrayOperation(ArrayOperator::Index, var, index),
398+
self.parser.arena,
399+
);
400+
401+
while lex.peek_is(&Token::OpenBracket) {
402+
let index = self.parse_index_exprs(lex, ArrayOperator::Index)?;
403+
if lex.peek_is(&Token::OpenBracket) {
404+
lhs = Expr::node(ExprNode::NestedArray(lhs, index), self.parser.arena);
405+
} else {
406+
return Ok(Place::ChainedIndex(lhs, index));
407+
}
408+
}
394409
}
395410
expr
396411
}

parser/src/tests.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,46 @@ fn test_parser_arrays() {
282282
));
283283
}
284284

285+
#[test]
286+
fn test_parser_nested_arrays() {
287+
let source = "
288+
{ a[1][2] }
289+
{ a[1][2][3] }
290+
{ a[1][2] = 2 }
291+
{ a[1][2][3] = 2 }
292+
{ a[1][2][3][4][5] = 2 }
293+
{ ++a[1][2] }
294+
{ a[1][2]-- }
295+
{ a[1][2] += 1 }
296+
{ b = a[1][2] }
297+
{ b = a[1][2][3] }
298+
{ a[1, 2][3] }
299+
{ a[1][2, 3] }
300+
";
301+
test_parser!(source => {
302+
rules: [
303+
(None, Some("(body (Index (Index awk::a 1) 2))")),
304+
(None, Some("(body (Index (Index (Index awk::a 1) 2) 3))")),
305+
(None, Some("(body (Assignment (Index (Index awk::a 1) 2) 2))")),
306+
(None, Some("(body (Assignment (Index (Index (Index awk::a 1) 2) 3) 2))")),
307+
(None, Some("(body (Assignment (Index (Index (Index (Index (Index awk::a 1) 2) 3) 4) 5) 2))")),
308+
(None, Some("(body (IncrementL (Index (Index awk::a 1) 2)))")),
309+
(None, Some("(body (DecrementR (Index (Index awk::a 1) 2)))")),
310+
(None, Some("(body (AddAssign (Index (Index awk::a 1) 2) 1))")),
311+
(None, Some("(body (Assignment awk::b (Index (Index awk::a 1) 2)))")),
312+
(None, Some("(body (Assignment awk::b (Index (Index (Index awk::a 1) 2) 3)))")),
313+
(None, Some("(body (Index (Index awk::a 1 2) 3))")),
314+
(None, Some("(body (Index (Index awk::a 1) 2 3))")),
315+
],
316+
});
317+
318+
test_parser!(is_err!(
319+
"{ 2[1][2] }",
320+
"{ \"a\"[1][2] }",
321+
"{ (a + b)[1][2] }"
322+
));
323+
}
324+
285325
#[test]
286326
fn test_parser_for_loop() {
287327
let source = "

0 commit comments

Comments
 (0)