正如 Fredrik 指出的,您可以在 Python 中执行 eval。我想我会添加一个更通用的方法,它可以在任何语言中使用,并且可能会为那些没有看到它们的人提供一些简单的解析器。
您正在描述一种语言,其正式定义如下所示:
expr := sum
sum := prod [("+" | "-") prod]...
prod := digit [("*" | "/") digit]...
digit := '0'..'9'
这个语法(我不会费心做出正确的 EBNF)接受以下字符串:“3”、“4*5/2”和“8*3+9”,等等。
这为我们提供了如何解析它的线索,而评估只不过是在我们进行过程中累积结果。以下是工作 Python 2 代码。注意代码与语法的紧密程度。
class ParseFail(Exception):
pass
def eval_expr(str):
value, pos = eval_sum(str, 0)
return value
def eval_sum(str, pos):
value, pos = eval_product(str, pos)
accum = value
while pos != len(str):
op = str[pos]
if not str[pos] in ['+', '-']:
raise ParseFail("Unexpected symbol at position "
"{pos} of {str}".format(str=str, pos=pos))
value, pos = eval_product(str, pos + 1)
if op == '+':
accum += value
else:
accum -= value
return accum, pos
def eval_product(str, pos):
value, pos = eval_digit(str, pos)
accum = value
while pos != len(str):
op = str[pos]
if not str[pos] in ['*', '/']:
return accum, pos
value, pos = eval_digit(str, pos + 1)
if op == '*':
accum *= value
else:
accum /= value
return accum, pos
def eval_digit(str, pos):
if not str[pos].isdigit():
raise ParseFail("Unexpected symbol at position "
"{pos} of {str}".format(str=str, pos=pos))
return int(str[pos]), pos + 1
try:
print "3 ->", eval_expr("3")
print "3*4 ->", eval_expr("3*4")
print "2+3*4-5 ->", eval_expr("2+3*4-5")
# Should raise ParseFail
print "2+3*4^2-5 ->", eval_expr("2+3*4^2-5")
except ParseFail as err:
print
print err.args[0]
这是一个示例运行:
$ python simple_expr.py
3 -> 3
3*4 -> 12
2+3*4-5 -> 9
2+3*4^2-5 ->
Unexpected symbol at position 5 of 2+3*4^2-5
很容易将其扩展到具有更多运算符的完整字符串计算器,例如指数运算符'^'和多位整数。括号、浮点数和函数可能需要一些工作,但也不是那么难。在我看来,每个程序员都应该在一生中尝试一次。