beam: fix unary-vs-power precedence in expr_eval (-2**2 now -(2**2))
This commit is contained in:
1 parent
5b130c472d
commit
17803fd3a4
2 files changed
+58
-1
No files matched your search
@@ -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()
|
||||
|
||||
|
||||
@@ -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)
|
||||
Reference in new issue
Block a user