2017-09-02 17 views
0

私は式(かっこを含む)を解析する方法を知っています。 しかし、通常は解析式は「オペランド演算子オペランド」とみなします。 F.e. :式の解析!演算子の連鎖

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

ご覧のとおり、値は常に2です。 私が探しているのは、類似の演算子のチェーンを1つのアイテム、つまり欲張りとして解析できるよりも、メカニズム(文法)です。 F.e.

5 + 4 + 2 + 7 * 6 * 2 

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

私はパーサは1つの「アクション」、乗算のための同じよう合計をガツガツしたい:私は次の式を持っているとしましょう。ここで

はNON-作業文法の一例ですが、あなたは私が何をしたいのアイデアを得ることが可能かもしれ(の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 
+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]]]] 

あなただけの数字を解析した場合、あなたはまた、解析、ティムを行うパーサを作ることができます

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)")) 

プリント:優先の各レベルに解析アクション(pp.pyparsing_common.number int型やfloat型に数値文字列を自動変換)を追加することにより、電子のevalを使用すると、文法フォーマリズムを指定しない場合

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

関連する問題