2017-09-02 70 views
0

嗨我知道如何解析表達式(包括括號)。 但通常解析表達式假定「操作數運算符操作數」。 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

回答

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

如果你只是分析數字,就可以使解析器也做解析添通過增加解析行動優先的每一個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