beam: fix safe_eval unary minus precedence vs **

This commit is contained in:
beam committed 2026-10-22 20:50:20 +00:00
1 parent bf5238169e
commit 7706712fbc
2 files changed
+14 -12

No files matched your search

+12 -12
View File
@@ -141,10 +141,10 @@ class _Parser:
return value return value
def term(self): def term(self):
value = self.power() value = self.unary()
while self.peek()[0] == _OP and self.peek()[1] in ("*", "/", "//", "%"): while self.peek()[0] == _OP and self.peek()[1] in ("*", "/", "//", "%"):
op = self.advance()[1] op = self.advance()[1]
rhs = self.power() rhs = self.unary()
if op == "*": if op == "*":
value = value * rhs value = value * rhs
elif op == "/": elif op == "/":
@@ -161,20 +161,20 @@ class _Parser:
value = value % rhs value = value % rhs
return value return value
def power(self):
base = self.unary()
if self.peek()[0] == _OP and self.peek()[1] == "**":
self.advance()
exp = self.power() # right-assoc
return base ** exp
return base
def unary(self): def unary(self):
if self.peek()[0] == _OP and self.peek()[1] in ("+", "-"): if self.peek()[0] == _OP and self.peek()[1] in ("+", "-"):
op = self.advance()[1] op = self.advance()[1]
val = self.unary() val = self.power() # unary lower precedence than ** (python semantics)
return -val if op == "-" else val return -val if op == "-" else val
return self.primary() return self.power()
def power(self):
base = self.primary()
if self.peek()[0] == _OP and self.peek()[1] == "**":
self.advance()
exp = self.unary() # right-assoc, exponent may be signed
return base ** exp
return base
def primary(self): def primary(self):
t = self.peek() t = self.peek()
+2
View File
@@ -4,6 +4,8 @@ cases = [
("2+3*4", 14), ("2+3*4", 14),
("(2+3)*4", 20), ("(2+3)*4", 20),
("2**3**2", 512), # right assoc ("2**3**2", 512), # right assoc
("-2**2", -4), # unary lower than **
("2**-2", 0.25), # signed exponent
("10//3", 3), ("10//3", 3),
("10%3", 1), ("10%3", 1),
("-5+2", -3), ("-5+2", -3),