2017-02-21 2 views
1

私が優先順位を見つけることができるほとんどの例では、グループ化された(oneOf)リテラルを使用して同じレベルを設定します。このアプローチでは、2つ(またはそれ以上)のうちどれを参照してから評価を続ける必要があります。私がしたいのは、オペレータを分割して、それがどれであるかを直接知って評価することです。pyparsing precedence split

これは私が前に持っていたが、それは

た2つ(またはそれ以上)のどちらと一致していたものです

arith_prec = [ 
    (subtract_op, 2, opAssoc.LEFT, ast.Substraction), 
    (add_op, 2, opAssoc.LEFT, ast.Addition), 
    (divide_op, 2, opAssoc.LEFT, ast.Division), 
    (multiplication_op, 2, opAssoc.LEFT, ast.Multiplication), 
] 

これは私が実現したいものですが、優先レベルが今間違っています

plusop = oneOf(['+', '-']) 
multop = oneOf(['*', '/']) 
arith_prec = [ 
    (plusop, 2, opAssoc.LEFT,), 
    (multop, 2, opAssoc.LEFT,), 
] 

これを行う方法はありますか?私はoneOfとOrをarith_precの中で使ってテストしましたが、無駄です。

答えて

1

あなたの解析アクション/クラス内の演算子と一致させる必要があります。 2つのオペランドを持つオペレーションだけではなく、複数のオペレーションを取得する可能性があることに注意してください。たとえば、 "1 - 3 + 2"を解析すると[1, '-', 3, '+', 2]が得られますので、実際にはこれを加算または減算クラスとして作成することはできません。

おそらく、左から右に反復します解析された値を通じて価値を評価するために、加減算とMultDivなどのクラス、それらを組み合わせる:

class BinOp: 
    operator_map = {} 

    def __init__(self, tokens): 
     self.tokens = tokens 

    def eval(self): 
     seq = self.tokens 
     ret = seq[0] 
     for operator, operand in zip(seq[1::2], seq[2::2]): 
      ret = self.operator_map[operator](ret, operand) 
     return ret 

class AddSub(BinOp): 
    operator_map = {'+': operator.add, '-': operator.sub} 

class MultDiv(BinOp): 
    operator_map = {'*': operator.mul, '/': operator.truediv} 

plusop = oneOf(AddSub.operator_map.keys()) 
multop = oneOf(MultDiv.operator_map.keys()) 
arith_prec = [ 
    (multop, 2, opAssoc.LEFT, MultDiv), 
    (plusop, 2, opAssoc.LEFT, AddSub), 
] 

または+」を含むために「追加」のあなたの概念を広げます'および' - '操作(エンジニアリングスクールのように、「加速」という概念を一般化して、速度の変化を上げ下げする必要がありました)

いずれにしても、infixNotationメソッドを使用する場合は、各レベルの優先順位には、そのレベルのすべての演算子が含まれます。

+0

ありがとうございました。そこで、私が始めた場所に戻って、そこから続けなければなりません。 –

+0

Btw、あなたの操作の優先順位は逆です - 'multop'が先に行くべきです。 – PaulMcG