mirror of
https://github.com/uutils/awk.git
synced 2026-06-10 16:15:04 -07:00
parser: add support for multidimensional arrays
This commit is contained in:
@@ -286,6 +286,7 @@ impl<'a> Code<'a> {
|
||||
self.bc
|
||||
.emit(Instruction::LoadBuiltinArray((dest, dest, var_index(var))));
|
||||
}
|
||||
Place::ChainedIndex(_, _) => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -317,6 +318,7 @@ impl<'a> Code<'a> {
|
||||
.emit(Instruction::StoreBuiltinArray((src, *rhs, var_index(var))));
|
||||
self.free_reg(rhs);
|
||||
}
|
||||
Place::ChainedIndex(_, _) => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -100,6 +100,7 @@ pub enum ExprNode<'a> {
|
||||
UnaryPlaceOperation(UnaryPlaceOperator, Place<'a>),
|
||||
BinaryPlaceOperation(BinaryPlaceOperator, Place<'a>, Expr<'a>),
|
||||
ArrayOperation(ArrayOperator, Variable<'a>, Vec<'a, Expr<'a>>),
|
||||
NestedArray(Expr<'a>, Vec<'a, Expr<'a>>),
|
||||
Ternary(Expr<'a>, Expr<'a>, Expr<'a>),
|
||||
Getline(Getline<'a>),
|
||||
}
|
||||
@@ -163,6 +164,7 @@ pub enum Place<'a> {
|
||||
Record(Expr<'a>),
|
||||
Variable(Variable<'a>),
|
||||
Index(Variable<'a>, Vec<'a, Expr<'a>>),
|
||||
ChainedIndex(Expr<'a>, Vec<'a, Expr<'a>>),
|
||||
}
|
||||
|
||||
/// GNU docs: https://www.gnu.org/software/gawk/manual/html_node/Redirection.html
|
||||
@@ -430,11 +432,13 @@ impl<'a> Place<'a> {
|
||||
&*node,
|
||||
&ExprNode::UnaryOperation(UnaryOperator::Record, _)
|
||||
| &ExprNode::ArrayOperation(ArrayOperator::Index, _, _)
|
||||
| &ExprNode::NestedArray(_, _)
|
||||
) =>
|
||||
{
|
||||
match Box::into_inner(node) {
|
||||
ExprNode::UnaryOperation(_, index) => Ok(Self::Record(index)),
|
||||
ExprNode::ArrayOperation(_, var, index) => Ok(Self::Index(var, index)),
|
||||
ExprNode::NestedArray(arr, indices) => Ok(Self::ChainedIndex(arr, indices)),
|
||||
_ => unreachable!("Box is magic; handled awkwardly in the match guard."),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,6 +240,11 @@ impl Display for Place<'_> {
|
||||
write_args(f, args, 0)?;
|
||||
write!(f, "]")
|
||||
}
|
||||
Self::ChainedIndex(arr, args) => {
|
||||
write!(f, "{arr}[")?;
|
||||
write_args(f, args, 0)?;
|
||||
write!(f, "]")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -319,6 +324,19 @@ impl Display for ExprNode<'_> {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Self::NestedArray(arr, args) => {
|
||||
let left_bp = ArrayOperator::Index.binding_power().0;
|
||||
if left_bp < parent_bp {
|
||||
write!(f, "(")?;
|
||||
}
|
||||
write!(f, "{arr}[")?;
|
||||
write_args(f, args, indent)?;
|
||||
write!(f, "]")?;
|
||||
if left_bp < parent_bp {
|
||||
write!(f, ")")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Self::Ternary(cond, then_expr, else_expr) => {
|
||||
let ternary_bp = Ternary.binding_power().0;
|
||||
let inner_w = encode(indent, 0);
|
||||
|
||||
+39
-17
@@ -54,6 +54,18 @@ impl<'a, 'b> Pratt<'a, 'b> {
|
||||
self.fold_rhs(lex, lhs, min_bp, |_| false)
|
||||
}
|
||||
|
||||
fn parse_index_exprs(
|
||||
&mut self,
|
||||
lex: &mut Lexer<'a>,
|
||||
op: ArrayOperator,
|
||||
) -> Result<Vec<'a, Expr<'a>>> {
|
||||
lex.next();
|
||||
let expr = self.parse_expression(lex, op.binding_power().1)?;
|
||||
let indices = self.parse_comma_expr(lex, expr)?;
|
||||
lex.expect(&Token::ClosedBracket, ParsingError::UnclosedArrayAccess)?;
|
||||
Ok(indices)
|
||||
}
|
||||
|
||||
fn fold_rhs(
|
||||
&mut self,
|
||||
lex: &mut Lexer<'a>,
|
||||
@@ -101,24 +113,34 @@ impl<'a, 'b> Pratt<'a, 'b> {
|
||||
self.parse_place_op(lex, op, place)?
|
||||
} else if let Ok(op) = ArrayOperator::parse(next, &span) {
|
||||
match op {
|
||||
ArrayOperator::Index => {
|
||||
let place = match Place::lower_from(lhs.take(), lex.span()) {
|
||||
Ok(Place::Variable(var)) => var,
|
||||
Ok(_) => return Err(ParsingError::OperatorExpectsVariable(lex.span())),
|
||||
Err((expr, _)) => {
|
||||
lhs = expr;
|
||||
if op.binding_power().0 < min_bp {
|
||||
break;
|
||||
}
|
||||
return Err(ParsingError::OperatorExpectsVariable(lex.span()));
|
||||
ArrayOperator::Index => match Place::lower_from(lhs.take(), lex.span()) {
|
||||
Ok(Place::Variable(var)) => {
|
||||
let index = self.parse_index_exprs(lex, op)?;
|
||||
Expr::node(op.expr(var, index), self.parser.arena)
|
||||
}
|
||||
Ok(Place::Index(var, index)) => {
|
||||
let new_indices = self.parse_index_exprs(lex, op)?;
|
||||
let inner = Expr::node(
|
||||
ExprNode::ArrayOperation(ArrayOperator::Index, var, index),
|
||||
self.parser.arena,
|
||||
);
|
||||
Expr::node(ExprNode::NestedArray(inner, new_indices), self.parser.arena)
|
||||
}
|
||||
Ok(Place::ChainedIndex(arr, indices)) => {
|
||||
let new_indices = self.parse_index_exprs(lex, op)?;
|
||||
let inner =
|
||||
Expr::node(ExprNode::NestedArray(arr, indices), self.parser.arena);
|
||||
Expr::node(ExprNode::NestedArray(inner, new_indices), self.parser.arena)
|
||||
}
|
||||
Ok(_) => return Err(ParsingError::OperatorExpectsVariable(lex.span())),
|
||||
Err((expr, _)) => {
|
||||
lhs = expr;
|
||||
if op.binding_power().0 < min_bp {
|
||||
break;
|
||||
}
|
||||
};
|
||||
lex.next();
|
||||
let expr = self.parse_expression(lex, op.binding_power().1)?;
|
||||
let comma_expr = self.parse_comma_expr(lex, expr)?;
|
||||
lex.expect(&Token::ClosedBracket, ParsingError::UnclosedArrayAccess)?;
|
||||
Expr::node(op.expr(place, comma_expr), self.parser.arena)
|
||||
}
|
||||
return Err(ParsingError::OperatorExpectsVariable(lex.span()));
|
||||
}
|
||||
},
|
||||
ArrayOperator::In => {
|
||||
lex.next();
|
||||
let Place::Variable(var) = self.parse_place(lex)? else {
|
||||
|
||||
@@ -200,6 +200,13 @@ impl Debug for Expr<'_> {
|
||||
}
|
||||
write!(f, ")")
|
||||
}
|
||||
ExprNode::NestedArray(inner, args) => {
|
||||
write!(f, "(Index {inner:?}")?;
|
||||
for arg in args {
|
||||
write!(f, " {arg:?}")?;
|
||||
}
|
||||
write!(f, ")")
|
||||
}
|
||||
ExprNode::UnaryPlaceOperation(op, a) => write!(f, "({op:?} {a:?})"),
|
||||
ExprNode::Ternary(a, b, c) => write!(f, "(?: {a:?} {b:?} {c:?})"),
|
||||
ExprNode::Getline(getline) => match getline {
|
||||
@@ -304,6 +311,13 @@ impl Debug for Place<'_> {
|
||||
}
|
||||
write!(f, ")")
|
||||
}
|
||||
Self::ChainedIndex(expr, index) => {
|
||||
write!(f, "(Index {expr:?}")?;
|
||||
for i in index {
|
||||
write!(f, " {i:?}")?;
|
||||
}
|
||||
write!(f, ")")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user