The continuation of my PyParsing quest is parsing nested ternary expressions (e.g. (x == 1 ? true : (y == 10 ? 100 : 200))
). As such, I constructed the following expression. Which, to me, seems intuitive. However I get no matches:
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
Initially I thought that the problem was with printables consuming everything; I set the excludeChars to not match :?)(
, but that didn't help either. The alternative was to construct nested expressions, one each for the "( ?", "? : " and ": )" blocks. But this approach is very messy. Does anybody have any recommendations on parsing ternary expressions?
UPDATE Using the answer from below, but modified to work with scanString:
When using scanString however, it returns a lot of other matches too (basically, anything matching 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
I think your problem is two-fold: the whitespace (which isn't handled well by your any
definition), and the recursion (which should use the <<
operator):
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 )
For example,
t2 = '(x == 1 ? true : (y == 10 ? 100 : 200))'
expr.parseString(t2)
([(['x == 1 ', '?', 'true ', ':', (['y == 10 ', '?', '100 ', ':', '200'], {})], {})], {})
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With