The trick in this case is that ghci doesn't use a recursive descent
parser — it uses an LR parser (generated by Happy).
Another workaround is to use memoization of some sort — see e.g. GLL
("Generalized LL") parsing.
Roman
Roman Cheplyaka wrote:
> Another workaround is to use memoization of some sort — see e.g. GLL
> ("Generalized LL") parsing.
Is there a GLL parser combinator library for Haskell? I know about the
gll-combinators for Scala, but havn't seen anything for Haskell.
Bonus points for providing the graph-structured stack (for maximal
sharing in the computation) and the shared packed parse forest (for
maximal sharing in the results) as reusable components.
Tillmann
I am not aware of any.
Dmitry Astapov and I played with this idea a long time ago, but we
didn't succeed. Might be a good time for someone interested to have
another go at it.
Roman
Right recursion is recursion of the form
A ::= B A
There are two cases to consider here.
The language defined by B may or may not contain the empty string.
If it contains the empty string, then we have an indirect left
recursion, since the rule
A ::= A
is an instance of the original rule.
If it doesn't contain the empty string, then, by the time you get to A,
you necessarily have to consume some part of the input. Thus, your
recursion is well-founded — you enter the recursion with the input
strictly smaller than you had in the beginning.
Roman
Thus, your
recursion is well-founded — you enter the recursion with the input
strictly smaller than you had in the beginning.
It is just a grammar production, which I chose to interpret recursively.
Whether it's productive when interpreted corecursively depends on the
particular interpretation, I guess, and may not actually depend on
factors like left recursion. I haven't thought about it much.
Or perhaps you meant that the production itself, when interpreted as a
definition, is corecursive? Well, yes, and so is any CFG written in BNF.
But that doesn't buy us much, and is irrelevant to the discussion of
parsing left-recursive grammars.
Or perhaps you meant that the production itself, when interpreted as a
definition, is corecursive?
It may become more obvious if you try to write two recursive descent
parsers (as recursive functions) which parse a left-recursive and a
non-left-recursive grammars, and see in which case the recursion is
well-founded and why.
Just a silly quick question: why isn't right-recursion a similar problem?
The recursion is well-founded if (drop n1 text) is smaller then text. So we have two cases, as Roman wrote:
If the language defined by B contains the empty string, then n1 can be 0, so the recursion is not well-founded and the parser might loop.