mittens 0.3.1 → 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 +4 -0
- data/Gemfile +1 -0
- data/README.md +2 -2
- data/Rakefile +10 -3
- 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,67 +1,67 @@
|
|
|
1
1
|
#include <assert.h>
|
|
2
|
+
#include <stdio.h> /* for fprintf etc */
|
|
2
3
|
#include <stdlib.h> /* for exit */
|
|
3
4
|
#include <string.h> /* for strlen */
|
|
4
|
-
#include <stdio.h> /* for fprintf etc */
|
|
5
5
|
#include "header.h"
|
|
6
6
|
|
|
7
|
-
/*
|
|
7
|
+
/* prototype functions for recursive use: */
|
|
8
8
|
|
|
9
9
|
static void generate(struct generator * g, struct node * p);
|
|
10
10
|
static void w(struct generator * g, const char * s);
|
|
11
11
|
static void writef(struct generator * g, const char * s, struct node * p);
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
return g->next_label++;
|
|
15
|
-
}
|
|
13
|
+
/* Write routines for items from the syntax tree */
|
|
16
14
|
|
|
17
|
-
static
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
15
|
+
static void write_relop(struct generator * g, int relop) {
|
|
16
|
+
// Relational operators are the same as C, save for (in-)equality.
|
|
17
|
+
switch (relop) {
|
|
18
|
+
case c_eq: write_string(g, " === "); break;
|
|
19
|
+
case c_ne: write_string(g, " !== "); break;
|
|
20
|
+
default: write_c_relop(g, relop);
|
|
21
|
+
}
|
|
24
22
|
}
|
|
25
23
|
|
|
26
|
-
/* Write routines for items from the syntax tree */
|
|
27
|
-
|
|
28
24
|
static void write_varname(struct generator * g, struct name * p) {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
25
|
+
if (p->type == t_external) {
|
|
26
|
+
if (g->options->externals_prefix) {
|
|
27
|
+
write_string(g, g->options->externals_prefix);
|
|
28
|
+
}
|
|
29
|
+
} else {
|
|
30
|
+
// We use the same naming scheme for both global and local variables.
|
|
31
|
+
write_char(g, "SBIrxg"[p->type]);
|
|
32
32
|
write_char(g, '_');
|
|
33
33
|
}
|
|
34
34
|
write_s(g, p->s);
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
/* Reference to variable, e.g. when assigning to or using in an expression. */
|
|
37
38
|
static void write_varref(struct generator * g, struct name * p) {
|
|
39
|
+
if (p->type != t_grouping && p->local_to == NULL) {
|
|
40
|
+
w(g, "this.#");
|
|
41
|
+
}
|
|
38
42
|
write_varname(g, p);
|
|
39
43
|
}
|
|
40
44
|
|
|
41
45
|
static void write_literal_string(struct generator * g, symbol * p) {
|
|
42
|
-
|
|
46
|
+
write_char(g, '"');
|
|
43
47
|
for (int i = 0; i < SIZE(p); i++) {
|
|
44
48
|
int ch = p[i];
|
|
45
49
|
if (32 <= ch && ch < 127) {
|
|
46
|
-
if (ch == '\"' || ch == '\\')
|
|
50
|
+
if (ch == '\"' || ch == '\\') write_char(g, '\\');
|
|
47
51
|
write_char(g, ch);
|
|
48
52
|
} else {
|
|
49
53
|
write_string(g, "\\u");
|
|
50
54
|
write_hex4(g, ch);
|
|
51
55
|
}
|
|
52
56
|
}
|
|
53
|
-
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
static void write_margin(struct generator * g) {
|
|
57
|
-
for (int i = 0; i < g->margin; i++) write_string(g, " ");
|
|
57
|
+
write_char(g, '"');
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
static void write_comment(struct generator * g, struct node * p) {
|
|
61
61
|
if (!g->options->comments) return;
|
|
62
62
|
write_margin(g);
|
|
63
63
|
write_string(g, "// ");
|
|
64
|
-
write_comment_content(g, p);
|
|
64
|
+
write_comment_content(g, p, NULL);
|
|
65
65
|
write_newline(g);
|
|
66
66
|
}
|
|
67
67
|
|
|
@@ -77,15 +77,15 @@ static void write_savecursor(struct generator * g, struct node * p,
|
|
|
77
77
|
struct str * savevar) {
|
|
78
78
|
g->B[0] = str_data(savevar);
|
|
79
79
|
g->S[1] = "";
|
|
80
|
-
if (p->mode != m_forward) g->S[1] = "
|
|
81
|
-
writef(g, "~
|
|
80
|
+
if (p->mode != m_forward) g->S[1] = "this.limit - ";
|
|
81
|
+
writef(g, "~Mconst /** number */ ~B0 = ~S1this.c;~N", p);
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
static void append_restore_string(struct node * p, struct str * out, struct str * savevar) {
|
|
85
|
-
str_append_string(out, "
|
|
86
|
-
if (p->mode != m_forward) str_append_string(out, "
|
|
85
|
+
str_append_string(out, "this.c = ");
|
|
86
|
+
if (p->mode != m_forward) str_append_string(out, "this.limit - ");
|
|
87
87
|
str_append(out, savevar);
|
|
88
|
-
|
|
88
|
+
str_append_ch(out, ';');
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
static void write_restorecursor(struct generator * g, struct node * p, struct str * savevar) {
|
|
@@ -96,12 +96,14 @@ static void write_restorecursor(struct generator * g, struct node * p, struct st
|
|
|
96
96
|
|
|
97
97
|
static void write_inc_cursor(struct generator * g, struct node * p) {
|
|
98
98
|
write_margin(g);
|
|
99
|
-
write_string(g, p->mode == m_forward ? "
|
|
99
|
+
write_string(g, p->mode == m_forward ? "this.c++;" : "this.c--;");
|
|
100
100
|
write_newline(g);
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
static void wsetlab_begin(struct generator * g, int n) {
|
|
104
104
|
g->I[0] = n;
|
|
105
|
+
// This label may end up unused, but we can't easily tell at this point.
|
|
106
|
+
w(g, "~M// deno-lint-ignore no-unused-labels~N");
|
|
105
107
|
w(g, "~Mlab~I0: {~N~+");
|
|
106
108
|
}
|
|
107
109
|
|
|
@@ -113,53 +115,62 @@ static void wgotol(struct generator * g, int n) {
|
|
|
113
115
|
write_margin(g);
|
|
114
116
|
write_string(g, "break lab");
|
|
115
117
|
write_int(g, n);
|
|
116
|
-
|
|
118
|
+
write_char(g, ';');
|
|
117
119
|
write_newline(g);
|
|
120
|
+
g->unreachable = true;
|
|
118
121
|
}
|
|
119
122
|
|
|
120
|
-
static void
|
|
123
|
+
static void write_failure_(struct generator * g, byte after_if) {
|
|
124
|
+
if (!after_if) write_margin(g);
|
|
121
125
|
if (str_len(g->failure_str) != 0) {
|
|
122
|
-
|
|
126
|
+
if (after_if) w(g, "{~N~+~M");
|
|
123
127
|
write_str(g, g->failure_str);
|
|
124
128
|
write_newline(g);
|
|
129
|
+
write_margin(g);
|
|
125
130
|
}
|
|
126
|
-
write_margin(g);
|
|
127
131
|
switch (g->failure_label) {
|
|
128
132
|
case x_return:
|
|
129
133
|
write_string(g, "return false;");
|
|
130
|
-
g->unreachable = true;
|
|
131
134
|
break;
|
|
132
135
|
default:
|
|
133
136
|
write_string(g, "break lab");
|
|
134
137
|
write_int(g, g->failure_label);
|
|
135
|
-
|
|
136
|
-
g->unreachable = true;
|
|
138
|
+
write_char(g, ';');
|
|
137
139
|
}
|
|
138
140
|
write_newline(g);
|
|
141
|
+
g->unreachable = true;
|
|
142
|
+
if (after_if && str_len(g->failure_str) != 0) {
|
|
143
|
+
w(g, "~-~M}~N");
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
static void write_failure(struct generator * g) {
|
|
148
|
+
write_failure_(g, false);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
static void write_failure_after_if(struct generator * g) {
|
|
152
|
+
write_failure_(g, true);
|
|
139
153
|
}
|
|
140
154
|
|
|
141
155
|
static void write_failure_if(struct generator * g, const char * s, struct node * p) {
|
|
142
156
|
writef(g, "~Mif (", p);
|
|
143
157
|
writef(g, s, p);
|
|
144
|
-
writef(g, ")
|
|
145
|
-
|
|
146
|
-
write_failure(g);
|
|
147
|
-
write_block_end(g);
|
|
158
|
+
writef(g, ") ", p);
|
|
159
|
+
write_failure_after_if(g);
|
|
148
160
|
g->unreachable = false;
|
|
149
161
|
}
|
|
150
162
|
|
|
151
163
|
/* if at limit fail */
|
|
152
164
|
static void write_check_limit(struct generator * g, struct node * p) {
|
|
153
165
|
if (p->mode == m_forward) {
|
|
154
|
-
write_failure_if(g, "
|
|
166
|
+
write_failure_if(g, "this.c >= this.limit", p);
|
|
155
167
|
} else {
|
|
156
|
-
write_failure_if(g, "
|
|
168
|
+
write_failure_if(g, "this.c <= this.limit_backward", p);
|
|
157
169
|
}
|
|
158
170
|
}
|
|
159
171
|
|
|
160
172
|
/* Formatted write. */
|
|
161
173
|
static void writef(struct generator * g, const char * input, struct node * p) {
|
|
162
|
-
(void)p;
|
|
163
174
|
int i = 0;
|
|
164
175
|
|
|
165
176
|
while (input[i]) {
|
|
@@ -171,10 +182,8 @@ static void writef(struct generator * g, const char * input, struct node * p) {
|
|
|
171
182
|
ch = input[i++];
|
|
172
183
|
switch (ch) {
|
|
173
184
|
case '~': write_char(g, '~'); continue;
|
|
174
|
-
case 'f':
|
|
175
|
-
write_failure(g);
|
|
185
|
+
case 'f': write_failure(g);
|
|
176
186
|
g->unreachable = false;
|
|
177
|
-
write_block_end(g);
|
|
178
187
|
continue;
|
|
179
188
|
case 'M': write_margin(g); continue;
|
|
180
189
|
case 'N': write_newline(g); continue;
|
|
@@ -197,6 +206,33 @@ static void writef(struct generator * g, const char * input, struct node * p) {
|
|
|
197
206
|
write_s(g, g->B[j]);
|
|
198
207
|
continue;
|
|
199
208
|
}
|
|
209
|
+
case 'F': { // Among function dispatcher.
|
|
210
|
+
struct among * x = p->among;
|
|
211
|
+
if (x->function_count == 0) {
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
w(g, ", ");
|
|
216
|
+
|
|
217
|
+
if (x->function_count == 1) {
|
|
218
|
+
// Only one different function used in this among.
|
|
219
|
+
struct amongvec * v = x->b;
|
|
220
|
+
for (int j = 0; j < x->literalstring_count; j++) {
|
|
221
|
+
if (v[j].function) {
|
|
222
|
+
write_varref(g, v[j].function);
|
|
223
|
+
goto continue_outer_loop;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
fprintf(stderr, "function_count == 1 but no among functions\n");
|
|
227
|
+
exit(1);
|
|
228
|
+
continue_outer_loop:
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
w(g, "this.#af_");
|
|
233
|
+
write_int(g, x->number);
|
|
234
|
+
continue;
|
|
235
|
+
}
|
|
200
236
|
case 'I': {
|
|
201
237
|
int j = input[i++] - '0';
|
|
202
238
|
if (j < 0 || j > (int)(sizeof(g->I) / sizeof(g->I[0])))
|
|
@@ -205,43 +241,17 @@ static void writef(struct generator * g, const char * input, struct node * p) {
|
|
|
205
241
|
continue;
|
|
206
242
|
}
|
|
207
243
|
case 'V':
|
|
208
|
-
|
|
209
|
-
int j = input[i++] - '0';
|
|
210
|
-
if (j < 0 || j > (int)(sizeof(g->V) / sizeof(g->V[0])))
|
|
211
|
-
goto invalid_escape2;
|
|
212
|
-
if (ch == 'V')
|
|
213
|
-
write_varref(g, g->V[j]);
|
|
214
|
-
else
|
|
215
|
-
write_varname(g, g->V[j]);
|
|
244
|
+
write_varref(g, p->name);
|
|
216
245
|
continue;
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
write_literal_string(g, g->L[j]);
|
|
246
|
+
case 'W':
|
|
247
|
+
write_varname(g, p->name);
|
|
248
|
+
continue;
|
|
249
|
+
case 'L':
|
|
250
|
+
write_literal_string(g, p->literalstring);
|
|
223
251
|
continue;
|
|
224
|
-
}
|
|
225
252
|
case '+': g->margin++; continue;
|
|
226
253
|
case '-': g->margin--; continue;
|
|
227
|
-
case 'n': write_string(g, g->options->name); continue;
|
|
228
254
|
case 'P': write_string(g, g->options->parent_class_name); continue;
|
|
229
|
-
case 'C': { // Constant.
|
|
230
|
-
if (g->options->js_esm) {
|
|
231
|
-
w(g, "const");
|
|
232
|
-
} else {
|
|
233
|
-
w(g, "/** @const */ var");
|
|
234
|
-
}
|
|
235
|
-
continue;
|
|
236
|
-
}
|
|
237
|
-
case 'D': { // Declare variable.
|
|
238
|
-
if (g->options->js_esm) {
|
|
239
|
-
w(g, "let");
|
|
240
|
-
} else {
|
|
241
|
-
w(g, "var");
|
|
242
|
-
}
|
|
243
|
-
continue;
|
|
244
|
-
}
|
|
245
255
|
default:
|
|
246
256
|
printf("Invalid escape sequence ~%c in writef(g, \"%s\", p)\n",
|
|
247
257
|
ch, input);
|
|
@@ -262,46 +272,56 @@ static void generate_AE(struct generator * g, struct node * p) {
|
|
|
262
272
|
const char * s;
|
|
263
273
|
switch (p->type) {
|
|
264
274
|
case c_name:
|
|
265
|
-
write_varref(g, p->name);
|
|
275
|
+
write_varref(g, p->name);
|
|
276
|
+
break;
|
|
266
277
|
case c_number:
|
|
267
|
-
write_int(g, p->number);
|
|
278
|
+
write_int(g, p->number);
|
|
279
|
+
break;
|
|
268
280
|
case c_maxint:
|
|
269
|
-
write_string(g, "(-1>>>1)");
|
|
281
|
+
write_string(g, "(-1>>>1)");
|
|
282
|
+
break;
|
|
270
283
|
case c_minint:
|
|
271
|
-
write_string(g, "(~(-1>>>1))");
|
|
284
|
+
write_string(g, "(~(-1>>>1))");
|
|
285
|
+
break;
|
|
272
286
|
case c_neg:
|
|
273
|
-
write_char(g, '-');
|
|
287
|
+
write_char(g, '-');
|
|
288
|
+
generate_AE(g, p->right);
|
|
289
|
+
break;
|
|
274
290
|
case c_multiply:
|
|
275
|
-
s = " * ";
|
|
276
|
-
|
|
277
|
-
s = " + "; goto label0;
|
|
278
|
-
case c_minus:
|
|
279
|
-
s = " - ";
|
|
280
|
-
label0:
|
|
281
|
-
write_char(g, '('); generate_AE(g, p->left);
|
|
282
|
-
write_string(g, s); generate_AE(g, p->right); write_char(g, ')'); break;
|
|
291
|
+
s = " * ";
|
|
292
|
+
goto label0;
|
|
283
293
|
case c_divide:
|
|
284
294
|
/* Snowball specifies integer division with semantics matching C,
|
|
285
295
|
* so we need to use `Math.trunc(x/y)` here.
|
|
286
296
|
*/
|
|
287
|
-
write_string(g, "Math.trunc
|
|
297
|
+
write_string(g, "Math.trunc");
|
|
298
|
+
s = " / ";
|
|
299
|
+
goto label0;
|
|
300
|
+
case c_plus:
|
|
301
|
+
s = " + ";
|
|
302
|
+
goto label0;
|
|
303
|
+
case c_minus:
|
|
304
|
+
s = " - ";
|
|
305
|
+
label0:
|
|
306
|
+
write_char(g, '(');
|
|
288
307
|
generate_AE(g, p->left);
|
|
289
|
-
write_string(g,
|
|
308
|
+
write_string(g, s);
|
|
290
309
|
generate_AE(g, p->right);
|
|
291
310
|
write_char(g, ')');
|
|
292
311
|
break;
|
|
293
312
|
case c_cursor:
|
|
294
|
-
w(g, "
|
|
313
|
+
w(g, "this.c");
|
|
314
|
+
break;
|
|
295
315
|
case c_limit:
|
|
296
|
-
w(g, p->mode == m_forward ? "
|
|
297
|
-
case c_lenof: /* Same as sizeof() for Javascript. */
|
|
298
|
-
case c_sizeof:
|
|
299
|
-
g->V[0] = p->name;
|
|
300
|
-
w(g, "~V0.length");
|
|
316
|
+
w(g, p->mode == m_forward ? "this.limit" : "this.limit_backward");
|
|
301
317
|
break;
|
|
302
318
|
case c_len: /* Same as size() for Javascript. */
|
|
303
319
|
case c_size:
|
|
304
|
-
w(g, "
|
|
320
|
+
w(g, "this.current.length");
|
|
321
|
+
break;
|
|
322
|
+
case c_lenof: /* Same as sizeof() for Javascript. */
|
|
323
|
+
case c_sizeof:
|
|
324
|
+
writef(g, "~V.length", p);
|
|
305
325
|
break;
|
|
306
326
|
}
|
|
307
327
|
}
|
|
@@ -317,13 +337,15 @@ static void generate_bra(struct generator * g, struct node * p) {
|
|
|
317
337
|
|
|
318
338
|
static void generate_and(struct generator * g, struct node * p) {
|
|
319
339
|
struct str * savevar = NULL;
|
|
320
|
-
if (
|
|
340
|
+
if (K_needed_for_and(p->left)) {
|
|
321
341
|
savevar = vars_newname(g);
|
|
322
342
|
}
|
|
323
343
|
|
|
324
344
|
write_comment(g, p);
|
|
325
345
|
|
|
326
|
-
if (savevar)
|
|
346
|
+
if (savevar) {
|
|
347
|
+
write_savecursor(g, p, savevar);
|
|
348
|
+
}
|
|
327
349
|
|
|
328
350
|
p = p->left;
|
|
329
351
|
while (p) {
|
|
@@ -340,7 +362,7 @@ static void generate_and(struct generator * g, struct node * p) {
|
|
|
340
362
|
|
|
341
363
|
static void generate_or(struct generator * g, struct node * p) {
|
|
342
364
|
struct str * savevar = NULL;
|
|
343
|
-
if (
|
|
365
|
+
if (K_needed_for_or(p->left)) {
|
|
344
366
|
savevar = vars_newname(g);
|
|
345
367
|
}
|
|
346
368
|
|
|
@@ -348,12 +370,14 @@ static void generate_or(struct generator * g, struct node * p) {
|
|
|
348
370
|
struct str * a1 = str_copy(g->failure_str);
|
|
349
371
|
|
|
350
372
|
int out_lab = new_label(g);
|
|
351
|
-
|
|
373
|
+
bool end_unreachable = true;
|
|
352
374
|
|
|
353
375
|
write_comment(g, p);
|
|
354
376
|
wsetlab_begin(g, out_lab);
|
|
355
377
|
|
|
356
|
-
if (savevar
|
|
378
|
+
if (savevar && K_needed_node_on_f(p)) {
|
|
379
|
+
write_savecursor(g, p, savevar);
|
|
380
|
+
}
|
|
357
381
|
|
|
358
382
|
p = p->left;
|
|
359
383
|
str_clear(g->failure_str);
|
|
@@ -365,7 +389,8 @@ static void generate_or(struct generator * g, struct node * p) {
|
|
|
365
389
|
exit(1);
|
|
366
390
|
}
|
|
367
391
|
while (p->right != NULL) {
|
|
368
|
-
|
|
392
|
+
int label = new_label(g);
|
|
393
|
+
g->failure_label = label;
|
|
369
394
|
wsetlab_begin(g, g->failure_label);
|
|
370
395
|
generate(g, p);
|
|
371
396
|
if (!g->unreachable) {
|
|
@@ -374,7 +399,9 @@ static void generate_or(struct generator * g, struct node * p) {
|
|
|
374
399
|
}
|
|
375
400
|
wsetlab_end(g);
|
|
376
401
|
g->unreachable = false;
|
|
377
|
-
if (savevar)
|
|
402
|
+
if (savevar) {
|
|
403
|
+
write_restorecursor(g, p, savevar);
|
|
404
|
+
}
|
|
378
405
|
p = p->right;
|
|
379
406
|
}
|
|
380
407
|
|
|
@@ -395,15 +422,14 @@ static void generate_or(struct generator * g, struct node * p) {
|
|
|
395
422
|
|
|
396
423
|
static void generate_backwards(struct generator * g, struct node * p) {
|
|
397
424
|
write_comment(g, p);
|
|
398
|
-
writef(g, "~
|
|
425
|
+
writef(g, "~Mthis.limit_backward = this.c; this.c = this.limit;~N", p);
|
|
399
426
|
generate(g, p->left);
|
|
400
|
-
w(g, "~
|
|
427
|
+
w(g, "~Mthis.c = this.limit_backward;~N");
|
|
401
428
|
}
|
|
402
429
|
|
|
403
|
-
|
|
404
430
|
static void generate_not(struct generator * g, struct node * p) {
|
|
405
431
|
struct str * savevar = NULL;
|
|
406
|
-
if (
|
|
432
|
+
if (K_needed_node_on_f(p->left)) {
|
|
407
433
|
savevar = vars_newname(g);
|
|
408
434
|
}
|
|
409
435
|
|
|
@@ -416,7 +442,8 @@ static void generate_not(struct generator * g, struct node * p) {
|
|
|
416
442
|
write_savecursor(g, p, savevar);
|
|
417
443
|
}
|
|
418
444
|
|
|
419
|
-
|
|
445
|
+
int label = new_label(g);
|
|
446
|
+
g->failure_label = label;
|
|
420
447
|
str_clear(g->failure_str);
|
|
421
448
|
|
|
422
449
|
wsetlab_begin(g, g->failure_label);
|
|
@@ -439,14 +466,14 @@ static void generate_not(struct generator * g, struct node * p) {
|
|
|
439
466
|
}
|
|
440
467
|
}
|
|
441
468
|
|
|
442
|
-
|
|
443
469
|
static void generate_try(struct generator * g, struct node * p) {
|
|
444
470
|
struct str * savevar = NULL;
|
|
445
|
-
if (K_needed(
|
|
471
|
+
if (K_needed(p->left)) {
|
|
446
472
|
savevar = vars_newname(g);
|
|
447
473
|
}
|
|
448
474
|
|
|
449
|
-
|
|
475
|
+
int label = new_label(g);
|
|
476
|
+
g->failure_label = label;
|
|
450
477
|
str_clear(g->failure_str);
|
|
451
478
|
|
|
452
479
|
write_comment(g, p);
|
|
@@ -467,14 +494,12 @@ static void generate_try(struct generator * g, struct node * p) {
|
|
|
467
494
|
|
|
468
495
|
static void generate_set(struct generator * g, struct node * p) {
|
|
469
496
|
write_comment(g, p);
|
|
470
|
-
g
|
|
471
|
-
writef(g, "~M~V0 = true;~N", p);
|
|
497
|
+
writef(g, "~M~V = true;~N", p);
|
|
472
498
|
}
|
|
473
499
|
|
|
474
500
|
static void generate_unset(struct generator * g, struct node * p) {
|
|
475
501
|
write_comment(g, p);
|
|
476
|
-
g
|
|
477
|
-
writef(g, "~M~V0 = false;~N", p);
|
|
502
|
+
writef(g, "~M~V = false;~N", p);
|
|
478
503
|
}
|
|
479
504
|
|
|
480
505
|
static void generate_fail(struct generator * g, struct node * p) {
|
|
@@ -484,10 +509,9 @@ static void generate_fail(struct generator * g, struct node * p) {
|
|
|
484
509
|
}
|
|
485
510
|
|
|
486
511
|
/* generate_test() also implements 'reverse' */
|
|
487
|
-
|
|
488
512
|
static void generate_test(struct generator * g, struct node * p) {
|
|
489
513
|
struct str * savevar = NULL;
|
|
490
|
-
if (K_needed(
|
|
514
|
+
if (K_needed(p->left)) {
|
|
491
515
|
savevar = vars_newname(g);
|
|
492
516
|
}
|
|
493
517
|
|
|
@@ -509,20 +533,22 @@ static void generate_test(struct generator * g, struct node * p) {
|
|
|
509
533
|
|
|
510
534
|
static void generate_do(struct generator * g, struct node * p) {
|
|
511
535
|
struct str * savevar = NULL;
|
|
512
|
-
if (K_needed(
|
|
536
|
+
if (K_needed(p->left)) {
|
|
513
537
|
savevar = vars_newname(g);
|
|
514
538
|
}
|
|
515
539
|
|
|
516
540
|
write_comment(g, p);
|
|
517
|
-
if (savevar)
|
|
541
|
+
if (savevar) {
|
|
542
|
+
write_savecursor(g, p, savevar);
|
|
543
|
+
}
|
|
518
544
|
|
|
519
545
|
if (p->left->type == c_call) {
|
|
520
546
|
/* Optimise do <call> */
|
|
521
547
|
write_comment(g, p->left);
|
|
522
|
-
g
|
|
523
|
-
w(g, "~M~V0();~N");
|
|
548
|
+
writef(g, "~M~V();~N", p->left);
|
|
524
549
|
} else {
|
|
525
|
-
|
|
550
|
+
int label = new_label(g);
|
|
551
|
+
g->failure_label = label;
|
|
526
552
|
str_clear(g->failure_str);
|
|
527
553
|
|
|
528
554
|
wsetlab_begin(g, g->failure_label);
|
|
@@ -549,37 +575,40 @@ static void generate_GO_grouping(struct generator * g, struct node * p, int is_g
|
|
|
549
575
|
struct grouping * q = p->name->grouping;
|
|
550
576
|
g->S[0] = p->mode == m_forward ? "" : "_b";
|
|
551
577
|
g->S[1] = complement ? "in" : "out";
|
|
552
|
-
g->V[0] = p->name;
|
|
553
578
|
g->I[0] = q->smallest_ch;
|
|
554
579
|
g->I[1] = q->largest_ch;
|
|
555
|
-
write_failure_if(g, "!
|
|
580
|
+
write_failure_if(g, "!this.go_~S1_grouping~S0(~V, ~I0, ~I1)", p);
|
|
556
581
|
if (!is_goto) {
|
|
557
582
|
if (p->mode == m_forward)
|
|
558
|
-
w(g, "~
|
|
583
|
+
w(g, "~Mthis.c++;~N");
|
|
559
584
|
else
|
|
560
|
-
w(g, "~
|
|
585
|
+
w(g, "~Mthis.c--;~N");
|
|
561
586
|
}
|
|
562
587
|
}
|
|
563
588
|
|
|
564
|
-
static void generate_GO(struct generator * g, struct node * p, int
|
|
589
|
+
static void generate_GO(struct generator * g, struct node * p, int is_goto) {
|
|
565
590
|
write_comment(g, p);
|
|
566
591
|
|
|
567
592
|
int a0 = g->failure_label;
|
|
568
593
|
struct str * a1 = str_copy(g->failure_str);
|
|
569
594
|
|
|
570
|
-
|
|
595
|
+
bool end_unreachable = false;
|
|
596
|
+
|
|
571
597
|
int golab = new_label(g);
|
|
572
598
|
g->I[0] = golab;
|
|
573
|
-
|
|
599
|
+
// This label may end up unused, but we can't easily tell at this point.
|
|
600
|
+
w(g, "~M// deno-lint-ignore no-unused-labels~N");
|
|
601
|
+
w(g, "~Mgolab~I0: while (true)~N");
|
|
574
602
|
w(g, "~{");
|
|
575
603
|
|
|
576
604
|
struct str * savevar = NULL;
|
|
577
|
-
if (
|
|
605
|
+
if (is_goto || repeat_restore(p->left)) {
|
|
578
606
|
savevar = vars_newname(g);
|
|
579
607
|
write_savecursor(g, p, savevar);
|
|
580
608
|
}
|
|
581
609
|
|
|
582
|
-
|
|
610
|
+
int label = new_label(g);
|
|
611
|
+
g->failure_label = label;
|
|
583
612
|
str_clear(g->failure_str);
|
|
584
613
|
wsetlab_begin(g, g->failure_label);
|
|
585
614
|
generate(g, p->left);
|
|
@@ -590,7 +619,7 @@ static void generate_GO(struct generator * g, struct node * p, int style) {
|
|
|
590
619
|
end_unreachable = true;
|
|
591
620
|
} else {
|
|
592
621
|
/* include for goto; omit for gopast */
|
|
593
|
-
if (
|
|
622
|
+
if (is_goto) write_restorecursor(g, p, savevar);
|
|
594
623
|
g->I[0] = golab;
|
|
595
624
|
w(g, "~Mbreak golab~I0;~N");
|
|
596
625
|
}
|
|
@@ -612,10 +641,10 @@ static void generate_GO(struct generator * g, struct node * p, int style) {
|
|
|
612
641
|
}
|
|
613
642
|
|
|
614
643
|
static void generate_loop(struct generator * g, struct node * p) {
|
|
615
|
-
struct str * loopvar = vars_newname(g);
|
|
616
644
|
write_comment(g, p);
|
|
645
|
+
struct str * loopvar = vars_newname(g);
|
|
617
646
|
g->B[0] = str_data(loopvar);
|
|
618
|
-
w(g, "~Mfor (
|
|
647
|
+
w(g, "~Mfor (let /** number */ ~B0 = ");
|
|
619
648
|
generate_AE(g, p->AE);
|
|
620
649
|
g->B[0] = str_data(loopvar);
|
|
621
650
|
writef(g, "; ~B0 > 0; ~B0--)~N", p);
|
|
@@ -629,15 +658,16 @@ static void generate_loop(struct generator * g, struct node * p) {
|
|
|
629
658
|
}
|
|
630
659
|
|
|
631
660
|
static void generate_repeat_or_atleast(struct generator * g, struct node * p, struct str * loopvar) {
|
|
632
|
-
writef(g, "~Mwhile(true)~N
|
|
661
|
+
writef(g, "~Mwhile (true) {~N~+", p);
|
|
633
662
|
|
|
634
663
|
struct str * savevar = NULL;
|
|
635
|
-
if (repeat_restore(
|
|
664
|
+
if (repeat_restore(p->left)) {
|
|
636
665
|
savevar = vars_newname(g);
|
|
637
666
|
write_savecursor(g, p, savevar);
|
|
638
667
|
}
|
|
639
668
|
|
|
640
|
-
|
|
669
|
+
int label = new_label(g);
|
|
670
|
+
g->failure_label = label;
|
|
641
671
|
str_clear(g->failure_str);
|
|
642
672
|
wsetlab_begin(g, g->failure_label);
|
|
643
673
|
generate(g, p->left);
|
|
@@ -668,12 +698,12 @@ static void generate_repeat(struct generator * g, struct node * p) {
|
|
|
668
698
|
}
|
|
669
699
|
|
|
670
700
|
static void generate_atleast(struct generator * g, struct node * p) {
|
|
671
|
-
struct str * loopvar = vars_newname(g);
|
|
672
|
-
|
|
673
701
|
write_comment(g, p);
|
|
702
|
+
|
|
674
703
|
w(g, "~{");
|
|
704
|
+
struct str * loopvar = vars_newname(g);
|
|
675
705
|
g->B[0] = str_data(loopvar);
|
|
676
|
-
w(g, "~
|
|
706
|
+
w(g, "~Mlet ~B0 = ");
|
|
677
707
|
generate_AE(g, p->AE);
|
|
678
708
|
w(g, ";~N");
|
|
679
709
|
{
|
|
@@ -692,117 +722,75 @@ static void generate_atleast(struct generator * g, struct node * p) {
|
|
|
692
722
|
str_delete(loopvar);
|
|
693
723
|
}
|
|
694
724
|
|
|
695
|
-
static void generate_setmark(struct generator * g, struct node * p) {
|
|
696
|
-
write_comment(g, p);
|
|
697
|
-
g->V[0] = p->name;
|
|
698
|
-
writef(g, "~M~V0 = base.cursor;~N", p);
|
|
699
|
-
}
|
|
700
|
-
|
|
701
725
|
static void generate_tomark(struct generator * g, struct node * p) {
|
|
702
726
|
write_comment(g, p);
|
|
703
727
|
g->S[0] = p->mode == m_forward ? ">" : "<";
|
|
704
728
|
|
|
705
|
-
w(g, "~Mif (
|
|
706
|
-
|
|
707
|
-
write_failure(g);
|
|
708
|
-
write_block_end(g);
|
|
709
|
-
g->unreachable = false;
|
|
710
|
-
w(g, "~Mbase.cursor = "); generate_AE(g, p->AE); writef(g, ";~N", p);
|
|
711
|
-
}
|
|
712
|
-
|
|
713
|
-
static void generate_atmark(struct generator * g, struct node * p) {
|
|
714
|
-
write_comment(g, p);
|
|
715
|
-
w(g, "~Mif (base.cursor != "); generate_AE(g, p->AE); writef(g, ")~N", p);
|
|
716
|
-
write_block_start(g);
|
|
717
|
-
write_failure(g);
|
|
718
|
-
write_block_end(g);
|
|
729
|
+
w(g, "~Mif (this.c ~S0 "); generate_AE(g, p->AE); w(g, ") ");
|
|
730
|
+
write_failure_after_if(g);
|
|
719
731
|
g->unreachable = false;
|
|
732
|
+
w(g, "~Mthis.c = "); generate_AE(g, p->AE); writef(g, ";~N", p);
|
|
720
733
|
}
|
|
721
734
|
|
|
722
735
|
static void generate_hop(struct generator * g, struct node * p) {
|
|
723
|
-
int c_count = ++g->keep_count;
|
|
724
736
|
write_comment(g, p);
|
|
725
737
|
g->S[0] = p->mode == m_forward ? "+" : "-";
|
|
726
738
|
|
|
727
|
-
g->
|
|
728
|
-
w(g, "~{~M~C /** number */ c~I0 = base.cursor ~S0 ");
|
|
729
|
-
generate_AE(g, p->AE);
|
|
730
|
-
w(g, ";~N");
|
|
731
|
-
|
|
732
|
-
g->I[0] = c_count;
|
|
733
|
-
g->S[1] = p->mode == m_forward ? "> base.limit" : "< base.limit_backward";
|
|
739
|
+
g->S[1] = p->mode == m_forward ? "> this.limit" : "< this.limit_backward";
|
|
734
740
|
g->S[2] = p->mode == m_forward ? "<" : ">";
|
|
735
741
|
if (p->AE->type == c_number) {
|
|
736
742
|
// Constant distance hop.
|
|
737
743
|
//
|
|
738
744
|
// No need to check for negative hop as that's converted to false by
|
|
739
745
|
// the analyser.
|
|
740
|
-
|
|
746
|
+
g->I[0] = p->AE->number;
|
|
747
|
+
write_failure_if(g, "this.c ~S0 ~I0 ~S1", p);
|
|
748
|
+
writef(g, "~Mthis.c ~S0= ~I0;~N", p);
|
|
741
749
|
} else {
|
|
742
|
-
|
|
750
|
+
w(g, "~{~Mconst /** number */ c = this.c ~S0 ");
|
|
751
|
+
generate_AE(g, p->AE);
|
|
752
|
+
w(g, ";~N");
|
|
753
|
+
write_failure_if(g, "c ~S1 || c ~S2 this.c", p);
|
|
754
|
+
writef(g, "~Mthis.c = c;~N", p);
|
|
755
|
+
writef(g, "~}", p);
|
|
743
756
|
}
|
|
744
|
-
writef(g, "~Mbase.cursor = c~I0;~N", p);
|
|
745
|
-
writef(g, "~}", p);
|
|
746
|
-
}
|
|
747
|
-
|
|
748
|
-
static void generate_delete(struct generator * g, struct node * p) {
|
|
749
|
-
write_comment(g, p);
|
|
750
|
-
writef(g, "~Mif (!base.slice_del())~N"
|
|
751
|
-
"~M{~N"
|
|
752
|
-
"~+~Mreturn false;~N~-"
|
|
753
|
-
"~M}~N", p);
|
|
754
757
|
}
|
|
755
758
|
|
|
756
759
|
static void generate_tolimit(struct generator * g, struct node * p) {
|
|
757
760
|
write_comment(g, p);
|
|
758
761
|
if (p->mode == m_forward) {
|
|
759
|
-
writef(g, "~
|
|
762
|
+
writef(g, "~Mthis.c = this.limit;~N", p);
|
|
760
763
|
} else {
|
|
761
|
-
writef(g, "~
|
|
762
|
-
}
|
|
763
|
-
}
|
|
764
|
-
|
|
765
|
-
static void generate_atlimit(struct generator * g, struct node * p) {
|
|
766
|
-
write_comment(g, p);
|
|
767
|
-
if (p->mode == m_forward) {
|
|
768
|
-
write_failure_if(g, "base.cursor < base.limit", p);
|
|
769
|
-
} else {
|
|
770
|
-
write_failure_if(g, "base.cursor > base.limit_backward", p);
|
|
764
|
+
writef(g, "~Mthis.c = this.limit_backward;~N", p);
|
|
771
765
|
}
|
|
772
766
|
}
|
|
773
767
|
|
|
774
768
|
static void generate_leftslice(struct generator * g, struct node * p) {
|
|
775
769
|
write_comment(g, p);
|
|
776
770
|
if (p->mode == m_forward) {
|
|
777
|
-
writef(g, "~
|
|
771
|
+
writef(g, "~Mthis.bra = this.c;~N", p);
|
|
778
772
|
} else {
|
|
779
|
-
writef(g, "~
|
|
773
|
+
writef(g, "~Mthis.ket = this.c;~N", p);
|
|
780
774
|
}
|
|
781
775
|
}
|
|
782
776
|
|
|
783
777
|
static void generate_rightslice(struct generator * g, struct node * p) {
|
|
784
778
|
write_comment(g, p);
|
|
785
779
|
if (p->mode == m_forward) {
|
|
786
|
-
writef(g, "~
|
|
780
|
+
writef(g, "~Mthis.ket = this.c;~N", p);
|
|
787
781
|
} else {
|
|
788
|
-
writef(g, "~
|
|
782
|
+
writef(g, "~Mthis.bra = this.c;~N", p);
|
|
789
783
|
}
|
|
790
784
|
}
|
|
791
785
|
|
|
792
786
|
static void generate_assignto(struct generator * g, struct node * p) {
|
|
793
787
|
write_comment(g, p);
|
|
794
|
-
g
|
|
795
|
-
writef(g, "~M~V0 = base.assign_to();~N", p);
|
|
788
|
+
writef(g, "~M~V = this.current.slice(0, this.limit);~N", p);
|
|
796
789
|
}
|
|
797
790
|
|
|
798
791
|
static void generate_sliceto(struct generator * g, struct node * p) {
|
|
799
792
|
write_comment(g, p);
|
|
800
|
-
g
|
|
801
|
-
writef(g, "~M~V0 = base.slice_to();~N"
|
|
802
|
-
"~Mif (~V0 == '')~N"
|
|
803
|
-
"~M{~N"
|
|
804
|
-
"~+~Mreturn false;~N~-"
|
|
805
|
-
"~M}~N", p);
|
|
793
|
+
writef(g, "~M~V = this.slice_to();~N", p);
|
|
806
794
|
}
|
|
807
795
|
|
|
808
796
|
static void generate_address(struct generator * g, struct node * p) {
|
|
@@ -815,60 +803,59 @@ static void generate_address(struct generator * g, struct node * p) {
|
|
|
815
803
|
}
|
|
816
804
|
|
|
817
805
|
static void generate_insert(struct generator * g, struct node * p, int style) {
|
|
818
|
-
int c_count;
|
|
819
|
-
int keep_c = style == c_attach;
|
|
820
806
|
write_comment(g, p);
|
|
807
|
+
int keep_c = style == c_attach;
|
|
821
808
|
if (p->mode == m_backward) keep_c = !keep_c;
|
|
822
809
|
if (keep_c) {
|
|
823
|
-
|
|
824
|
-
g
|
|
825
|
-
|
|
810
|
+
w(g, "~{~Mconst /** number */ c = this.c;~N");
|
|
811
|
+
writef(g, "~Mthis.insert(c, c, ", p);
|
|
812
|
+
} else {
|
|
813
|
+
writef(g, "~Mthis.insert(this.c, this.c, ", p);
|
|
826
814
|
}
|
|
827
|
-
writef(g, "~Mbase.insert(base.cursor, base.cursor, ", p);
|
|
828
815
|
generate_address(g, p);
|
|
829
816
|
writef(g, ");~N", p);
|
|
830
|
-
if (keep_c)
|
|
831
|
-
g->I[0] = c_count;
|
|
832
|
-
w(g, "~Mbase.cursor = c~I0;~N~}");
|
|
833
|
-
}
|
|
817
|
+
if (keep_c) w(g, "~Mthis.c = c;~N~}");
|
|
834
818
|
}
|
|
835
819
|
|
|
836
|
-
static void
|
|
837
|
-
int c_count;
|
|
838
|
-
int keep_c = p->mode == m_forward; /* like 'attach' */
|
|
839
|
-
|
|
820
|
+
static void generate_stringassign(struct generator * g, struct node * p) {
|
|
840
821
|
write_comment(g, p);
|
|
822
|
+
int keep_c = p->mode == m_forward; /* like 'attach' */
|
|
841
823
|
if (keep_c) {
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
824
|
+
w(g, "~{~Mconst /** number */ c = this.c;~N");
|
|
825
|
+
if (p->mode == m_forward) {
|
|
826
|
+
writef(g, "~Mthis.insert(c, this.limit, ", p);
|
|
827
|
+
} else {
|
|
828
|
+
writef(g, "~Mthis.insert(this.limit_backward, c, ", p);
|
|
829
|
+
}
|
|
848
830
|
} else {
|
|
849
|
-
|
|
831
|
+
if (p->mode == m_forward) {
|
|
832
|
+
writef(g, "~Mthis.insert(this.c, this.limit, ", p);
|
|
833
|
+
} else {
|
|
834
|
+
writef(g, "~Mthis.insert(this.limit_backward, this.c, ", p);
|
|
835
|
+
}
|
|
850
836
|
}
|
|
851
837
|
generate_address(g, p);
|
|
852
838
|
writef(g, ");~N", p);
|
|
853
839
|
if (keep_c) {
|
|
854
|
-
g
|
|
855
|
-
w(g, "~Mbase.cursor = c~I0;~N~}");
|
|
840
|
+
w(g, "~Mthis.c = c;~N~}");
|
|
856
841
|
}
|
|
857
842
|
}
|
|
858
843
|
|
|
859
844
|
static void generate_slicefrom(struct generator * g, struct node * p) {
|
|
860
845
|
write_comment(g, p);
|
|
861
|
-
|
|
846
|
+
if (p->literalstring && SIZE(p->literalstring) == 0) {
|
|
847
|
+
w(g, "~Mthis.slice_del();~N");
|
|
848
|
+
return;
|
|
849
|
+
}
|
|
850
|
+
w(g, "~Mthis.slice_from(");
|
|
862
851
|
generate_address(g, p);
|
|
863
|
-
|
|
864
|
-
"~M{~N"
|
|
865
|
-
"~+~Mreturn false;~N~-"
|
|
866
|
-
"~M}~N", p);
|
|
852
|
+
w(g, ");~N");
|
|
867
853
|
}
|
|
868
854
|
|
|
869
855
|
static void generate_setlimit(struct generator * g, struct node * p) {
|
|
870
|
-
struct str * varname = vars_newname(g);
|
|
871
856
|
write_comment(g, p);
|
|
857
|
+
struct str * varname = vars_newname(g);
|
|
858
|
+
|
|
872
859
|
if (p->left && p->left->type == c_tomark) {
|
|
873
860
|
/* Special case for:
|
|
874
861
|
*
|
|
@@ -880,30 +867,32 @@ static void generate_setlimit(struct generator * g, struct node * p) {
|
|
|
880
867
|
*/
|
|
881
868
|
struct node * q = p->left;
|
|
882
869
|
write_comment(g, q);
|
|
870
|
+
|
|
883
871
|
g->S[0] = q->mode == m_forward ? ">" : "<";
|
|
884
|
-
w(g, "~Mif (
|
|
885
|
-
|
|
886
|
-
write_failure(g);
|
|
887
|
-
write_block_end(g);
|
|
872
|
+
w(g, "~Mif (this.c ~S0 "); generate_AE(g, q->AE); w(g, ") ");
|
|
873
|
+
write_failure_after_if(g);
|
|
888
874
|
g->unreachable = false;
|
|
889
875
|
|
|
890
876
|
g->B[0] = str_data(varname);
|
|
891
|
-
w(g, "~M~C /** number */ ~B0 = ");
|
|
892
877
|
if (p->mode == m_forward) {
|
|
893
|
-
w(g, "
|
|
894
|
-
w(g, "~
|
|
878
|
+
w(g, "~Mlet /** number */ ~B0 = this.limit;~N");
|
|
879
|
+
w(g, "~Mthis.limit = ");
|
|
880
|
+
generate_AE(g, q->AE);
|
|
881
|
+
w(g, ";~N");
|
|
882
|
+
w(g, "~M~B0 -= this.limit;~N");
|
|
895
883
|
} else {
|
|
896
|
-
w(g, "
|
|
897
|
-
w(g, "~
|
|
884
|
+
w(g, "~Mconst /** number */ ~B0 = this.limit_backward;~N");
|
|
885
|
+
w(g, "~Mthis.limit_backward = ");
|
|
886
|
+
generate_AE(g, q->AE);
|
|
887
|
+
w(g, ";~N");
|
|
898
888
|
}
|
|
899
|
-
generate_AE(g, q->AE); writef(g, ";~N", q);
|
|
900
889
|
|
|
901
890
|
if (p->mode == m_forward) {
|
|
902
|
-
str_assign(g->failure_str, "
|
|
891
|
+
str_assign(g->failure_str, "this.limit += ");
|
|
903
892
|
str_append(g->failure_str, varname);
|
|
904
893
|
str_append_ch(g->failure_str, ';');
|
|
905
894
|
} else {
|
|
906
|
-
str_assign(g->failure_str, "
|
|
895
|
+
str_assign(g->failure_str, "this.limit_backward = ");
|
|
907
896
|
str_append(g->failure_str, varname);
|
|
908
897
|
str_append_ch(g->failure_str, ';');
|
|
909
898
|
}
|
|
@@ -915,22 +904,22 @@ static void generate_setlimit(struct generator * g, struct node * p) {
|
|
|
915
904
|
|
|
916
905
|
if (!g->unreachable) {
|
|
917
906
|
g->B[0] = str_data(varname);
|
|
918
|
-
w(g, "~
|
|
907
|
+
w(g, "~Mconst /** number */ ~B0 = ");
|
|
919
908
|
if (p->mode == m_forward) {
|
|
920
|
-
w(g, "
|
|
921
|
-
w(g, "~
|
|
909
|
+
w(g, "this.limit - this.c;~N");
|
|
910
|
+
w(g, "~Mthis.limit = this.c;~N");
|
|
922
911
|
} else {
|
|
923
|
-
w(g, "
|
|
924
|
-
w(g, "~
|
|
912
|
+
w(g, "this.limit_backward;~N");
|
|
913
|
+
w(g, "~Mthis.limit_backward = this.c;~N");
|
|
925
914
|
}
|
|
926
915
|
write_restorecursor(g, p, savevar);
|
|
927
916
|
|
|
928
917
|
if (p->mode == m_forward) {
|
|
929
|
-
str_assign(g->failure_str, "
|
|
918
|
+
str_assign(g->failure_str, "this.limit += ");
|
|
930
919
|
str_append(g->failure_str, varname);
|
|
931
920
|
str_append_ch(g->failure_str, ';');
|
|
932
921
|
} else {
|
|
933
|
-
str_assign(g->failure_str, "
|
|
922
|
+
str_assign(g->failure_str, "this.limit_backward = ");
|
|
934
923
|
str_append(g->failure_str, varname);
|
|
935
924
|
str_append_ch(g->failure_str, ';');
|
|
936
925
|
}
|
|
@@ -955,38 +944,74 @@ static void generate_setlimit(struct generator * g, struct node * p) {
|
|
|
955
944
|
static void generate_dollar(struct generator * g, struct node * p) {
|
|
956
945
|
write_comment(g, p);
|
|
957
946
|
|
|
947
|
+
int a0 = g->failure_label;
|
|
948
|
+
struct str * a1 = str_copy(g->failure_str);
|
|
949
|
+
int label = new_label(g);
|
|
950
|
+
g->failure_label = label;
|
|
951
|
+
str_clear(g->failure_str);
|
|
952
|
+
|
|
958
953
|
struct str * savevar = vars_newname(g);
|
|
959
954
|
g->B[0] = str_data(savevar);
|
|
960
955
|
writef(g, "~{~N"
|
|
961
|
-
"~
|
|
962
|
-
writef(g, "~M~B0.copy_from(
|
|
956
|
+
"~Mconst /** !Object */ ~B0 = new ~P();~N", p);
|
|
957
|
+
writef(g, "~M~B0.copy_from(this);~N", p);
|
|
958
|
+
|
|
959
|
+
writef(g, "~Mthis.current = ~V;~N"
|
|
960
|
+
"~Mthis.c = 0;~N"
|
|
961
|
+
"~Mthis.limit_backward = 0;~N"
|
|
962
|
+
"~Mthis.limit = this.current.length;~N", p);
|
|
963
|
+
if (p->left->possible_signals == -1) {
|
|
964
|
+
/* Assume failure. */
|
|
965
|
+
w(g, "~Mlet /**boolean*/ ~B0_f = true;~N");
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
wsetlab_begin(g, g->failure_label);
|
|
963
969
|
|
|
964
|
-
++g->copy_from_count;
|
|
965
|
-
str_assign(g->failure_str, "base.copy_from(");
|
|
966
|
-
str_append(g->failure_str, savevar);
|
|
967
|
-
str_append_string(g->failure_str, ");");
|
|
968
|
-
g->V[0] = p->name;
|
|
969
|
-
writef(g, "~Mbase.current = ~V0;~N"
|
|
970
|
-
"~Mbase.cursor = 0;~N"
|
|
971
|
-
"~Mbase.limit_backward = 0;~N"
|
|
972
|
-
"~Mbase.limit = base.current.length;~N", p);
|
|
973
970
|
generate(g, p->left);
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
971
|
+
|
|
972
|
+
if (p->left->possible_signals == -1) {
|
|
973
|
+
/* Mark success. */
|
|
974
|
+
g->B[0] = str_data(savevar);
|
|
975
|
+
w(g, "~M~B0_f = false;~N");
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
wsetlab_end(g);
|
|
979
|
+
|
|
980
|
+
g->failure_label = a0;
|
|
981
|
+
str_delete(g->failure_str);
|
|
982
|
+
g->failure_str = a1;
|
|
983
|
+
|
|
984
|
+
g->B[0] = str_data(savevar);
|
|
985
|
+
writef(g, "~M~V = this.current;~N"
|
|
986
|
+
"~Mthis.copy_from(~B0);~N", p);
|
|
987
|
+
++g->copy_from_count;
|
|
988
|
+
|
|
989
|
+
if (p->left->possible_signals == 0) {
|
|
990
|
+
// p->left always signals f.
|
|
991
|
+
write_failure(g);
|
|
992
|
+
} else if (p->left->possible_signals == -1) {
|
|
993
|
+
write_failure_if(g, "~B0_f", p);
|
|
980
994
|
}
|
|
981
995
|
w(g, "~}");
|
|
996
|
+
|
|
982
997
|
str_delete(savevar);
|
|
983
998
|
}
|
|
984
999
|
|
|
985
1000
|
static void generate_integer_assign(struct generator * g, struct node * p, const char * s) {
|
|
986
1001
|
write_comment(g, p);
|
|
987
|
-
|
|
1002
|
+
if (p->AE->type == c_number && p->AE->number == 1) {
|
|
1003
|
+
if (strcmp(s, "+=") == 0) {
|
|
1004
|
+
// Optimise `+= 1` to increment.
|
|
1005
|
+
writef(g, "~M++~V;~N", p);
|
|
1006
|
+
return;
|
|
1007
|
+
} else if (strcmp(s, "-=") == 0) {
|
|
1008
|
+
// Optimise `-= 1` to decrement.
|
|
1009
|
+
writef(g, "~M--~V;~N", p);
|
|
1010
|
+
return;
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
988
1013
|
g->S[0] = s;
|
|
989
|
-
|
|
1014
|
+
writef(g, "~M~V ~S0 ", p);
|
|
990
1015
|
generate_AE(g, p->AE);
|
|
991
1016
|
w(g, ";~N");
|
|
992
1017
|
}
|
|
@@ -994,7 +1019,7 @@ static void generate_integer_assign(struct generator * g, struct node * p, const
|
|
|
994
1019
|
static void generate_integer_test(struct generator * g, struct node * p) {
|
|
995
1020
|
write_comment(g, p);
|
|
996
1021
|
int relop = p->type;
|
|
997
|
-
int optimise_to_return = (g
|
|
1022
|
+
int optimise_to_return = tailcallable(g, p);
|
|
998
1023
|
if (optimise_to_return) {
|
|
999
1024
|
w(g, "~Mreturn ");
|
|
1000
1025
|
p->right = NULL;
|
|
@@ -1004,39 +1029,42 @@ static void generate_integer_test(struct generator * g, struct node * p) {
|
|
|
1004
1029
|
relop ^= 1;
|
|
1005
1030
|
}
|
|
1006
1031
|
generate_AE(g, p->left);
|
|
1007
|
-
|
|
1008
|
-
write_c_relop(g, relop);
|
|
1032
|
+
write_relop(g, relop);
|
|
1009
1033
|
generate_AE(g, p->AE);
|
|
1010
1034
|
if (optimise_to_return) {
|
|
1011
1035
|
w(g, ";~N");
|
|
1012
1036
|
} else {
|
|
1013
|
-
w(g, ")
|
|
1014
|
-
|
|
1015
|
-
write_failure(g);
|
|
1016
|
-
write_block_end(g);
|
|
1037
|
+
w(g, ") ");
|
|
1038
|
+
write_failure_after_if(g);
|
|
1017
1039
|
g->unreachable = false;
|
|
1018
1040
|
}
|
|
1019
1041
|
}
|
|
1020
1042
|
|
|
1021
1043
|
static void generate_call(struct generator * g, struct node * p) {
|
|
1022
|
-
int signals =
|
|
1044
|
+
int signals = p->name->definition->possible_signals;
|
|
1023
1045
|
write_comment(g, p);
|
|
1024
|
-
g
|
|
1025
|
-
|
|
1026
|
-
(
|
|
1027
|
-
|
|
1028
|
-
|
|
1046
|
+
if (tailcallable(g, p)) {
|
|
1047
|
+
/* Tail call. */
|
|
1048
|
+
writef(g, "~Mreturn ~V();~N", p);
|
|
1049
|
+
p->right = NULL;
|
|
1050
|
+
g->unreachable = true;
|
|
1051
|
+
return;
|
|
1052
|
+
}
|
|
1053
|
+
if (just_return_on_fail(g) && signals == 0) {
|
|
1054
|
+
/* Always fails. */
|
|
1055
|
+
writef(g, "~Mreturn ~V();~N", p);
|
|
1056
|
+
g->unreachable = true;
|
|
1029
1057
|
return;
|
|
1030
1058
|
}
|
|
1031
1059
|
if (signals == 1) {
|
|
1032
1060
|
/* Always succeeds. */
|
|
1033
|
-
writef(g, "~M~
|
|
1061
|
+
writef(g, "~M~V();~N", p);
|
|
1034
1062
|
} else if (signals == 0) {
|
|
1035
1063
|
/* Always fails. */
|
|
1036
|
-
writef(g, "~M~
|
|
1064
|
+
writef(g, "~M~V();~N", p);
|
|
1037
1065
|
write_failure(g);
|
|
1038
1066
|
} else {
|
|
1039
|
-
write_failure_if(g, "!~
|
|
1067
|
+
write_failure_if(g, "!~V()", p);
|
|
1040
1068
|
}
|
|
1041
1069
|
}
|
|
1042
1070
|
|
|
@@ -1046,41 +1074,44 @@ static void generate_grouping(struct generator * g, struct node * p, int complem
|
|
|
1046
1074
|
struct grouping * q = p->name->grouping;
|
|
1047
1075
|
g->S[0] = p->mode == m_forward ? "" : "_b";
|
|
1048
1076
|
g->S[1] = complement ? "out" : "in";
|
|
1049
|
-
g->V[0] = p->name;
|
|
1050
1077
|
g->I[0] = q->smallest_ch;
|
|
1051
1078
|
g->I[1] = q->largest_ch;
|
|
1052
|
-
|
|
1079
|
+
if (tailcallable(g, p)) {
|
|
1080
|
+
writef(g, "~Mreturn this.~S1_grouping~S0(~V, ~I0, ~I1);~N", p);
|
|
1081
|
+
p->right = NULL;
|
|
1082
|
+
} else {
|
|
1083
|
+
write_failure_if(g, "!(this.~S1_grouping~S0(~V, ~I0, ~I1))", p);
|
|
1084
|
+
}
|
|
1053
1085
|
}
|
|
1054
1086
|
|
|
1055
1087
|
static void generate_namedstring(struct generator * g, struct node * p) {
|
|
1056
1088
|
write_comment(g, p);
|
|
1057
1089
|
g->S[0] = p->mode == m_forward ? "" : "_b";
|
|
1058
|
-
g
|
|
1059
|
-
|
|
1090
|
+
if (tailcallable(g, p)) {
|
|
1091
|
+
writef(g, "~Mreturn this.eq_s~S0(~V);~N", p);
|
|
1092
|
+
p->right = NULL;
|
|
1093
|
+
} else {
|
|
1094
|
+
write_failure_if(g, "!(this.eq_s~S0(~V))", p);
|
|
1095
|
+
}
|
|
1060
1096
|
}
|
|
1061
1097
|
|
|
1062
1098
|
static void generate_literalstring(struct generator * g, struct node * p) {
|
|
1063
|
-
symbol * b = p->literalstring;
|
|
1064
1099
|
write_comment(g, p);
|
|
1065
1100
|
g->S[0] = p->mode == m_forward ? "" : "_b";
|
|
1066
|
-
g
|
|
1067
|
-
|
|
1101
|
+
if (tailcallable(g, p)) {
|
|
1102
|
+
writef(g, "~Mreturn this.eq_s~S0(~L);~N", p);
|
|
1103
|
+
p->right = NULL;
|
|
1104
|
+
} else {
|
|
1105
|
+
write_failure_if(g, "!(this.eq_s~S0(~L))", p);
|
|
1106
|
+
}
|
|
1068
1107
|
}
|
|
1069
1108
|
|
|
1070
1109
|
static void generate_define(struct generator * g, struct node * p) {
|
|
1071
|
-
struct name * q = p->name;
|
|
1072
|
-
if (q->type == t_routine && !q->used) return;
|
|
1073
|
-
|
|
1074
1110
|
write_newline(g);
|
|
1075
1111
|
write_comment(g, p);
|
|
1076
1112
|
|
|
1077
|
-
g
|
|
1078
|
-
|
|
1079
|
-
w(g, "~M/** @return {boolean} */~N"
|
|
1080
|
-
"~Mfunction ~W0() {~+~N");
|
|
1081
|
-
} else {
|
|
1082
|
-
w(g, "~Mthis.~W0 = /** @return {boolean} */ function() {~+~N");
|
|
1083
|
-
}
|
|
1113
|
+
writef(g, "~M/** @return {boolean} */~N"
|
|
1114
|
+
"~M#~W() {~+~N", p);
|
|
1084
1115
|
|
|
1085
1116
|
/* Save output. */
|
|
1086
1117
|
struct str * saved_output = g->outbuf;
|
|
@@ -1091,24 +1122,67 @@ static void generate_define(struct generator * g, struct node * p) {
|
|
|
1091
1122
|
g->next_label = 0;
|
|
1092
1123
|
g->var_number = 0;
|
|
1093
1124
|
|
|
1094
|
-
|
|
1095
|
-
|
|
1125
|
+
struct name * q = p->name;
|
|
1126
|
+
|
|
1127
|
+
if (q->amongvar_needed) {
|
|
1128
|
+
// The "among var" (`a`) is only assigned to, but the initialisation
|
|
1129
|
+
// can be generated in a nested block so it seems hard to declare it as
|
|
1130
|
+
// const and still have it visible when we want to use it.
|
|
1131
|
+
w(g, "~Mlet /** number */ a;~N");
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
/* Declare localised variables. */
|
|
1135
|
+
for (struct name * name = g->analyser->names; name; name = name->next) {
|
|
1136
|
+
if (name->local_to == q) {
|
|
1137
|
+
switch (name->type) {
|
|
1138
|
+
case t_string:
|
|
1139
|
+
w(g, "~Mlet /** string */ ");
|
|
1140
|
+
write_varname(g, name);
|
|
1141
|
+
w(g, ";~N");
|
|
1142
|
+
break;
|
|
1143
|
+
case t_integer:
|
|
1144
|
+
w(g, "~Mlet /** number */ ");
|
|
1145
|
+
write_varname(g, name);
|
|
1146
|
+
w(g, ";~N");
|
|
1147
|
+
break;
|
|
1148
|
+
case t_boolean:
|
|
1149
|
+
w(g, "~Mlet /** boolean */ ");
|
|
1150
|
+
write_varname(g, name);
|
|
1151
|
+
w(g, ";~N");
|
|
1152
|
+
break;
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1096
1155
|
}
|
|
1156
|
+
|
|
1097
1157
|
str_clear(g->failure_str);
|
|
1098
1158
|
g->failure_label = x_return;
|
|
1099
1159
|
g->unreachable = false;
|
|
1100
1160
|
g->keep_count = 0;
|
|
1101
|
-
int signals = check_possible_signals_list(g, p->left, c_define, 0);
|
|
1102
1161
|
|
|
1103
1162
|
/* Generate function body. */
|
|
1104
1163
|
generate(g, p->left);
|
|
1105
1164
|
if (p->left->right) {
|
|
1106
1165
|
assert(p->left->right->type == c_functionend);
|
|
1107
|
-
if (
|
|
1166
|
+
if (p->left->possible_signals) {
|
|
1108
1167
|
generate(g, p->left->right);
|
|
1109
1168
|
}
|
|
1110
1169
|
}
|
|
1111
|
-
w(g, "~-~M}
|
|
1170
|
+
w(g, "~-~M}~N");
|
|
1171
|
+
|
|
1172
|
+
if (q->type == t_external) {
|
|
1173
|
+
w(g, "~N");
|
|
1174
|
+
w(g, "~M/**@return{string}*/~N");
|
|
1175
|
+
writef(g, "~M~W(/**string*/input) {~+~N", p);
|
|
1176
|
+
w(g, "~Mthis.setCurrent(input);~N");
|
|
1177
|
+
writef(g, "~Mthis.#~W();~N", p);
|
|
1178
|
+
w(g, "~Mreturn this.getCurrent();~N");
|
|
1179
|
+
w(g, "~-~M}~N");
|
|
1180
|
+
|
|
1181
|
+
if (SIZE(q->s) == 4 && memcmp(q->s, "stem", 4) == 0) {
|
|
1182
|
+
w(g, "~N");
|
|
1183
|
+
w(g, "~MstemWord = this.stem;~N");
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1112
1186
|
|
|
1113
1187
|
str_append(saved_output, g->declarations);
|
|
1114
1188
|
str_append(saved_output, g->outbuf);
|
|
@@ -1132,14 +1206,18 @@ static void generate_substring(struct generator * g, struct node * p) {
|
|
|
1132
1206
|
g->I[0] = x->number;
|
|
1133
1207
|
|
|
1134
1208
|
if (x->amongvar_needed) {
|
|
1135
|
-
writef(g, "~
|
|
1209
|
+
writef(g, "~Ma = this.find_among~S0(a_~I0~F);~N", p);
|
|
1136
1210
|
if (!x->always_matches) {
|
|
1137
|
-
write_failure_if(g, "
|
|
1211
|
+
write_failure_if(g, "a === 0", p);
|
|
1138
1212
|
}
|
|
1139
1213
|
} else if (x->always_matches) {
|
|
1140
|
-
writef(g, "~
|
|
1214
|
+
writef(g, "~Mthis.find_among~S0(a_~I0~F);~N", p);
|
|
1215
|
+
} else if (x->command_count == 0 && tailcallable(g, p)) {
|
|
1216
|
+
writef(g, "~Mreturn this.find_among~S0(a_~I0~F) !== 0;~N", p);
|
|
1217
|
+
x->node->right = NULL;
|
|
1218
|
+
g->unreachable = true;
|
|
1141
1219
|
} else {
|
|
1142
|
-
write_failure_if(g, "
|
|
1220
|
+
write_failure_if(g, "this.find_among~S0(a_~I0~F) === 0", p);
|
|
1143
1221
|
}
|
|
1144
1222
|
}
|
|
1145
1223
|
|
|
@@ -1156,23 +1234,51 @@ static void generate_among(struct generator * g, struct node * p) {
|
|
|
1156
1234
|
/* Only one outcome ("no match" already handled). */
|
|
1157
1235
|
generate(g, x->commands[0]);
|
|
1158
1236
|
} else if (x->command_count > 0) {
|
|
1159
|
-
|
|
1237
|
+
if (x->same_action == c_slicefrom && x->command_count > 1) {
|
|
1238
|
+
if (x->nocommand_count > 0) {
|
|
1239
|
+
w(g, "~Mif (a > 0) {~N~+");
|
|
1240
|
+
}
|
|
1241
|
+
write_comment(g, x->commands[0]);
|
|
1242
|
+
g->I[0] = x->number;
|
|
1243
|
+
w(g, "~Mthis.slice_from(as_~I0[a - 1]);~N");
|
|
1244
|
+
if (x->nocommand_count > 0) {
|
|
1245
|
+
write_block_end(g);
|
|
1246
|
+
}
|
|
1247
|
+
g->unreachable = false;
|
|
1248
|
+
return;
|
|
1249
|
+
}
|
|
1250
|
+
|
|
1251
|
+
w(g, "~Mswitch (a) {~N~+");
|
|
1160
1252
|
for (int i = 1; i <= x->command_count; i++) {
|
|
1161
1253
|
g->I[0] = i;
|
|
1162
|
-
w(g, "~Mcase ~I0
|
|
1254
|
+
w(g, "~Mcase ~I0: {~N~+");
|
|
1163
1255
|
generate(g, x->commands[i - 1]);
|
|
1164
1256
|
if (!g->unreachable) w(g, "~Mbreak;~N");
|
|
1165
|
-
w(g, "
|
|
1257
|
+
w(g, "~-~M}~N");
|
|
1166
1258
|
g->unreachable = false;
|
|
1167
1259
|
}
|
|
1168
1260
|
write_block_end(g);
|
|
1169
1261
|
}
|
|
1170
1262
|
}
|
|
1171
1263
|
|
|
1172
|
-
static void generate_booltest(struct generator * g, struct node * p) {
|
|
1264
|
+
static void generate_booltest(struct generator * g, struct node * p, int inverted) {
|
|
1173
1265
|
write_comment(g, p);
|
|
1174
|
-
g
|
|
1175
|
-
|
|
1266
|
+
if (tailcallable(g, p)) {
|
|
1267
|
+
// Optimise at end of function.
|
|
1268
|
+
if (inverted) {
|
|
1269
|
+
writef(g, "~Mreturn !~V;~N", p);
|
|
1270
|
+
} else {
|
|
1271
|
+
writef(g, "~Mreturn ~V;~N", p);
|
|
1272
|
+
}
|
|
1273
|
+
p->right = NULL;
|
|
1274
|
+
g->unreachable = true;
|
|
1275
|
+
return;
|
|
1276
|
+
}
|
|
1277
|
+
if (inverted) {
|
|
1278
|
+
write_failure_if(g, "~V", p);
|
|
1279
|
+
} else {
|
|
1280
|
+
write_failure_if(g, "!~V", p);
|
|
1281
|
+
}
|
|
1176
1282
|
}
|
|
1177
1283
|
|
|
1178
1284
|
static void generate_false(struct generator * g, struct node * p) {
|
|
@@ -1184,7 +1290,7 @@ static void generate_debug(struct generator * g, struct node * p) {
|
|
|
1184
1290
|
write_comment(g, p);
|
|
1185
1291
|
g->I[0] = g->debug_count++;
|
|
1186
1292
|
g->I[1] = p->line_number;
|
|
1187
|
-
writef(g, "~
|
|
1293
|
+
writef(g, "~Mthis.debug(~I0, ~I1);~N", p);
|
|
1188
1294
|
}
|
|
1189
1295
|
|
|
1190
1296
|
static void generate(struct generator * g, struct node * p) {
|
|
@@ -1217,25 +1323,21 @@ static void generate(struct generator * g, struct node * p) {
|
|
|
1217
1323
|
case c_repeat: generate_repeat(g, p); break;
|
|
1218
1324
|
case c_loop: generate_loop(g, p); break;
|
|
1219
1325
|
case c_atleast: generate_atleast(g, p); break;
|
|
1220
|
-
case c_setmark: generate_setmark(g, p); break;
|
|
1221
1326
|
case c_tomark: generate_tomark(g, p); break;
|
|
1222
|
-
case c_atmark: generate_atmark(g, p); break;
|
|
1223
1327
|
case c_hop: generate_hop(g, p); break;
|
|
1224
|
-
case c_delete: generate_delete(g, p); break;
|
|
1225
1328
|
case c_next: generate_next(g, p); break;
|
|
1226
1329
|
case c_tolimit: generate_tolimit(g, p); break;
|
|
1227
|
-
case c_atlimit: generate_atlimit(g, p); break;
|
|
1228
1330
|
case c_leftslice: generate_leftslice(g, p); break;
|
|
1229
1331
|
case c_rightslice: generate_rightslice(g, p); break;
|
|
1230
1332
|
case c_assignto: generate_assignto(g, p); break;
|
|
1231
1333
|
case c_sliceto: generate_sliceto(g, p); break;
|
|
1232
|
-
case
|
|
1334
|
+
case c_stringassign: generate_stringassign(g, p); break;
|
|
1233
1335
|
case c_insert:
|
|
1234
1336
|
case c_attach: generate_insert(g, p, p->type); break;
|
|
1235
1337
|
case c_slicefrom: generate_slicefrom(g, p); break;
|
|
1236
1338
|
case c_setlimit: generate_setlimit(g, p); break;
|
|
1237
1339
|
case c_dollar: generate_dollar(g, p); break;
|
|
1238
|
-
case
|
|
1340
|
+
case c_assign: generate_integer_assign(g, p, "="); break;
|
|
1239
1341
|
case c_plusassign: generate_integer_assign(g, p, "+="); break;
|
|
1240
1342
|
case c_minusassign: generate_integer_assign(g, p, "-="); break;
|
|
1241
1343
|
case c_multiplyassign:generate_integer_assign(g, p, "*="); break;
|
|
@@ -1243,8 +1345,7 @@ static void generate(struct generator * g, struct node * p) {
|
|
|
1243
1345
|
/* Snowball specifies integer division with semantics matching C,
|
|
1244
1346
|
* so we need to use `Math.trunc(x/y)` here.
|
|
1245
1347
|
*/
|
|
1246
|
-
g
|
|
1247
|
-
w(g, "~M~V0 = Math.trunc(~V0 / ");
|
|
1348
|
+
writef(g, "~M~V = Math.trunc(~V / ", p);
|
|
1248
1349
|
generate_AE(g, p->AE);
|
|
1249
1350
|
w(g, ");~N");
|
|
1250
1351
|
break;
|
|
@@ -1263,7 +1364,8 @@ static void generate(struct generator * g, struct node * p) {
|
|
|
1263
1364
|
case c_literalstring: generate_literalstring(g, p); break;
|
|
1264
1365
|
case c_among: generate_among(g, p); break;
|
|
1265
1366
|
case c_substring: generate_substring(g, p); break;
|
|
1266
|
-
case c_booltest: generate_booltest(g, p); break;
|
|
1367
|
+
case c_booltest: generate_booltest(g, p, false); break;
|
|
1368
|
+
case c_not_booltest: generate_booltest(g, p, true); break;
|
|
1267
1369
|
case c_false: generate_false(g, p); break;
|
|
1268
1370
|
case c_true: break;
|
|
1269
1371
|
case c_debug: generate_debug(g, p); break;
|
|
@@ -1278,40 +1380,15 @@ static void generate(struct generator * g, struct node * p) {
|
|
|
1278
1380
|
}
|
|
1279
1381
|
|
|
1280
1382
|
static void generate_class_begin(struct generator * g) {
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
"~N"
|
|
1285
|
-
"/** @typedef {{ stemWord(word: string): string }} Stemmer */~N"
|
|
1286
|
-
"~N"
|
|
1287
|
-
"/** @type {{ new(): Stemmer }} */~N"
|
|
1288
|
-
"~C ~n = function() {~+~N"
|
|
1289
|
-
"~M~D base = new ~P();~N");
|
|
1290
|
-
} else {
|
|
1291
|
-
w(g, "/**@constructor*/~N"
|
|
1292
|
-
"~D ~n = function() {~+~N"
|
|
1293
|
-
"~M~C ~P = require('./base-stemmer.js');~N"
|
|
1294
|
-
"~M~D base = new ~P();~N");
|
|
1295
|
-
}
|
|
1383
|
+
w(g, "import ~P from './base-stemmer.js'~N"
|
|
1384
|
+
"~N"
|
|
1385
|
+
"export default class extends ~P {~+~N");
|
|
1296
1386
|
write_newline(g);
|
|
1297
1387
|
}
|
|
1298
1388
|
|
|
1299
1389
|
static void generate_class_end(struct generator * g) {
|
|
1390
|
+
w(g, "~-}~N");
|
|
1300
1391
|
w(g, "~N");
|
|
1301
|
-
w(g, "~M/**@return{string}*/~N");
|
|
1302
|
-
w(g, "~Mthis['stemWord'] = function(/**string*/word) {~+~N");
|
|
1303
|
-
w(g, "~Mbase.setCurrent(word);~N");
|
|
1304
|
-
w(g, "~Mthis.stem();~N");
|
|
1305
|
-
w(g, "~Mreturn base.getCurrent();~N");
|
|
1306
|
-
w(g, "~-~M};~N");
|
|
1307
|
-
w(g, "~-};~N");
|
|
1308
|
-
if (g->options->js_esm) {
|
|
1309
|
-
w(g, "~N"
|
|
1310
|
-
"export default ~n~N");
|
|
1311
|
-
} else {
|
|
1312
|
-
w(g, "~N"
|
|
1313
|
-
"if (typeof module === 'object' && module.exports) module.exports = ~n;~N");
|
|
1314
|
-
}
|
|
1315
1392
|
}
|
|
1316
1393
|
|
|
1317
1394
|
static void generate_among_table(struct generator * g, struct among * x) {
|
|
@@ -1320,22 +1397,36 @@ static void generate_among_table(struct generator * g, struct among * x) {
|
|
|
1320
1397
|
struct amongvec * v = x->b;
|
|
1321
1398
|
|
|
1322
1399
|
g->I[0] = x->number;
|
|
1323
|
-
w(g, "~
|
|
1400
|
+
w(g, "~Mconst a_~I0 = [~N~+");
|
|
1324
1401
|
|
|
1325
1402
|
for (int i = 0; i < x->literalstring_count; i++) {
|
|
1326
|
-
g
|
|
1327
|
-
g->I[
|
|
1328
|
-
g->L[0] = v[i].b;
|
|
1329
|
-
g->S[0] = i < x->literalstring_count - 1 ? "," : "";
|
|
1403
|
+
if (i) w(g, ",~N");
|
|
1404
|
+
g->I[0] = v[i].result;
|
|
1330
1405
|
|
|
1331
|
-
w(g, "~M[
|
|
1406
|
+
w(g, "~M[");
|
|
1407
|
+
write_literal_string(g, v[i].b);
|
|
1408
|
+
w(g, ", ~I0");
|
|
1409
|
+
if (v[i].i >= 0 || v[i].function != NULL) {
|
|
1410
|
+
w(g, ", ");
|
|
1411
|
+
write_int(g, v[i].i >= 0 ? i - v[i].i : 0);
|
|
1412
|
+
}
|
|
1332
1413
|
if (v[i].function != NULL) {
|
|
1333
1414
|
w(g, ", ");
|
|
1334
|
-
|
|
1415
|
+
write_int(g, v[i].function_index);
|
|
1416
|
+
}
|
|
1417
|
+
w(g, "]");
|
|
1418
|
+
}
|
|
1419
|
+
w(g, "~N~-~M];~N~N");
|
|
1420
|
+
|
|
1421
|
+
if (x->same_action == c_slicefrom && x->command_count > 1) {
|
|
1422
|
+
g->I[0] = x->number;
|
|
1423
|
+
w(g, "~Mconst /** Array<string> */ as_~I0 = [");
|
|
1424
|
+
for (int i = 1; i <= x->command_count; i++) {
|
|
1425
|
+
if (i > 1) w(g, ", ");
|
|
1426
|
+
write_literal_string(g, x->commands[i - 1]->left->literalstring);
|
|
1335
1427
|
}
|
|
1336
|
-
w(g, "]~
|
|
1428
|
+
w(g, "];~N~N");
|
|
1337
1429
|
}
|
|
1338
|
-
w(g, "~-~M];~N~N");
|
|
1339
1430
|
}
|
|
1340
1431
|
|
|
1341
1432
|
static void generate_amongs(struct generator * g) {
|
|
@@ -1344,11 +1435,45 @@ static void generate_amongs(struct generator * g) {
|
|
|
1344
1435
|
}
|
|
1345
1436
|
}
|
|
1346
1437
|
|
|
1347
|
-
static void
|
|
1438
|
+
static void generate_among_dispatcher(struct generator * g, struct among * x) {
|
|
1439
|
+
if (x->function_count <= 1) return;
|
|
1440
|
+
|
|
1441
|
+
struct amongvec * v = x->b;
|
|
1442
|
+
|
|
1443
|
+
write_comment(g, x->node);
|
|
1444
|
+
|
|
1445
|
+
g->I[0] = x->number;
|
|
1446
|
+
w(g, "~N~M/** @return {boolean} */~N");
|
|
1447
|
+
w(g, "~M#af_~I0() {~N~+");
|
|
1448
|
+
w(g, "~Mswitch (this.af) {~N~+");
|
|
1449
|
+
for (int n = 1; n <= x->function_count; n++) {
|
|
1450
|
+
w(g, "~Mcase ");
|
|
1451
|
+
write_int(g, n);
|
|
1452
|
+
w(g, ": return ");
|
|
1453
|
+
for (int i = 0; i < x->literalstring_count; i++) {
|
|
1454
|
+
if (v[i].function_index == n) {
|
|
1455
|
+
write_varref(g, v[i].function);
|
|
1456
|
+
w(g, "();~N");
|
|
1457
|
+
break;
|
|
1458
|
+
}
|
|
1459
|
+
}
|
|
1460
|
+
}
|
|
1461
|
+
w(g, "~-~M}~N");
|
|
1462
|
+
w(g, "~Mreturn false;~N");
|
|
1463
|
+
w(g, "~-~M}~N");
|
|
1464
|
+
}
|
|
1465
|
+
|
|
1466
|
+
static void generate_among_dispatchers(struct generator * g) {
|
|
1467
|
+
for (struct among * x = g->analyser->amongs; x; x = x->next) {
|
|
1468
|
+
generate_among_dispatcher(g, x);
|
|
1469
|
+
}
|
|
1470
|
+
}
|
|
1471
|
+
|
|
1472
|
+
static void set_bit(symbol * b, int i) { b[i >> 3] |= 1 << (i & 7); }
|
|
1348
1473
|
|
|
1349
1474
|
static void generate_grouping_table(struct generator * g, struct grouping * q) {
|
|
1350
1475
|
int range = q->largest_ch - q->smallest_ch + 1;
|
|
1351
|
-
int size = (range + 7)/ 8; /* assume 8 bits per symbol */
|
|
1476
|
+
int size = (range + 7) / 8; /* assume 8 bits per symbol */
|
|
1352
1477
|
symbol * b = q->b;
|
|
1353
1478
|
symbol * map = create_b(size);
|
|
1354
1479
|
|
|
@@ -1356,11 +1481,12 @@ static void generate_grouping_table(struct generator * g, struct grouping * q) {
|
|
|
1356
1481
|
|
|
1357
1482
|
for (int i = 0; i < SIZE(b); i++) set_bit(map, b[i] - q->smallest_ch);
|
|
1358
1483
|
|
|
1359
|
-
g
|
|
1360
|
-
|
|
1484
|
+
w(g, "~Mconst /** Array<number> */ ");
|
|
1485
|
+
write_varname(g, q->name);
|
|
1486
|
+
write_string(g, " = [");
|
|
1361
1487
|
for (int i = 0; i < size; i++) {
|
|
1488
|
+
if (i) w(g, ", ");
|
|
1362
1489
|
write_int(g, map[i]);
|
|
1363
|
-
if (i < size - 1) w(g, ", ");
|
|
1364
1490
|
}
|
|
1365
1491
|
w(g, "];~N~N");
|
|
1366
1492
|
|
|
@@ -1369,27 +1495,32 @@ static void generate_grouping_table(struct generator * g, struct grouping * q) {
|
|
|
1369
1495
|
|
|
1370
1496
|
static void generate_groupings(struct generator * g) {
|
|
1371
1497
|
for (struct grouping * q = g->analyser->groupings; q; q = q->next) {
|
|
1372
|
-
|
|
1373
|
-
generate_grouping_table(g, q);
|
|
1498
|
+
generate_grouping_table(g, q);
|
|
1374
1499
|
}
|
|
1375
1500
|
}
|
|
1376
1501
|
|
|
1377
1502
|
static void generate_members(struct generator * g) {
|
|
1378
|
-
|
|
1503
|
+
bool wrote_members = false;
|
|
1379
1504
|
|
|
1380
1505
|
for (struct name * q = g->analyser->names; q; q = q->next) {
|
|
1381
|
-
|
|
1506
|
+
if (q->local_to) continue;
|
|
1382
1507
|
switch (q->type) {
|
|
1383
1508
|
case t_string:
|
|
1384
|
-
w(g, "~M
|
|
1509
|
+
w(g, "~M#");
|
|
1510
|
+
write_varname(g, q);
|
|
1511
|
+
w(g, "/** string */ = '';~N");
|
|
1385
1512
|
wrote_members = true;
|
|
1386
1513
|
break;
|
|
1387
1514
|
case t_integer:
|
|
1388
|
-
w(g, "~M
|
|
1515
|
+
w(g, "~M#");
|
|
1516
|
+
write_varname(g, q);
|
|
1517
|
+
w(g, "/** number */ = 0;~N");
|
|
1389
1518
|
wrote_members = true;
|
|
1390
1519
|
break;
|
|
1391
1520
|
case t_boolean:
|
|
1392
|
-
w(g, "~M
|
|
1521
|
+
w(g, "~M#");
|
|
1522
|
+
write_varname(g, q);
|
|
1523
|
+
w(g, "/** boolean */ = false;~N");
|
|
1393
1524
|
wrote_members = true;
|
|
1394
1525
|
break;
|
|
1395
1526
|
}
|
|
@@ -1410,12 +1541,30 @@ extern void generate_program_js(struct generator * g) {
|
|
|
1410
1541
|
|
|
1411
1542
|
write_start_comment(g, "// ", NULL);
|
|
1412
1543
|
|
|
1413
|
-
|
|
1544
|
+
// Disable some deno-lint warnings which the generated code can trigger.
|
|
1545
|
+
w(g, "// deno-lint-ignore-file"
|
|
1546
|
+
// Some of our generated deno-lint-ignore comments may not be used.
|
|
1547
|
+
" ban-unused-ignore"
|
|
1548
|
+
// Expressions in conditionals may be constant.
|
|
1549
|
+
" no-constant-condition"
|
|
1550
|
+
// Empty blocks may be generated in some cases.
|
|
1551
|
+
" no-empty"
|
|
1552
|
+
// Among var `a` is only assigned to once per `among`, but is declared
|
|
1553
|
+
// at the start of the function and may be initialised in a nested
|
|
1554
|
+
// block.
|
|
1555
|
+
//
|
|
1556
|
+
// Some localised variables may only be assigned to once.
|
|
1557
|
+
" prefer-const~N~N");
|
|
1414
1558
|
|
|
1415
1559
|
generate_amongs(g);
|
|
1416
1560
|
generate_groupings(g);
|
|
1417
1561
|
|
|
1562
|
+
generate_class_begin(g);
|
|
1563
|
+
|
|
1418
1564
|
generate_members(g);
|
|
1565
|
+
|
|
1566
|
+
generate_among_dispatchers(g);
|
|
1567
|
+
|
|
1419
1568
|
generate_methods(g);
|
|
1420
1569
|
|
|
1421
1570
|
generate_class_end(g);
|