mittens 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +7 -0
- data/LICENSE.txt +30 -0
- data/README.md +62 -0
- data/Rakefile +21 -0
- data/ext/mittens/ext.c +96 -0
- data/ext/mittens/extconf.rb +12 -0
- data/lib/mittens/version.rb +3 -0
- data/lib/mittens.rb +7 -0
- data/mittens.gemspec +22 -0
- data/vendor/snowball/.gitignore +26 -0
- data/vendor/snowball/.travis.yml +112 -0
- data/vendor/snowball/AUTHORS +27 -0
- data/vendor/snowball/CONTRIBUTING.rst +216 -0
- data/vendor/snowball/COPYING +29 -0
- data/vendor/snowball/GNUmakefile +742 -0
- data/vendor/snowball/NEWS +754 -0
- data/vendor/snowball/README.rst +37 -0
- data/vendor/snowball/ada/README.md +74 -0
- data/vendor/snowball/ada/generate/generate.adb +83 -0
- data/vendor/snowball/ada/generate.gpr +21 -0
- data/vendor/snowball/ada/src/stemmer.adb +620 -0
- data/vendor/snowball/ada/src/stemmer.ads +219 -0
- data/vendor/snowball/ada/src/stemwords.adb +70 -0
- data/vendor/snowball/ada/stemmer_config.gpr +83 -0
- data/vendor/snowball/ada/stemwords.gpr +21 -0
- data/vendor/snowball/algorithms/arabic.sbl +558 -0
- data/vendor/snowball/algorithms/armenian.sbl +301 -0
- data/vendor/snowball/algorithms/basque.sbl +149 -0
- data/vendor/snowball/algorithms/catalan.sbl +202 -0
- data/vendor/snowball/algorithms/danish.sbl +93 -0
- data/vendor/snowball/algorithms/dutch.sbl +164 -0
- data/vendor/snowball/algorithms/english.sbl +229 -0
- data/vendor/snowball/algorithms/finnish.sbl +197 -0
- data/vendor/snowball/algorithms/french.sbl +254 -0
- data/vendor/snowball/algorithms/german.sbl +139 -0
- data/vendor/snowball/algorithms/german2.sbl +145 -0
- data/vendor/snowball/algorithms/greek.sbl +701 -0
- data/vendor/snowball/algorithms/hindi.sbl +323 -0
- data/vendor/snowball/algorithms/hungarian.sbl +241 -0
- data/vendor/snowball/algorithms/indonesian.sbl +192 -0
- data/vendor/snowball/algorithms/irish.sbl +149 -0
- data/vendor/snowball/algorithms/italian.sbl +202 -0
- data/vendor/snowball/algorithms/kraaij_pohlmann.sbl +240 -0
- data/vendor/snowball/algorithms/lithuanian.sbl +373 -0
- data/vendor/snowball/algorithms/lovins.sbl +208 -0
- data/vendor/snowball/algorithms/nepali.sbl +92 -0
- data/vendor/snowball/algorithms/norwegian.sbl +80 -0
- data/vendor/snowball/algorithms/porter.sbl +139 -0
- data/vendor/snowball/algorithms/portuguese.sbl +218 -0
- data/vendor/snowball/algorithms/romanian.sbl +236 -0
- data/vendor/snowball/algorithms/russian.sbl +221 -0
- data/vendor/snowball/algorithms/serbian.sbl +2379 -0
- data/vendor/snowball/algorithms/spanish.sbl +230 -0
- data/vendor/snowball/algorithms/swedish.sbl +72 -0
- data/vendor/snowball/algorithms/tamil.sbl +405 -0
- data/vendor/snowball/algorithms/turkish.sbl +470 -0
- data/vendor/snowball/algorithms/yiddish.sbl +460 -0
- data/vendor/snowball/charsets/ISO-8859-2.sbl +98 -0
- data/vendor/snowball/charsets/KOI8-R.sbl +74 -0
- data/vendor/snowball/charsets/cp850.sbl +130 -0
- data/vendor/snowball/compiler/analyser.c +1547 -0
- data/vendor/snowball/compiler/driver.c +615 -0
- data/vendor/snowball/compiler/generator.c +1748 -0
- data/vendor/snowball/compiler/generator_ada.c +1702 -0
- data/vendor/snowball/compiler/generator_csharp.c +1322 -0
- data/vendor/snowball/compiler/generator_go.c +1278 -0
- data/vendor/snowball/compiler/generator_java.c +1313 -0
- data/vendor/snowball/compiler/generator_js.c +1316 -0
- data/vendor/snowball/compiler/generator_pascal.c +1387 -0
- data/vendor/snowball/compiler/generator_python.c +1337 -0
- data/vendor/snowball/compiler/generator_rust.c +1295 -0
- data/vendor/snowball/compiler/header.h +418 -0
- data/vendor/snowball/compiler/space.c +286 -0
- data/vendor/snowball/compiler/syswords.h +86 -0
- data/vendor/snowball/compiler/syswords2.h +13 -0
- data/vendor/snowball/compiler/tokeniser.c +567 -0
- data/vendor/snowball/csharp/.gitignore +8 -0
- data/vendor/snowball/csharp/Snowball/Algorithms/.gitignore +1 -0
- data/vendor/snowball/csharp/Snowball/Among.cs +108 -0
- data/vendor/snowball/csharp/Snowball/AssemblyInfo.cs +36 -0
- data/vendor/snowball/csharp/Snowball/Stemmer.cs +660 -0
- data/vendor/snowball/csharp/Stemwords/App.config +6 -0
- data/vendor/snowball/csharp/Stemwords/Program.cs +114 -0
- data/vendor/snowball/doc/TODO +12 -0
- data/vendor/snowball/doc/libstemmer_c_README +148 -0
- data/vendor/snowball/doc/libstemmer_csharp_README +53 -0
- data/vendor/snowball/doc/libstemmer_java_README +67 -0
- data/vendor/snowball/doc/libstemmer_js_README +48 -0
- data/vendor/snowball/doc/libstemmer_python_README +113 -0
- data/vendor/snowball/examples/stemwords.c +204 -0
- data/vendor/snowball/go/README.md +55 -0
- data/vendor/snowball/go/among.go +16 -0
- data/vendor/snowball/go/env.go +403 -0
- data/vendor/snowball/go/stemwords/generate.go +68 -0
- data/vendor/snowball/go/stemwords/main.go +68 -0
- data/vendor/snowball/go/util.go +34 -0
- data/vendor/snowball/iconv.py +50 -0
- data/vendor/snowball/include/libstemmer.h +78 -0
- data/vendor/snowball/java/org/tartarus/snowball/Among.java +29 -0
- data/vendor/snowball/java/org/tartarus/snowball/SnowballProgram.java +381 -0
- data/vendor/snowball/java/org/tartarus/snowball/SnowballStemmer.java +8 -0
- data/vendor/snowball/java/org/tartarus/snowball/TestApp.java +75 -0
- data/vendor/snowball/javascript/base-stemmer.js +294 -0
- data/vendor/snowball/javascript/stemwords.js +106 -0
- data/vendor/snowball/libstemmer/libstemmer_c.in +96 -0
- data/vendor/snowball/libstemmer/mkalgorithms.pl +90 -0
- data/vendor/snowball/libstemmer/mkmodules.pl +267 -0
- data/vendor/snowball/libstemmer/modules.txt +63 -0
- data/vendor/snowball/libstemmer/test.c +34 -0
- data/vendor/snowball/pascal/.gitignore +4 -0
- data/vendor/snowball/pascal/SnowballProgram.pas +430 -0
- data/vendor/snowball/pascal/generate.pl +23 -0
- data/vendor/snowball/pascal/stemwords-template.dpr +78 -0
- data/vendor/snowball/python/MANIFEST.in +7 -0
- data/vendor/snowball/python/create_init.py +54 -0
- data/vendor/snowball/python/setup.cfg +6 -0
- data/vendor/snowball/python/setup.py +81 -0
- data/vendor/snowball/python/snowballstemmer/among.py +13 -0
- data/vendor/snowball/python/snowballstemmer/basestemmer.py +323 -0
- data/vendor/snowball/python/stemwords.py +101 -0
- data/vendor/snowball/python/testapp.py +28 -0
- data/vendor/snowball/runtime/api.c +58 -0
- data/vendor/snowball/runtime/api.h +32 -0
- data/vendor/snowball/runtime/header.h +61 -0
- data/vendor/snowball/runtime/utilities.c +513 -0
- data/vendor/snowball/rust/Cargo.toml +7 -0
- data/vendor/snowball/rust/build.rs +55 -0
- data/vendor/snowball/rust/rust-pre-1.27-compat.patch +30 -0
- data/vendor/snowball/rust/src/main.rs +102 -0
- data/vendor/snowball/rust/src/snowball/algorithms/mod.rs +2 -0
- data/vendor/snowball/rust/src/snowball/among.rs +6 -0
- data/vendor/snowball/rust/src/snowball/mod.rs +6 -0
- data/vendor/snowball/rust/src/snowball/snowball_env.rs +421 -0
- data/vendor/snowball/tests/stemtest.c +95 -0
- metadata +178 -0
|
@@ -0,0 +1,1702 @@
|
|
|
1
|
+
#include <stdlib.h> /* for exit */
|
|
2
|
+
#include <string.h> /* for strlen */
|
|
3
|
+
#include <stdio.h> /* for fprintf etc */
|
|
4
|
+
#include <ctype.h>
|
|
5
|
+
#include <limits.h>
|
|
6
|
+
#include "header.h"
|
|
7
|
+
|
|
8
|
+
/* prototypes */
|
|
9
|
+
|
|
10
|
+
static void generate(struct generator * g, struct node * p);
|
|
11
|
+
static void generate_next(struct generator * g, struct node * p);
|
|
12
|
+
static void w(struct generator * g, const char * s);
|
|
13
|
+
static void writef(struct generator * g, const char * s, struct node * p);
|
|
14
|
+
|
|
15
|
+
static int new_label(struct generator * g) {
|
|
16
|
+
return g->next_label++;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
static struct str * vars_newname(struct generator * g) {
|
|
20
|
+
|
|
21
|
+
struct str * output;
|
|
22
|
+
g->var_number++;
|
|
23
|
+
output = str_new();
|
|
24
|
+
str_append_string(output, "v_");
|
|
25
|
+
str_append_int(output, g->var_number);
|
|
26
|
+
return output;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/* Write routines for items from the syntax tree */
|
|
30
|
+
|
|
31
|
+
static void write_varname(struct generator * g, struct name * p) {
|
|
32
|
+
|
|
33
|
+
int ch = p->b[0];
|
|
34
|
+
if (p->type != t_external) {
|
|
35
|
+
write_char(g, "SBIRXG"[p->type]);
|
|
36
|
+
write_char(g, '_');
|
|
37
|
+
}
|
|
38
|
+
write_char(g, toupper(ch));
|
|
39
|
+
str_append_b_tail(g->outbuf, p->b, 1);
|
|
40
|
+
|
|
41
|
+
ch = p->b[SIZE(p->b) - 1];
|
|
42
|
+
if (ch == '_') {
|
|
43
|
+
write_char(g, 'E');
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
static void write_varref(struct generator * g, struct name * p) { /* reference to variable */
|
|
48
|
+
if (p->type < t_routine) write_string(g, "Z.");
|
|
49
|
+
write_varname(g, p);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
static void write_literal_string(struct generator * g, symbol * p) {
|
|
53
|
+
int i;
|
|
54
|
+
// Ada supports UTF-8 literal strings, we only need to escape the quote and
|
|
55
|
+
// special characters.
|
|
56
|
+
write_char(g, '"');
|
|
57
|
+
for (i = 0; i < SIZE(p); i++) {
|
|
58
|
+
int ch = p[i];
|
|
59
|
+
if (ch == '"') {
|
|
60
|
+
write_string(g, "\"\"");
|
|
61
|
+
} else if (ch < 32 || ch == 127) {
|
|
62
|
+
printf("In write_literal_string, can't handle non-graphic character 0x%02x currently\n", (int)p[i]);
|
|
63
|
+
exit(1);
|
|
64
|
+
} else if (ch <= 255) {
|
|
65
|
+
write_char(g, ch);
|
|
66
|
+
} else {
|
|
67
|
+
printf("In write_literal_string, can't convert p[%d] to char because it's 0x%02x\n", i, (int)p[i]);
|
|
68
|
+
exit(1);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
write_char(g, '"');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
static void write_margin(struct generator * g) {
|
|
75
|
+
int i;
|
|
76
|
+
for (i = 0; i < g->margin; i++) write_string(g, " ");
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/* Write a variable declaration. */
|
|
80
|
+
static void write_declare(struct generator * g,
|
|
81
|
+
char * declaration,
|
|
82
|
+
struct node * p) {
|
|
83
|
+
struct str * temp = g->outbuf;
|
|
84
|
+
g->outbuf = g->declarations;
|
|
85
|
+
write_string(g, " ");
|
|
86
|
+
writef(g, declaration, p);
|
|
87
|
+
write_string(g, ";");
|
|
88
|
+
write_newline(g);
|
|
89
|
+
g->outbuf = temp;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
static void write_comment(struct generator * g, struct node * p) {
|
|
93
|
+
if (g->options->comments) {
|
|
94
|
+
write_margin(g);
|
|
95
|
+
write_string(g, "-- ");
|
|
96
|
+
write_comment_content(g, p);
|
|
97
|
+
write_newline(g);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
static void write_block_start(struct generator * g) {
|
|
102
|
+
w(g, "~Mbegin~+~N");
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
static void write_block_end(struct generator * g) { /* block end */
|
|
106
|
+
w(g, "~-~Mend;~N");
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
static void restore_string(struct node * p, struct str * out, struct str * savevar) {
|
|
110
|
+
|
|
111
|
+
str_clear(out);
|
|
112
|
+
str_append_string(out, "Z.C := ");
|
|
113
|
+
if (p->mode != m_forward) str_append_string(out, "Z.L - ");
|
|
114
|
+
str_append(out, savevar);
|
|
115
|
+
str_append_string(out, ";");
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
static void write_savecursor(struct generator * g, struct node * p,
|
|
119
|
+
struct str * savevar) {
|
|
120
|
+
g->B[0] = str_data(savevar);
|
|
121
|
+
g->S[1] = "";
|
|
122
|
+
if (p->mode != m_forward) g->S[1] = "Z.L - ";
|
|
123
|
+
write_declare(g, " ~B0 : Char_Index", p);
|
|
124
|
+
writef(g, "~M~B0 := ~S1Z.C;~N" , p);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
static void write_restorecursor(struct generator * g, struct node * p, struct str * savevar) {
|
|
128
|
+
write_margin(g);
|
|
129
|
+
if (p->mode == m_forward) {
|
|
130
|
+
write_string(g, "Z.C := ");
|
|
131
|
+
} else {
|
|
132
|
+
write_string(g, "Z.C := Z.L - ");
|
|
133
|
+
}
|
|
134
|
+
write_str(g, savevar);
|
|
135
|
+
write_string(g, ";");
|
|
136
|
+
write_newline(g);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
static void wsetl(struct generator * g, int n) {
|
|
140
|
+
|
|
141
|
+
write_newline(g);
|
|
142
|
+
write_margin(g);
|
|
143
|
+
write_string(g, "<<lab");
|
|
144
|
+
write_int(g, n);
|
|
145
|
+
write_string(g, ">>");
|
|
146
|
+
write_newline(g);
|
|
147
|
+
g->line_labelled = g->line_count;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
static void wgotol(struct generator * g, int n) {
|
|
151
|
+
write_margin(g);
|
|
152
|
+
write_string(g, "goto lab");
|
|
153
|
+
write_int(g, n);
|
|
154
|
+
write_string(g, ";");
|
|
155
|
+
write_newline(g);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
static void write_failure(struct generator * g) {
|
|
159
|
+
|
|
160
|
+
if (str_len(g->failure_str) != 0) {
|
|
161
|
+
write_margin(g);
|
|
162
|
+
write_str(g, g->failure_str);
|
|
163
|
+
write_newline(g);
|
|
164
|
+
}
|
|
165
|
+
write_margin(g);
|
|
166
|
+
switch (g->failure_label) {
|
|
167
|
+
case x_return:
|
|
168
|
+
write_string(g, "Result := False;");
|
|
169
|
+
write_newline(g);
|
|
170
|
+
write_margin(g);
|
|
171
|
+
write_string(g, "return;");
|
|
172
|
+
break;
|
|
173
|
+
default:
|
|
174
|
+
write_string(g, "goto lab");
|
|
175
|
+
write_int(g, g->failure_label);
|
|
176
|
+
write_string(g, ";");
|
|
177
|
+
g->label_used = 1;
|
|
178
|
+
}
|
|
179
|
+
write_newline(g);
|
|
180
|
+
g->unreachable = true;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
static void write_failure_if(struct generator * g, char * s, struct node * p) {
|
|
184
|
+
|
|
185
|
+
writef(g, "~Mif ", p);
|
|
186
|
+
writef(g, s, p);
|
|
187
|
+
writef(g, " then~N~+", p);
|
|
188
|
+
write_failure(g);
|
|
189
|
+
writef(g, "~-~Mend if;~N", p);
|
|
190
|
+
g->unreachable = false;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/* if at limit fail */
|
|
194
|
+
static void write_check_limit(struct generator * g, struct node * p) {
|
|
195
|
+
if (p->mode == m_forward) {
|
|
196
|
+
write_failure_if(g, "Z.C >= Z.L", p);
|
|
197
|
+
} else {
|
|
198
|
+
write_failure_if(g, "Z.C <= Z.Lb", p);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/* Formatted write. */
|
|
203
|
+
static void writef(struct generator * g, const char * input, struct node * p) {
|
|
204
|
+
int i = 0;
|
|
205
|
+
int l = strlen(input);
|
|
206
|
+
|
|
207
|
+
while (i < l) {
|
|
208
|
+
int ch = input[i++];
|
|
209
|
+
if (ch != '~') {
|
|
210
|
+
write_char(g, ch);
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
switch (input[i++]) {
|
|
214
|
+
default: write_char(g, input[i - 1]); continue;
|
|
215
|
+
case 'C': write_comment(g, p); continue;
|
|
216
|
+
case 'f':
|
|
217
|
+
write_failure(g);
|
|
218
|
+
g->unreachable = false;
|
|
219
|
+
continue;
|
|
220
|
+
case 'M': write_margin(g); continue;
|
|
221
|
+
case 'N': write_newline(g); continue;
|
|
222
|
+
case '{': write_block_start(g); continue;
|
|
223
|
+
case '}': write_block_end(g); continue;
|
|
224
|
+
case 'S': write_string(g, g->S[input[i++] - '0']); continue;
|
|
225
|
+
case 'B': write_b(g, g->B[input[i++] - '0']); continue;
|
|
226
|
+
case 'I': write_int(g, g->I[input[i++] - '0']); continue;
|
|
227
|
+
case 'V': write_varref(g, g->V[input[i++] - '0']); continue;
|
|
228
|
+
case 'W': write_varname(g, g->V[input[i++] - '0']); continue;
|
|
229
|
+
case 'L': write_literal_string(g, g->L[input[i++] - '0']); continue;
|
|
230
|
+
case '+': g->margin++; continue;
|
|
231
|
+
case '-': g->margin--; continue;
|
|
232
|
+
case 'n': write_string(g, g->options->name); continue;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
static void w(struct generator * g, const char * s) {
|
|
238
|
+
writef(g, s, 0);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
static int need_among_var(struct node *p) {
|
|
242
|
+
|
|
243
|
+
while (p) {
|
|
244
|
+
if (p->type == c_substring || p->type == c_among) {
|
|
245
|
+
return 1;
|
|
246
|
+
}
|
|
247
|
+
if (p->right && need_among_var(p->right)) {
|
|
248
|
+
return 1;
|
|
249
|
+
}
|
|
250
|
+
p = p->left;
|
|
251
|
+
}
|
|
252
|
+
return 0;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
static int need_among_handler(struct among *a) {
|
|
256
|
+
int i;
|
|
257
|
+
struct amongvec * v = a->b;
|
|
258
|
+
|
|
259
|
+
for (i = 0; i < a->literalstring_count; i++, v++) {
|
|
260
|
+
if (v->function != 0) {
|
|
261
|
+
return 1;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
return 0;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
static void generate_AE(struct generator * g, struct node * p) {
|
|
269
|
+
const char * s;
|
|
270
|
+
switch (p->type) {
|
|
271
|
+
case c_name:
|
|
272
|
+
write_varref(g, p->name); break;
|
|
273
|
+
case c_number:
|
|
274
|
+
// Avoid `parentheses required for unary minus` error from gnat.
|
|
275
|
+
if (p->number < 0)
|
|
276
|
+
write_char(g, '(');
|
|
277
|
+
write_int(g, p->number);
|
|
278
|
+
if (p->number < 0)
|
|
279
|
+
write_char(g, ')');
|
|
280
|
+
break;
|
|
281
|
+
case c_maxint:
|
|
282
|
+
write_string(g, "Integer'Last"); break;
|
|
283
|
+
case c_minint:
|
|
284
|
+
write_string(g, "Integer'First"); break;
|
|
285
|
+
case c_neg:
|
|
286
|
+
write_string(g, "(-"); generate_AE(g, p->right); write_char(g, ')'); break;
|
|
287
|
+
case c_multiply:
|
|
288
|
+
s = " * "; goto label0;
|
|
289
|
+
case c_plus:
|
|
290
|
+
s = " + "; goto label0;
|
|
291
|
+
case c_minus:
|
|
292
|
+
s = " - "; goto label0;
|
|
293
|
+
case c_divide:
|
|
294
|
+
s = " / ";
|
|
295
|
+
label0:
|
|
296
|
+
write_char(g, '('); generate_AE(g, p->left);
|
|
297
|
+
write_string(g, s); generate_AE(g, p->right); write_char(g, ')'); break;
|
|
298
|
+
case c_cursor:
|
|
299
|
+
w(g, "Z.C"); break;
|
|
300
|
+
case c_limit:
|
|
301
|
+
w(g, p->mode == m_forward ? "Z.L" : "Z.Lb"); break;
|
|
302
|
+
case c_len:
|
|
303
|
+
w(g, "Length_Utf8 (Z)");
|
|
304
|
+
break;
|
|
305
|
+
case c_size:
|
|
306
|
+
w(g, "Length (Z)");
|
|
307
|
+
break;
|
|
308
|
+
case c_lenof:
|
|
309
|
+
case c_sizeof:
|
|
310
|
+
g->V[0] = p->name;
|
|
311
|
+
w(g, "Length_Utf8 (~V0)");
|
|
312
|
+
break;
|
|
313
|
+
default:
|
|
314
|
+
break;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
static void generate_bra(struct generator * g, struct node * p) {
|
|
319
|
+
write_comment(g, p);
|
|
320
|
+
p = p->left;
|
|
321
|
+
while (p) {
|
|
322
|
+
generate(g, p);
|
|
323
|
+
p = p->right;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
static void generate_and(struct generator * g, struct node * p) {
|
|
328
|
+
struct str * savevar = vars_newname(g);
|
|
329
|
+
int keep_c = K_needed(g, p->left);
|
|
330
|
+
|
|
331
|
+
write_comment(g, p);
|
|
332
|
+
|
|
333
|
+
if (keep_c) write_savecursor(g, p, savevar);
|
|
334
|
+
|
|
335
|
+
p = p->left;
|
|
336
|
+
while (p) {
|
|
337
|
+
generate(g, p);
|
|
338
|
+
if (g->unreachable) break;
|
|
339
|
+
if (keep_c && p->right != 0) write_restorecursor(g, p, savevar);
|
|
340
|
+
p = p->right;
|
|
341
|
+
}
|
|
342
|
+
str_delete(savevar);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
static void generate_or(struct generator * g, struct node * p) {
|
|
346
|
+
struct str * savevar = vars_newname(g);
|
|
347
|
+
int used = g->label_used;
|
|
348
|
+
int keep_c = K_needed(g, p->left);
|
|
349
|
+
|
|
350
|
+
int a0 = g->failure_label;
|
|
351
|
+
struct str * a1 = str_copy(g->failure_str);
|
|
352
|
+
|
|
353
|
+
int out_lab = new_label(g);
|
|
354
|
+
int end_unreachable = true;
|
|
355
|
+
|
|
356
|
+
write_comment(g, p);
|
|
357
|
+
|
|
358
|
+
if (keep_c) write_savecursor(g, p, savevar);
|
|
359
|
+
|
|
360
|
+
p = p->left;
|
|
361
|
+
str_clear(g->failure_str);
|
|
362
|
+
|
|
363
|
+
if (p == 0) {
|
|
364
|
+
/* p should never be 0 after an or: there should be at least two
|
|
365
|
+
* sub nodes. */
|
|
366
|
+
fprintf(stderr, "Error: \"or\" node without children nodes.");
|
|
367
|
+
exit(1);
|
|
368
|
+
}
|
|
369
|
+
while (p->right) {
|
|
370
|
+
g->failure_label = new_label(g);
|
|
371
|
+
g->label_used = 0;
|
|
372
|
+
generate(g, p);
|
|
373
|
+
if (!g->unreachable) {
|
|
374
|
+
wgotol(g, out_lab);
|
|
375
|
+
end_unreachable = false;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
if (g->label_used)
|
|
379
|
+
wsetl(g, g->failure_label);
|
|
380
|
+
g->unreachable = false;
|
|
381
|
+
if (keep_c) {
|
|
382
|
+
write_restorecursor(g, p, savevar);
|
|
383
|
+
}
|
|
384
|
+
p = p->right;
|
|
385
|
+
}
|
|
386
|
+
g->label_used = used;
|
|
387
|
+
g->failure_label = a0;
|
|
388
|
+
str_delete(g->failure_str);
|
|
389
|
+
g->failure_str = a1;
|
|
390
|
+
|
|
391
|
+
generate(g, p);
|
|
392
|
+
wsetl(g, out_lab);
|
|
393
|
+
if (!end_unreachable) {
|
|
394
|
+
g->unreachable = false;
|
|
395
|
+
}
|
|
396
|
+
str_delete(savevar);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
static void generate_backwards(struct generator * g, struct node * p) {
|
|
400
|
+
writef(g, "~MZ.Lb := Z.C; Z.C := Z.L;~C~N", p);
|
|
401
|
+
generate(g, p->left);
|
|
402
|
+
w(g, "~MZ.C := Z.Lb;~N");
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
static void generate_not(struct generator * g, struct node * p) {
|
|
407
|
+
struct str * savevar = vars_newname(g);
|
|
408
|
+
int keep_c = K_needed(g, p->left);
|
|
409
|
+
|
|
410
|
+
int a0 = g->failure_label, l;
|
|
411
|
+
struct str * a1 = str_copy(g->failure_str);
|
|
412
|
+
|
|
413
|
+
write_comment(g, p);
|
|
414
|
+
if (keep_c) {
|
|
415
|
+
write_savecursor(g, p, savevar);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
g->failure_label = new_label(g);
|
|
419
|
+
str_clear(g->failure_str);
|
|
420
|
+
|
|
421
|
+
l = g->failure_label;
|
|
422
|
+
|
|
423
|
+
generate(g, p->left);
|
|
424
|
+
|
|
425
|
+
g->failure_label = a0;
|
|
426
|
+
str_delete(g->failure_str);
|
|
427
|
+
g->failure_str = a1;
|
|
428
|
+
|
|
429
|
+
if (!g->unreachable) write_failure(g);
|
|
430
|
+
|
|
431
|
+
if (g->label_used)
|
|
432
|
+
wsetl(g, l);
|
|
433
|
+
|
|
434
|
+
g->unreachable = false;
|
|
435
|
+
|
|
436
|
+
if (keep_c) write_restorecursor(g, p, savevar);
|
|
437
|
+
str_delete(savevar);
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
|
|
441
|
+
static void generate_try(struct generator * g, struct node * p) {
|
|
442
|
+
struct str * savevar;
|
|
443
|
+
int keep_c = K_needed(g, p->left);
|
|
444
|
+
|
|
445
|
+
g->failure_label = new_label(g);
|
|
446
|
+
g->label_used = 0;
|
|
447
|
+
str_clear(g->failure_str);
|
|
448
|
+
|
|
449
|
+
write_comment(g, p);
|
|
450
|
+
if (keep_c) {
|
|
451
|
+
savevar = vars_newname(g);
|
|
452
|
+
write_savecursor(g, p, savevar);
|
|
453
|
+
restore_string(p, g->failure_str, savevar);
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
generate(g, p->left);
|
|
457
|
+
if (g->label_used)
|
|
458
|
+
wsetl(g, g->failure_label);
|
|
459
|
+
g->unreachable = false;
|
|
460
|
+
|
|
461
|
+
if (keep_c) {
|
|
462
|
+
str_delete(savevar);
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
static void generate_set(struct generator * g, struct node * p) {
|
|
467
|
+
write_comment(g, p);
|
|
468
|
+
g->V[0] = p->name;
|
|
469
|
+
writef(g, "~M~V0 := True;~N", p);
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
static void generate_unset(struct generator * g, struct node * p) {
|
|
473
|
+
write_comment(g, p);
|
|
474
|
+
g->V[0] = p->name;
|
|
475
|
+
writef(g, "~M~V0 := False;~N", p);
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
static void generate_fail(struct generator * g, struct node * p) {
|
|
479
|
+
write_comment(g, p);
|
|
480
|
+
generate(g, p->left);
|
|
481
|
+
if (!g->unreachable) write_failure(g);
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
/* generate_test() also implements 'reverse' */
|
|
485
|
+
|
|
486
|
+
static void generate_test(struct generator * g, struct node * p) {
|
|
487
|
+
struct str * savevar = vars_newname(g);
|
|
488
|
+
int keep_c = K_needed(g, p->left);
|
|
489
|
+
|
|
490
|
+
write_comment(g, p);
|
|
491
|
+
|
|
492
|
+
if (keep_c) {
|
|
493
|
+
write_savecursor(g, p, savevar);
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
generate(g, p->left);
|
|
497
|
+
|
|
498
|
+
if (!g->unreachable) {
|
|
499
|
+
if (keep_c) {
|
|
500
|
+
write_restorecursor(g, p, savevar);
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
str_delete(savevar);
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
static void generate_do(struct generator * g, struct node * p) {
|
|
507
|
+
struct str * savevar = vars_newname(g);
|
|
508
|
+
int keep_c = K_needed(g, p->left);
|
|
509
|
+
write_comment(g, p);
|
|
510
|
+
if (keep_c) write_savecursor(g, p, savevar);
|
|
511
|
+
|
|
512
|
+
if (p->left->type == c_call) {
|
|
513
|
+
/* Optimise do <call> */
|
|
514
|
+
write_comment(g, p->left);
|
|
515
|
+
g->V[0] = p->left->name;
|
|
516
|
+
w(g, "~M~V0 (Z, Result);~N");
|
|
517
|
+
} else {
|
|
518
|
+
g->failure_label = new_label(g);
|
|
519
|
+
str_clear(g->failure_str);
|
|
520
|
+
|
|
521
|
+
generate(g, p->left);
|
|
522
|
+
if (g->label_used)
|
|
523
|
+
wsetl(g, g->failure_label);
|
|
524
|
+
g->unreachable = false;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
if (keep_c) write_restorecursor(g, p, savevar);
|
|
528
|
+
str_delete(savevar);
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
static void generate_GO_grouping(struct generator * g, struct node * p, int is_goto, int complement) {
|
|
532
|
+
|
|
533
|
+
struct grouping * q = p->name->grouping;
|
|
534
|
+
g->S[0] = p->mode == m_forward ? "" : "_Backward";
|
|
535
|
+
g->S[1] = complement ? "In" : "Out";
|
|
536
|
+
g->S[2] = g->options->encoding == ENC_UTF8 ? "" : "";
|
|
537
|
+
g->V[0] = p->name;
|
|
538
|
+
g->I[0] = q->smallest_ch;
|
|
539
|
+
g->I[1] = q->largest_ch;
|
|
540
|
+
if (is_goto) {
|
|
541
|
+
writef(g, "~M~S1_Grouping~S0~S2 (Z, ~V0, ~I0, ~I1, True, C);", p);
|
|
542
|
+
write_failure_if(g, "C < 0", p);
|
|
543
|
+
} else {
|
|
544
|
+
writef(g, "~C"
|
|
545
|
+
"~M~S1_Grouping~S0~S2 (Z, ~V0, ~I0, ~I1, True, C);~N", p);
|
|
546
|
+
write_failure_if(g, "C < 0", p);
|
|
547
|
+
|
|
548
|
+
if (p->mode == m_forward)
|
|
549
|
+
w(g, "~MZ.C := Z.C + C;~N");
|
|
550
|
+
else
|
|
551
|
+
w(g, "~MZ.C := Z.C - C;~N");
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
static void generate_GO(struct generator * g, struct node * p, int style) {
|
|
556
|
+
int end_unreachable = false;
|
|
557
|
+
int used = g->label_used;
|
|
558
|
+
/* Initialise to NULL to suppress bogus "may be used uninitialised" warning. */
|
|
559
|
+
struct str * savevar = NULL;
|
|
560
|
+
int keep_c = style == 1 || repeat_restore(g, p->left);
|
|
561
|
+
int a0 = g->failure_label;
|
|
562
|
+
|
|
563
|
+
int golab = new_label(g);
|
|
564
|
+
|
|
565
|
+
if (p->left->type == c_grouping || p->left->type == c_non) {
|
|
566
|
+
/* Special case for "goto" or "gopast" when used on a grouping or an
|
|
567
|
+
* inverted grouping - the movement of c by the matching action is
|
|
568
|
+
* exactly what we want! */
|
|
569
|
+
#ifdef OPTIMISATION_WARNINGS
|
|
570
|
+
printf("Optimising %s %s\n", style ? "goto" : "gopast", p->left->type == c_non ? "non" : "grouping");
|
|
571
|
+
#endif
|
|
572
|
+
if (g->options->comments) {
|
|
573
|
+
writef(g, "~M~C", p);
|
|
574
|
+
}
|
|
575
|
+
generate_GO_grouping(g, p->left, style, p->left->type == c_non);
|
|
576
|
+
return;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
write_comment(g, p);
|
|
580
|
+
w(g, "~Mloop~N~+");
|
|
581
|
+
|
|
582
|
+
if (keep_c) {
|
|
583
|
+
savevar = vars_newname(g);
|
|
584
|
+
write_savecursor(g, p, savevar);
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
g->failure_label = new_label(g);
|
|
588
|
+
g->label_used = 0;
|
|
589
|
+
str_clear(g->failure_str);
|
|
590
|
+
generate(g, p->left);
|
|
591
|
+
|
|
592
|
+
if (g->unreachable) {
|
|
593
|
+
/* Cannot break out of this loop: therefore the code after the
|
|
594
|
+
* end of the loop is unreachable.*/
|
|
595
|
+
end_unreachable = true;
|
|
596
|
+
} else {
|
|
597
|
+
/* include for goto; omit for gopast */
|
|
598
|
+
if (style == 1) write_restorecursor(g, p, savevar);
|
|
599
|
+
g->I[0] = golab;
|
|
600
|
+
w(g, "~Mexit;~N");
|
|
601
|
+
}
|
|
602
|
+
g->unreachable = false;
|
|
603
|
+
if (g->label_used)
|
|
604
|
+
wsetl(g, g->failure_label);
|
|
605
|
+
if (keep_c) {
|
|
606
|
+
write_restorecursor(g, p, savevar);
|
|
607
|
+
str_delete(savevar);
|
|
608
|
+
}
|
|
609
|
+
g->label_used = used;
|
|
610
|
+
g->failure_label = a0;
|
|
611
|
+
|
|
612
|
+
write_check_limit(g, p);
|
|
613
|
+
generate_next(g, p);
|
|
614
|
+
|
|
615
|
+
g->I[0] = golab;
|
|
616
|
+
w(g, "~-~Mend loop;~N");
|
|
617
|
+
g->unreachable = end_unreachable;
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
static void generate_loop(struct generator * g, struct node * p) {
|
|
621
|
+
struct str * loopvar = vars_newname(g);
|
|
622
|
+
write_comment(g, p);
|
|
623
|
+
g->B[0] = str_data(loopvar);
|
|
624
|
+
write_declare(g, " ~B0 : Integer", p);
|
|
625
|
+
w(g, "~MFor ~B0 := ");
|
|
626
|
+
generate_AE(g, p->AE);
|
|
627
|
+
writef(g, " DownTo 1 Do~N", p);
|
|
628
|
+
writef(g, "~{", p);
|
|
629
|
+
|
|
630
|
+
generate(g, p->left);
|
|
631
|
+
|
|
632
|
+
w(g, "~}");
|
|
633
|
+
str_delete(loopvar);
|
|
634
|
+
g->unreachable = false;
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
static void generate_repeat_or_atleast(struct generator * g, struct node * p, struct str * loopvar) {
|
|
638
|
+
struct str * savevar = vars_newname(g);
|
|
639
|
+
int keep_c = repeat_restore(g, p->left);
|
|
640
|
+
int replab = new_label(g);
|
|
641
|
+
g->I[0] = replab;
|
|
642
|
+
wsetl(g, replab);
|
|
643
|
+
writef(g, "~N~Mloop~N~+", p);
|
|
644
|
+
|
|
645
|
+
if (keep_c) write_savecursor(g, p, savevar);
|
|
646
|
+
|
|
647
|
+
g->failure_label = new_label(g);
|
|
648
|
+
g->label_used = 0;
|
|
649
|
+
generate(g, p->left);
|
|
650
|
+
|
|
651
|
+
if (!g->unreachable) {
|
|
652
|
+
if (loopvar != 0) {
|
|
653
|
+
g->B[0] = str_data(loopvar);
|
|
654
|
+
w(g, "~M~B0 := ~B0 - 1;~N");
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
g->I[0] = replab;
|
|
658
|
+
w(g, "~Mgoto lab~I0;~N");
|
|
659
|
+
}
|
|
660
|
+
if (g->label_used)
|
|
661
|
+
wsetl(g, g->failure_label);
|
|
662
|
+
g->unreachable = false;
|
|
663
|
+
|
|
664
|
+
if (keep_c) write_restorecursor(g, p, savevar);
|
|
665
|
+
|
|
666
|
+
w(g, "~N~Mexit;~N~-~Mend loop;~N");
|
|
667
|
+
str_delete(savevar);
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
static void generate_repeat(struct generator * g, struct node * p) {
|
|
671
|
+
write_comment(g, p);
|
|
672
|
+
generate_repeat_or_atleast(g, p, NULL);
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
static void generate_atleast(struct generator * g, struct node * p) {
|
|
676
|
+
struct str * loopvar = vars_newname(g);
|
|
677
|
+
|
|
678
|
+
write_comment(g, p);
|
|
679
|
+
w(g, "~{");
|
|
680
|
+
g->B[0] = str_data(loopvar);
|
|
681
|
+
|
|
682
|
+
write_declare(g, " ~B0 : Integer", p);
|
|
683
|
+
w(g, "~M~B0 := ");
|
|
684
|
+
generate_AE(g, p->AE);
|
|
685
|
+
w(g, ";~N");
|
|
686
|
+
{
|
|
687
|
+
int a0 = g->failure_label;
|
|
688
|
+
|
|
689
|
+
generate_repeat_or_atleast(g, p, loopvar);
|
|
690
|
+
|
|
691
|
+
g->failure_label = a0;
|
|
692
|
+
}
|
|
693
|
+
g->B[0] = str_data(loopvar);
|
|
694
|
+
write_failure_if(g, "~B0 > 0", p);
|
|
695
|
+
w(g, "~}");
|
|
696
|
+
str_delete(loopvar);
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
static void generate_setmark(struct generator * g, struct node * p) {
|
|
700
|
+
write_comment(g, p);
|
|
701
|
+
g->V[0] = p->name;
|
|
702
|
+
writef(g, "~M~V0 := Z.C;~N", p);
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
static void generate_tomark(struct generator * g, struct node * p) {
|
|
706
|
+
write_comment(g, p);
|
|
707
|
+
g->S[0] = p->mode == m_forward ? ">" : "<";
|
|
708
|
+
|
|
709
|
+
w(g, "~Mif Z.C ~S0 "); generate_AE(g, p->AE); w(g, " then~N");
|
|
710
|
+
write_failure(g);
|
|
711
|
+
w(g, "~Mend if;~N");
|
|
712
|
+
g->unreachable = false;
|
|
713
|
+
w(g, "~MZ.C := "); generate_AE(g, p->AE); writef(g, ";~N", p);
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
static void generate_atmark(struct generator * g, struct node * p) {
|
|
717
|
+
write_comment(g, p);
|
|
718
|
+
w(g, "~Mif Z.C /= "); generate_AE(g, p->AE); writef(g, " then~N~+", p);
|
|
719
|
+
write_failure(g);
|
|
720
|
+
w(g, "~-~Mend if;~N");
|
|
721
|
+
g->unreachable = false;
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
static void generate_hop(struct generator * g, struct node * p) {
|
|
725
|
+
g->S[0] = p->mode == m_forward ? "" : "_Backward";
|
|
726
|
+
if (g->options->encoding == ENC_UTF8) {
|
|
727
|
+
w(g, "~MC := Skip_Utf8~S0 (Z, ");
|
|
728
|
+
generate_AE(g, p->AE); writef(g, ");~C~N", p);
|
|
729
|
+
write_failure_if(g, "C < 0", p);
|
|
730
|
+
} else {
|
|
731
|
+
w(g, "~MC := Z.C ~S0 ");
|
|
732
|
+
generate_AE(g, p->AE);
|
|
733
|
+
writef(g, ";~C~N", p);
|
|
734
|
+
if (p->mode == m_forward) {
|
|
735
|
+
write_failure_if(g, "C > Z.L or C < Z.C", p);
|
|
736
|
+
} else {
|
|
737
|
+
write_failure_if(g, "C < Z.Lb or C > Z.C", p);
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
writef(g, "~MZ.C := C;~N", p);
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
static void generate_delete(struct generator * g, struct node * p) {
|
|
744
|
+
write_comment(g, p);
|
|
745
|
+
writef(g, "~MSlice_Del (Z);~N", p);
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
static void generate_next(struct generator * g, struct node * p) {
|
|
749
|
+
write_comment(g, p);
|
|
750
|
+
if (p->mode == m_forward)
|
|
751
|
+
w(g, "~MC := Skip_Utf8 (Z);~N");
|
|
752
|
+
else
|
|
753
|
+
w(g, "~MC := Skip_Utf8_Backward (Z);~N");
|
|
754
|
+
write_failure_if(g, "C < 0", p);
|
|
755
|
+
w(g, "~MZ.C := C;~N");
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
static void generate_tolimit(struct generator * g, struct node * p) {
|
|
759
|
+
g->S[0] = p->mode == m_forward ? "" : "b";
|
|
760
|
+
writef(g, "~MZ.C := Z.L~S0;~C~N", p);
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
static void generate_atlimit(struct generator * g, struct node * p) {
|
|
764
|
+
write_comment(g, p);
|
|
765
|
+
g->S[0] = p->mode == m_forward ? "" : "b";
|
|
766
|
+
g->S[1] = p->mode == m_forward ? "<" : ">";
|
|
767
|
+
write_failure_if(g, "Z.C ~S1 Z.L~S0", p);
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
static void generate_leftslice(struct generator * g, struct node * p) {
|
|
771
|
+
g->S[0] = p->mode == m_forward ? "Bra" : "Ket";
|
|
772
|
+
writef(g, "~MZ.~S0 := Z.C;~C~N", p);
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
static void generate_rightslice(struct generator * g, struct node * p) {
|
|
776
|
+
g->S[0] = p->mode == m_forward ? "Ket" : "Bra";
|
|
777
|
+
writef(g, "~MZ.~S0 := Z.C;~C~N", p);
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
static void generate_assignto(struct generator * g, struct node * p) {
|
|
781
|
+
g->V[0] = p->name;
|
|
782
|
+
writef(g, "~M~V0 := Assign_To (Z, ~V0);~C~N", p);
|
|
783
|
+
write_failure_if(g, "~V0 == 0", p);
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
static void generate_sliceto(struct generator * g, struct node * p) {
|
|
787
|
+
write_comment(g, p);
|
|
788
|
+
g->V[0] = p->name;
|
|
789
|
+
writef(g, "~M~V0 := Ada.Strings.Unbounded.To_Unbounded_String (Slice_To (Z));~N", p);
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
static void generate_address(struct generator * g, struct node * p) {
|
|
793
|
+
symbol * b = p->literalstring;
|
|
794
|
+
if (b != 0) {
|
|
795
|
+
write_literal_string(g, b);
|
|
796
|
+
} else {
|
|
797
|
+
write_varname(g, p->name);
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
static void generate_insert(struct generator * g, struct node * p, int style) {
|
|
802
|
+
|
|
803
|
+
int keep_c = style == c_attach;
|
|
804
|
+
write_comment(g, p);
|
|
805
|
+
if (p->mode == m_backward) keep_c = !keep_c;
|
|
806
|
+
if (keep_c) w(g, "~MC := Z.C;~N");
|
|
807
|
+
writef(g, "~MInsert (Z, Z.C, Z.C, ", p);
|
|
808
|
+
generate_address(g, p);
|
|
809
|
+
writef(g, ");~N", p);
|
|
810
|
+
if (keep_c) w(g, "~MZ.C := C;~N");
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
static void generate_assignfrom(struct generator * g, struct node * p) {
|
|
814
|
+
int keep_c = p->mode == m_forward; /* like 'attach' */
|
|
815
|
+
|
|
816
|
+
write_comment(g, p);
|
|
817
|
+
if (keep_c) writef(g, "~MC := Z.C;~N", p);
|
|
818
|
+
if (p->mode == m_forward) {
|
|
819
|
+
writef(g, "~MInsert (Z, Z.C, Z.L, ", p);
|
|
820
|
+
} else {
|
|
821
|
+
writef(g, "~MInsert (Z, Z.Lb, Z.C, ", p);
|
|
822
|
+
}
|
|
823
|
+
generate_address(g, p);
|
|
824
|
+
writef(g, ");~N", p);
|
|
825
|
+
if (keep_c) w(g, "~MZ.C := C;~N");
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
static void generate_slicefrom(struct generator * g, struct node * p) {
|
|
829
|
+
write_comment(g, p);
|
|
830
|
+
w(g, "~MSlice_From (Z, ");
|
|
831
|
+
generate_address(g, p);
|
|
832
|
+
writef(g, ");~N", p);
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
static void generate_setlimit(struct generator * g, struct node * p) {
|
|
836
|
+
struct str * savevar = vars_newname(g);
|
|
837
|
+
struct str * varname = vars_newname(g);
|
|
838
|
+
|
|
839
|
+
g->B[0] = str_data(varname);
|
|
840
|
+
write_declare(g, " ~B0 : Integer", p);
|
|
841
|
+
if (p->left && p->left->type == c_tomark) {
|
|
842
|
+
/* Special case for:
|
|
843
|
+
*
|
|
844
|
+
* setlimit tomark AE for C
|
|
845
|
+
*
|
|
846
|
+
* All uses of setlimit in the current stemmers we ship follow this
|
|
847
|
+
* pattern, and by special-casing we can avoid having to save and
|
|
848
|
+
* restore c.
|
|
849
|
+
*/
|
|
850
|
+
struct node * q = p->left;
|
|
851
|
+
|
|
852
|
+
++g->keep_count;
|
|
853
|
+
|
|
854
|
+
g->S[0] = q->mode == m_forward ? ">" : "<";
|
|
855
|
+
|
|
856
|
+
w(g, "~Mif Z.C ~S0 "); generate_AE(g, q->AE); writef(g, " then~N~+", q);
|
|
857
|
+
w(g, "~MResult := False;~N");
|
|
858
|
+
w(g, "~Mreturn;~-~N");
|
|
859
|
+
w(g, "~Mend if;~N");
|
|
860
|
+
w(g, "~M~B0");
|
|
861
|
+
g->unreachable = false;
|
|
862
|
+
|
|
863
|
+
if (p->mode == m_forward) {
|
|
864
|
+
w(g, " := Z.L - Z.C; Z.L := ");
|
|
865
|
+
} else {
|
|
866
|
+
w(g, " := Z.Lb; Z.Lb := ");
|
|
867
|
+
}
|
|
868
|
+
generate_AE(g, q->AE);
|
|
869
|
+
w(g, ";~N");
|
|
870
|
+
|
|
871
|
+
if (p->mode == m_forward) {
|
|
872
|
+
str_assign(g->failure_str, "Z.L := Z.L + ");
|
|
873
|
+
str_append(g->failure_str, varname);
|
|
874
|
+
str_append_ch(g->failure_str, ';');
|
|
875
|
+
} else {
|
|
876
|
+
str_assign(g->failure_str, "Z.Lb := ");
|
|
877
|
+
str_append(g->failure_str, varname);
|
|
878
|
+
str_append_ch(g->failure_str, ';');
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
} else {
|
|
882
|
+
write_savecursor(g, p, savevar);
|
|
883
|
+
|
|
884
|
+
generate(g, p->left);
|
|
885
|
+
|
|
886
|
+
if (!g->unreachable) {
|
|
887
|
+
g->B[0] = str_data(varname);
|
|
888
|
+
if (p->mode == m_forward) {
|
|
889
|
+
w(g, "~M~B0 := Z.L - Z.C;~N");
|
|
890
|
+
w(g, "~MZ.L := Z.C;~N");
|
|
891
|
+
} else {
|
|
892
|
+
w(g, "~M~B0 := Z.Lb;~N");
|
|
893
|
+
w(g, "~MZ.Lb := Z.C;~N");
|
|
894
|
+
}
|
|
895
|
+
write_restorecursor(g, p, savevar);
|
|
896
|
+
|
|
897
|
+
if (p->mode == m_forward) {
|
|
898
|
+
str_assign(g->failure_str, "Z.L := Z.L + ");
|
|
899
|
+
str_append(g->failure_str, varname);
|
|
900
|
+
str_append_ch(g->failure_str, ';');
|
|
901
|
+
} else {
|
|
902
|
+
str_assign(g->failure_str, "Z.Lb := ");
|
|
903
|
+
str_append(g->failure_str, varname);
|
|
904
|
+
str_append_ch(g->failure_str, ';');
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
if (!g->unreachable) {
|
|
910
|
+
generate(g, p->aux);
|
|
911
|
+
|
|
912
|
+
if (!g->unreachable) {
|
|
913
|
+
write_margin(g);
|
|
914
|
+
write_str(g, g->failure_str);
|
|
915
|
+
write_newline(g);
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
str_delete(varname);
|
|
919
|
+
str_delete(savevar);
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
/* dollar sets snowball up to operate on a string variable as if it were the
|
|
923
|
+
* current string */
|
|
924
|
+
static void generate_dollar(struct generator * g, struct node * p) {
|
|
925
|
+
struct str * savevar = vars_newname(g);
|
|
926
|
+
g->B[0] = str_data(savevar);
|
|
927
|
+
write_comment(g, p);
|
|
928
|
+
g->V[0] = p->name;
|
|
929
|
+
|
|
930
|
+
{
|
|
931
|
+
struct str * saved_output = g->outbuf;
|
|
932
|
+
str_clear(g->failure_str);
|
|
933
|
+
g->outbuf = g->failure_str;
|
|
934
|
+
writef(g, "~V0 := FCurrent; "
|
|
935
|
+
"FCurrent := ~B0_Current; "
|
|
936
|
+
"FCursor := ~B0_Cursor; "
|
|
937
|
+
"FLimit := ~B0_Limit; "
|
|
938
|
+
"FBkLimit := ~B0_BkLimit; "
|
|
939
|
+
"FBra := ~B0_Bra; "
|
|
940
|
+
"FKet := ~B0_Ket;", p);
|
|
941
|
+
g->failure_str = g->outbuf;
|
|
942
|
+
g->outbuf = saved_output;
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
write_declare(g, "~B0_Current : AnsiString", p);
|
|
946
|
+
write_declare(g, "~B0_Cursor : Integer", p);
|
|
947
|
+
write_declare(g, "~B0_Limit : Integer", p);
|
|
948
|
+
write_declare(g, "~B0_BkLimit : Integer", p);
|
|
949
|
+
write_declare(g, "~B0_Bra : Integer", p);
|
|
950
|
+
write_declare(g, "~B0_Ket : Integer", p);
|
|
951
|
+
writef(g, "~{"
|
|
952
|
+
"~M~B0_Current := FCurrent;~N"
|
|
953
|
+
"{ ~M~B0_Current := Copy(FCurrent, 1, FLimit); }~N"
|
|
954
|
+
"~M~B0_Cursor := FCursor;~N"
|
|
955
|
+
"~M~B0_Limit := FLimit;~N"
|
|
956
|
+
"~M~B0_BkLimit := FBkLimit;~N"
|
|
957
|
+
"~M~B0_Bra := FBra;~N"
|
|
958
|
+
"~M~B0_Ket := FKet;~N"
|
|
959
|
+
"~MFCurrent := ~V0;~N"
|
|
960
|
+
"~MFCursor := 0;~N"
|
|
961
|
+
"~MFLimit := Length(current);~N", p);
|
|
962
|
+
generate(g, p->left);
|
|
963
|
+
if (!g->unreachable) {
|
|
964
|
+
write_margin(g);
|
|
965
|
+
write_str(g, g->failure_str);
|
|
966
|
+
write_newline(g);
|
|
967
|
+
}
|
|
968
|
+
w(g, "~}");
|
|
969
|
+
str_delete(savevar);
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
static void generate_integer_assign(struct generator * g, struct node * p, char * s) {
|
|
973
|
+
|
|
974
|
+
g->V[0] = p->name;
|
|
975
|
+
w(g, "~M~V0 := ");
|
|
976
|
+
|
|
977
|
+
if (s != 0) {
|
|
978
|
+
g->S[0] = s;
|
|
979
|
+
w(g, "~V0 ~S0 ");
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
generate_AE(g, p->AE);
|
|
983
|
+
w(g, ";~N");
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
static void generate_integer_test(struct generator * g, struct node * p, char * s) {
|
|
987
|
+
|
|
988
|
+
w(g, "~Mif not (");
|
|
989
|
+
generate_AE(g, p->left);
|
|
990
|
+
write_char(g, ' ');
|
|
991
|
+
write_string(g, s);
|
|
992
|
+
write_char(g, ' ');
|
|
993
|
+
generate_AE(g, p->AE);
|
|
994
|
+
w(g, ") then~+~N");
|
|
995
|
+
write_failure(g);
|
|
996
|
+
w(g, "~-~Mend if;~N");
|
|
997
|
+
g->unreachable = false;
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
static void generate_integer_function(struct generator * g, struct node * p, char * s) {
|
|
1001
|
+
|
|
1002
|
+
w(g, "~MResult := (");
|
|
1003
|
+
generate_AE(g, p->left);
|
|
1004
|
+
write_char(g, ' ');
|
|
1005
|
+
write_string(g, s);
|
|
1006
|
+
write_char(g, ' ');
|
|
1007
|
+
generate_AE(g, p->AE);
|
|
1008
|
+
w(g, ");~N");
|
|
1009
|
+
g->unreachable = false;
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
static void generate_call(struct generator * g, struct node * p) {
|
|
1013
|
+
|
|
1014
|
+
write_comment(g, p);
|
|
1015
|
+
g->V[0] = p->name;
|
|
1016
|
+
writef(g, "~M~V0 (Z, Result);~N", p);
|
|
1017
|
+
write_failure_if(g, "not Result", p);
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
static void generate_grouping(struct generator * g, struct node * p, int complement) {
|
|
1021
|
+
|
|
1022
|
+
struct grouping * q = p->name->grouping;
|
|
1023
|
+
g->S[0] = p->mode == m_forward ? "" : "_Backward";
|
|
1024
|
+
g->S[1] = complement ? "Out_" : "In_";
|
|
1025
|
+
g->S[2] = g->options->encoding == ENC_UTF8 ? "" : "";
|
|
1026
|
+
g->V[0] = p->name;
|
|
1027
|
+
g->I[0] = q->smallest_ch;
|
|
1028
|
+
g->I[1] = q->largest_ch;
|
|
1029
|
+
writef(g, "~M~S1Grouping~S0~S2 (Z, ~V0, ~I0, ~I1, False, C);~N", p);
|
|
1030
|
+
write_failure_if(g, "C /= 0", p);
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
static void generate_namedstring(struct generator * g, struct node * p) {
|
|
1034
|
+
|
|
1035
|
+
write_comment(g, p);
|
|
1036
|
+
g->S[0] = p->mode == m_forward ? "" : "_Backward";
|
|
1037
|
+
g->V[0] = p->name;
|
|
1038
|
+
writef(g, "~MC := Eq_S~S0 (Z, Ada.Strings.Unbounded.To_String (~V0));", p);
|
|
1039
|
+
write_failure_if(g, "C = 0", p);
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
static void generate_literalstring(struct generator * g, struct node * p) {
|
|
1043
|
+
symbol * b = p->literalstring;
|
|
1044
|
+
write_comment(g, p);
|
|
1045
|
+
g->S[0] = p->mode == m_forward ? "" : "_Backward";
|
|
1046
|
+
g->L[0] = b;
|
|
1047
|
+
writef(g, "~MC := Eq_S~S0 (Z, ~L0);~N", p);
|
|
1048
|
+
write_failure_if(g, "C = 0", p);
|
|
1049
|
+
if (p->mode == m_forward) {
|
|
1050
|
+
writef(g, "~MZ.C := Z.C + C;~N", p);
|
|
1051
|
+
} else {
|
|
1052
|
+
writef(g, "~MZ.C := Z.C - C;~N", p);
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
static void generate_define(struct generator * g, struct node * p) {
|
|
1057
|
+
struct str *saved_output;
|
|
1058
|
+
struct str *saved_declarations;
|
|
1059
|
+
|
|
1060
|
+
/* Generate function header. */
|
|
1061
|
+
g->V[0] = p->name;
|
|
1062
|
+
w(g, "~N~Mprocedure ~W0 (Z : in out Context_Type; Result : out Boolean) is~N");
|
|
1063
|
+
|
|
1064
|
+
/* Save output*/
|
|
1065
|
+
saved_output = g->outbuf;
|
|
1066
|
+
saved_declarations = g->declarations;
|
|
1067
|
+
|
|
1068
|
+
g->outbuf = str_new();
|
|
1069
|
+
g->declarations = str_new();
|
|
1070
|
+
|
|
1071
|
+
g->next_label = 0;
|
|
1072
|
+
g->var_number = 0;
|
|
1073
|
+
|
|
1074
|
+
g->failure_label = x_return;
|
|
1075
|
+
g->unreachable = false;
|
|
1076
|
+
|
|
1077
|
+
/* Generate function body. */
|
|
1078
|
+
w(g, "~{");
|
|
1079
|
+
switch (p->left->type) {
|
|
1080
|
+
case c_eq: generate_integer_function(g, p->left, "="); break;
|
|
1081
|
+
case c_ne: generate_integer_function(g, p->left, "/="); break;
|
|
1082
|
+
case c_gr: generate_integer_function(g, p->left, ">"); break;
|
|
1083
|
+
case c_ge: generate_integer_function(g, p->left, ">="); break;
|
|
1084
|
+
case c_ls: generate_integer_function(g, p->left, "<"); break;
|
|
1085
|
+
case c_le: generate_integer_function(g, p->left, "<="); break;
|
|
1086
|
+
default:
|
|
1087
|
+
generate(g, p->left);
|
|
1088
|
+
if (!g->unreachable) w(g, "~N~MResult := True;~N");
|
|
1089
|
+
str_append_string(saved_output, " C : Result_Index;\n");
|
|
1090
|
+
if (need_among_var(p->left) || 1) {
|
|
1091
|
+
str_append_string(saved_output, " A : Integer;\n");
|
|
1092
|
+
}
|
|
1093
|
+
break;
|
|
1094
|
+
}
|
|
1095
|
+
g->V[0] = p->name;
|
|
1096
|
+
w(g, "~-~Mend ~W0;~N");
|
|
1097
|
+
|
|
1098
|
+
if (g->var_number) {
|
|
1099
|
+
str_append(saved_output, g->declarations);
|
|
1100
|
+
}
|
|
1101
|
+
|
|
1102
|
+
str_append(saved_output, g->outbuf);
|
|
1103
|
+
str_delete(g->declarations);
|
|
1104
|
+
str_delete(g->outbuf);
|
|
1105
|
+
g->declarations = saved_declarations;
|
|
1106
|
+
g->outbuf = saved_output;
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1109
|
+
static void generate_substring(struct generator * g, struct node * p) {
|
|
1110
|
+
struct among * x = p->among;
|
|
1111
|
+
int block = -1;
|
|
1112
|
+
unsigned int bitmap = 0;
|
|
1113
|
+
struct amongvec * among_cases = x->b;
|
|
1114
|
+
int c;
|
|
1115
|
+
int empty_case = -1;
|
|
1116
|
+
int n_cases = 0;
|
|
1117
|
+
symbol cases[2];
|
|
1118
|
+
int shortest_size = INT_MAX;
|
|
1119
|
+
int call_done = 0;
|
|
1120
|
+
int need_handler = need_among_handler(x);
|
|
1121
|
+
|
|
1122
|
+
write_comment(g, p);
|
|
1123
|
+
|
|
1124
|
+
g->S[0] = p->mode == m_forward ? "" : "_Backward";
|
|
1125
|
+
g->I[0] = x->number;
|
|
1126
|
+
|
|
1127
|
+
/* In forward mode with non-ASCII UTF-8 characters, the first character
|
|
1128
|
+
* of the string will often be the same, so instead look at the last
|
|
1129
|
+
* common character position.
|
|
1130
|
+
*
|
|
1131
|
+
* In backward mode, we can't match if there are fewer characters before
|
|
1132
|
+
* the current position than the minimum length.
|
|
1133
|
+
*/
|
|
1134
|
+
for (c = 0; c < x->literalstring_count; ++c) {
|
|
1135
|
+
int size = among_cases[c].size;
|
|
1136
|
+
if (size != 0 && size < shortest_size) {
|
|
1137
|
+
shortest_size = size;
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
for (c = 0; c < x->literalstring_count; ++c) {
|
|
1142
|
+
symbol ch;
|
|
1143
|
+
if (among_cases[c].size == 0) {
|
|
1144
|
+
empty_case = c;
|
|
1145
|
+
continue;
|
|
1146
|
+
}
|
|
1147
|
+
if (p->mode == m_forward) {
|
|
1148
|
+
ch = among_cases[c].b[shortest_size - 1];
|
|
1149
|
+
} else {
|
|
1150
|
+
ch = among_cases[c].b[among_cases[c].size - 1];
|
|
1151
|
+
}
|
|
1152
|
+
if (n_cases == 0) {
|
|
1153
|
+
block = ch >> 5;
|
|
1154
|
+
} else if (ch >> 5 != block) {
|
|
1155
|
+
block = -1;
|
|
1156
|
+
if (n_cases > 2) break;
|
|
1157
|
+
}
|
|
1158
|
+
if (block == -1) {
|
|
1159
|
+
if (n_cases > 0 && ch == cases[0]) continue;
|
|
1160
|
+
if (n_cases < 2) {
|
|
1161
|
+
cases[n_cases++] = ch;
|
|
1162
|
+
} else if (ch != cases[1]) {
|
|
1163
|
+
++n_cases;
|
|
1164
|
+
break;
|
|
1165
|
+
}
|
|
1166
|
+
} else {
|
|
1167
|
+
if ((bitmap & (1u << (ch & 0x1f))) == 0) {
|
|
1168
|
+
bitmap |= 1u << (ch & 0x1f);
|
|
1169
|
+
if (n_cases < 2)
|
|
1170
|
+
cases[n_cases] = ch;
|
|
1171
|
+
++n_cases;
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1176
|
+
if (block != -1 || n_cases <= 2) {
|
|
1177
|
+
char buf[64];
|
|
1178
|
+
char buf2[128];
|
|
1179
|
+
char buf3[64];
|
|
1180
|
+
g->I[2] = block;
|
|
1181
|
+
g->I[3] = bitmap;
|
|
1182
|
+
g->I[4] = shortest_size - 1;
|
|
1183
|
+
g->S[3] = buf3;
|
|
1184
|
+
snprintf(buf3, sizeof(buf3), "16#%x#", bitmap);
|
|
1185
|
+
if (p->mode == m_forward) {
|
|
1186
|
+
if (shortest_size == 1)
|
|
1187
|
+
sprintf(buf, "Z.C");
|
|
1188
|
+
else
|
|
1189
|
+
sprintf(buf, "Z.C + %d", shortest_size - 1);
|
|
1190
|
+
snprintf(buf2, sizeof(buf2), "Character'Pos (Z.P (%s + 1))", buf);
|
|
1191
|
+
g->S[1] = buf;
|
|
1192
|
+
g->S[2] = buf2;
|
|
1193
|
+
if (shortest_size == 1) {
|
|
1194
|
+
writef(g, "~Mif Z.C >= Z.L", p);
|
|
1195
|
+
} else {
|
|
1196
|
+
writef(g, "~Mif Z.C + ~I4 >= Z.L", p);
|
|
1197
|
+
}
|
|
1198
|
+
} else {
|
|
1199
|
+
g->S[1] = "Z.C - 1";
|
|
1200
|
+
g->S[2] = "Character'Pos (Z.P (Z.C))";
|
|
1201
|
+
if (shortest_size == 1) {
|
|
1202
|
+
writef(g, "~Mif Z.C <= Z.Lb", p);
|
|
1203
|
+
} else {
|
|
1204
|
+
writef(g, "~Mif Z.C - ~I4 <= Z.Lb", p);
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
if (n_cases == 0) {
|
|
1208
|
+
/* We get this for the degenerate case: among ( '' )
|
|
1209
|
+
* This doesn't seem to be a useful construct, but it is
|
|
1210
|
+
* syntactically valid.
|
|
1211
|
+
*/
|
|
1212
|
+
} else if (n_cases == 1) {
|
|
1213
|
+
g->I[4] = cases[0];
|
|
1214
|
+
writef(g, " or else ~S2 /= ~I4", p);
|
|
1215
|
+
} else if (n_cases == 2) {
|
|
1216
|
+
g->I[4] = cases[0];
|
|
1217
|
+
g->I[5] = cases[1];
|
|
1218
|
+
writef(g, " or else (~S2 /= ~I4 and then ~S2 /= ~I5)", p);
|
|
1219
|
+
} else {
|
|
1220
|
+
writef(g, " or else Check_Among (Z, ~S1, ~I2, ~S3)", p);
|
|
1221
|
+
}
|
|
1222
|
+
writef(g, " then~+~N", p);
|
|
1223
|
+
if (empty_case != -1) {
|
|
1224
|
+
/* If the among includes the empty string, it can never fail
|
|
1225
|
+
* so not matching the bitmap means we match the empty string.
|
|
1226
|
+
*/
|
|
1227
|
+
g->I[4] = among_cases[empty_case].result;
|
|
1228
|
+
writef(g, "~MA := ~I4;~-~N~Melse~+~C", p);
|
|
1229
|
+
if (need_handler) {
|
|
1230
|
+
writef(g, "~MFind_Among~S0 (Z, A_~I0, Among_String, Among_Handler'Access, A);~N", p);
|
|
1231
|
+
} else {
|
|
1232
|
+
writef(g, "~MFind_Among~S0 (Z, A_~I0, Among_String, null, A);~N", p);
|
|
1233
|
+
}
|
|
1234
|
+
write_failure_if(g, "A = 0", p);
|
|
1235
|
+
call_done = 1;
|
|
1236
|
+
} else {
|
|
1237
|
+
writef(g, "~f~C", p);
|
|
1238
|
+
}
|
|
1239
|
+
writef(g, "~-~Mend if;~N", p);
|
|
1240
|
+
} else {
|
|
1241
|
+
#ifdef OPTIMISATION_WARNINGS
|
|
1242
|
+
printf("Couldn't shortcut among %d\n", x->number);
|
|
1243
|
+
#endif
|
|
1244
|
+
}
|
|
1245
|
+
|
|
1246
|
+
if (!call_done) {
|
|
1247
|
+
if (need_handler) {
|
|
1248
|
+
writef(g, "~MFind_Among~S0 (Z, A_~I0, Among_String, Among_Handler'Access, A);~N", p);
|
|
1249
|
+
} else {
|
|
1250
|
+
writef(g, "~MFind_Among~S0 (Z, A_~I0, Among_String, null, A);~N", p);
|
|
1251
|
+
}
|
|
1252
|
+
write_failure_if(g, "A = 0", p);
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
|
|
1256
|
+
static void generate_among(struct generator * g, struct node * p) {
|
|
1257
|
+
|
|
1258
|
+
struct among * x = p->among;
|
|
1259
|
+
|
|
1260
|
+
if (x->substring == 0) generate_substring(g, p);
|
|
1261
|
+
|
|
1262
|
+
if (x->starter != 0) generate(g, x->starter);
|
|
1263
|
+
|
|
1264
|
+
if (x->command_count == 1 && x->nocommand_count == 0) {
|
|
1265
|
+
/* Only one outcome ("no match" already handled). */
|
|
1266
|
+
generate(g, x->commands[0]);
|
|
1267
|
+
} else if (x->command_count > 0) {
|
|
1268
|
+
int i;
|
|
1269
|
+
write_comment(g, p);
|
|
1270
|
+
w(g, "~Mcase A is~N~+");
|
|
1271
|
+
for (i = 1; i <= x->command_count; i++) {
|
|
1272
|
+
g->I[0] = i;
|
|
1273
|
+
w(g, "~Mwhen ~I0 =>~N");
|
|
1274
|
+
g->margin++;
|
|
1275
|
+
generate(g, x->commands[i - 1]);
|
|
1276
|
+
g->margin--;
|
|
1277
|
+
g->unreachable = false;
|
|
1278
|
+
}
|
|
1279
|
+
w(g, "~Mwhen others =>~N");
|
|
1280
|
+
w(g, "~M null;~N");
|
|
1281
|
+
w(g, "~-~Mend case;~N");
|
|
1282
|
+
}
|
|
1283
|
+
}
|
|
1284
|
+
|
|
1285
|
+
static void generate_booltest(struct generator * g, struct node * p) {
|
|
1286
|
+
|
|
1287
|
+
write_comment(g, p);
|
|
1288
|
+
g->V[0] = p->name;
|
|
1289
|
+
write_failure_if(g, "not ~V0", p);
|
|
1290
|
+
}
|
|
1291
|
+
|
|
1292
|
+
static void generate_false(struct generator * g, struct node * p) {
|
|
1293
|
+
|
|
1294
|
+
write_comment(g, p);
|
|
1295
|
+
write_failure(g);
|
|
1296
|
+
}
|
|
1297
|
+
|
|
1298
|
+
static void generate_debug(struct generator * g, struct node * p) {
|
|
1299
|
+
|
|
1300
|
+
write_comment(g, p);
|
|
1301
|
+
g->I[0] = g->debug_count++;
|
|
1302
|
+
g->I[1] = p->line_number;
|
|
1303
|
+
writef(g, "~Mdebug(~I0, ~I1);~N", p);
|
|
1304
|
+
}
|
|
1305
|
+
|
|
1306
|
+
static void generate(struct generator * g, struct node * p) {
|
|
1307
|
+
|
|
1308
|
+
int a0;
|
|
1309
|
+
struct str * a1;
|
|
1310
|
+
|
|
1311
|
+
if (g->unreachable) return;
|
|
1312
|
+
|
|
1313
|
+
a0 = g->failure_label;
|
|
1314
|
+
a1 = str_copy(g->failure_str);
|
|
1315
|
+
|
|
1316
|
+
switch (p->type) {
|
|
1317
|
+
case c_define: generate_define(g, p); break;
|
|
1318
|
+
case c_bra: generate_bra(g, p); break;
|
|
1319
|
+
case c_and: generate_and(g, p); break;
|
|
1320
|
+
case c_or: generate_or(g, p); break;
|
|
1321
|
+
case c_backwards: generate_backwards(g, p); break;
|
|
1322
|
+
case c_not: generate_not(g, p); break;
|
|
1323
|
+
case c_set: generate_set(g, p); break;
|
|
1324
|
+
case c_unset: generate_unset(g, p); break;
|
|
1325
|
+
case c_try: generate_try(g, p); break;
|
|
1326
|
+
case c_fail: generate_fail(g, p); break;
|
|
1327
|
+
case c_reverse:
|
|
1328
|
+
case c_test: generate_test(g, p); break;
|
|
1329
|
+
case c_do: generate_do(g, p); break;
|
|
1330
|
+
case c_goto: generate_GO(g, p, 1); break;
|
|
1331
|
+
case c_gopast: generate_GO(g, p, 0); break;
|
|
1332
|
+
case c_repeat: generate_repeat(g, p); break;
|
|
1333
|
+
case c_loop: generate_loop(g, p); break;
|
|
1334
|
+
case c_atleast: generate_atleast(g, p); break;
|
|
1335
|
+
case c_setmark: generate_setmark(g, p); break;
|
|
1336
|
+
case c_tomark: generate_tomark(g, p); break;
|
|
1337
|
+
case c_atmark: generate_atmark(g, p); break;
|
|
1338
|
+
case c_hop: generate_hop(g, p); break;
|
|
1339
|
+
case c_delete: generate_delete(g, p); break;
|
|
1340
|
+
case c_next: generate_next(g, p); break;
|
|
1341
|
+
case c_tolimit: generate_tolimit(g, p); break;
|
|
1342
|
+
case c_atlimit: generate_atlimit(g, p); break;
|
|
1343
|
+
case c_leftslice: generate_leftslice(g, p); break;
|
|
1344
|
+
case c_rightslice: generate_rightslice(g, p); break;
|
|
1345
|
+
case c_assignto: generate_assignto(g, p); break;
|
|
1346
|
+
case c_sliceto: generate_sliceto(g, p); break;
|
|
1347
|
+
case c_assign: generate_assignfrom(g, p); break;
|
|
1348
|
+
case c_insert:
|
|
1349
|
+
case c_attach: generate_insert(g, p, p->type); break;
|
|
1350
|
+
case c_slicefrom: generate_slicefrom(g, p); break;
|
|
1351
|
+
case c_setlimit: generate_setlimit(g, p); break;
|
|
1352
|
+
case c_dollar: generate_dollar(g, p); break;
|
|
1353
|
+
case c_mathassign: generate_integer_assign(g, p, NULL); break;
|
|
1354
|
+
case c_plusassign: generate_integer_assign(g, p, "+"); break;
|
|
1355
|
+
case c_minusassign: generate_integer_assign(g, p, "-"); break;
|
|
1356
|
+
case c_multiplyassign:generate_integer_assign(g, p, "*"); break;
|
|
1357
|
+
case c_divideassign: generate_integer_assign(g, p, "/"); break;
|
|
1358
|
+
case c_eq: generate_integer_test(g, p, "="); break;
|
|
1359
|
+
case c_ne: generate_integer_test(g, p, "/="); break;
|
|
1360
|
+
case c_gr: generate_integer_test(g, p, ">"); break;
|
|
1361
|
+
case c_ge: generate_integer_test(g, p, ">="); break;
|
|
1362
|
+
case c_ls: generate_integer_test(g, p, "<"); break;
|
|
1363
|
+
case c_le: generate_integer_test(g, p, "<="); break;
|
|
1364
|
+
case c_call: generate_call(g, p); break;
|
|
1365
|
+
case c_grouping: generate_grouping(g, p, false); break;
|
|
1366
|
+
case c_non: generate_grouping(g, p, true); break;
|
|
1367
|
+
case c_name: generate_namedstring(g, p); break;
|
|
1368
|
+
case c_literalstring: generate_literalstring(g, p); break;
|
|
1369
|
+
case c_among: generate_among(g, p); break;
|
|
1370
|
+
case c_substring: generate_substring(g, p); break;
|
|
1371
|
+
case c_booltest: generate_booltest(g, p); break;
|
|
1372
|
+
case c_false: generate_false(g, p); break;
|
|
1373
|
+
case c_true: break;
|
|
1374
|
+
case c_debug: generate_debug(g, p); break;
|
|
1375
|
+
default: fprintf(stderr, "%d encountered\n", p->type);
|
|
1376
|
+
exit(1);
|
|
1377
|
+
}
|
|
1378
|
+
|
|
1379
|
+
g->failure_label = a0;
|
|
1380
|
+
str_delete(g->failure_str);
|
|
1381
|
+
g->failure_str = a1;
|
|
1382
|
+
}
|
|
1383
|
+
|
|
1384
|
+
/* Class declaration generation. */
|
|
1385
|
+
static void generate_unit_start(struct generator * g) {
|
|
1386
|
+
g->margin = 0;
|
|
1387
|
+
write_start_comment(g, "-- ", NULL);
|
|
1388
|
+
}
|
|
1389
|
+
|
|
1390
|
+
static void generate_method_decl(struct generator * g, struct name * q) {
|
|
1391
|
+
g->V[0] = q;
|
|
1392
|
+
w(g, "~Mprocedure ~W0 (Z : in out Context_Type; Result : out Boolean);~N");
|
|
1393
|
+
}
|
|
1394
|
+
|
|
1395
|
+
static void generate_method_decls(struct generator * g, enum name_types type) {
|
|
1396
|
+
struct name * q;
|
|
1397
|
+
struct among * a = g->analyser->amongs;
|
|
1398
|
+
int need_handler = 0;
|
|
1399
|
+
|
|
1400
|
+
for (q = g->analyser->names; q; q = q->next) {
|
|
1401
|
+
if ((enum name_types)q->type == type) {
|
|
1402
|
+
generate_method_decl(g, q);
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
|
|
1406
|
+
while (a != 0 && need_handler == 0) {
|
|
1407
|
+
need_handler = need_among_handler(a);
|
|
1408
|
+
a = a->next;
|
|
1409
|
+
}
|
|
1410
|
+
if (need_handler) {
|
|
1411
|
+
w(g, "~N~Mprocedure Among_Handler (Context : in out Stemmer.Context_Type'Class; Operation : in Operation_Index; Result : out Boolean);~N");
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1415
|
+
static int has_string_variable(struct generator * g) {
|
|
1416
|
+
struct name * q;
|
|
1417
|
+
for (q = g->analyser->names; q; q = q->next) {
|
|
1418
|
+
g->V[0] = q;
|
|
1419
|
+
if (q->type == t_string) {
|
|
1420
|
+
return 1;
|
|
1421
|
+
}
|
|
1422
|
+
}
|
|
1423
|
+
|
|
1424
|
+
return 0;
|
|
1425
|
+
}
|
|
1426
|
+
|
|
1427
|
+
static void generate_member_decls(struct generator * g) {
|
|
1428
|
+
struct name * q;
|
|
1429
|
+
int count = 0;
|
|
1430
|
+
|
|
1431
|
+
|
|
1432
|
+
for (q = g->analyser->names; q; q = q->next) {
|
|
1433
|
+
if (q->type == t_string || q->type == t_integer || q->type == t_boolean)
|
|
1434
|
+
count++;
|
|
1435
|
+
}
|
|
1436
|
+
|
|
1437
|
+
w(g, " type Context_Type is new Stemmer.Context_Type with");
|
|
1438
|
+
if (count > 0) {
|
|
1439
|
+
w(g, " record~N~+");
|
|
1440
|
+
for (q = g->analyser->names; q; q = q->next) {
|
|
1441
|
+
g->V[0] = q;
|
|
1442
|
+
switch (q->type) {
|
|
1443
|
+
case t_string:
|
|
1444
|
+
w(g, "~M~W0 : Ada.Strings.Unbounded.Unbounded_String;~N");
|
|
1445
|
+
break;
|
|
1446
|
+
case t_integer:
|
|
1447
|
+
w(g, "~M~W0 : Integer;~N");
|
|
1448
|
+
break;
|
|
1449
|
+
case t_boolean:
|
|
1450
|
+
w(g, "~M~W0 : Boolean;~N");
|
|
1451
|
+
break;
|
|
1452
|
+
}
|
|
1453
|
+
}
|
|
1454
|
+
|
|
1455
|
+
w(g, "~-");
|
|
1456
|
+
w(g, "~- end record;~N");
|
|
1457
|
+
} else {
|
|
1458
|
+
w(g, " null record;~N");
|
|
1459
|
+
}
|
|
1460
|
+
}
|
|
1461
|
+
|
|
1462
|
+
static int generate_among_string(struct generator * g, struct among * x, int count) {
|
|
1463
|
+
int i;
|
|
1464
|
+
struct amongvec * v = x->b;
|
|
1465
|
+
int limit = count == 0 ? 38 : 80;
|
|
1466
|
+
|
|
1467
|
+
g->I[0] = x->number;
|
|
1468
|
+
|
|
1469
|
+
for (i = 0; i < x->literalstring_count; i++, v++) {
|
|
1470
|
+
/* Write among's string. */
|
|
1471
|
+
g->L[0] = v->b;
|
|
1472
|
+
g->I[1] = i;
|
|
1473
|
+
if (count + SIZE(v->b) > limit) {
|
|
1474
|
+
w(g, "~N~M& ");
|
|
1475
|
+
count = 3;
|
|
1476
|
+
limit = 80;
|
|
1477
|
+
} else if (count > 0) {
|
|
1478
|
+
w(g, " & ");
|
|
1479
|
+
}
|
|
1480
|
+
w(g, "~L0");
|
|
1481
|
+
count += SIZE(v->b) + 5;
|
|
1482
|
+
}
|
|
1483
|
+
return count;
|
|
1484
|
+
}
|
|
1485
|
+
|
|
1486
|
+
static int generate_among_table(struct generator * g, struct among * x, int start_pos, int *operation) {
|
|
1487
|
+
int i;
|
|
1488
|
+
struct amongvec * v = x->b;
|
|
1489
|
+
|
|
1490
|
+
g->I[0] = x->number;
|
|
1491
|
+
|
|
1492
|
+
g->I[1] = x->literalstring_count - 1;
|
|
1493
|
+
w(g, "~MA_~I0 : constant Among_Array_Type (0 .. ~I1) := ~+(~N");
|
|
1494
|
+
|
|
1495
|
+
v = x->b;
|
|
1496
|
+
for (i = 0; i < x->literalstring_count; i++, v++) {
|
|
1497
|
+
g->I[1] = start_pos;
|
|
1498
|
+
|
|
1499
|
+
/* Write among's string position. */
|
|
1500
|
+
if (x->literalstring_count == 1) {
|
|
1501
|
+
w(g, "~Mothers => (~I1, ");
|
|
1502
|
+
} else {
|
|
1503
|
+
w(g, "~M(~I1, ");
|
|
1504
|
+
}
|
|
1505
|
+
start_pos = start_pos + SIZE(v->b);
|
|
1506
|
+
g->I[1] = start_pos - 1;
|
|
1507
|
+
w(g, "~I1, ");
|
|
1508
|
+
|
|
1509
|
+
/* Write among's index & result. */
|
|
1510
|
+
g->I[2] = v->i;
|
|
1511
|
+
w(g, "~I2, ");
|
|
1512
|
+
g->I[2] = v->result;
|
|
1513
|
+
w(g, "~I2, ");
|
|
1514
|
+
|
|
1515
|
+
/* Write among's handler. */
|
|
1516
|
+
if (v->function == 0) {
|
|
1517
|
+
w(g, "0)");
|
|
1518
|
+
} else {
|
|
1519
|
+
*operation = *operation + 1;
|
|
1520
|
+
g->I[1] = *operation;
|
|
1521
|
+
w(g, "~I1)");
|
|
1522
|
+
}
|
|
1523
|
+
if (i + 1 < x->literalstring_count) {
|
|
1524
|
+
w(g, ",~N");
|
|
1525
|
+
}
|
|
1526
|
+
}
|
|
1527
|
+
w(g, ");~-~N~N");
|
|
1528
|
+
return start_pos;
|
|
1529
|
+
}
|
|
1530
|
+
|
|
1531
|
+
static int generate_amongs(struct generator * g) {
|
|
1532
|
+
struct among * a = g->analyser->amongs;
|
|
1533
|
+
int count;
|
|
1534
|
+
int start_pos;
|
|
1535
|
+
|
|
1536
|
+
w(g, "~MAmong_String : constant String := ~+");
|
|
1537
|
+
count = 0;
|
|
1538
|
+
while (a != 0) {
|
|
1539
|
+
count = generate_among_string(g, a, count);
|
|
1540
|
+
a = a->next;
|
|
1541
|
+
}
|
|
1542
|
+
w(g, ";~N~-~N");
|
|
1543
|
+
|
|
1544
|
+
int operation = 0;
|
|
1545
|
+
start_pos = 1;
|
|
1546
|
+
a = g->analyser->amongs;
|
|
1547
|
+
while (a != 0) {
|
|
1548
|
+
start_pos = generate_among_table(g, a, start_pos, &operation);
|
|
1549
|
+
a = a->next;
|
|
1550
|
+
}
|
|
1551
|
+
return operation;
|
|
1552
|
+
}
|
|
1553
|
+
|
|
1554
|
+
static int generate_constructor(struct generator * g) {
|
|
1555
|
+
return generate_amongs(g);
|
|
1556
|
+
}
|
|
1557
|
+
|
|
1558
|
+
static void generate_methods(struct generator * g) {
|
|
1559
|
+
struct node * p = g->analyser->program;
|
|
1560
|
+
while (p != 0) {
|
|
1561
|
+
generate(g, p);
|
|
1562
|
+
p = p->right;
|
|
1563
|
+
}
|
|
1564
|
+
}
|
|
1565
|
+
|
|
1566
|
+
static int generate_operations_dispatcher(struct generator * g) {
|
|
1567
|
+
struct among * a = g->analyser->amongs;
|
|
1568
|
+
int i;
|
|
1569
|
+
int operation = 0;
|
|
1570
|
+
|
|
1571
|
+
w(g, "~N~Mprocedure Among_Handler (Context : in out Stemmer.Context_Type'Class; Operation : in Operation_Index; Result : out Boolean) is~N");
|
|
1572
|
+
w(g, "~Mbegin~+~N~M");
|
|
1573
|
+
w(g, "case Operation is~+~N~M");
|
|
1574
|
+
a = g->analyser->amongs;
|
|
1575
|
+
while (a != 0) {
|
|
1576
|
+
struct amongvec * v = a->b;
|
|
1577
|
+
for (i = 0; i < a->literalstring_count; i++, v++) {
|
|
1578
|
+
if (v->function != 0) {
|
|
1579
|
+
operation++;
|
|
1580
|
+
g->I[2] = operation;
|
|
1581
|
+
w(g, "when ~I2 =>~N~M");
|
|
1582
|
+
g->V[0] = v->function;
|
|
1583
|
+
w(g, " ~W0 (Context_Type (Context), Result);~N~M");
|
|
1584
|
+
}
|
|
1585
|
+
}
|
|
1586
|
+
a = a->next;
|
|
1587
|
+
}
|
|
1588
|
+
w(g, "when others =>~N~M");
|
|
1589
|
+
w(g, " Result := False;~-~N~Mend case;~-~N~M");
|
|
1590
|
+
w(g, "end Among_Handler;~N~-");
|
|
1591
|
+
return operation;
|
|
1592
|
+
}
|
|
1593
|
+
|
|
1594
|
+
static void set_bit(symbol * b, int i) { b[i/8] |= 1 << i%8; }
|
|
1595
|
+
|
|
1596
|
+
static void generate_grouping_table(struct generator * g, struct grouping * q) {
|
|
1597
|
+
|
|
1598
|
+
int range = q->largest_ch - q->smallest_ch + 1;
|
|
1599
|
+
int size = (range + 7)/ 8; /* assume 8 bits per symbol */
|
|
1600
|
+
symbol * b = q->b;
|
|
1601
|
+
symbol * map = create_b(size);
|
|
1602
|
+
int i;
|
|
1603
|
+
int count = 0;
|
|
1604
|
+
int need_comma = 0;
|
|
1605
|
+
|
|
1606
|
+
for (i = 0; i < size; i++) map[i] = 0;
|
|
1607
|
+
|
|
1608
|
+
/* Using unicode would require revision here */
|
|
1609
|
+
|
|
1610
|
+
for (i = 0; i < SIZE(b); i++) set_bit(map, b[i] - q->smallest_ch);
|
|
1611
|
+
|
|
1612
|
+
g->V[0] = q->name;
|
|
1613
|
+
g->I[0] = 8 * size - 1;
|
|
1614
|
+
w(g, "~N~M~W0 : constant Grouping_Array (0 .. ~I0) := (~N~+~M");
|
|
1615
|
+
for (i = 0; i < size; i++) {
|
|
1616
|
+
unsigned char m = map[i];
|
|
1617
|
+
int j;
|
|
1618
|
+
count++;
|
|
1619
|
+
if (i != 0) {
|
|
1620
|
+
w(g, ",~N~M");
|
|
1621
|
+
need_comma = 0;
|
|
1622
|
+
}
|
|
1623
|
+
for (j = 0; j < 8; j++) {
|
|
1624
|
+
if (need_comma)
|
|
1625
|
+
w(g, ", ");
|
|
1626
|
+
|
|
1627
|
+
if (m & (1 << j)) {
|
|
1628
|
+
w(g, "True");
|
|
1629
|
+
} else {
|
|
1630
|
+
w(g, "False");
|
|
1631
|
+
}
|
|
1632
|
+
need_comma = 1;
|
|
1633
|
+
}
|
|
1634
|
+
}
|
|
1635
|
+
w(g, "~N~-~M);~N");
|
|
1636
|
+
|
|
1637
|
+
lose_b(map);
|
|
1638
|
+
}
|
|
1639
|
+
|
|
1640
|
+
static void generate_groupings(struct generator * g) {
|
|
1641
|
+
struct grouping * q;
|
|
1642
|
+
for (q = g->analyser->groupings; q; q = q->next) {
|
|
1643
|
+
if (q->name->used)
|
|
1644
|
+
generate_grouping_table(g, q);
|
|
1645
|
+
}
|
|
1646
|
+
}
|
|
1647
|
+
|
|
1648
|
+
extern void generate_program_ada(struct generator * g) {
|
|
1649
|
+
|
|
1650
|
+
g->outbuf = str_new();
|
|
1651
|
+
g->failure_str = str_new();
|
|
1652
|
+
|
|
1653
|
+
generate_unit_start(g);
|
|
1654
|
+
|
|
1655
|
+
/* generate implementation. */
|
|
1656
|
+
w(g, "package body Stemmer.");
|
|
1657
|
+
w(g, g->options->package);
|
|
1658
|
+
w(g, " is~N~+~N");
|
|
1659
|
+
w(g, "~Mpragma Style_Checks (\"-mr\");~N");
|
|
1660
|
+
w(g, "~Mpragma Warnings (Off, \"*variable*is never read and never assigned*\");~N");
|
|
1661
|
+
w(g, "~Mpragma Warnings (Off, \"*mode could be*instead of*\");~N");
|
|
1662
|
+
w(g, "~Mpragma Warnings (Off, \"*formal parameter.*is not modified*\");~N");
|
|
1663
|
+
w(g, "~Mpragma Warnings (Off, \"*this line is too long*\");~N");
|
|
1664
|
+
w(g, "~Mpragma Warnings (Off, \"*is not referenced*\");~N");
|
|
1665
|
+
w(g, "~N");
|
|
1666
|
+
|
|
1667
|
+
generate_method_decls(g, t_routine);
|
|
1668
|
+
generate_groupings(g);
|
|
1669
|
+
|
|
1670
|
+
int operations = generate_constructor(g);
|
|
1671
|
+
generate_methods(g);
|
|
1672
|
+
if (operations > 0) {
|
|
1673
|
+
generate_operations_dispatcher(g);
|
|
1674
|
+
}
|
|
1675
|
+
|
|
1676
|
+
w(g, "end Stemmer.");
|
|
1677
|
+
w(g, g->options->package);
|
|
1678
|
+
w(g, ";~N");
|
|
1679
|
+
|
|
1680
|
+
output_str(g->options->output_src, g->outbuf);
|
|
1681
|
+
|
|
1682
|
+
str_clear(g->outbuf);
|
|
1683
|
+
|
|
1684
|
+
g->margin = 0;
|
|
1685
|
+
write_start_comment(g, "-- ", NULL);
|
|
1686
|
+
if (has_string_variable(g)) {
|
|
1687
|
+
w(g, "private with Ada.Strings.Unbounded;~N");
|
|
1688
|
+
}
|
|
1689
|
+
w(g, "package Stemmer.");
|
|
1690
|
+
w(g, g->options->package);
|
|
1691
|
+
w(g, " with SPARK_Mode is~N~+");
|
|
1692
|
+
w(g, " type Context_Type is new Stemmer.Context_Type with private;~N");
|
|
1693
|
+
w(g, " procedure Stem (Z : in out Context_Type; Result : out Boolean);~N");
|
|
1694
|
+
w(g, "private~N");
|
|
1695
|
+
generate_member_decls(g);
|
|
1696
|
+
w(g, "end Stemmer.");
|
|
1697
|
+
w(g, g->options->package);
|
|
1698
|
+
w(g, ";~N");
|
|
1699
|
+
output_str(g->options->output_h, g->outbuf);
|
|
1700
|
+
str_delete(g->failure_str);
|
|
1701
|
+
str_delete(g->outbuf);
|
|
1702
|
+
}
|