mittens 0.2.0 → 0.3.0
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/README.md +3 -3
- data/lib/mittens/version.rb +1 -1
- data/vendor/snowball/.github/workflows/ci.yml +216 -0
- data/vendor/snowball/CONTRIBUTING.rst +111 -62
- data/vendor/snowball/GNUmakefile +194 -136
- data/vendor/snowball/NEWS +798 -3
- data/vendor/snowball/README.rst +50 -1
- data/vendor/snowball/ada/src/stemmer.adb +25 -13
- data/vendor/snowball/ada/src/stemmer.ads +9 -9
- data/vendor/snowball/ada/stemmer_config.gpr +7 -7
- data/vendor/snowball/algorithms/basque.sbl +4 -19
- data/vendor/snowball/algorithms/catalan.sbl +2 -9
- data/vendor/snowball/algorithms/danish.sbl +1 -1
- data/vendor/snowball/algorithms/dutch.sbl +284 -122
- data/vendor/snowball/algorithms/dutch_porter.sbl +178 -0
- data/vendor/snowball/algorithms/english.sbl +52 -37
- data/vendor/snowball/algorithms/esperanto.sbl +157 -0
- data/vendor/snowball/algorithms/estonian.sbl +269 -0
- data/vendor/snowball/algorithms/finnish.sbl +2 -3
- data/vendor/snowball/algorithms/french.sbl +42 -16
- data/vendor/snowball/algorithms/german.sbl +35 -14
- data/vendor/snowball/algorithms/greek.sbl +76 -76
- data/vendor/snowball/algorithms/hungarian.sbl +8 -6
- data/vendor/snowball/algorithms/indonesian.sbl +14 -8
- data/vendor/snowball/algorithms/italian.sbl +11 -21
- data/vendor/snowball/algorithms/lithuanian.sbl +36 -37
- data/vendor/snowball/algorithms/lovins.sbl +0 -1
- data/vendor/snowball/algorithms/nepali.sbl +138 -37
- data/vendor/snowball/algorithms/norwegian.sbl +19 -5
- data/vendor/snowball/algorithms/porter.sbl +2 -2
- data/vendor/snowball/algorithms/portuguese.sbl +9 -13
- data/vendor/snowball/algorithms/romanian.sbl +17 -4
- data/vendor/snowball/algorithms/serbian.sbl +467 -468
- data/vendor/snowball/algorithms/spanish.sbl +5 -7
- data/vendor/snowball/algorithms/swedish.sbl +60 -6
- data/vendor/snowball/algorithms/tamil.sbl +207 -176
- data/vendor/snowball/algorithms/turkish.sbl +461 -445
- data/vendor/snowball/algorithms/yiddish.sbl +36 -38
- data/vendor/snowball/compiler/analyser.c +445 -192
- data/vendor/snowball/compiler/driver.c +109 -101
- data/vendor/snowball/compiler/generator.c +853 -464
- data/vendor/snowball/compiler/generator_ada.c +404 -366
- data/vendor/snowball/compiler/generator_csharp.c +297 -260
- data/vendor/snowball/compiler/generator_go.c +323 -254
- data/vendor/snowball/compiler/generator_java.c +326 -252
- data/vendor/snowball/compiler/generator_js.c +362 -252
- data/vendor/snowball/compiler/generator_pascal.c +349 -197
- data/vendor/snowball/compiler/generator_python.c +257 -240
- data/vendor/snowball/compiler/generator_rust.c +423 -251
- data/vendor/snowball/compiler/header.h +117 -71
- data/vendor/snowball/compiler/space.c +137 -68
- data/vendor/snowball/compiler/syswords.h +2 -2
- data/vendor/snowball/compiler/tokeniser.c +125 -107
- data/vendor/snowball/csharp/Snowball/Among.cs +14 -14
- data/vendor/snowball/csharp/Snowball/AssemblyInfo.cs +7 -7
- data/vendor/snowball/csharp/Snowball/Stemmer.cs +57 -37
- data/vendor/snowball/csharp/Stemwords/App.config +2 -2
- data/vendor/snowball/csharp/Stemwords/Program.cs +16 -12
- data/vendor/snowball/doc/libstemmer_c_README +7 -4
- data/vendor/snowball/doc/libstemmer_csharp_README +4 -1
- data/vendor/snowball/doc/libstemmer_java_README +12 -1
- data/vendor/snowball/doc/libstemmer_js_README +6 -4
- data/vendor/snowball/doc/libstemmer_python_README +9 -4
- data/vendor/snowball/examples/stemwords.c +12 -12
- data/vendor/snowball/go/env.go +107 -31
- data/vendor/snowball/go/util.go +0 -4
- data/vendor/snowball/include/libstemmer.h +4 -0
- data/vendor/snowball/java/org/tartarus/snowball/Among.java +32 -15
- data/vendor/snowball/java/org/tartarus/snowball/SnowballProgram.java +347 -261
- data/vendor/snowball/java/org/tartarus/snowball/SnowballStemmer.java +3 -0
- data/vendor/snowball/java/org/tartarus/snowball/TestApp.java +52 -37
- data/vendor/snowball/javascript/base-stemmer.js +186 -2
- data/vendor/snowball/javascript/stemwords.js +3 -6
- data/vendor/snowball/libstemmer/libstemmer_c.in +1 -1
- data/vendor/snowball/libstemmer/mkalgorithms.pl +6 -6
- data/vendor/snowball/libstemmer/mkmodules.pl +2 -2
- data/vendor/snowball/libstemmer/modules.txt +13 -10
- data/vendor/snowball/libstemmer/test.c +1 -1
- data/vendor/snowball/pascal/SnowballProgram.pas +84 -2
- data/vendor/snowball/pascal/generate.pl +13 -13
- data/vendor/snowball/python/create_init.py +4 -1
- data/vendor/snowball/python/setup.cfg +0 -3
- data/vendor/snowball/python/setup.py +8 -3
- data/vendor/snowball/python/snowballstemmer/basestemmer.py +20 -54
- data/vendor/snowball/python/stemwords.py +8 -12
- data/vendor/snowball/runtime/api.c +10 -5
- data/vendor/snowball/runtime/header.h +10 -9
- data/vendor/snowball/runtime/utilities.c +9 -9
- data/vendor/snowball/rust/build.rs +1 -1
- data/vendor/snowball/rust/src/snowball/snowball_env.rs +83 -5
- data/vendor/snowball/tests/stemtest.c +7 -4
- metadata +7 -7
- data/vendor/snowball/.travis.yml +0 -112
- data/vendor/snowball/algorithms/german2.sbl +0 -145
- data/vendor/snowball/algorithms/kraaij_pohlmann.sbl +0 -240
- data/vendor/snowball/compiler/syswords2.h +0 -13
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
#include <assert.h>
|
2
2
|
#include <stdlib.h> /* for exit */
|
3
3
|
#include <string.h> /* for strlen */
|
4
4
|
#include <stdio.h> /* for fprintf etc */
|
@@ -15,7 +15,6 @@ static int new_label(struct generator * g) {
|
|
15
15
|
}
|
16
16
|
|
17
17
|
static struct str * vars_newname(struct generator * g) {
|
18
|
-
|
19
18
|
struct str * output;
|
20
19
|
g->var_number++;
|
21
20
|
output = str_new();
|
@@ -24,57 +23,38 @@ static struct str * vars_newname(struct generator * g) {
|
|
24
23
|
return output;
|
25
24
|
}
|
26
25
|
|
27
|
-
|
28
26
|
/* Write routines for items from the syntax tree */
|
29
27
|
|
30
28
|
static void write_varname(struct generator * g, struct name * p) {
|
31
|
-
|
32
29
|
int ch = "SBIrxg"[p->type];
|
33
30
|
if (p->type != t_external) {
|
34
31
|
write_char(g, ch);
|
35
32
|
write_char(g, '_');
|
36
33
|
}
|
37
|
-
|
34
|
+
write_s(g, p->s);
|
38
35
|
}
|
39
36
|
|
40
37
|
static void write_varref(struct generator * g, struct name * p) {
|
41
38
|
write_varname(g, p);
|
42
39
|
}
|
43
40
|
|
44
|
-
static void write_hexdigit(struct generator * g, int n) {
|
45
|
-
|
46
|
-
write_char(g, n < 10 ? n + '0' : n - 10 + 'A');
|
47
|
-
}
|
48
|
-
|
49
|
-
static void write_hex(struct generator * g, int ch) {
|
50
|
-
|
51
|
-
write_string(g, "\\u");
|
52
|
-
{
|
53
|
-
int i;
|
54
|
-
for (i = 12; i >= 0; i -= 4) write_hexdigit(g, ch >> i & 0xf);
|
55
|
-
}
|
56
|
-
}
|
57
|
-
|
58
41
|
static void write_literal_string(struct generator * g, symbol * p) {
|
59
|
-
|
60
|
-
int i;
|
61
42
|
write_string(g, "\"");
|
62
|
-
for (i = 0; i < SIZE(p); i++) {
|
43
|
+
for (int i = 0; i < SIZE(p); i++) {
|
63
44
|
int ch = p[i];
|
64
45
|
if (32 <= ch && ch < 127) {
|
65
46
|
if (ch == '\"' || ch == '\\') write_string(g, "\\");
|
66
47
|
write_char(g, ch);
|
67
48
|
} else {
|
68
|
-
|
49
|
+
write_string(g, "\\u");
|
50
|
+
write_hex4(g, ch);
|
69
51
|
}
|
70
52
|
}
|
71
53
|
write_string(g, "\"");
|
72
54
|
}
|
73
55
|
|
74
56
|
static void write_margin(struct generator * g) {
|
75
|
-
|
76
|
-
int i;
|
77
|
-
for (i = 0; i < g->margin; i++) write_string(g, " ");
|
57
|
+
for (int i = 0; i < g->margin; i++) write_string(g, " ");
|
78
58
|
}
|
79
59
|
|
80
60
|
static void write_comment(struct generator * g, struct node * p) {
|
@@ -86,46 +66,35 @@ static void write_comment(struct generator * g, struct node * p) {
|
|
86
66
|
}
|
87
67
|
|
88
68
|
static void write_block_start(struct generator * g) {
|
89
|
-
|
90
69
|
w(g, "~M{~+~N");
|
91
70
|
}
|
92
71
|
|
93
|
-
static void write_block_end(struct generator * g)
|
94
|
-
|
72
|
+
static void write_block_end(struct generator * g) {
|
95
73
|
w(g, "~-~M}~N");
|
96
74
|
}
|
97
75
|
|
98
76
|
static void write_savecursor(struct generator * g, struct node * p,
|
99
77
|
struct str * savevar) {
|
100
|
-
|
101
78
|
g->B[0] = str_data(savevar);
|
102
79
|
g->S[1] = "";
|
103
80
|
if (p->mode != m_forward) g->S[1] = "base.limit - ";
|
104
|
-
writef(g, "~
|
81
|
+
writef(g, "~M~C /** number */ ~B0 = ~S1base.cursor;~N", p);
|
105
82
|
}
|
106
83
|
|
107
|
-
static void
|
108
|
-
|
109
|
-
str_clear(out);
|
84
|
+
static void append_restore_string(struct node * p, struct str * out, struct str * savevar) {
|
110
85
|
str_append_string(out, "base.cursor = ");
|
111
86
|
if (p->mode != m_forward) str_append_string(out, "base.limit - ");
|
112
87
|
str_append(out, savevar);
|
113
88
|
str_append_string(out, ";");
|
114
89
|
}
|
115
90
|
|
116
|
-
static void write_restorecursor(struct generator * g, struct node * p,
|
117
|
-
struct str * savevar) {
|
118
|
-
|
119
|
-
struct str * temp = str_new();
|
91
|
+
static void write_restorecursor(struct generator * g, struct node * p, struct str * savevar) {
|
120
92
|
write_margin(g);
|
121
|
-
|
122
|
-
write_str(g, temp);
|
93
|
+
append_restore_string(p, g->outbuf, savevar);
|
123
94
|
write_newline(g);
|
124
|
-
str_delete(temp);
|
125
95
|
}
|
126
96
|
|
127
97
|
static void write_inc_cursor(struct generator * g, struct node * p) {
|
128
|
-
|
129
98
|
write_margin(g);
|
130
99
|
write_string(g, p->mode == m_forward ? "base.cursor++;" : "base.cursor--;");
|
131
100
|
write_newline(g);
|
@@ -137,12 +106,10 @@ static void wsetlab_begin(struct generator * g, int n) {
|
|
137
106
|
}
|
138
107
|
|
139
108
|
static void wsetlab_end(struct generator * g) {
|
140
|
-
|
141
109
|
w(g, "~-~M}~N");
|
142
110
|
}
|
143
111
|
|
144
112
|
static void wgotol(struct generator * g, int n) {
|
145
|
-
|
146
113
|
write_margin(g);
|
147
114
|
write_string(g, "break lab");
|
148
115
|
write_int(g, n);
|
@@ -151,7 +118,6 @@ static void wgotol(struct generator * g, int n) {
|
|
151
118
|
}
|
152
119
|
|
153
120
|
static void write_failure(struct generator * g) {
|
154
|
-
|
155
121
|
if (str_len(g->failure_str) != 0) {
|
156
122
|
write_margin(g);
|
157
123
|
write_str(g, g->failure_str);
|
@@ -172,8 +138,7 @@ static void write_failure(struct generator * g) {
|
|
172
138
|
write_newline(g);
|
173
139
|
}
|
174
140
|
|
175
|
-
static void write_failure_if(struct generator * g, char * s, struct node * p) {
|
176
|
-
|
141
|
+
static void write_failure_if(struct generator * g, const char * s, struct node * p) {
|
177
142
|
writef(g, "~Mif (", p);
|
178
143
|
writef(g, s, p);
|
179
144
|
writef(g, ")~N", p);
|
@@ -185,7 +150,6 @@ static void write_failure_if(struct generator * g, char * s, struct node * p) {
|
|
185
150
|
|
186
151
|
/* if at limit fail */
|
187
152
|
static void write_check_limit(struct generator * g, struct node * p) {
|
188
|
-
|
189
153
|
if (p->mode == m_forward) {
|
190
154
|
write_failure_if(g, "base.cursor >= base.limit", p);
|
191
155
|
} else {
|
@@ -195,18 +159,18 @@ static void write_check_limit(struct generator * g, struct node * p) {
|
|
195
159
|
|
196
160
|
/* Formatted write. */
|
197
161
|
static void writef(struct generator * g, const char * input, struct node * p) {
|
162
|
+
(void)p;
|
198
163
|
int i = 0;
|
199
|
-
int l = strlen(input);
|
200
164
|
|
201
|
-
while (i
|
165
|
+
while (input[i]) {
|
202
166
|
int ch = input[i++];
|
203
167
|
if (ch != '~') {
|
204
168
|
write_char(g, ch);
|
205
169
|
continue;
|
206
170
|
}
|
207
|
-
|
208
|
-
|
209
|
-
case '
|
171
|
+
ch = input[i++];
|
172
|
+
switch (ch) {
|
173
|
+
case '~': write_char(g, '~'); continue;
|
210
174
|
case 'f': write_block_start(g);
|
211
175
|
write_failure(g);
|
212
176
|
g->unreachable = false;
|
@@ -216,22 +180,82 @@ static void writef(struct generator * g, const char * input, struct node * p) {
|
|
216
180
|
case 'N': write_newline(g); continue;
|
217
181
|
case '{': write_block_start(g); continue;
|
218
182
|
case '}': write_block_end(g); continue;
|
219
|
-
case 'S':
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
183
|
+
case 'S': {
|
184
|
+
int j = input[i++] - '0';
|
185
|
+
if (j < 0 || j > (int)(sizeof(g->S) / sizeof(g->S[0]))) {
|
186
|
+
printf("Invalid escape sequence ~%c%c in writef(g, \"%s\", p)\n",
|
187
|
+
ch, input[i - 1], input);
|
188
|
+
exit(1);
|
189
|
+
}
|
190
|
+
write_string(g, g->S[j]);
|
191
|
+
continue;
|
192
|
+
}
|
193
|
+
case 'B': {
|
194
|
+
int j = input[i++] - '0';
|
195
|
+
if (j < 0 || j > (int)(sizeof(g->B) / sizeof(g->B[0])))
|
196
|
+
goto invalid_escape2;
|
197
|
+
write_s(g, g->B[j]);
|
198
|
+
continue;
|
199
|
+
}
|
200
|
+
case 'I': {
|
201
|
+
int j = input[i++] - '0';
|
202
|
+
if (j < 0 || j > (int)(sizeof(g->I) / sizeof(g->I[0])))
|
203
|
+
goto invalid_escape2;
|
204
|
+
write_int(g, g->I[j]);
|
205
|
+
continue;
|
206
|
+
}
|
207
|
+
case 'V':
|
208
|
+
case 'W': {
|
209
|
+
int j = input[i++] - '0';
|
210
|
+
if (j < 0 || j > (int)(sizeof(g->V) / sizeof(g->V[0])))
|
211
|
+
goto invalid_escape2;
|
212
|
+
if (ch == 'V')
|
213
|
+
write_varref(g, g->V[j]);
|
214
|
+
else
|
215
|
+
write_varname(g, g->V[j]);
|
216
|
+
continue;
|
217
|
+
}
|
218
|
+
case 'L': {
|
219
|
+
int j = input[i++] - '0';
|
220
|
+
if (j < 0 || j > (int)(sizeof(g->L) / sizeof(g->L[0])))
|
221
|
+
goto invalid_escape2;
|
222
|
+
write_literal_string(g, g->L[j]);
|
223
|
+
continue;
|
224
|
+
}
|
225
225
|
case '+': g->margin++; continue;
|
226
226
|
case '-': g->margin--; continue;
|
227
227
|
case 'n': write_string(g, g->options->name); continue;
|
228
228
|
case 'P': write_string(g, g->options->parent_class_name); continue;
|
229
|
+
case 'C': { // Constant.
|
230
|
+
if (g->options->js_esm) {
|
231
|
+
w(g, "const");
|
232
|
+
} else {
|
233
|
+
w(g, "/** @const */ var");
|
234
|
+
}
|
235
|
+
continue;
|
236
|
+
}
|
237
|
+
case 'D': { // Declare variable.
|
238
|
+
if (g->options->js_esm) {
|
239
|
+
w(g, "let");
|
240
|
+
} else {
|
241
|
+
w(g, "var");
|
242
|
+
}
|
243
|
+
continue;
|
244
|
+
}
|
245
|
+
default:
|
246
|
+
printf("Invalid escape sequence ~%c in writef(g, \"%s\", p)\n",
|
247
|
+
ch, input);
|
248
|
+
exit(1);
|
249
|
+
invalid_escape2:
|
250
|
+
printf("Invalid escape sequence ~%c%c in writef(g, \"%s\", p)\n",
|
251
|
+
ch, input[i - 1], input);
|
252
|
+
exit(1);
|
229
253
|
}
|
230
254
|
}
|
231
255
|
}
|
232
256
|
|
233
257
|
static void w(struct generator * g, const char * s) {
|
234
|
-
writef(g, s,
|
258
|
+
writef(g, s, NULL);
|
235
259
|
}
|
236
260
|
|
237
261
|
static void generate_AE(struct generator * g, struct node * p) {
|
@@ -283,7 +307,6 @@ static void generate_AE(struct generator * g, struct node * p) {
|
|
283
307
|
}
|
284
308
|
|
285
309
|
static void generate_bra(struct generator * g, struct node * p) {
|
286
|
-
|
287
310
|
write_comment(g, p);
|
288
311
|
p = p->left;
|
289
312
|
while (p) {
|
@@ -293,28 +316,33 @@ static void generate_bra(struct generator * g, struct node * p) {
|
|
293
316
|
}
|
294
317
|
|
295
318
|
static void generate_and(struct generator * g, struct node * p) {
|
296
|
-
|
297
|
-
|
298
|
-
|
319
|
+
struct str * savevar = NULL;
|
320
|
+
if (K_needed(g, p->left)) {
|
321
|
+
savevar = vars_newname(g);
|
322
|
+
}
|
299
323
|
|
300
324
|
write_comment(g, p);
|
301
325
|
|
302
|
-
if (
|
326
|
+
if (savevar) write_savecursor(g, p, savevar);
|
303
327
|
|
304
328
|
p = p->left;
|
305
329
|
while (p) {
|
306
330
|
generate(g, p);
|
307
331
|
if (g->unreachable) break;
|
308
|
-
if (
|
332
|
+
if (savevar && p->right != NULL) write_restorecursor(g, p, savevar);
|
309
333
|
p = p->right;
|
310
334
|
}
|
311
|
-
|
335
|
+
|
336
|
+
if (savevar) {
|
337
|
+
str_delete(savevar);
|
338
|
+
}
|
312
339
|
}
|
313
340
|
|
314
341
|
static void generate_or(struct generator * g, struct node * p) {
|
315
|
-
|
316
|
-
|
317
|
-
|
342
|
+
struct str * savevar = NULL;
|
343
|
+
if (K_needed(g, p->left)) {
|
344
|
+
savevar = vars_newname(g);
|
345
|
+
}
|
318
346
|
|
319
347
|
int a0 = g->failure_label;
|
320
348
|
struct str * a1 = str_copy(g->failure_str);
|
@@ -325,18 +353,18 @@ static void generate_or(struct generator * g, struct node * p) {
|
|
325
353
|
write_comment(g, p);
|
326
354
|
wsetlab_begin(g, out_lab);
|
327
355
|
|
328
|
-
if (
|
356
|
+
if (savevar) write_savecursor(g, p, savevar);
|
329
357
|
|
330
358
|
p = p->left;
|
331
359
|
str_clear(g->failure_str);
|
332
360
|
|
333
|
-
if (p ==
|
334
|
-
/* p should never be
|
361
|
+
if (p == NULL) {
|
362
|
+
/* p should never be NULL after an or: there should be at least two
|
335
363
|
* sub nodes. */
|
336
364
|
fprintf(stderr, "Error: \"or\" node without children nodes.");
|
337
365
|
exit(1);
|
338
366
|
}
|
339
|
-
while (p->right !=
|
367
|
+
while (p->right != NULL) {
|
340
368
|
g->failure_label = new_label(g);
|
341
369
|
wsetlab_begin(g, g->failure_label);
|
342
370
|
generate(g, p);
|
@@ -346,7 +374,7 @@ static void generate_or(struct generator * g, struct node * p) {
|
|
346
374
|
}
|
347
375
|
wsetlab_end(g);
|
348
376
|
g->unreachable = false;
|
349
|
-
if (
|
377
|
+
if (savevar) write_restorecursor(g, p, savevar);
|
350
378
|
p = p->right;
|
351
379
|
}
|
352
380
|
|
@@ -359,11 +387,13 @@ static void generate_or(struct generator * g, struct node * p) {
|
|
359
387
|
if (!end_unreachable) {
|
360
388
|
g->unreachable = false;
|
361
389
|
}
|
362
|
-
|
390
|
+
|
391
|
+
if (savevar) {
|
392
|
+
str_delete(savevar);
|
393
|
+
}
|
363
394
|
}
|
364
395
|
|
365
396
|
static void generate_backwards(struct generator * g, struct node * p) {
|
366
|
-
|
367
397
|
write_comment(g, p);
|
368
398
|
writef(g, "~Mbase.limit_backward = base.cursor; base.cursor = base.limit;~N", p);
|
369
399
|
generate(g, p->left);
|
@@ -372,15 +402,16 @@ static void generate_backwards(struct generator * g, struct node * p) {
|
|
372
402
|
|
373
403
|
|
374
404
|
static void generate_not(struct generator * g, struct node * p) {
|
375
|
-
|
376
|
-
|
377
|
-
|
405
|
+
struct str * savevar = NULL;
|
406
|
+
if (K_needed(g, p->left)) {
|
407
|
+
savevar = vars_newname(g);
|
408
|
+
}
|
378
409
|
|
379
410
|
int a0 = g->failure_label;
|
380
411
|
struct str * a1 = str_copy(g->failure_str);
|
381
412
|
|
382
413
|
write_comment(g, p);
|
383
|
-
if (
|
414
|
+
if (savevar) {
|
384
415
|
write_block_start(g);
|
385
416
|
write_savecursor(g, p, savevar);
|
386
417
|
}
|
@@ -401,48 +432,52 @@ static void generate_not(struct generator * g, struct node * p) {
|
|
401
432
|
wsetlab_end(g);
|
402
433
|
g->unreachable = false;
|
403
434
|
|
404
|
-
if (
|
405
|
-
|
406
|
-
|
435
|
+
if (savevar) {
|
436
|
+
write_restorecursor(g, p, savevar);
|
437
|
+
write_block_end(g);
|
438
|
+
str_delete(savevar);
|
439
|
+
}
|
407
440
|
}
|
408
441
|
|
409
442
|
|
410
443
|
static void generate_try(struct generator * g, struct node * p) {
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
write_comment(g, p);
|
416
|
-
if (keep_c) write_savecursor(g, p, savevar);
|
444
|
+
struct str * savevar = NULL;
|
445
|
+
if (K_needed(g, p->left)) {
|
446
|
+
savevar = vars_newname(g);
|
447
|
+
}
|
417
448
|
|
418
449
|
g->failure_label = new_label(g);
|
419
450
|
str_clear(g->failure_str);
|
420
|
-
|
451
|
+
|
452
|
+
write_comment(g, p);
|
453
|
+
if (savevar) {
|
454
|
+
write_savecursor(g, p, savevar);
|
455
|
+
append_restore_string(p, g->failure_str, savevar);
|
456
|
+
}
|
421
457
|
|
422
458
|
wsetlab_begin(g, g->failure_label);
|
423
459
|
generate(g, p->left);
|
424
460
|
wsetlab_end(g);
|
425
461
|
g->unreachable = false;
|
426
462
|
|
427
|
-
|
463
|
+
if (savevar) {
|
464
|
+
str_delete(savevar);
|
465
|
+
}
|
428
466
|
}
|
429
467
|
|
430
468
|
static void generate_set(struct generator * g, struct node * p) {
|
431
|
-
|
432
469
|
write_comment(g, p);
|
433
470
|
g->V[0] = p->name;
|
434
471
|
writef(g, "~M~V0 = true;~N", p);
|
435
472
|
}
|
436
473
|
|
437
474
|
static void generate_unset(struct generator * g, struct node * p) {
|
438
|
-
|
439
475
|
write_comment(g, p);
|
440
476
|
g->V[0] = p->name;
|
441
477
|
writef(g, "~M~V0 = false;~N", p);
|
442
478
|
}
|
443
479
|
|
444
480
|
static void generate_fail(struct generator * g, struct node * p) {
|
445
|
-
|
446
481
|
write_comment(g, p);
|
447
482
|
generate(g, p->left);
|
448
483
|
if (!g->unreachable) write_failure(g);
|
@@ -451,32 +486,35 @@ static void generate_fail(struct generator * g, struct node * p) {
|
|
451
486
|
/* generate_test() also implements 'reverse' */
|
452
487
|
|
453
488
|
static void generate_test(struct generator * g, struct node * p) {
|
454
|
-
|
455
|
-
|
456
|
-
|
489
|
+
struct str * savevar = NULL;
|
490
|
+
if (K_needed(g, p->left)) {
|
491
|
+
savevar = vars_newname(g);
|
492
|
+
}
|
457
493
|
|
458
494
|
write_comment(g, p);
|
459
495
|
|
460
|
-
if (
|
496
|
+
if (savevar) {
|
461
497
|
write_savecursor(g, p, savevar);
|
462
498
|
}
|
463
499
|
|
464
500
|
generate(g, p->left);
|
465
501
|
|
466
|
-
if (
|
467
|
-
if (
|
502
|
+
if (savevar) {
|
503
|
+
if (!g->unreachable) {
|
468
504
|
write_restorecursor(g, p, savevar);
|
469
505
|
}
|
506
|
+
str_delete(savevar);
|
470
507
|
}
|
471
|
-
str_delete(savevar);
|
472
508
|
}
|
473
509
|
|
474
510
|
static void generate_do(struct generator * g, struct node * p) {
|
511
|
+
struct str * savevar = NULL;
|
512
|
+
if (K_needed(g, p->left)) {
|
513
|
+
savevar = vars_newname(g);
|
514
|
+
}
|
475
515
|
|
476
|
-
struct str * savevar = vars_newname(g);
|
477
|
-
int keep_c = K_needed(g, p->left);
|
478
516
|
write_comment(g, p);
|
479
|
-
if (
|
517
|
+
if (savevar) write_savecursor(g, p, savevar);
|
480
518
|
|
481
519
|
if (p->left->type == c_call) {
|
482
520
|
/* Optimise do <call> */
|
@@ -493,26 +531,53 @@ static void generate_do(struct generator * g, struct node * p) {
|
|
493
531
|
g->unreachable = false;
|
494
532
|
}
|
495
533
|
|
496
|
-
if (
|
497
|
-
|
534
|
+
if (savevar) {
|
535
|
+
write_restorecursor(g, p, savevar);
|
536
|
+
str_delete(savevar);
|
537
|
+
}
|
498
538
|
}
|
499
539
|
|
500
|
-
static void
|
540
|
+
static void generate_next(struct generator * g, struct node * p) {
|
541
|
+
write_comment(g, p);
|
542
|
+
write_check_limit(g, p);
|
543
|
+
write_inc_cursor(g, p);
|
544
|
+
}
|
501
545
|
|
502
|
-
|
503
|
-
|
504
|
-
|
546
|
+
static void generate_GO_grouping(struct generator * g, struct node * p, int is_goto, int complement) {
|
547
|
+
write_comment(g, p);
|
548
|
+
|
549
|
+
struct grouping * q = p->name->grouping;
|
550
|
+
g->S[0] = p->mode == m_forward ? "" : "_b";
|
551
|
+
g->S[1] = complement ? "in" : "out";
|
552
|
+
g->V[0] = p->name;
|
553
|
+
g->I[0] = q->smallest_ch;
|
554
|
+
g->I[1] = q->largest_ch;
|
555
|
+
write_failure_if(g, "!base.go_~S1_grouping~S0(~V0, ~I0, ~I1)", p);
|
556
|
+
if (!is_goto) {
|
557
|
+
if (p->mode == m_forward)
|
558
|
+
w(g, "~Mbase.cursor++;~N");
|
559
|
+
else
|
560
|
+
w(g, "~Mbase.cursor--;~N");
|
561
|
+
}
|
562
|
+
}
|
563
|
+
|
564
|
+
static void generate_GO(struct generator * g, struct node * p, int style) {
|
565
|
+
write_comment(g, p);
|
505
566
|
|
506
567
|
int a0 = g->failure_label;
|
507
568
|
struct str * a1 = str_copy(g->failure_str);
|
508
569
|
|
570
|
+
int end_unreachable = false;
|
509
571
|
int golab = new_label(g);
|
510
572
|
g->I[0] = golab;
|
511
|
-
write_comment(g, p);
|
512
573
|
w(g, "~Mgolab~I0: while(true)~N");
|
513
574
|
w(g, "~{");
|
514
575
|
|
515
|
-
|
576
|
+
struct str * savevar = NULL;
|
577
|
+
if (style == 1 || repeat_restore(g, p->left)) {
|
578
|
+
savevar = vars_newname(g);
|
579
|
+
write_savecursor(g, p, savevar);
|
580
|
+
}
|
516
581
|
|
517
582
|
g->failure_label = new_label(g);
|
518
583
|
str_clear(g->failure_str);
|
@@ -531,7 +596,10 @@ static void generate_GO(struct generator * g, struct node * p, int style) {
|
|
531
596
|
}
|
532
597
|
g->unreachable = false;
|
533
598
|
wsetlab_end(g);
|
534
|
-
if (
|
599
|
+
if (savevar) {
|
600
|
+
write_restorecursor(g, p, savevar);
|
601
|
+
str_delete(savevar);
|
602
|
+
}
|
535
603
|
|
536
604
|
g->failure_label = a0;
|
537
605
|
str_delete(g->failure_str);
|
@@ -540,16 +608,14 @@ static void generate_GO(struct generator * g, struct node * p, int style) {
|
|
540
608
|
write_check_limit(g, p);
|
541
609
|
write_inc_cursor(g, p);
|
542
610
|
write_block_end(g);
|
543
|
-
str_delete(savevar);
|
544
611
|
g->unreachable = end_unreachable;
|
545
612
|
}
|
546
613
|
|
547
614
|
static void generate_loop(struct generator * g, struct node * p) {
|
548
|
-
|
549
615
|
struct str * loopvar = vars_newname(g);
|
550
616
|
write_comment(g, p);
|
551
617
|
g->B[0] = str_data(loopvar);
|
552
|
-
w(g, "~Mfor (
|
618
|
+
w(g, "~Mfor (~D /** number */ ~B0 = ");
|
553
619
|
generate_AE(g, p->AE);
|
554
620
|
g->B[0] = str_data(loopvar);
|
555
621
|
writef(g, "; ~B0 > 0; ~B0--)~N", p);
|
@@ -563,12 +629,13 @@ static void generate_loop(struct generator * g, struct node * p) {
|
|
563
629
|
}
|
564
630
|
|
565
631
|
static void generate_repeat_or_atleast(struct generator * g, struct node * p, struct str * loopvar) {
|
566
|
-
|
567
|
-
struct str * savevar = vars_newname(g);
|
568
|
-
int keep_c = repeat_restore(g, p->left);
|
569
632
|
writef(g, "~Mwhile(true)~N~{", p);
|
570
633
|
|
571
|
-
|
634
|
+
struct str * savevar = NULL;
|
635
|
+
if (repeat_restore(g, p->left)) {
|
636
|
+
savevar = vars_newname(g);
|
637
|
+
write_savecursor(g, p, savevar);
|
638
|
+
}
|
572
639
|
|
573
640
|
g->failure_label = new_label(g);
|
574
641
|
str_clear(g->failure_str);
|
@@ -576,7 +643,7 @@ static void generate_repeat_or_atleast(struct generator * g, struct node * p, st
|
|
576
643
|
generate(g, p->left);
|
577
644
|
|
578
645
|
if (!g->unreachable) {
|
579
|
-
if (loopvar !=
|
646
|
+
if (loopvar != NULL) {
|
580
647
|
g->B[0] = str_data(loopvar);
|
581
648
|
w(g, "~M~B0--;~N");
|
582
649
|
}
|
@@ -587,10 +654,12 @@ static void generate_repeat_or_atleast(struct generator * g, struct node * p, st
|
|
587
654
|
wsetlab_end(g);
|
588
655
|
g->unreachable = false;
|
589
656
|
|
590
|
-
if (
|
657
|
+
if (savevar) {
|
658
|
+
write_restorecursor(g, p, savevar);
|
659
|
+
str_delete(savevar);
|
660
|
+
}
|
591
661
|
|
592
662
|
w(g, "~Mbreak;~N~}");
|
593
|
-
str_delete(savevar);
|
594
663
|
}
|
595
664
|
|
596
665
|
static void generate_repeat(struct generator * g, struct node * p) {
|
@@ -599,12 +668,12 @@ static void generate_repeat(struct generator * g, struct node * p) {
|
|
599
668
|
}
|
600
669
|
|
601
670
|
static void generate_atleast(struct generator * g, struct node * p) {
|
602
|
-
|
603
671
|
struct str * loopvar = vars_newname(g);
|
672
|
+
|
604
673
|
write_comment(g, p);
|
605
674
|
w(g, "~{");
|
606
675
|
g->B[0] = str_data(loopvar);
|
607
|
-
w(g, "~
|
676
|
+
w(g, "~M~D ~B0 = ");
|
608
677
|
generate_AE(g, p->AE);
|
609
678
|
w(g, ";~N");
|
610
679
|
{
|
@@ -624,14 +693,12 @@ static void generate_atleast(struct generator * g, struct node * p) {
|
|
624
693
|
}
|
625
694
|
|
626
695
|
static void generate_setmark(struct generator * g, struct node * p) {
|
627
|
-
|
628
696
|
write_comment(g, p);
|
629
697
|
g->V[0] = p->name;
|
630
698
|
writef(g, "~M~V0 = base.cursor;~N", p);
|
631
699
|
}
|
632
700
|
|
633
701
|
static void generate_tomark(struct generator * g, struct node * p) {
|
634
|
-
|
635
702
|
write_comment(g, p);
|
636
703
|
g->S[0] = p->mode == m_forward ? ">" : "<";
|
637
704
|
|
@@ -644,7 +711,6 @@ static void generate_tomark(struct generator * g, struct node * p) {
|
|
644
711
|
}
|
645
712
|
|
646
713
|
static void generate_atmark(struct generator * g, struct node * p) {
|
647
|
-
|
648
714
|
write_comment(g, p);
|
649
715
|
w(g, "~Mif (base.cursor != "); generate_AE(g, p->AE); writef(g, ")~N", p);
|
650
716
|
write_block_start(g);
|
@@ -659,7 +725,7 @@ static void generate_hop(struct generator * g, struct node * p) {
|
|
659
725
|
g->S[0] = p->mode == m_forward ? "+" : "-";
|
660
726
|
|
661
727
|
g->I[0] = c_count;
|
662
|
-
w(g, "~{~
|
728
|
+
w(g, "~{~M~C /** number */ c~I0 = base.cursor ~S0 ");
|
663
729
|
generate_AE(g, p->AE);
|
664
730
|
w(g, ";~N");
|
665
731
|
|
@@ -680,7 +746,6 @@ static void generate_hop(struct generator * g, struct node * p) {
|
|
680
746
|
}
|
681
747
|
|
682
748
|
static void generate_delete(struct generator * g, struct node * p) {
|
683
|
-
|
684
749
|
write_comment(g, p);
|
685
750
|
writef(g, "~Mif (!base.slice_del())~N"
|
686
751
|
"~M{~N"
|
@@ -688,16 +753,7 @@ static void generate_delete(struct generator * g, struct node * p) {
|
|
688
753
|
"~M}~N", p);
|
689
754
|
}
|
690
755
|
|
691
|
-
|
692
|
-
static void generate_next(struct generator * g, struct node * p) {
|
693
|
-
|
694
|
-
write_comment(g, p);
|
695
|
-
write_check_limit(g, p);
|
696
|
-
write_inc_cursor(g, p);
|
697
|
-
}
|
698
|
-
|
699
756
|
static void generate_tolimit(struct generator * g, struct node * p) {
|
700
|
-
|
701
757
|
write_comment(g, p);
|
702
758
|
if (p->mode == m_forward) {
|
703
759
|
writef(g, "~Mbase.cursor = base.limit;~N", p);
|
@@ -707,7 +763,6 @@ static void generate_tolimit(struct generator * g, struct node * p) {
|
|
707
763
|
}
|
708
764
|
|
709
765
|
static void generate_atlimit(struct generator * g, struct node * p) {
|
710
|
-
|
711
766
|
write_comment(g, p);
|
712
767
|
if (p->mode == m_forward) {
|
713
768
|
write_failure_if(g, "base.cursor < base.limit", p);
|
@@ -717,7 +772,6 @@ static void generate_atlimit(struct generator * g, struct node * p) {
|
|
717
772
|
}
|
718
773
|
|
719
774
|
static void generate_leftslice(struct generator * g, struct node * p) {
|
720
|
-
|
721
775
|
write_comment(g, p);
|
722
776
|
if (p->mode == m_forward) {
|
723
777
|
writef(g, "~Mbase.bra = base.cursor;~N", p);
|
@@ -727,7 +781,6 @@ static void generate_leftslice(struct generator * g, struct node * p) {
|
|
727
781
|
}
|
728
782
|
|
729
783
|
static void generate_rightslice(struct generator * g, struct node * p) {
|
730
|
-
|
731
784
|
write_comment(g, p);
|
732
785
|
if (p->mode == m_forward) {
|
733
786
|
writef(g, "~Mbase.ket = base.cursor;~N", p);
|
@@ -737,14 +790,12 @@ static void generate_rightslice(struct generator * g, struct node * p) {
|
|
737
790
|
}
|
738
791
|
|
739
792
|
static void generate_assignto(struct generator * g, struct node * p) {
|
740
|
-
|
741
793
|
write_comment(g, p);
|
742
794
|
g->V[0] = p->name;
|
743
795
|
writef(g, "~M~V0 = base.assign_to();~N", p);
|
744
796
|
}
|
745
797
|
|
746
798
|
static void generate_sliceto(struct generator * g, struct node * p) {
|
747
|
-
|
748
799
|
write_comment(g, p);
|
749
800
|
g->V[0] = p->name;
|
750
801
|
writef(g, "~M~V0 = base.slice_to();~N"
|
@@ -755,9 +806,8 @@ static void generate_sliceto(struct generator * g, struct node * p) {
|
|
755
806
|
}
|
756
807
|
|
757
808
|
static void generate_address(struct generator * g, struct node * p) {
|
758
|
-
|
759
809
|
symbol * b = p->literalstring;
|
760
|
-
if (b !=
|
810
|
+
if (b != NULL) {
|
761
811
|
write_literal_string(g, b);
|
762
812
|
} else {
|
763
813
|
write_varref(g, p->name);
|
@@ -772,7 +822,7 @@ static void generate_insert(struct generator * g, struct node * p, int style) {
|
|
772
822
|
if (keep_c) {
|
773
823
|
c_count = ++g->keep_count;
|
774
824
|
g->I[0] = c_count;
|
775
|
-
w(g, "~{~
|
825
|
+
w(g, "~{~M~C /** number */ c~I0 = base.cursor;~N");
|
776
826
|
}
|
777
827
|
writef(g, "~Mbase.insert(base.cursor, base.cursor, ", p);
|
778
828
|
generate_address(g, p);
|
@@ -791,7 +841,7 @@ static void generate_assignfrom(struct generator * g, struct node * p) {
|
|
791
841
|
if (keep_c) {
|
792
842
|
c_count = ++g->keep_count;
|
793
843
|
g->I[0] = c_count;
|
794
|
-
w(g, "~{~
|
844
|
+
w(g, "~{~M~C /** number */ c~I0 = base.cursor;~N");
|
795
845
|
}
|
796
846
|
if (p->mode == m_forward) {
|
797
847
|
writef(g, "~Mbase.insert(base.cursor, base.limit, ", p);
|
@@ -806,9 +856,7 @@ static void generate_assignfrom(struct generator * g, struct node * p) {
|
|
806
856
|
}
|
807
857
|
}
|
808
858
|
|
809
|
-
|
810
859
|
static void generate_slicefrom(struct generator * g, struct node * p) {
|
811
|
-
|
812
860
|
write_comment(g, p);
|
813
861
|
w(g, "~Mif (!base.slice_from(");
|
814
862
|
generate_address(g, p);
|
@@ -819,7 +867,6 @@ static void generate_slicefrom(struct generator * g, struct node * p) {
|
|
819
867
|
}
|
820
868
|
|
821
869
|
static void generate_setlimit(struct generator * g, struct node * p) {
|
822
|
-
struct str * savevar = vars_newname(g);
|
823
870
|
struct str * varname = vars_newname(g);
|
824
871
|
write_comment(g, p);
|
825
872
|
if (p->left && p->left->type == c_tomark) {
|
@@ -832,6 +879,7 @@ static void generate_setlimit(struct generator * g, struct node * p) {
|
|
832
879
|
* restore c.
|
833
880
|
*/
|
834
881
|
struct node * q = p->left;
|
882
|
+
write_comment(g, q);
|
835
883
|
g->S[0] = q->mode == m_forward ? ">" : "<";
|
836
884
|
w(g, "~Mif (base.cursor ~S0 "); generate_AE(g, q->AE); w(g, ")~N");
|
837
885
|
write_block_start(g);
|
@@ -840,7 +888,7 @@ static void generate_setlimit(struct generator * g, struct node * p) {
|
|
840
888
|
g->unreachable = false;
|
841
889
|
|
842
890
|
g->B[0] = str_data(varname);
|
843
|
-
w(g, "~
|
891
|
+
w(g, "~M~C /** number */ ~B0 = ");
|
844
892
|
if (p->mode == m_forward) {
|
845
893
|
w(g, "base.limit - base.cursor;~N");
|
846
894
|
w(g, "~Mbase.limit = ");
|
@@ -860,12 +908,14 @@ static void generate_setlimit(struct generator * g, struct node * p) {
|
|
860
908
|
str_append_ch(g->failure_str, ';');
|
861
909
|
}
|
862
910
|
} else {
|
911
|
+
struct str * savevar = vars_newname(g);
|
863
912
|
write_savecursor(g, p, savevar);
|
913
|
+
|
864
914
|
generate(g, p->left);
|
865
915
|
|
866
916
|
if (!g->unreachable) {
|
867
917
|
g->B[0] = str_data(varname);
|
868
|
-
w(g, "~
|
918
|
+
w(g, "~M~C /** number */ ~B0 = ");
|
869
919
|
if (p->mode == m_forward) {
|
870
920
|
w(g, "base.limit - base.cursor;~N");
|
871
921
|
w(g, "~Mbase.limit = base.cursor;~N");
|
@@ -885,6 +935,7 @@ static void generate_setlimit(struct generator * g, struct node * p) {
|
|
885
935
|
str_append_ch(g->failure_str, ';');
|
886
936
|
}
|
887
937
|
}
|
938
|
+
str_delete(savevar);
|
888
939
|
}
|
889
940
|
|
890
941
|
if (!g->unreachable) {
|
@@ -897,17 +948,17 @@ static void generate_setlimit(struct generator * g, struct node * p) {
|
|
897
948
|
}
|
898
949
|
}
|
899
950
|
str_delete(varname);
|
900
|
-
str_delete(savevar);
|
901
951
|
}
|
902
952
|
|
903
953
|
/* dollar sets snowball up to operate on a string variable as if it were the
|
904
954
|
* current string */
|
905
955
|
static void generate_dollar(struct generator * g, struct node * p) {
|
956
|
+
write_comment(g, p);
|
906
957
|
|
907
958
|
struct str * savevar = vars_newname(g);
|
908
959
|
g->B[0] = str_data(savevar);
|
909
|
-
writef(g, "~{~
|
910
|
-
"~
|
960
|
+
writef(g, "~{~N"
|
961
|
+
"~M~D /** !Object */ ~B0 = new ~P();~N", p);
|
911
962
|
writef(g, "~M~B0.copy_from(base);~N", p);
|
912
963
|
|
913
964
|
++g->copy_from_count;
|
@@ -931,36 +982,66 @@ static void generate_dollar(struct generator * g, struct node * p) {
|
|
931
982
|
str_delete(savevar);
|
932
983
|
}
|
933
984
|
|
934
|
-
static void generate_integer_assign(struct generator * g, struct node * p, char * s) {
|
935
|
-
|
985
|
+
static void generate_integer_assign(struct generator * g, struct node * p, const char * s) {
|
986
|
+
write_comment(g, p);
|
936
987
|
g->V[0] = p->name;
|
937
988
|
g->S[0] = s;
|
938
|
-
w(g, "~M~V0 ~S0 ");
|
989
|
+
w(g, "~M~V0 ~S0 ");
|
990
|
+
generate_AE(g, p->AE);
|
991
|
+
w(g, ";~N");
|
939
992
|
}
|
940
993
|
|
941
|
-
static void generate_integer_test(struct generator * g, struct node * p
|
942
|
-
|
943
|
-
|
994
|
+
static void generate_integer_test(struct generator * g, struct node * p) {
|
995
|
+
write_comment(g, p);
|
996
|
+
int relop = p->type;
|
997
|
+
int optimise_to_return = (g->failure_label == x_return && p->right && p->right->type == c_functionend);
|
998
|
+
if (optimise_to_return) {
|
999
|
+
w(g, "~Mreturn ");
|
1000
|
+
p->right = NULL;
|
1001
|
+
} else {
|
1002
|
+
w(g, "~Mif (");
|
1003
|
+
// We want the inverse of the snowball test here.
|
1004
|
+
relop ^= 1;
|
1005
|
+
}
|
944
1006
|
generate_AE(g, p->left);
|
945
|
-
|
946
|
-
|
947
|
-
write_char(g, ' ');
|
1007
|
+
// Relational operators are the same as C.
|
1008
|
+
write_c_relop(g, relop);
|
948
1009
|
generate_AE(g, p->AE);
|
949
|
-
|
950
|
-
|
951
|
-
|
952
|
-
|
953
|
-
|
1010
|
+
if (optimise_to_return) {
|
1011
|
+
w(g, ";~N");
|
1012
|
+
} else {
|
1013
|
+
w(g, ")~N");
|
1014
|
+
write_block_start(g);
|
1015
|
+
write_failure(g);
|
1016
|
+
write_block_end(g);
|
1017
|
+
g->unreachable = false;
|
1018
|
+
}
|
954
1019
|
}
|
955
1020
|
|
956
1021
|
static void generate_call(struct generator * g, struct node * p) {
|
957
|
-
|
1022
|
+
int signals = check_possible_signals_list(g, p->name->definition, c_define, 0);
|
958
1023
|
write_comment(g, p);
|
959
1024
|
g->V[0] = p->name;
|
960
|
-
|
1025
|
+
if (g->failure_label == x_return &&
|
1026
|
+
(signals == 0 || (p->right && p->right->type == c_functionend))) {
|
1027
|
+
/* Always fails or tail call. */
|
1028
|
+
writef(g, "~Mreturn ~V0();~N", p);
|
1029
|
+
return;
|
1030
|
+
}
|
1031
|
+
if (signals == 1) {
|
1032
|
+
/* Always succeeds. */
|
1033
|
+
writef(g, "~M~V0();~N", p);
|
1034
|
+
} else if (signals == 0) {
|
1035
|
+
/* Always fails. */
|
1036
|
+
writef(g, "~M~V0();~N", p);
|
1037
|
+
write_failure(g);
|
1038
|
+
} else {
|
1039
|
+
write_failure_if(g, "!~V0()", p);
|
1040
|
+
}
|
961
1041
|
}
|
962
1042
|
|
963
1043
|
static void generate_grouping(struct generator * g, struct node * p, int complement) {
|
1044
|
+
write_comment(g, p);
|
964
1045
|
|
965
1046
|
struct grouping * q = p->name->grouping;
|
966
1047
|
g->S[0] = p->mode == m_forward ? "" : "_b";
|
@@ -972,7 +1053,6 @@ static void generate_grouping(struct generator * g, struct node * p, int complem
|
|
972
1053
|
}
|
973
1054
|
|
974
1055
|
static void generate_namedstring(struct generator * g, struct node * p) {
|
975
|
-
|
976
1056
|
write_comment(g, p);
|
977
1057
|
g->S[0] = p->mode == m_forward ? "" : "_b";
|
978
1058
|
g->V[0] = p->name;
|
@@ -989,18 +1069,22 @@ static void generate_literalstring(struct generator * g, struct node * p) {
|
|
989
1069
|
|
990
1070
|
static void generate_define(struct generator * g, struct node * p) {
|
991
1071
|
struct name * q = p->name;
|
1072
|
+
if (q->type == t_routine && !q->used) return;
|
992
1073
|
|
993
|
-
|
994
|
-
|
1074
|
+
write_newline(g);
|
1075
|
+
write_comment(g, p);
|
995
1076
|
|
996
1077
|
g->V[0] = q;
|
997
1078
|
if (q->type == t_routine) {
|
998
|
-
w(g, "~
|
1079
|
+
w(g, "~M/** @return {boolean} */~N"
|
999
1080
|
"~Mfunction ~W0() {~+~N");
|
1000
1081
|
} else {
|
1001
|
-
w(g, "~
|
1082
|
+
w(g, "~Mthis.~W0 = /** @return {boolean} */ function() {~+~N");
|
1002
1083
|
}
|
1003
1084
|
|
1085
|
+
/* Save output. */
|
1086
|
+
struct str * saved_output = g->outbuf;
|
1087
|
+
struct str * saved_declarations = g->declarations;
|
1004
1088
|
g->outbuf = str_new();
|
1005
1089
|
g->declarations = str_new();
|
1006
1090
|
|
@@ -1008,14 +1092,22 @@ static void generate_define(struct generator * g, struct node * p) {
|
|
1008
1092
|
g->var_number = 0;
|
1009
1093
|
|
1010
1094
|
if (p->amongvar_needed) {
|
1011
|
-
w(g, "~
|
1095
|
+
w(g, "~M~D /** number */ among_var;~N");
|
1012
1096
|
}
|
1013
1097
|
str_clear(g->failure_str);
|
1014
1098
|
g->failure_label = x_return;
|
1015
1099
|
g->unreachable = false;
|
1016
1100
|
g->keep_count = 0;
|
1101
|
+
int signals = check_possible_signals_list(g, p->left, c_define, 0);
|
1102
|
+
|
1103
|
+
/* Generate function body. */
|
1017
1104
|
generate(g, p->left);
|
1018
|
-
if (
|
1105
|
+
if (p->left->right) {
|
1106
|
+
assert(p->left->right->type == c_functionend);
|
1107
|
+
if (signals) {
|
1108
|
+
generate(g, p->left->right);
|
1109
|
+
}
|
1110
|
+
}
|
1019
1111
|
w(g, "~-~M};~N");
|
1020
1112
|
|
1021
1113
|
str_append(saved_output, g->declarations);
|
@@ -1026,38 +1118,46 @@ static void generate_define(struct generator * g, struct node * p) {
|
|
1026
1118
|
g->outbuf = saved_output;
|
1027
1119
|
}
|
1028
1120
|
|
1121
|
+
static void generate_functionend(struct generator * g, struct node * p) {
|
1122
|
+
(void)p;
|
1123
|
+
w(g, "~Mreturn true;~N");
|
1124
|
+
}
|
1125
|
+
|
1029
1126
|
static void generate_substring(struct generator * g, struct node * p) {
|
1127
|
+
write_comment(g, p);
|
1030
1128
|
|
1031
1129
|
struct among * x = p->among;
|
1032
1130
|
|
1033
|
-
write_comment(g, p);
|
1034
|
-
|
1035
1131
|
g->S[0] = p->mode == m_forward ? "" : "_b";
|
1036
1132
|
g->I[0] = x->number;
|
1037
1133
|
|
1038
|
-
if (
|
1039
|
-
write_failure_if(g, "base.find_among~S0(a_~I0) == 0", p);
|
1040
|
-
} else {
|
1134
|
+
if (x->amongvar_needed) {
|
1041
1135
|
writef(g, "~Mamong_var = base.find_among~S0(a_~I0);~N", p);
|
1042
|
-
|
1136
|
+
if (!x->always_matches) {
|
1137
|
+
write_failure_if(g, "among_var == 0", p);
|
1138
|
+
}
|
1139
|
+
} else if (x->always_matches) {
|
1140
|
+
writef(g, "~Mbase.find_among~S0(a_~I0);~N", p);
|
1141
|
+
} else {
|
1142
|
+
write_failure_if(g, "base.find_among~S0(a_~I0) == 0", p);
|
1043
1143
|
}
|
1044
1144
|
}
|
1045
1145
|
|
1046
1146
|
static void generate_among(struct generator * g, struct node * p) {
|
1047
|
-
|
1048
1147
|
struct among * x = p->among;
|
1049
1148
|
|
1050
|
-
if (x->substring ==
|
1051
|
-
|
1052
|
-
|
1149
|
+
if (x->substring == NULL) {
|
1150
|
+
generate_substring(g, p);
|
1151
|
+
} else {
|
1152
|
+
write_comment(g, p);
|
1153
|
+
}
|
1053
1154
|
|
1054
1155
|
if (x->command_count == 1 && x->nocommand_count == 0) {
|
1055
1156
|
/* Only one outcome ("no match" already handled). */
|
1056
1157
|
generate(g, x->commands[0]);
|
1057
1158
|
} else if (x->command_count > 0) {
|
1058
|
-
int i;
|
1059
1159
|
w(g, "~Mswitch (among_var) {~N~+");
|
1060
|
-
for (i = 1; i <= x->command_count; i++) {
|
1160
|
+
for (int i = 1; i <= x->command_count; i++) {
|
1061
1161
|
g->I[0] = i;
|
1062
1162
|
w(g, "~Mcase ~I0:~N~+");
|
1063
1163
|
generate(g, x->commands[i - 1]);
|
@@ -1070,20 +1170,17 @@ static void generate_among(struct generator * g, struct node * p) {
|
|
1070
1170
|
}
|
1071
1171
|
|
1072
1172
|
static void generate_booltest(struct generator * g, struct node * p) {
|
1073
|
-
|
1074
1173
|
write_comment(g, p);
|
1075
1174
|
g->V[0] = p->name;
|
1076
1175
|
write_failure_if(g, "!~V0", p);
|
1077
1176
|
}
|
1078
1177
|
|
1079
1178
|
static void generate_false(struct generator * g, struct node * p) {
|
1080
|
-
|
1081
1179
|
write_comment(g, p);
|
1082
1180
|
write_failure(g);
|
1083
1181
|
}
|
1084
1182
|
|
1085
1183
|
static void generate_debug(struct generator * g, struct node * p) {
|
1086
|
-
|
1087
1184
|
write_comment(g, p);
|
1088
1185
|
g->I[0] = g->debug_count++;
|
1089
1186
|
g->I[1] = p->line_number;
|
@@ -1091,14 +1188,10 @@ static void generate_debug(struct generator * g, struct node * p) {
|
|
1091
1188
|
}
|
1092
1189
|
|
1093
1190
|
static void generate(struct generator * g, struct node * p) {
|
1094
|
-
|
1095
|
-
int a0;
|
1096
|
-
struct str * a1;
|
1097
|
-
|
1098
1191
|
if (g->unreachable) return;
|
1099
1192
|
|
1100
|
-
a0 = g->failure_label;
|
1101
|
-
a1 = str_copy(g->failure_str);
|
1193
|
+
int a0 = g->failure_label;
|
1194
|
+
struct str * a1 = str_copy(g->failure_str);
|
1102
1195
|
|
1103
1196
|
switch (p->type) {
|
1104
1197
|
case c_define: generate_define(g, p); break;
|
@@ -1116,6 +1209,11 @@ static void generate(struct generator * g, struct node * p) {
|
|
1116
1209
|
case c_do: generate_do(g, p); break;
|
1117
1210
|
case c_goto: generate_GO(g, p, 1); break;
|
1118
1211
|
case c_gopast: generate_GO(g, p, 0); break;
|
1212
|
+
case c_goto_grouping: generate_GO_grouping(g, p, 1, 0); break;
|
1213
|
+
case c_gopast_grouping:
|
1214
|
+
generate_GO_grouping(g, p, 0, 0); break;
|
1215
|
+
case c_goto_non: generate_GO_grouping(g, p, 1, 1); break;
|
1216
|
+
case c_gopast_non: generate_GO_grouping(g, p, 0, 1); break;
|
1119
1217
|
case c_repeat: generate_repeat(g, p); break;
|
1120
1218
|
case c_loop: generate_loop(g, p); break;
|
1121
1219
|
case c_atleast: generate_atleast(g, p); break;
|
@@ -1150,12 +1248,14 @@ static void generate(struct generator * g, struct node * p) {
|
|
1150
1248
|
generate_AE(g, p->AE);
|
1151
1249
|
w(g, ");~N");
|
1152
1250
|
break;
|
1153
|
-
case c_eq:
|
1154
|
-
case c_ne:
|
1155
|
-
case
|
1156
|
-
case c_ge:
|
1157
|
-
case
|
1158
|
-
case c_le:
|
1251
|
+
case c_eq:
|
1252
|
+
case c_ne:
|
1253
|
+
case c_gt:
|
1254
|
+
case c_ge:
|
1255
|
+
case c_lt:
|
1256
|
+
case c_le:
|
1257
|
+
generate_integer_test(g, p);
|
1258
|
+
break;
|
1159
1259
|
case c_call: generate_call(g, p); break;
|
1160
1260
|
case c_grouping: generate_grouping(g, p, false); break;
|
1161
1261
|
case c_non: generate_grouping(g, p, true); break;
|
@@ -1167,6 +1267,7 @@ static void generate(struct generator * g, struct node * p) {
|
|
1167
1267
|
case c_false: generate_false(g, p); break;
|
1168
1268
|
case c_true: break;
|
1169
1269
|
case c_debug: generate_debug(g, p); break;
|
1270
|
+
case c_functionend: generate_functionend(g, p); break;
|
1170
1271
|
default: fprintf(stderr, "%d encountered\n", p->type);
|
1171
1272
|
exit(1);
|
1172
1273
|
}
|
@@ -1177,10 +1278,22 @@ static void generate(struct generator * g, struct node * p) {
|
|
1177
1278
|
}
|
1178
1279
|
|
1179
1280
|
static void generate_class_begin(struct generator * g) {
|
1180
|
-
|
1181
|
-
|
1182
|
-
|
1183
|
-
|
1281
|
+
if (g->options->js_esm) {
|
1282
|
+
w(g, "// deno-lint-ignore-file~N"
|
1283
|
+
"import ~P from './base-stemmer.mjs'~N"
|
1284
|
+
"~N"
|
1285
|
+
"/** @typedef {{ stemWord(word: string): string }} Stemmer */~N"
|
1286
|
+
"~N"
|
1287
|
+
"/** @type {{ new(): Stemmer }} */~N"
|
1288
|
+
"~C ~n = function() {~+~N"
|
1289
|
+
"~M~D base = new ~P();~N");
|
1290
|
+
} else {
|
1291
|
+
w(g, "/**@constructor*/~N"
|
1292
|
+
"~D ~n = function() {~+~N"
|
1293
|
+
"~M~C ~P = require('./base-stemmer.js');~N"
|
1294
|
+
"~M~D base = new ~P();~N");
|
1295
|
+
}
|
1296
|
+
write_newline(g);
|
1184
1297
|
}
|
1185
1298
|
|
1186
1299
|
static void generate_class_end(struct generator * g) {
|
@@ -1192,39 +1305,41 @@ static void generate_class_end(struct generator * g) {
|
|
1192
1305
|
w(g, "~Mreturn base.getCurrent();~N");
|
1193
1306
|
w(g, "~-~M};~N");
|
1194
1307
|
w(g, "~-};~N");
|
1195
|
-
|
1308
|
+
if (g->options->js_esm) {
|
1309
|
+
w(g, "~N"
|
1310
|
+
"export default ~n~N");
|
1311
|
+
} else {
|
1312
|
+
w(g, "~N"
|
1313
|
+
"if (typeof module === 'object' && module.exports) module.exports = ~n;~N");
|
1314
|
+
}
|
1196
1315
|
}
|
1197
1316
|
|
1198
1317
|
static void generate_among_table(struct generator * g, struct among * x) {
|
1318
|
+
write_comment(g, x->node);
|
1199
1319
|
|
1200
1320
|
struct amongvec * v = x->b;
|
1201
1321
|
|
1202
1322
|
g->I[0] = x->number;
|
1203
|
-
|
1204
|
-
|
1205
|
-
{
|
1206
|
-
|
1207
|
-
|
1208
|
-
|
1209
|
-
|
1210
|
-
|
1211
|
-
|
1212
|
-
|
1213
|
-
w(g, "
|
1214
|
-
|
1215
|
-
w(g, ", ");
|
1216
|
-
write_varname(g, v->function);
|
1217
|
-
}
|
1218
|
-
w(g, "]~S0~N");
|
1219
|
-
v++;
|
1323
|
+
w(g, "~M~C a_~I0 = [~N~+");
|
1324
|
+
|
1325
|
+
for (int i = 0; i < x->literalstring_count; i++) {
|
1326
|
+
g->I[0] = v[i].i;
|
1327
|
+
g->I[1] = v[i].result;
|
1328
|
+
g->L[0] = v[i].b;
|
1329
|
+
g->S[0] = i < x->literalstring_count - 1 ? "," : "";
|
1330
|
+
|
1331
|
+
w(g, "~M[~L0, ~I0, ~I1");
|
1332
|
+
if (v[i].function != NULL) {
|
1333
|
+
w(g, ", ");
|
1334
|
+
write_varname(g, v[i].function);
|
1220
1335
|
}
|
1336
|
+
w(g, "]~S0~N");
|
1221
1337
|
}
|
1222
1338
|
w(g, "~-~M];~N~N");
|
1223
1339
|
}
|
1224
1340
|
|
1225
1341
|
static void generate_amongs(struct generator * g) {
|
1226
|
-
struct among * x;
|
1227
|
-
for (x = g->analyser->amongs; x; x = x->next) {
|
1342
|
+
for (struct among * x = g->analyser->amongs; x; x = x->next) {
|
1228
1343
|
generate_among_table(g, x);
|
1229
1344
|
}
|
1230
1345
|
}
|
@@ -1232,69 +1347,64 @@ static void generate_amongs(struct generator * g) {
|
|
1232
1347
|
static void set_bit(symbol * b, int i) { b[i/8] |= 1 << i%8; }
|
1233
1348
|
|
1234
1349
|
static void generate_grouping_table(struct generator * g, struct grouping * q) {
|
1235
|
-
|
1236
1350
|
int range = q->largest_ch - q->smallest_ch + 1;
|
1237
1351
|
int size = (range + 7)/ 8; /* assume 8 bits per symbol */
|
1238
1352
|
symbol * b = q->b;
|
1239
1353
|
symbol * map = create_b(size);
|
1240
|
-
int i;
|
1241
|
-
for (i = 0; i < size; i++) map[i] = 0;
|
1242
1354
|
|
1243
|
-
|
1355
|
+
for (int i = 0; i < size; i++) map[i] = 0;
|
1244
1356
|
|
1245
|
-
for (i = 0; i < SIZE(b); i++) set_bit(map, b[i] - q->smallest_ch);
|
1357
|
+
for (int i = 0; i < SIZE(b); i++) set_bit(map, b[i] - q->smallest_ch);
|
1246
1358
|
|
1247
1359
|
g->V[0] = q->name;
|
1248
|
-
|
1249
|
-
|
1250
|
-
for (i = 0; i < size; i++) {
|
1360
|
+
w(g, "~M~C /** Array<int> */ ~W0 = [");
|
1361
|
+
for (int i = 0; i < size; i++) {
|
1251
1362
|
write_int(g, map[i]);
|
1252
1363
|
if (i < size - 1) w(g, ", ");
|
1253
1364
|
}
|
1254
1365
|
w(g, "];~N~N");
|
1366
|
+
|
1255
1367
|
lose_b(map);
|
1256
1368
|
}
|
1257
1369
|
|
1258
1370
|
static void generate_groupings(struct generator * g) {
|
1259
|
-
struct grouping * q;
|
1260
|
-
for (q = g->analyser->groupings; q; q = q->next) {
|
1371
|
+
for (struct grouping * q = g->analyser->groupings; q; q = q->next) {
|
1261
1372
|
if (q->name->used)
|
1262
1373
|
generate_grouping_table(g, q);
|
1263
1374
|
}
|
1264
1375
|
}
|
1265
1376
|
|
1266
1377
|
static void generate_members(struct generator * g) {
|
1378
|
+
int wrote_members = false;
|
1267
1379
|
|
1268
|
-
struct name * q;
|
1269
|
-
for (q = g->analyser->names; q; q = q->next) {
|
1380
|
+
for (struct name * q = g->analyser->names; q; q = q->next) {
|
1270
1381
|
g->V[0] = q;
|
1271
1382
|
switch (q->type) {
|
1272
1383
|
case t_string:
|
1273
|
-
w(g, "~
|
1384
|
+
w(g, "~M~D /** string */ ~W0 = '';~N");
|
1385
|
+
wrote_members = true;
|
1274
1386
|
break;
|
1275
1387
|
case t_integer:
|
1276
|
-
w(g, "~
|
1388
|
+
w(g, "~M~D /** number */ ~W0 = 0;~N");
|
1389
|
+
wrote_members = true;
|
1277
1390
|
break;
|
1278
1391
|
case t_boolean:
|
1279
|
-
w(g, "~
|
1392
|
+
w(g, "~M~D /** boolean */ ~W0 = false;~N");
|
1393
|
+
wrote_members = true;
|
1280
1394
|
break;
|
1281
1395
|
}
|
1282
1396
|
}
|
1283
|
-
w(g, "~N");
|
1397
|
+
if (wrote_members) w(g, "~N");
|
1284
1398
|
}
|
1285
1399
|
|
1286
1400
|
static void generate_methods(struct generator * g) {
|
1287
|
-
|
1288
|
-
struct node * p = g->analyser->program;
|
1289
|
-
while (p != 0) {
|
1401
|
+
for (struct node * p = g->analyser->program; p; p = p->right) {
|
1290
1402
|
generate(g, p);
|
1291
1403
|
g->unreachable = false;
|
1292
|
-
p = p->right;
|
1293
1404
|
}
|
1294
1405
|
}
|
1295
1406
|
|
1296
1407
|
extern void generate_program_js(struct generator * g) {
|
1297
|
-
|
1298
1408
|
g->outbuf = str_new();
|
1299
1409
|
g->failure_str = str_new();
|
1300
1410
|
|