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