pyparsing优先级拆分

pyparsing precedence splitting

在我能找到的大多数示例中,优先级使用分组的 (oneOf) 文字来设置相同的级别。使用这种方法,我将不得不查找它是 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,),
]

有办法吗?我已经在 arith_prec 中使用 oneOf 和 Or 进行了测试,但没有用。

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

也许将它们组合成 class 类,如 AddSub 和 MultDiv,它们将迭代 left-to-right 通过解析的值来计算值:

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

或者扩展您的 "addition" 概念以包括“+”和“-”操作。 (就像在工程学院一样,我们必须概括 "acceleration" 的概念以包括速度的任何变化,无论是向上还是向下。)

无论如何,如果您使用 infixNotation 方法,则必须让每个优先级别都包含该级别的所有运算符。