Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork298
Description
I have a grammar where I want to be able to parse an empty line as a "null statement", like Python'spass. It's probably not strictly necessary for my language but it will be helpful during development.
Problem is, the two approaches I have tried don't work.
This code below ends up in an infinite loop:
importunittestclassPyParsingTests(unittest.TestCase):deftest_compound_statements(self):importpyparsingaspp# No warning is emittedpp.enable_all_warnings()# doesn't matter whether I remove newline from the set of skippable whitespace characters, or not# pp.ParserElement.set_default_whitespace_chars(' \t')empty_line=pp.rest_of_linenull_statement=empty_line# Doesn't matter which of the two formulations below I use - same result in each case#compound_statement = pp.OneOrMore(null_statement)compound_statement=null_statement+null_statement[...]# I know this is deprecated, but using here just in case. No RecursiveGrammarException is raised#compound_statement.validate()# Expected result here - parses 3 'empty_line' elements.# Observed result - seems to loop forevercompound_statement.parse_string("\n\n\n",parse_all=True)# Same happens even without the parse_all#compound_statement.parse_string("\n\n\n")# And with whitespace in each line#compound_statement.parse_string(" \n \n \n")if__name__=='__main__':unittest.main()
I guessed that this is becausepp.rest_of_line does not consume the end of line character, meaning the parser would never make progress. This makes sense but I can't imagine the infinite loop is desired.
If I amend theempty_line definition to this:empty_line = pp.rest_of_line + "\n", then I get the following exceptions:
ErrorTraceback (mostrecentcalllast):File"E:\Code\whatever\.venv\Lib\site-packages\pyparsing\core.py",line846,in_parseNoCacheloc,tokens=self.parseImpl(instring,pre_loc,do_actions)^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^File"E:\Code\whatever\.venv\Lib\site-packages\pyparsing\core.py",line2492,inparseImplifinstring[loc]==self.firstMatchChar:~~~~~~~~^^^^^IndexError:stringindexoutofrangeDuringhandlingoftheaboveexception,anotherexceptionoccurred:Traceback (mostrecentcalllast):File"E:\Code\whatever\tests\test_random.py",line22,intest_compound_statementscompound_statement.parse_string("\n\n\n",parse_all=True)File"E:\Code\whatever\.venv\Lib\site-packages\pyparsing\core.py",line1212,inparse_stringraiseexc.with_traceback(None)pyparsing.exceptions.ParseException:Expected'\n',foundendoftext (atchar3), (line:4,col:1)
I am not sure how I would avoid the second exception (which seems to be complaining that it can't parse a 4th line, even though it only wants "one or more", and the first exception being unhandled before the second is thrown just looks like a bug.