[Core] Fix #15558: Direct expression in ternary operator (#22938)

* [Core] Fix #15558: Direct expression in ternary operator

* [Core] Added tests for Non-Numeric conditions in ternary op.

* [Core] prevent relational operator chains at grammar level.

* [Core] Rewrite expressions grammar as a layered grammar.

* [Core] Revert to left associative relops (like C/C++) plus tests.
This commit is contained in:
Frank David Martínez M
2025-08-25 14:52:42 -05:00
committed by GitHub
parent 0805164677
commit 0f2ea5588c
5 changed files with 565 additions and 464 deletions

View File

@@ -3264,7 +3264,7 @@ Expression *ConditionalExpression::simplify() const
if (!v)
return new ConditionalExpression(owner, condition->simplify(), trueExpr->simplify(), falseExpr->simplify());
else {
if (fabs(v->getValue()) > 0.5)
if (fabs(v->getValue()) >= Base::Precision::Confusion())
return trueExpr->simplify();
else
return falseExpr->simplify();

File diff suppressed because it is too large Load Diff

View File

@@ -45,7 +45,7 @@ std::stack<FunctionExpression::Function> functions; /**< Function
%token DOCUMENT OBJECT
%token EXPONENT
%type <arguments> args
%type <expr> input unit_num us_building_unit other_unit exp unit_exp cond indexable
%type <expr> input unit_num us_building_unit other_unit exp unit_exp indexable
%type <quantity> UNIT USUNIT
%type <string> id_or_cell STRING IDENTIFIER CELLADDRESS
%type <ivalue> INTEGER
@@ -61,8 +61,8 @@ std::stack<FunctionExpression::Function> functions; /**< Function
%type <string_or_identifier> document
%type <string_or_identifier> object
%type <ivalue> integer
%precedence EQ NEQ LT GT GTE LTE
%precedence ':'
%right '?' ':'
%left EQ NEQ LT GT GTE LTE
%left MINUSSIGN '+'
%left '*' '/' '%'
%precedence NUM_AND_UNIT
@@ -70,7 +70,7 @@ std::stack<FunctionExpression::Function> functions; /**< Function
%precedence NEG
%precedence POS
%destructor { delete $$; } num range exp cond unit_exp indexable
%destructor { delete $$; } num range exp unit_exp indexable
%destructor { delete $$; } <component>
%destructor { std::vector<Expression*>::const_iterator i = $$.begin(); while (i != $$.end()) { delete *i; ++i; } } args
@@ -99,9 +99,15 @@ exp: num { $$ = $1;
| exp '%' exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::MOD, $3); }
| exp '/' unit_exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::DIV, $3); }
| exp '^' exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::POW, $3); }
| exp EQ exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::EQ, $3); }
| exp NEQ exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::NEQ, $3); }
| exp LT exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::LT, $3); }
| exp GT exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::GT, $3); }
| exp GTE exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::GTE, $3); }
| exp LTE exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::LTE, $3); }
| indexable { $$ = $1; }
| FUNC args ')' { $$ = new FunctionExpression(DocumentObject, $1.first, std::move($1.second), $2);}
| cond '?' exp ':' exp { $$ = new ConditionalExpression(DocumentObject, $1, $3, $5); }
| exp '?' exp ':' exp { $$ = new ConditionalExpression(DocumentObject, $1, $3, $5); }
| '(' exp ')' { $$ = $2; }
;
@@ -112,26 +118,15 @@ num: ONE { $$ = new NumberExpression(Docu
args: exp { $$.push_back($1); }
| range { $$.push_back($1); }
| cond { $$.push_back($1); }
| args ',' exp { $1.push_back($3); $$ = $1; }
| args ';' exp { $1.push_back($3); $$ = $1; }
| args ',' range { $1.push_back($3); $$ = $1; }
| args ';' range { $1.push_back($3); $$ = $1; }
| args ',' cond { $1.push_back($3); $$ = $1; }
| args ';' cond { $1.push_back($3); $$ = $1; }
;
range: id_or_cell ':' id_or_cell { $$ = new RangeExpression(DocumentObject, $1, $3); }
;
cond: exp EQ exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::EQ, $3); }
| exp NEQ exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::NEQ, $3); }
| exp LT exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::LT, $3); }
| exp GT exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::GT, $3); }
| exp GTE exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::GTE, $3); }
| exp LTE exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::LTE, $3); }
| '(' cond ')' { $$ = $2; }
;
us_building_unit: USUNIT { $$ = new UnitExpression(DocumentObject, $1.scaler, $1.unitStr ); }
other_unit: UNIT { $$ = new UnitExpression(DocumentObject, $1.scaler, $1.unitStr ); }

View File

@@ -2,7 +2,7 @@
(cd "$(dirname "$0")" && \
flex -v -oExpression.lex.c Expression.l && \
bison -d -v -Wall -oExpression.tab.c Expression.y && \
bison -d -v -Wall -oExpression.tab.c -Wcounterexamples -Wconflicts-sr Expression.y && \
sed -i '1s|^|// clang-format off\n|' Expression.tab.c && \
sed -i '1s|^|// clang-format off\n|' Expression.lex.c \
)