beam: fix unary-vs-power precedence in expr_eval (-2**2 now -(2**2))

This commit is contained in:
beam committed 2026-11-03 17:24:46 +00:00
1 parent 5b130c472d
commit 17803fd3a4
2 files changed
+58 -1

No files matched your search

+2 -1
View File
@@ -111,7 +111,8 @@ class Parser:
def parse_unary(self):
if self.peek()[0] == 'op' and self.peek()[1] in ('+', '-'):
op = self.advance()[1]
v = self.parse_unary()
# operand is a full power expression so that -2**2 == -(2**2)
v = self.parse_factor()
return -v if op == '-' else v
return self.parse_primary()
+56
View File
@@ -0,0 +1,56 @@
import math
import sys, os
sys.path.insert(0, os.path.dirname(__file__))
from expr_eval import evaluate, EvalError
def test_basic():
assert evaluate("2 + 3 * 4") == 14
assert evaluate("(2+3)*4") == 20
assert evaluate("10 / 3") == 10/3
assert evaluate("10 // 3") == 3
assert evaluate("10 % 3") == 1
def test_power_precedence():
# unary binds looser than ** (matches Python)
assert evaluate("-2**2") == -4
assert evaluate("(-2)**2") == 4
assert evaluate("2**-2") == 0.25
assert evaluate("2**3**2") == 512
def test_unary():
assert evaluate("--5") == 5
assert evaluate("-(-3)") == 3
def test_funcs():
assert evaluate("sqrt(16)") == 4
assert abs(evaluate("sin(0)")) < 1e-12
assert evaluate("max(1,2,3)") == 3
assert evaluate("min(1,2,3)") == 1
assert evaluate("abs(-7)") == 7
def test_vars():
assert evaluate("x + pi", {"x": 3, "pi": math.pi}) == 3 + math.pi
def test_errors():
for e in ["2 +", "1/0", "foo", "2 @ 3", "sqrt(-1)"]:
try:
evaluate(e)
raise AssertionError(f"no error for {e!r}")
except EvalError:
pass
if __name__ == "__main__":
# run all test_ functions
import traceback
g = globals()
failed = 0
for name in sorted(n for n in g if n.startswith("test_")):
try:
g[name]()
print("PASS", name)
except Exception:
failed += 1
print("FAIL", name)
traceback.print_exc()
print("FAILED:", failed)
sys.exit(1 if failed else 0)