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,59 +23,39 @@ 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
|
-
|
42
38
|
/* In java, references look just the same */
|
43
39
|
write_varname(g, p);
|
44
40
|
}
|
45
41
|
|
46
|
-
static void write_hexdigit(struct generator * g, int n) {
|
47
|
-
|
48
|
-
write_char(g, n < 10 ? n + '0' : n - 10 + 'A');
|
49
|
-
}
|
50
|
-
|
51
|
-
static void write_hex(struct generator * g, int ch) {
|
52
|
-
|
53
|
-
write_string(g, "\\u");
|
54
|
-
{
|
55
|
-
int i;
|
56
|
-
for (i = 12; i >= 0; i -= 4) write_hexdigit(g, ch >> i & 0xf);
|
57
|
-
}
|
58
|
-
}
|
59
|
-
|
60
42
|
static void write_literal_string(struct generator * g, symbol * p) {
|
61
|
-
|
62
|
-
int i;
|
63
43
|
write_string(g, "\"");
|
64
|
-
for (i = 0; i < SIZE(p); i++) {
|
44
|
+
for (int i = 0; i < SIZE(p); i++) {
|
65
45
|
int ch = p[i];
|
66
46
|
if (32 <= ch && ch < 127) {
|
67
47
|
if (ch == '\"' || ch == '\\') write_string(g, "\\");
|
68
48
|
write_char(g, ch);
|
69
49
|
} else {
|
70
|
-
|
50
|
+
write_string(g, "\\u");
|
51
|
+
write_hex4(g, ch);
|
71
52
|
}
|
72
53
|
}
|
73
54
|
write_string(g, "\"");
|
74
55
|
}
|
75
56
|
|
76
57
|
static void write_margin(struct generator * g) {
|
77
|
-
|
78
|
-
int i;
|
79
|
-
for (i = 0; i < g->margin; i++) write_string(g, " ");
|
58
|
+
for (int i = 0; i < g->margin; i++) write_string(g, " ");
|
80
59
|
}
|
81
60
|
|
82
61
|
static void write_comment(struct generator * g, struct node * p) {
|
@@ -88,65 +67,51 @@ static void write_comment(struct generator * g, struct node * p) {
|
|
88
67
|
}
|
89
68
|
|
90
69
|
static void write_block_start(struct generator * g) {
|
91
|
-
|
92
70
|
w(g, "~M{~+~N");
|
93
71
|
}
|
94
72
|
|
95
|
-
static void write_block_end(struct generator * g)
|
96
|
-
|
73
|
+
static void write_block_end(struct generator * g) {
|
97
74
|
w(g, "~-~M}~N");
|
98
75
|
}
|
99
76
|
|
100
77
|
static void write_savecursor(struct generator * g, struct node * p,
|
101
78
|
struct str * savevar) {
|
102
|
-
|
103
79
|
g->B[0] = str_data(savevar);
|
104
80
|
g->S[1] = "";
|
105
81
|
if (p->mode != m_forward) g->S[1] = "limit - ";
|
106
82
|
writef(g, "~Mint ~B0 = ~S1cursor;~N", p);
|
107
83
|
}
|
108
84
|
|
109
|
-
static void
|
110
|
-
|
111
|
-
str_clear(out);
|
85
|
+
static void append_restore_string(struct node * p, struct str * out, struct str * savevar) {
|
112
86
|
str_append_string(out, "cursor = ");
|
113
87
|
if (p->mode != m_forward) str_append_string(out, "limit - ");
|
114
88
|
str_append(out, savevar);
|
115
89
|
str_append_string(out, ";");
|
116
90
|
}
|
117
91
|
|
118
|
-
static void write_restorecursor(struct generator * g, struct node * p,
|
119
|
-
struct str * savevar) {
|
120
|
-
|
121
|
-
struct str * temp = str_new();
|
92
|
+
static void write_restorecursor(struct generator * g, struct node * p, struct str * savevar) {
|
122
93
|
write_margin(g);
|
123
|
-
|
124
|
-
write_str(g, temp);
|
94
|
+
append_restore_string(p, g->outbuf, savevar);
|
125
95
|
write_newline(g);
|
126
|
-
str_delete(temp);
|
127
96
|
}
|
128
97
|
|
129
98
|
static void write_inc_cursor(struct generator * g, struct node * p) {
|
130
|
-
|
131
99
|
write_margin(g);
|
132
100
|
write_string(g, p->mode == m_forward ? "cursor++;" : "cursor--;");
|
133
101
|
write_newline(g);
|
134
102
|
}
|
135
103
|
|
136
104
|
static void wsetlab_begin(struct generator * g, int n) {
|
137
|
-
|
138
105
|
w(g, "~Mlab");
|
139
106
|
write_int(g, n);
|
140
107
|
w(g, ": {~+~N");
|
141
108
|
}
|
142
109
|
|
143
110
|
static void wsetlab_end(struct generator * g) {
|
144
|
-
|
145
111
|
w(g, "~-~M}~N");
|
146
112
|
}
|
147
113
|
|
148
114
|
static void wgotol(struct generator * g, int n) {
|
149
|
-
|
150
115
|
write_margin(g);
|
151
116
|
write_string(g, "break lab");
|
152
117
|
write_int(g, n);
|
@@ -155,7 +120,6 @@ static void wgotol(struct generator * g, int n) {
|
|
155
120
|
}
|
156
121
|
|
157
122
|
static void write_failure(struct generator * g) {
|
158
|
-
|
159
123
|
if (str_len(g->failure_str) != 0) {
|
160
124
|
write_margin(g);
|
161
125
|
write_str(g, g->failure_str);
|
@@ -176,8 +140,7 @@ static void write_failure(struct generator * g) {
|
|
176
140
|
write_newline(g);
|
177
141
|
}
|
178
142
|
|
179
|
-
static void write_failure_if(struct generator * g, char * s, struct node * p) {
|
180
|
-
|
143
|
+
static void write_failure_if(struct generator * g, const char * s, struct node * p) {
|
181
144
|
writef(g, "~Mif (", p);
|
182
145
|
writef(g, s, p);
|
183
146
|
writef(g, ")~N", p);
|
@@ -189,7 +152,6 @@ static void write_failure_if(struct generator * g, char * s, struct node * p) {
|
|
189
152
|
|
190
153
|
/* if at limit fail */
|
191
154
|
static void write_check_limit(struct generator * g, struct node * p) {
|
192
|
-
|
193
155
|
if (p->mode == m_forward) {
|
194
156
|
write_failure_if(g, "cursor >= limit", p);
|
195
157
|
} else {
|
@@ -199,18 +161,18 @@ static void write_check_limit(struct generator * g, struct node * p) {
|
|
199
161
|
|
200
162
|
/* Formatted write. */
|
201
163
|
static void writef(struct generator * g, const char * input, struct node * p) {
|
164
|
+
(void)p;
|
202
165
|
int i = 0;
|
203
|
-
int l = strlen(input);
|
204
166
|
|
205
|
-
while (i
|
167
|
+
while (input[i]) {
|
206
168
|
int ch = input[i++];
|
207
169
|
if (ch != '~') {
|
208
170
|
write_char(g, ch);
|
209
171
|
continue;
|
210
172
|
}
|
211
|
-
|
212
|
-
|
213
|
-
case '
|
173
|
+
ch = input[i++];
|
174
|
+
switch (ch) {
|
175
|
+
case '~': write_char(g, '~'); continue;
|
214
176
|
case 'f': write_block_start(g);
|
215
177
|
write_failure(g);
|
216
178
|
g->unreachable = false;
|
@@ -220,21 +182,65 @@ static void writef(struct generator * g, const char * input, struct node * p) {
|
|
220
182
|
case 'N': write_newline(g); continue;
|
221
183
|
case '{': write_block_start(g); continue;
|
222
184
|
case '}': write_block_end(g); continue;
|
223
|
-
case 'S':
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
185
|
+
case 'S': {
|
186
|
+
int j = input[i++] - '0';
|
187
|
+
if (j < 0 || j > (int)(sizeof(g->S) / sizeof(g->S[0]))) {
|
188
|
+
printf("Invalid escape sequence ~%c%c in writef(g, \"%s\", p)\n",
|
189
|
+
ch, input[i - 1], input);
|
190
|
+
exit(1);
|
191
|
+
}
|
192
|
+
write_string(g, g->S[j]);
|
193
|
+
continue;
|
194
|
+
}
|
195
|
+
case 'B': {
|
196
|
+
int j = input[i++] - '0';
|
197
|
+
if (j < 0 || j > (int)(sizeof(g->B) / sizeof(g->B[0])))
|
198
|
+
goto invalid_escape2;
|
199
|
+
write_s(g, g->B[j]);
|
200
|
+
continue;
|
201
|
+
}
|
202
|
+
case 'I': {
|
203
|
+
int j = input[i++] - '0';
|
204
|
+
if (j < 0 || j > (int)(sizeof(g->I) / sizeof(g->I[0])))
|
205
|
+
goto invalid_escape2;
|
206
|
+
write_int(g, g->I[j]);
|
207
|
+
continue;
|
208
|
+
}
|
209
|
+
case 'V':
|
210
|
+
case 'W': {
|
211
|
+
int j = input[i++] - '0';
|
212
|
+
if (j < 0 || j > (int)(sizeof(g->V) / sizeof(g->V[0])))
|
213
|
+
goto invalid_escape2;
|
214
|
+
if (ch == 'V')
|
215
|
+
write_varref(g, g->V[j]);
|
216
|
+
else
|
217
|
+
write_varname(g, g->V[j]);
|
218
|
+
continue;
|
219
|
+
}
|
220
|
+
case 'L': {
|
221
|
+
int j = input[i++] - '0';
|
222
|
+
if (j < 0 || j > (int)(sizeof(g->L) / sizeof(g->L[0])))
|
223
|
+
goto invalid_escape2;
|
224
|
+
write_literal_string(g, g->L[j]);
|
225
|
+
continue;
|
226
|
+
}
|
229
227
|
case '+': g->margin++; continue;
|
230
228
|
case '-': g->margin--; continue;
|
231
229
|
case 'n': write_string(g, g->options->name); continue;
|
230
|
+
default:
|
231
|
+
printf("Invalid escape sequence ~%c in writef(g, \"%s\", p)\n",
|
232
|
+
ch, input);
|
233
|
+
exit(1);
|
234
|
+
invalid_escape2:
|
235
|
+
printf("Invalid escape sequence ~%c%c in writef(g, \"%s\", p)\n",
|
236
|
+
ch, input[i - 1], input);
|
237
|
+
exit(1);
|
232
238
|
}
|
233
239
|
}
|
234
240
|
}
|
235
241
|
|
236
242
|
static void w(struct generator * g, const char * s) {
|
237
|
-
writef(g, s,
|
243
|
+
writef(g, s, NULL);
|
238
244
|
}
|
239
245
|
|
240
246
|
static void generate_AE(struct generator * g, struct node * p) {
|
@@ -272,13 +278,12 @@ static void generate_AE(struct generator * g, struct node * p) {
|
|
272
278
|
break;
|
273
279
|
case c_len: /* Same as size() for Java. */
|
274
280
|
case c_size:
|
275
|
-
w(g, "
|
281
|
+
w(g, "length");
|
276
282
|
break;
|
277
283
|
}
|
278
284
|
}
|
279
285
|
|
280
286
|
static void generate_bra(struct generator * g, struct node * p) {
|
281
|
-
|
282
287
|
write_comment(g, p);
|
283
288
|
p = p->left;
|
284
289
|
while (p) {
|
@@ -288,28 +293,33 @@ static void generate_bra(struct generator * g, struct node * p) {
|
|
288
293
|
}
|
289
294
|
|
290
295
|
static void generate_and(struct generator * g, struct node * p) {
|
291
|
-
|
292
|
-
|
293
|
-
|
296
|
+
struct str * savevar = NULL;
|
297
|
+
if (K_needed(g, p->left)) {
|
298
|
+
savevar = vars_newname(g);
|
299
|
+
}
|
294
300
|
|
295
301
|
write_comment(g, p);
|
296
302
|
|
297
|
-
if (
|
303
|
+
if (savevar) write_savecursor(g, p, savevar);
|
298
304
|
|
299
305
|
p = p->left;
|
300
306
|
while (p) {
|
301
307
|
generate(g, p);
|
302
308
|
if (g->unreachable) break;
|
303
|
-
if (
|
309
|
+
if (savevar && p->right != NULL) write_restorecursor(g, p, savevar);
|
304
310
|
p = p->right;
|
305
311
|
}
|
306
|
-
|
312
|
+
|
313
|
+
if (savevar) {
|
314
|
+
str_delete(savevar);
|
315
|
+
}
|
307
316
|
}
|
308
317
|
|
309
318
|
static void generate_or(struct generator * g, struct node * p) {
|
310
|
-
|
311
|
-
|
312
|
-
|
319
|
+
struct str * savevar = NULL;
|
320
|
+
if (K_needed(g, p->left)) {
|
321
|
+
savevar = vars_newname(g);
|
322
|
+
}
|
313
323
|
|
314
324
|
int a0 = g->failure_label;
|
315
325
|
struct str * a1 = str_copy(g->failure_str);
|
@@ -320,18 +330,18 @@ static void generate_or(struct generator * g, struct node * p) {
|
|
320
330
|
write_comment(g, p);
|
321
331
|
wsetlab_begin(g, out_lab);
|
322
332
|
|
323
|
-
if (
|
333
|
+
if (savevar) write_savecursor(g, p, savevar);
|
324
334
|
|
325
335
|
p = p->left;
|
326
336
|
str_clear(g->failure_str);
|
327
337
|
|
328
|
-
if (p ==
|
329
|
-
/* p should never be
|
338
|
+
if (p == NULL) {
|
339
|
+
/* p should never be NULL after an or: there should be at least two
|
330
340
|
* sub nodes. */
|
331
341
|
fprintf(stderr, "Error: \"or\" node without children nodes.");
|
332
342
|
exit(1);
|
333
343
|
}
|
334
|
-
while (p->right !=
|
344
|
+
while (p->right != NULL) {
|
335
345
|
g->failure_label = new_label(g);
|
336
346
|
wsetlab_begin(g, g->failure_label);
|
337
347
|
generate(g, p);
|
@@ -341,7 +351,7 @@ static void generate_or(struct generator * g, struct node * p) {
|
|
341
351
|
}
|
342
352
|
wsetlab_end(g);
|
343
353
|
g->unreachable = false;
|
344
|
-
if (
|
354
|
+
if (savevar) write_restorecursor(g, p, savevar);
|
345
355
|
p = p->right;
|
346
356
|
}
|
347
357
|
|
@@ -354,11 +364,13 @@ static void generate_or(struct generator * g, struct node * p) {
|
|
354
364
|
if (!end_unreachable) {
|
355
365
|
g->unreachable = false;
|
356
366
|
}
|
357
|
-
|
367
|
+
|
368
|
+
if (savevar) {
|
369
|
+
str_delete(savevar);
|
370
|
+
}
|
358
371
|
}
|
359
372
|
|
360
373
|
static void generate_backwards(struct generator * g, struct node * p) {
|
361
|
-
|
362
374
|
write_comment(g, p);
|
363
375
|
writef(g, "~Mlimit_backward = cursor;~N"
|
364
376
|
"~Mcursor = limit;~N", p);
|
@@ -368,15 +380,16 @@ static void generate_backwards(struct generator * g, struct node * p) {
|
|
368
380
|
|
369
381
|
|
370
382
|
static void generate_not(struct generator * g, struct node * p) {
|
371
|
-
|
372
|
-
|
373
|
-
|
383
|
+
struct str * savevar = NULL;
|
384
|
+
if (K_needed(g, p->left)) {
|
385
|
+
savevar = vars_newname(g);
|
386
|
+
}
|
374
387
|
|
375
388
|
int a0 = g->failure_label;
|
376
389
|
struct str * a1 = str_copy(g->failure_str);
|
377
390
|
|
378
391
|
write_comment(g, p);
|
379
|
-
if (
|
392
|
+
if (savevar) {
|
380
393
|
write_block_start(g);
|
381
394
|
write_savecursor(g, p, savevar);
|
382
395
|
}
|
@@ -397,48 +410,52 @@ static void generate_not(struct generator * g, struct node * p) {
|
|
397
410
|
wsetlab_end(g);
|
398
411
|
g->unreachable = false;
|
399
412
|
|
400
|
-
if (
|
401
|
-
|
402
|
-
|
413
|
+
if (savevar) {
|
414
|
+
write_restorecursor(g, p, savevar);
|
415
|
+
write_block_end(g);
|
416
|
+
str_delete(savevar);
|
417
|
+
}
|
403
418
|
}
|
404
419
|
|
405
420
|
|
406
421
|
static void generate_try(struct generator * g, struct node * p) {
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
write_comment(g, p);
|
412
|
-
if (keep_c) write_savecursor(g, p, savevar);
|
422
|
+
struct str * savevar = NULL;
|
423
|
+
if (K_needed(g, p->left)) {
|
424
|
+
savevar = vars_newname(g);
|
425
|
+
}
|
413
426
|
|
414
427
|
g->failure_label = new_label(g);
|
415
428
|
str_clear(g->failure_str);
|
416
|
-
|
429
|
+
|
430
|
+
write_comment(g, p);
|
431
|
+
if (savevar) {
|
432
|
+
write_savecursor(g, p, savevar);
|
433
|
+
append_restore_string(p, g->failure_str, savevar);
|
434
|
+
}
|
417
435
|
|
418
436
|
wsetlab_begin(g, g->failure_label);
|
419
437
|
generate(g, p->left);
|
420
438
|
wsetlab_end(g);
|
421
439
|
g->unreachable = false;
|
422
440
|
|
423
|
-
|
441
|
+
if (savevar) {
|
442
|
+
str_delete(savevar);
|
443
|
+
}
|
424
444
|
}
|
425
445
|
|
426
446
|
static void generate_set(struct generator * g, struct node * p) {
|
427
|
-
|
428
447
|
write_comment(g, p);
|
429
448
|
g->V[0] = p->name;
|
430
449
|
writef(g, "~M~V0 = true;~N", p);
|
431
450
|
}
|
432
451
|
|
433
452
|
static void generate_unset(struct generator * g, struct node * p) {
|
434
|
-
|
435
453
|
write_comment(g, p);
|
436
454
|
g->V[0] = p->name;
|
437
455
|
writef(g, "~M~V0 = false;~N", p);
|
438
456
|
}
|
439
457
|
|
440
458
|
static void generate_fail(struct generator * g, struct node * p) {
|
441
|
-
|
442
459
|
write_comment(g, p);
|
443
460
|
generate(g, p->left);
|
444
461
|
if (!g->unreachable) write_failure(g);
|
@@ -447,32 +464,35 @@ static void generate_fail(struct generator * g, struct node * p) {
|
|
447
464
|
/* generate_test() also implements 'reverse' */
|
448
465
|
|
449
466
|
static void generate_test(struct generator * g, struct node * p) {
|
450
|
-
|
451
|
-
|
452
|
-
|
467
|
+
struct str * savevar = NULL;
|
468
|
+
if (K_needed(g, p->left)) {
|
469
|
+
savevar = vars_newname(g);
|
470
|
+
}
|
453
471
|
|
454
472
|
write_comment(g, p);
|
455
473
|
|
456
|
-
if (
|
474
|
+
if (savevar) {
|
457
475
|
write_savecursor(g, p, savevar);
|
458
476
|
}
|
459
477
|
|
460
478
|
generate(g, p->left);
|
461
479
|
|
462
|
-
if (
|
463
|
-
if (
|
480
|
+
if (savevar) {
|
481
|
+
if (!g->unreachable) {
|
464
482
|
write_restorecursor(g, p, savevar);
|
465
483
|
}
|
484
|
+
str_delete(savevar);
|
466
485
|
}
|
467
|
-
str_delete(savevar);
|
468
486
|
}
|
469
487
|
|
470
488
|
static void generate_do(struct generator * g, struct node * p) {
|
489
|
+
struct str * savevar = NULL;
|
490
|
+
if (K_needed(g, p->left)) {
|
491
|
+
savevar = vars_newname(g);
|
492
|
+
}
|
471
493
|
|
472
|
-
struct str * savevar = vars_newname(g);
|
473
|
-
int keep_c = K_needed(g, p->left);
|
474
494
|
write_comment(g, p);
|
475
|
-
if (
|
495
|
+
if (savevar) write_savecursor(g, p, savevar);
|
476
496
|
|
477
497
|
if (p->left->type == c_call) {
|
478
498
|
/* Optimise do <call> */
|
@@ -489,26 +509,54 @@ static void generate_do(struct generator * g, struct node * p) {
|
|
489
509
|
g->unreachable = false;
|
490
510
|
}
|
491
511
|
|
492
|
-
if (
|
493
|
-
|
512
|
+
if (savevar) {
|
513
|
+
write_restorecursor(g, p, savevar);
|
514
|
+
str_delete(savevar);
|
515
|
+
}
|
494
516
|
}
|
495
517
|
|
496
|
-
static void
|
518
|
+
static void generate_next(struct generator * g, struct node * p) {
|
519
|
+
write_comment(g, p);
|
520
|
+
write_check_limit(g, p);
|
521
|
+
write_inc_cursor(g, p);
|
522
|
+
}
|
497
523
|
|
498
|
-
|
499
|
-
|
500
|
-
|
524
|
+
static void generate_GO_grouping(struct generator * g, struct node * p, int is_goto, int complement) {
|
525
|
+
write_comment(g, p);
|
526
|
+
|
527
|
+
struct grouping * q = p->name->grouping;
|
528
|
+
g->S[0] = p->mode == m_forward ? "" : "_b";
|
529
|
+
g->S[1] = complement ? "in" : "out";
|
530
|
+
g->V[0] = p->name;
|
531
|
+
g->I[0] = q->smallest_ch;
|
532
|
+
g->I[1] = q->largest_ch;
|
533
|
+
write_failure_if(g, "!go_~S1_grouping~S0(~V0, ~I0, ~I1)", p);
|
534
|
+
if (!is_goto) {
|
535
|
+
if (p->mode == m_forward)
|
536
|
+
w(g, "~Mcursor++;~N");
|
537
|
+
else
|
538
|
+
w(g, "~Mcursor--;~N");
|
539
|
+
}
|
540
|
+
}
|
541
|
+
|
542
|
+
static void generate_GO(struct generator * g, struct node * p, int style) {
|
543
|
+
write_comment(g, p);
|
501
544
|
|
502
545
|
int a0 = g->failure_label;
|
503
546
|
struct str * a1 = str_copy(g->failure_str);
|
504
547
|
|
548
|
+
int end_unreachable = false;
|
549
|
+
|
505
550
|
int golab = new_label(g);
|
506
551
|
g->I[0] = golab;
|
507
|
-
write_comment(g, p);
|
508
552
|
w(g, "~Mgolab~I0: while(true)~N");
|
509
553
|
w(g, "~{");
|
510
554
|
|
511
|
-
|
555
|
+
struct str * savevar = NULL;
|
556
|
+
if (style == 1 || repeat_restore(g, p->left)) {
|
557
|
+
savevar = vars_newname(g);
|
558
|
+
write_savecursor(g, p, savevar);
|
559
|
+
}
|
512
560
|
|
513
561
|
g->failure_label = new_label(g);
|
514
562
|
str_clear(g->failure_str);
|
@@ -527,7 +575,10 @@ static void generate_GO(struct generator * g, struct node * p, int style) {
|
|
527
575
|
}
|
528
576
|
g->unreachable = false;
|
529
577
|
wsetlab_end(g);
|
530
|
-
if (
|
578
|
+
if (savevar) {
|
579
|
+
write_restorecursor(g, p, savevar);
|
580
|
+
str_delete(savevar);
|
581
|
+
}
|
531
582
|
|
532
583
|
g->failure_label = a0;
|
533
584
|
str_delete(g->failure_str);
|
@@ -536,12 +587,10 @@ static void generate_GO(struct generator * g, struct node * p, int style) {
|
|
536
587
|
write_check_limit(g, p);
|
537
588
|
write_inc_cursor(g, p);
|
538
589
|
write_block_end(g);
|
539
|
-
str_delete(savevar);
|
540
590
|
g->unreachable = end_unreachable;
|
541
591
|
}
|
542
592
|
|
543
593
|
static void generate_loop(struct generator * g, struct node * p) {
|
544
|
-
|
545
594
|
struct str * loopvar = vars_newname(g);
|
546
595
|
write_comment(g, p);
|
547
596
|
g->B[0] = str_data(loopvar);
|
@@ -559,12 +608,13 @@ static void generate_loop(struct generator * g, struct node * p) {
|
|
559
608
|
}
|
560
609
|
|
561
610
|
static void generate_repeat_or_atleast(struct generator * g, struct node * p, struct str * loopvar) {
|
562
|
-
|
563
|
-
struct str * savevar = vars_newname(g);
|
564
|
-
int keep_c = repeat_restore(g, p->left);
|
565
611
|
writef(g, "~Mwhile(true)~N~{", p);
|
566
612
|
|
567
|
-
|
613
|
+
struct str * savevar = NULL;
|
614
|
+
if (repeat_restore(g, p->left)) {
|
615
|
+
savevar = vars_newname(g);
|
616
|
+
write_savecursor(g, p, savevar);
|
617
|
+
}
|
568
618
|
|
569
619
|
g->failure_label = new_label(g);
|
570
620
|
str_clear(g->failure_str);
|
@@ -572,7 +622,7 @@ static void generate_repeat_or_atleast(struct generator * g, struct node * p, st
|
|
572
622
|
generate(g, p->left);
|
573
623
|
|
574
624
|
if (!g->unreachable) {
|
575
|
-
if (loopvar !=
|
625
|
+
if (loopvar != NULL) {
|
576
626
|
g->B[0] = str_data(loopvar);
|
577
627
|
w(g, "~M~B0--;~N");
|
578
628
|
}
|
@@ -583,10 +633,12 @@ static void generate_repeat_or_atleast(struct generator * g, struct node * p, st
|
|
583
633
|
wsetlab_end(g);
|
584
634
|
g->unreachable = false;
|
585
635
|
|
586
|
-
if (
|
636
|
+
if (savevar) {
|
637
|
+
write_restorecursor(g, p, savevar);
|
638
|
+
str_delete(savevar);
|
639
|
+
}
|
587
640
|
|
588
641
|
w(g, "~Mbreak;~N~}");
|
589
|
-
str_delete(savevar);
|
590
642
|
}
|
591
643
|
|
592
644
|
static void generate_repeat(struct generator * g, struct node * p) {
|
@@ -595,8 +647,8 @@ static void generate_repeat(struct generator * g, struct node * p) {
|
|
595
647
|
}
|
596
648
|
|
597
649
|
static void generate_atleast(struct generator * g, struct node * p) {
|
598
|
-
|
599
650
|
struct str * loopvar = vars_newname(g);
|
651
|
+
|
600
652
|
write_comment(g, p);
|
601
653
|
w(g, "~{");
|
602
654
|
g->B[0] = str_data(loopvar);
|
@@ -620,14 +672,12 @@ static void generate_atleast(struct generator * g, struct node * p) {
|
|
620
672
|
}
|
621
673
|
|
622
674
|
static void generate_setmark(struct generator * g, struct node * p) {
|
623
|
-
|
624
675
|
write_comment(g, p);
|
625
676
|
g->V[0] = p->name;
|
626
677
|
writef(g, "~M~V0 = cursor;~N", p);
|
627
678
|
}
|
628
679
|
|
629
680
|
static void generate_tomark(struct generator * g, struct node * p) {
|
630
|
-
|
631
681
|
write_comment(g, p);
|
632
682
|
g->S[0] = p->mode == m_forward ? ">" : "<";
|
633
683
|
|
@@ -640,7 +690,6 @@ static void generate_tomark(struct generator * g, struct node * p) {
|
|
640
690
|
}
|
641
691
|
|
642
692
|
static void generate_atmark(struct generator * g, struct node * p) {
|
643
|
-
|
644
693
|
write_comment(g, p);
|
645
694
|
w(g, "~Mif (cursor != "); generate_AE(g, p->AE); writef(g, ")~N", p);
|
646
695
|
write_block_start(g);
|
@@ -650,7 +699,6 @@ static void generate_atmark(struct generator * g, struct node * p) {
|
|
650
699
|
}
|
651
700
|
|
652
701
|
static void generate_hop(struct generator * g, struct node * p) {
|
653
|
-
|
654
702
|
write_comment(g, p);
|
655
703
|
g->S[0] = p->mode == m_forward ? "+" : "-";
|
656
704
|
|
@@ -674,28 +722,17 @@ static void generate_hop(struct generator * g, struct node * p) {
|
|
674
722
|
}
|
675
723
|
|
676
724
|
static void generate_delete(struct generator * g, struct node * p) {
|
677
|
-
|
678
725
|
write_comment(g, p);
|
679
726
|
writef(g, "~Mslice_del();~N", p);
|
680
727
|
}
|
681
728
|
|
682
|
-
|
683
|
-
static void generate_next(struct generator * g, struct node * p) {
|
684
|
-
|
685
|
-
write_comment(g, p);
|
686
|
-
write_check_limit(g, p);
|
687
|
-
write_inc_cursor(g, p);
|
688
|
-
}
|
689
|
-
|
690
729
|
static void generate_tolimit(struct generator * g, struct node * p) {
|
691
|
-
|
692
730
|
write_comment(g, p);
|
693
731
|
g->S[0] = p->mode == m_forward ? "limit" : "limit_backward";
|
694
732
|
writef(g, "~Mcursor = ~S0;~N", p);
|
695
733
|
}
|
696
734
|
|
697
735
|
static void generate_atlimit(struct generator * g, struct node * p) {
|
698
|
-
|
699
736
|
write_comment(g, p);
|
700
737
|
g->S[0] = p->mode == m_forward ? "limit" : "limit_backward";
|
701
738
|
g->S[1] = p->mode == m_forward ? "<" : ">";
|
@@ -703,37 +740,32 @@ static void generate_atlimit(struct generator * g, struct node * p) {
|
|
703
740
|
}
|
704
741
|
|
705
742
|
static void generate_leftslice(struct generator * g, struct node * p) {
|
706
|
-
|
707
743
|
write_comment(g, p);
|
708
744
|
g->S[0] = p->mode == m_forward ? "bra" : "ket";
|
709
745
|
writef(g, "~M~S0 = cursor;~N", p);
|
710
746
|
}
|
711
747
|
|
712
748
|
static void generate_rightslice(struct generator * g, struct node * p) {
|
713
|
-
|
714
749
|
write_comment(g, p);
|
715
750
|
g->S[0] = p->mode == m_forward ? "ket" : "bra";
|
716
751
|
writef(g, "~M~S0 = cursor;~N", p);
|
717
752
|
}
|
718
753
|
|
719
754
|
static void generate_assignto(struct generator * g, struct node * p) {
|
720
|
-
|
721
755
|
write_comment(g, p);
|
722
756
|
g->V[0] = p->name;
|
723
757
|
writef(g, "~Massign_to(~V0);~N", p);
|
724
758
|
}
|
725
759
|
|
726
760
|
static void generate_sliceto(struct generator * g, struct node * p) {
|
727
|
-
|
728
761
|
write_comment(g, p);
|
729
762
|
g->V[0] = p->name;
|
730
763
|
writef(g, "~Mslice_to(~V0);~N", p);
|
731
764
|
}
|
732
765
|
|
733
766
|
static void generate_address(struct generator * g, struct node * p) {
|
734
|
-
|
735
767
|
symbol * b = p->literalstring;
|
736
|
-
if (b !=
|
768
|
+
if (b != NULL) {
|
737
769
|
write_literal_string(g, b);
|
738
770
|
} else {
|
739
771
|
write_varref(g, p->name);
|
@@ -741,7 +773,6 @@ static void generate_address(struct generator * g, struct node * p) {
|
|
741
773
|
}
|
742
774
|
|
743
775
|
static void generate_insert(struct generator * g, struct node * p, int style) {
|
744
|
-
|
745
776
|
int keep_c = style == c_attach;
|
746
777
|
write_comment(g, p);
|
747
778
|
if (p->mode == m_backward) keep_c = !keep_c;
|
@@ -753,7 +784,6 @@ static void generate_insert(struct generator * g, struct node * p, int style) {
|
|
753
784
|
}
|
754
785
|
|
755
786
|
static void generate_assignfrom(struct generator * g, struct node * p) {
|
756
|
-
|
757
787
|
int keep_c = p->mode == m_forward; /* like 'attach' */
|
758
788
|
|
759
789
|
write_comment(g, p);
|
@@ -768,9 +798,7 @@ static void generate_assignfrom(struct generator * g, struct node * p) {
|
|
768
798
|
if (keep_c) w(g, "~Mcursor = c;~N~}");
|
769
799
|
}
|
770
800
|
|
771
|
-
|
772
801
|
static void generate_slicefrom(struct generator * g, struct node * p) {
|
773
|
-
|
774
802
|
write_comment(g, p);
|
775
803
|
w(g, "~Mslice_from(");
|
776
804
|
generate_address(g, p);
|
@@ -778,7 +806,6 @@ static void generate_slicefrom(struct generator * g, struct node * p) {
|
|
778
806
|
}
|
779
807
|
|
780
808
|
static void generate_setlimit(struct generator * g, struct node * p) {
|
781
|
-
struct str * savevar = vars_newname(g);
|
782
809
|
struct str * varname = vars_newname(g);
|
783
810
|
write_comment(g, p);
|
784
811
|
if (p->left && p->left->type == c_tomark) {
|
@@ -791,6 +818,7 @@ static void generate_setlimit(struct generator * g, struct node * p) {
|
|
791
818
|
* restore c.
|
792
819
|
*/
|
793
820
|
struct node * q = p->left;
|
821
|
+
write_comment(g, q);
|
794
822
|
g->S[0] = q->mode == m_forward ? ">" : "<";
|
795
823
|
w(g, "~Mif (cursor ~S0 "); generate_AE(g, q->AE); w(g, ")~N");
|
796
824
|
write_block_start(g);
|
@@ -806,7 +834,8 @@ static void generate_setlimit(struct generator * g, struct node * p) {
|
|
806
834
|
w(g, "~Mint ~B0 = limit_backward;~N");
|
807
835
|
w(g, "~Mlimit_backward = ");
|
808
836
|
}
|
809
|
-
generate_AE(g, q->AE);
|
837
|
+
generate_AE(g, q->AE);
|
838
|
+
writef(g, ";~N", q);
|
810
839
|
|
811
840
|
if (p->mode == m_forward) {
|
812
841
|
str_assign(g->failure_str, "limit += ");
|
@@ -818,7 +847,9 @@ static void generate_setlimit(struct generator * g, struct node * p) {
|
|
818
847
|
str_append_ch(g->failure_str, ';');
|
819
848
|
}
|
820
849
|
} else {
|
850
|
+
struct str * savevar = vars_newname(g);
|
821
851
|
write_savecursor(g, p, savevar);
|
852
|
+
|
822
853
|
generate(g, p->left);
|
823
854
|
|
824
855
|
if (!g->unreachable) {
|
@@ -842,6 +873,7 @@ static void generate_setlimit(struct generator * g, struct node * p) {
|
|
842
873
|
str_append_ch(g->failure_str, ';');
|
843
874
|
}
|
844
875
|
}
|
876
|
+
str_delete(savevar);
|
845
877
|
}
|
846
878
|
|
847
879
|
if (!g->unreachable) {
|
@@ -854,16 +886,16 @@ static void generate_setlimit(struct generator * g, struct node * p) {
|
|
854
886
|
}
|
855
887
|
}
|
856
888
|
str_delete(varname);
|
857
|
-
str_delete(savevar);
|
858
889
|
}
|
859
890
|
|
860
891
|
/* dollar sets snowball up to operate on a string variable as if it were the
|
861
892
|
* current string */
|
862
893
|
static void generate_dollar(struct generator * g, struct node * p) {
|
894
|
+
write_comment(g, p);
|
863
895
|
|
864
896
|
struct str * savevar = vars_newname(g);
|
865
897
|
g->B[0] = str_data(savevar);
|
866
|
-
writef(g, "~{~
|
898
|
+
writef(g, "~{~N"
|
867
899
|
"~MSnowballProgram ~B0 = new SnowballProgram(this);~N", p);
|
868
900
|
|
869
901
|
++g->copy_from_count;
|
@@ -884,36 +916,66 @@ static void generate_dollar(struct generator * g, struct node * p) {
|
|
884
916
|
str_delete(savevar);
|
885
917
|
}
|
886
918
|
|
887
|
-
static void generate_integer_assign(struct generator * g, struct node * p, char * s) {
|
888
|
-
|
919
|
+
static void generate_integer_assign(struct generator * g, struct node * p, const char * s) {
|
920
|
+
write_comment(g, p);
|
889
921
|
g->V[0] = p->name;
|
890
922
|
g->S[0] = s;
|
891
|
-
w(g, "~M~V0 ~S0 ");
|
923
|
+
w(g, "~M~V0 ~S0 ");
|
924
|
+
generate_AE(g, p->AE);
|
925
|
+
w(g, ";~N");
|
892
926
|
}
|
893
927
|
|
894
|
-
static void generate_integer_test(struct generator * g, struct node * p
|
895
|
-
|
896
|
-
|
928
|
+
static void generate_integer_test(struct generator * g, struct node * p) {
|
929
|
+
write_comment(g, p);
|
930
|
+
int relop = p->type;
|
931
|
+
int optimise_to_return = (g->failure_label == x_return && p->right && p->right->type == c_functionend);
|
932
|
+
if (optimise_to_return) {
|
933
|
+
w(g, "~Mreturn ");
|
934
|
+
p->right = NULL;
|
935
|
+
} else {
|
936
|
+
w(g, "~Mif (");
|
937
|
+
// We want the inverse of the snowball test here.
|
938
|
+
relop ^= 1;
|
939
|
+
}
|
897
940
|
generate_AE(g, p->left);
|
898
|
-
|
899
|
-
|
900
|
-
write_char(g, ' ');
|
941
|
+
// Relational operators are the same as C.
|
942
|
+
write_c_relop(g, relop);
|
901
943
|
generate_AE(g, p->AE);
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
|
906
|
-
|
944
|
+
if (optimise_to_return) {
|
945
|
+
w(g, ";~N");
|
946
|
+
} else {
|
947
|
+
w(g, ")~N");
|
948
|
+
write_block_start(g);
|
949
|
+
write_failure(g);
|
950
|
+
write_block_end(g);
|
951
|
+
g->unreachable = false;
|
952
|
+
}
|
907
953
|
}
|
908
954
|
|
909
955
|
static void generate_call(struct generator * g, struct node * p) {
|
910
|
-
|
956
|
+
int signals = check_possible_signals_list(g, p->name->definition, c_define, 0);
|
911
957
|
write_comment(g, p);
|
912
958
|
g->V[0] = p->name;
|
913
|
-
|
959
|
+
if (g->failure_label == x_return &&
|
960
|
+
(signals == 0 || (p->right && p->right->type == c_functionend))) {
|
961
|
+
/* Always fails or tail call. */
|
962
|
+
writef(g, "~Mreturn ~V0();~N", p);
|
963
|
+
return;
|
964
|
+
}
|
965
|
+
if (signals == 1) {
|
966
|
+
/* Always succeeds. */
|
967
|
+
writef(g, "~M~V0();~N", p);
|
968
|
+
} else if (signals == 0) {
|
969
|
+
/* Always fails. */
|
970
|
+
writef(g, "~M~V0();~N", p);
|
971
|
+
write_failure(g);
|
972
|
+
} else {
|
973
|
+
write_failure_if(g, "!~V0()", p);
|
974
|
+
}
|
914
975
|
}
|
915
976
|
|
916
977
|
static void generate_grouping(struct generator * g, struct node * p, int complement) {
|
978
|
+
write_comment(g, p);
|
917
979
|
|
918
980
|
struct grouping * q = p->name->grouping;
|
919
981
|
g->S[0] = p->mode == m_forward ? "" : "_b";
|
@@ -925,7 +987,6 @@ static void generate_grouping(struct generator * g, struct node * p, int complem
|
|
925
987
|
}
|
926
988
|
|
927
989
|
static void generate_namedstring(struct generator * g, struct node * p) {
|
928
|
-
|
929
990
|
write_comment(g, p);
|
930
991
|
g->S[0] = p->mode == m_forward ? "" : "_b";
|
931
992
|
g->V[0] = p->name;
|
@@ -942,21 +1003,22 @@ static void generate_literalstring(struct generator * g, struct node * p) {
|
|
942
1003
|
|
943
1004
|
static void generate_define(struct generator * g, struct node * p) {
|
944
1005
|
struct name * q = p->name;
|
1006
|
+
if (q->type == t_routine && !q->used) return;
|
945
1007
|
|
946
|
-
|
1008
|
+
write_newline(g);
|
1009
|
+
write_comment(g, p);
|
947
1010
|
|
948
|
-
|
949
|
-
* be required to allow the SnowballProgram base class to invoke them.
|
950
|
-
* FIXME: Is this avoidable?
|
951
|
-
*/
|
952
|
-
if (q->type == t_routine && !q->used_in_among) {
|
1011
|
+
if (q->type == t_routine) {
|
953
1012
|
g->S[0] = "private";
|
954
1013
|
} else {
|
1014
|
+
w(g, "~M@Override~N");
|
955
1015
|
g->S[0] = "public";
|
956
1016
|
}
|
957
1017
|
g->V[0] = q;
|
958
|
-
w(g, "~
|
1018
|
+
w(g, "~M~S0 boolean ~V0() {~+~N");
|
959
1019
|
|
1020
|
+
/* Save output. */
|
1021
|
+
struct str * saved_output = g->outbuf;
|
960
1022
|
g->outbuf = str_new();
|
961
1023
|
|
962
1024
|
g->next_label = 0;
|
@@ -966,8 +1028,16 @@ static void generate_define(struct generator * g, struct node * p) {
|
|
966
1028
|
str_clear(g->failure_str);
|
967
1029
|
g->failure_label = x_return;
|
968
1030
|
g->unreachable = false;
|
1031
|
+
int signals = check_possible_signals_list(g, p->left, c_define, 0);
|
1032
|
+
|
1033
|
+
/* Generate function body. */
|
969
1034
|
generate(g, p->left);
|
970
|
-
if (
|
1035
|
+
if (p->left->right) {
|
1036
|
+
assert(p->left->right->type == c_functionend);
|
1037
|
+
if (signals) {
|
1038
|
+
generate(g, p->left->right);
|
1039
|
+
}
|
1040
|
+
}
|
971
1041
|
w(g, "~}");
|
972
1042
|
|
973
1043
|
str_append(saved_output, g->outbuf);
|
@@ -975,38 +1045,46 @@ static void generate_define(struct generator * g, struct node * p) {
|
|
975
1045
|
g->outbuf = saved_output;
|
976
1046
|
}
|
977
1047
|
|
1048
|
+
static void generate_functionend(struct generator * g, struct node * p) {
|
1049
|
+
(void)p;
|
1050
|
+
w(g, "~Mreturn true;~N");
|
1051
|
+
}
|
1052
|
+
|
978
1053
|
static void generate_substring(struct generator * g, struct node * p) {
|
1054
|
+
write_comment(g, p);
|
979
1055
|
|
980
1056
|
struct among * x = p->among;
|
981
1057
|
|
982
|
-
write_comment(g, p);
|
983
|
-
|
984
1058
|
g->S[0] = p->mode == m_forward ? "" : "_b";
|
985
1059
|
g->I[0] = x->number;
|
986
1060
|
|
987
|
-
if (
|
988
|
-
write_failure_if(g, "find_among~S0(a_~I0) == 0", p);
|
989
|
-
} else {
|
1061
|
+
if (x->amongvar_needed) {
|
990
1062
|
writef(g, "~Mamong_var = find_among~S0(a_~I0);~N", p);
|
991
|
-
|
1063
|
+
if (!x->always_matches) {
|
1064
|
+
write_failure_if(g, "among_var == 0", p);
|
1065
|
+
}
|
1066
|
+
} else if (x->always_matches) {
|
1067
|
+
writef(g, "~Mfind_among~S0(a_~I0);~N", p);
|
1068
|
+
} else {
|
1069
|
+
write_failure_if(g, "find_among~S0(a_~I0) == 0", p);
|
992
1070
|
}
|
993
1071
|
}
|
994
1072
|
|
995
1073
|
static void generate_among(struct generator * g, struct node * p) {
|
996
|
-
|
997
1074
|
struct among * x = p->among;
|
998
1075
|
|
999
|
-
if (x->substring ==
|
1000
|
-
|
1001
|
-
|
1076
|
+
if (x->substring == NULL) {
|
1077
|
+
generate_substring(g, p);
|
1078
|
+
} else {
|
1079
|
+
write_comment(g, p);
|
1080
|
+
}
|
1002
1081
|
|
1003
1082
|
if (x->command_count == 1 && x->nocommand_count == 0) {
|
1004
1083
|
/* Only one outcome ("no match" already handled). */
|
1005
1084
|
generate(g, x->commands[0]);
|
1006
1085
|
} else if (x->command_count > 0) {
|
1007
|
-
int i;
|
1008
1086
|
w(g, "~Mswitch (among_var) {~N~+");
|
1009
|
-
for (i = 1; i <= x->command_count; i++) {
|
1087
|
+
for (int i = 1; i <= x->command_count; i++) {
|
1010
1088
|
g->I[0] = i;
|
1011
1089
|
w(g, "~Mcase ~I0:~N~+");
|
1012
1090
|
generate(g, x->commands[i - 1]);
|
@@ -1019,20 +1097,17 @@ static void generate_among(struct generator * g, struct node * p) {
|
|
1019
1097
|
}
|
1020
1098
|
|
1021
1099
|
static void generate_booltest(struct generator * g, struct node * p) {
|
1022
|
-
|
1023
1100
|
write_comment(g, p);
|
1024
1101
|
g->V[0] = p->name;
|
1025
1102
|
write_failure_if(g, "!(~V0)", p);
|
1026
1103
|
}
|
1027
1104
|
|
1028
1105
|
static void generate_false(struct generator * g, struct node * p) {
|
1029
|
-
|
1030
1106
|
write_comment(g, p);
|
1031
1107
|
write_failure(g);
|
1032
1108
|
}
|
1033
1109
|
|
1034
1110
|
static void generate_debug(struct generator * g, struct node * p) {
|
1035
|
-
|
1036
1111
|
write_comment(g, p);
|
1037
1112
|
g->I[0] = g->debug_count++;
|
1038
1113
|
g->I[1] = p->line_number;
|
@@ -1040,14 +1115,10 @@ static void generate_debug(struct generator * g, struct node * p) {
|
|
1040
1115
|
}
|
1041
1116
|
|
1042
1117
|
static void generate(struct generator * g, struct node * p) {
|
1043
|
-
|
1044
|
-
int a0;
|
1045
|
-
struct str * a1;
|
1046
|
-
|
1047
1118
|
if (g->unreachable) return;
|
1048
1119
|
|
1049
|
-
a0 = g->failure_label;
|
1050
|
-
a1 = str_copy(g->failure_str);
|
1120
|
+
int a0 = g->failure_label;
|
1121
|
+
struct str * a1 = str_copy(g->failure_str);
|
1051
1122
|
|
1052
1123
|
switch (p->type) {
|
1053
1124
|
case c_define: generate_define(g, p); break;
|
@@ -1065,6 +1136,11 @@ static void generate(struct generator * g, struct node * p) {
|
|
1065
1136
|
case c_do: generate_do(g, p); break;
|
1066
1137
|
case c_goto: generate_GO(g, p, 1); break;
|
1067
1138
|
case c_gopast: generate_GO(g, p, 0); break;
|
1139
|
+
case c_goto_grouping: generate_GO_grouping(g, p, 1, 0); break;
|
1140
|
+
case c_gopast_grouping:
|
1141
|
+
generate_GO_grouping(g, p, 0, 0); break;
|
1142
|
+
case c_goto_non: generate_GO_grouping(g, p, 1, 1); break;
|
1143
|
+
case c_gopast_non: generate_GO_grouping(g, p, 0, 1); break;
|
1068
1144
|
case c_repeat: generate_repeat(g, p); break;
|
1069
1145
|
case c_loop: generate_loop(g, p); break;
|
1070
1146
|
case c_atleast: generate_atleast(g, p); break;
|
@@ -1091,12 +1167,14 @@ static void generate(struct generator * g, struct node * p) {
|
|
1091
1167
|
case c_minusassign: generate_integer_assign(g, p, "-="); break;
|
1092
1168
|
case c_multiplyassign:generate_integer_assign(g, p, "*="); break;
|
1093
1169
|
case c_divideassign: generate_integer_assign(g, p, "/="); break;
|
1094
|
-
case c_eq:
|
1095
|
-
case c_ne:
|
1096
|
-
case
|
1097
|
-
case c_ge:
|
1098
|
-
case
|
1099
|
-
case c_le:
|
1170
|
+
case c_eq:
|
1171
|
+
case c_ne:
|
1172
|
+
case c_gt:
|
1173
|
+
case c_ge:
|
1174
|
+
case c_lt:
|
1175
|
+
case c_le:
|
1176
|
+
generate_integer_test(g, p);
|
1177
|
+
break;
|
1100
1178
|
case c_call: generate_call(g, p); break;
|
1101
1179
|
case c_grouping: generate_grouping(g, p, false); break;
|
1102
1180
|
case c_non: generate_grouping(g, p, true); break;
|
@@ -1108,6 +1186,7 @@ static void generate(struct generator * g, struct node * p) {
|
|
1108
1186
|
case c_false: generate_false(g, p); break;
|
1109
1187
|
case c_true: break;
|
1110
1188
|
case c_debug: generate_debug(g, p); break;
|
1189
|
+
case c_functionend: generate_functionend(g, p); break;
|
1111
1190
|
default: fprintf(stderr, "%d encountered\n", p->type);
|
1112
1191
|
exit(1);
|
1113
1192
|
}
|
@@ -1118,7 +1197,6 @@ static void generate(struct generator * g, struct node * p) {
|
|
1118
1197
|
}
|
1119
1198
|
|
1120
1199
|
static void generate_class_begin(struct generator * g) {
|
1121
|
-
|
1122
1200
|
w(g, "package ");
|
1123
1201
|
w(g, g->options->package);
|
1124
1202
|
w(g, ";~N~N");
|
@@ -1147,65 +1225,61 @@ static void generate_class_begin(struct generator * g) {
|
|
1147
1225
|
w(g, g->options->parent_class_name);
|
1148
1226
|
w(g, " {~+~N"
|
1149
1227
|
"~N"
|
1150
|
-
"~Mprivate static final long serialVersionUID = 1L;~N"
|
1151
|
-
|
1228
|
+
"~Mprivate static final long serialVersionUID = 1L;~N");
|
1229
|
+
if (g->analyser->among_with_function_count > 0) {
|
1230
|
+
w(g, "~Mprivate static final java.lang.invoke.MethodHandles.Lookup methodObject = java.lang.invoke.MethodHandles.lookup();~N");
|
1231
|
+
}
|
1232
|
+
write_newline(g);
|
1152
1233
|
}
|
1153
1234
|
|
1154
1235
|
static void generate_class_end(struct generator * g) {
|
1155
|
-
|
1156
1236
|
w(g, "~N}");
|
1157
|
-
w(g, "~N
|
1237
|
+
w(g, "~N");
|
1158
1238
|
}
|
1159
1239
|
|
1160
1240
|
static void generate_equals(struct generator * g) {
|
1161
|
-
|
1162
1241
|
w(g, "~N"
|
1163
|
-
"@Override~N"
|
1242
|
+
"~M@Override~N"
|
1164
1243
|
"~Mpublic boolean equals( Object o ) {~N"
|
1165
1244
|
"~+~Mreturn o instanceof ");
|
1166
1245
|
w(g, g->options->name);
|
1167
1246
|
w(g, ";~N~-~M}~N"
|
1168
1247
|
"~N"
|
1169
|
-
"@Override~N"
|
1248
|
+
"~M@Override~N"
|
1170
1249
|
"~Mpublic int hashCode() {~N"
|
1171
1250
|
"~+~Mreturn ");
|
1172
1251
|
w(g, g->options->name);
|
1173
1252
|
w(g, ".class.getName().hashCode();~N"
|
1174
1253
|
"~-~M}~N");
|
1175
|
-
w(g, "~N~N");
|
1176
1254
|
}
|
1177
1255
|
|
1178
1256
|
static void generate_among_table(struct generator * g, struct among * x) {
|
1257
|
+
write_comment(g, x->node);
|
1179
1258
|
|
1180
1259
|
struct amongvec * v = x->b;
|
1181
1260
|
|
1182
1261
|
g->I[0] = x->number;
|
1183
1262
|
|
1184
|
-
w(g, "~Mprivate final static Among a_~I0
|
1185
|
-
{
|
1186
|
-
|
1187
|
-
|
1188
|
-
|
1189
|
-
|
1190
|
-
|
1191
|
-
|
1192
|
-
|
1193
|
-
w(g, "
|
1194
|
-
|
1195
|
-
|
1196
|
-
write_varname(g, v->function);
|
1197
|
-
w(g, "\", ~n.class");
|
1198
|
-
}
|
1199
|
-
w(g, ")~S0~N");
|
1200
|
-
v++;
|
1263
|
+
w(g, "~Mprivate final static Among[] a_~I0 = {~N~+");
|
1264
|
+
for (int i = 0; i < x->literalstring_count; i++) {
|
1265
|
+
g->I[0] = v[i].i;
|
1266
|
+
g->I[1] = v[i].result;
|
1267
|
+
g->L[0] = v[i].b;
|
1268
|
+
g->S[0] = i < x->literalstring_count - 1 ? "," : "";
|
1269
|
+
|
1270
|
+
w(g, "~Mnew Among(~L0, ~I0, ~I1");
|
1271
|
+
if (v[i].function != NULL) {
|
1272
|
+
w(g, ", \"");
|
1273
|
+
write_varname(g, v[i].function);
|
1274
|
+
w(g, "\", methodObject");
|
1201
1275
|
}
|
1276
|
+
w(g, ")~S0~N");
|
1202
1277
|
}
|
1203
1278
|
w(g, "~-~M};~N~N");
|
1204
1279
|
}
|
1205
1280
|
|
1206
1281
|
static void generate_amongs(struct generator * g) {
|
1207
|
-
struct among * x;
|
1208
|
-
for (x = g->analyser->amongs; x; x = x->next) {
|
1282
|
+
for (struct among * x = g->analyser->amongs; x; x = x->next) {
|
1209
1283
|
generate_among_table(g, x);
|
1210
1284
|
}
|
1211
1285
|
}
|
@@ -1213,41 +1287,37 @@ static void generate_amongs(struct generator * g) {
|
|
1213
1287
|
static void set_bit(symbol * b, int i) { b[i/8] |= 1 << i%8; }
|
1214
1288
|
|
1215
1289
|
static void generate_grouping_table(struct generator * g, struct grouping * q) {
|
1216
|
-
|
1217
1290
|
int range = q->largest_ch - q->smallest_ch + 1;
|
1218
1291
|
int size = (range + 7)/ 8; /* assume 8 bits per symbol */
|
1219
1292
|
symbol * b = q->b;
|
1220
1293
|
symbol * map = create_b(size);
|
1221
|
-
int i;
|
1222
|
-
for (i = 0; i < size; i++) map[i] = 0;
|
1223
1294
|
|
1224
|
-
|
1295
|
+
for (int i = 0; i < size; i++) map[i] = 0;
|
1225
1296
|
|
1226
|
-
for (i = 0; i < SIZE(b); i++) set_bit(map, b[i] - q->smallest_ch);
|
1297
|
+
for (int i = 0; i < SIZE(b); i++) set_bit(map, b[i] - q->smallest_ch);
|
1227
1298
|
|
1228
1299
|
g->V[0] = q->name;
|
1229
|
-
|
1230
|
-
|
1231
|
-
for (i = 0; i < size; i++) {
|
1300
|
+
w(g, "~Mprivate static final char[] ~V0 = {");
|
1301
|
+
for (int i = 0; i < size; i++) {
|
1232
1302
|
write_int(g, map[i]);
|
1233
1303
|
if (i < size - 1) w(g, ", ");
|
1234
1304
|
}
|
1235
1305
|
w(g, " };~N~N");
|
1306
|
+
|
1236
1307
|
lose_b(map);
|
1237
1308
|
}
|
1238
1309
|
|
1239
1310
|
static void generate_groupings(struct generator * g) {
|
1240
|
-
struct grouping * q;
|
1241
|
-
for (q = g->analyser->groupings; q; q = q->next) {
|
1311
|
+
for (struct grouping * q = g->analyser->groupings; q; q = q->next) {
|
1242
1312
|
if (q->name->used)
|
1243
1313
|
generate_grouping_table(g, q);
|
1244
1314
|
}
|
1245
1315
|
}
|
1246
1316
|
|
1247
1317
|
static void generate_members(struct generator * g) {
|
1318
|
+
int wrote_members = false;
|
1248
1319
|
|
1249
|
-
struct name * q;
|
1250
|
-
for (q = g->analyser->names; q; q = q->next) {
|
1320
|
+
for (struct name * q = g->analyser->names; q; q = q->next) {
|
1251
1321
|
g->V[0] = q;
|
1252
1322
|
switch (q->type) {
|
1253
1323
|
case t_string:
|
@@ -1256,32 +1326,34 @@ static void generate_members(struct generator * g) {
|
|
1256
1326
|
w(g, " ~W0 = new ");
|
1257
1327
|
w(g, g->options->string_class);
|
1258
1328
|
w(g, "();~N");
|
1329
|
+
wrote_members = true;
|
1259
1330
|
break;
|
1260
1331
|
case t_integer:
|
1261
1332
|
w(g, "~Mprivate int ~W0;~N");
|
1333
|
+
wrote_members = true;
|
1262
1334
|
break;
|
1263
1335
|
case t_boolean:
|
1264
1336
|
w(g, "~Mprivate boolean ~W0;~N");
|
1337
|
+
wrote_members = true;
|
1265
1338
|
break;
|
1266
1339
|
}
|
1267
1340
|
}
|
1268
|
-
w(g, "~N");
|
1341
|
+
if (wrote_members) w(g, "~N");
|
1269
1342
|
}
|
1270
1343
|
|
1271
1344
|
static void generate_methods(struct generator * g) {
|
1272
|
-
|
1273
|
-
struct node * p;
|
1274
|
-
for (p = g->analyser->program; p; p = p->right) {
|
1345
|
+
for (struct node * p = g->analyser->program; p; p = p->right) {
|
1275
1346
|
generate(g, p);
|
1276
1347
|
g->unreachable = false;
|
1277
1348
|
}
|
1278
1349
|
}
|
1279
1350
|
|
1280
1351
|
extern void generate_program_java(struct generator * g) {
|
1281
|
-
|
1282
1352
|
g->outbuf = str_new();
|
1283
1353
|
g->failure_str = str_new();
|
1284
1354
|
|
1355
|
+
w(g, "~+");
|
1356
|
+
|
1285
1357
|
generate_amongs(g);
|
1286
1358
|
generate_groupings(g);
|
1287
1359
|
|
@@ -1291,6 +1363,8 @@ extern void generate_program_java(struct generator * g) {
|
|
1291
1363
|
|
1292
1364
|
generate_class_end(g);
|
1293
1365
|
|
1366
|
+
w(g, "~-");
|
1367
|
+
|
1294
1368
|
{
|
1295
1369
|
/* We need to call generate_class_begin() after we've generated the
|
1296
1370
|
* methods so we know if copy_from_count > 0.
|