首先,这不是家庭作业,我试图学习pyparsing而且我被困在这里。
我的问题如下,我试图解析(abc or def) or def)
等语句
我的程序去了一个中缀表达式a or b
,因为双方都可以是表达式本身,它们也可以是中缀表达式,解析器会递归,直到达到递归深度并且没有工作完成。
以下代码:
# infix operators are automatically created and dealt with
infix_operators = ['and', '&', 'or', '|', 'implies', '->']
variable = Word(alphas)
infix_op = oneOf(infix_operators, caseless=True)
expr = Forward()
infix_expr = (expr + infix_op + expr)
complex_expr = nestedExpr('(', ')', content=expr)
expr << (infix_expr | complex_expr | variable)
print str(expr.parseString("(abc or def) or def)")[0])
我的问题很简单;如何在这种情况下避免无限循环?
答案 0 :(得分:1)
规范解决方案是实现此BNF的东西:
atom := variable | 'True' | 'False' | '(' expr ')'
factor := [ 'not' ]... atom
term := factor [ '&' factor ]...
expr := term [ '|' term ]...
解决了左递归问题,因为即使expr
最终通过term
递归 - &gt; factor
- &gt; atom
,当它到达expr
时,它首先必须解析一个前导符号(&#39;所以expr
永远不必首先解析更深的expr
在首先解析其他一些元素之前。
这个BNF几乎直接翻译为pyparsing:
and_ = Keyword('and')
or_ = Keyword('or')
not_ = Keyword('not')
true_ = Keyword('true')
false_ = Keyword('false')
not_op = not_ | '~'
and_op = and_ | '&'
or_op = or_ | '|'
expr = Forward()
identifier = ~(and_ | or_ | not_ | true_ | false_) + Word(alphas)
atom = identifier | Group('(' + expr + ')')
factor = Group(ZeroOrMore(not_op) + atom)
term = Group(factor + ZeroOrMore(and_op + factor))
expr <<= Group(term + ZeroOrMore(or_op + term))
或者你可以使用pyparsing的infixNotation
助手:
expr = infixNotation(true_ | false_ | identifier,
[
(not_op, 1, opAssoc.RIGHT),
(and_op, 2, opAssoc.LEFT),
(or_op, 2, opAssoc.LEFT),
])
infixNotation
由一个基本操作数构成(在本例中,是一个alpha变量名或一个布尔文字true
或false
),后跟一个{{ 1}}元组,按运算符优先顺序给出。 (operator, arity, associativity)
负责所有递归定义,右关联运算符与左关联运算符的解析,并对运算符进行一些预测,以避免在没有运算符的情况下对给定优先级的操作进行额外嵌套
您可以使用pyparsing的infixNotation
方法测试此表达式:
runTests
,并提供:
expr.runTests("""
p and not q
not p or p
r and (p or q)
r and p or q
not q
q
""", fullDump=False)