This file was automatically generated from http://svn.pugscode.org/pugs/ext/Parse-Rule/Architecture.pod on Wed Jun 6 22:16:50 2007 GMT, revision 16639.
Architecture - the Parse::Rule OO architecture
This architecture guide was written largely for the purpose of me, the implementor, because as I convert to the new architecture, I'm having trouble navigating and understanding what I still need to do. But it will probably serve as a useful guide to the hacker/extender.
Here are the goals:
However, being noncommittal to these two things at once is a bit of a challenge. They are not orthogonal. For example, the CPS runtime would like the Text medium to take a match object and return an updated match object upon matching a literal and fail if it couldn't. However, the optimized DFA runtime would like to query the Text medium for each of its characters and then compile a match itself.
So I designed it as a combinator library, much like Haskell's Parsec. However, instead of providing one library of combinators, I make a "combinator library" an object. Then to build a match, you call combinators as methods from that object:
my $c = Parse::Rule::CPS::Text.new;
# / [foo]+ /
$c.quantify(:min(1), $c.literal("foo"));
This combinator library object is composed out of roles to achieve
almost independent modularity. There is a base role called Strategy
that has things like quantify, concat, capture, etc. Every
runtime must implement all of these combinators (except those
combinators -- currently none -- that can be built out of other
combinators).
There is also a base role for each medium. For example, for Text,
the base role requires the literal and any_char combinators to be
implemented. On top of those, together with the combinators from a
Strategy role, it builds things like beginning_of_line,
word_boundary, etc. Since these use the combinators in a role, they
are not specific to any particular strategy.
Then to build the final library object, create a class that combines a
Strategy role and a medium role, and override those methods required
by the medium role in terms of that strategy. There will therefore be
one class for every strategy/medium combination, but it should be very
small.
Here is the module tree layout:
Core - absolutely global stuff, like the structure of the
match object
Strategy - the strategy base role
Medium - the medium and pos base roles
Media:: - the base roles and pos objects for each medium
Strategies:: - one module for each strategy, with a submodule for
each medium