本文实现了对四则运算的语法解析规则。
EBNF 语法格式
calc_grammar = """// 求和?start: sum| NAME "=" sum -> assign_var // 赋值?sum: product| sum "+" product -> add // 加法| sum "-" product -> sub // 减法?product: atom| product "*" atom -> mul // 乘法| product "/" atom -> div // 除法?atom: NUMBER -> number // 正数| "-" atom -> neg // 数值取反| NAME -> var // 支持变量| "(" sum ")" // 支持括号// 第一个字符下划或大小写字母,其余字符是大小写字母%import common.CNAME -> NAME// 正数%import common.NUMBER%import common.WS_INLINE// 忽略空格和制表符%ignore WS_INLINE
"""
评估语法解析树
import operatorimport pytestfrom lark import Lark, Transformer, v_args, UnexpectedToken@v_args(inline=True) # Affects the signatures of the methods
class CalculateTree(Transformer):number = floatdef __init__(self):self.vars = {}def assign_var(self, name, value):self.vars[name] = valuereturn valuedef var(self, name):try:return self.vars[name]except KeyError:raise Exception("Variable not found: %s" % name)add = operator.addsub = operator.submul = operator.muldiv = operator.floordivneg = operator.negcalc = Lark(calc_grammar, parser="lalr", transformer=CalculateTree()).parsedef test_calc():assert calc("a = 1+2") == 3assert calc("1+a*-3") == -8.0assert calc("2*(3+4)") == 14.0with pytest.raises(UnexpectedToken):calc("2**4")transform_tree = CalculateTree().transform(Lark(calc_grammar, parser="lalr").parse("2*(3+4)"))assert transform_tree == 14.0with pytest.raises(UnexpectedToken):CalculateTree().transform(Lark(calc_grammar, parser="lalr").parse("2**4"))
参考
https://github.com/lark-parser/lark/blob/master/examples/calc.py