@@ -1097,12 +1097,16 @@ class RegexCompiler {
1097
1097
has $ ! restart ;
1098
1098
has $ ! cstack ;
1099
1099
has $ ! subcur ;
1100
+ has $ ! rep ;
1100
1101
1101
1102
method compile ($ node ) {
1102
1103
# TODO better name for $start
1103
1104
# we need to unpack the array we !cursor_start_all into a bunch of variables
1104
1105
my $ start := $ * BLOCK . add_tmp();
1105
1106
1107
+ my $ jump := $ * BLOCK . add_tmp();
1108
+ my $ cstack_top := $ * BLOCK . add_tmp();
1109
+
1106
1110
Chunk. new ($ T_OBJ , $ ! cursor , [
1107
1111
" { $ ! label } = { $ ! initial_label } ;\n " ,
1108
1112
" $ start = self['!cursor_start_all']({ $ * BLOCK . ctx} , \{\} );\n " ,
@@ -1113,10 +1117,25 @@ class RegexCompiler {
1113
1117
" { $ ! bstack } = $ start[ 4 ] ;\n " ,
1114
1118
" { $ ! restart } = $ start[ 5 ] ;\n " ,
1115
1119
" { $ ! js_loop_label } : while (1) \{\n switch ({ $ ! label } ) \{\n " ,
1120
+
1116
1121
self . case($ ! initial_label ),
1117
1122
self . compile_rx($ node ),
1123
+
1118
1124
self . case($ ! fail_label ),
1119
- self . goto($ ! done_label ),
1125
+ " if ($ ! bstack .length == 0) \{ { self . goto($ ! done_label )} \}\n " ,
1126
+ " $ cstack_top = $ ! bstack. pop () ;\n " ,
1127
+ " if ($ ! cstack && $ ! cstack .length != 0) \{\n " ,
1128
+ " $ ! subcur = $ ! cstack[ $ cstack_top -1] ;\n " ,
1129
+ " \}\n " ,
1130
+ " $ ! rep = $ ! bstack. pop () ;\n $ ! pos =$ ! bstack. pop () ;\n $ jump =$ ! bstack. pop () ;\n " ,
1131
+ " if ($ ! pos < -1) \{ { self . goto($ ! done_label )} \}\n " ,
1132
+ " if ($ ! pos < 0) \{ { self . fail } \}\n " ,
1133
+ " if ($ jump == 0) \{ { self . fail } \}\n " ,
1134
+ " if (!($ ! cstack instanceof Array)) \{ { self . goto($ jump )} \}\n " ,
1135
+ " if ($ ! bstack .length == 0) \{ $ ! cstack .length = 0;{ self . goto($ jump )} \}\n " ,
1136
+ " $ ! cstack .length = $ ! bstack[ $ ! bstack . length-1] ;\n " ,
1137
+ self . goto($ jump ),
1138
+
1120
1139
self . case($ ! done_label ),
1121
1140
" { $ ! cursor } ['!cursor_fail']({ $ * BLOCK . ctx} , \{\} );\n " ,
1122
1141
" break { $ ! js_loop_label } \n " ,
@@ -1154,6 +1173,22 @@ class RegexCompiler {
1154
1173
" if ($ str $ cmpop $ qconst ) \{ { self . fail } \} else \{ { $ ! pos } +=$ constlen\}\n " ;
1155
1174
}
1156
1175
1176
+ method scan ($ node ) {
1177
+ my $ loop := self . new_label;
1178
+ my $ scan := self . new_label;
1179
+ my $ done := self . new_label;
1180
+
1181
+ " if (self['\$!from'] != -1) \{ { self . goto($ done )} \}\n " # HACK
1182
+ ~ self . goto($ scan )
1183
+ ~ self . case($ loop )
1184
+ ~ " $ ! pos ++;\n "
1185
+ ~ " if ($ ! pos >= $ ! target .length) \{ { self . fail } \}\n " # HACK
1186
+ ~ " $ ! cursor[ ' \$!from' ] = $ ! pos ;\n "
1187
+ ~ self . case($ scan )
1188
+ ~ self . mark($ loop ,$ ! pos ,0 )
1189
+ ~ self . case($ done );
1190
+ }
1191
+
1157
1192
method pass ($ node ) {
1158
1193
my $ name ;
1159
1194
@@ -1189,6 +1224,7 @@ class RegexCompiler {
1189
1224
$ ! restart := $ * BLOCK . add_tmp();
1190
1225
$ ! cstack := $ * BLOCK . add_tmp();
1191
1226
$ ! subcur := $ * BLOCK . add_tmp();
1227
+ $ ! rep := $ * BLOCK . add_tmp();
1192
1228
1193
1229
$ ! fail_label := self . new_label;
1194
1230
$ ! done_label := self . new_label;
@@ -1210,6 +1246,12 @@ class RegexCompiler {
1210
1246
" $ ! label = $ label ;break;\n " ;
1211
1247
}
1212
1248
1249
+ # push a new backtracking mark on the bstack with label $label, position $pos and count $count.
1250
+ # (all arguments are taken as js code snippets).
1251
+ method mark ($ label ,$ pos ,$ count ) {
1252
+ " $ ! bstack. push ($ label ,$ pos ,$ count ,$ ! bstack . length ? $ ! bstack [bstack. length-1] : 0 ) ;\n " ;
1253
+ }
1254
+
1213
1255
method fail () {
1214
1256
self . goto($ ! fail_label );
1215
1257
}
0 commit comments