aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRobin Haberkorn <robin.haberkorn@googlemail.com>2024-11-25 18:58:53 +0300
committerRobin Haberkorn <robin.haberkorn@googlemail.com>2024-11-25 18:58:53 +0300
commit5597bc72671d0128e6f0dba446c4dc8d47bf37d0 (patch)
treeed8b93c4003c10a64f2eab6f8a304a838a632209
parent726847bdf3250e235c97c451a6ab466b3e9103f2 (diff)
downloadsciteco-5597bc72671d0128e6f0dba446c4dc8d47bf37d0.tar.gz
fixed subtle operator precedence bug
* It was possible to provoke operator right-associativity when placing a high-precedence operator between two low-precedence operators. 1-6*5-1 evaluated to -28 instead of the expected -30. * The reason is that SciTECO relies on operators to be resolved from left-to-right as soon as possible. The higher precedence operator prevents that and pushing the 2nd "-" only evaluated 6*5. At the end 1-30-1 would be left on the stack. teco_expressions_eval() however evaluates from right-to-left which is wrong in this case. * Instead, we now do a full eval on every operator with a lower precedence, making sure that 1-30 is evaluated first.
-rw-r--r--src/expressions.c2
-rw-r--r--tests/testsuite.at6
2 files changed, 7 insertions, 1 deletions
diff --git a/src/expressions.c b/src/expressions.c
index 25213e9..2424fb3 100644
--- a/src/expressions.c
+++ b/src/expressions.c
@@ -145,7 +145,7 @@ teco_expressions_push_calc(teco_operator_t op, GError **error)
/* calculate if op has lower precedence than op on stack */
if (first >= 0 &&
teco_expressions_precedence(op) <= teco_expressions_precedence(teco_expressions_peek_op(first)) &&
- !teco_expressions_calc(error))
+ !teco_expressions_eval(FALSE, error))
return FALSE;
teco_expressions_push_op(op);
diff --git a/tests/testsuite.at b/tests/testsuite.at
index 59b1041..74df3a0 100644
--- a/tests/testsuite.at
+++ b/tests/testsuite.at
@@ -52,6 +52,12 @@ AT_SETUP([Missing left operand])
AT_CHECK([$SCITECO -e '+23='], 1, ignore, ignore)
AT_CLEANUP
+AT_SETUP([Operator precedence])
+AT_CHECK([$SCITECO -e "(1-6*5)+29\"N(0/0)'"], 0, ignore, ignore)
+AT_CHECK([$SCITECO -e "(1-6*5-1)+30\"N(0/0)'"], 0, ignore, ignore)
+AT_CHECK([$SCITECO -e "(1-6*5-1*2)+31\"N(0/0)'"], 0, ignore, ignore)
+AT_CLEANUP
+
AT_SETUP([Closing loops at the correct macro level])
AT_CHECK([$SCITECO -e '@^Ua{>} <Ma'], 1, ignore, ignore)
AT_CLEANUP