Result
is the match state that is passed around. It essentially forms a linked list through the rule as it is executed, but the linked list is done in code (i.e. with closures). It has the following members:
$.backtrack - Parsers tail-call this if they fail (see below)
$.marks - A hash that stores backtrack closures to various.
points earlier in the match. This is used to
implement backtracking controls. a*: ...
$.pos - The current position of the match (also holds the
string that is being matched against).
$.match - State that is scope-local. A new match object gets
allocated when you enter a new rule or parenthesized
group.
A Parser
is simply an object wrapper around a closure. The closure, $.parse
, takes two parameters: a Result
object and a continuation (which takes in turn a Result
object as a parameter). If the parser succeeds, it tail-calls the continuation (i.e. returns whatever the continuation returns) with an updated Result
object. If the parser fails, it tail-calls $result.backtrack()(). Backtracking parsers such as quantifiers are implemented by passing a Result
object that has a $.backtrack closure that calls back into the parser.
$.Parser
and $.Result
are virtual classes within the strategy. They're done like this until pugs gets support for virtual classes.
Captures within quantified expressions are "parallelized". That is, /[ foo (bar) ]*/ will put an array in $1, and /[ [ foo (bar) ]* ]*/ will put an array of arrays in $1. This is done by setting $match.multidex
to the index where captures should put themselves. In the former example, when (bar)
runs, multidex
will be, say, [3]
(on the fourth match of the group). In the latter, it will be, say, [2,4]
(on the third match of the outer group, and the fifth match of the inner group). XXX wrong; they should be "flat".