diff --git a/src/Regex/P6Regex/Actions.pm b/src/Regex/P6Regex/Actions.pm index a94bae8..cc6bcc6 100644 --- a/src/Regex/P6Regex/Actions.pm +++ b/src/Regex/P6Regex/Actions.pm @@ -67,10 +67,14 @@ method termish($/) { method quantified_atom($/) { my $past := $.ast; if $ { - if !$past { $/.panic("Can't quantify zero-width atom"); } - my $qast := $[0].ast; - $qast.unshift($past); - $past := $qast; + if !$past { $/.panic("Can't quantify zero-width atom"); } + my $qast := $[0].ast; + $qast.unshift($past); + $past := $qast; + } + elsif $[0] { backmod($past, $[0]); } + if $past && !$past.backtrack && @MODIFIERS[0] { + $past.backtrack('r'); } make $past; } @@ -86,47 +90,35 @@ method atom($/) { } method quantifier:sym<*>($/) { - make $.ast; + my $past := PAST::Regex.new( :pasttype('quant') ); + make backmod($past, $); } method quantifier:sym<+>($/) { - my $past := $.ast; - $past.min(1); - make $past; + my $past := PAST::Regex.new( :pasttype('quant'), :min(1) ); + make backmod($past, $); } method quantifier:sym($/) { - my $past := $.ast; - $past.min(0); - $past.max(1); + my $past := PAST::Regex.new( :pasttype('quant'), :min(0), :max(1) ); + make backmod($past, $); make $past; } method quantifier:sym<**>($/) { - my $past := $.ast; + my $past; if $ { - $past.min(1); - $past.sep($.ast); + $past := PAST::Regex.new( :pasttype('quant'), :min(1), + :sep( $.ast ) ); } else { - $past.min(+$); + $past := PAST::Regex.new( :pasttype('quant'), :min(+$) ); if ! $ { $past.max(+$); } elsif $[0] ne '*' { $past.max(+$[0]); } } - make $past; + make backmod($past, $); } -method quantmod($/) { - my $past := PAST::Regex.new( :pasttype('quant') ); - my $str := ~$/; - if $str eq ':' { $past.backtrack('r'); } - elsif $str eq ':?' or $str eq '?' { $past.backtrack('f') } - elsif $str eq ':!' or $str eq '!' { $past.backtrack('g') } - elsif @MODIFIERS[0] { $past.backtrack('r') } - make $past; -} - - method metachar:sym($/) { my $past := @MODIFIERS[0] ?? PAST::Regex.new( 'ws', :pasttype('subrule'), @@ -381,6 +373,12 @@ method cclass_elem($/) { make $past; } +method mod_internal($/) { + my %mods := @MODIFIERS[0]; + my $n := $[0] gt '' ?? +$[0] !! 1; + %mods{ ~$ } := $n; + make 0; +} sub capnames($ast, $count) { my %capnames; @@ -431,9 +429,9 @@ sub capnames($ast, $count) { %capnames; } -method mod_internal($/) { - my %mods := @MODIFIERS[0]; - my $n := $[0] gt '' ?? +$[0] !! 1; - %mods{ ~$ } := $n; - make 0; +sub backmod($ast, $backmod) { + if $backmod eq ':' { $ast.backtrack('r') } + elsif $backmod eq ':?' || $backmod eq '?' { $ast.backtrack('f') } + elsif $backmod eq ':!' || $backmod eq '!' { $ast.backtrack('g') } + $ast; } diff --git a/src/Regex/P6Regex/Grammar.pm b/src/Regex/P6Regex/Grammar.pm index 09c489e..98e7cbb 100644 --- a/src/Regex/P6Regex/Grammar.pm +++ b/src/Regex/P6Regex/Grammar.pm @@ -26,7 +26,7 @@ grammar Regex::P6Regex::Grammar is PCT::Grammar; } token quantified_atom { - [ <.ws> ]? + [ <.ws> [ | ] ]? {*} } @@ -40,11 +40,11 @@ grammar Regex::P6Regex::Grammar is PCT::Grammar; } # proto token quantifier { <...> } - token quantifier:sym<*> { $=['*'] {*} } - token quantifier:sym<+> { $=['+'] {*} } - token quantifier:sym { $=['?'] {*} } + token quantifier:sym<*> { $=['*'] {*} } + token quantifier:sym<+> { $=['+'] {*} } + token quantifier:sym { $=['?'] {*} } token quantifier:sym<**> { - $=['**'] \s* \s* + $=['**'] \s* \s* [ || $=[\d+] [ '..' $=[\d+|'*'] ]? || @@ -52,7 +52,7 @@ grammar Regex::P6Regex::Grammar is PCT::Grammar; {*} } - token quantmod { ':'? [ '?' | '!' | '+' ]? {*} } + token backmod { ':'? [ '?' | '!' | ] } # proto token metachar { <...> } token metachar:sym { <.normspace> {*} }