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