Sean Mackesey
Sean Mackesey

Reputation: 10949

Simple parslet parser for comma-delimited list does not work

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.

Upvotes: 3

Views: 239

Answers (1)

Nigel Thorne
Nigel Thorne

Reputation: 21548

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:

  • Make 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)

Upvotes: 4

Related Questions