Skip to content

Commit 5c9e6eb

Browse files
committed
Factor out NFA and capture storage.
1 parent 98cc1cc commit 5c9e6eb

File tree

1 file changed

+66
-38
lines changed

1 file changed

+66
-38
lines changed

src/QRegex/P6Regex/Actions.nqp

Lines changed: 66 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
class QRegex::P6Regex::Actions is HLL::Actions {
22
method TOP($/) {
3-
make qbuildsub($<nibbler>.ast, :anon(1), :addself(1));
3+
make self.qbuildsub($<nibbler>.ast, :anon(1), :addself(1));
44
}
55

66
method nibbler($/) { make $<termaltseq>.ast }
@@ -136,7 +136,7 @@ class QRegex::P6Regex::Actions is HLL::Actions {
136136
}
137137

138138
method metachar:sym<( )>($/) {
139-
my $subpast := QAST::Node.new(qbuildsub($<nibbler>.ast, :anon(1), :addself(1)));
139+
my $subpast := QAST::Node.new(self.qbuildsub($<nibbler>.ast, :anon(1), :addself(1)));
140140
my $qast := QAST::Regex.new( $subpast, $<nibbler>.ast, :rxtype('subrule'),
141141
:subtype('capture'), :node($/) );
142142
make $qast;
@@ -401,8 +401,8 @@ class QRegex::P6Regex::Actions is HLL::Actions {
401401
}
402402
elsif $<nibbler> {
403403
$name eq 'after' ??
404-
$qast[0].push(qbuildsub(self.flip_ast($<nibbler>[0].ast), :anon(1), :addself(1))) !!
405-
$qast[0].push(qbuildsub($<nibbler>[0].ast, :anon(1), :addself(1)));
404+
$qast[0].push(self.qbuildsub(self.flip_ast($<nibbler>[0].ast), :anon(1), :addself(1))) !!
405+
$qast[0].push(self.qbuildsub($<nibbler>[0].ast, :anon(1), :addself(1)));
406406
}
407407
}
408408
make $qast;
@@ -535,46 +535,37 @@ class QRegex::P6Regex::Actions is HLL::Actions {
535535
elsif $backmod eq ':!' || $backmod eq '!' { $ast.backtrack('g') }
536536
$ast;
537537
}
538+
539+
our sub qbuildsub(*@pos, *%named) {
540+
QRegex::P6Regex::Actions.qbuildsub(|@pos, |%named)
541+
}
538542

539-
our sub qbuildsub($qast, $block = QAST::Block.new(), :$anon, :$addself) {
540-
my $blockid := $block.cuid;
541-
my $hashpast := QAST::Op.new( :op<hash> );
542-
for capnames($qast, 0) {
543-
if $_.key gt '' {
544-
$hashpast.push(QAST::SVal.new( :value($_.key) ));
545-
$hashpast.push(QAST::IVal.new( :value(
546-
nqp::iscclass(pir::const::CCLASS_NUMERIC, $_.key, 0) + ($_.value > 1) * 2) ));
547-
}
548-
}
549-
my $initpast := QAST::Stmts.new();
550-
if $addself {
551-
$initpast.push(QAST::Var.new( :name('self'), :scope('local'), :decl('param') ));
552-
}
553-
my $capblock := QAST::BlockMemo.new( :name($blockid ~ '_caps'), $hashpast );
554-
$initpast.push(QAST::Stmt.new($capblock));
543+
method qbuildsub($qast, $block = QAST::Block.new(), :$anon, :$addself, *%rest) {
544+
my $code_obj := nqp::existskey(%rest, 'code_obj')
545+
?? %rest<code_obj>
546+
!! self.create_regex_code_object($block);
555547

556-
my $nfapast := QRegex::NFA.new.addnode($qast).qast;
557-
if $nfapast {
558-
my $nfablock := QAST::BlockMemo.new( :name($blockid ~ '_nfa'), $nfapast);
559-
$initpast.push(QAST::Stmt.new($nfablock));
548+
if $addself {
549+
$block.push(QAST::Var.new( :name('self'), :scope('local'), :decl('param') ));
560550
}
561-
qalt_nfas($qast, $blockid, $initpast);
562-
563551
unless $block.symbol('') {
564-
$initpast.push(QAST::Var.new(:name<>, :scope<lexical>, :decl('var')));
552+
$block.push(QAST::Var.new(:name<>, :scope<lexical>, :decl('var')));
565553
$block.symbol('', :scope<lexical>);
566554
}
567555

556+
self.store_regex_caps($code_obj, $block, capnames($qast, 0));
557+
self.store_regex_nfa($code_obj, $block, QRegex::NFA.new.addnode($qast));
558+
self.alt_nfas($code_obj, $block, $qast);
559+
568560
$block<orig_qast> := $qast;
569-
570561
$qast := QAST::Regex.new( :rxtype<concat>,
571562
QAST::Regex.new( :rxtype<scan> ),
572563
$qast,
573564
($anon ??
574565
QAST::Regex.new( :rxtype<pass> ) !!
575566
QAST::Regex.new( :rxtype<pass>, :name(%*RX<name>) )));
576-
$block.push($initpast);
577567
$block.push($qast);
568+
578569
$block;
579570
}
580571

@@ -628,23 +619,22 @@ class QRegex::P6Regex::Actions is HLL::Actions {
628619
%capnames;
629620
}
630621

631-
sub qalt_nfas($ast, $subid, $initpast) {
622+
method alt_nfas($code_obj, $block, $ast) {
632623
my $rxtype := $ast.rxtype;
633624
if $rxtype eq 'alt' {
634-
my $nfapast := QAST::Op.new( :op('list') );
635-
$ast.name(QAST::Node.unique('alt_nfa_') ~ '_' ~ ~nqp::time_n());
625+
my @alternatives;
636626
for $ast.list {
637-
qalt_nfas($_, $subid, $initpast);
638-
$nfapast.push(QRegex::NFA.new.addnode($_).qast(:non_empty));
627+
self.alt_nfas($code_obj, $block, $_);
628+
nqp::push(@alternatives, QRegex::NFA.new.addnode($_));
639629
}
640-
my $nfablock := QAST::BlockMemo.new( :name($subid ~ '_' ~ $ast.name), $nfapast);
641-
$initpast.push(QAST::Stmt.new($nfablock));
630+
$ast.name(QAST::Node.unique('alt_nfa_') ~ '_' ~ ~nqp::time_n());
631+
self.store_regex_alt_nfa($code_obj, $block, $ast.name, @alternatives);
642632
}
643633
elsif $rxtype eq 'subcapture' || $rxtype eq 'quant' {
644-
qalt_nfas($ast[0], $subid, $initpast)
634+
self.alt_nfas($code_obj, $block, $ast[0])
645635
}
646636
elsif $rxtype eq 'concat' || $rxtype eq 'altseq' || $rxtype eq 'conj' || $rxtype eq 'conjseq' {
647-
for $ast.list { qalt_nfas($_, $subid, $initpast) }
637+
for $ast.list { self.alt_nfas($code_obj, $block, $_) }
648638
}
649639
}
650640

@@ -669,4 +659,42 @@ class QRegex::P6Regex::Actions is HLL::Actions {
669659
}
670660
$qast
671661
}
662+
663+
# This is overridden by a compiler that wants to create code objects
664+
# for regexes.
665+
method create_regex_code_object($block) {
666+
}
667+
668+
# Stores the captures info for a regex.
669+
method store_regex_caps($code_obj, $block, %caps) {
670+
my $hashpast := QAST::Op.new( :op<hash> );
671+
for %caps {
672+
if $_.key gt '' {
673+
$hashpast.push(QAST::SVal.new( :value($_.key) ));
674+
$hashpast.push(QAST::IVal.new( :value(
675+
nqp::iscclass(pir::const::CCLASS_NUMERIC, $_.key, 0) + ($_.value > 1) * 2) ));
676+
}
677+
}
678+
my $capblock := QAST::BlockMemo.new( :name($block.cuid ~ '_caps'), $hashpast );
679+
$block.push(QAST::Stmt.new($capblock));
680+
}
681+
682+
# Stores the NFA for a regex.
683+
method store_regex_nfa($code_obj, $block, $nfa) {
684+
my $nfaqast := $nfa.qast;
685+
if $nfaqast {
686+
my $nfablock := QAST::BlockMemo.new( :name($block.cuid ~ '_nfa'), $nfaqast);
687+
$block.push(QAST::Stmt.new($nfablock));
688+
}
689+
}
690+
691+
# Stores the NFA for a regex alternation.
692+
method store_regex_alt_nfa($code_obj, $block, $key, @alternatives) {
693+
my $nfaqast := QAST::Op.new( :op('list') );
694+
for @alternatives {
695+
$nfaqast.push($_.qast(:non_empty));
696+
}
697+
my $nfablock := QAST::BlockMemo.new( :name($block.cuid ~ '_' ~ $key), $nfaqast);
698+
$block.push(QAST::Stmt.new($nfablock));
699+
}
672700
}

0 commit comments

Comments
 (0)