Skip to content

Commit 063ee2d

Browse files
committed
Implement scan.
1 parent 04230e6 commit 063ee2d

File tree

1 file changed

+43
-1
lines changed

1 file changed

+43
-1
lines changed

src/vm/js/QAST/Compiler.nqp

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1097,12 +1097,16 @@ class RegexCompiler {
10971097
has $!restart;
10981098
has $!cstack;
10991099
has $!subcur;
1100+
has $!rep;
11001101

11011102
method compile($node) {
11021103
# TODO better name for $start
11031104
# we need to unpack the array we !cursor_start_all into a bunch of variables
11041105
my $start := $*BLOCK.add_tmp();
11051106

1107+
my $jump := $*BLOCK.add_tmp();
1108+
my $cstack_top := $*BLOCK.add_tmp();
1109+
11061110
Chunk.new($T_OBJ, $!cursor, [
11071111
"{$!label} = {$!initial_label};\n",
11081112
"$start = self['!cursor_start_all']({$*BLOCK.ctx}, \{\});\n",
@@ -1113,10 +1117,25 @@ class RegexCompiler {
11131117
"{$!bstack} = $start[4];\n",
11141118
"{$!restart} = $start[5];\n",
11151119
"{$!js_loop_label}: while (1) \{\nswitch ({$!label}) \{\n",
1120+
11161121
self.case($!initial_label),
11171122
self.compile_rx($node),
1123+
11181124
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+
11201139
self.case($!done_label),
11211140
"{$!cursor}['!cursor_fail']({$*BLOCK.ctx}, \{\});\n",
11221141
"break {$!js_loop_label}\n",
@@ -1154,6 +1173,22 @@ class RegexCompiler {
11541173
"if ($str $cmpop $qconst) \{{self.fail}\} else \{{$!pos}+=$constlen\}\n";
11551174
}
11561175

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+
11571192
method pass($node) {
11581193
my $name;
11591194

@@ -1189,6 +1224,7 @@ class RegexCompiler {
11891224
$!restart := $*BLOCK.add_tmp();
11901225
$!cstack := $*BLOCK.add_tmp();
11911226
$!subcur := $*BLOCK.add_tmp();
1227+
$!rep := $*BLOCK.add_tmp();
11921228

11931229
$!fail_label := self.new_label;
11941230
$!done_label := self.new_label;
@@ -1210,6 +1246,12 @@ class RegexCompiler {
12101246
"$!label = $label;break;\n";
12111247
}
12121248

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+
12131255
method fail() {
12141256
self.goto($!fail_label);
12151257
}

0 commit comments

Comments
 (0)