解析表达式!运营商链
嗨我知道如何解析表达式(包括括号)。 但通常解析表达式假定“操作数运算符操作数”。 F.e. :解析表达式!运营商链
5 + 12
(5 * 6) + 11
(3 + 4) + (5 * 2)
正如你所看到的值总是两个。 我在寻找的是机制(语法),可以解析类似的运算符链作为一个单一的项目,即贪婪 F.e.让说我有以下表现:
5 + 4 + 2 + 7 * 6 * 2
=> sum(5 + 4 + 2)
+
=> mult(7 * 6 * 2)
我想解析器狼吞虎咽之和为一个单一的“行动”,同为乘法。
这是不工作的语法的一个例子,但可能是你能得到什么,我想要做的想法(蟒蛇 - 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
这差不多就是你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]]]]
如果你只是分析数字,就可以使解析器也做解析添通过增加解析行动优先的每一个E级的eval(pp.pyparsing_common.number
自动转换数字字符串到整数或浮点数):
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]
这不是贪婪的exprs。我已经这样做了。如果是“1 + 2 + 3 + ....”。然后它被解析为[[+,1,2,3],+ ...] – user1019129
如果是“1 + 2-3 + 4”,你会怎么做?或“5 * 2/3 * 6”?当多个运营商具有相同的优先级时,您无法真正按运营商进行分组。 – PaulMcG
从左到右掠夺,[+,1,2,3,4]; [*,[/,[*,5,2],3],6] – user1019129
如果不指定语法形式主义中,问题太广泛而无法回答。 (除非你觉得答案是“找到一个解析器,它可以让你使用Kleene恒星,然后使用'term('+'term)*'”。) – rici