mittens 0.3.1 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/Gemfile +1 -0
- data/README.md +2 -2
- data/Rakefile +10 -3
- data/lib/mittens/version.rb +1 -1
- data/vendor/snowball/.github/workflows/ci.yml +144 -17
- data/vendor/snowball/.github/workflows/coverage.yml +117 -0
- data/vendor/snowball/.github/workflows/runtime-tests.yml +26 -0
- data/vendor/snowball/.gitignore +33 -7
- data/vendor/snowball/CONTRIBUTING.rst +7 -0
- data/vendor/snowball/COPYING +1 -1
- data/vendor/snowball/GNUmakefile +736 -298
- data/vendor/snowball/NEWS +1394 -7
- data/vendor/snowball/README.rst +8 -8
- data/vendor/snowball/ada/generate/generate.adb +5 -5
- data/vendor/snowball/ada/src/stemmer.adb +177 -188
- data/vendor/snowball/ada/src/stemmer.ads +86 -89
- data/vendor/snowball/ada/src/stemwords.adb +21 -5
- data/vendor/snowball/algorithms/czech.sbl +255 -0
- data/vendor/snowball/algorithms/danish.sbl +22 -10
- data/vendor/snowball/algorithms/english.sbl +7 -4
- data/vendor/snowball/algorithms/esperanto.sbl +6 -7
- data/vendor/snowball/algorithms/estonian.sbl +9 -4
- data/vendor/snowball/algorithms/finnish.sbl +33 -21
- data/vendor/snowball/algorithms/german.sbl +5 -0
- data/vendor/snowball/algorithms/indonesian.sbl +115 -96
- data/vendor/snowball/algorithms/italian.sbl +26 -1
- data/vendor/snowball/algorithms/lithuanian.sbl +13 -13
- data/vendor/snowball/algorithms/norwegian.sbl +17 -6
- data/vendor/snowball/algorithms/persian.sbl +387 -0
- data/vendor/snowball/algorithms/polish.sbl +177 -0
- data/vendor/snowball/algorithms/sesotho.sbl +115 -0
- data/vendor/snowball/algorithms/turkish.sbl +4 -4
- data/vendor/snowball/compiler/analyser.c +2002 -711
- data/vendor/snowball/compiler/driver.c +460 -298
- data/vendor/snowball/compiler/generator.c +439 -1965
- data/vendor/snowball/compiler/generator_ada.c +605 -430
- data/vendor/snowball/compiler/generator_c.c +2227 -0
- data/vendor/snowball/compiler/generator_csharp.c +365 -274
- data/vendor/snowball/compiler/generator_dart.c +1476 -0
- data/vendor/snowball/compiler/generator_go.c +348 -270
- data/vendor/snowball/compiler/generator_java.c +330 -233
- data/vendor/snowball/compiler/generator_js.c +534 -385
- data/vendor/snowball/compiler/generator_pascal.c +361 -320
- data/vendor/snowball/compiler/generator_php.c +1445 -0
- data/vendor/snowball/compiler/generator_python.c +399 -299
- data/vendor/snowball/compiler/generator_rust.c +370 -261
- data/vendor/snowball/compiler/generator_zig.c +1474 -0
- data/vendor/snowball/compiler/header.h +153 -86
- data/vendor/snowball/compiler/space.c +121 -63
- data/vendor/snowball/compiler/tokeniser.c +286 -182
- data/vendor/snowball/compiler/tokens.h +71 -0
- data/vendor/snowball/csharp/Snowball/Among.cs +14 -26
- data/vendor/snowball/csharp/Snowball/AssemblyInfo.cs +3 -3
- data/vendor/snowball/csharp/Snowball/Stemmer.cs +41 -45
- data/vendor/snowball/csharp/Stemwords/Program.cs +20 -14
- data/vendor/snowball/cxx/.gitignore +4 -0
- data/vendor/snowball/cxx/generate_algorithms.pl +87 -0
- data/vendor/snowball/cxx/stemmer.h +12 -0
- data/vendor/snowball/cxx/stemwords.cxx +176 -0
- data/vendor/snowball/cxx/utilities.cxx +2 -0
- data/vendor/snowball/dart/.gitignore +4 -0
- data/vendor/snowball/dart/analysis_options.yaml +1 -0
- data/vendor/snowball/dart/example/test_app.dart +65 -0
- data/vendor/snowball/dart/generate_algorithms.pl +21 -0
- data/vendor/snowball/dart/lib/snowball.dart +18 -0
- data/vendor/snowball/dart/lib/src/snowball.dart +339 -0
- data/vendor/snowball/dart/pubspec.yaml +17 -0
- data/vendor/snowball/doc/libstemmer_dart_README +37 -0
- data/vendor/snowball/doc/libstemmer_js_README +2 -2
- data/vendor/snowball/doc/libstemmer_php_README +38 -0
- data/vendor/snowball/doc/libstemmer_python_README +3 -3
- data/vendor/snowball/examples/stemwords.c +18 -3
- data/vendor/snowball/go/README.md +12 -4
- data/vendor/snowball/go/env.go +12 -14
- data/vendor/snowball/go/stemwords/main.go +2 -1
- data/vendor/snowball/java/org/tartarus/snowball/CharArraySequence.java +36 -0
- data/vendor/snowball/java/org/tartarus/snowball/SnowballProgram.java +17 -34
- data/vendor/snowball/java/org/tartarus/snowball/SnowballStemmer.java +0 -2
- data/vendor/snowball/javascript/base-stemmer.js +219 -252
- data/vendor/snowball/javascript/stemwords.js +86 -58
- data/vendor/snowball/libstemmer/mkmodules.pl +1 -1
- data/vendor/snowball/libstemmer/modules.txt +4 -0
- data/vendor/snowball/pascal/SnowballProgram.pas +18 -31
- data/vendor/snowball/php/base-stemmer.php +453 -0
- data/vendor/snowball/php/stemwords.php +25 -0
- data/vendor/snowball/python/create_init.py +16 -21
- data/vendor/snowball/python/pyproject.toml +3 -0
- data/vendor/snowball/python/setup.py +5 -7
- data/vendor/snowball/python/snowballstemmer/among.py +1 -2
- data/vendor/snowball/python/snowballstemmer/basestemmer.py +24 -33
- data/vendor/snowball/python/stemwords.py +72 -63
- data/vendor/snowball/runtime/api.c +11 -42
- data/vendor/snowball/runtime/api.h +11 -9
- data/vendor/snowball/runtime/snowball_runtime.h +110 -0
- data/vendor/snowball/runtime/utilities.c +282 -106
- data/vendor/snowball/rust/src/main.rs +2 -2
- data/vendor/snowball/rust/src/snowball/snowball_env.rs +7 -9
- data/vendor/snowball/tests/compilertest +62 -0
- data/vendor/snowball/tests/errors/ae-errors.sbl +53 -0
- data/vendor/snowball/tests/errors/ae-errors.stderr +8 -0
- data/vendor/snowball/tests/errors/bad-dollar.sbl +14 -0
- data/vendor/snowball/tests/errors/bad-dollar.stderr +4 -0
- data/vendor/snowball/tests/errors/bad-grouping-definition.sbl +9 -0
- data/vendor/snowball/tests/errors/bad-grouping-definition.stderr +6 -0
- data/vendor/snowball/tests/errors/missing-bra.sbl +6 -0
- data/vendor/snowball/tests/errors/missing-bra.stderr +3 -0
- data/vendor/snowball/tests/errors/missing-command.sbl +9 -0
- data/vendor/snowball/tests/errors/missing-command.stderr +1 -0
- data/vendor/snowball/tests/errors/missing-ket-backwardmode.sbl +3 -0
- data/vendor/snowball/tests/errors/missing-ket-backwardmode.stderr +1 -0
- data/vendor/snowball/tests/errors/missing-ket.sbl +7 -0
- data/vendor/snowball/tests/errors/missing-ket.stderr +6 -0
- data/vendor/snowball/tests/errors/notdefined.sbl +4 -0
- data/vendor/snowball/tests/errors/notdefined.stderr +2 -0
- data/vendor/snowball/tests/errors/string-omitted.sbl +5 -0
- data/vendor/snowball/tests/errors/string-omitted.stderr +1 -0
- data/vendor/snowball/tests/errors/undeclared.sbl +20 -0
- data/vendor/snowball/tests/errors/undeclared.stderr +9 -0
- data/vendor/snowball/tests/errors/unexpected-token.sbl +24 -0
- data/vendor/snowball/tests/errors/unexpected-token.stderr +17 -0
- data/vendor/snowball/tests/errors/wrongdirection.sbl +14 -0
- data/vendor/snowball/tests/errors/wrongdirection.stderr +1 -0
- data/vendor/snowball/tests/runtime/among.sbl +19 -0
- data/vendor/snowball/tests/runtime/arithmeticexpr.sbl +86 -0
- data/vendor/snowball/tests/runtime/attachinsert.sbl +47 -0
- data/vendor/snowball/tests/runtime/booleans.sbl +19 -0
- data/vendor/snowball/tests/runtime/externals.sbl +22 -0
- data/vendor/snowball/tests/runtime/hop.sbl +12 -0
- data/vendor/snowball/tests/runtime/integertests.sbl +60 -0
- data/vendor/snowball/tests/runtime/intlimits.sbl +25 -0
- data/vendor/snowball/tests/runtime/naming.sbl +20 -0
- data/vendor/snowball/tests/runtime/not.sbl +30 -0
- data/vendor/snowball/tests/runtime/or.sbl +17 -0
- data/vendor/snowball/tests/runtime/repeat.sbl +16 -0
- data/vendor/snowball/tests/runtime/setlimit.sbl +24 -0
- data/vendor/snowball/tests/runtime/sizelen.sbl +56 -0
- data/vendor/snowball/tests/runtime/slice.sbl +27 -0
- data/vendor/snowball/tests/runtime/stringdollar.sbl +39 -0
- data/vendor/snowball/tests/runtime/strings.sbl +66 -0
- data/vendor/snowball/tests/runtime/test.sbl +19 -0
- data/vendor/snowball/tests/stemtest.c +41 -1
- data/vendor/snowball/tests/syntax/canon.sbl +32 -0
- data/vendor/snowball/tests/syntax/canon.stderr +0 -0
- data/vendor/snowball/tests/syntax/canon.syntax +57 -0
- data/vendor/snowball/tests/syntax/emptyprogram.sbl +2 -0
- data/vendor/snowball/tests/syntax/emptyprogram.syntax +0 -0
- data/vendor/snowball/tests/syntax/groupings.sbl +11 -0
- data/vendor/snowball/tests/syntax/inline.sbl +144 -0
- data/vendor/snowball/tests/syntax/inline.stderr +0 -0
- data/vendor/snowball/tests/syntax/inline.syntax +121 -0
- data/vendor/snowball/tests/syntax/legacy.sbl +17 -0
- data/vendor/snowball/tests/syntax/legacy.stderr +5 -0
- data/vendor/snowball/tests/syntax/legacy.syntax +19 -0
- data/vendor/snowball/tests/syntax/loops.sbl +14 -0
- data/vendor/snowball/tests/syntax/loops.stderr +9 -0
- data/vendor/snowball/tests/syntax/loops.syntax +29 -0
- data/vendor/snowball/tests/syntax/noops.sbl +76 -0
- data/vendor/snowball/tests/syntax/noops.stderr +27 -0
- data/vendor/snowball/tests/syntax/noops.syntax +135 -0
- data/vendor/snowball/tests/syntax/simplifyae.sbl +21 -0
- data/vendor/snowball/tests/syntax/simplifyae.stderr +0 -0
- data/vendor/snowball/tests/syntax/simplifyae.syntax +39 -0
- data/vendor/snowball/tests/syntax/unused.sbl +18 -0
- data/vendor/snowball/tests/syntax/unused.stderr +7 -0
- data/vendor/snowball/tests/syntax/unused.syntax +3 -0
- data/vendor/snowball/zig/env.zig +599 -0
- data/vendor/snowball/zig/generate_algorithms.pl +19 -0
- data/vendor/snowball/zig/stemwords.zig +123 -0
- metadata +102 -4
- data/vendor/snowball/compiler/syswords.h +0 -86
- data/vendor/snowball/runtime/header.h +0 -62
|
@@ -1,79 +1,64 @@
|
|
|
1
1
|
#include <assert.h>
|
|
2
|
+
#include <stdio.h> /* for fprintf etc */
|
|
2
3
|
#include <stdlib.h> /* for exit */
|
|
3
4
|
#include <string.h> /* for strlen */
|
|
4
|
-
#include <stdio.h> /* for fprintf etc */
|
|
5
5
|
#include "header.h"
|
|
6
6
|
|
|
7
|
-
/*
|
|
7
|
+
/* prototype functions for recursive use: */
|
|
8
8
|
|
|
9
9
|
static void generate(struct generator * g, struct node * p);
|
|
10
10
|
static void w(struct generator * g, const char * s);
|
|
11
11
|
static void writef(struct generator * g, const char * s, struct node * p);
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
return g->next_label++;
|
|
15
|
-
}
|
|
13
|
+
/* Write routines for items from the syntax tree */
|
|
16
14
|
|
|
17
|
-
static
|
|
18
|
-
|
|
19
|
-
g
|
|
20
|
-
output = str_new();
|
|
21
|
-
str_append_string(output, "v_");
|
|
22
|
-
str_append_int(output, g->var_number);
|
|
23
|
-
return output;
|
|
15
|
+
static void write_relop(struct generator * g, int relop) {
|
|
16
|
+
// Relational operators are the same as C.
|
|
17
|
+
write_c_relop(g, relop);
|
|
24
18
|
}
|
|
25
19
|
|
|
26
|
-
/* Write routines for items from the syntax tree */
|
|
27
|
-
|
|
28
20
|
static void write_varname(struct generator * g, struct name * p) {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
default: {
|
|
33
|
-
int ch = "SbirxG"[p->type];
|
|
34
|
-
write_char(g, ch);
|
|
35
|
-
write_char(g, '_');
|
|
36
|
-
break;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
21
|
+
// We use the same naming scheme for both global and local variables.
|
|
22
|
+
write_char(g, "SbirrG"[p->type]);
|
|
23
|
+
write_char(g, '_');
|
|
39
24
|
write_s(g, p->s);
|
|
40
25
|
}
|
|
41
26
|
|
|
27
|
+
/* Reference to variable, e.g. when assigning to or using in an expression. */
|
|
42
28
|
static void write_varref(struct generator * g, struct name * p) {
|
|
43
|
-
|
|
29
|
+
if (p->local_to == NULL) {
|
|
30
|
+
write_string(g, "context.");
|
|
31
|
+
}
|
|
44
32
|
write_varname(g, p);
|
|
45
33
|
}
|
|
46
34
|
|
|
47
35
|
static void write_literal_string(struct generator * g, symbol * p) {
|
|
48
36
|
int i = 0;
|
|
49
|
-
|
|
37
|
+
write_char(g, '"');
|
|
50
38
|
while (i < SIZE(p)) {
|
|
51
39
|
int ch;
|
|
52
40
|
i += get_utf8(p + i, &ch);
|
|
53
|
-
|
|
41
|
+
// Write out ASCII and lower Unicode printables as literal characters.
|
|
42
|
+
// Use escapes for anything over 0x590 as a crude way to avoid LTR
|
|
43
|
+
// characters affecting the rendering of source character order in
|
|
44
|
+
// confusing ways.
|
|
45
|
+
if ((32 <= ch && ch < 127) || (0xa0 < ch && ch < 0x590)) {
|
|
54
46
|
if (ch == '"' || ch == '\\') write_char(g, '\\');
|
|
55
47
|
write_wchar_as_utf8(g, ch);
|
|
56
48
|
} else {
|
|
57
|
-
// Use escapes for anything over 0x590 as a crude way to avoid
|
|
58
|
-
// LTR characters affecting the rendering of source character
|
|
59
|
-
// order in confusing ways.
|
|
60
49
|
write_string(g, "\\u{");
|
|
61
50
|
write_hex4(g, ch);
|
|
62
51
|
write_string(g, "}");
|
|
63
52
|
}
|
|
64
53
|
}
|
|
65
|
-
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
static void write_margin(struct generator * g) {
|
|
69
|
-
for (int i = 0; i < g->margin; i++) write_string(g, " ");
|
|
54
|
+
write_char(g, '"');
|
|
70
55
|
}
|
|
71
56
|
|
|
72
57
|
static void write_comment(struct generator * g, struct node * p) {
|
|
73
58
|
if (!g->options->comments) return;
|
|
74
59
|
write_margin(g);
|
|
75
60
|
write_string(g, "// ");
|
|
76
|
-
write_comment_content(g, p);
|
|
61
|
+
write_comment_content(g, p, NULL);
|
|
77
62
|
write_newline(g);
|
|
78
63
|
}
|
|
79
64
|
|
|
@@ -97,7 +82,7 @@ static void append_restore_string(struct node * p, struct str * out, struct str
|
|
|
97
82
|
str_append_string(out, "env.cursor = ");
|
|
98
83
|
if (p->mode != m_forward) str_append_string(out, "env.limit - ");
|
|
99
84
|
str_append(out, savevar);
|
|
100
|
-
|
|
85
|
+
str_append_ch(out, ';');
|
|
101
86
|
}
|
|
102
87
|
|
|
103
88
|
static void write_restorecursor(struct generator * g, struct node * p, struct str * savevar) {
|
|
@@ -128,6 +113,7 @@ static void wsetlab_end(struct generator * g, int n) {
|
|
|
128
113
|
static void wgotol(struct generator * g, int n) {
|
|
129
114
|
g->I[0] = n;
|
|
130
115
|
w(g, "~Mbreak 'lab~I0;~N");
|
|
116
|
+
g->unreachable = true;
|
|
131
117
|
}
|
|
132
118
|
|
|
133
119
|
static void write_failure(struct generator * g) {
|
|
@@ -138,15 +124,15 @@ static void write_failure(struct generator * g) {
|
|
|
138
124
|
}
|
|
139
125
|
switch (g->failure_label) {
|
|
140
126
|
case x_return:
|
|
141
|
-
w(g, "~Mreturn false
|
|
142
|
-
g->unreachable = true;
|
|
127
|
+
w(g, "~Mreturn false;");
|
|
143
128
|
break;
|
|
144
129
|
default:
|
|
145
130
|
w(g, "~Mbreak 'lab");
|
|
146
131
|
write_int(g, g->failure_label);
|
|
147
|
-
|
|
148
|
-
g->unreachable = true;
|
|
132
|
+
write_char(g, ';');
|
|
149
133
|
}
|
|
134
|
+
write_newline(g);
|
|
135
|
+
g->unreachable = true;
|
|
150
136
|
}
|
|
151
137
|
|
|
152
138
|
static void write_failure_if(struct generator * g, const char * s, struct node * p) {
|
|
@@ -170,7 +156,6 @@ static void write_check_limit(struct generator * g, struct node * p) {
|
|
|
170
156
|
|
|
171
157
|
/* Formatted write. */
|
|
172
158
|
static void writef(struct generator * g, const char * input, struct node * p) {
|
|
173
|
-
(void)p;
|
|
174
159
|
int i = 0;
|
|
175
160
|
|
|
176
161
|
while (input[i]) {
|
|
@@ -215,27 +200,26 @@ static void writef(struct generator * g, const char * input, struct node * p) {
|
|
|
215
200
|
write_int(g, g->I[j]);
|
|
216
201
|
continue;
|
|
217
202
|
}
|
|
218
|
-
case '
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
write_varref(g, g->V[j]);
|
|
225
|
-
else
|
|
226
|
-
write_varname(g, g->V[j]);
|
|
203
|
+
case 'E': {
|
|
204
|
+
// Write an external name.
|
|
205
|
+
if (g->options->externals_prefix) {
|
|
206
|
+
write_string(g, g->options->externals_prefix);
|
|
207
|
+
}
|
|
208
|
+
write_s(g, p->name->s);
|
|
227
209
|
continue;
|
|
228
210
|
}
|
|
229
|
-
case '
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
211
|
+
case 'V':
|
|
212
|
+
write_varref(g, p->name);
|
|
213
|
+
continue;
|
|
214
|
+
case 'W':
|
|
215
|
+
write_varname(g, p->name);
|
|
216
|
+
continue;
|
|
217
|
+
case 'L':
|
|
218
|
+
write_literal_string(g, p->literalstring);
|
|
234
219
|
continue;
|
|
235
|
-
}
|
|
236
220
|
case '+': g->margin++; continue;
|
|
237
221
|
case '-': g->margin--; continue;
|
|
238
|
-
case 'n':
|
|
222
|
+
case 'n': write_s(g, g->options->name); continue;
|
|
239
223
|
default:
|
|
240
224
|
printf("Invalid escape sequence ~%c in writef(g, \"%s\", p)\n",
|
|
241
225
|
ch, input);
|
|
@@ -256,37 +240,44 @@ static void generate_AE(struct generator * g, struct node * p) {
|
|
|
256
240
|
const char * s;
|
|
257
241
|
switch (p->type) {
|
|
258
242
|
case c_name:
|
|
259
|
-
write_varref(g, p->name);
|
|
243
|
+
write_varref(g, p->name);
|
|
244
|
+
break;
|
|
260
245
|
case c_number:
|
|
261
|
-
write_int(g, p->number);
|
|
246
|
+
write_int(g, p->number);
|
|
247
|
+
break;
|
|
262
248
|
case c_maxint:
|
|
263
|
-
write_string(g, "i32::MAX");
|
|
249
|
+
write_string(g, "i32::MAX");
|
|
250
|
+
break;
|
|
264
251
|
case c_minint:
|
|
265
|
-
write_string(g, "i32::MIN");
|
|
252
|
+
write_string(g, "i32::MIN");
|
|
253
|
+
break;
|
|
266
254
|
case c_neg:
|
|
267
|
-
write_char(g, '-');
|
|
255
|
+
write_char(g, '-');
|
|
256
|
+
generate_AE(g, p->right);
|
|
257
|
+
break;
|
|
268
258
|
case c_multiply:
|
|
269
|
-
s = " * ";
|
|
270
|
-
|
|
271
|
-
s = " + "; goto label0;
|
|
272
|
-
case c_minus:
|
|
273
|
-
s = " - "; goto label0;
|
|
259
|
+
s = " * ";
|
|
260
|
+
goto label0;
|
|
274
261
|
case c_divide:
|
|
275
262
|
s = " / ";
|
|
263
|
+
goto label0;
|
|
264
|
+
case c_plus:
|
|
265
|
+
s = " + ";
|
|
266
|
+
goto label0;
|
|
267
|
+
case c_minus:
|
|
268
|
+
s = " - ";
|
|
276
269
|
label0:
|
|
277
|
-
write_char(g, '(');
|
|
278
|
-
|
|
270
|
+
write_char(g, '(');
|
|
271
|
+
generate_AE(g, p->left);
|
|
272
|
+
write_string(g, s);
|
|
273
|
+
generate_AE(g, p->right);
|
|
274
|
+
write_char(g, ')');
|
|
275
|
+
break;
|
|
279
276
|
case c_cursor:
|
|
280
|
-
w(g, "env.cursor");
|
|
281
|
-
case c_limit:
|
|
282
|
-
w(g, p->mode == m_forward ? "env.limit" : "env.limit_backward"); break;
|
|
283
|
-
case c_lenof:
|
|
284
|
-
g->V[0] = p->name;
|
|
285
|
-
w(g, "(~V0.chars().count() as i32)");
|
|
277
|
+
w(g, "env.cursor");
|
|
286
278
|
break;
|
|
287
|
-
case
|
|
288
|
-
g->
|
|
289
|
-
w(g, "(~V0.len() as i32)");
|
|
279
|
+
case c_limit:
|
|
280
|
+
w(g, p->mode == m_forward ? "env.limit" : "env.limit_backward");
|
|
290
281
|
break;
|
|
291
282
|
case c_len:
|
|
292
283
|
w(g, "(env.current.chars().count() as i32)");
|
|
@@ -294,6 +285,12 @@ static void generate_AE(struct generator * g, struct node * p) {
|
|
|
294
285
|
case c_size:
|
|
295
286
|
w(g, "(env.current.len() as i32)");
|
|
296
287
|
break;
|
|
288
|
+
case c_lenof:
|
|
289
|
+
writef(g, "(~V.chars().count() as i32)", p);
|
|
290
|
+
break;
|
|
291
|
+
case c_sizeof:
|
|
292
|
+
writef(g, "(~V.len() as i32)", p);
|
|
293
|
+
break;
|
|
297
294
|
}
|
|
298
295
|
}
|
|
299
296
|
|
|
@@ -308,13 +305,15 @@ static void generate_bra(struct generator * g, struct node * p) {
|
|
|
308
305
|
|
|
309
306
|
static void generate_and(struct generator * g, struct node * p) {
|
|
310
307
|
struct str * savevar = NULL;
|
|
311
|
-
if (
|
|
308
|
+
if (K_needed_for_and(p->left)) {
|
|
312
309
|
savevar = vars_newname(g);
|
|
313
310
|
}
|
|
314
311
|
|
|
315
312
|
write_comment(g, p);
|
|
316
313
|
|
|
317
|
-
if (savevar)
|
|
314
|
+
if (savevar) {
|
|
315
|
+
write_savecursor(g, p, savevar);
|
|
316
|
+
}
|
|
318
317
|
|
|
319
318
|
p = p->left;
|
|
320
319
|
while (p) {
|
|
@@ -331,7 +330,7 @@ static void generate_and(struct generator * g, struct node * p) {
|
|
|
331
330
|
|
|
332
331
|
static void generate_or(struct generator * g, struct node * p) {
|
|
333
332
|
struct str * savevar = NULL;
|
|
334
|
-
if (
|
|
333
|
+
if (K_needed_for_or(p->left)) {
|
|
335
334
|
savevar = vars_newname(g);
|
|
336
335
|
}
|
|
337
336
|
|
|
@@ -339,12 +338,14 @@ static void generate_or(struct generator * g, struct node * p) {
|
|
|
339
338
|
struct str * a1 = str_copy(g->failure_str);
|
|
340
339
|
|
|
341
340
|
int out_lab = new_label(g);
|
|
342
|
-
|
|
341
|
+
bool end_unreachable = true;
|
|
343
342
|
|
|
344
343
|
write_comment(g, p);
|
|
345
344
|
wsetlab_begin(g, out_lab);
|
|
346
345
|
|
|
347
|
-
if (savevar
|
|
346
|
+
if (savevar && K_needed_node_on_f(p)) {
|
|
347
|
+
write_savecursor(g, p, savevar);
|
|
348
|
+
}
|
|
348
349
|
|
|
349
350
|
p = p->left;
|
|
350
351
|
str_clear(g->failure_str);
|
|
@@ -364,9 +365,11 @@ static void generate_or(struct generator * g, struct node * p) {
|
|
|
364
365
|
wgotol(g, out_lab);
|
|
365
366
|
end_unreachable = false;
|
|
366
367
|
}
|
|
367
|
-
|
|
368
|
+
wsetlab_end(g, label);
|
|
368
369
|
g->unreachable = false;
|
|
369
|
-
if (savevar)
|
|
370
|
+
if (savevar) {
|
|
371
|
+
write_restorecursor(g, p, savevar);
|
|
372
|
+
}
|
|
370
373
|
p = p->right;
|
|
371
374
|
}
|
|
372
375
|
|
|
@@ -375,6 +378,7 @@ static void generate_or(struct generator * g, struct node * p) {
|
|
|
375
378
|
g->failure_str = a1;
|
|
376
379
|
|
|
377
380
|
generate(g, p);
|
|
381
|
+
|
|
378
382
|
wsetlab_end(g, out_lab);
|
|
379
383
|
if (!end_unreachable) {
|
|
380
384
|
g->unreachable = false;
|
|
@@ -393,10 +397,9 @@ static void generate_backwards(struct generator * g, struct node * p) {
|
|
|
393
397
|
w(g, "~Menv.cursor = env.limit_backward;~N");
|
|
394
398
|
}
|
|
395
399
|
|
|
396
|
-
|
|
397
400
|
static void generate_not(struct generator * g, struct node * p) {
|
|
398
401
|
struct str * savevar = NULL;
|
|
399
|
-
if (
|
|
402
|
+
if (K_needed_node_on_f(p->left)) {
|
|
400
403
|
savevar = vars_newname(g);
|
|
401
404
|
}
|
|
402
405
|
|
|
@@ -421,7 +424,7 @@ static void generate_not(struct generator * g, struct node * p) {
|
|
|
421
424
|
g->failure_str = a1;
|
|
422
425
|
|
|
423
426
|
if (!g->unreachable) write_failure(g);
|
|
424
|
-
|
|
427
|
+
wsetlab_end(g, label);
|
|
425
428
|
|
|
426
429
|
g->unreachable = false;
|
|
427
430
|
|
|
@@ -431,18 +434,16 @@ static void generate_not(struct generator * g, struct node * p) {
|
|
|
431
434
|
}
|
|
432
435
|
}
|
|
433
436
|
|
|
434
|
-
|
|
435
437
|
static void generate_try(struct generator * g, struct node * p) {
|
|
436
438
|
struct str * savevar = NULL;
|
|
437
|
-
if (K_needed(
|
|
439
|
+
if (K_needed(p->left)) {
|
|
438
440
|
savevar = vars_newname(g);
|
|
439
441
|
}
|
|
440
442
|
|
|
443
|
+
write_comment(g, p);
|
|
441
444
|
int label = new_label(g);
|
|
442
445
|
g->failure_label = label;
|
|
443
446
|
str_clear(g->failure_str);
|
|
444
|
-
|
|
445
|
-
write_comment(g, p);
|
|
446
447
|
if (savevar) {
|
|
447
448
|
write_savecursor(g, p, savevar);
|
|
448
449
|
append_restore_string(p, g->failure_str, savevar);
|
|
@@ -459,14 +460,12 @@ static void generate_try(struct generator * g, struct node * p) {
|
|
|
459
460
|
|
|
460
461
|
static void generate_set(struct generator * g, struct node * p) {
|
|
461
462
|
write_comment(g, p);
|
|
462
|
-
g
|
|
463
|
-
writef(g, "~M~V0 = true;~N", p);
|
|
463
|
+
writef(g, "~M~V = true;~N", p);
|
|
464
464
|
}
|
|
465
465
|
|
|
466
466
|
static void generate_unset(struct generator * g, struct node * p) {
|
|
467
467
|
write_comment(g, p);
|
|
468
|
-
g
|
|
469
|
-
writef(g, "~M~V0 = false;~N", p);
|
|
468
|
+
writef(g, "~M~V = false;~N", p);
|
|
470
469
|
}
|
|
471
470
|
|
|
472
471
|
static void generate_fail(struct generator * g, struct node * p) {
|
|
@@ -476,10 +475,9 @@ static void generate_fail(struct generator * g, struct node * p) {
|
|
|
476
475
|
}
|
|
477
476
|
|
|
478
477
|
/* generate_test() also implements 'reverse' */
|
|
479
|
-
|
|
480
478
|
static void generate_test(struct generator * g, struct node * p) {
|
|
481
479
|
struct str * savevar = NULL;
|
|
482
|
-
if (K_needed(
|
|
480
|
+
if (K_needed(p->left)) {
|
|
483
481
|
savevar = vars_newname(g);
|
|
484
482
|
}
|
|
485
483
|
|
|
@@ -501,18 +499,19 @@ static void generate_test(struct generator * g, struct node * p) {
|
|
|
501
499
|
|
|
502
500
|
static void generate_do(struct generator * g, struct node * p) {
|
|
503
501
|
struct str * savevar = NULL;
|
|
504
|
-
if (K_needed(
|
|
502
|
+
if (K_needed(p->left)) {
|
|
505
503
|
savevar = vars_newname(g);
|
|
506
504
|
}
|
|
507
505
|
|
|
508
506
|
write_comment(g, p);
|
|
509
|
-
if (savevar)
|
|
507
|
+
if (savevar) {
|
|
508
|
+
write_savecursor(g, p, savevar);
|
|
509
|
+
}
|
|
510
510
|
|
|
511
511
|
if (p->left->type == c_call) {
|
|
512
512
|
/* Optimise do <call> */
|
|
513
513
|
write_comment(g, p->left);
|
|
514
|
-
g
|
|
515
|
-
w(g, "~M~W0(env, context);~N");
|
|
514
|
+
writef(g, "~M~W(env, context);~N", p->left);
|
|
516
515
|
} else {
|
|
517
516
|
int label = new_label(g);
|
|
518
517
|
g->failure_label = label;
|
|
@@ -542,34 +541,36 @@ static void generate_GO_grouping(struct generator * g, struct node * p, int is_g
|
|
|
542
541
|
struct grouping * q = p->name->grouping;
|
|
543
542
|
g->S[0] = p->mode == m_forward ? "" : "_b";
|
|
544
543
|
g->S[1] = complement ? "in" : "out";
|
|
545
|
-
g->V[0] = p->name;
|
|
546
544
|
g->I[0] = q->smallest_ch;
|
|
547
545
|
g->I[1] = q->largest_ch;
|
|
548
|
-
write_failure_if(g, "!env.go_~S1_grouping~S0(~
|
|
546
|
+
write_failure_if(g, "!env.go_~S1_grouping~S0(~W, ~I0, ~I1)", p);
|
|
549
547
|
if (!is_goto) {
|
|
548
|
+
write_margin(g);
|
|
550
549
|
write_string(g, p->mode == m_forward ? "env.next_char();" : "env.previous_char();");
|
|
550
|
+
write_newline(g);
|
|
551
551
|
}
|
|
552
552
|
}
|
|
553
553
|
|
|
554
|
-
static void generate_GO(struct generator * g, struct node * p, int
|
|
554
|
+
static void generate_GO(struct generator * g, struct node * p, int is_goto) {
|
|
555
555
|
write_comment(g, p);
|
|
556
556
|
|
|
557
557
|
int a0 = g->failure_label;
|
|
558
558
|
struct str * a1 = str_copy(g->failure_str);
|
|
559
559
|
|
|
560
|
-
|
|
560
|
+
bool end_unreachable = false;
|
|
561
561
|
|
|
562
562
|
int golab = new_label(g);
|
|
563
563
|
g->I[0] = golab;
|
|
564
564
|
w(g, "~M'golab~I0: loop {~N~+");
|
|
565
565
|
|
|
566
566
|
struct str * savevar = NULL;
|
|
567
|
-
if (
|
|
567
|
+
if (is_goto || repeat_restore(p->left)) {
|
|
568
568
|
savevar = vars_newname(g);
|
|
569
569
|
write_savecursor(g, p, savevar);
|
|
570
570
|
}
|
|
571
571
|
|
|
572
|
-
|
|
572
|
+
int label = new_label(g);
|
|
573
|
+
g->failure_label = label;
|
|
573
574
|
str_clear(g->failure_str);
|
|
574
575
|
wsetlab_begin(g, g->failure_label);
|
|
575
576
|
generate(g, p->left);
|
|
@@ -580,12 +581,13 @@ static void generate_GO(struct generator * g, struct node * p, int style) {
|
|
|
580
581
|
end_unreachable = true;
|
|
581
582
|
} else {
|
|
582
583
|
/* include for goto; omit for gopast */
|
|
583
|
-
if (
|
|
584
|
+
if (is_goto) write_restorecursor(g, p, savevar);
|
|
584
585
|
g->I[0] = golab;
|
|
585
586
|
w(g, "~Mbreak 'golab~I0;~N");
|
|
587
|
+
g->unreachable = true;
|
|
586
588
|
}
|
|
589
|
+
wsetlab_end(g, g->failure_label);
|
|
587
590
|
g->unreachable = false;
|
|
588
|
-
w(g, "~-~M}~N");
|
|
589
591
|
if (savevar) {
|
|
590
592
|
write_restorecursor(g, p, savevar);
|
|
591
593
|
str_delete(savevar);
|
|
@@ -602,8 +604,8 @@ static void generate_GO(struct generator * g, struct node * p, int style) {
|
|
|
602
604
|
}
|
|
603
605
|
|
|
604
606
|
static void generate_loop(struct generator * g, struct node * p) {
|
|
605
|
-
struct str * loopvar = vars_newname(g);
|
|
606
607
|
write_comment(g, p);
|
|
608
|
+
struct str * loopvar = vars_newname(g);
|
|
607
609
|
w(g, "~Mfor _ in 0..");
|
|
608
610
|
generate_AE(g, p->AE);
|
|
609
611
|
writef(g, " {~+~N", p);
|
|
@@ -621,12 +623,13 @@ static void generate_repeat_or_atleast(struct generator * g, struct node * p, st
|
|
|
621
623
|
writef(g, "~M'replab~I0: loop{~N~+", p);
|
|
622
624
|
|
|
623
625
|
struct str * savevar = NULL;
|
|
624
|
-
if (repeat_restore(
|
|
626
|
+
if (repeat_restore(p->left)) {
|
|
625
627
|
savevar = vars_newname(g);
|
|
626
628
|
write_savecursor(g, p, savevar);
|
|
627
629
|
}
|
|
628
630
|
|
|
629
|
-
|
|
631
|
+
int label = new_label(g);
|
|
632
|
+
g->failure_label = label;
|
|
630
633
|
str_clear(g->failure_str);
|
|
631
634
|
g->I[0] = g->failure_label;
|
|
632
635
|
w(g, "~M'lab~I0: for _ in 0..1 {~N~+");
|
|
@@ -659,9 +662,9 @@ static void generate_repeat(struct generator * g, struct node * p) {
|
|
|
659
662
|
}
|
|
660
663
|
|
|
661
664
|
static void generate_atleast(struct generator * g, struct node * p) {
|
|
662
|
-
struct str * loopvar = vars_newname(g);
|
|
663
|
-
|
|
664
665
|
write_comment(g, p);
|
|
666
|
+
|
|
667
|
+
struct str * loopvar = vars_newname(g);
|
|
665
668
|
g->B[0] = str_data(loopvar);
|
|
666
669
|
w(g, "~Mlet mut ~B0 = ");
|
|
667
670
|
generate_AE(g, p->AE);
|
|
@@ -681,12 +684,6 @@ static void generate_atleast(struct generator * g, struct node * p) {
|
|
|
681
684
|
str_delete(loopvar);
|
|
682
685
|
}
|
|
683
686
|
|
|
684
|
-
static void generate_setmark(struct generator * g, struct node * p) {
|
|
685
|
-
write_comment(g, p);
|
|
686
|
-
g->V[0] = p->name;
|
|
687
|
-
writef(g, "~M~V0 = env.cursor;~N", p);
|
|
688
|
-
}
|
|
689
|
-
|
|
690
687
|
static void generate_tomark(struct generator * g, struct node * p) {
|
|
691
688
|
write_comment(g, p);
|
|
692
689
|
g->S[0] = p->mode == m_forward ? ">" : "<";
|
|
@@ -700,15 +697,6 @@ static void generate_tomark(struct generator * g, struct node * p) {
|
|
|
700
697
|
w(g, "~Menv.cursor = "); generate_AE(g, p->AE); writef(g, ";~N", p);
|
|
701
698
|
}
|
|
702
699
|
|
|
703
|
-
static void generate_atmark(struct generator * g, struct node * p) {
|
|
704
|
-
write_comment(g, p);
|
|
705
|
-
w(g, "~Mif env.cursor != "); generate_AE(g, p->AE); writef(g, " ", p);
|
|
706
|
-
write_block_start(g);
|
|
707
|
-
write_failure(g);
|
|
708
|
-
write_block_end(g);
|
|
709
|
-
g->unreachable = false;
|
|
710
|
-
}
|
|
711
|
-
|
|
712
700
|
static void generate_hop(struct generator * g, struct node * p) {
|
|
713
701
|
write_comment(g, p);
|
|
714
702
|
// Generate the AE to a temporary block so we can substitute it in
|
|
@@ -725,26 +713,12 @@ static void generate_hop(struct generator * g, struct node * p) {
|
|
|
725
713
|
str_delete(ae);
|
|
726
714
|
}
|
|
727
715
|
|
|
728
|
-
static void generate_delete(struct generator * g, struct node * p) {
|
|
729
|
-
write_comment(g, p);
|
|
730
|
-
writef(g, "~Mif !env.slice_del() {~N"
|
|
731
|
-
"~+~Mreturn false;~N~-"
|
|
732
|
-
"~M}~N", p);
|
|
733
|
-
}
|
|
734
|
-
|
|
735
716
|
static void generate_tolimit(struct generator * g, struct node * p) {
|
|
736
717
|
write_comment(g, p);
|
|
737
718
|
g->S[0] = p->mode == m_forward ? "env.limit" : "env.limit_backward";
|
|
738
719
|
writef(g, "~Menv.cursor = ~S0;~N", p);
|
|
739
720
|
}
|
|
740
721
|
|
|
741
|
-
static void generate_atlimit(struct generator * g, struct node * p) {
|
|
742
|
-
write_comment(g, p);
|
|
743
|
-
g->S[0] = p->mode == m_forward ? "env.limit" : "env.limit_backward";
|
|
744
|
-
g->S[1] = p->mode == m_forward ? "<" : ">";
|
|
745
|
-
write_failure_if(g, "env.cursor ~S1 ~S0", p);
|
|
746
|
-
}
|
|
747
|
-
|
|
748
722
|
static void generate_leftslice(struct generator * g, struct node * p) {
|
|
749
723
|
write_comment(g, p);
|
|
750
724
|
g->S[0] = p->mode == m_forward ? "env.bra" : "env.ket";
|
|
@@ -759,16 +733,12 @@ static void generate_rightslice(struct generator * g, struct node * p) {
|
|
|
759
733
|
|
|
760
734
|
static void generate_assignto(struct generator * g, struct node * p) {
|
|
761
735
|
write_comment(g, p);
|
|
762
|
-
g
|
|
763
|
-
writef(g, "~M~V0 = env.assign_to();~N", p);
|
|
736
|
+
writef(g, "~M~V = env.assign_to();~N", p);
|
|
764
737
|
}
|
|
765
738
|
|
|
766
739
|
static void generate_sliceto(struct generator * g, struct node * p) {
|
|
767
740
|
write_comment(g, p);
|
|
768
|
-
g
|
|
769
|
-
writef(g, "~M~V0 = env.slice_to();~N"
|
|
770
|
-
"~Mif ~V0.is_empty() {~N"
|
|
771
|
-
"~+~Mreturn false;~N~-~M}~N", p);
|
|
741
|
+
writef(g, "~M~V = env.slice_to();~N", p);
|
|
772
742
|
}
|
|
773
743
|
|
|
774
744
|
static void generate_address(struct generator * g, struct node * p) {
|
|
@@ -786,8 +756,8 @@ static void generate_address(struct generator * g, struct node * p) {
|
|
|
786
756
|
}
|
|
787
757
|
|
|
788
758
|
static void generate_insert(struct generator * g, struct node * p, int style) {
|
|
789
|
-
int keep_c = style == c_attach;
|
|
790
759
|
write_comment(g, p);
|
|
760
|
+
int keep_c = style == c_attach;
|
|
791
761
|
if (p->mode == m_backward) keep_c = !keep_c;
|
|
792
762
|
if (keep_c) w(g, "~Mlet c = env.cursor;~N");
|
|
793
763
|
w(g, "~Mlet (bra, ket) = (env.cursor, env.cursor);~N");
|
|
@@ -797,11 +767,12 @@ static void generate_insert(struct generator * g, struct node * p, int style) {
|
|
|
797
767
|
if (keep_c) w(g, "~Menv.cursor = c;~N");
|
|
798
768
|
}
|
|
799
769
|
|
|
800
|
-
static void
|
|
801
|
-
int keep_c = p->mode == m_forward; /* like 'attach' */
|
|
802
|
-
|
|
770
|
+
static void generate_stringassign(struct generator * g, struct node * p) {
|
|
803
771
|
write_comment(g, p);
|
|
804
|
-
|
|
772
|
+
int keep_c = p->mode == m_forward; /* like 'attach' */
|
|
773
|
+
if (keep_c) {
|
|
774
|
+
writef(g, "~Mlet c = env.cursor;~N", p);
|
|
775
|
+
}
|
|
805
776
|
/* Copying limits and cursors is necessary here because the rust
|
|
806
777
|
* borrowchecker does not like taking something from someone you are about
|
|
807
778
|
* to mutate... */
|
|
@@ -813,20 +784,26 @@ static void generate_assignfrom(struct generator * g, struct node * p) {
|
|
|
813
784
|
writef(g, "~Menv.insert(bra, ket, ", p);
|
|
814
785
|
generate_address(g, p);
|
|
815
786
|
writef(g, ");~N", p);
|
|
816
|
-
if (keep_c)
|
|
787
|
+
if (keep_c) {
|
|
788
|
+
w(g, "~Menv.cursor = c;~N");
|
|
789
|
+
}
|
|
817
790
|
}
|
|
818
791
|
|
|
819
792
|
static void generate_slicefrom(struct generator * g, struct node * p) {
|
|
820
793
|
write_comment(g, p);
|
|
821
|
-
|
|
794
|
+
if (p->literalstring && SIZE(p->literalstring) == 0) {
|
|
795
|
+
w(g, "~Menv.slice_del();~N");
|
|
796
|
+
return;
|
|
797
|
+
}
|
|
798
|
+
w(g, "~Menv.slice_from(");
|
|
822
799
|
generate_address(g, p);
|
|
823
|
-
|
|
824
|
-
"~+~Mreturn false;~N~-~M}~N", p);
|
|
800
|
+
w(g, ");~N");
|
|
825
801
|
}
|
|
826
802
|
|
|
827
803
|
static void generate_setlimit(struct generator * g, struct node * p) {
|
|
828
|
-
struct str * varname = vars_newname(g);
|
|
829
804
|
write_comment(g, p);
|
|
805
|
+
struct str * varname = vars_newname(g);
|
|
806
|
+
|
|
830
807
|
if (p->left && p->left->type == c_tomark) {
|
|
831
808
|
/* Special case for:
|
|
832
809
|
*
|
|
@@ -838,6 +815,7 @@ static void generate_setlimit(struct generator * g, struct node * p) {
|
|
|
838
815
|
*/
|
|
839
816
|
struct node * q = p->left;
|
|
840
817
|
write_comment(g, q);
|
|
818
|
+
|
|
841
819
|
g->S[0] = q->mode == m_forward ? ">" : "<";
|
|
842
820
|
w(g, "~Mif env.cursor ~S0 "); generate_AE(g, q->AE); w(g, " ");
|
|
843
821
|
write_block_start(g);
|
|
@@ -847,23 +825,26 @@ static void generate_setlimit(struct generator * g, struct node * p) {
|
|
|
847
825
|
|
|
848
826
|
g->B[0] = str_data(varname);
|
|
849
827
|
if (p->mode == m_forward) {
|
|
850
|
-
w(g, "~Mlet ~B0 = env.limit
|
|
828
|
+
w(g, "~Mlet mut ~B0 = env.limit;~N");
|
|
851
829
|
w(g, "~Menv.limit = ");
|
|
830
|
+
generate_AE(g, q->AE);
|
|
831
|
+
w(g, ";~N");
|
|
832
|
+
w(g, "~M~B0 -= env.limit;~N");
|
|
852
833
|
} else {
|
|
853
834
|
w(g, "~Mlet ~B0 = env.limit_backward;~N");
|
|
854
835
|
w(g, "~Menv.limit_backward = ");
|
|
836
|
+
generate_AE(g, q->AE);
|
|
837
|
+
w(g, ";~N");
|
|
855
838
|
}
|
|
856
|
-
generate_AE(g, q->AE);
|
|
857
|
-
writef(g, ";~N", q);
|
|
858
839
|
|
|
859
840
|
if (p->mode == m_forward) {
|
|
860
841
|
str_assign(g->failure_str, "env.limit += ");
|
|
861
842
|
str_append(g->failure_str, varname);
|
|
862
|
-
|
|
843
|
+
str_append_ch(g->failure_str, ';');
|
|
863
844
|
} else {
|
|
864
845
|
str_assign(g->failure_str, "env.limit_backward = ");
|
|
865
846
|
str_append(g->failure_str, varname);
|
|
866
|
-
|
|
847
|
+
str_append_ch(g->failure_str, ';');
|
|
867
848
|
}
|
|
868
849
|
} else {
|
|
869
850
|
struct str * savevar = vars_newname(g);
|
|
@@ -885,11 +866,11 @@ static void generate_setlimit(struct generator * g, struct node * p) {
|
|
|
885
866
|
if (p->mode == m_forward) {
|
|
886
867
|
str_assign(g->failure_str, "env.limit += ");
|
|
887
868
|
str_append(g->failure_str, varname);
|
|
888
|
-
|
|
869
|
+
str_append_ch(g->failure_str, ';');
|
|
889
870
|
} else {
|
|
890
871
|
str_assign(g->failure_str, "env.limit_backward = ");
|
|
891
872
|
str_append(g->failure_str, varname);
|
|
892
|
-
|
|
873
|
+
str_append_ch(g->failure_str, ';');
|
|
893
874
|
}
|
|
894
875
|
}
|
|
895
876
|
str_delete(savevar);
|
|
@@ -904,6 +885,7 @@ static void generate_setlimit(struct generator * g, struct node * p) {
|
|
|
904
885
|
write_newline(g);
|
|
905
886
|
}
|
|
906
887
|
}
|
|
888
|
+
|
|
907
889
|
str_delete(varname);
|
|
908
890
|
}
|
|
909
891
|
|
|
@@ -912,36 +894,64 @@ static void generate_setlimit(struct generator * g, struct node * p) {
|
|
|
912
894
|
static void generate_dollar(struct generator * g, struct node * p) {
|
|
913
895
|
write_comment(g, p);
|
|
914
896
|
|
|
897
|
+
int a0 = g->failure_label;
|
|
898
|
+
struct str * a1 = str_copy(g->failure_str);
|
|
899
|
+
int label = new_label(g);
|
|
900
|
+
g->failure_label = label;
|
|
901
|
+
str_clear(g->failure_str);
|
|
902
|
+
|
|
915
903
|
struct str * savevar = vars_newname(g);
|
|
916
|
-
g->V[0] = p->name;
|
|
917
904
|
g->B[0] = str_data(savevar);
|
|
918
905
|
writef(g, "~Mlet ~B0 = env.clone();~N"
|
|
919
|
-
"~Menv.set_current_s(~
|
|
906
|
+
"~Menv.set_current_s(~V.clone());~N"
|
|
920
907
|
"~Menv.cursor = 0;~N"
|
|
921
908
|
"~Menv.limit = env.current.len() as i32;~N", p);
|
|
909
|
+
if (p->left->possible_signals == -1) {
|
|
910
|
+
/* Assume failure. */
|
|
911
|
+
w(g, "~Mlet mut ~B0_f = true;~N");
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
wsetlab_begin(g, g->failure_label);
|
|
915
|
+
|
|
922
916
|
generate(g, p->left);
|
|
923
|
-
|
|
924
|
-
|
|
917
|
+
|
|
918
|
+
if (!g->unreachable && p->left->possible_signals == -1) {
|
|
919
|
+
/* Mark success. */
|
|
925
920
|
g->B[0] = str_data(savevar);
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
921
|
+
w(g, "~M~B0_f = false;~N");
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
wsetlab_end(g, g->failure_label);
|
|
925
|
+
|
|
926
|
+
g->failure_label = a0;
|
|
927
|
+
str_delete(g->failure_str);
|
|
928
|
+
g->failure_str = a1;
|
|
929
|
+
|
|
930
|
+
g->B[0] = str_data(savevar);
|
|
931
|
+
/* Update string variable; restore env. */
|
|
932
|
+
writef(g, "~M~V = env.current.clone().into_owned();~N"
|
|
933
|
+
"~M*env = ~B0;~N", p);
|
|
934
|
+
|
|
935
|
+
if (p->left->possible_signals == 0) {
|
|
936
|
+
// p->left always signals f.
|
|
937
|
+
write_failure(g);
|
|
938
|
+
} else if (p->left->possible_signals == -1) {
|
|
939
|
+
write_failure_if(g, "~B0_f", p);
|
|
930
940
|
}
|
|
941
|
+
|
|
931
942
|
str_delete(savevar);
|
|
932
943
|
}
|
|
933
944
|
|
|
934
945
|
static void generate_integer_assign(struct generator * g, struct node * p, const char * s) {
|
|
935
946
|
write_comment(g, p);
|
|
936
|
-
g->V[0] = p->name;
|
|
937
947
|
g->S[0] = s;
|
|
938
|
-
|
|
948
|
+
writef(g, "~M~V ~S0 ", p); generate_AE(g, p->AE); w(g, ";~N");
|
|
939
949
|
}
|
|
940
950
|
|
|
941
951
|
static void generate_integer_test(struct generator * g, struct node * p) {
|
|
942
952
|
write_comment(g, p);
|
|
943
953
|
int relop = p->type;
|
|
944
|
-
int optimise_to_return = (g
|
|
954
|
+
int optimise_to_return = tailcallable(g, p);
|
|
945
955
|
if (optimise_to_return) {
|
|
946
956
|
w(g, "~Mreturn ");
|
|
947
957
|
p->right = NULL;
|
|
@@ -951,12 +961,12 @@ static void generate_integer_test(struct generator * g, struct node * p) {
|
|
|
951
961
|
relop ^= 1;
|
|
952
962
|
}
|
|
953
963
|
generate_AE(g, p->left);
|
|
954
|
-
|
|
955
|
-
write_c_relop(g, relop);
|
|
964
|
+
write_relop(g, relop);
|
|
956
965
|
generate_AE(g, p->AE);
|
|
957
966
|
if (optimise_to_return) {
|
|
958
967
|
w(g, "~N");
|
|
959
968
|
} else {
|
|
969
|
+
write_char(g, ' ');
|
|
960
970
|
write_block_start(g);
|
|
961
971
|
write_failure(g);
|
|
962
972
|
write_block_end(g);
|
|
@@ -965,24 +975,30 @@ static void generate_integer_test(struct generator * g, struct node * p) {
|
|
|
965
975
|
}
|
|
966
976
|
|
|
967
977
|
static void generate_call(struct generator * g, struct node * p) {
|
|
968
|
-
int signals =
|
|
978
|
+
int signals = p->name->definition->possible_signals;
|
|
969
979
|
write_comment(g, p);
|
|
970
|
-
g
|
|
971
|
-
|
|
972
|
-
(
|
|
973
|
-
|
|
974
|
-
|
|
980
|
+
if (tailcallable(g, p)) {
|
|
981
|
+
/* Tail call. */
|
|
982
|
+
writef(g, "~Mreturn ~W(env, context);~N", p);
|
|
983
|
+
p->right = NULL;
|
|
984
|
+
g->unreachable = true;
|
|
985
|
+
return;
|
|
986
|
+
}
|
|
987
|
+
if (just_return_on_fail(g) && signals == 0) {
|
|
988
|
+
/* Always fails. */
|
|
989
|
+
writef(g, "~Mreturn ~W(env, context);~N", p);
|
|
990
|
+
g->unreachable = true;
|
|
975
991
|
return;
|
|
976
992
|
}
|
|
977
993
|
if (signals == 1) {
|
|
978
994
|
/* Always succeeds. */
|
|
979
|
-
writef(g, "~M~
|
|
995
|
+
writef(g, "~M~W(env, context);~N", p);
|
|
980
996
|
} else if (signals == 0) {
|
|
981
997
|
/* Always fails. */
|
|
982
|
-
writef(g, "~M~
|
|
998
|
+
writef(g, "~M~W(env, context);~N", p);
|
|
983
999
|
write_failure(g);
|
|
984
1000
|
} else {
|
|
985
|
-
write_failure_if(g, "!~
|
|
1001
|
+
write_failure_if(g, "!~W(env, context)", p);
|
|
986
1002
|
}
|
|
987
1003
|
}
|
|
988
1004
|
|
|
@@ -992,40 +1008,57 @@ static void generate_grouping(struct generator * g, struct node * p, int complem
|
|
|
992
1008
|
struct grouping * q = p->name->grouping;
|
|
993
1009
|
g->S[0] = p->mode == m_forward ? "" : "_b";
|
|
994
1010
|
g->S[1] = complement ? "out" : "in";
|
|
995
|
-
g->V[0] = p->name;
|
|
996
1011
|
g->I[0] = q->smallest_ch;
|
|
997
1012
|
g->I[1] = q->largest_ch;
|
|
998
|
-
|
|
1013
|
+
if (tailcallable(g, p)) {
|
|
1014
|
+
writef(g, "~Mreturn env.~S1_grouping~S0(~W, ~I0, ~I1);~N", p);
|
|
1015
|
+
p->right = NULL;
|
|
1016
|
+
} else {
|
|
1017
|
+
write_failure_if(g, "!env.~S1_grouping~S0(~W, ~I0, ~I1)", p);
|
|
1018
|
+
}
|
|
999
1019
|
}
|
|
1000
1020
|
|
|
1001
1021
|
static void generate_namedstring(struct generator * g, struct node * p) {
|
|
1002
1022
|
write_comment(g, p);
|
|
1003
1023
|
g->S[0] = p->mode == m_forward ? "" : "_b";
|
|
1004
|
-
g
|
|
1005
|
-
|
|
1024
|
+
if (tailcallable(g, p)) {
|
|
1025
|
+
writef(g, "~Mreturn env.eq_s~S0(&~V);~N", p);
|
|
1026
|
+
p->right = NULL;
|
|
1027
|
+
} else {
|
|
1028
|
+
write_failure_if(g, "!env.eq_s~S0(&~V)", p);
|
|
1029
|
+
}
|
|
1006
1030
|
}
|
|
1007
1031
|
|
|
1008
1032
|
static void generate_literalstring(struct generator * g, struct node * p) {
|
|
1009
|
-
symbol * b = p->literalstring;
|
|
1010
1033
|
write_comment(g, p);
|
|
1011
1034
|
g->S[0] = p->mode == m_forward ? "" : "_b";
|
|
1012
|
-
g
|
|
1013
|
-
|
|
1035
|
+
if (tailcallable(g, p)) {
|
|
1036
|
+
writef(g, "~Mreturn env.eq_s~S0(&~L);~N", p);
|
|
1037
|
+
p->right = NULL;
|
|
1038
|
+
} else {
|
|
1039
|
+
write_failure_if(g, "!env.eq_s~S0(&~L)", p);
|
|
1040
|
+
}
|
|
1014
1041
|
}
|
|
1015
1042
|
|
|
1016
1043
|
static void generate_setup_context(struct generator * g) {
|
|
1017
1044
|
w(g, "~Mlet mut context = &mut Context {~+~N");
|
|
1018
1045
|
for (struct name * q = g->analyser->names; q; q = q->next) {
|
|
1019
|
-
|
|
1046
|
+
if (q->local_to) continue;
|
|
1020
1047
|
switch (q->type) {
|
|
1021
1048
|
case t_string:
|
|
1022
|
-
|
|
1049
|
+
write_margin(g);
|
|
1050
|
+
write_varname(g, q);
|
|
1051
|
+
w(g, ": String::new(),~N");
|
|
1023
1052
|
break;
|
|
1024
1053
|
case t_integer:
|
|
1025
|
-
|
|
1054
|
+
write_margin(g);
|
|
1055
|
+
write_varname(g, q);
|
|
1056
|
+
w(g, ": 0,~N");
|
|
1026
1057
|
break;
|
|
1027
1058
|
case t_boolean:
|
|
1028
|
-
|
|
1059
|
+
write_margin(g);
|
|
1060
|
+
write_varname(g, q);
|
|
1061
|
+
w(g, ": false,~N");
|
|
1029
1062
|
break;
|
|
1030
1063
|
}
|
|
1031
1064
|
}
|
|
@@ -1034,23 +1067,52 @@ static void generate_setup_context(struct generator * g) {
|
|
|
1034
1067
|
|
|
1035
1068
|
static void generate_define(struct generator * g, struct node * p) {
|
|
1036
1069
|
struct name * q = p->name;
|
|
1037
|
-
if (q->type == t_routine && !q->used) return;
|
|
1038
1070
|
|
|
1039
1071
|
write_newline(g);
|
|
1040
1072
|
write_comment(g, p);
|
|
1041
1073
|
|
|
1042
|
-
g->V[0] = q;
|
|
1043
1074
|
if (q->type == t_routine) {
|
|
1044
|
-
|
|
1075
|
+
writef(g, "~Mfn ~W(env: &mut SnowballEnv, context: &mut Context) -> bool {~+~N", p);
|
|
1045
1076
|
} else {
|
|
1046
|
-
|
|
1077
|
+
writef(g, "~Mpub fn ~E(env: &mut SnowballEnv) -> bool {~+~N", p);
|
|
1047
1078
|
generate_setup_context(g);
|
|
1079
|
+
if (q->used != q->definition) {
|
|
1080
|
+
// This external needs to be callable as a routine, so generate
|
|
1081
|
+
// the actual code like a routine with an external which just
|
|
1082
|
+
// forwards to that.
|
|
1083
|
+
writef(g, "~Mreturn ~W(env, context);~N", p);
|
|
1084
|
+
w(g, "~-~M}~N");
|
|
1085
|
+
writef(g, "~Mfn ~W(env: &mut SnowballEnv, context: &mut Context) -> bool {~+~N", p);
|
|
1086
|
+
}
|
|
1048
1087
|
}
|
|
1049
|
-
if (p->amongvar_needed) w(g, "~Mlet mut among_var;~N");
|
|
1050
1088
|
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1089
|
+
if (q->amongvar_needed) {
|
|
1090
|
+
w(g, "~Mlet mut among_var;~N");
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
/* Declare localised variables. */
|
|
1094
|
+
for (struct name * name = g->analyser->names; name; name = name->next) {
|
|
1095
|
+
if (name->local_to == q) {
|
|
1096
|
+
switch (name->type) {
|
|
1097
|
+
case t_string:
|
|
1098
|
+
// String variables not localised for Rust currently.
|
|
1099
|
+
w(g, "~Mlet mut ");
|
|
1100
|
+
write_varname(g, name);
|
|
1101
|
+
w(g, " : String;~N");
|
|
1102
|
+
break;
|
|
1103
|
+
case t_integer:
|
|
1104
|
+
w(g, "~Mlet mut ");
|
|
1105
|
+
write_varname(g, name);
|
|
1106
|
+
w(g, " : i32;~N");
|
|
1107
|
+
break;
|
|
1108
|
+
case t_boolean:
|
|
1109
|
+
w(g, "~Mlet mut ");
|
|
1110
|
+
write_varname(g, name);
|
|
1111
|
+
w(g, " : bool;~N");
|
|
1112
|
+
break;
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1115
|
+
}
|
|
1054
1116
|
|
|
1055
1117
|
g->next_label = 0;
|
|
1056
1118
|
g->var_number = 0;
|
|
@@ -1058,21 +1120,16 @@ static void generate_define(struct generator * g, struct node * p) {
|
|
|
1058
1120
|
str_clear(g->failure_str);
|
|
1059
1121
|
g->failure_label = x_return;
|
|
1060
1122
|
g->unreachable = false;
|
|
1061
|
-
int signals = check_possible_signals_list(g, p->left, c_define, 0);
|
|
1062
1123
|
|
|
1063
1124
|
/* Generate function body. */
|
|
1064
1125
|
generate(g, p->left);
|
|
1065
1126
|
if (p->left->right) {
|
|
1066
1127
|
assert(p->left->right->type == c_functionend);
|
|
1067
|
-
if (
|
|
1128
|
+
if (p->left->possible_signals) {
|
|
1068
1129
|
generate(g, p->left->right);
|
|
1069
1130
|
}
|
|
1070
1131
|
}
|
|
1071
1132
|
w(g, "~-~M}~N");
|
|
1072
|
-
|
|
1073
|
-
str_append(saved_output, g->outbuf);
|
|
1074
|
-
str_delete(g->outbuf);
|
|
1075
|
-
g->outbuf = saved_output;
|
|
1076
1133
|
}
|
|
1077
1134
|
|
|
1078
1135
|
static void generate_functionend(struct generator * g, struct node * p) {
|
|
@@ -1139,13 +1196,16 @@ static void generate_substring(struct generator * g, struct node * p) {
|
|
|
1139
1196
|
}
|
|
1140
1197
|
}
|
|
1141
1198
|
|
|
1142
|
-
|
|
1199
|
+
int pre_check = (block != -1 || n_cases <= 2);
|
|
1200
|
+
if (pre_check) {
|
|
1143
1201
|
char buf[64];
|
|
1144
1202
|
g->I[2] = block;
|
|
1145
1203
|
g->I[3] = bitmap;
|
|
1146
1204
|
g->I[4] = shortest_size - 1;
|
|
1147
1205
|
if (p->mode == m_forward) {
|
|
1148
|
-
|
|
1206
|
+
checked_snprintf(buf, sizeof(buf),
|
|
1207
|
+
"env.current.as_bytes()[(env.cursor + %d) as usize]",
|
|
1208
|
+
shortest_size - 1);
|
|
1149
1209
|
g->S[1] = buf;
|
|
1150
1210
|
if (shortest_size == 1) {
|
|
1151
1211
|
writef(g, "~Mif (env.cursor >= env.limit", p);
|
|
@@ -1160,12 +1220,8 @@ static void generate_substring(struct generator * g, struct node * p) {
|
|
|
1160
1220
|
writef(g, "~Mif (env.cursor - ~I4 <= env.limit_backward", p);
|
|
1161
1221
|
}
|
|
1162
1222
|
}
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
* This doesn't seem to be a useful construct, but it is
|
|
1166
|
-
* syntactically valid.
|
|
1167
|
-
*/
|
|
1168
|
-
} else if (n_cases == 1) {
|
|
1223
|
+
assert(n_cases > 0);
|
|
1224
|
+
if (n_cases == 1) {
|
|
1169
1225
|
g->I[4] = cases[0];
|
|
1170
1226
|
writef(g, " || ~S1 as u8 != ~I4 as u8", p);
|
|
1171
1227
|
} else if (n_cases == 2) {
|
|
@@ -1176,7 +1232,7 @@ static void generate_substring(struct generator * g, struct node * p) {
|
|
|
1176
1232
|
writef(g, " || ~S1 as u8 >> 5 != ~I2 as u8 || ((~I3 as i32 >> (~S1 as u8 & 0x1f)) & 1) == 0", p);
|
|
1177
1233
|
}
|
|
1178
1234
|
write_string(g, ") ");
|
|
1179
|
-
if (empty_case != -1) {
|
|
1235
|
+
if (empty_case != -1 && !among_cases[empty_case].function) {
|
|
1180
1236
|
/* If the among includes the empty string, it can never fail
|
|
1181
1237
|
* so not matching the bitmap means we match the empty string.
|
|
1182
1238
|
*/
|
|
@@ -1198,12 +1254,35 @@ static void generate_substring(struct generator * g, struct node * p) {
|
|
|
1198
1254
|
if (!x->always_matches) {
|
|
1199
1255
|
write_failure_if(g, "among_var == 0", p);
|
|
1200
1256
|
}
|
|
1201
|
-
|
|
1257
|
+
if (block_opened) write_block_end(g);
|
|
1258
|
+
return;
|
|
1259
|
+
}
|
|
1260
|
+
|
|
1261
|
+
if (pre_check && !x->function_count) {
|
|
1262
|
+
// If all cases are one symbol long (so one byte of UTF-8, one
|
|
1263
|
+
// character long in fixed-width encodings) then we don't need to call
|
|
1264
|
+
// the helper and can just inc/dec the cursor by 1.
|
|
1265
|
+
if (x->longest_size == 1 && !x->always_matches) {
|
|
1266
|
+
if (p->mode == m_forward) {
|
|
1267
|
+
w(g, "~Menv.cursor += 1;~N");
|
|
1268
|
+
} else {
|
|
1269
|
+
w(g, "~Menv.cursor -= 1;~N");
|
|
1270
|
+
}
|
|
1271
|
+
// Suppress generating table for this among.
|
|
1272
|
+
x->used = false;
|
|
1273
|
+
return;
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
|
|
1277
|
+
if (x->always_matches) {
|
|
1202
1278
|
writef(g, "~Menv.find_among~S0(A_~I0, context);~N", p);
|
|
1279
|
+
} else if (x->command_count == 0 && tailcallable(g, p)) {
|
|
1280
|
+
writef(g, "~Mreturn env.find_among~S0(A_~I0, context) != 0;~N", p);
|
|
1281
|
+
x->node->right = NULL;
|
|
1282
|
+
g->unreachable = true;
|
|
1203
1283
|
} else {
|
|
1204
1284
|
write_failure_if(g, "env.find_among~S0(A_~I0, context) == 0", p);
|
|
1205
1285
|
}
|
|
1206
|
-
if (block_opened) write_block_end(g);
|
|
1207
1286
|
}
|
|
1208
1287
|
|
|
1209
1288
|
static void generate_among(struct generator * g, struct node * p) {
|
|
@@ -1232,10 +1311,24 @@ static void generate_among(struct generator * g, struct node * p) {
|
|
|
1232
1311
|
}
|
|
1233
1312
|
}
|
|
1234
1313
|
|
|
1235
|
-
static void generate_booltest(struct generator * g, struct node * p) {
|
|
1314
|
+
static void generate_booltest(struct generator * g, struct node * p, int inverted) {
|
|
1236
1315
|
write_comment(g, p);
|
|
1237
|
-
g
|
|
1238
|
-
|
|
1316
|
+
if (tailcallable(g, p)) {
|
|
1317
|
+
// Optimise at end of function.
|
|
1318
|
+
if (inverted) {
|
|
1319
|
+
writef(g, "~Mreturn !~V;~N", p);
|
|
1320
|
+
} else {
|
|
1321
|
+
writef(g, "~Mreturn ~V;~N", p);
|
|
1322
|
+
}
|
|
1323
|
+
p->right = NULL;
|
|
1324
|
+
g->unreachable = true;
|
|
1325
|
+
return;
|
|
1326
|
+
}
|
|
1327
|
+
if (inverted) {
|
|
1328
|
+
write_failure_if(g, "~V", p);
|
|
1329
|
+
} else {
|
|
1330
|
+
write_failure_if(g, "!~V", p);
|
|
1331
|
+
}
|
|
1239
1332
|
}
|
|
1240
1333
|
|
|
1241
1334
|
static void generate_false(struct generator * g, struct node * p) {
|
|
@@ -1280,25 +1373,21 @@ static void generate(struct generator * g, struct node * p) {
|
|
|
1280
1373
|
case c_repeat: generate_repeat(g, p); break;
|
|
1281
1374
|
case c_loop: generate_loop(g, p); break;
|
|
1282
1375
|
case c_atleast: generate_atleast(g, p); break;
|
|
1283
|
-
case c_setmark: generate_setmark(g, p); break;
|
|
1284
1376
|
case c_tomark: generate_tomark(g, p); break;
|
|
1285
|
-
case c_atmark: generate_atmark(g, p); break;
|
|
1286
1377
|
case c_hop: generate_hop(g, p); break;
|
|
1287
|
-
case c_delete: generate_delete(g, p); break;
|
|
1288
1378
|
case c_next: generate_next(g, p); break;
|
|
1289
1379
|
case c_tolimit: generate_tolimit(g, p); break;
|
|
1290
|
-
case c_atlimit: generate_atlimit(g, p); break;
|
|
1291
1380
|
case c_leftslice: generate_leftslice(g, p); break;
|
|
1292
1381
|
case c_rightslice: generate_rightslice(g, p); break;
|
|
1293
1382
|
case c_assignto: generate_assignto(g, p); break;
|
|
1294
1383
|
case c_sliceto: generate_sliceto(g, p); break;
|
|
1295
|
-
case
|
|
1384
|
+
case c_stringassign: generate_stringassign(g, p); break;
|
|
1296
1385
|
case c_insert:
|
|
1297
1386
|
case c_attach: generate_insert(g, p, p->type); break;
|
|
1298
1387
|
case c_slicefrom: generate_slicefrom(g, p); break;
|
|
1299
1388
|
case c_setlimit: generate_setlimit(g, p); break;
|
|
1300
1389
|
case c_dollar: generate_dollar(g, p); break;
|
|
1301
|
-
case
|
|
1390
|
+
case c_assign: generate_integer_assign(g, p, "="); break;
|
|
1302
1391
|
case c_plusassign: generate_integer_assign(g, p, "+="); break;
|
|
1303
1392
|
case c_minusassign: generate_integer_assign(g, p, "-="); break;
|
|
1304
1393
|
case c_multiplyassign:generate_integer_assign(g, p, "*="); break;
|
|
@@ -1318,7 +1407,8 @@ static void generate(struct generator * g, struct node * p) {
|
|
|
1318
1407
|
case c_literalstring: generate_literalstring(g, p); break;
|
|
1319
1408
|
case c_among: generate_among(g, p); break;
|
|
1320
1409
|
case c_substring: generate_substring(g, p); break;
|
|
1321
|
-
case c_booltest: generate_booltest(g, p); break;
|
|
1410
|
+
case c_booltest: generate_booltest(g, p, false); break;
|
|
1411
|
+
case c_not_booltest: generate_booltest(g, p, true); break;
|
|
1322
1412
|
case c_false: generate_false(g, p); break;
|
|
1323
1413
|
case c_true: break;
|
|
1324
1414
|
case c_debug: generate_debug(g, p); break;
|
|
@@ -1346,7 +1436,7 @@ static void generate_allow_warnings(struct generator * g) {
|
|
|
1346
1436
|
|
|
1347
1437
|
static void generate_class_begin(struct generator * g) {
|
|
1348
1438
|
w(g, "use snowball::SnowballEnv;~N");
|
|
1349
|
-
if (g->analyser->
|
|
1439
|
+
if (g->analyser->amongs) {
|
|
1350
1440
|
w(g, "use snowball::Among;~N~N");
|
|
1351
1441
|
}
|
|
1352
1442
|
}
|
|
@@ -1359,37 +1449,40 @@ static void generate_among_table(struct generator * g, struct among * x) {
|
|
|
1359
1449
|
g->I[0] = x->number;
|
|
1360
1450
|
g->I[1] = x->literalstring_count;
|
|
1361
1451
|
|
|
1362
|
-
w(g, "~Mstatic A_~I0: &'static [Among<Context>; ~I1] = &[~N~+");
|
|
1452
|
+
w(g, "~N~Mstatic A_~I0: &'static [Among<Context>; ~I1] = &[~N~+");
|
|
1363
1453
|
for (int i = 0; i < x->literalstring_count; i++) {
|
|
1364
1454
|
g->I[0] = v[i].i;
|
|
1365
1455
|
g->I[1] = v[i].result;
|
|
1366
|
-
g->L[0] = v[i].b;
|
|
1367
|
-
g->S[0] = ",";
|
|
1368
1456
|
|
|
1369
|
-
w(g, "~MAmong(
|
|
1457
|
+
w(g, "~MAmong(");
|
|
1458
|
+
write_literal_string(g, v[i].b);
|
|
1459
|
+
w(g, ", ~I0, ~I1, ");
|
|
1370
1460
|
if (v[i].function != NULL) {
|
|
1371
1461
|
w(g, "Some(&");
|
|
1372
1462
|
write_varname(g, v[i].function);
|
|
1373
1463
|
w(g, ")");
|
|
1374
1464
|
} else {
|
|
1375
|
-
|
|
1465
|
+
w(g, "None");
|
|
1376
1466
|
}
|
|
1377
|
-
w(g, ")
|
|
1467
|
+
w(g, "),~N");
|
|
1378
1468
|
}
|
|
1379
|
-
w(g, "~-~M];~N
|
|
1469
|
+
w(g, "~-~M];~N");
|
|
1380
1470
|
}
|
|
1381
1471
|
|
|
1382
1472
|
static void generate_amongs(struct generator * g) {
|
|
1473
|
+
struct str * s = g->outbuf;
|
|
1474
|
+
g->outbuf = g->declarations;
|
|
1383
1475
|
for (struct among * x = g->analyser->amongs; x; x = x->next) {
|
|
1384
|
-
generate_among_table(g, x);
|
|
1476
|
+
if (x->used) generate_among_table(g, x);
|
|
1385
1477
|
}
|
|
1478
|
+
g->outbuf = s;
|
|
1386
1479
|
}
|
|
1387
1480
|
|
|
1388
|
-
static void set_bit(symbol * b, int i) { b[i
|
|
1481
|
+
static void set_bit(symbol * b, int i) { b[i >> 3] |= 1 << (i & 7); }
|
|
1389
1482
|
|
|
1390
1483
|
static void generate_grouping_table(struct generator * g, struct grouping * q) {
|
|
1391
1484
|
int range = q->largest_ch - q->smallest_ch + 1;
|
|
1392
|
-
int size = (range + 7)/ 8; /* assume 8 bits per symbol */
|
|
1485
|
+
int size = (range + 7) / 8; /* assume 8 bits per symbol */
|
|
1393
1486
|
symbol * b = q->b;
|
|
1394
1487
|
symbol * map = create_b(size);
|
|
1395
1488
|
|
|
@@ -1397,39 +1490,48 @@ static void generate_grouping_table(struct generator * g, struct grouping * q) {
|
|
|
1397
1490
|
|
|
1398
1491
|
for (int i = 0; i < SIZE(b); i++) set_bit(map, b[i] - q->smallest_ch);
|
|
1399
1492
|
|
|
1400
|
-
g->V[0] = q->name;
|
|
1401
1493
|
g->I[0] = size;
|
|
1402
|
-
w(g, "~Mstatic
|
|
1494
|
+
w(g, "~N~Mstatic ");
|
|
1495
|
+
write_varname(g, q->name);
|
|
1496
|
+
w(g, ": &'static [u8; ~I0] = &[");
|
|
1403
1497
|
for (int i = 0; i < size; i++) {
|
|
1498
|
+
if (i) w(g, ", ");
|
|
1404
1499
|
write_int(g, map[i]);
|
|
1405
|
-
if (i < size - 1) w(g, ", ");
|
|
1406
1500
|
}
|
|
1407
|
-
w(g, "];~N
|
|
1501
|
+
w(g, "];~N");
|
|
1408
1502
|
|
|
1409
1503
|
lose_b(map);
|
|
1410
1504
|
}
|
|
1411
1505
|
|
|
1412
1506
|
static void generate_groupings(struct generator * g) {
|
|
1507
|
+
struct str * s = g->outbuf;
|
|
1508
|
+
g->outbuf = g->declarations;
|
|
1413
1509
|
for (struct grouping * q = g->analyser->groupings; q; q = q->next) {
|
|
1414
|
-
|
|
1415
|
-
generate_grouping_table(g, q);
|
|
1510
|
+
generate_grouping_table(g, q);
|
|
1416
1511
|
}
|
|
1512
|
+
g->outbuf = s;
|
|
1417
1513
|
}
|
|
1418
1514
|
|
|
1419
1515
|
static void generate_members(struct generator * g) {
|
|
1420
1516
|
w(g, "#[derive(Clone)]~N");
|
|
1421
1517
|
w(g, "struct Context {~+~N");
|
|
1422
1518
|
for (struct name * q = g->analyser->names; q; q = q->next) {
|
|
1423
|
-
|
|
1519
|
+
if (q->local_to) continue;
|
|
1424
1520
|
switch (q->type) {
|
|
1425
1521
|
case t_string:
|
|
1426
|
-
|
|
1522
|
+
write_margin(g);
|
|
1523
|
+
write_varname(g, q);
|
|
1524
|
+
w(g, ": String,~N");
|
|
1427
1525
|
break;
|
|
1428
1526
|
case t_integer:
|
|
1429
|
-
|
|
1527
|
+
write_margin(g);
|
|
1528
|
+
write_varname(g, q);
|
|
1529
|
+
w(g, ": i32,~N");
|
|
1430
1530
|
break;
|
|
1431
1531
|
case t_boolean:
|
|
1432
|
-
|
|
1532
|
+
write_margin(g);
|
|
1533
|
+
write_varname(g, q);
|
|
1534
|
+
w(g, ": bool,~N");
|
|
1433
1535
|
break;
|
|
1434
1536
|
}
|
|
1435
1537
|
}
|
|
@@ -1455,13 +1557,20 @@ extern void generate_program_rust(struct generator * g) {
|
|
|
1455
1557
|
}
|
|
1456
1558
|
generate_class_begin(g);
|
|
1457
1559
|
|
|
1458
|
-
generate_amongs(g);
|
|
1459
|
-
generate_groupings(g);
|
|
1460
|
-
|
|
1461
1560
|
generate_members(g);
|
|
1561
|
+
|
|
1562
|
+
g->declarations = g->outbuf;
|
|
1563
|
+
g->outbuf = str_new();
|
|
1564
|
+
|
|
1462
1565
|
generate_methods(g);
|
|
1463
1566
|
|
|
1567
|
+
generate_amongs(g);
|
|
1568
|
+
generate_groupings(g);
|
|
1569
|
+
|
|
1570
|
+
output_str(g->options->output_src, g->declarations);
|
|
1571
|
+
str_delete(g->declarations);
|
|
1464
1572
|
output_str(g->options->output_src, g->outbuf);
|
|
1465
|
-
str_delete(g->failure_str);
|
|
1466
1573
|
str_delete(g->outbuf);
|
|
1574
|
+
|
|
1575
|
+
str_delete(g->failure_str);
|
|
1467
1576
|
}
|