Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

pyparsing not parsing the whole string

Tags:

pyparsing

I have the following grammar and test case:

from pyparsing import Word, nums, Forward, Suppress, OneOrMore, Group

#A grammar for a simple class of regular expressions
number = Word(nums)('number')
lparen = Suppress('(')
rparen = Suppress(')')

expression = Forward()('expression')

concatenation = Group(expression + expression)
concatenation.setResultsName('concatenation')

disjunction = Group(lparen + OneOrMore(expression + Suppress('|')) + expression + rparen)
disjunction.setResultsName('disjunction')

kleene = Group(lparen + expression + rparen + '*')
kleene.setResultsName('kleene')

expression << (number | disjunction | kleene | concatenation)

#Test a simple input
tests = """
(8)*((3|2)|2)
""".splitlines()[1:]

for t in tests:
    print t
    print expression.parseString(t)
    print

The result should be

[['8', '*'],[['3', '2'], '2']]

but instead, I only get

[['8', '*']]

How do I get pyparsing to parse the whole string?

like image 710
Elliot Gorokhovsky Avatar asked Jan 05 '23 13:01

Elliot Gorokhovsky


2 Answers

parseString has a parameter parseAll. If you call parseString with parseAll=True you will get error messages if your grammar does not parse the whole string. Go from there!

like image 90
halloleo Avatar answered Mar 18 '23 03:03

halloleo


Your concatenation expression is not doing what you want, and comes close to being left-recursive (fortunately it is the last term in your expression). Your grammar works if you instead do:

expression << OneOrMore(number | disjunction | kleene)

With this change, I get this result:

[['8', '*'], [['3', '2'], '2']]

EDIT: You an also avoid the precedence of << over | if you use the <<= operator instead:

expression <<= OneOrMore(number | disjunction | kleene)
like image 38
PaulMcG Avatar answered Mar 18 '23 04:03

PaulMcG