pyparsing优先分裂

时间:2017-02-21 11:25:51

标签: python python-3.x pyparsing

在大多数可以找到优先级的示例中,使用分组(oneOf)文字来设置相同的级别。通过这种方法,我将不得不查找它中的哪一个(或更多),然后继续评估。我想做的是拆分操作员直接知道它是哪一个并进行评估。

这是我想要实现的,但优先级现在是错误的

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

有没有办法做到这一点?我已经使用arith_prec中的oneOf和Or进行了测试,但没有用。

1 个答案:

答案 0 :(得分:1)

您必须匹配解析操作/类中的运算符。请注意,您可能会获得多个操作,而不仅仅是具有两个操作数的操作。例如,解析“1 - 3 + 2”会给你[1, '-', 3, '+', 2],所以你真的不能创建一个加法或减法类。

也许将它们组合到AddSub和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方法,则必须让每个级别的优先级都包含该级别的所有运算符。