Skip to content

Instantly share code, notes, and snippets.

@FROGGS
Created February 19, 2013 09:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save FROGGS/4984189 to your computer and use it in GitHub Desktop.
Save FROGGS/4984189 to your computer and use it in GitHub Desktop.
Allow / [ a || b || @A ] / to do sequential matching instead of LTM.
diff --git a/src/NQP/Actions.pm b/src/NQP/Actions.pm
index 0d3111e..6fbeccb 100644
--- a/src/NQP/Actions.pm
+++ b/src/NQP/Actions.pm
@@ -1665,7 +1665,8 @@ class NQP::RegexActions is QRegex::P6Regex::Actions {
method metachar:sym<nqpvar>($/) {
make QAST::Regex.new( QAST::Node.new(
QAST::SVal.new( :value('!INTERPOLATE') ),
- $<var>.ast),
+ $<var>.ast,
+ QAST::IVal.new( :value($*SEQ ?? 1 !! 0) ) ), # sequential matching
:rxtype<subrule>, :subtype<method>, :node($/));
}
diff --git a/src/QRegex/Cursor.nqp b/src/QRegex/Cursor.nqp
index 1a93813..0b0a605 100755
--- a/src/QRegex/Cursor.nqp
+++ b/src/QRegex/Cursor.nqp
@@ -681,7 +681,7 @@ class NQPCursor does NQPCursorRole {
nqp::findmethod($cur, $rule)($cur).MATCH()
}
- method !INTERPOLATE($var) {
+ method !INTERPOLATE($var, $s = 0) {
if nqp::islist($var) {
my int $maxlen := -1;
my $cur := self.'!cursor_start_cur'();
@@ -702,6 +702,7 @@ class NQPCursor does NQPCursorRole {
$maxlen := $len if $len > $maxlen && $pos + $len <= $eos
&& nqp::substr($tgt, $pos, $len) eq $_;
}
+ last if $s && $maxlen > -1;
}
$cur.'!cursor_pass'($pos + $maxlen, '') if $maxlen >= 0;
return $cur;
diff --git a/src/QRegex/P6Regex/Grammar.nqp b/src/QRegex/P6Regex/Grammar.nqp
index 9ae0b89..91d0a08 100755
--- a/src/QRegex/P6Regex/Grammar.nqp
+++ b/src/QRegex/P6Regex/Grammar.nqp
@@ -81,10 +81,16 @@ grammar QRegex::P6Regex::Grammar is HLL::Grammar {
token nibbler {
:my $OLDRX := nqp::getlexdyn('%*RX');
:my %*RX;
+ :my $*SEQ := 0;
{
for $OLDRX { %*RX{$_.key} := $_.value; }
}
- [ <.ws> ['||'|'|'|'&&'|'&'] ]?
+ [ <.ws> [
+ | '||' { $*SEQ := 1; }
+ | '|'
+ | '&&'
+ | '&'
+ ] ]?
<termaltseq> <.ws>
[
|| <?infixstopper>
@@ -107,22 +113,22 @@ grammar QRegex::P6Regex::Grammar is HLL::Grammar {
token termaltseq {
<termconjseq>
- [ '||' [ <termconjseq> || <.throw_null_pattern> ] ]*
+ [ '||' [ { $*SEQ := 1; } <termconjseq> || <.throw_null_pattern> ] ]*
}
token termconjseq {
<termalt>
- [ '&&' [ <termalt> || <.throw_null_pattern> ] ]*
+ [ '&&' [ { $*SEQ := 0; } <termalt> || <.throw_null_pattern> ] ]*
}
token termalt {
<termconj>
- [ '|' <![|]> [ <termconj> || <.throw_null_pattern> ] ]*
+ [ '|' <![|]> [ { $*SEQ := 0; } <termconj> || <.throw_null_pattern> ] ]*
}
token termconj {
<termish>
- [ '&' <![&]> [ <termish> || <.throw_null_pattern> ] ]*
+ [ '&' <![&]> [ { $*SEQ := 0; } <termish> || <.throw_null_pattern> ] ]*
}
token termish {
diff --git a/src/Perl6/Actions.pm b/src/Perl6/Actions.pm
index b31c6da..decaaae 100644
--- a/src/Perl6/Actions.pm
+++ b/src/Perl6/Actions.pm
@@ -5880,7 +5880,8 @@ class Perl6::RegexActions is QRegex::P6Regex::Actions does STDActions {
make QAST::Regex.new( QAST::Node.new(
QAST::SVal.new( :value('INTERPOLATE') ),
$<var>.ast,
- QAST::IVal.new( :value(%*RX<i> ?? 1 !! 0) ) ),
+ QAST::IVal.new( :value(%*RX<i> ?? 1 !! 0) ),
+ QAST::IVal.new( :value($*SEQ ?? 1 !! 0) ) ), # sequential matching
:rxtype<subrule>, :subtype<method>, :node($/));
}
diff --git a/src/core/Cursor.pm b/src/core/Cursor.pm
index 537b182..0f0c624 100644
--- a/src/core/Cursor.pm
+++ b/src/core/Cursor.pm
@@ -45,10 +45,34 @@ my class Cursor does NQPCursorRole {
$match;
}
- method INTERPOLATE($var, $i = 0) {
- nqp::isconcrete($var) ??
- ($var ~~ Callable ?? $var(self) !! self."!LITERAL"(nqp::unbox_s($var.Str), $i)) !!
+ method INTERPOLATE($var, $i = 0, $s = 0) {
+ if nqp::isconcrete($var) {
+ if nqp::istype($var, Positional) # for array-likes
+ || nqp::istype($var, Capture) { # for references to arrays, dunno if they should be treated as positionals directly
+ my $maxlen := -1;
+ my $cur := self.'!cursor_start_cur'();
+ my $pos := nqp::getattr_i($cur, $?CLASS, '$!from');
+ my $tgt := $cur.target;
+ my $eos := nqp::chars($tgt);
+ for $var.list {
+ my $topic := $_ ~~ Callable ?? $_(self) !! $_;
+ my $len := nqp::chars($topic);
+ if $len > $maxlen && $pos + $len <= $eos
+ && nqp::substr($tgt, $pos, $len) eq $topic {
+ $maxlen := $len;
+ last if $s; # stop here for sequential alternation
+ }
+ }
+ $cur.'!cursor_pass'($pos + $maxlen, '') if $maxlen >= 0;
+ $cur
+ }
+ else {
+ $var ~~ Callable ?? $var(self) !! self."!LITERAL"(nqp::unbox_s($var.Str), $i)
+ }
+ }
+ else {
self."!cursor_start_cur"()
+ }
}
method OTHERGRAMMAR($grammar, $name, |) {
@FROGGS
Copy link
Author

FROGGS commented Feb 19, 2013

Tests:

NQP: Result: PASS

Rakudo:
t/spec/S05-interpolation/regex-in-variable.rakudo (Wstat: 0 Tests: 33 Failed: 0)
TODO passed: 24
t/spec/S05-metasyntax/litvar.rakudo (Wstat: 0 Tests: 33 Failed: 0)
TODO passed: 24-26, 28-29
t/spec/S05-metasyntax/sequential-alternation.rakudo (Wstat: 0 Tests: 10 Failed: 0)
TODO passed: 7-10
Files=723, Tests=26819, 717 wallclock secs ( 9.54 usr 1.42 sys + 2155.61 cusr 146.80 csys = 2313.37 CPU)
Result: PASS

@zhuomingliang
Copy link

I'm sorry, but why use "$_SEQ ?? 1 !! 0", instead of "$_SEQ"?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment