/usr/local/CPAN/Perl6-Pugs/P6P6Rule.pm
# Perl6 implementation of the 'Rule' syntax
# author: Flavio S. Glock - fglock@gmail.com
use v6-alpha;
grammar Pugs::Grammar::P6Rule
does Pugs::Grammar::BaseCategory;
# this file was extracted from the P6 version in Pugs-Compiler-Rule
use Pugs::Compiler::Rule;
use Pugs::Compiler::Token;
use Pugs::Compiler::Regex;
use Pugs::Grammar::Perl6;
use Pugs::Runtime::Match;
our @rule_terms;
# TODO - reuse 'ident' from other modules
regex ident {
[ <alnum> | _ | <'::'> ]+
}
token capturing_group {
\( <rule> \)
{ return { capturing_group => $/{rule}() ,} }
}
token non_capturing_group {
\[ <rule> \]
{ return $/{rule}() }
}
regex metasyntax {
\< ([ <metasyntax> | . ]+?) \>
{ return { metasyntax => $/[0]() ,} }
}
token named_capture_body {
| <capturing_group> { return { rule => $/{capturing_group}(), } }
| <non_capturing_group> { return { rule => $/{non_capturing_group}(),} }
| <metasyntax> { return { rule => $/{metasyntax}(), } }
| { die "invalid alias syntax" }
}
@Pugs::Grammar::P6Rule::rule_terms = (
#*capturing_group =
token {
\( <rule> \)
{ return { capturing_group => $/{rule}() ,} }
},
#*after =
token {
\< after <?ws> <rule> \>
{ return { after => {
rule => $/{rule}(),
}, }
}
},
#*before =
token {
\< before <?ws> <rule> \>
{ return { before => {
rule => $/{rule}(),
}, }
}
},
#*negate =
token {
\< \! <rule> \>
{ return { negate => {
rule => $/{rule}(),
}, }
}
},
regex {
#metasyntax =>
\< ([ <metasyntax> | \\ . | . ]+?) \>
{ return { metasyntax => $/[0]() ,} }
},
#*named_capture =
token {
\$ \< <ident> \> <?ws>? \:\= <?ws>? <named_capture_body>
{ my $body = $/{named_capture_body}();
$body->{ident} = $/{ident}();
return { named_capture => $body, }
}
},
regex {
#match_variable
[ \$ | \@ | \% ] <digit>+
{ return { match_variable => $/() ,} }
},
regex {
#variable_rule =>
[ \$ | \@ | \% ]
\^?
[ <alnum> | _ | \: \: ]+
{ return { variable => $() ,} }
},
regex {
# closure_rule =>
# callback perl6 compiler
\{ <Pugs::Grammar::Perl6.parse> \}
{ return { closure => $/{'Pugs::Grammar::Perl6.parse'}() ,} }
},
regex {
#special_char =>
\\ .
{ return { special_char => $(), } }
},
Pugs::Compiler::Token->compile(
#dot =>
\.
{ return { 'dot' => 1 ,} }
},
Pugs::Compiler::Token->compile(
#non_capturing_group =>
\[ <rule> \]
{ return $/{rule}() }
},
#*colon =
token {
( <':::'>
| \:\?
| \:\+
| \:\: | \:
| \$\$ | \$
| \^\^ | \^
)
{ return { colon => $/() ,} }
},
); # /@rule_terms
token term {
| <before \} > { fail }
| <before \] > { fail }
| <before \) > { fail }
| <before \> > { fail }
| <@Pugs::Grammar::P6Rule::rule_terms>
{
#print "term: ", Dumper( $_[0]->data );
return $/{'Pugs::Grammar::P6Rule::rule_terms'}()
}
| ( <-[ \] \} \) \> \: \? \+ \* \| \& ]> )
{
#print "constant: ", Dumper( $_[0]->data );
return { 'constant' => $/[0]->() ,}
}
}
token quantifier {
$<ws1> := (<?ws>?)
<term>
$<ws2> := (<?ws>?)
$<quant> := (
| <'??'>
| <'*?'>
| <'+?'>
| <'?'>
| <'*'>
| <'+'>
| <null> )
$<ws3> := (<?ws>?)
{ return {
term => $/{term}(),
quant => $/{quant}(),
ws1 => $/{ws1}(),
ws2 => $/{ws2}(),
ws3 => $/{ws3}(),
}
}
}
token concat {
$<q1> := <quantifier>
[ $<q2> := <concat>
{ return { concat => [
{ quant => $/{q1}() ,},
$/{q2}(),
] ,}
}
| { return { quant => $/{q1}() ,} }
]
}
token rule {
[ <?ws>? \| ]?
$<q1> := <concat>
[ \| $<q2> := <rule>
{ return { alt => [
$/{q1}(),
$/{q2}(),
] ,}
}
| { return $/{q1}() }
]
}