pyparsing的递归表达式 [英] Recursive expressions with pyparsing
问题描述
我试图弄清楚在可能进行递归(任何形式都未包含)表达式的情况下如何执行左关联表达式.例如,我想这样做:
I'm trying to figure out how to do a left-associative expression where recursive (not-enclosed in anything) expressions are possible. For example, I'd like to do:
expr + OP + expr
可以将2个操作(如1 x 2 x 3
)解析为(expr OP expr) OP expr
结果.
that parses 2 operations like 1 x 2 x 3
into (expr OP expr) OP expr
result.
如果我尝试阻止expr
解析进行无限递归,则可以执行以下操作:
If I try to prevent expr
parsing from infinite recursion, i can do something like:
expr -> Group(simple_expr + OP + expr)
| simple_expr
但是我会得到expr OP (expr OR expr)
结果.
如何强制左侧装订?
我对operatorPrecedence
有所了解,但是当运算符为"IS" + Optional("NOT")
或类似名称时,它似乎无法正确匹配.
I know about the operatorPrecedence
but when the operator is "IS" + Optional("NOT")
or similar, it doesn't seem to match properly.
推荐答案
下面是一个示例解析操作,该操作将采用标记的平面列表并将其嵌套,就好像是递归左解析一样:
Here is an example parse action that will take the flat lists of tokens and nest them as if parsed left-recursively:
from pyparsing import *
# parse action -maker
def makeLRlike(numterms):
if numterms is None:
# None operator can only by binary op
initlen = 2
incr = 1
else:
initlen = {0:1,1:2,2:3,3:5}[numterms]
incr = {0:1,1:1,2:2,3:4}[numterms]
# define parse action for this number of terms,
# to convert flat list of tokens into nested list
def pa(s,l,t):
t = t[0]
if len(t) > initlen:
ret = ParseResults(t[:initlen])
i = initlen
while i < len(t):
ret = ParseResults([ret] + t[i:i+incr])
i += incr
return ParseResults([ret])
return pa
# setup a simple grammar for 4-function arithmetic
varname = oneOf(list(alphas))
integer = Word(nums)
operand = integer | varname
# ordinary opPrec definition
arith1 = operatorPrecedence(operand,
[
(None, 2, opAssoc.LEFT),
(oneOf("* /"), 2, opAssoc.LEFT),
(oneOf("+ -"), 2, opAssoc.LEFT),
])
# opPrec definition with parseAction makeLRlike
arith2 = operatorPrecedence(operand,
[
(None, 2, opAssoc.LEFT, makeLRlike(None)),
(oneOf("* /"), 2, opAssoc.LEFT, makeLRlike(2)),
(oneOf("+ -"), 2, opAssoc.LEFT, makeLRlike(2)),
])
# parse a few test strings, using both parsers
for arith in (arith1, arith2):
print arith.parseString("A+B+C+D+E")[0]
print arith.parseString("A+B+C*D+E")[0]
print arith.parseString("12AX+34BY+C*5DZ+E")[0]
打印:
(正常)
['A', '+', 'B', '+', 'C', '+', 'D', '+', 'E']
['A', '+', 'B', '+', ['C', '*', 'D'], '+', 'E']
[['12', 'A', 'X'], '+', ['34', 'B', 'Y'], '+', ['C', '*', ['5', 'D', 'Z']], '+', 'E']
(类似于LR)
[[[['A', '+', 'B'], '+', 'C'], '+', 'D'], '+', 'E']
[[['A', '+', 'B'], '+', ['C', '*', 'D']], '+', 'E']
[[[[['12', 'A'], 'X'], '+', [['34', 'B'], 'Y']], '+', ['C', '*', [['5', 'D'], 'Z']]], '+', 'E']
这篇关于pyparsing的递归表达式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!