mirror of
https://github.com/uutils/awk.git
synced 2026-06-10 16:15:04 -07:00
parser: handle chained array indexing in parse_place and add tests
This commit is contained in:
+21
-6
@@ -382,15 +382,30 @@ impl<'a, 'b> Pratt<'a, 'b> {
|
||||
}
|
||||
tok if tok.is_place() => {
|
||||
let expr = self.parse_lhs(lex, 0)?;
|
||||
if lex.consume(&Token::OpenBracket) {
|
||||
if lex.peek_is(&Token::OpenBracket) {
|
||||
let Expr::Leaf(Atom::Variable(var)) = expr else {
|
||||
return Err(ParsingError::OperatorExpectsVariable(start..lex.span().end));
|
||||
};
|
||||
let expr =
|
||||
self.parse_expression(lex, ArrayOperator::Index.binding_power().1)?;
|
||||
let index = self.parse_comma_expr(lex, expr)?;
|
||||
lex.expect(&Token::ClosedBracket, ParsingError::UnclosedArrayAccess)?;
|
||||
return Ok(Place::Index(var, index));
|
||||
|
||||
let index = self.parse_index_exprs(lex, ArrayOperator::Index)?;
|
||||
|
||||
if !lex.peek_is(&Token::OpenBracket) {
|
||||
return Ok(Place::Index(var, index));
|
||||
}
|
||||
|
||||
let mut lhs = Expr::node(
|
||||
ExprNode::ArrayOperation(ArrayOperator::Index, var, index),
|
||||
self.parser.arena,
|
||||
);
|
||||
|
||||
while lex.peek_is(&Token::OpenBracket) {
|
||||
let index = self.parse_index_exprs(lex, ArrayOperator::Index)?;
|
||||
if lex.peek_is(&Token::OpenBracket) {
|
||||
lhs = Expr::node(ExprNode::NestedArray(lhs, index), self.parser.arena);
|
||||
} else {
|
||||
return Ok(Place::ChainedIndex(lhs, index));
|
||||
}
|
||||
}
|
||||
}
|
||||
expr
|
||||
}
|
||||
|
||||
@@ -282,6 +282,46 @@ fn test_parser_arrays() {
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parser_nested_arrays() {
|
||||
let source = "
|
||||
{ a[1][2] }
|
||||
{ a[1][2][3] }
|
||||
{ a[1][2] = 2 }
|
||||
{ a[1][2][3] = 2 }
|
||||
{ a[1][2][3][4][5] = 2 }
|
||||
{ ++a[1][2] }
|
||||
{ a[1][2]-- }
|
||||
{ a[1][2] += 1 }
|
||||
{ b = a[1][2] }
|
||||
{ b = a[1][2][3] }
|
||||
{ a[1, 2][3] }
|
||||
{ a[1][2, 3] }
|
||||
";
|
||||
test_parser!(source => {
|
||||
rules: [
|
||||
(None, Some("(body (Index (Index awk::a 1) 2))")),
|
||||
(None, Some("(body (Index (Index (Index awk::a 1) 2) 3))")),
|
||||
(None, Some("(body (Assignment (Index (Index awk::a 1) 2) 2))")),
|
||||
(None, Some("(body (Assignment (Index (Index (Index awk::a 1) 2) 3) 2))")),
|
||||
(None, Some("(body (Assignment (Index (Index (Index (Index (Index awk::a 1) 2) 3) 4) 5) 2))")),
|
||||
(None, Some("(body (IncrementL (Index (Index awk::a 1) 2)))")),
|
||||
(None, Some("(body (DecrementR (Index (Index awk::a 1) 2)))")),
|
||||
(None, Some("(body (AddAssign (Index (Index awk::a 1) 2) 1))")),
|
||||
(None, Some("(body (Assignment awk::b (Index (Index awk::a 1) 2)))")),
|
||||
(None, Some("(body (Assignment awk::b (Index (Index (Index awk::a 1) 2) 3)))")),
|
||||
(None, Some("(body (Index (Index awk::a 1 2) 3))")),
|
||||
(None, Some("(body (Index (Index awk::a 1) 2 3))")),
|
||||
],
|
||||
});
|
||||
|
||||
test_parser!(is_err!(
|
||||
"{ 2[1][2] }",
|
||||
"{ \"a\"[1][2] }",
|
||||
"{ (a + b)[1][2] }"
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parser_for_loop() {
|
||||
let source = "
|
||||
|
||||
Reference in New Issue
Block a user