parsimonious
parsimonious copied to clipboard
RecursionError
I'm writing a custom language, and a friend recommended to use this library. Grammar:
grammar = Grammar(r"""
program = stmt*
class = "class" params? compound
while = "while" cond compound
function = "function" params f_compound
cond = ("(" value (comp value)* ")") / (value (comp value)*)
assign = var "=" value
if = "if" cond compound else?
else = "else" compound
try = "try" compound except?
except = "except" compound
params = "(" comma_args? ")"
f_stmt = stmt / return
stmt = (assign / if / while / function / class)
f_compound = "{" f_stmt* "}"
compound = "{" stmt* "}"
return = "return" stmt?
array = "[" comma_args? "]"
comma_args = value ("," value)*
value = string / integer / float / var / array / binop / call / comp
float = integer "." integer
attr = var "." varname
string = ('"' ~'[^"]*' '"') / ("'" ~"[^']*" "'")
binop = value op value
op = ~"[\+\-\/\*]"
comp = "==" / "!=" / ">=" / "<=" / ">" / "<"
call = var params
var = varname / attr
varname = ~"[A-Z_][A-Z0-9_]*"i
integer = ~"[0-9]+"
_ = ~r'\s'*
""")
when using print(grammar.parse("x = 1 + 1")), I get the following error:
Traceback (most recent call last):
File "test_lexer.py", line 36, in <module>
res = grammar.parse("x=1+1")
File "/usr/lib/python3.6/site-packages/parsimonious/grammar.py", line 115, in parse
return self.default_rule.parse(text, pos=pos)
File "/usr/lib/python3.6/site-packages/parsimonious/expressions.py", line 120, in parse
node = self.match(text, pos=pos)
File "/usr/lib/python3.6/site-packages/parsimonious/expressions.py", line 135, in match
node = self.match_core(text, pos, {}, error)
File "/usr/lib/python3.6/site-packages/parsimonious/expressions.py", line 178, in match_core
error)
File "/usr/lib/python3.6/site-packages/parsimonious/expressions.py", line 458, in _uncached_match
node = self.members[0].match_core(text, new_pos, cache, error)
File "/usr/lib/python3.6/site-packages/parsimonious/expressions.py", line 178, in match_core
error)
File "/usr/lib/python3.6/site-packages/parsimonious/expressions.py", line 356, in _uncached_match
node = m.match_core(text, pos, cache, error)
File "/usr/lib/python3.6/site-packages/parsimonious/expressions.py", line 178, in match_core
error)
File "/usr/lib/python3.6/site-packages/parsimonious/expressions.py", line 333, in _uncached_match
node = m.match_core(text, new_pos, cache, error)
File "/usr/lib/python3.6/site-packages/parsimonious/expressions.py", line 178, in match_core
error)
File "/usr/lib/python3.6/site-packages/parsimonious/expressions.py", line 356, in _uncached_match
node = m.match_core(text, pos, cache, error)
File "/usr/lib/python3.6/site-packages/parsimonious/expressions.py", line 178, in match_core
error)
and this repeated until it says RecursionError: maximum recursion depth exceeded
Is it my grammar at fault, or is there something else I'm doing wrong?
Right now, all I can find wrong is
value = string / integer / float / var / array / binop / call / comp
binop = value op value
They seem to be self-referential, and might be the source of the recursion.
I'm not sure how to fix the grammar, but am quite sure that it's not an issue with the parser.
I tried to reproduce your bug with a simpler version of the grammar:
>>> g = Grammar(r'''
... expr = value EOF
... value = integer / binop
... integer = ~"[0-9]+"
... binop = value spaces op spaces value
... op = ~"[\+\-]"
... EOF = ~"$"
... spaces = ~"\s*"
... ''')
But when trying to parse '1 + 1', the problem is that parsimonious stops after matching the 'integer':
>>> g.parse('1 + 1')
....
ParseError: Rule 'EOF' didn't match at ' + 1' (line 1, column 2).
Only after switching the order of binop and integer in the value rule, I get the RecursionError.