解析嵌套的三元表达式

时间:2014-12-17 13:51:14

标签: python pyparsing

我的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

2 个答案:

答案 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负责处理所有递归表达式,并使用()解析操作的优先级和覆盖该优先级。