我的PyParsing任务的继续是解析嵌套的三元表达式(例如(x == 1 ? true : (y == 10 ? 100 : 200))
)。因此,我构造了以下表达式。对我来说,这看起来很直观。但是我没有匹配:
any = Word(printables)
conditional = Forward()
sub_exp = (conditional | any)
conditional = Literal('(') + sub_exp + Literal('?') + sub_exp + Literal(':') + sub_exp + Literal(')')
for exp in conditional.scanString(block_str):
print exp
最初我认为问题在于印刷品消耗了所有东西;我将excludeChars设置为与:?)(
不匹配,但这也没有帮助。另一种方法是构建嵌套表达式,每个用于" (?"," ?:"和&# 34; :)"块。但这种方法非常混乱。有人对解析三元表达式有任何建议吗?
更新 使用下面的答案,但修改为使用scanString:
然而,当使用scanString时,它也会返回许多其他匹配(基本上,与atom匹配的任何东西)。
lpar = Literal('(').suppress()
rpar = Literal(')').suppress()
any = Combine(OneOrMore(Word(printables, excludeChars='()?:') | White(' ', max=1)))
expr = Forward()
atom = any | Group(lpar + expr + Literal('?') + expr + Literal(':') + expr + rpar)
expr << Literal('(') + atom + ZeroOrMore(expr) + Literal('?') + atom + ZeroOrMore(expr) + Literal(':') + atom + ZeroOrMore(expr) + Literal(')')
for ternary_exp in expr.scanString(block_str):
print ternary_exp
答案 0 :(得分:3)
我认为你的问题是双重的:空格(你的any
定义没有很好地处理)和递归(应该使用<<
运算符):< / p>
lpar = Literal( '(' ).suppress()
rpar = Literal( ')' ).suppress()
any = Combine(OneOrMore(Word(printables, excludeChars='()?:') | White(' ',max=1)))
expr = Forward()
atom = any | Group( lpar + expr + Literal('?') + expr + Literal(':') + expr + rpar )
expr << atom + ZeroOrMore( expr )
例如,
t2 = '(x == 1 ? true : (y == 10 ? 100 : 200))'
expr.parseString(t2)
([(['x == 1 ', '?', 'true ', ':', (['y == 10 ', '?', '100 ', ':', '200'], {})], {})], {})
答案 1 :(得分:1)
对于这种算术表达式解析,请尝试使用pyparsing的内置infixNotation
(以前称为operatorPrecedence
):
from pyparsing import *
integer = Word(nums)
variable = Word(alphas, alphanums)
boolLiteral = oneOf("true false")
operand = boolLiteral | variable | integer
comparison_op = oneOf("== <= >= != < >")
QM,COLON = map(Literal,"?:")
expr = infixNotation(operand,
[
(comparison_op, 2, opAssoc.LEFT),
((QM,COLON), 3, opAssoc.LEFT),
])
print expr.parseString("(x==1? true: (y == 10? 100 : 200) )")
打印
[[['x', '==', '1'], '?', 'true', ':', [['y', '==', '10'], '?', '100', ':', '200']]]
infixNotation
负责处理所有递归表达式,并使用()解析操作的优先级和覆盖该优先级。