This is due to referential transparency. Just as no function can distinguish
let x = 1:x let x = 1:1:1:x let x = 1:1:1:1:1:1:1:1:1:... -- if this were writeable
no function can distinguish a grammar from a leaf graph and a grammar that is an infinite tree. Partitioning algorithms from below should be able to see the grammar in the form of a graph in order to list all possible states of parsing.
The fact that parsers see their input from top to bottom, because infinite trees allow them to be more powerful, because a tree can be computationally more complex than any graph; eg,
numSequence n = string (show n) *> option () (numSequence (n+1))
accepts any finite ascending sequence of numbers starting with n . This has infinitely many different parsing states. (Perhaps this could have been imagined without context, but it would have been difficult and would have required a greater understanding of the code than, I think, a parsing library could use)
The combinatorial library can be written from the bottom up, although it is a bit ugly, requiring all parsers to be "labeled" in such a way that
- the same label always refers to the same parser, and
- there is only a finite set of labels
at this point, it begins to resemble the traditional specification of grammar much more than the combinatorial specification. However, it can still be enjoyable; you would only have to stick recursive works, which would rule out any infinitely large rules such as numSequence .
luqui
source share