@@ -459,6 +459,105 @@ class RegexCompiler {
459
459
);
460
460
}
461
461
462
+ method dynquant ($ node ) {
463
+ my $ backtrack := $ node . backtrack || ' g' ;
464
+ my $ sep := $ node [2 ];
465
+
466
+ my str $ min := $ * BLOCK . add_tmp;
467
+ my str $ max := $ * BLOCK . add_tmp;
468
+
469
+ my str $ tmp_rep := $ * BLOCK . add_tmp;
470
+
471
+ my str $ skip_entire := self . new_label;
472
+ my str $ sep_label := self . new_label;
473
+ my str $ loop_label := self . new_label;
474
+ my str $ done_label := self . new_label;
475
+
476
+ my @ chunks ;
477
+
478
+ my $ minmax := $ ! compiler . as_js($ node [1 ], : want($ T_OBJ ));
479
+ @ chunks . push ($ minmax );
480
+ @ chunks . push (
481
+ " $ min = { $ minmax . expr} .array[0];\n "
482
+ ~ " $ max = { $ minmax . expr} .array[1];\n " );
483
+
484
+ @ chunks . push (" if ($ min === 0 && $ max === 0) \{ { self . goto($ skip_entire )} \}\n " );
485
+
486
+ my str $ needmark ;
487
+ if $ backtrack eq ' r' {
488
+ $ needmark := ' true' ;
489
+ } else {
490
+ $ needmark := $ * BLOCK . add_tmp;
491
+ @ chunks . push (" $ needmark = $ min > 1 || $ max > 1;\n " );
492
+ }
493
+
494
+ if $ backtrack eq ' f' {
495
+ @ chunks . push (" $ ! rep = 0;\n " );
496
+
497
+ @ chunks . push (
498
+ " if ($ min < 1) \{\n "
499
+ ~ self . mark($ loop_label , $ ! pos , $ ! rep )
500
+ ~ self . goto($ done_label )
501
+ ~ " \}\n "
502
+ );
503
+
504
+ @ chunks . push (self . goto($ sep_label )) if $ sep ;
505
+
506
+ @ chunks . push (self . case($ loop_label ));
507
+
508
+ @ chunks . push (" $ tmp_rep = $ ! rep ;\n " );
509
+
510
+ if $ sep {
511
+ @ chunks . push (self . compile_rx($ sep ));
512
+ @ chunks . push (self . case($ sep_label ));
513
+ }
514
+
515
+ @ chunks . push (self . compile_rx($ node [0 ]));
516
+
517
+ @ chunks . push (" $ ! rep = $ tmp_rep +1;\n " );
518
+
519
+ @ chunks . push (" if ($ min > 1 && $ ! rep < $ min ) \{ { self . goto($ loop_label )} \}\n " );
520
+
521
+
522
+ @ chunks . push (" if ($ max > 1 && $ ! rep > $ max ) \{ { self . goto($ done_label )} \}\n " );
523
+
524
+ @ chunks . push (" if ($ max !== 1) \{ { self . mark($ loop_label , $ ! pos , $ ! rep )} \}\n " );
525
+ @ chunks . push (self . case($ done_label ));
526
+ }
527
+ else {
528
+ @ chunks . push (" if ($ min === 0) \{ { self . mark($ done_label , $ ! pos , 0 )} \} " );
529
+ @ chunks . push (" else if ($ needmark ) \{ { self . mark($ done_label , -1 , 0 )} \}\n " );
530
+
531
+ @ chunks . push (self . case($ loop_label ));
532
+
533
+ @ chunks . push (self . compile_rx($ node [0 ]));
534
+
535
+ @ chunks . push (" if ($ needmark ) \{\n "
536
+ ~ self . peek($ done_label , ' *' , $ ! rep )
537
+ ~ ($ backtrack eq ' r' ?? self . commit($ done_label ) !! ' ' )
538
+ ~ " $ ! rep ++;\n "
539
+ ~ " if ($ max > 1 && $ ! rep >= $ max ) \{ " ~ self . goto($ done_label ) ~ " \}\n "
540
+ ~ " \}\n " );
541
+
542
+
543
+ @ chunks . push (" if ($ max === 1) \{ { self . goto($ done_label )} \} " );
544
+
545
+ @ chunks . push (self . mark($ done_label , $ ! pos , $ ! rep ));
546
+
547
+ @ chunks . push (self . compile_rx($ sep )) if $ sep ;
548
+
549
+ @ chunks . push (self . goto($ loop_label ));
550
+
551
+ @ chunks . push (self . case($ done_label ));
552
+
553
+ @ chunks . push (" if ($ min > 1 && $ ! rep < $ min ) \{ { self . fail } \} " );
554
+ }
555
+
556
+ @ chunks . push (self . case($ skip_entire ));
557
+
558
+ Chunk. new ($ T_VOID , ' ' , @ chunks );
559
+ }
560
+
462
561
method quant ($ node ) {
463
562
my int $ min := $ node . min ;
464
563
my int $ max := $ node . max ;
0 commit comments