Why does the following Parslet parser not work for parsing comma-delimited lists? When I parse, it gets stuck and does not provide an error message:
class TestParser < Parslet::Parser
rule(:name) { match['a-z'].repeat >> str(',').maybe }
rule(:names) { name.repeat }
root(:names)
end
TestParser.new.parse_with_debug('tom,samantha,ricardo') # hangs here
I am aware of "Parslet word until delimeter present", and I know how to parse the list in other ways, but I don't understand why the above does not work.
Explanation:
An infinite loops mean you have a rule in your parser that you are looping over, but it can match against an empty string. If it consumed anything, you wouldn't get an infinite loop.
In your case: Repeat
defaults to Repeat(0)
which can match zero characters. The Maybe
makes the comma optional, so name
can match without consuming anything, so it does... Repeatedly.
Solution:
name
call repeat(1)
instead. Diagnosis:
Checkout my fork of Parslet that detects these infinite loops.
Its on github. ( https://github.com/NigelThorne/parslet )
My branch complains when it's going through a loop a second time, and it hasn't consumed anything since the last iteration. (Only use this for development... as there is a check inside a time critical loop, so performs slower)