Skip to content

Commit ad6ba45

Browse files
gabrielhnfAlonely0
authored andcommitted
parser: add support for multidimensional arrays
1 parent 19d1b46 commit ad6ba45

5 files changed

Lines changed: 77 additions & 17 deletions

File tree

interpreter/src/ir/lower.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,7 @@ impl<'a> Code<'a> {
286286
self.bc
287287
.emit(Instruction::LoadBuiltinArray((dest, dest, var_index(var))));
288288
}
289+
Place::ChainedIndex(_, _) => todo!(),
289290
}
290291
}
291292

@@ -317,6 +318,7 @@ impl<'a> Code<'a> {
317318
.emit(Instruction::StoreBuiltinArray((src, *rhs, var_index(var))));
318319
self.free_reg(rhs);
319320
}
321+
Place::ChainedIndex(_, _) => todo!(),
320322
}
321323
}
322324

parser/src/ast.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ pub enum ExprNode<'a> {
100100
UnaryPlaceOperation(UnaryPlaceOperator, Place<'a>),
101101
BinaryPlaceOperation(BinaryPlaceOperator, Place<'a>, Expr<'a>),
102102
ArrayOperation(ArrayOperator, Variable<'a>, Vec<'a, Expr<'a>>),
103+
NestedArray(Expr<'a>, Vec<'a, Expr<'a>>),
103104
Ternary(Expr<'a>, Expr<'a>, Expr<'a>),
104105
Getline(Getline<'a>),
105106
}
@@ -163,6 +164,7 @@ pub enum Place<'a> {
163164
Record(Expr<'a>),
164165
Variable(Variable<'a>),
165166
Index(Variable<'a>, Vec<'a, Expr<'a>>),
167+
ChainedIndex(Expr<'a>, Vec<'a, Expr<'a>>),
166168
}
167169

168170
/// GNU docs: https://www.gnu.org/software/gawk/manual/html_node/Redirection.html
@@ -430,11 +432,13 @@ impl<'a> Place<'a> {
430432
&*node,
431433
&ExprNode::UnaryOperation(UnaryOperator::Record, _)
432434
| &ExprNode::ArrayOperation(ArrayOperator::Index, _, _)
435+
| &ExprNode::NestedArray(_, _)
433436
) =>
434437
{
435438
match Box::into_inner(node) {
436439
ExprNode::UnaryOperation(_, index) => Ok(Self::Record(index)),
437440
ExprNode::ArrayOperation(_, var, index) => Ok(Self::Index(var, index)),
441+
ExprNode::NestedArray(arr, indices) => Ok(Self::ChainedIndex(arr, indices)),
438442
_ => unreachable!("Box is magic; handled awkwardly in the match guard."),
439443
}
440444
}

parser/src/idempotency.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,11 @@ impl Display for Place<'_> {
240240
write_args(f, args, 0)?;
241241
write!(f, "]")
242242
}
243+
Self::ChainedIndex(arr, args) => {
244+
write!(f, "{arr}[")?;
245+
write_args(f, args, 0)?;
246+
write!(f, "]")
247+
}
243248
}
244249
}
245250
}
@@ -319,6 +324,19 @@ impl Display for ExprNode<'_> {
319324
}
320325
Ok(())
321326
}
327+
Self::NestedArray(arr, args) => {
328+
let left_bp = ArrayOperator::Index.binding_power().0;
329+
if left_bp < parent_bp {
330+
write!(f, "(")?;
331+
}
332+
write!(f, "{arr}[")?;
333+
write_args(f, args, indent)?;
334+
write!(f, "]")?;
335+
if left_bp < parent_bp {
336+
write!(f, ")")?;
337+
}
338+
Ok(())
339+
}
322340
Self::Ternary(cond, then_expr, else_expr) => {
323341
let ternary_bp = Ternary.binding_power().0;
324342
let inner_w = encode(indent, 0);

parser/src/pratt.rs

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,18 @@ impl<'a, 'b> Pratt<'a, 'b> {
5454
self.fold_rhs(lex, lhs, min_bp, |_| false)
5555
}
5656

57+
fn parse_index_exprs(
58+
&mut self,
59+
lex: &mut Lexer<'a>,
60+
op: ArrayOperator,
61+
) -> Result<Vec<'a, Expr<'a>>> {
62+
lex.next();
63+
let expr = self.parse_expression(lex, op.binding_power().1)?;
64+
let indices = self.parse_comma_expr(lex, expr)?;
65+
lex.expect(&Token::ClosedBracket, ParsingError::UnclosedArrayAccess)?;
66+
Ok(indices)
67+
}
68+
5769
fn fold_rhs(
5870
&mut self,
5971
lex: &mut Lexer<'a>,
@@ -101,24 +113,34 @@ impl<'a, 'b> Pratt<'a, 'b> {
101113
self.parse_place_op(lex, op, place)?
102114
} else if let Ok(op) = ArrayOperator::parse(next, &span) {
103115
match op {
104-
ArrayOperator::Index => {
105-
let place = match Place::lower_from(lhs.take(), lex.span()) {
106-
Ok(Place::Variable(var)) => var,
107-
Ok(_) => return Err(ParsingError::OperatorExpectsVariable(lex.span())),
108-
Err((expr, _)) => {
109-
lhs = expr;
110-
if op.binding_power().0 < min_bp {
111-
break;
112-
}
113-
return Err(ParsingError::OperatorExpectsVariable(lex.span()));
116+
ArrayOperator::Index => match Place::lower_from(lhs.take(), lex.span()) {
117+
Ok(Place::Variable(var)) => {
118+
let index = self.parse_index_exprs(lex, op)?;
119+
Expr::node(op.expr(var, index), self.parser.arena)
120+
}
121+
Ok(Place::Index(var, index)) => {
122+
let new_indices = self.parse_index_exprs(lex, op)?;
123+
let inner = Expr::node(
124+
ExprNode::ArrayOperation(ArrayOperator::Index, var, index),
125+
self.parser.arena,
126+
);
127+
Expr::node(ExprNode::NestedArray(inner, new_indices), self.parser.arena)
128+
}
129+
Ok(Place::ChainedIndex(arr, indices)) => {
130+
let new_indices = self.parse_index_exprs(lex, op)?;
131+
let inner =
132+
Expr::node(ExprNode::NestedArray(arr, indices), self.parser.arena);
133+
Expr::node(ExprNode::NestedArray(inner, new_indices), self.parser.arena)
134+
}
135+
Ok(_) => return Err(ParsingError::OperatorExpectsVariable(lex.span())),
136+
Err((expr, _)) => {
137+
lhs = expr;
138+
if op.binding_power().0 < min_bp {
139+
break;
114140
}
115-
};
116-
lex.next();
117-
let expr = self.parse_expression(lex, op.binding_power().1)?;
118-
let comma_expr = self.parse_comma_expr(lex, expr)?;
119-
lex.expect(&Token::ClosedBracket, ParsingError::UnclosedArrayAccess)?;
120-
Expr::node(op.expr(place, comma_expr), self.parser.arena)
121-
}
141+
return Err(ParsingError::OperatorExpectsVariable(lex.span()));
142+
}
143+
},
122144
ArrayOperator::In => {
123145
lex.next();
124146
let Place::Variable(var) = self.parse_place(lex)? else {

parser/src/sexpr.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,13 @@ impl Debug for Expr<'_> {
200200
}
201201
write!(f, ")")
202202
}
203+
ExprNode::NestedArray(inner, args) => {
204+
write!(f, "(Index {inner:?}")?;
205+
for arg in args {
206+
write!(f, " {arg:?}")?;
207+
}
208+
write!(f, ")")
209+
}
203210
ExprNode::UnaryPlaceOperation(op, a) => write!(f, "({op:?} {a:?})"),
204211
ExprNode::Ternary(a, b, c) => write!(f, "(?: {a:?} {b:?} {c:?})"),
205212
ExprNode::Getline(getline) => match getline {
@@ -304,6 +311,13 @@ impl Debug for Place<'_> {
304311
}
305312
write!(f, ")")
306313
}
314+
Self::ChainedIndex(expr, index) => {
315+
write!(f, "(Index {expr:?}")?;
316+
for i in index {
317+
write!(f, " {i:?}")?;
318+
}
319+
write!(f, ")")
320+
}
307321
}
308322
}
309323
}

0 commit comments

Comments
 (0)