1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-29 12:07:46 +00:00

expr: Evaluate parenthesis content before checking for closing parenthesis

This commit is contained in:
Dorian Peron 2025-02-22 04:52:06 +01:00 committed by Sylvestre Ledru
parent 4513b58e59
commit 2fc762b9d2
2 changed files with 19 additions and 6 deletions

View file

@ -4,7 +4,7 @@
// file that was distributed with this source code.
use clap::{crate_version, Arg, ArgAction, Command};
use syntax_tree::AstNode;
use syntax_tree::{is_truthy, AstNode};
use thiserror::Error;
use uucore::{
display::Quotable,
@ -12,8 +12,6 @@ use uucore::{
format_usage, help_about, help_section, help_usage,
};
use crate::syntax_tree::is_truthy;
mod syntax_tree;
mod options {

View file

@ -292,7 +292,7 @@ const PRECEDENCE: &[&[(&str, BinOp)]] = &[
&[(":", BinOp::String(StringOp::Match))],
];
#[derive(Debug)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum NumOrStr {
Num(BigInt),
Str(String),
@ -343,6 +343,9 @@ impl NumOrStr {
#[derive(Debug, PartialEq, Eq)]
pub enum AstNode {
Evaluated {
value: NumOrStr,
},
Leaf {
value: String,
},
@ -366,8 +369,15 @@ impl AstNode {
Parser::new(input).parse()
}
pub fn evaluated(self) -> ExprResult<Self> {
Ok(Self::Evaluated {
value: self.eval()?,
})
}
pub fn eval(&self) -> ExprResult<NumOrStr> {
match self {
Self::Evaluated { value } => Ok(value.clone()),
Self::Leaf { value } => Ok(value.to_string().into()),
Self::BinOp {
op_type,
@ -536,7 +546,10 @@ impl<'a> Parser<'a> {
value: self.next()?.into(),
},
"(" => {
let s = self.parse_expression()?;
// Evaluate the node just after parsing to we detect arithmetic
// errors before checking for the closing parenthesis.
let s = self.parse_expression()?.evaluated()?;
match self.next() {
Ok(")") => {}
// Since we have parsed at least a '(', there will be a token
@ -680,7 +693,9 @@ mod test {
AstNode::parse(&["(", "1", "+", "2", ")", "*", "3"]),
Ok(op(
BinOp::Numeric(NumericOp::Mul),
op(BinOp::Numeric(NumericOp::Add), "1", "2"),
op(BinOp::Numeric(NumericOp::Add), "1", "2")
.evaluated()
.unwrap(),
"3"
))
);