解析表达式!运营商链

时间:2017-09-02 21:55:09

标签: parsing expression grammar greedy lepl

嗨,我知道如何解析表达式(包括括号)。 但通常解析表达式假定为“操作数运算符操作数”。 F.E. :

 5 + 12
 ( 5 * 6 ) + 11
 ( 3 + 4 ) + ( 5 * 2)

正如您所看到的,值总是两个。 我正在寻找的是机制(语法),而不是将类似运算符的链解析为单个项,即贪婪 F.E.假设我有以下表达式:

5 + 4 + 2 + 7 * 6 * 2

=> sum(5 + 4 + 2) 
+ 
=> mult(7 * 6 * 2)

我希望解析器将总和作为单个“动作”吞噬,对于乘法也是如此。

以下是非工作语法的一个示例,但也许您可以了解我想要做的事情(python - LEPL模块):

def build_grammar2(self):
    spaces = Token('[ \t]+')[:]
    plus = Token('\+')
    left_bracket = Token('\(')
    right_bracket = Token('\)')
    mult = Token('\*')
    bit_var = Token('[a-zA-Z0-9_!\?]+')

#   with Separator(~spaces):

    expr, group2 = Delayed(), Delayed()

    mul_node = bit_var & (~mult & bit_var)[1:] > Node
    add_node = bit_var & (~plus & bit_var)[1:] > Node
    node = mul_node | add_node

    parens = ~left_bracket & expr & ~right_bracket

    group1 = parens | node
    add = group1 & ~plus & group2 > Node
    group2 +=  group1 | add
    mul = group2 & ~mult & expr > Node
    expr +=  group2 | mul

    self.grammar = expr

1 个答案:

答案 0 :(得分:0)

这几乎是你通过pyparsing得到的:

import pyparsing as pp

add_op = pp.oneOf("+ -")
mul_op = pp.oneOf("* /")

operand = pp.pyparsing_common.number | pp.pyparsing_common.identifier

arith = pp.infixNotation(operand, 
                [
                ("-", 1, pp.opAssoc.RIGHT),
                (mul_op, 2, pp.opAssoc.LEFT),
                (add_op, 2, pp.opAssoc.LEFT),
                ])

print(arith.parseString("1+2-3+X*-7*6+Y*(3+2)").asList())

打印

[[1, '+', 2, '-', 3, '+', ['X', '*', ['-', 7], '*', 6], '+', ['Y', '*', [3, '+', 2]]]]

如果您只是解析数字,您可以通过向每个优先级别添加解析操作来使解析器也执行解析时间eval(pp.pyparsing_common.number自动将数字字符串转换为int或float):

operand = pp.pyparsing_common.number

op_fn = {
    '*': lambda a,b: a*b,
    '/': lambda a,b: a/b,
    '+': lambda a,b: a+b,
    '-': lambda a,b: a-b,
    }.get
def binop(t):
    t_iter = iter(t[0])
    ret = next(t_iter)
    for op, val in zip(t_iter, t_iter):
        ret = op_fn(op)(ret, val)
    return ret

arith = pp.infixNotation(operand, 
                [
                ("-", 1, pp.opAssoc.RIGHT, lambda t: -t[1]),
                (mul_op, 2, pp.opAssoc.LEFT, binop),
                (add_op, 2, pp.opAssoc.LEFT, binop),
                ])


print(arith.parseString("1+2-3+8*-7*6+4*(3+2)"))

打印:

[-316]