The answer came from Frerich on the elixir slack.
I’d gotten too far into think about the parsing aspect of the problem and didn’t see the purely functional aspect - eager vs lazy evaluation.
The solution in the end is simple, introduce an intermediate parser that sits between value() and list()
My first use of a macro in Elixir:
defmacro lazy(parser) do
quote do
Parser.new(
:lazy,
fn ctx -> Parser.invoke(unquote(parser), ctx) end
)
end
end
Now I can write:
def value() do
choice([
number_value(),
boolean_value(),
string_value(),
lazy(list_value())
])
)
And the recursion is broken.


















