1
1
class QRegex::P6Regex::Actions is HLL::Actions {
2
2
method TOP ($/ ) {
3
- make qbuildsub($ < nibbler > . ast, : anon(1 ), : addself(1 ));
3
+ make self . qbuildsub($ < nibbler > . ast, : anon(1 ), : addself(1 ));
4
4
}
5
5
6
6
method nibbler ($/ ) { make $ < termaltseq > . ast }
@@ -136,7 +136,7 @@ class QRegex::P6Regex::Actions is HLL::Actions {
136
136
}
137
137
138
138
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 )));
140
140
my $ qast := QAST ::Regex. new ( $ subpast , $ < nibbler > . ast, : rxtype(' subrule' ),
141
141
: subtype(' capture' ), : node($/ ) );
142
142
make $ qast ;
@@ -401,8 +401,8 @@ class QRegex::P6Regex::Actions is HLL::Actions {
401
401
}
402
402
elsif $ < nibbler > {
403
403
$ 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 )));
406
406
}
407
407
}
408
408
make $ qast ;
@@ -535,46 +535,37 @@ class QRegex::P6Regex::Actions is HLL::Actions {
535
535
elsif $ backmod eq ' :!' || $ backmod eq ' !' { $ ast . backtrack(' g' ) }
536
536
$ ast ;
537
537
}
538
+
539
+ our sub qbuildsub (* @ pos , * % named ) {
540
+ QRegex::P6Regex::Actions. qbuildsub(| @ pos , | % named )
541
+ }
538
542
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 );
555
547
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' ) ));
560
550
}
561
- qalt_nfas($ qast , $ blockid , $ initpast );
562
-
563
551
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' )));
565
553
$ block . symbol(' $¢' , : scope<lexical >);
566
554
}
567
555
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
+
568
560
$ block <orig_qast > := $ qast ;
569
-
570
561
$ qast := QAST ::Regex. new ( : rxtype<concat >,
571
562
QAST ::Regex. new ( : rxtype<scan > ),
572
563
$ qast ,
573
564
($ anon ??
574
565
QAST ::Regex. new ( : rxtype<pass > ) !!
575
566
QAST ::Regex. new ( : rxtype<pass >, : name(% * RX <name >) )));
576
- $ block . push ($ initpast );
577
567
$ block . push ($ qast );
568
+
578
569
$ block ;
579
570
}
580
571
@@ -628,23 +619,22 @@ class QRegex::P6Regex::Actions is HLL::Actions {
628
619
% capnames ;
629
620
}
630
621
631
- sub qalt_nfas ( $ ast , $ subid , $ initpast ) {
622
+ method alt_nfas ( $ code_obj , $ block , $ ast ) {
632
623
my $ rxtype := $ ast . rxtype;
633
624
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 ;
636
626
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($ _ ));
639
629
}
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 );
642
632
}
643
633
elsif $ rxtype eq ' subcapture' || $ rxtype eq ' quant' {
644
- qalt_nfas( $ ast [ 0 ] , $ subid , $ initpast )
634
+ self . alt_nfas( $ code_obj , $ block , $ ast [ 0 ] )
645
635
}
646
636
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 , $ _ ) }
648
638
}
649
639
}
650
640
@@ -669,4 +659,42 @@ class QRegex::P6Regex::Actions is HLL::Actions {
669
659
}
670
660
$ qast
671
661
}
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
+ }
672
700
}
0 commit comments