mittens 0.3.0 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/Gemfile +2 -1
- data/README.md +2 -2
- data/Rakefile +12 -5
- data/ext/mittens/extconf.rb +3 -1
- data/lib/mittens/version.rb +1 -1
- data/vendor/snowball/.github/workflows/ci.yml +144 -17
- data/vendor/snowball/.github/workflows/coverage.yml +117 -0
- data/vendor/snowball/.github/workflows/runtime-tests.yml +26 -0
- data/vendor/snowball/.gitignore +33 -7
- data/vendor/snowball/CONTRIBUTING.rst +7 -0
- data/vendor/snowball/COPYING +1 -1
- data/vendor/snowball/GNUmakefile +736 -298
- data/vendor/snowball/NEWS +1394 -7
- data/vendor/snowball/README.rst +8 -8
- data/vendor/snowball/ada/generate/generate.adb +5 -5
- data/vendor/snowball/ada/src/stemmer.adb +177 -188
- data/vendor/snowball/ada/src/stemmer.ads +86 -89
- data/vendor/snowball/ada/src/stemwords.adb +21 -5
- data/vendor/snowball/algorithms/czech.sbl +255 -0
- data/vendor/snowball/algorithms/danish.sbl +22 -10
- data/vendor/snowball/algorithms/english.sbl +7 -4
- data/vendor/snowball/algorithms/esperanto.sbl +6 -7
- data/vendor/snowball/algorithms/estonian.sbl +9 -4
- data/vendor/snowball/algorithms/finnish.sbl +33 -21
- data/vendor/snowball/algorithms/german.sbl +5 -0
- data/vendor/snowball/algorithms/indonesian.sbl +115 -96
- data/vendor/snowball/algorithms/italian.sbl +26 -1
- data/vendor/snowball/algorithms/lithuanian.sbl +13 -13
- data/vendor/snowball/algorithms/norwegian.sbl +17 -6
- data/vendor/snowball/algorithms/persian.sbl +387 -0
- data/vendor/snowball/algorithms/polish.sbl +177 -0
- data/vendor/snowball/algorithms/sesotho.sbl +115 -0
- data/vendor/snowball/algorithms/turkish.sbl +4 -4
- data/vendor/snowball/compiler/analyser.c +2002 -711
- data/vendor/snowball/compiler/driver.c +460 -298
- data/vendor/snowball/compiler/generator.c +439 -1965
- data/vendor/snowball/compiler/generator_ada.c +605 -430
- data/vendor/snowball/compiler/generator_c.c +2227 -0
- data/vendor/snowball/compiler/generator_csharp.c +365 -274
- data/vendor/snowball/compiler/generator_dart.c +1476 -0
- data/vendor/snowball/compiler/generator_go.c +348 -270
- data/vendor/snowball/compiler/generator_java.c +330 -233
- data/vendor/snowball/compiler/generator_js.c +534 -385
- data/vendor/snowball/compiler/generator_pascal.c +361 -320
- data/vendor/snowball/compiler/generator_php.c +1445 -0
- data/vendor/snowball/compiler/generator_python.c +399 -299
- data/vendor/snowball/compiler/generator_rust.c +370 -261
- data/vendor/snowball/compiler/generator_zig.c +1474 -0
- data/vendor/snowball/compiler/header.h +153 -86
- data/vendor/snowball/compiler/space.c +121 -63
- data/vendor/snowball/compiler/tokeniser.c +286 -182
- data/vendor/snowball/compiler/tokens.h +71 -0
- data/vendor/snowball/csharp/Snowball/Among.cs +14 -26
- data/vendor/snowball/csharp/Snowball/AssemblyInfo.cs +3 -3
- data/vendor/snowball/csharp/Snowball/Stemmer.cs +41 -45
- data/vendor/snowball/csharp/Stemwords/Program.cs +20 -14
- data/vendor/snowball/cxx/.gitignore +4 -0
- data/vendor/snowball/cxx/generate_algorithms.pl +87 -0
- data/vendor/snowball/cxx/stemmer.h +12 -0
- data/vendor/snowball/cxx/stemwords.cxx +176 -0
- data/vendor/snowball/cxx/utilities.cxx +2 -0
- data/vendor/snowball/dart/.gitignore +4 -0
- data/vendor/snowball/dart/analysis_options.yaml +1 -0
- data/vendor/snowball/dart/example/test_app.dart +65 -0
- data/vendor/snowball/dart/generate_algorithms.pl +21 -0
- data/vendor/snowball/dart/lib/snowball.dart +18 -0
- data/vendor/snowball/dart/lib/src/snowball.dart +339 -0
- data/vendor/snowball/dart/pubspec.yaml +17 -0
- data/vendor/snowball/doc/libstemmer_dart_README +37 -0
- data/vendor/snowball/doc/libstemmer_js_README +2 -2
- data/vendor/snowball/doc/libstemmer_php_README +38 -0
- data/vendor/snowball/doc/libstemmer_python_README +3 -3
- data/vendor/snowball/examples/stemwords.c +18 -3
- data/vendor/snowball/go/README.md +12 -4
- data/vendor/snowball/go/env.go +12 -14
- data/vendor/snowball/go/stemwords/main.go +2 -1
- data/vendor/snowball/java/org/tartarus/snowball/CharArraySequence.java +36 -0
- data/vendor/snowball/java/org/tartarus/snowball/SnowballProgram.java +17 -34
- data/vendor/snowball/java/org/tartarus/snowball/SnowballStemmer.java +0 -2
- data/vendor/snowball/javascript/base-stemmer.js +219 -252
- data/vendor/snowball/javascript/stemwords.js +86 -58
- data/vendor/snowball/libstemmer/mkmodules.pl +1 -1
- data/vendor/snowball/libstemmer/modules.txt +4 -0
- data/vendor/snowball/pascal/SnowballProgram.pas +18 -31
- data/vendor/snowball/php/base-stemmer.php +453 -0
- data/vendor/snowball/php/stemwords.php +25 -0
- data/vendor/snowball/python/create_init.py +16 -21
- data/vendor/snowball/python/pyproject.toml +3 -0
- data/vendor/snowball/python/setup.py +5 -7
- data/vendor/snowball/python/snowballstemmer/among.py +1 -2
- data/vendor/snowball/python/snowballstemmer/basestemmer.py +24 -33
- data/vendor/snowball/python/stemwords.py +72 -63
- data/vendor/snowball/runtime/api.c +11 -42
- data/vendor/snowball/runtime/api.h +11 -9
- data/vendor/snowball/runtime/snowball_runtime.h +110 -0
- data/vendor/snowball/runtime/utilities.c +282 -106
- data/vendor/snowball/rust/src/main.rs +2 -2
- data/vendor/snowball/rust/src/snowball/snowball_env.rs +7 -9
- data/vendor/snowball/tests/compilertest +62 -0
- data/vendor/snowball/tests/errors/ae-errors.sbl +53 -0
- data/vendor/snowball/tests/errors/ae-errors.stderr +8 -0
- data/vendor/snowball/tests/errors/bad-dollar.sbl +14 -0
- data/vendor/snowball/tests/errors/bad-dollar.stderr +4 -0
- data/vendor/snowball/tests/errors/bad-grouping-definition.sbl +9 -0
- data/vendor/snowball/tests/errors/bad-grouping-definition.stderr +6 -0
- data/vendor/snowball/tests/errors/missing-bra.sbl +6 -0
- data/vendor/snowball/tests/errors/missing-bra.stderr +3 -0
- data/vendor/snowball/tests/errors/missing-command.sbl +9 -0
- data/vendor/snowball/tests/errors/missing-command.stderr +1 -0
- data/vendor/snowball/tests/errors/missing-ket-backwardmode.sbl +3 -0
- data/vendor/snowball/tests/errors/missing-ket-backwardmode.stderr +1 -0
- data/vendor/snowball/tests/errors/missing-ket.sbl +7 -0
- data/vendor/snowball/tests/errors/missing-ket.stderr +6 -0
- data/vendor/snowball/tests/errors/notdefined.sbl +4 -0
- data/vendor/snowball/tests/errors/notdefined.stderr +2 -0
- data/vendor/snowball/tests/errors/string-omitted.sbl +5 -0
- data/vendor/snowball/tests/errors/string-omitted.stderr +1 -0
- data/vendor/snowball/tests/errors/undeclared.sbl +20 -0
- data/vendor/snowball/tests/errors/undeclared.stderr +9 -0
- data/vendor/snowball/tests/errors/unexpected-token.sbl +24 -0
- data/vendor/snowball/tests/errors/unexpected-token.stderr +17 -0
- data/vendor/snowball/tests/errors/wrongdirection.sbl +14 -0
- data/vendor/snowball/tests/errors/wrongdirection.stderr +1 -0
- data/vendor/snowball/tests/runtime/among.sbl +19 -0
- data/vendor/snowball/tests/runtime/arithmeticexpr.sbl +86 -0
- data/vendor/snowball/tests/runtime/attachinsert.sbl +47 -0
- data/vendor/snowball/tests/runtime/booleans.sbl +19 -0
- data/vendor/snowball/tests/runtime/externals.sbl +22 -0
- data/vendor/snowball/tests/runtime/hop.sbl +12 -0
- data/vendor/snowball/tests/runtime/integertests.sbl +60 -0
- data/vendor/snowball/tests/runtime/intlimits.sbl +25 -0
- data/vendor/snowball/tests/runtime/naming.sbl +20 -0
- data/vendor/snowball/tests/runtime/not.sbl +30 -0
- data/vendor/snowball/tests/runtime/or.sbl +17 -0
- data/vendor/snowball/tests/runtime/repeat.sbl +16 -0
- data/vendor/snowball/tests/runtime/setlimit.sbl +24 -0
- data/vendor/snowball/tests/runtime/sizelen.sbl +56 -0
- data/vendor/snowball/tests/runtime/slice.sbl +27 -0
- data/vendor/snowball/tests/runtime/stringdollar.sbl +39 -0
- data/vendor/snowball/tests/runtime/strings.sbl +66 -0
- data/vendor/snowball/tests/runtime/test.sbl +19 -0
- data/vendor/snowball/tests/stemtest.c +41 -1
- data/vendor/snowball/tests/syntax/canon.sbl +32 -0
- data/vendor/snowball/tests/syntax/canon.stderr +0 -0
- data/vendor/snowball/tests/syntax/canon.syntax +57 -0
- data/vendor/snowball/tests/syntax/emptyprogram.sbl +2 -0
- data/vendor/snowball/tests/syntax/emptyprogram.syntax +0 -0
- data/vendor/snowball/tests/syntax/groupings.sbl +11 -0
- data/vendor/snowball/tests/syntax/inline.sbl +144 -0
- data/vendor/snowball/tests/syntax/inline.stderr +0 -0
- data/vendor/snowball/tests/syntax/inline.syntax +121 -0
- data/vendor/snowball/tests/syntax/legacy.sbl +17 -0
- data/vendor/snowball/tests/syntax/legacy.stderr +5 -0
- data/vendor/snowball/tests/syntax/legacy.syntax +19 -0
- data/vendor/snowball/tests/syntax/loops.sbl +14 -0
- data/vendor/snowball/tests/syntax/loops.stderr +9 -0
- data/vendor/snowball/tests/syntax/loops.syntax +29 -0
- data/vendor/snowball/tests/syntax/noops.sbl +76 -0
- data/vendor/snowball/tests/syntax/noops.stderr +27 -0
- data/vendor/snowball/tests/syntax/noops.syntax +135 -0
- data/vendor/snowball/tests/syntax/simplifyae.sbl +21 -0
- data/vendor/snowball/tests/syntax/simplifyae.stderr +0 -0
- data/vendor/snowball/tests/syntax/simplifyae.syntax +39 -0
- data/vendor/snowball/tests/syntax/unused.sbl +18 -0
- data/vendor/snowball/tests/syntax/unused.stderr +7 -0
- data/vendor/snowball/tests/syntax/unused.syntax +3 -0
- data/vendor/snowball/zig/env.zig +599 -0
- data/vendor/snowball/zig/generate_algorithms.pl +19 -0
- data/vendor/snowball/zig/stemwords.zig +123 -0
- metadata +102 -4
- data/vendor/snowball/compiler/syswords.h +0 -86
- data/vendor/snowball/runtime/header.h +0 -62
|
@@ -1,77 +1,57 @@
|
|
|
1
1
|
#include <assert.h>
|
|
2
|
+
#include <ctype.h> /* for toupper */
|
|
3
|
+
#include <stdio.h> /* for fprintf etc */
|
|
2
4
|
#include <stdlib.h> /* for exit */
|
|
3
5
|
#include <string.h> /* for strlen */
|
|
4
|
-
#include <stdio.h> /* for fprintf etc */
|
|
5
|
-
#include <ctype.h> /* for toupper */
|
|
6
6
|
#include "header.h"
|
|
7
7
|
|
|
8
|
-
/*
|
|
8
|
+
/* prototype functions for recursive use: */
|
|
9
9
|
|
|
10
10
|
static void generate(struct generator * g, struct node * p);
|
|
11
11
|
static void w(struct generator * g, const char * s);
|
|
12
12
|
static void writef(struct generator * g, const char * s, struct node * p);
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
return g->next_label++;
|
|
16
|
-
}
|
|
14
|
+
/* Write routines for items from the syntax tree */
|
|
17
15
|
|
|
18
|
-
static
|
|
19
|
-
|
|
20
|
-
g
|
|
21
|
-
output = str_new();
|
|
22
|
-
str_append_string(output, "v_");
|
|
23
|
-
str_append_int(output, g->var_number);
|
|
24
|
-
return output;
|
|
16
|
+
static void write_relop(struct generator * g, int relop) {
|
|
17
|
+
// Relational operators are the same as C.
|
|
18
|
+
write_c_relop(g, relop);
|
|
25
19
|
}
|
|
26
20
|
|
|
27
|
-
/* Write routines for items from the syntax tree */
|
|
28
|
-
|
|
29
21
|
static void write_varname(struct generator * g, struct name * p) {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
p->s[0] = toupper(save_initial);
|
|
34
|
-
str_append_s(g->outbuf, p->s);
|
|
35
|
-
p->s[0] = save_initial;
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
default: {
|
|
39
|
-
int ch = "SbirxG"[p->type];
|
|
40
|
-
write_char(g, ch);
|
|
41
|
-
write_char(g, '_');
|
|
42
|
-
break;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
22
|
+
// We use the same naming scheme for both global and local variables.
|
|
23
|
+
write_char(g, "SbirrG"[p->type]);
|
|
24
|
+
write_char(g, '_');
|
|
45
25
|
write_s(g, p->s);
|
|
46
26
|
}
|
|
47
27
|
|
|
28
|
+
/* Reference to variable, e.g. when assigning to or using in an expression. */
|
|
48
29
|
static void write_varref(struct generator * g, struct name * p) {
|
|
49
|
-
|
|
30
|
+
if (p->type >= t_routine || p->local_to == NULL) {
|
|
31
|
+
write_string(g, "context.");
|
|
32
|
+
}
|
|
50
33
|
write_varname(g, p);
|
|
51
34
|
}
|
|
52
35
|
|
|
53
36
|
static void write_literal_string(struct generator * g, symbol * p) {
|
|
54
37
|
int i = 0;
|
|
55
|
-
|
|
38
|
+
write_char(g, '"');
|
|
56
39
|
while (i < SIZE(p)) {
|
|
57
40
|
int ch;
|
|
58
41
|
i += get_utf8(p + i, &ch);
|
|
59
|
-
|
|
42
|
+
// Write out ASCII and lower Unicode printables as literal characters.
|
|
43
|
+
// Use escapes for anything over 0x590 as a crude way to avoid LTR
|
|
44
|
+
// characters affecting the rendering of source character order in
|
|
45
|
+
// confusing ways.
|
|
46
|
+
if ((32 <= ch && ch < 127) || (0xa0 < ch && ch < 0x590)) {
|
|
60
47
|
if (ch == '"' || ch == '\\') write_char(g, '\\');
|
|
61
48
|
write_wchar_as_utf8(g, ch);
|
|
62
49
|
} else {
|
|
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
50
|
write_string(g, "\\u");
|
|
67
51
|
write_hex4(g, ch);
|
|
68
52
|
}
|
|
69
53
|
}
|
|
70
|
-
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
static void write_margin(struct generator * g) {
|
|
74
|
-
for (int i = 0; i < g->margin; i++) write_string(g, " ");
|
|
54
|
+
write_char(g, '"');
|
|
75
55
|
}
|
|
76
56
|
|
|
77
57
|
static void write_comment(struct generator * g, struct node * p) {
|
|
@@ -79,7 +59,7 @@ static void write_comment(struct generator * g, struct node * p) {
|
|
|
79
59
|
/* FIXME could use Go //line syntax if we had original filename */
|
|
80
60
|
write_margin(g);
|
|
81
61
|
write_string(g, "// ");
|
|
82
|
-
write_comment_content(g, p);
|
|
62
|
+
write_comment_content(g, p, NULL);
|
|
83
63
|
write_newline(g);
|
|
84
64
|
}
|
|
85
65
|
|
|
@@ -113,24 +93,27 @@ static void write_restorecursor(struct generator * g, struct node * p, struct st
|
|
|
113
93
|
|
|
114
94
|
static void write_inc_cursor(struct generator * g, struct node * p) {
|
|
115
95
|
write_margin(g);
|
|
116
|
-
write_string(g, p->mode == m_forward ? "env.NextChar()
|
|
96
|
+
write_string(g, p->mode == m_forward ? "env.NextChar()" : "env.PrevChar()");
|
|
117
97
|
write_newline(g);
|
|
118
98
|
}
|
|
119
99
|
|
|
120
100
|
static void wsetlab_begin(struct generator * g, int n) {
|
|
121
101
|
g->I[0] = n;
|
|
122
|
-
w(g, "
|
|
102
|
+
w(g, "~-~Mlab~I0:~N~+~Mfor {~N~+");
|
|
123
103
|
}
|
|
124
104
|
|
|
125
105
|
static void wsetlab_end(struct generator * g, int n) {
|
|
126
|
-
g->
|
|
127
|
-
|
|
106
|
+
if (!g->unreachable) {
|
|
107
|
+
g->I[0] = n;
|
|
108
|
+
w(g, "~Mbreak lab~I0~N");
|
|
109
|
+
}
|
|
128
110
|
w(g, "~-~M}~N");
|
|
129
111
|
}
|
|
130
112
|
|
|
131
113
|
static void wgotol(struct generator * g, int n) {
|
|
132
114
|
g->I[0] = n;
|
|
133
115
|
w(g, "~Mbreak lab~I0~N");
|
|
116
|
+
g->unreachable = true;
|
|
134
117
|
}
|
|
135
118
|
|
|
136
119
|
static void write_failure(struct generator * g) {
|
|
@@ -141,14 +124,14 @@ static void write_failure(struct generator * g) {
|
|
|
141
124
|
}
|
|
142
125
|
switch (g->failure_label) {
|
|
143
126
|
case x_return:
|
|
144
|
-
w(g, "~Mreturn false
|
|
145
|
-
g->unreachable = true;
|
|
127
|
+
w(g, "~Mreturn false");
|
|
146
128
|
break;
|
|
147
129
|
default:
|
|
148
|
-
g
|
|
149
|
-
|
|
150
|
-
g->unreachable = true;
|
|
130
|
+
w(g, "~Mbreak lab");
|
|
131
|
+
write_int(g, g->failure_label);
|
|
151
132
|
}
|
|
133
|
+
write_newline(g);
|
|
134
|
+
g->unreachable = true;
|
|
152
135
|
}
|
|
153
136
|
|
|
154
137
|
static void write_failure_if(struct generator * g, const char * s, struct node * p) {
|
|
@@ -172,7 +155,6 @@ static void write_check_limit(struct generator * g, struct node * p) {
|
|
|
172
155
|
|
|
173
156
|
/* Formatted write. */
|
|
174
157
|
static void writef(struct generator * g, const char * input, struct node * p) {
|
|
175
|
-
(void)p;
|
|
176
158
|
int i = 0;
|
|
177
159
|
|
|
178
160
|
while (input[i]) {
|
|
@@ -217,27 +199,29 @@ static void writef(struct generator * g, const char * input, struct node * p) {
|
|
|
217
199
|
write_int(g, g->I[j]);
|
|
218
200
|
continue;
|
|
219
201
|
}
|
|
220
|
-
case '
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
202
|
+
case 'E': {
|
|
203
|
+
// Write an external name.
|
|
204
|
+
if (g->options->externals_prefix) {
|
|
205
|
+
write_string(g, g->options->externals_prefix);
|
|
206
|
+
}
|
|
207
|
+
char save_initial = p->name->s[0];
|
|
208
|
+
p->name->s[0] = toupper(save_initial);
|
|
209
|
+
write_s(g, p->name->s);
|
|
210
|
+
p->name->s[0] = save_initial;
|
|
229
211
|
continue;
|
|
230
212
|
}
|
|
231
|
-
case '
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
213
|
+
case 'V':
|
|
214
|
+
write_varref(g, p->name);
|
|
215
|
+
continue;
|
|
216
|
+
case 'W':
|
|
217
|
+
write_varname(g, p->name);
|
|
218
|
+
continue;
|
|
219
|
+
case 'L':
|
|
220
|
+
write_literal_string(g, p->literalstring);
|
|
236
221
|
continue;
|
|
237
|
-
}
|
|
238
222
|
case '+': g->margin++; continue;
|
|
239
223
|
case '-': g->margin--; continue;
|
|
240
|
-
case 'n':
|
|
224
|
+
case 'n': write_s(g, g->options->name); continue;
|
|
241
225
|
default:
|
|
242
226
|
printf("Invalid escape sequence ~%c in writef(g, \"%s\", p)\n",
|
|
243
227
|
ch, input);
|
|
@@ -258,37 +242,44 @@ static void generate_AE(struct generator * g, struct node * p) {
|
|
|
258
242
|
const char * s;
|
|
259
243
|
switch (p->type) {
|
|
260
244
|
case c_name:
|
|
261
|
-
write_varref(g, p->name);
|
|
245
|
+
write_varref(g, p->name);
|
|
246
|
+
break;
|
|
262
247
|
case c_number:
|
|
263
|
-
write_int(g, p->number);
|
|
248
|
+
write_int(g, p->number);
|
|
249
|
+
break;
|
|
264
250
|
case c_maxint:
|
|
265
|
-
write_string(g, "snowballRuntime.MaxInt");
|
|
251
|
+
write_string(g, "snowballRuntime.MaxInt");
|
|
252
|
+
break;
|
|
266
253
|
case c_minint:
|
|
267
|
-
write_string(g, "snowballRuntime.MinInt");
|
|
254
|
+
write_string(g, "snowballRuntime.MinInt");
|
|
255
|
+
break;
|
|
268
256
|
case c_neg:
|
|
269
|
-
write_char(g, '-');
|
|
257
|
+
write_char(g, '-');
|
|
258
|
+
generate_AE(g, p->right);
|
|
259
|
+
break;
|
|
270
260
|
case c_multiply:
|
|
271
|
-
s = " * ";
|
|
272
|
-
|
|
273
|
-
s = " + "; goto label0;
|
|
274
|
-
case c_minus:
|
|
275
|
-
s = " - "; goto label0;
|
|
261
|
+
s = " * ";
|
|
262
|
+
goto label0;
|
|
276
263
|
case c_divide:
|
|
277
264
|
s = " / ";
|
|
265
|
+
goto label0;
|
|
266
|
+
case c_plus:
|
|
267
|
+
s = " + ";
|
|
268
|
+
goto label0;
|
|
269
|
+
case c_minus:
|
|
270
|
+
s = " - ";
|
|
278
271
|
label0:
|
|
279
|
-
write_char(g, '(');
|
|
280
|
-
|
|
272
|
+
write_char(g, '(');
|
|
273
|
+
generate_AE(g, p->left);
|
|
274
|
+
write_string(g, s);
|
|
275
|
+
generate_AE(g, p->right);
|
|
276
|
+
write_char(g, ')');
|
|
277
|
+
break;
|
|
281
278
|
case c_cursor:
|
|
282
|
-
w(g, "env.Cursor");
|
|
283
|
-
case c_limit:
|
|
284
|
-
w(g, p->mode == m_forward ? "env.Limit" : "env.LimitBackward"); break;
|
|
285
|
-
case c_lenof:
|
|
286
|
-
g->V[0] = p->name;
|
|
287
|
-
w(g, "snowballRuntime.RuneCountInString(~V0)");
|
|
279
|
+
w(g, "env.Cursor");
|
|
288
280
|
break;
|
|
289
|
-
case
|
|
290
|
-
g->
|
|
291
|
-
w(g, "len(~V0)");
|
|
281
|
+
case c_limit:
|
|
282
|
+
w(g, p->mode == m_forward ? "env.Limit" : "env.LimitBackward");
|
|
292
283
|
break;
|
|
293
284
|
case c_len:
|
|
294
285
|
w(g, "snowballRuntime.RuneCountInString(env.Current())");
|
|
@@ -296,6 +287,12 @@ static void generate_AE(struct generator * g, struct node * p) {
|
|
|
296
287
|
case c_size:
|
|
297
288
|
w(g, "len(env.Current())");
|
|
298
289
|
break;
|
|
290
|
+
case c_lenof:
|
|
291
|
+
writef(g, "snowballRuntime.RuneCountInString(~V)", p);
|
|
292
|
+
break;
|
|
293
|
+
case c_sizeof:
|
|
294
|
+
writef(g, "len(~V)", p);
|
|
295
|
+
break;
|
|
299
296
|
}
|
|
300
297
|
}
|
|
301
298
|
|
|
@@ -310,13 +307,15 @@ static void generate_bra(struct generator * g, struct node * p) {
|
|
|
310
307
|
|
|
311
308
|
static void generate_and(struct generator * g, struct node * p) {
|
|
312
309
|
struct str * savevar = NULL;
|
|
313
|
-
if (
|
|
310
|
+
if (K_needed_for_and(p->left)) {
|
|
314
311
|
savevar = vars_newname(g);
|
|
315
312
|
}
|
|
316
313
|
|
|
317
314
|
write_comment(g, p);
|
|
318
315
|
|
|
319
|
-
if (savevar)
|
|
316
|
+
if (savevar) {
|
|
317
|
+
write_savecursor(g, p, savevar);
|
|
318
|
+
}
|
|
320
319
|
|
|
321
320
|
p = p->left;
|
|
322
321
|
while (p) {
|
|
@@ -333,7 +332,7 @@ static void generate_and(struct generator * g, struct node * p) {
|
|
|
333
332
|
|
|
334
333
|
static void generate_or(struct generator * g, struct node * p) {
|
|
335
334
|
struct str * savevar = NULL;
|
|
336
|
-
if (
|
|
335
|
+
if (K_needed_for_or(p->left)) {
|
|
337
336
|
savevar = vars_newname(g);
|
|
338
337
|
}
|
|
339
338
|
|
|
@@ -341,12 +340,14 @@ static void generate_or(struct generator * g, struct node * p) {
|
|
|
341
340
|
struct str * a1 = str_copy(g->failure_str);
|
|
342
341
|
|
|
343
342
|
int out_lab = new_label(g);
|
|
344
|
-
|
|
343
|
+
bool end_unreachable = true;
|
|
345
344
|
|
|
346
345
|
write_comment(g, p);
|
|
347
346
|
wsetlab_begin(g, out_lab);
|
|
348
347
|
|
|
349
|
-
if (savevar
|
|
348
|
+
if (savevar && K_needed_node_on_f(p)) {
|
|
349
|
+
write_savecursor(g, p, savevar);
|
|
350
|
+
}
|
|
350
351
|
|
|
351
352
|
p = p->left;
|
|
352
353
|
str_clear(g->failure_str);
|
|
@@ -366,9 +367,12 @@ static void generate_or(struct generator * g, struct node * p) {
|
|
|
366
367
|
wgotol(g, out_lab);
|
|
367
368
|
end_unreachable = false;
|
|
368
369
|
}
|
|
369
|
-
|
|
370
|
+
|
|
371
|
+
wsetlab_end(g, label);
|
|
370
372
|
g->unreachable = false;
|
|
371
|
-
if (savevar)
|
|
373
|
+
if (savevar) {
|
|
374
|
+
write_restorecursor(g, p, savevar);
|
|
375
|
+
}
|
|
372
376
|
p = p->right;
|
|
373
377
|
}
|
|
374
378
|
|
|
@@ -377,6 +381,7 @@ static void generate_or(struct generator * g, struct node * p) {
|
|
|
377
381
|
g->failure_str = a1;
|
|
378
382
|
|
|
379
383
|
generate(g, p);
|
|
384
|
+
|
|
380
385
|
wsetlab_end(g, out_lab);
|
|
381
386
|
if (!end_unreachable) {
|
|
382
387
|
g->unreachable = false;
|
|
@@ -395,10 +400,9 @@ static void generate_backwards(struct generator * g, struct node * p) {
|
|
|
395
400
|
w(g, "~Menv.Cursor = env.LimitBackward~N");
|
|
396
401
|
}
|
|
397
402
|
|
|
398
|
-
|
|
399
403
|
static void generate_not(struct generator * g, struct node * p) {
|
|
400
404
|
struct str * savevar = NULL;
|
|
401
|
-
if (
|
|
405
|
+
if (K_needed_node_on_f(p->left)) {
|
|
402
406
|
savevar = vars_newname(g);
|
|
403
407
|
}
|
|
404
408
|
|
|
@@ -423,7 +427,8 @@ static void generate_not(struct generator * g, struct node * p) {
|
|
|
423
427
|
g->failure_str = a1;
|
|
424
428
|
|
|
425
429
|
if (!g->unreachable) write_failure(g);
|
|
426
|
-
|
|
430
|
+
|
|
431
|
+
wsetlab_end(g, label);
|
|
427
432
|
|
|
428
433
|
g->unreachable = false;
|
|
429
434
|
|
|
@@ -433,10 +438,9 @@ static void generate_not(struct generator * g, struct node * p) {
|
|
|
433
438
|
}
|
|
434
439
|
}
|
|
435
440
|
|
|
436
|
-
|
|
437
441
|
static void generate_try(struct generator * g, struct node * p) {
|
|
438
442
|
struct str * savevar = NULL;
|
|
439
|
-
if (K_needed(
|
|
443
|
+
if (K_needed(p->left)) {
|
|
440
444
|
savevar = vars_newname(g);
|
|
441
445
|
}
|
|
442
446
|
|
|
@@ -449,6 +453,7 @@ static void generate_try(struct generator * g, struct node * p) {
|
|
|
449
453
|
write_savecursor(g, p, savevar);
|
|
450
454
|
append_restore_string(p, g->failure_str, savevar);
|
|
451
455
|
}
|
|
456
|
+
|
|
452
457
|
wsetlab_begin(g, label);
|
|
453
458
|
generate(g, p->left);
|
|
454
459
|
wsetlab_end(g, label);
|
|
@@ -461,14 +466,12 @@ static void generate_try(struct generator * g, struct node * p) {
|
|
|
461
466
|
|
|
462
467
|
static void generate_set(struct generator * g, struct node * p) {
|
|
463
468
|
write_comment(g, p);
|
|
464
|
-
g
|
|
465
|
-
writef(g, "~M~V0 = true~N", p);
|
|
469
|
+
writef(g, "~M~V = true~N", p);
|
|
466
470
|
}
|
|
467
471
|
|
|
468
472
|
static void generate_unset(struct generator * g, struct node * p) {
|
|
469
473
|
write_comment(g, p);
|
|
470
|
-
g
|
|
471
|
-
writef(g, "~M~V0 = false~N", p);
|
|
474
|
+
writef(g, "~M~V = false~N", p);
|
|
472
475
|
}
|
|
473
476
|
|
|
474
477
|
static void generate_fail(struct generator * g, struct node * p) {
|
|
@@ -478,10 +481,9 @@ static void generate_fail(struct generator * g, struct node * p) {
|
|
|
478
481
|
}
|
|
479
482
|
|
|
480
483
|
/* generate_test() also implements 'reverse' */
|
|
481
|
-
|
|
482
484
|
static void generate_test(struct generator * g, struct node * p) {
|
|
483
485
|
struct str * savevar = NULL;
|
|
484
|
-
if (K_needed(
|
|
486
|
+
if (K_needed(p->left)) {
|
|
485
487
|
savevar = vars_newname(g);
|
|
486
488
|
}
|
|
487
489
|
|
|
@@ -503,18 +505,19 @@ static void generate_test(struct generator * g, struct node * p) {
|
|
|
503
505
|
|
|
504
506
|
static void generate_do(struct generator * g, struct node * p) {
|
|
505
507
|
struct str * savevar = NULL;
|
|
506
|
-
if (K_needed(
|
|
508
|
+
if (K_needed(p->left)) {
|
|
507
509
|
savevar = vars_newname(g);
|
|
508
510
|
}
|
|
509
511
|
|
|
510
512
|
write_comment(g, p);
|
|
511
|
-
if (savevar)
|
|
513
|
+
if (savevar) {
|
|
514
|
+
write_savecursor(g, p, savevar);
|
|
515
|
+
}
|
|
512
516
|
|
|
513
517
|
if (p->left->type == c_call) {
|
|
514
518
|
/* Optimise do <call> */
|
|
515
519
|
write_comment(g, p->left);
|
|
516
|
-
g
|
|
517
|
-
w(g, "~M~W0(env, context)~N");
|
|
520
|
+
writef(g, "~M~W(env, context)~N", p->left);
|
|
518
521
|
} else {
|
|
519
522
|
int label = new_label(g);
|
|
520
523
|
g->failure_label = label;
|
|
@@ -522,6 +525,7 @@ static void generate_do(struct generator * g, struct node * p) {
|
|
|
522
525
|
|
|
523
526
|
wsetlab_begin(g, label);
|
|
524
527
|
generate(g, p->left);
|
|
528
|
+
|
|
525
529
|
wsetlab_end(g, label);
|
|
526
530
|
g->unreachable = false;
|
|
527
531
|
}
|
|
@@ -544,34 +548,34 @@ static void generate_GO_grouping(struct generator * g, struct node * p, int is_g
|
|
|
544
548
|
struct grouping * q = p->name->grouping;
|
|
545
549
|
g->S[0] = p->mode == m_forward ? "" : "B";
|
|
546
550
|
g->S[1] = complement ? "In" : "Out";
|
|
547
|
-
g->V[0] = p->name;
|
|
548
551
|
g->I[0] = q->smallest_ch;
|
|
549
552
|
g->I[1] = q->largest_ch;
|
|
550
|
-
write_failure_if(g, "!env.Go~S1Grouping~S0(~
|
|
553
|
+
write_failure_if(g, "!env.Go~S1Grouping~S0(~W, ~I0, ~I1)", p);
|
|
551
554
|
if (!is_goto) {
|
|
552
|
-
|
|
555
|
+
w(g, p->mode == m_forward ? "~Menv.NextChar()~N" : "~Menv.PrevChar()~N");
|
|
553
556
|
}
|
|
554
557
|
}
|
|
555
558
|
|
|
556
|
-
static void generate_GO(struct generator * g, struct node * p, int
|
|
559
|
+
static void generate_GO(struct generator * g, struct node * p, int is_goto) {
|
|
557
560
|
write_comment(g, p);
|
|
558
561
|
|
|
559
562
|
int a0 = g->failure_label;
|
|
560
563
|
struct str * a1 = str_copy(g->failure_str);
|
|
561
564
|
|
|
562
|
-
|
|
565
|
+
bool end_unreachable = false;
|
|
563
566
|
|
|
564
567
|
int golab = new_label(g);
|
|
565
568
|
g->I[0] = golab;
|
|
566
|
-
w(g, "
|
|
569
|
+
w(g, "~-~Mgolab~I0:~N~+~Mfor {~N~+");
|
|
567
570
|
|
|
568
571
|
struct str * savevar = NULL;
|
|
569
|
-
if (
|
|
572
|
+
if (is_goto || repeat_restore(p->left)) {
|
|
570
573
|
savevar = vars_newname(g);
|
|
571
574
|
write_savecursor(g, p, savevar);
|
|
572
575
|
}
|
|
573
576
|
|
|
574
|
-
|
|
577
|
+
int label = new_label(g);
|
|
578
|
+
g->failure_label = label;
|
|
575
579
|
str_clear(g->failure_str);
|
|
576
580
|
wsetlab_begin(g, g->failure_label);
|
|
577
581
|
generate(g, p->left);
|
|
@@ -582,12 +586,13 @@ static void generate_GO(struct generator * g, struct node * p, int style) {
|
|
|
582
586
|
end_unreachable = true;
|
|
583
587
|
} else {
|
|
584
588
|
/* include for goto; omit for gopast */
|
|
585
|
-
if (
|
|
589
|
+
if (is_goto) write_restorecursor(g, p, savevar);
|
|
586
590
|
g->I[0] = golab;
|
|
587
591
|
w(g, "~Mbreak golab~I0~N");
|
|
592
|
+
g->unreachable = true;
|
|
588
593
|
}
|
|
594
|
+
wsetlab_end(g, g->failure_label);
|
|
589
595
|
g->unreachable = false;
|
|
590
|
-
w(g, "~-~M}~N");
|
|
591
596
|
if (savevar) {
|
|
592
597
|
write_restorecursor(g, p, savevar);
|
|
593
598
|
str_delete(savevar);
|
|
@@ -604,11 +609,11 @@ static void generate_GO(struct generator * g, struct node * p, int style) {
|
|
|
604
609
|
}
|
|
605
610
|
|
|
606
611
|
static void generate_loop(struct generator * g, struct node * p) {
|
|
607
|
-
struct str * loopvar = vars_newname(g);
|
|
608
612
|
write_comment(g, p);
|
|
609
|
-
|
|
613
|
+
struct str * loopvar = vars_newname(g);
|
|
614
|
+
w(g, "~Mfor _ = range make([]struct{}, ");
|
|
610
615
|
generate_AE(g, p->AE);
|
|
611
|
-
writef(g, ") {~+", p);
|
|
616
|
+
writef(g, ") {~N~+", p);
|
|
612
617
|
|
|
613
618
|
generate(g, p->left);
|
|
614
619
|
|
|
@@ -620,18 +625,19 @@ static void generate_loop(struct generator * g, struct node * p) {
|
|
|
620
625
|
static void generate_repeat_or_atleast(struct generator * g, struct node * p, struct str * loopvar) {
|
|
621
626
|
int replab = new_label(g);
|
|
622
627
|
g->I[0] = replab;
|
|
623
|
-
writef(g, "
|
|
628
|
+
writef(g, "~-~Mreplab~I0:~N~+~Mfor {~N~+", p);
|
|
624
629
|
|
|
625
630
|
struct str * savevar = NULL;
|
|
626
|
-
if (repeat_restore(
|
|
631
|
+
if (repeat_restore(p->left)) {
|
|
627
632
|
savevar = vars_newname(g);
|
|
628
633
|
write_savecursor(g, p, savevar);
|
|
629
634
|
}
|
|
630
635
|
|
|
631
|
-
|
|
636
|
+
int label = new_label(g);
|
|
637
|
+
g->failure_label = label;
|
|
632
638
|
str_clear(g->failure_str);
|
|
633
639
|
g->I[0] = g->failure_label;
|
|
634
|
-
w(g, "
|
|
640
|
+
w(g, "~-~Mlab~I0:~N~+~Mfor range [2]struct{}{} {~N~+");
|
|
635
641
|
generate(g, p->left);
|
|
636
642
|
|
|
637
643
|
if (!g->unreachable) {
|
|
@@ -661,9 +667,9 @@ static void generate_repeat(struct generator * g, struct node * p) {
|
|
|
661
667
|
}
|
|
662
668
|
|
|
663
669
|
static void generate_atleast(struct generator * g, struct node * p) {
|
|
664
|
-
struct str * loopvar = vars_newname(g);
|
|
665
|
-
|
|
666
670
|
write_comment(g, p);
|
|
671
|
+
|
|
672
|
+
struct str * loopvar = vars_newname(g);
|
|
667
673
|
g->B[0] = str_data(loopvar);
|
|
668
674
|
w(g, "~Mvar ~B0 = ");
|
|
669
675
|
generate_AE(g, p->AE);
|
|
@@ -683,12 +689,6 @@ static void generate_atleast(struct generator * g, struct node * p) {
|
|
|
683
689
|
str_delete(loopvar);
|
|
684
690
|
}
|
|
685
691
|
|
|
686
|
-
static void generate_setmark(struct generator * g, struct node * p) {
|
|
687
|
-
write_comment(g, p);
|
|
688
|
-
g->V[0] = p->name;
|
|
689
|
-
writef(g, "~M~V0 = env.Cursor~N", p);
|
|
690
|
-
}
|
|
691
|
-
|
|
692
692
|
static void generate_tomark(struct generator * g, struct node * p) {
|
|
693
693
|
write_comment(g, p);
|
|
694
694
|
g->S[0] = p->mode == m_forward ? ">" : "<";
|
|
@@ -701,15 +701,6 @@ static void generate_tomark(struct generator * g, struct node * p) {
|
|
|
701
701
|
w(g, "~Menv.Cursor = "); generate_AE(g, p->AE); writef(g, "~N", p);
|
|
702
702
|
}
|
|
703
703
|
|
|
704
|
-
static void generate_atmark(struct generator * g, struct node * p) {
|
|
705
|
-
write_comment(g, p);
|
|
706
|
-
w(g, "~Mif env.Cursor != "); generate_AE(g, p->AE); writef(g, " ", p);
|
|
707
|
-
write_block_start(g);
|
|
708
|
-
write_failure(g);
|
|
709
|
-
write_block_end(g);
|
|
710
|
-
g->unreachable = false;
|
|
711
|
-
}
|
|
712
|
-
|
|
713
704
|
static void generate_hop(struct generator * g, struct node * p) {
|
|
714
705
|
write_comment(g, p);
|
|
715
706
|
// Generate the AE to a temporary block so we can substitute it in
|
|
@@ -726,26 +717,12 @@ static void generate_hop(struct generator * g, struct node * p) {
|
|
|
726
717
|
str_delete(ae);
|
|
727
718
|
}
|
|
728
719
|
|
|
729
|
-
static void generate_delete(struct generator * g, struct node * p) {
|
|
730
|
-
write_comment(g, p);
|
|
731
|
-
writef(g, "~Mif !env.SliceDel() {~N"
|
|
732
|
-
"~+~Mreturn false~N~-"
|
|
733
|
-
"~M}~N", p);
|
|
734
|
-
}
|
|
735
|
-
|
|
736
720
|
static void generate_tolimit(struct generator * g, struct node * p) {
|
|
737
721
|
write_comment(g, p);
|
|
738
722
|
g->S[0] = p->mode == m_forward ? "env.Limit" : "env.LimitBackward";
|
|
739
723
|
writef(g, "~Menv.Cursor = ~S0~N", p);
|
|
740
724
|
}
|
|
741
725
|
|
|
742
|
-
static void generate_atlimit(struct generator * g, struct node * p) {
|
|
743
|
-
write_comment(g, p);
|
|
744
|
-
g->S[0] = p->mode == m_forward ? "env.Limit" : "env.LimitBackward";
|
|
745
|
-
g->S[1] = p->mode == m_forward ? "<" : ">";
|
|
746
|
-
write_failure_if(g, "env.Cursor ~S1 ~S0", p);
|
|
747
|
-
}
|
|
748
|
-
|
|
749
726
|
static void generate_leftslice(struct generator * g, struct node * p) {
|
|
750
727
|
write_comment(g, p);
|
|
751
728
|
g->S[0] = p->mode == m_forward ? "env.Bra" : "env.Ket";
|
|
@@ -760,16 +737,12 @@ static void generate_rightslice(struct generator * g, struct node * p) {
|
|
|
760
737
|
|
|
761
738
|
static void generate_assignto(struct generator * g, struct node * p) {
|
|
762
739
|
write_comment(g, p);
|
|
763
|
-
g
|
|
764
|
-
writef(g, "~M~V0 = env.AssignTo()~N", p);
|
|
740
|
+
writef(g, "~M~V = env.AssignTo()~N", p);
|
|
765
741
|
}
|
|
766
742
|
|
|
767
743
|
static void generate_sliceto(struct generator * g, struct node * p) {
|
|
768
744
|
write_comment(g, p);
|
|
769
|
-
g
|
|
770
|
-
writef(g, "~M~V0 = env.SliceTo()~N"
|
|
771
|
-
"~Mif ~V0 == \"\" {~N"
|
|
772
|
-
"~+~Mreturn false~N~-~M}~N", p);
|
|
745
|
+
writef(g, "~M~V = env.SliceTo()~N", p);
|
|
773
746
|
}
|
|
774
747
|
|
|
775
748
|
static void generate_address(struct generator * g, struct node * p) {
|
|
@@ -782,26 +755,28 @@ static void generate_address(struct generator * g, struct node * p) {
|
|
|
782
755
|
}
|
|
783
756
|
|
|
784
757
|
static void generate_insert(struct generator * g, struct node * p, int style) {
|
|
785
|
-
|
|
786
|
-
|
|
758
|
+
write_margin(g);
|
|
787
759
|
write_block_start(g);
|
|
788
760
|
write_comment(g, p);
|
|
761
|
+
int keep_c = style == c_attach;
|
|
789
762
|
if (p->mode == m_backward) keep_c = !keep_c;
|
|
790
763
|
if (keep_c) w(g, "~Mvar c = env.Cursor~N");
|
|
791
764
|
w(g, "~Mbra, ket := env.Cursor, env.Cursor~N");
|
|
792
765
|
writef(g, "~Menv.Insert(bra, ket, ", p);
|
|
793
766
|
generate_address(g, p);
|
|
794
|
-
writef(g, ")
|
|
767
|
+
writef(g, ")~N", p);
|
|
795
768
|
if (keep_c) w(g, "~Menv.Cursor = c~N");
|
|
796
769
|
write_block_end(g);
|
|
797
770
|
}
|
|
798
771
|
|
|
799
|
-
static void
|
|
800
|
-
|
|
801
|
-
|
|
772
|
+
static void generate_stringassign(struct generator * g, struct node * p) {
|
|
773
|
+
write_margin(g);
|
|
802
774
|
write_block_start(g);
|
|
803
775
|
write_comment(g, p);
|
|
804
|
-
|
|
776
|
+
int keep_c = p->mode == m_forward; /* like 'attach' */
|
|
777
|
+
if (keep_c) {
|
|
778
|
+
writef(g, "~Mvar c = env.Cursor~N", p);
|
|
779
|
+
}
|
|
805
780
|
if (p->mode == m_forward) {
|
|
806
781
|
writef(g, "~Menv.Insert(env.Cursor, env.Limit, ", p);
|
|
807
782
|
} else {
|
|
@@ -809,21 +784,27 @@ static void generate_assignfrom(struct generator * g, struct node * p) {
|
|
|
809
784
|
}
|
|
810
785
|
generate_address(g, p);
|
|
811
786
|
writef(g, ")~N", p);
|
|
812
|
-
if (keep_c)
|
|
787
|
+
if (keep_c) {
|
|
788
|
+
w(g, "~Menv.Cursor = c~N");
|
|
789
|
+
}
|
|
813
790
|
write_block_end(g);
|
|
814
791
|
}
|
|
815
792
|
|
|
816
793
|
static void generate_slicefrom(struct generator * g, struct node * p) {
|
|
817
794
|
write_comment(g, p);
|
|
818
|
-
|
|
795
|
+
if (p->literalstring && SIZE(p->literalstring) == 0) {
|
|
796
|
+
w(g, "~Menv.SliceDel()~N");
|
|
797
|
+
return;
|
|
798
|
+
}
|
|
799
|
+
w(g, "~Menv.SliceFrom(");
|
|
819
800
|
generate_address(g, p);
|
|
820
|
-
|
|
821
|
-
"~+~Mreturn false~N~-~M}~N", p);
|
|
801
|
+
w(g, ")~N");
|
|
822
802
|
}
|
|
823
803
|
|
|
824
804
|
static void generate_setlimit(struct generator * g, struct node * p) {
|
|
825
|
-
struct str * varname = vars_newname(g);
|
|
826
805
|
write_comment(g, p);
|
|
806
|
+
struct str * varname = vars_newname(g);
|
|
807
|
+
|
|
827
808
|
if (p->left && p->left->type == c_tomark) {
|
|
828
809
|
/* Special case for:
|
|
829
810
|
*
|
|
@@ -835,6 +816,7 @@ static void generate_setlimit(struct generator * g, struct node * p) {
|
|
|
835
816
|
*/
|
|
836
817
|
struct node * q = p->left;
|
|
837
818
|
write_comment(g, q);
|
|
819
|
+
|
|
838
820
|
g->S[0] = q->mode == m_forward ? ">" : "<";
|
|
839
821
|
w(g, "~Mif env.Cursor ~S0 "); generate_AE(g, q->AE); w(g, " ");
|
|
840
822
|
write_block_start(g);
|
|
@@ -844,22 +826,24 @@ static void generate_setlimit(struct generator * g, struct node * p) {
|
|
|
844
826
|
|
|
845
827
|
g->B[0] = str_data(varname);
|
|
846
828
|
if (p->mode == m_forward) {
|
|
847
|
-
w(g, "~Mvar ~B0 = env.Limit
|
|
829
|
+
w(g, "~Mvar ~B0 = env.Limit~N");
|
|
848
830
|
w(g, "~Menv.Limit = ");
|
|
831
|
+
generate_AE(g, q->AE);
|
|
832
|
+
w(g, "~N");
|
|
833
|
+
w(g, "~M~B0 -= env.Limit~N");
|
|
849
834
|
} else {
|
|
850
835
|
w(g, "~Mvar ~B0 = env.LimitBackward~N");
|
|
851
836
|
w(g, "~Menv.LimitBackward = ");
|
|
837
|
+
generate_AE(g, q->AE);
|
|
838
|
+
w(g, "~N");
|
|
852
839
|
}
|
|
853
|
-
generate_AE(g, q->AE); writef(g, ";~N", q);
|
|
854
840
|
|
|
855
841
|
if (p->mode == m_forward) {
|
|
856
842
|
str_assign(g->failure_str, "env.Limit += ");
|
|
857
843
|
str_append(g->failure_str, varname);
|
|
858
|
-
str_append_string(g->failure_str, ";");
|
|
859
844
|
} else {
|
|
860
845
|
str_assign(g->failure_str, "env.LimitBackward = ");
|
|
861
846
|
str_append(g->failure_str, varname);
|
|
862
|
-
str_append_string(g->failure_str, ";");
|
|
863
847
|
}
|
|
864
848
|
} else {
|
|
865
849
|
struct str * savevar = vars_newname(g);
|
|
@@ -881,11 +865,9 @@ static void generate_setlimit(struct generator * g, struct node * p) {
|
|
|
881
865
|
if (p->mode == m_forward) {
|
|
882
866
|
str_assign(g->failure_str, "env.Limit += ");
|
|
883
867
|
str_append(g->failure_str, varname);
|
|
884
|
-
str_append_string(g->failure_str, ";");
|
|
885
868
|
} else {
|
|
886
869
|
str_assign(g->failure_str, "env.LimitBackward = ");
|
|
887
870
|
str_append(g->failure_str, varname);
|
|
888
|
-
str_append_string(g->failure_str, ";");
|
|
889
871
|
}
|
|
890
872
|
}
|
|
891
873
|
str_delete(savevar);
|
|
@@ -908,28 +890,56 @@ static void generate_setlimit(struct generator * g, struct node * p) {
|
|
|
908
890
|
static void generate_dollar(struct generator * g, struct node * p) {
|
|
909
891
|
write_comment(g, p);
|
|
910
892
|
|
|
893
|
+
int a0 = g->failure_label;
|
|
894
|
+
struct str * a1 = str_copy(g->failure_str);
|
|
895
|
+
int label = new_label(g);
|
|
896
|
+
g->failure_label = label;
|
|
897
|
+
str_clear(g->failure_str);
|
|
898
|
+
|
|
911
899
|
struct str * savevar = vars_newname(g);
|
|
912
|
-
g->V[0] = p->name;
|
|
913
900
|
g->B[0] = str_data(savevar);
|
|
914
901
|
writef(g, "~Mvar ~B0 = env.Clone()~N"
|
|
915
|
-
"~Menv.SetCurrent(~
|
|
902
|
+
"~Menv.SetCurrent(~V)~N", p);
|
|
903
|
+
if (p->left->possible_signals == -1) {
|
|
904
|
+
/* Assume failure. */
|
|
905
|
+
w(g, "~Mvar ~B0_f = true~N");
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
wsetlab_begin(g, g->failure_label);
|
|
909
|
+
|
|
916
910
|
generate(g, p->left);
|
|
917
|
-
|
|
918
|
-
|
|
911
|
+
|
|
912
|
+
if (!g->unreachable && p->left->possible_signals == -1) {
|
|
913
|
+
/* Mark success. */
|
|
919
914
|
g->B[0] = str_data(savevar);
|
|
920
|
-
|
|
921
|
-
w(g, "~M~V0 = env.Current()~N");
|
|
922
|
-
/* Reset env */
|
|
923
|
-
w(g, "~M*env = *~B0~N");
|
|
915
|
+
w(g, "~M~B0_f = false~N");
|
|
924
916
|
}
|
|
917
|
+
|
|
918
|
+
wsetlab_end(g, g->failure_label);
|
|
919
|
+
|
|
920
|
+
g->failure_label = a0;
|
|
921
|
+
str_delete(g->failure_str);
|
|
922
|
+
g->failure_str = a1;
|
|
923
|
+
|
|
924
|
+
g->B[0] = str_data(savevar);
|
|
925
|
+
/* Update string variable; restore env. */
|
|
926
|
+
writef(g, "~M~V = env.Current()~N"
|
|
927
|
+
"~M*env = *~B0~N", p);
|
|
928
|
+
|
|
929
|
+
if (p->left->possible_signals == 0) {
|
|
930
|
+
// p->left always signals f.
|
|
931
|
+
write_failure(g);
|
|
932
|
+
} else if (p->left->possible_signals == -1) {
|
|
933
|
+
write_failure_if(g, "~B0_f", p);
|
|
934
|
+
}
|
|
935
|
+
|
|
925
936
|
str_delete(savevar);
|
|
926
937
|
}
|
|
927
938
|
|
|
928
939
|
static void generate_integer_assign(struct generator * g, struct node * p, const char * s) {
|
|
929
940
|
write_comment(g, p);
|
|
930
|
-
g->V[0] = p->name;
|
|
931
941
|
g->S[0] = s;
|
|
932
|
-
|
|
942
|
+
writef(g, "~M~V ~S0 ", p);
|
|
933
943
|
generate_AE(g, p->AE);
|
|
934
944
|
w(g, "~N");
|
|
935
945
|
}
|
|
@@ -937,7 +947,7 @@ static void generate_integer_assign(struct generator * g, struct node * p, const
|
|
|
937
947
|
static void generate_integer_test(struct generator * g, struct node * p) {
|
|
938
948
|
write_comment(g, p);
|
|
939
949
|
int relop = p->type;
|
|
940
|
-
int optimise_to_return = (g
|
|
950
|
+
int optimise_to_return = tailcallable(g, p);
|
|
941
951
|
if (optimise_to_return) {
|
|
942
952
|
w(g, "~Mreturn ");
|
|
943
953
|
p->right = NULL;
|
|
@@ -947,12 +957,12 @@ static void generate_integer_test(struct generator * g, struct node * p) {
|
|
|
947
957
|
relop ^= 1;
|
|
948
958
|
}
|
|
949
959
|
generate_AE(g, p->left);
|
|
950
|
-
|
|
951
|
-
write_c_relop(g, relop);
|
|
960
|
+
write_relop(g, relop);
|
|
952
961
|
generate_AE(g, p->AE);
|
|
953
962
|
if (optimise_to_return) {
|
|
954
963
|
w(g, "~N");
|
|
955
964
|
} else {
|
|
965
|
+
write_char(g, ' ');
|
|
956
966
|
write_block_start(g);
|
|
957
967
|
write_failure(g);
|
|
958
968
|
write_block_end(g);
|
|
@@ -961,24 +971,28 @@ static void generate_integer_test(struct generator * g, struct node * p) {
|
|
|
961
971
|
}
|
|
962
972
|
|
|
963
973
|
static void generate_call(struct generator * g, struct node * p) {
|
|
964
|
-
int signals =
|
|
974
|
+
int signals = p->name->definition->possible_signals;
|
|
965
975
|
write_comment(g, p);
|
|
966
|
-
g
|
|
967
|
-
|
|
968
|
-
(
|
|
969
|
-
|
|
970
|
-
|
|
976
|
+
if (tailcallable(g, p)) {
|
|
977
|
+
/* Tail call. */
|
|
978
|
+
writef(g, "~Mreturn ~W(env, context)~N", p);
|
|
979
|
+
p->right = NULL;
|
|
980
|
+
return;
|
|
981
|
+
}
|
|
982
|
+
if (just_return_on_fail(g) && signals == 0) {
|
|
983
|
+
/* Always fails. */
|
|
984
|
+
writef(g, "~Mreturn ~W(env, context)~N", p);
|
|
971
985
|
return;
|
|
972
986
|
}
|
|
973
987
|
if (signals == 1) {
|
|
974
988
|
/* Always succeeds. */
|
|
975
|
-
writef(g, "~M~
|
|
989
|
+
writef(g, "~M~W(env, context)~N", p);
|
|
976
990
|
} else if (signals == 0) {
|
|
977
991
|
/* Always fails. */
|
|
978
|
-
writef(g, "~M~
|
|
992
|
+
writef(g, "~M~W(env, context)~N", p);
|
|
979
993
|
write_failure(g);
|
|
980
994
|
} else {
|
|
981
|
-
write_failure_if(g, "!~
|
|
995
|
+
write_failure_if(g, "!~W(env, context)", p);
|
|
982
996
|
}
|
|
983
997
|
}
|
|
984
998
|
|
|
@@ -988,40 +1002,63 @@ static void generate_grouping(struct generator * g, struct node * p, int complem
|
|
|
988
1002
|
struct grouping * q = p->name->grouping;
|
|
989
1003
|
g->S[0] = p->mode == m_forward ? "" : "B";
|
|
990
1004
|
g->S[1] = complement ? "Out" : "In";
|
|
991
|
-
g->V[0] = p->name;
|
|
992
1005
|
g->I[0] = q->smallest_ch;
|
|
993
1006
|
g->I[1] = q->largest_ch;
|
|
994
|
-
|
|
1007
|
+
if (tailcallable(g, p)) {
|
|
1008
|
+
writef(g, "~Mreturn env.~S1Grouping~S0(~W, ~I0, ~I1);~N", p);
|
|
1009
|
+
p->right = NULL;
|
|
1010
|
+
} else {
|
|
1011
|
+
write_failure_if(g, "!env.~S1Grouping~S0(~W, ~I0, ~I1)", p);
|
|
1012
|
+
}
|
|
995
1013
|
}
|
|
996
1014
|
|
|
997
1015
|
static void generate_namedstring(struct generator * g, struct node * p) {
|
|
998
1016
|
write_comment(g, p);
|
|
999
1017
|
g->S[0] = p->mode == m_forward ? "" : "B";
|
|
1000
|
-
g
|
|
1001
|
-
|
|
1018
|
+
if (tailcallable(g, p)) {
|
|
1019
|
+
writef(g, "~Mreturn env.EqS~S0(~V)~N", p);
|
|
1020
|
+
p->right = NULL;
|
|
1021
|
+
} else {
|
|
1022
|
+
write_failure_if(g, "!env.EqS~S0(~V)", p);
|
|
1023
|
+
}
|
|
1002
1024
|
}
|
|
1003
1025
|
|
|
1004
1026
|
static void generate_literalstring(struct generator * g, struct node * p) {
|
|
1005
|
-
symbol * b = p->literalstring;
|
|
1006
1027
|
write_comment(g, p);
|
|
1007
1028
|
g->S[0] = p->mode == m_forward ? "" : "B";
|
|
1008
|
-
g
|
|
1009
|
-
|
|
1029
|
+
if (tailcallable(g, p)) {
|
|
1030
|
+
writef(g, "~Mreturn env.EqS~S0(~L)~N", p);
|
|
1031
|
+
p->right = NULL;
|
|
1032
|
+
} else {
|
|
1033
|
+
write_failure_if(g, "!env.EqS~S0(~L)", p);
|
|
1034
|
+
}
|
|
1010
1035
|
}
|
|
1011
1036
|
|
|
1012
1037
|
static void generate_setup_context(struct generator * g) {
|
|
1013
|
-
|
|
1038
|
+
if (g->analyser->variable_count == 0) {
|
|
1039
|
+
w(g, "~Mvar context = &Context{}~N");
|
|
1040
|
+
w(g, "~M_ = context~N");
|
|
1041
|
+
return;
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
w(g, "~Mvar context = &Context{~+~N");
|
|
1014
1045
|
for (struct name * q = g->analyser->names; q; q = q->next) {
|
|
1015
|
-
|
|
1046
|
+
if (q->local_to) continue;
|
|
1016
1047
|
switch (q->type) {
|
|
1017
1048
|
case t_string:
|
|
1018
|
-
|
|
1049
|
+
write_margin(g);
|
|
1050
|
+
write_varname(g, q);
|
|
1051
|
+
w(g, ": \"\",~N");
|
|
1019
1052
|
break;
|
|
1020
1053
|
case t_integer:
|
|
1021
|
-
|
|
1054
|
+
write_margin(g);
|
|
1055
|
+
write_varname(g, q);
|
|
1056
|
+
w(g, ": 0,~N");
|
|
1022
1057
|
break;
|
|
1023
1058
|
case t_boolean:
|
|
1024
|
-
|
|
1059
|
+
write_margin(g);
|
|
1060
|
+
write_varname(g, q);
|
|
1061
|
+
w(g, ": false,~N");
|
|
1025
1062
|
break;
|
|
1026
1063
|
}
|
|
1027
1064
|
}
|
|
@@ -1030,27 +1067,55 @@ static void generate_setup_context(struct generator * g) {
|
|
|
1030
1067
|
}
|
|
1031
1068
|
|
|
1032
1069
|
static void generate_define(struct generator * g, struct node * p) {
|
|
1033
|
-
struct name * q = p->name;
|
|
1034
|
-
if (q->type == t_routine && !q->used) return;
|
|
1035
|
-
|
|
1036
1070
|
write_newline(g);
|
|
1037
1071
|
write_comment(g, p);
|
|
1038
1072
|
|
|
1039
|
-
|
|
1040
|
-
|
|
1073
|
+
struct name * q = p->name;
|
|
1041
1074
|
if (q->type == t_routine) {
|
|
1042
|
-
|
|
1075
|
+
writef(g, "~Mfunc ~W(env *snowballRuntime.Env, ctx interface{}) bool {~+~N", p);
|
|
1043
1076
|
w(g, "~Mcontext := ctx.(*Context)~N");
|
|
1044
1077
|
w(g, "~M_ = context~N");
|
|
1045
1078
|
} else {
|
|
1046
|
-
|
|
1079
|
+
writef(g, "~Mfunc ~E(env *snowballRuntime.Env) bool {~+~N", p);
|
|
1047
1080
|
generate_setup_context(g);
|
|
1081
|
+
if (q->used != q->definition) {
|
|
1082
|
+
// This external needs to be callable as a routine, so generate
|
|
1083
|
+
// the actual code like a routine with an external which just
|
|
1084
|
+
// forwards to that.
|
|
1085
|
+
writef(g, "~Mreturn ~W(env, context)~N", p);
|
|
1086
|
+
w(g, "~-~M}~N");
|
|
1087
|
+
writef(g, "~Mfunc ~W(env *snowballRuntime.Env, ctx interface{}) bool {~+~N", p);
|
|
1088
|
+
w(g, "~Mcontext := ctx.(*Context)~N");
|
|
1089
|
+
w(g, "~M_ = context~N");
|
|
1090
|
+
}
|
|
1048
1091
|
}
|
|
1049
|
-
if (p->amongvar_needed) w(g, "~Mvar among_var int32~N");
|
|
1050
1092
|
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1093
|
+
if (q->amongvar_needed) {
|
|
1094
|
+
w(g, "~Mvar among_var int32~N");
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
/* Declare localised variables. */
|
|
1098
|
+
for (struct name * name = g->analyser->names; name; name = name->next) {
|
|
1099
|
+
if (name->local_to == q) {
|
|
1100
|
+
switch (name->type) {
|
|
1101
|
+
case t_string:
|
|
1102
|
+
w(g, "~Mvar ");
|
|
1103
|
+
write_varname(g, name);
|
|
1104
|
+
w(g, " string~N");
|
|
1105
|
+
break;
|
|
1106
|
+
case t_integer:
|
|
1107
|
+
w(g, "~Mvar ");
|
|
1108
|
+
write_varname(g, name);
|
|
1109
|
+
w(g, " int~N");
|
|
1110
|
+
break;
|
|
1111
|
+
case t_boolean:
|
|
1112
|
+
w(g, "~Mvar ");
|
|
1113
|
+
write_varname(g, name);
|
|
1114
|
+
w(g, " bool~N");
|
|
1115
|
+
break;
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1054
1119
|
|
|
1055
1120
|
g->next_label = 0;
|
|
1056
1121
|
g->var_number = 0;
|
|
@@ -1058,21 +1123,16 @@ static void generate_define(struct generator * g, struct node * p) {
|
|
|
1058
1123
|
str_clear(g->failure_str);
|
|
1059
1124
|
g->failure_label = x_return;
|
|
1060
1125
|
g->unreachable = false;
|
|
1061
|
-
int signals = check_possible_signals_list(g, p->left, c_define, 0);
|
|
1062
1126
|
|
|
1063
1127
|
/* Generate function body. */
|
|
1064
1128
|
generate(g, p->left);
|
|
1065
1129
|
if (p->left->right) {
|
|
1066
1130
|
assert(p->left->right->type == c_functionend);
|
|
1067
|
-
if (
|
|
1131
|
+
if (p->left->possible_signals) {
|
|
1068
1132
|
generate(g, p->left->right);
|
|
1069
1133
|
}
|
|
1070
1134
|
}
|
|
1071
1135
|
w(g, "~-~M}~N");
|
|
1072
|
-
|
|
1073
|
-
str_append(saved_output, g->outbuf);
|
|
1074
|
-
str_delete(g->outbuf);
|
|
1075
|
-
g->outbuf = saved_output;
|
|
1076
1136
|
}
|
|
1077
1137
|
|
|
1078
1138
|
static void generate_functionend(struct generator * g, struct node * p) {
|
|
@@ -1095,6 +1155,10 @@ static void generate_substring(struct generator * g, struct node * p) {
|
|
|
1095
1155
|
}
|
|
1096
1156
|
} else if (x->always_matches) {
|
|
1097
1157
|
writef(g, "~Menv.FindAmong~S0(A_~I0, context)~N", p);
|
|
1158
|
+
} else if (x->command_count == 0 && tailcallable(g, p)) {
|
|
1159
|
+
writef(g, "~Mreturn env.FindAmong~S0(A_~I0, context) != 0~N", p);
|
|
1160
|
+
x->node->right = NULL;
|
|
1161
|
+
g->unreachable = true;
|
|
1098
1162
|
} else {
|
|
1099
1163
|
write_failure_if(g, "env.FindAmong~S0(A_~I0, context) == 0", p);
|
|
1100
1164
|
}
|
|
@@ -1125,10 +1189,23 @@ static void generate_among(struct generator * g, struct node * p) {
|
|
|
1125
1189
|
}
|
|
1126
1190
|
}
|
|
1127
1191
|
|
|
1128
|
-
static void generate_booltest(struct generator * g, struct node * p) {
|
|
1192
|
+
static void generate_booltest(struct generator * g, struct node * p, int inverted) {
|
|
1129
1193
|
write_comment(g, p);
|
|
1130
|
-
g
|
|
1131
|
-
|
|
1194
|
+
if (tailcallable(g, p)) {
|
|
1195
|
+
// Optimise at end of function.
|
|
1196
|
+
if (inverted) {
|
|
1197
|
+
writef(g, "~Mreturn !~V~N", p);
|
|
1198
|
+
} else {
|
|
1199
|
+
writef(g, "~Mreturn ~V~N", p);
|
|
1200
|
+
}
|
|
1201
|
+
p->right = NULL;
|
|
1202
|
+
return;
|
|
1203
|
+
}
|
|
1204
|
+
if (inverted) {
|
|
1205
|
+
write_failure_if(g, "~V", p);
|
|
1206
|
+
} else {
|
|
1207
|
+
write_failure_if(g, "!~V", p);
|
|
1208
|
+
}
|
|
1132
1209
|
}
|
|
1133
1210
|
|
|
1134
1211
|
static void generate_false(struct generator * g, struct node * p) {
|
|
@@ -1173,25 +1250,21 @@ static void generate(struct generator * g, struct node * p) {
|
|
|
1173
1250
|
case c_repeat: generate_repeat(g, p); break;
|
|
1174
1251
|
case c_loop: generate_loop(g, p); break;
|
|
1175
1252
|
case c_atleast: generate_atleast(g, p); break;
|
|
1176
|
-
case c_setmark: generate_setmark(g, p); break;
|
|
1177
1253
|
case c_tomark: generate_tomark(g, p); break;
|
|
1178
|
-
case c_atmark: generate_atmark(g, p); break;
|
|
1179
1254
|
case c_hop: generate_hop(g, p); break;
|
|
1180
|
-
case c_delete: generate_delete(g, p); break;
|
|
1181
1255
|
case c_next: generate_next(g, p); break;
|
|
1182
1256
|
case c_tolimit: generate_tolimit(g, p); break;
|
|
1183
|
-
case c_atlimit: generate_atlimit(g, p); break;
|
|
1184
1257
|
case c_leftslice: generate_leftslice(g, p); break;
|
|
1185
1258
|
case c_rightslice: generate_rightslice(g, p); break;
|
|
1186
1259
|
case c_assignto: generate_assignto(g, p); break;
|
|
1187
1260
|
case c_sliceto: generate_sliceto(g, p); break;
|
|
1188
|
-
case
|
|
1261
|
+
case c_stringassign: generate_stringassign(g, p); break;
|
|
1189
1262
|
case c_insert:
|
|
1190
1263
|
case c_attach: generate_insert(g, p, p->type); break;
|
|
1191
1264
|
case c_slicefrom: generate_slicefrom(g, p); break;
|
|
1192
1265
|
case c_setlimit: generate_setlimit(g, p); break;
|
|
1193
1266
|
case c_dollar: generate_dollar(g, p); break;
|
|
1194
|
-
case
|
|
1267
|
+
case c_assign: generate_integer_assign(g, p, "="); break;
|
|
1195
1268
|
case c_plusassign: generate_integer_assign(g, p, "+="); break;
|
|
1196
1269
|
case c_minusassign: generate_integer_assign(g, p, "-="); break;
|
|
1197
1270
|
case c_multiplyassign:generate_integer_assign(g, p, "*="); break;
|
|
@@ -1211,7 +1284,8 @@ static void generate(struct generator * g, struct node * p) {
|
|
|
1211
1284
|
case c_literalstring: generate_literalstring(g, p); break;
|
|
1212
1285
|
case c_among: generate_among(g, p); break;
|
|
1213
1286
|
case c_substring: generate_substring(g, p); break;
|
|
1214
|
-
case c_booltest: generate_booltest(g, p); break;
|
|
1287
|
+
case c_booltest: generate_booltest(g, p, false); break;
|
|
1288
|
+
case c_not_booltest: generate_booltest(g, p, true); break;
|
|
1215
1289
|
case c_false: generate_false(g, p); break;
|
|
1216
1290
|
case c_true: break;
|
|
1217
1291
|
case c_debug: generate_debug(g, p); break;
|
|
@@ -1227,13 +1301,13 @@ static void generate(struct generator * g, struct node * p) {
|
|
|
1227
1301
|
|
|
1228
1302
|
static void generate_class_begin(struct generator * g) {
|
|
1229
1303
|
w(g, "package ");
|
|
1230
|
-
|
|
1304
|
+
write_string(g, g->options->package);
|
|
1231
1305
|
w(g, "~N~N");
|
|
1232
1306
|
|
|
1233
|
-
w(g, "import(~N");
|
|
1234
|
-
w(g, "
|
|
1235
|
-
|
|
1236
|
-
w(g, "\"~N)~N~N");
|
|
1307
|
+
w(g, "import (~N");
|
|
1308
|
+
w(g, "~+~MsnowballRuntime \"");
|
|
1309
|
+
write_string(g, g->options->go_snowball_runtime);
|
|
1310
|
+
w(g, "\"~N~-)~N~N");
|
|
1237
1311
|
}
|
|
1238
1312
|
|
|
1239
1313
|
static void generate_among_table(struct generator * g, struct among * x) {
|
|
@@ -1247,17 +1321,17 @@ static void generate_among_table(struct generator * g, struct among * x) {
|
|
|
1247
1321
|
for (int i = 0; i < x->literalstring_count; i++) {
|
|
1248
1322
|
g->I[0] = v[i].i;
|
|
1249
1323
|
g->I[1] = v[i].result;
|
|
1250
|
-
g->L[0] = v[i].b;
|
|
1251
|
-
g->S[0] = ",";
|
|
1252
1324
|
|
|
1253
|
-
w(g, "~M&snowballRuntime.Among{Str
|
|
1325
|
+
w(g, "~M&snowballRuntime.Among{Str: ");
|
|
1326
|
+
write_literal_string(g, v[i].b);
|
|
1327
|
+
w(g, ", A: ~I0, B: ~I1, F: ");
|
|
1328
|
+
|
|
1254
1329
|
if (v[i].function != NULL) {
|
|
1255
|
-
w(g, "F:");
|
|
1256
1330
|
write_varname(g, v[i].function);
|
|
1257
1331
|
} else {
|
|
1258
|
-
w(g, "
|
|
1332
|
+
w(g, "nil");
|
|
1259
1333
|
}
|
|
1260
|
-
w(g, "}
|
|
1334
|
+
w(g, "},~N");
|
|
1261
1335
|
}
|
|
1262
1336
|
w(g, "~-~M}~N~N");
|
|
1263
1337
|
}
|
|
@@ -1268,11 +1342,11 @@ static void generate_amongs(struct generator * g) {
|
|
|
1268
1342
|
}
|
|
1269
1343
|
}
|
|
1270
1344
|
|
|
1271
|
-
static void set_bit(symbol * b, int i) { b[i
|
|
1345
|
+
static void set_bit(symbol * b, int i) { b[i >> 3] |= 1 << (i & 7); }
|
|
1272
1346
|
|
|
1273
1347
|
static void generate_grouping_table(struct generator * g, struct grouping * q) {
|
|
1274
1348
|
int range = q->largest_ch - q->smallest_ch + 1;
|
|
1275
|
-
int size = (range + 7)/ 8; /* assume 8 bits per symbol */
|
|
1349
|
+
int size = (range + 7) / 8; /* assume 8 bits per symbol */
|
|
1276
1350
|
symbol * b = q->b;
|
|
1277
1351
|
symbol * map = create_b(size);
|
|
1278
1352
|
|
|
@@ -1280,11 +1354,12 @@ static void generate_grouping_table(struct generator * g, struct grouping * q) {
|
|
|
1280
1354
|
|
|
1281
1355
|
for (int i = 0; i < SIZE(b); i++) set_bit(map, b[i] - q->smallest_ch);
|
|
1282
1356
|
|
|
1283
|
-
g
|
|
1284
|
-
|
|
1357
|
+
w(g, "~Mvar ");
|
|
1358
|
+
write_varname(g, q->name);
|
|
1359
|
+
w(g, " = []byte{");
|
|
1285
1360
|
for (int i = 0; i < size; i++) {
|
|
1361
|
+
if (i) w(g, ", ");
|
|
1286
1362
|
write_int(g, map[i]);
|
|
1287
|
-
if (i < size - 1) w(g, ", ");
|
|
1288
1363
|
}
|
|
1289
1364
|
w(g, "}~N~N");
|
|
1290
1365
|
|
|
@@ -1293,24 +1368,29 @@ static void generate_grouping_table(struct generator * g, struct grouping * q) {
|
|
|
1293
1368
|
|
|
1294
1369
|
static void generate_groupings(struct generator * g) {
|
|
1295
1370
|
for (struct grouping * q = g->analyser->groupings; q; q = q->next) {
|
|
1296
|
-
|
|
1297
|
-
generate_grouping_table(g, q);
|
|
1371
|
+
generate_grouping_table(g, q);
|
|
1298
1372
|
}
|
|
1299
1373
|
}
|
|
1300
1374
|
|
|
1301
1375
|
static void generate_members(struct generator * g) {
|
|
1302
1376
|
w(g, "type Context struct {~+~N");
|
|
1303
1377
|
for (struct name * q = g->analyser->names; q; q = q->next) {
|
|
1304
|
-
|
|
1378
|
+
if (q->local_to) continue;
|
|
1305
1379
|
switch (q->type) {
|
|
1306
1380
|
case t_string:
|
|
1307
|
-
|
|
1381
|
+
write_margin(g);
|
|
1382
|
+
write_varname(g, q);
|
|
1383
|
+
w(g, " string~N");
|
|
1308
1384
|
break;
|
|
1309
1385
|
case t_integer:
|
|
1310
|
-
|
|
1386
|
+
write_margin(g);
|
|
1387
|
+
write_varname(g, q);
|
|
1388
|
+
w(g, " int~N");
|
|
1311
1389
|
break;
|
|
1312
1390
|
case t_boolean:
|
|
1313
|
-
|
|
1391
|
+
write_margin(g);
|
|
1392
|
+
write_varname(g, q);
|
|
1393
|
+
w(g, " bool~N");
|
|
1314
1394
|
break;
|
|
1315
1395
|
}
|
|
1316
1396
|
}
|
|
@@ -1325,14 +1405,12 @@ static void generate_methods(struct generator * g) {
|
|
|
1325
1405
|
}
|
|
1326
1406
|
|
|
1327
1407
|
extern void generate_program_go(struct generator * g) {
|
|
1408
|
+
g->margin_indent = "\t";
|
|
1409
|
+
|
|
1328
1410
|
g->outbuf = str_new();
|
|
1329
1411
|
g->failure_str = str_new();
|
|
1330
1412
|
|
|
1331
1413
|
write_start_comment(g, "//! ", NULL);
|
|
1332
|
-
if (g->analyser->int_limits_used) {
|
|
1333
|
-
/* std::usize is used in the code generated for usize::MAX and usize::MIN */
|
|
1334
|
-
w(g, "use std::usize;~N~N");
|
|
1335
|
-
}
|
|
1336
1414
|
generate_class_begin(g);
|
|
1337
1415
|
|
|
1338
1416
|
generate_amongs(g);
|