1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-30 20:47: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. // file that was distributed with this source code.
use clap::{crate_version, Arg, ArgAction, Command}; use clap::{crate_version, Arg, ArgAction, Command};
use syntax_tree::AstNode; use syntax_tree::{is_truthy, AstNode};
use thiserror::Error; use thiserror::Error;
use uucore::{ use uucore::{
display::Quotable, display::Quotable,
@ -12,8 +12,6 @@ use uucore::{
format_usage, help_about, help_section, help_usage, format_usage, help_about, help_section, help_usage,
}; };
use crate::syntax_tree::is_truthy;
mod syntax_tree; mod syntax_tree;
mod options { mod options {

View file

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