Apocalypse 5
by Larry Wall
|
Pages: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
Editor's Note: this Apocalypse is out of date and remains here for historic reasons. See Synopsis 05 for the latest information.
Defining Your Own Rules
Suppose your name is Hugo and you don't like to use ! to negate an assertion.
You can define your own assertion like this:
my rule not (str $rx) { <!<{"<$rx>"}>> } # define Hugo not
/ <not [a-z]> / # same as <![a-z]>
That rule would be lexically scoped because of the my. If you think it looks like a sub declaration,
you're right. In fact, it's possible you could even declare it anonymously like a closure:
my $not = rule (str $rx) { <!<{"<$rx>"}>> };
/ <$not tonight dear> /
But maybe you don't want it lexically scoped because you're writing a grammar for general use:
grammar HugoGrammar {
rule not ($rx) { <!$rx> }
rule identifier { <not before \d> \w+ }
rule \j { \c[LF] }
rule parse { ^ <identifier> \j $ }
}
HugoGrammar.parse($line);
In this case a rule is simply a method in a grammar class, and a
grammar class is any class derived implicitly or explicitly from the
universal RULE grammar class. The built-in regex assertions like
<before \w> are really just calls to methods in the RULE class.
The namespace of a grammar is simply the method namespace of the current
class, which is the class's methods plus all inherited methods.
In addition to normal subrules, we allow some funny looking method names like:
rule :a { ... }
rule \a { ... }
Modules that mutate Perl's grammar on the fly can do so by deriving an anonymous grammar class from the default Perl6Grammar, and installing extra rules on the fly. The current regex state then continues parsing the rest of the lexical scope using some rule from the new rule set. Subsequent grammatical mutations will be derived from the current anonymous grammar unless you switch explicitly to an entirely different grammar.
Since we're writing grammar rules as if they were methods, we have access to the full syntax of method declaration, including formal parameter lists and compile-time properties. So we can easily annotate rules with pragmatic information such as operator precedence levels when you don't want to write a strictly recursive-descent parser, for instance. (And we don't want to, for Perl.)
Pages: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 |

