2016-08-04 3 views
1

'|'を考慮して抽象構文木を作成するにはどうすればよいですか?これは私のコードを使用プライ</p> <pre><code>expr : expr '+' term | expr '-' term | term term : term '*' factor | term '/' factor | factor factor : '(' expr ')' | identifier | number </code></pre> <p>である:以下の文法を考えると(プライ/ Yaccの)

from ply import lex, yacc 

tokens = [ 
    "identifier", 
    "number", 
    "plus", 
    "minus", 
    "mult", 
    "div" 
] 

t_ignore = r" \t" 
t_identifier = r"^[a-zA-Z]+$" 
t_number = r"[+-]?(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?" 
t_plus = r"\+" 
t_minus = r"-" 
t_mult = r"\*" 
t_div = r"/" 

def p_stmt(p): 
    """stmt : expr""" 
    p[0] = ("stmt", p[1]) 

def p_expr(p): 
    """expr : expr plus term 
      | expr minus term 
      | term""" 
    p[0] = ("expr", p[1], p[2]) # Problem here <<< 

def p_term(p): 
    """term : term mult factor 
      | term div factor 
      | factor""" 

def p_factor(p): 
    """factor : '(' expr ')' 
       | identifier 
       | number""" 


if __name__ == "__main__": 
    lex.lex() 
    yacc.yacc() 
    data = "32 + 10" 
    result = yacc.parse(data) 
    print(result) 

私が表現してASTを構築することが出来るのですか、私はアクセスできない場合演算子?私はp_expr_plusのような関数を分けることができましたが、この場合は演算子の優先順位を削除します。 docsは私が初心者であり、この問題を解決することはできないので、あまり役に立ちません。私が対象is thisで見つけた最高の素材ですが、演算子の優先順位の複雑さは考慮されていません。

EDIT:IndexErrorを取得しているため、2またはp [3]にアクセスできません(これは用語にのみ一致します)。私がリンクしたPDFでは、( '+'、p 1、p 2)のように明示的に演算子をタプルの中に入れて、優先順位を考慮して問題を明らかにしています(関数を分離できません。表現は、パイプを考慮して任意の演算子にアクセスする方法があるはずです)。

+0

からスニペットを見てみましょう。優先順位に問題はありません。あなたは本当に優先順位を使用しません。文法は曖昧でなく、演算子の優先順位は文法に固有のものです。 2つの異なるアクション関数の間で非終端記号を分割しても、文法は変更されず、より単純なアクションが生成されます。 – rici

答えて

1

p[0] = ("expr", p[1], p[2])で、p 1は左側の式、p [2]は演算子、p [3]は右手となります期間。

p [2]を使用して演算子を決定し、p [3]を追加するだけです。必要なので、これでいいです。

また、最後のルールが| term"""の場合、pは4個ではなく2個のアイテムしか持たないため、pのアイテム数を確認する必要があります。

はあなたがあるため優先度の「機能を分離することができない」と感じ、なぜ私は理解していないGardenSnake example:

def p_comparison(p): 
    """comparison : comparison PLUS comparison 
        | comparison MINUS comparison 
        | comparison MULT comparison 
        | comparison DIV comparison 
        | comparison LT comparison 
        | comparison EQ comparison 
        | comparison GT comparison 
        | PLUS comparison 
        | MINUS comparison 
        | power""" 
    if len(p) == 4: 
     p[0] = binary_ops[p[2]]((p[1], p[3])) 
    elif len(p) == 3: 
     p[0] = unary_ops[p[1]](p[2]) 
    else: 
     p[0] = p[1] 
+0

問題は、p [3]を使用するとリストのインデックスが範囲外になることです。オペレータは考慮されません。私がリンクしたPDFでは、演算子を明示的に「保存」します:( '+'、p [1]、p [2])。これの問題は、それがどの演算子でもありうることです。優先順位を検討する必要があります。 –

+0

ああ、そうです。それは最後の行である必要があります。最後のルールが一致すると、 'p'は4つではなく2つのアイテムしか持たないでしょう。 –

+0

exprとtermの両方が終了するので、" 32 + 10 "は" expr plus term " –