解析表达式!运营商链

问题描述:

嗨我知道如何解析表达式(包括括号)。 但通常解析表达式假定“操作数运算符操作数”。 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) 

我想解析器狼吞虎咽之和为一个单一的“行动”,同为乘法。

这是不工作的语法的一个例子,但可能是你能得到什么,我想要做的想法(蟒蛇 - 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 
+0

如果不指定语法形式主义中,问题太广泛而无法回答。 (除非你觉得答案是“找到一个解析器,它可以让你使用Kleene恒星,然后使用'term('+'term)*'”。) – rici

这差不多就是你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]]]] 

如果你只是分析数字,就可以使解析器也做解析添通过增加解析行动优先的每一个E级的eval(pp.pyparsing_common.number自动转换数字字符串到整数或浮点数):

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] 
+0

这不是贪婪的exprs。我已经这样做了。如果是“1 + 2 + 3 + ....”。然后它被解析为[[+,1,2,3],+ ...] – user1019129

+0

如果是“1 + 2-3 + 4”,你会怎么做?或“5 * 2/3 * 6”?当多个运营商具有相同的优先级时,您无法真正按运营商进行分组。 – PaulMcG

+0

从左到右掠夺,[+,1,2,3,4]; [*,[/,[*,5,2],3],6] – user1019129