Benchmark-Perl-Formance-Cargo
view release on metacpan or search on metacpan
share/P6STD/STD_P5.pm6 view on Meta::CPAN
for @tmp {
$m ~= "\t$_ used at line " ~ %unk_routines{$_}.<line> ~ "\n";
}
}
$m;
}
# Look for an expression followed by a required lambda.
token xblock {
:my $*GOAL ::= '{';
:dba('block expression') '(' ~ ')' <EXPR>
<.ws>
<block>
}
token block {
:temp $*CURLEX;
:dba('scoped block')
[ <?before '{' > || <.panic: "Missing block"> ]
<.newlex>
<blockoid>
}
token blockoid {
# encapsulate braided languages
:temp %*LANG;
<.finishlex>
[
| :dba('block') '{' ~ '}' <statementlist>
| <?terminator> <.panic: 'Missing block'>
| <?> <.panic: "Malformed block">
]
[
| <?before \h* $$> # (usual case without comments)
{ @*MEMOS[$¢.pos]<endstmt> = 2; }
| \h* <?before <[\\,:]>>
| <.unv>? $$
{ @*MEMOS[$¢.pos]<endstmt> = 2; }
| {} <.unsp>? { @*MEMOS[$¢.pos]<endargs> = 1; }
]
}
token regex_block {
# encapsulate braided languages
:temp %*LANG;
:my $lang = %*LANG<Regex>;
:my $*GOAL ::= '}';
[ <quotepair> <.ws>
{
my $kv = $<quotepair>[*-1];
$lang = $lang.tweak($kv.<k>, $kv.<v>)
or self.sorry("Unrecognized adverb :" ~ $kv.<k> ~ '(' ~ $kv.<v> ~ ')');
}
]*
'{'
<nibble( $¢.cursor_fresh($lang).unbalanced('}') )>
[ '}' || <.panic: "Unable to parse regex; couldn't find right brace"> ]
[
| <?before \h* $$> # (usual case without comments)
{ @*MEMOS[$¢.pos]<endstmt> = 2; }
| \h* <?before <[\\,:]>>
| <.unv>? $$
{ @*MEMOS[$¢.pos]<endstmt> = 2; }
| {} <.unsp>? { @*MEMOS[$¢.pos]<endargs> = 1; }
]
}
# statement semantics
rule statementlist {
:my $*INVOCANT_OK = 0;
:dba('statement list')
[
| $
| <?before <[\)\]\}]> >
| [<statement><eat_terminator> ]*
]
}
# embedded semis, context-dependent semantics
rule semilist {
:my $*INVOCANT_OK = 0;
:dba('semicolon list')
[
| <?before <[\)\]\}]> >
| [<statement><eat_terminator> ]*
]
}
token label {
:my $label;
<identifier> ':' <?before \s> <.ws>
[ <?{ $¢.is_name($label = $<identifier>.Str) }>
<.sorry("Illegal redeclaration of '$label'")>
]?
# add label as a pseudo type
{{ $¢.add_my_name($label); }}
}
token statement {
:my $*endargs = -1;
:my $*QSIGIL ::= 0;
<!before <[\)\]\}]> >
# this could either be a statement that follows a declaration
# or a statement that is within the block of a code declaration
<!!{ $¢ = %*LANG<MAIN>.bless($¢); }>
[
| <label> <statement>
| <statement_control=p5statement_control>
share/P6STD/STD_P5.pm6 view on Meta::CPAN
<[Ee]> <[+\-]>? \d+[_\d+]*
}
# careful to distinguish from both integer and 42.method
token dec_number {
:dba('decimal number')
[
| $<coeff> = [ '.' \d+[_\d+]* ] <escale>?
| $<coeff> = [\d+[_\d+]* '.' \d+[_\d+]* ] <escale>?
| $<coeff> = [\d+[_\d+]* ] <escale>
]
<!!before [ '.' <?before \d> <.panic: "Number contains two decimal points (missing 'v' for version number?)">]? >
}
token octints { [<.ws><octint><.ws>] +% ',' }
token octint {
<[ 0..7 ]>+ [ _ <[ 0..7 ]>+ ]*
}
token hexints { [<.ws><hexint><.ws>] +% ',' }
token hexint {
<[ 0..9 a..f A..F ]>+ [ _ <[ 0..9 a..f A..F ]>+ ]*
}
##########
# Quotes #
##########
our @herestub_queue;
class Herestub {
has Str $.delim;
has $.orignode;
has $.lang;
} # end class
role herestop {
token stopper { ^^ {} $<ws>=(\h*?) $*DELIM \h* <.unv>?? $$ \v? }
} # end role
# XXX be sure to temporize @herestub_queue on reentry to new line of heredocs
method heredoc () {
my $*CTX ::= self.callm if $*DEBUG +& DEBUG::trace_call;
return if self.peek;
my $here = self;
while my $herestub = shift @herestub_queue {
my $*DELIM = $herestub.delim;
my $lang = $herestub.lang.mixin( ::herestop );
my $doc;
if ($doc) = $here.nibble($lang) {
$here = $doc.trim_heredoc();
$herestub.orignode<doc> = $doc;
}
else {
self.panic("Ending delimiter $*DELIM not found");
}
}
return self.cursor($here.pos); # return to initial type
}
proto token backslash { <...> }
proto token escape { <...> }
token starter { <!> }
token escape:none { <!> }
token babble ($l) {
:my $lang = $l;
:my $start;
:my $stop;
<.ws>
[ <quotepair> <.ws>
{
my $kv = $<quotepair>[*-1];
$lang = $lang.tweak($kv.<k>, $kv.<v>)
or self.sorry("Unrecognized adverb :" ~ $kv.<k> ~ '(' ~ $kv.<v> ~ ')');
}
]*
{
($start,$stop) = $¢.peek_delimiters();
$lang = $start ne $stop ?? $lang.balanced($start,$stop)
!! $lang.unbalanced($stop);
$<B> = [$lang,$start,$stop];
}
}
token quibble ($l) {
:my ($lang, $start, $stop);
<babble($l)>
{ my $B = $<babble><B>; ($lang,$start,$stop) = @$B; }
$start <nibble($lang)> [ $stop || <.panic: "Couldn't find terminator $stop"> ]
{{
if $lang<_herelang> {
push @herestub_queue,
::Herestub.new(
delim => $<nibble><nibbles>[0]<TEXT>,
orignode => $¢,
lang => $lang<_herelang>,
);
}
}}
}
token sibble ($l, $lang2) {
:my ($lang, $start, $stop);
<babble($l)>
{ my $B = $<babble><B>; ($lang,$start,$stop) = @$B; }
$start <left=nibble($lang)> [ $stop || <.panic: "Couldn't find terminator $stop"> ]
[ <?{ $start ne $stop }>
<.ws> <quibble($lang2)>
||
{ $lang = $lang2.unbalanced($stop); }
<right=nibble($lang)> $stop
]
share/P6STD/STD_P5.pm6 view on Meta::CPAN
|| $start [ :lang($lang) <statementlist> ] [$stop || <.panic: "Couldn't find terminator $stop"> ]
]
}
# note: polymorphic over many quote languages, we hope
token nibbler {
:my $text = '';
:my $from = self.pos;
:my $to = $from;
:my @nibbles = ();
:my $multiline = 0;
{ $<_from> = self.pos; }
[ <!before <stopper> >
[
|| <starter> <nibbler> <stopper>
{{
push @nibbles, $¢.makestr(TEXT => $text, _from => $from, _pos => $to ) if $from != $to;
my $n = $<nibbler>[*-1]<nibbles>;
my @n = @$n;
push @nibbles, $<starter>;
push @nibbles, @n;
push @nibbles, $<stopper>;
$text = '';
$to = $from = $¢.pos;
}}
|| <escape> {{
push @nibbles, $¢.makestr(TEXT => $text, _from => $from, _pos => $to ) if $from != $to;
push @nibbles, $<escape>[*-1];
$text = '';
$to = $from = $¢.pos;
}}
|| .
{{
my $ch = substr($*ORIG, $¢.pos-1, 1);
$text ~= $ch;
$to = $¢.pos;
if $ch ~~ "\n" {
$multiline++;
}
}}
]
]*
{{
push @nibbles, $¢.makestr(TEXT => $text, _from => $from, _pos => $to ) if $from != $to or !@nibbles;
$<nibbles> = \@nibbles;
$<_pos> = $¢.pos;
$<nibbler> :delete;
$<escape> :delete;
$<starter> :delete;
$<stopper> :delete;
$*LAST_NIBBLE = $¢;
$*LAST_NIBBLE_MULTILINE = $¢ if $multiline;
}}
}
# and this is what makes nibbler polymorphic...
method nibble ($lang) {
self.cursor_fresh($lang).nibbler;
}
token p5quote:sym<' '> { "'" <nibble($¢.cursor_fresh( %*LANG<Q> ).tweak(:q).unbalanced("'"))> "'" }
token p5quote:sym<" "> { '"' <nibble($¢.cursor_fresh( %*LANG<Q> ).tweak(:qq).unbalanced('"'))> '"' }
token p5circumfix:sym«< >» { '<'
<nibble($¢.cursor_fresh( %*LANG<Q> ).tweak(:qq).tweak(:w).balanced('<','>'))> '>' }
token p5quote:sym</ /> {
'/' <nibble( $¢.cursor_fresh( %*LANG<Regex> ).unbalanced("/") )> [ '/' || <.panic: "Unable to parse regex; couldn't find final '/'"> ]
<p5rx_mods>?
}
# handle composite forms like qww
token quote:qq {
'qq'
[
| » <.ws> <quibble($¢.cursor_fresh( %*LANG<Q> ).tweak(:qq))>
]
}
token quote:q {
'q'
[
| » <.ws> <quibble($¢.cursor_fresh( %*LANG<Q> ).tweak(:q))>
]
}
token quote:qr {
<sym> » <!before '('>
<quibble( $¢.cursor_fresh( %*LANG<Regex> ) )>
<p5rx_mods>
}
token quote:m {
<sym> » <!before '('>
<quibble( $¢.cursor_fresh( %*LANG<Regex> ) )>
<p5rx_mods>
}
token quote:s {
<sym> » <!before '('>
<pat=sibble( $¢.cursor_fresh( %*LANG<Regex> ), $¢.cursor_fresh( %*LANG<Q> ).tweak(:qq))>
<p5rx_mods>
}
token quote:tr {
<sym> » <!before '('> <pat=tribble( $¢.cursor_fresh( %*LANG<Q> ).tweak(:q))>
<p5tr_mods>
}
token p5rx_mods {
<!after \s>
(< i g s m x c e >+)
}
token p5tr_mods {
(< c d s ] >+)
}
# assumes whitespace is eaten already
method peek_delimiters {
my $pos = self.pos;
my $startpos = $pos;
my $char = substr($*ORIG,$pos++,1);
if $char ~~ /^\s$/ {
self.panic("Whitespace character is not allowed as delimiter"); # "can't happen"
}
elsif $char ~~ /^\w$/ {
self.panic("Alphanumeric character is not allowed as delimiter");
}
elsif %STD::close2open{$char} {
self.panic("Use of a closing delimiter for an opener is reserved");
}
my $rightbrack = %STD::open2close{$char};
if not defined $rightbrack {
return $char, $char;
}
while substr($*ORIG,$pos,1) eq $char {
$pos++;
}
my $len = $pos - $startpos;
my $start = $char x $len;
my $stop = $rightbrack x $len;
return $start, $stop;
}
role startstop[$start,$stop] {
token starter { $start }
token stopper { $stop }
} # end role
role stop[$stop] {
token starter { <!> }
token stopper { $stop }
} # end role
role unitstop[$stop] {
token unitstopper { $stop }
} # end role
token unitstopper { $ }
method balanced ($start,$stop) { self.mixin( ::startstop[$start,$stop] ); }
method unbalanced ($stop) { self.mixin( ::stop[$stop] ); }
method unitstop ($stop) { self.mixin( ::unitstop[$stop] ); }
token charname {
[
| <radint>
| <[a..z A..Z]><-[ \] , \# ]>*?<[a..z A..Z ) ]> <?before \s*<[ \] , \# ]>>
] || <.panic: "Unrecognized character name">
}
token charnames { [<.ws><charname><.ws>] +% ',' }
token charspec {
[
| :dba('character name') '[' ~ ']' <charnames>
| \d+
| <[ ?..Z \\.._ ]>
| <?> <.panic: "Unrecognized \\c character">
]
}
method truly ($bool,$opt) {
return self if $bool;
self.panic("Cannot negate $opt adverb");
}
grammar Q is STD {
role b1 {
token p5escape:sym<\\> { <sym> <item=p5backslash> }
token p5backslash:qq { <?before 'q'> { $<quote> = $¢.cursor_fresh(%*LANG<MAIN>).quote(); } }
token p5backslash:sym<\\> { <text=sym> }
token p5backslash:stopper { <text=stopper> }
token p5backslash:a { <sym> }
token p5backslash:b { <sym> }
token p5backslash:c { <sym> <charspec> }
token p5backslash:e { <sym> }
token p5backslash:f { <sym> }
token p5backslash:n { <sym> }
token p5backslash:o { :dba('octal character') <sym> [ <octint> | '[' ~ ']' <octints> ] }
token p5backslash:r { <sym> }
token p5backslash:t { <sym> }
token p5backslash:x { :dba('hex character') <sym> [ <hexint> | '[' ~ ']' <hexints> ] }
token p5backslash:sym<0> { <sym> }
} # end role
role b0 {
token p5escape:sym<\\> { <!> }
} # end role
role c1 {
token p5escape:sym<{ }> { <?before '{'> [ :lang(%*LANG<MAIN>) <block> ] }
} # end role
role c0 {
token p5escape:sym<{ }> { <!> }
} # end role
role s1 {
token p5escape:sym<$> {
:my $*QSIGIL ::= '$';
<?before '$'>
[ :lang(%*LANG<MAIN>) <EXPR(item %methodcall)> ] || <.panic: "Non-variable \$ must be backslashed">
}
} # end role
role s0 {
token p5escape:sym<$> { <!> }
} # end role
role a1 {
token p5escape:sym<@> {
:my $*QSIGIL ::= '@';
<?before '@'>
[ :lang(%*LANG<MAIN>) <EXPR(item %methodcall)> | <!> ] # trap ABORTBRANCH from variable's ::
}
} # end role
role a0 {
token p5escape:sym<@> { <!> }
} # end role
role h1 {
token p5escape:sym<%> {
:my $*QSIGIL ::= '%';
<?before '%'>
[ :lang(%*LANG<MAIN>) <EXPR(item %methodcall)> | <!> ]
}
} # end role
role h0 {
token p5escape:sym<%> { <!> }
} # end role
role f1 {
token p5escape:sym<&> {
:my $*QSIGIL ::= '&';
<?before '&'>
[ :lang(%*LANG<MAIN>) <EXPR(item %methodcall)> | <!> ]
}
} # end role
role f0 {
token p5escape:sym<&> { <!> }
} # end role
role w1 {
method postprocess ($s) { $s.words }
} # end role
role w0 {
method postprocess ($s) { $s }
} # end role
role ww1 {
method postprocess ($s) { $s.words }
} # end role
role ww0 {
method postprocess ($s) { $s }
} # end role
role x1 {
method postprocess ($s) { $s.run }
} # end role
role x0 {
method postprocess ($s) { $s }
} # end role
role q {
token stopper { \' }
token p5escape:sym<\\> { <sym> <item=p5backslash> }
token p5backslash:qq { <?before 'q'> { $<quote> = $¢.cursor_fresh(%*LANG<MAIN>).quote(); } }
token p5backslash:sym<\\> { <text=sym> }
token p5backslash:stopper { <text=stopper> }
# in single quotes, keep backslash on random character by default
token p5backslash:misc { {} (.) { $<text> = "\\" ~ $0.Str; } }
# begin tweaks (DO NOT ERASE)
multi method tweak (:single(:$q)!) { self.panic("Too late for :q") }
multi method tweak (:double(:$qq)!) { self.panic("Too late for :qq") }
# end tweaks (DO NOT ERASE)
} # end role
role qq does b1 does c1 does s1 does a1 does h1 does f1 {
token stopper { \" }
# in double quotes, omit backslash on random \W backslash by default
token p5backslash:misc { {} [ (\W) { $<text> = $0.Str; } | $<x>=(\w) <.panic("Unrecognized backslash sequence: '\\" ~ $<x>.Str ~ "'")> ] }
# begin tweaks (DO NOT ERASE)
multi method tweak (:single(:$q)!) { self.panic("Too late for :q") }
multi method tweak (:double(:$qq)!) { self.panic("Too late for :qq") }
# end tweaks (DO NOT ERASE)
} # end role
role p5 {
# begin tweaks (DO NOT ERASE)
multi method tweak (:$g!) { self }
multi method tweak (:$i!) { self }
multi method tweak (:$m!) { self }
multi method tweak (:$s!) { self }
multi method tweak (:$x!) { self }
multi method tweak (:$p!) { self }
multi method tweak (:$c!) { self }
# end tweaks (DO NOT ERASE)
} # end role
# begin tweaks (DO NOT ERASE)
multi method tweak (:single(:$q)!) { self.truly($q,':q'); self.mixin( ::q ); }
multi method tweak (:double(:$qq)!) { self.truly($qq, ':qq'); self.mixin( ::qq ); }
multi method tweak (:backslash(:$b)!) { self.mixin($b ?? ::b1 !! ::b0) }
multi method tweak (:scalar(:$s)!) { self.mixin($s ?? ::s1 !! ::s0) }
multi method tweak (:array(:$a)!) { self.mixin($a ?? ::a1 !! ::a0) }
multi method tweak (:hash(:$h)!) { self.mixin($h ?? ::h1 !! ::h0) }
multi method tweak (:function(:$f)!) { self.mixin($f ?? ::f1 !! ::f0) }
multi method tweak (:closure(:$c)!) { self.mixin($c ?? ::c1 !! ::c0) }
multi method tweak (:exec(:$x)!) { self.mixin($x ?? ::x1 !! ::x0) }
multi method tweak (:words(:$w)!) { self.mixin($w ?? ::w1 !! ::w0) }
multi method tweak (:quotewords(:$ww)!) { self.mixin($ww ?? ::ww1 !! ::ww0) }
multi method tweak (:heredoc(:$to)!) { self.truly($to, ':to'); self.cursor_herelang; }
multi method tweak (:$regex!) {
return %*LANG<Regex>;
}
multi method tweak (:$trans!) {
return %*LANG<Trans>;
}
multi method tweak (*%x) {
my @k = keys(%x);
self.panic("Unrecognized quote modifier: " ~ join('',@k));
}
# end tweaks (DO NOT ERASE)
} # end grammar
###########################
# Captures and Signatures #
###########################
token capterm {
'\\'
[
| '(' <capture>? ')'
| <?before \S> <termish>
]
}
rule capture {
:my $*INVOCANT_OK = 1;
<EXPR>
}
rule param_sep { [','|':'|';'|';;'] }
token signature ($lexsig = 0) {
# XXX incorrectly scopes &infix:<x> parameters to outside following block
:my $*IN_DECL = 1;
:my $*zone = 'posreq';
:my $startpos = self.pos;
<.ws>
[
| <?before '-->' | ')' | ']' | '{' | ':'\s >
| [ <parameter> || <.panic: "Malformed parameter"> ]
] +% <param_sep>
<.ws>
{ $*IN_DECL = 0; }
[ '-->' <.ws> <typename> ]?
{{
$*LEFTSIGIL = '@';
if $lexsig {
$*CURLEX.<$?SIGNATURE> ~= '(' ~ substr($*ORIG, $startpos, $¢.pos - $startpos) ~ ')';
$*CURLEX.<!NEEDSIG>:delete;
}
}}
}
token type_constraint {
share/P6STD/STD_P5.pm6 view on Meta::CPAN
token p5terminator:sym<}>
{ '}' <O(|%terminator)> }
token p5terminator:sym<:>
{ ':' <?{ $*GOAL eq ':' }> <O(|%terminator)> }
regex infixstopper {
:dba('infix stopper')
[
| <?before <stopper> >
| <?before ':' > <?{ $*GOAL eq ':' }>
| <?{ $*GOAL eq 'endargs' and @*MEMOS[$¢.pos]<endargs> }>
]
}
# overridden in subgrammars
token stopper { <!> }
# hopefully we can include these tokens in any outer LTM matcher
regex stdstopper {
:temp @*STUB = return self if @*MEMOS[self.pos]<endstmt> :exists;
:dba('standard stopper')
[
| <?terminator>
| <?unitstopper>
| $ # unlikely, check last (normal LTM behavior)
]
{ @*MEMOS[$¢.pos]<endstmt> ||= 1; }
}
## vim: expandtab sw=4 ft=perl6
grammar Regex is STD {
# begin tweaks (DO NOT ERASE)
multi method tweak (:global(:$g)!) { self }
multi method tweak (:ignorecase(:$i)!) { self }
# end tweaks (DO NOT ERASE)
token category:p5metachar { <sym> }
proto token p5metachar { <...> }
token category:p5backslash { <sym> }
proto token p5backslash { <...> }
token category:p5assertion { <sym> }
proto token p5assertion { <...> }
token category:p5quantifier { <sym> }
proto token p5quantifier { <...> }
token category:p5mod_internal { <sym> }
proto token p5mod_internal { <...> }
proto token p5regex_infix { <...> }
# suppress fancy end-of-line checking
token codeblock {
:my $*GOAL ::= '}';
'{' :: [ :lang($¢.cursor_fresh(%*LANG<MAIN>)) <statementlist> ]
[ '}' || <.panic: "Unable to parse statement list; couldn't find right brace"> ]
}
token ws {
<?{ $*RX<s> }>
|| [ <?before \s | '#'> <.nextsame> ]? # still get all the pod goodness, hopefully
}
rule nibbler {
:temp $*ignorecase;
<EXPR>
}
token termish {
<.ws> # XXX assuming old /x here?
<term=quant_atom_list>
}
token quant_atom_list {
<quantified_atom>+
}
token infixish {
<!infixstopper>
<!stdstopper>
<regex_infix=p5regex_infix>
{
$<O> = $<regex_infix><O>;
$<sym> = $<regex_infix><sym>;
}
}
regex infixstopper {
:dba('infix stopper')
<?before <stopper> >
}
token p5regex_infix:sym<|> { <sym> <O(|%tight_or)> }
token quantified_atom {
<!stopper>
<!p5regex_infix>
<atom>
[ <.ws> <quantifier=p5quantifier>
# <?{ $<atom>.max_width }>
# || <.panic: "Cannot quantify zero-width atom">
]?
<.ws>
}
token atom {
[
| \w
| <metachar=p5metachar>
| '\\' :: .
]
}
# sequence stoppers
token p5metachar:sym<|> { '|' :: <fail> }
token p5metachar:sym<)> { ')' :: <fail> }
token p5metachar:quant { <quantifier=p5quantifier> <.panic: "quantifier quantifies nothing"> }
# "normal" metachars
token p5metachar:sym<[ ]> {
<before '['> <quibble($¢.cursor_fresh( %*LANG<Q> ).tweak(:q))> # XXX parse as q[] for now
}
token p5metachar:sym«(? )» {
'(?' {} <assertion=p5assertion>
[ ')' || <.panic: "Perl 5 regex assertion not terminated by parenthesis"> ]
}
token p5metachar:sym<( )> {
'(' {} [:lang(self.unbalanced(')')) <nibbler>]?
[ ')' || <.panic: "Unable to parse Perl 5 regex; couldn't find right parenthesis"> ]
{ $/<sym> := <( )> }
}
token p5metachar:sym<\\> { <sym> <backslash=p5backslash> }
token p5metachar:sym<.> { <sym> }
token p5metachar:sym<^> { <sym> }
token p5metachar:sym<$> {
'$' <?before \W | $>
}
token p5metachar:var {
<?before <sigil=p5sigil>\w>
<.panic: "Cannot interpolate variable in Perl 5 regex">
}
token p5backslash:A { <sym> }
token p5backslash:a { <sym> }
token p5backslash:b { :i <sym> }
token p5backslash:c { :i <sym>
<[ ?.._ ]> || <.panic: "Unrecognized \\c character">
}
token p5backslash:d { :i <sym> }
token p5backslash:e { :i <sym> }
token p5backslash:f { :i <sym> }
token p5backslash:h { :i <sym> }
token p5backslash:l { :i <sym> }
token p5backslash:n { :i <sym> }
token p5backslash:o { :dba('octal character') '0' [ <octint> | '{' ~ '}' <octints> ] }
token p5backslash:p { :i <sym> '{' <[\w:]>+ '}' }
token p5backslash:Q { <sym> }
token p5backslash:r { :i <sym> }
token p5backslash:s { :i <sym> }
token p5backslash:t { :i <sym> }
token p5backslash:u { :i <sym> }
token p5backslash:v { :i <sym> }
token p5backslash:w { :i <sym> }
token p5backslash:x { :i :dba('hex character') <sym> [ <hexint> | '{' ~ '}' <hexints> ] }
token p5backslash:z { :i <sym> }
token p5backslash:misc { $<litchar>=(\W) | $<number>=(\d+) }
token p5backslash:oops { <.panic: "Unrecognized Perl 5 regex backslash sequence"> }
token p5assertion:sym<?> { <sym> <codeblock> }
token p5assertion:sym<{ }> { <codeblock> }
token p5assertion:sym«<» { <sym> <?before '=' | '!'> <assertion=p5assertion> }
token p5assertion:sym<=> { <sym> [ <?before ')'> | <rx> ] }
token p5assertion:sym<!> { <sym> [ <?before ')'> | <rx> ] }
token p5assertion:sym«>» { <sym> <rx> }
token rx {
( run in 2.192 seconds using v1.01-cache-2.11-cpan-75ffa21a3d4 )