0

嗨,我知道如何解析表达式(包括括号)。但通常解析表达式假定“操作数运算符操作数”。铁:

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

如您所见,值始终为两个。我正在寻找的是机制(语法),它可以将类似运算符的链解析为单个项目,即贪婪的 Fe 假设我有以下表达式:

5 + 4 + 2 + 7 * 6 * 2

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

我希望解析器将总和作为一个单一的“动作”吞噬,乘法也是如此。

这是非工作语法的一个示例,但您可能会明白我想要做什么(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
4

1 回答 1

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

pp.pyparsing_common.number如果您只是解析数字,则可以通过将解析操作添加到每个优先级(自动将数字字符串转换为 int 或 float)来使解析器也执行解析时评估:

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

印刷:

[-316]
于 2017-09-03T01:02:49.407 回答