com-lihaoyi / fastparse

Writing Fast Parsers Fast in Scala
https://com-lihaoyi.github.io/fastparse
MIT License
1.09k stars 164 forks source link

Unexpected parsing behavior when composing parsers programmatically #298

Open Amaumaury opened 7 months ago

Amaumaury commented 7 months ago

I'm trying to build a simple parser using fastparse which succeeds when the given input is one of the words defined in a given list. Concretely this is what my code looks like:

val words = List("a", "b", "c", "d")

def reader[$: P] = words.map(f => P( f )).reduce((l, r) => l | r )

fastparse.parse(input, reader(_))

The parser fails when input is "a", "b", or "c" and succeeds when given "d". Precisely, the parser seems to succeed when "d" appears in the input and all other characters are from the list of words.

From my understanding this parser should succeed on "a", "b", "c" and "d". Am I missing something ?

lihaoyi commented 6 months ago

This is a known issue, the workaround is to do something like this

val words = List("a", "b", "c", "d")

def reader[$: P] = words.map(f => () => P( f )).foldLeft(Fail)((l, r) => l | r() )

fastparse.parse(input, reader(_))

Basically the call to P( f ) runs immediately, which is causing problems because .map and .reduce are eager. To defer evaluation, we need to wrap it in a () => and only call it when necessary

Amaumaury commented 6 months ago

Thanks a lot for answering. I'm sorry I was not able to identify this as a known issue before posting.