Search code examples
pythonpyparsing

pyparsing - 2nd execution of the same statement throws an exception


Could you explain why the second execution of exactly the same parseString throws the pyparsing.ParseException: not a subentry exception, please?

Code:

from pyparsing import *
from pprint import pprint

indentStack = [1]
stmt = Forward()
suite = indentedBlock(stmt, indentStack)

funcDecl = "def" + Word(printables)
funcDef = Group( funcDecl + suite )

stmt << ( funcDef | "open" | "close")
module_body = OneOrMore(stmt)

code="""\
def process
    open
    close"""

# first execution - works fine, but modifies funcDef
pprint(funcDef)
f1 = funcDef.parseString(code)
pprint(f1)

# second execution
pprint(funcDef)
f2 = funcDef.parseString(code)  ### throws pyparsing.ParseException: not a subentry (at char 16), (line:2, col:5)
pprint(f2)


pyparsing.ParseException: not a subentry (at char 16), (line:2, col:5)

I tried to simplify the the example available in the pyparsing wiki: http://pyparsing.wikispaces.com/file/view/indentedGrammarExample.py

Full stacktrace: https://pastebin.com/QXF5ZJZ7

Link to the documentation of parseString: https://pythonhosted.org/pyparsing/pyparsing.ParserElement-class.html#parseString

EDIT 2018-02-20

I extended the code by pprint(funcDef) and I found out that after the first execution of funcDef.parseString(code) the definition of funcDef has changed from:

from:

Group:({{"def" W:(0123...)} indented block})

to:

Group:({"def" W:(0123...) indented block})

EDIT 2018-02-21

Adding indentStack.pop() before the 2nd execution of funcDef.parseString(code) solved the problem.

It's worth to mention that it's indentStack = [1] does not solve the problem. It's very interesting case so I created two snippets to show the difference (I also added few extra debug print's into the library):


Solution

  • In this case stack is multiple levels deep.

    Adding indentStack[:] = [1] before the 2nd execution of funcDef.parseString(code) solved the problem.