mittens 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (137) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +3 -0
  3. data/Gemfile +7 -0
  4. data/LICENSE.txt +30 -0
  5. data/README.md +62 -0
  6. data/Rakefile +21 -0
  7. data/ext/mittens/ext.c +96 -0
  8. data/ext/mittens/extconf.rb +12 -0
  9. data/lib/mittens/version.rb +3 -0
  10. data/lib/mittens.rb +7 -0
  11. data/mittens.gemspec +22 -0
  12. data/vendor/snowball/.gitignore +26 -0
  13. data/vendor/snowball/.travis.yml +112 -0
  14. data/vendor/snowball/AUTHORS +27 -0
  15. data/vendor/snowball/CONTRIBUTING.rst +216 -0
  16. data/vendor/snowball/COPYING +29 -0
  17. data/vendor/snowball/GNUmakefile +742 -0
  18. data/vendor/snowball/NEWS +754 -0
  19. data/vendor/snowball/README.rst +37 -0
  20. data/vendor/snowball/ada/README.md +74 -0
  21. data/vendor/snowball/ada/generate/generate.adb +83 -0
  22. data/vendor/snowball/ada/generate.gpr +21 -0
  23. data/vendor/snowball/ada/src/stemmer.adb +620 -0
  24. data/vendor/snowball/ada/src/stemmer.ads +219 -0
  25. data/vendor/snowball/ada/src/stemwords.adb +70 -0
  26. data/vendor/snowball/ada/stemmer_config.gpr +83 -0
  27. data/vendor/snowball/ada/stemwords.gpr +21 -0
  28. data/vendor/snowball/algorithms/arabic.sbl +558 -0
  29. data/vendor/snowball/algorithms/armenian.sbl +301 -0
  30. data/vendor/snowball/algorithms/basque.sbl +149 -0
  31. data/vendor/snowball/algorithms/catalan.sbl +202 -0
  32. data/vendor/snowball/algorithms/danish.sbl +93 -0
  33. data/vendor/snowball/algorithms/dutch.sbl +164 -0
  34. data/vendor/snowball/algorithms/english.sbl +229 -0
  35. data/vendor/snowball/algorithms/finnish.sbl +197 -0
  36. data/vendor/snowball/algorithms/french.sbl +254 -0
  37. data/vendor/snowball/algorithms/german.sbl +139 -0
  38. data/vendor/snowball/algorithms/german2.sbl +145 -0
  39. data/vendor/snowball/algorithms/greek.sbl +701 -0
  40. data/vendor/snowball/algorithms/hindi.sbl +323 -0
  41. data/vendor/snowball/algorithms/hungarian.sbl +241 -0
  42. data/vendor/snowball/algorithms/indonesian.sbl +192 -0
  43. data/vendor/snowball/algorithms/irish.sbl +149 -0
  44. data/vendor/snowball/algorithms/italian.sbl +202 -0
  45. data/vendor/snowball/algorithms/kraaij_pohlmann.sbl +240 -0
  46. data/vendor/snowball/algorithms/lithuanian.sbl +373 -0
  47. data/vendor/snowball/algorithms/lovins.sbl +208 -0
  48. data/vendor/snowball/algorithms/nepali.sbl +92 -0
  49. data/vendor/snowball/algorithms/norwegian.sbl +80 -0
  50. data/vendor/snowball/algorithms/porter.sbl +139 -0
  51. data/vendor/snowball/algorithms/portuguese.sbl +218 -0
  52. data/vendor/snowball/algorithms/romanian.sbl +236 -0
  53. data/vendor/snowball/algorithms/russian.sbl +221 -0
  54. data/vendor/snowball/algorithms/serbian.sbl +2379 -0
  55. data/vendor/snowball/algorithms/spanish.sbl +230 -0
  56. data/vendor/snowball/algorithms/swedish.sbl +72 -0
  57. data/vendor/snowball/algorithms/tamil.sbl +405 -0
  58. data/vendor/snowball/algorithms/turkish.sbl +470 -0
  59. data/vendor/snowball/algorithms/yiddish.sbl +460 -0
  60. data/vendor/snowball/charsets/ISO-8859-2.sbl +98 -0
  61. data/vendor/snowball/charsets/KOI8-R.sbl +74 -0
  62. data/vendor/snowball/charsets/cp850.sbl +130 -0
  63. data/vendor/snowball/compiler/analyser.c +1547 -0
  64. data/vendor/snowball/compiler/driver.c +615 -0
  65. data/vendor/snowball/compiler/generator.c +1748 -0
  66. data/vendor/snowball/compiler/generator_ada.c +1702 -0
  67. data/vendor/snowball/compiler/generator_csharp.c +1322 -0
  68. data/vendor/snowball/compiler/generator_go.c +1278 -0
  69. data/vendor/snowball/compiler/generator_java.c +1313 -0
  70. data/vendor/snowball/compiler/generator_js.c +1316 -0
  71. data/vendor/snowball/compiler/generator_pascal.c +1387 -0
  72. data/vendor/snowball/compiler/generator_python.c +1337 -0
  73. data/vendor/snowball/compiler/generator_rust.c +1295 -0
  74. data/vendor/snowball/compiler/header.h +418 -0
  75. data/vendor/snowball/compiler/space.c +286 -0
  76. data/vendor/snowball/compiler/syswords.h +86 -0
  77. data/vendor/snowball/compiler/syswords2.h +13 -0
  78. data/vendor/snowball/compiler/tokeniser.c +567 -0
  79. data/vendor/snowball/csharp/.gitignore +8 -0
  80. data/vendor/snowball/csharp/Snowball/Algorithms/.gitignore +1 -0
  81. data/vendor/snowball/csharp/Snowball/Among.cs +108 -0
  82. data/vendor/snowball/csharp/Snowball/AssemblyInfo.cs +36 -0
  83. data/vendor/snowball/csharp/Snowball/Stemmer.cs +660 -0
  84. data/vendor/snowball/csharp/Stemwords/App.config +6 -0
  85. data/vendor/snowball/csharp/Stemwords/Program.cs +114 -0
  86. data/vendor/snowball/doc/TODO +12 -0
  87. data/vendor/snowball/doc/libstemmer_c_README +148 -0
  88. data/vendor/snowball/doc/libstemmer_csharp_README +53 -0
  89. data/vendor/snowball/doc/libstemmer_java_README +67 -0
  90. data/vendor/snowball/doc/libstemmer_js_README +48 -0
  91. data/vendor/snowball/doc/libstemmer_python_README +113 -0
  92. data/vendor/snowball/examples/stemwords.c +204 -0
  93. data/vendor/snowball/go/README.md +55 -0
  94. data/vendor/snowball/go/among.go +16 -0
  95. data/vendor/snowball/go/env.go +403 -0
  96. data/vendor/snowball/go/stemwords/generate.go +68 -0
  97. data/vendor/snowball/go/stemwords/main.go +68 -0
  98. data/vendor/snowball/go/util.go +34 -0
  99. data/vendor/snowball/iconv.py +50 -0
  100. data/vendor/snowball/include/libstemmer.h +78 -0
  101. data/vendor/snowball/java/org/tartarus/snowball/Among.java +29 -0
  102. data/vendor/snowball/java/org/tartarus/snowball/SnowballProgram.java +381 -0
  103. data/vendor/snowball/java/org/tartarus/snowball/SnowballStemmer.java +8 -0
  104. data/vendor/snowball/java/org/tartarus/snowball/TestApp.java +75 -0
  105. data/vendor/snowball/javascript/base-stemmer.js +294 -0
  106. data/vendor/snowball/javascript/stemwords.js +106 -0
  107. data/vendor/snowball/libstemmer/libstemmer_c.in +96 -0
  108. data/vendor/snowball/libstemmer/mkalgorithms.pl +90 -0
  109. data/vendor/snowball/libstemmer/mkmodules.pl +267 -0
  110. data/vendor/snowball/libstemmer/modules.txt +63 -0
  111. data/vendor/snowball/libstemmer/test.c +34 -0
  112. data/vendor/snowball/pascal/.gitignore +4 -0
  113. data/vendor/snowball/pascal/SnowballProgram.pas +430 -0
  114. data/vendor/snowball/pascal/generate.pl +23 -0
  115. data/vendor/snowball/pascal/stemwords-template.dpr +78 -0
  116. data/vendor/snowball/python/MANIFEST.in +7 -0
  117. data/vendor/snowball/python/create_init.py +54 -0
  118. data/vendor/snowball/python/setup.cfg +6 -0
  119. data/vendor/snowball/python/setup.py +81 -0
  120. data/vendor/snowball/python/snowballstemmer/among.py +13 -0
  121. data/vendor/snowball/python/snowballstemmer/basestemmer.py +323 -0
  122. data/vendor/snowball/python/stemwords.py +101 -0
  123. data/vendor/snowball/python/testapp.py +28 -0
  124. data/vendor/snowball/runtime/api.c +58 -0
  125. data/vendor/snowball/runtime/api.h +32 -0
  126. data/vendor/snowball/runtime/header.h +61 -0
  127. data/vendor/snowball/runtime/utilities.c +513 -0
  128. data/vendor/snowball/rust/Cargo.toml +7 -0
  129. data/vendor/snowball/rust/build.rs +55 -0
  130. data/vendor/snowball/rust/rust-pre-1.27-compat.patch +30 -0
  131. data/vendor/snowball/rust/src/main.rs +102 -0
  132. data/vendor/snowball/rust/src/snowball/algorithms/mod.rs +2 -0
  133. data/vendor/snowball/rust/src/snowball/among.rs +6 -0
  134. data/vendor/snowball/rust/src/snowball/mod.rs +6 -0
  135. data/vendor/snowball/rust/src/snowball/snowball_env.rs +421 -0
  136. data/vendor/snowball/tests/stemtest.c +95 -0
  137. metadata +178 -0
@@ -0,0 +1,1313 @@
1
+
2
+ #include <stdlib.h> /* for exit */
3
+ #include <string.h> /* for strlen */
4
+ #include <stdio.h> /* for fprintf etc */
5
+ #include "header.h"
6
+
7
+ /* prototypes */
8
+
9
+ static void generate(struct generator * g, struct node * p);
10
+ static void w(struct generator * g, const char * s);
11
+ static void writef(struct generator * g, const char * s, struct node * p);
12
+
13
+ static int new_label(struct generator * g) {
14
+ return g->next_label++;
15
+ }
16
+
17
+ static struct str * vars_newname(struct generator * g) {
18
+
19
+ struct str * output;
20
+ g->var_number++;
21
+ output = str_new();
22
+ str_append_string(output, "v_");
23
+ str_append_int(output, g->var_number);
24
+ return output;
25
+ }
26
+
27
+
28
+ /* Write routines for items from the syntax tree */
29
+
30
+ static void write_varname(struct generator * g, struct name * p) {
31
+
32
+ int ch = "SBIrxg"[p->type];
33
+ if (p->type != t_external) {
34
+ write_char(g, ch);
35
+ write_char(g, '_');
36
+ }
37
+ write_b(g, p->b);
38
+ }
39
+
40
+ static void write_varref(struct generator * g, struct name * p) {
41
+
42
+ /* In java, references look just the same */
43
+ write_varname(g, p);
44
+ }
45
+
46
+ static void write_hexdigit(struct generator * g, int n) {
47
+
48
+ write_char(g, n < 10 ? n + '0' : n - 10 + 'A');
49
+ }
50
+
51
+ static void write_hex(struct generator * g, int ch) {
52
+
53
+ write_string(g, "\\u");
54
+ {
55
+ int i;
56
+ for (i = 12; i >= 0; i -= 4) write_hexdigit(g, ch >> i & 0xf);
57
+ }
58
+ }
59
+
60
+ static void write_literal_string(struct generator * g, symbol * p) {
61
+
62
+ int i;
63
+ write_string(g, "\"");
64
+ for (i = 0; i < SIZE(p); i++) {
65
+ int ch = p[i];
66
+ if (32 <= ch && ch < 127) {
67
+ if (ch == '\"' || ch == '\\') write_string(g, "\\");
68
+ write_char(g, ch);
69
+ } else {
70
+ write_hex(g, ch);
71
+ }
72
+ }
73
+ write_string(g, "\"");
74
+ }
75
+
76
+ static void write_margin(struct generator * g) {
77
+
78
+ int i;
79
+ for (i = 0; i < g->margin; i++) write_string(g, " ");
80
+ }
81
+
82
+ static void write_comment(struct generator * g, struct node * p) {
83
+ if (!g->options->comments) return;
84
+ write_margin(g);
85
+ write_string(g, "// ");
86
+ write_comment_content(g, p);
87
+ write_newline(g);
88
+ }
89
+
90
+ static void write_block_start(struct generator * g) {
91
+
92
+ w(g, "~M{~+~N");
93
+ }
94
+
95
+ static void write_block_end(struct generator * g) /* block end */ {
96
+
97
+ w(g, "~-~M}~N");
98
+ }
99
+
100
+ static void write_savecursor(struct generator * g, struct node * p,
101
+ struct str * savevar) {
102
+
103
+ g->B[0] = str_data(savevar);
104
+ g->S[1] = "";
105
+ if (p->mode != m_forward) g->S[1] = "limit - ";
106
+ writef(g, "~Mint ~B0 = ~S1cursor;~N", p);
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, "cursor = ");
113
+ if (p->mode != m_forward) str_append_string(out, "limit - ");
114
+ str_append(out, savevar);
115
+ str_append_string(out, ";");
116
+ }
117
+
118
+ static void write_restorecursor(struct generator * g, struct node * p,
119
+ struct str * savevar) {
120
+
121
+ struct str * temp = str_new();
122
+ write_margin(g);
123
+ restore_string(p, temp, savevar);
124
+ write_str(g, temp);
125
+ write_newline(g);
126
+ str_delete(temp);
127
+ }
128
+
129
+ static void write_inc_cursor(struct generator * g, struct node * p) {
130
+
131
+ write_margin(g);
132
+ write_string(g, p->mode == m_forward ? "cursor++;" : "cursor--;");
133
+ write_newline(g);
134
+ }
135
+
136
+ static void wsetlab_begin(struct generator * g, int n) {
137
+
138
+ w(g, "~Mlab");
139
+ write_int(g, n);
140
+ w(g, ": {~+~N");
141
+ }
142
+
143
+ static void wsetlab_end(struct generator * g) {
144
+
145
+ w(g, "~-~M}~N");
146
+ }
147
+
148
+ static void wgotol(struct generator * g, int n) {
149
+
150
+ write_margin(g);
151
+ write_string(g, "break lab");
152
+ write_int(g, n);
153
+ write_string(g, ";");
154
+ write_newline(g);
155
+ }
156
+
157
+ static void write_failure(struct generator * g) {
158
+
159
+ if (str_len(g->failure_str) != 0) {
160
+ write_margin(g);
161
+ write_str(g, g->failure_str);
162
+ write_newline(g);
163
+ }
164
+ write_margin(g);
165
+ switch (g->failure_label) {
166
+ case x_return:
167
+ write_string(g, "return false;");
168
+ g->unreachable = true;
169
+ break;
170
+ default:
171
+ write_string(g, "break lab");
172
+ write_int(g, g->failure_label);
173
+ write_string(g, ";");
174
+ g->unreachable = true;
175
+ }
176
+ write_newline(g);
177
+ }
178
+
179
+ static void write_failure_if(struct generator * g, char * s, struct node * p) {
180
+
181
+ writef(g, "~Mif (", p);
182
+ writef(g, s, p);
183
+ writef(g, ")~N", p);
184
+ write_block_start(g);
185
+ write_failure(g);
186
+ write_block_end(g);
187
+ g->unreachable = false;
188
+ }
189
+
190
+ /* if at limit fail */
191
+ static void write_check_limit(struct generator * g, struct node * p) {
192
+
193
+ if (p->mode == m_forward) {
194
+ write_failure_if(g, "cursor >= limit", p);
195
+ } else {
196
+ write_failure_if(g, "cursor <= limit_backward", p);
197
+ }
198
+ }
199
+
200
+ /* Formatted write. */
201
+ static void writef(struct generator * g, const char * input, struct node * p) {
202
+ int i = 0;
203
+ int l = strlen(input);
204
+
205
+ while (i < l) {
206
+ int ch = input[i++];
207
+ if (ch != '~') {
208
+ write_char(g, ch);
209
+ continue;
210
+ }
211
+ switch (input[i++]) {
212
+ default: write_char(g, input[i - 1]); continue;
213
+ case 'C': write_comment(g, p); continue;
214
+ case 'f': write_block_start(g);
215
+ write_failure(g);
216
+ g->unreachable = false;
217
+ write_block_end(g);
218
+ continue;
219
+ case 'M': write_margin(g); continue;
220
+ case 'N': write_newline(g); continue;
221
+ case '{': write_block_start(g); continue;
222
+ case '}': write_block_end(g); continue;
223
+ case 'S': write_string(g, g->S[input[i++] - '0']); continue;
224
+ case 'B': write_b(g, g->B[input[i++] - '0']); continue;
225
+ case 'I': write_int(g, g->I[input[i++] - '0']); continue;
226
+ case 'V': write_varref(g, g->V[input[i++] - '0']); continue;
227
+ case 'W': write_varname(g, g->V[input[i++] - '0']); continue;
228
+ case 'L': write_literal_string(g, g->L[input[i++] - '0']); continue;
229
+ case '+': g->margin++; continue;
230
+ case '-': g->margin--; continue;
231
+ case 'n': write_string(g, g->options->name); continue;
232
+ }
233
+ }
234
+ }
235
+
236
+ static void w(struct generator * g, const char * s) {
237
+ writef(g, s, 0);
238
+ }
239
+
240
+ static void generate_AE(struct generator * g, struct node * p) {
241
+ const char * s;
242
+ switch (p->type) {
243
+ case c_name:
244
+ write_varref(g, p->name); break;
245
+ case c_number:
246
+ write_int(g, p->number); break;
247
+ case c_maxint:
248
+ write_string(g, "Integer.MAX_VALUE"); break;
249
+ case c_minint:
250
+ write_string(g, "Integer.MIN_VALUE"); break;
251
+ case c_neg:
252
+ write_char(g, '-'); generate_AE(g, p->right); break;
253
+ case c_multiply:
254
+ s = " * "; goto label0;
255
+ case c_plus:
256
+ s = " + "; goto label0;
257
+ case c_minus:
258
+ s = " - "; goto label0;
259
+ case c_divide:
260
+ s = " / ";
261
+ label0:
262
+ write_char(g, '('); generate_AE(g, p->left);
263
+ write_string(g, s); generate_AE(g, p->right); write_char(g, ')'); break;
264
+ case c_cursor:
265
+ w(g, "cursor"); break;
266
+ case c_limit:
267
+ w(g, p->mode == m_forward ? "limit" : "limit_backward"); break;
268
+ case c_lenof: /* Same as sizeof() for Java. */
269
+ case c_sizeof:
270
+ g->V[0] = p->name;
271
+ w(g, "~V0.length()");
272
+ break;
273
+ case c_len: /* Same as size() for Java. */
274
+ case c_size:
275
+ w(g, "current.length()");
276
+ break;
277
+ }
278
+ }
279
+
280
+ static void generate_bra(struct generator * g, struct node * p) {
281
+
282
+ write_comment(g, p);
283
+ p = p->left;
284
+ while (p) {
285
+ generate(g, p);
286
+ p = p->right;
287
+ }
288
+ }
289
+
290
+ static void generate_and(struct generator * g, struct node * p) {
291
+
292
+ struct str * savevar = vars_newname(g);
293
+ int keep_c = K_needed(g, p->left);
294
+
295
+ write_comment(g, p);
296
+
297
+ if (keep_c) write_savecursor(g, p, savevar);
298
+
299
+ p = p->left;
300
+ while (p) {
301
+ generate(g, p);
302
+ if (g->unreachable) break;
303
+ if (keep_c && p->right != 0) write_restorecursor(g, p, savevar);
304
+ p = p->right;
305
+ }
306
+ str_delete(savevar);
307
+ }
308
+
309
+ static void generate_or(struct generator * g, struct node * p) {
310
+
311
+ struct str * savevar = vars_newname(g);
312
+ int keep_c = K_needed(g, p->left);
313
+
314
+ int a0 = g->failure_label;
315
+ struct str * a1 = str_copy(g->failure_str);
316
+
317
+ int out_lab = new_label(g);
318
+ int end_unreachable = true;
319
+
320
+ write_comment(g, p);
321
+ wsetlab_begin(g, out_lab);
322
+
323
+ if (keep_c) write_savecursor(g, p, savevar);
324
+
325
+ p = p->left;
326
+ str_clear(g->failure_str);
327
+
328
+ if (p == 0) {
329
+ /* p should never be 0 after an or: there should be at least two
330
+ * sub nodes. */
331
+ fprintf(stderr, "Error: \"or\" node without children nodes.");
332
+ exit(1);
333
+ }
334
+ while (p->right != 0) {
335
+ g->failure_label = new_label(g);
336
+ wsetlab_begin(g, g->failure_label);
337
+ generate(g, p);
338
+ if (!g->unreachable) {
339
+ wgotol(g, out_lab);
340
+ end_unreachable = false;
341
+ }
342
+ wsetlab_end(g);
343
+ g->unreachable = false;
344
+ if (keep_c) write_restorecursor(g, p, savevar);
345
+ p = p->right;
346
+ }
347
+
348
+ g->failure_label = a0;
349
+ str_delete(g->failure_str);
350
+ g->failure_str = a1;
351
+
352
+ generate(g, p);
353
+ wsetlab_end(g);
354
+ if (!end_unreachable) {
355
+ g->unreachable = false;
356
+ }
357
+ str_delete(savevar);
358
+ }
359
+
360
+ static void generate_backwards(struct generator * g, struct node * p) {
361
+
362
+ write_comment(g, p);
363
+ writef(g, "~Mlimit_backward = cursor;~N"
364
+ "~Mcursor = limit;~N", p);
365
+ generate(g, p->left);
366
+ w(g, "~Mcursor = limit_backward;~N");
367
+ }
368
+
369
+
370
+ static void generate_not(struct generator * g, struct node * p) {
371
+
372
+ struct str * savevar = vars_newname(g);
373
+ int keep_c = K_needed(g, p->left);
374
+
375
+ int a0 = g->failure_label;
376
+ struct str * a1 = str_copy(g->failure_str);
377
+
378
+ write_comment(g, p);
379
+ if (keep_c) {
380
+ write_block_start(g);
381
+ write_savecursor(g, p, savevar);
382
+ }
383
+
384
+ g->failure_label = new_label(g);
385
+ str_clear(g->failure_str);
386
+
387
+ wsetlab_begin(g, g->failure_label);
388
+
389
+ generate(g, p->left);
390
+
391
+ g->failure_label = a0;
392
+ str_delete(g->failure_str);
393
+ g->failure_str = a1;
394
+
395
+ if (!g->unreachable) write_failure(g);
396
+
397
+ wsetlab_end(g);
398
+ g->unreachable = false;
399
+
400
+ if (keep_c) write_restorecursor(g, p, savevar);
401
+ if (keep_c) write_block_end(g);
402
+ str_delete(savevar);
403
+ }
404
+
405
+
406
+ static void generate_try(struct generator * g, struct node * p) {
407
+
408
+ struct str * savevar = vars_newname(g);
409
+ int keep_c = K_needed(g, p->left);
410
+
411
+ write_comment(g, p);
412
+ if (keep_c) write_savecursor(g, p, savevar);
413
+
414
+ g->failure_label = new_label(g);
415
+ str_clear(g->failure_str);
416
+ if (keep_c) restore_string(p, g->failure_str, savevar);
417
+
418
+ wsetlab_begin(g, g->failure_label);
419
+ generate(g, p->left);
420
+ wsetlab_end(g);
421
+ g->unreachable = false;
422
+
423
+ str_delete(savevar);
424
+ }
425
+
426
+ static void generate_set(struct generator * g, struct node * p) {
427
+
428
+ write_comment(g, p);
429
+ g->V[0] = p->name;
430
+ writef(g, "~M~V0 = true;~N", p);
431
+ }
432
+
433
+ static void generate_unset(struct generator * g, struct node * p) {
434
+
435
+ write_comment(g, p);
436
+ g->V[0] = p->name;
437
+ writef(g, "~M~V0 = false;~N", p);
438
+ }
439
+
440
+ static void generate_fail(struct generator * g, struct node * p) {
441
+
442
+ write_comment(g, p);
443
+ generate(g, p->left);
444
+ if (!g->unreachable) write_failure(g);
445
+ }
446
+
447
+ /* generate_test() also implements 'reverse' */
448
+
449
+ static void generate_test(struct generator * g, struct node * p) {
450
+
451
+ struct str * savevar = vars_newname(g);
452
+ int keep_c = K_needed(g, p->left);
453
+
454
+ write_comment(g, p);
455
+
456
+ if (keep_c) {
457
+ write_savecursor(g, p, savevar);
458
+ }
459
+
460
+ generate(g, p->left);
461
+
462
+ if (!g->unreachable) {
463
+ if (keep_c) {
464
+ write_restorecursor(g, p, savevar);
465
+ }
466
+ }
467
+ str_delete(savevar);
468
+ }
469
+
470
+ static void generate_do(struct generator * g, struct node * p) {
471
+
472
+ struct str * savevar = vars_newname(g);
473
+ int keep_c = K_needed(g, p->left);
474
+ write_comment(g, p);
475
+ if (keep_c) write_savecursor(g, p, savevar);
476
+
477
+ if (p->left->type == c_call) {
478
+ /* Optimise do <call> */
479
+ write_comment(g, p->left);
480
+ g->V[0] = p->left->name;
481
+ w(g, "~M~V0();~N");
482
+ } else {
483
+ g->failure_label = new_label(g);
484
+ str_clear(g->failure_str);
485
+
486
+ wsetlab_begin(g, g->failure_label);
487
+ generate(g, p->left);
488
+ wsetlab_end(g);
489
+ g->unreachable = false;
490
+ }
491
+
492
+ if (keep_c) write_restorecursor(g, p, savevar);
493
+ str_delete(savevar);
494
+ }
495
+
496
+ static void generate_GO(struct generator * g, struct node * p, int style) {
497
+
498
+ int end_unreachable = false;
499
+ struct str * savevar = vars_newname(g);
500
+ int keep_c = style == 1 || repeat_restore(g, p->left);
501
+
502
+ int a0 = g->failure_label;
503
+ struct str * a1 = str_copy(g->failure_str);
504
+
505
+ int golab = new_label(g);
506
+ g->I[0] = golab;
507
+ write_comment(g, p);
508
+ w(g, "~Mgolab~I0: while(true)~N");
509
+ w(g, "~{");
510
+
511
+ if (keep_c) write_savecursor(g, p, savevar);
512
+
513
+ g->failure_label = new_label(g);
514
+ str_clear(g->failure_str);
515
+ wsetlab_begin(g, g->failure_label);
516
+ generate(g, p->left);
517
+
518
+ if (g->unreachable) {
519
+ /* Cannot break out of this loop: therefore the code after the
520
+ * end of the loop is unreachable.*/
521
+ end_unreachable = true;
522
+ } else {
523
+ /* include for goto; omit for gopast */
524
+ if (style == 1) write_restorecursor(g, p, savevar);
525
+ g->I[0] = golab;
526
+ w(g, "~Mbreak golab~I0;~N");
527
+ }
528
+ g->unreachable = false;
529
+ wsetlab_end(g);
530
+ if (keep_c) write_restorecursor(g, p, savevar);
531
+
532
+ g->failure_label = a0;
533
+ str_delete(g->failure_str);
534
+ g->failure_str = a1;
535
+
536
+ write_check_limit(g, p);
537
+ write_inc_cursor(g, p);
538
+ write_block_end(g);
539
+ str_delete(savevar);
540
+ g->unreachable = end_unreachable;
541
+ }
542
+
543
+ static void generate_loop(struct generator * g, struct node * p) {
544
+
545
+ struct str * loopvar = vars_newname(g);
546
+ write_comment(g, p);
547
+ g->B[0] = str_data(loopvar);
548
+ w(g, "~Mfor (int ~B0 = ");
549
+ generate_AE(g, p->AE);
550
+ g->B[0] = str_data(loopvar);
551
+ writef(g, "; ~B0 > 0; ~B0--)~N", p);
552
+ writef(g, "~{", p);
553
+
554
+ generate(g, p->left);
555
+
556
+ w(g, "~}");
557
+ str_delete(loopvar);
558
+ g->unreachable = false;
559
+ }
560
+
561
+ static void generate_repeat_or_atleast(struct generator * g, struct node * p, struct str * loopvar) {
562
+
563
+ struct str * savevar = vars_newname(g);
564
+ int keep_c = repeat_restore(g, p->left);
565
+ writef(g, "~Mwhile(true)~N~{", p);
566
+
567
+ if (keep_c) write_savecursor(g, p, savevar);
568
+
569
+ g->failure_label = new_label(g);
570
+ str_clear(g->failure_str);
571
+ wsetlab_begin(g, g->failure_label);
572
+ generate(g, p->left);
573
+
574
+ if (!g->unreachable) {
575
+ if (loopvar != 0) {
576
+ g->B[0] = str_data(loopvar);
577
+ w(g, "~M~B0--;~N");
578
+ }
579
+
580
+ w(g, "~Mcontinue;~N");
581
+ }
582
+
583
+ wsetlab_end(g);
584
+ g->unreachable = false;
585
+
586
+ if (keep_c) write_restorecursor(g, p, savevar);
587
+
588
+ w(g, "~Mbreak;~N~}");
589
+ str_delete(savevar);
590
+ }
591
+
592
+ static void generate_repeat(struct generator * g, struct node * p) {
593
+ write_comment(g, p);
594
+ generate_repeat_or_atleast(g, p, NULL);
595
+ }
596
+
597
+ static void generate_atleast(struct generator * g, struct node * p) {
598
+
599
+ struct str * loopvar = vars_newname(g);
600
+ write_comment(g, p);
601
+ w(g, "~{");
602
+ g->B[0] = str_data(loopvar);
603
+ w(g, "~Mint ~B0 = ");
604
+ generate_AE(g, p->AE);
605
+ w(g, ";~N");
606
+ {
607
+ int a0 = g->failure_label;
608
+ struct str * a1 = str_copy(g->failure_str);
609
+
610
+ generate_repeat_or_atleast(g, p, loopvar);
611
+
612
+ g->failure_label = a0;
613
+ str_delete(g->failure_str);
614
+ g->failure_str = a1;
615
+ }
616
+ g->B[0] = str_data(loopvar);
617
+ write_failure_if(g, "~B0 > 0", p);
618
+ w(g, "~}");
619
+ str_delete(loopvar);
620
+ }
621
+
622
+ static void generate_setmark(struct generator * g, struct node * p) {
623
+
624
+ write_comment(g, p);
625
+ g->V[0] = p->name;
626
+ writef(g, "~M~V0 = cursor;~N", p);
627
+ }
628
+
629
+ static void generate_tomark(struct generator * g, struct node * p) {
630
+
631
+ write_comment(g, p);
632
+ g->S[0] = p->mode == m_forward ? ">" : "<";
633
+
634
+ w(g, "~Mif (cursor ~S0 "); generate_AE(g, p->AE); w(g, ")~N");
635
+ write_block_start(g);
636
+ write_failure(g);
637
+ write_block_end(g);
638
+ g->unreachable = false;
639
+ w(g, "~Mcursor = "); generate_AE(g, p->AE); writef(g, ";~N", p);
640
+ }
641
+
642
+ static void generate_atmark(struct generator * g, struct node * p) {
643
+
644
+ write_comment(g, p);
645
+ w(g, "~Mif (cursor != "); generate_AE(g, p->AE); writef(g, ")~N", p);
646
+ write_block_start(g);
647
+ write_failure(g);
648
+ write_block_end(g);
649
+ g->unreachable = false;
650
+ }
651
+
652
+ static void generate_hop(struct generator * g, struct node * p) {
653
+
654
+ write_comment(g, p);
655
+ g->S[0] = p->mode == m_forward ? "+" : "-";
656
+
657
+ w(g, "~{~Mint c = cursor ~S0 ");
658
+ generate_AE(g, p->AE);
659
+ w(g, ";~N");
660
+
661
+ g->S[1] = p->mode == m_forward ? "> limit" : "< limit_backward";
662
+ g->S[2] = p->mode == m_forward ? "<" : ">";
663
+ if (p->AE->type == c_number) {
664
+ // Constant distance hop.
665
+ //
666
+ // No need to check for negative hop as that's converted to false by
667
+ // the analyser.
668
+ write_failure_if(g, "c ~S1", p);
669
+ } else {
670
+ write_failure_if(g, "c ~S1 || c ~S2 cursor", p);
671
+ }
672
+ writef(g, "~Mcursor = c;~N", p);
673
+ writef(g, "~}", p);
674
+ }
675
+
676
+ static void generate_delete(struct generator * g, struct node * p) {
677
+
678
+ write_comment(g, p);
679
+ writef(g, "~Mslice_del();~N", p);
680
+ }
681
+
682
+
683
+ static void generate_next(struct generator * g, struct node * p) {
684
+
685
+ write_comment(g, p);
686
+ write_check_limit(g, p);
687
+ write_inc_cursor(g, p);
688
+ }
689
+
690
+ static void generate_tolimit(struct generator * g, struct node * p) {
691
+
692
+ write_comment(g, p);
693
+ g->S[0] = p->mode == m_forward ? "limit" : "limit_backward";
694
+ writef(g, "~Mcursor = ~S0;~N", p);
695
+ }
696
+
697
+ static void generate_atlimit(struct generator * g, struct node * p) {
698
+
699
+ write_comment(g, p);
700
+ g->S[0] = p->mode == m_forward ? "limit" : "limit_backward";
701
+ g->S[1] = p->mode == m_forward ? "<" : ">";
702
+ write_failure_if(g, "cursor ~S1 ~S0", p);
703
+ }
704
+
705
+ static void generate_leftslice(struct generator * g, struct node * p) {
706
+
707
+ write_comment(g, p);
708
+ g->S[0] = p->mode == m_forward ? "bra" : "ket";
709
+ writef(g, "~M~S0 = cursor;~N", p);
710
+ }
711
+
712
+ static void generate_rightslice(struct generator * g, struct node * p) {
713
+
714
+ write_comment(g, p);
715
+ g->S[0] = p->mode == m_forward ? "ket" : "bra";
716
+ writef(g, "~M~S0 = cursor;~N", p);
717
+ }
718
+
719
+ static void generate_assignto(struct generator * g, struct node * p) {
720
+
721
+ write_comment(g, p);
722
+ g->V[0] = p->name;
723
+ writef(g, "~Massign_to(~V0);~N", p);
724
+ }
725
+
726
+ static void generate_sliceto(struct generator * g, struct node * p) {
727
+
728
+ write_comment(g, p);
729
+ g->V[0] = p->name;
730
+ writef(g, "~Mslice_to(~V0);~N", p);
731
+ }
732
+
733
+ static void generate_address(struct generator * g, struct node * p) {
734
+
735
+ symbol * b = p->literalstring;
736
+ if (b != 0) {
737
+ write_literal_string(g, b);
738
+ } else {
739
+ write_varref(g, p->name);
740
+ }
741
+ }
742
+
743
+ static void generate_insert(struct generator * g, struct node * p, int style) {
744
+
745
+ int keep_c = style == c_attach;
746
+ write_comment(g, p);
747
+ if (p->mode == m_backward) keep_c = !keep_c;
748
+ if (keep_c) w(g, "~{~Mint c = cursor;~N");
749
+ writef(g, "~Minsert(cursor, cursor, ", p);
750
+ generate_address(g, p);
751
+ writef(g, ");~N", p);
752
+ if (keep_c) w(g, "~Mcursor = c;~N~}");
753
+ }
754
+
755
+ static void generate_assignfrom(struct generator * g, struct node * p) {
756
+
757
+ int keep_c = p->mode == m_forward; /* like 'attach' */
758
+
759
+ write_comment(g, p);
760
+ if (keep_c) writef(g, "~{~Mint c = cursor;~N", p);
761
+ if (p->mode == m_forward) {
762
+ writef(g, "~Minsert(cursor, limit, ", p);
763
+ } else {
764
+ writef(g, "~Minsert(limit_backward, cursor, ", p);
765
+ }
766
+ generate_address(g, p);
767
+ writef(g, ");~N", p);
768
+ if (keep_c) w(g, "~Mcursor = c;~N~}");
769
+ }
770
+
771
+
772
+ static void generate_slicefrom(struct generator * g, struct node * p) {
773
+
774
+ write_comment(g, p);
775
+ w(g, "~Mslice_from(");
776
+ generate_address(g, p);
777
+ writef(g, ");~N", p);
778
+ }
779
+
780
+ static void generate_setlimit(struct generator * g, struct node * p) {
781
+ struct str * savevar = vars_newname(g);
782
+ struct str * varname = vars_newname(g);
783
+ write_comment(g, p);
784
+ if (p->left && p->left->type == c_tomark) {
785
+ /* Special case for:
786
+ *
787
+ * setlimit tomark AE for C
788
+ *
789
+ * All uses of setlimit in the current stemmers we ship follow this
790
+ * pattern, and by special-casing we can avoid having to save and
791
+ * restore c.
792
+ */
793
+ struct node * q = p->left;
794
+ g->S[0] = q->mode == m_forward ? ">" : "<";
795
+ w(g, "~Mif (cursor ~S0 "); generate_AE(g, q->AE); w(g, ")~N");
796
+ write_block_start(g);
797
+ write_failure(g);
798
+ write_block_end(g);
799
+ g->unreachable = false;
800
+
801
+ g->B[0] = str_data(varname);
802
+ if (p->mode == m_forward) {
803
+ w(g, "~Mint ~B0 = limit - cursor;~N");
804
+ w(g, "~Mlimit = ");
805
+ } else {
806
+ w(g, "~Mint ~B0 = limit_backward;~N");
807
+ w(g, "~Mlimit_backward = ");
808
+ }
809
+ generate_AE(g, q->AE); writef(g, ";~N", q);
810
+
811
+ if (p->mode == m_forward) {
812
+ str_assign(g->failure_str, "limit += ");
813
+ str_append(g->failure_str, varname);
814
+ str_append_ch(g->failure_str, ';');
815
+ } else {
816
+ str_assign(g->failure_str, "limit_backward = ");
817
+ str_append(g->failure_str, varname);
818
+ str_append_ch(g->failure_str, ';');
819
+ }
820
+ } else {
821
+ write_savecursor(g, p, savevar);
822
+ generate(g, p->left);
823
+
824
+ if (!g->unreachable) {
825
+ g->B[0] = str_data(varname);
826
+ if (p->mode == m_forward) {
827
+ w(g, "~Mint ~B0 = limit - cursor;~N");
828
+ w(g, "~Mlimit = cursor;~N");
829
+ } else {
830
+ w(g, "~Mint ~B0 = limit_backward;~N");
831
+ w(g, "~Mlimit_backward = cursor;~N");
832
+ }
833
+ write_restorecursor(g, p, savevar);
834
+
835
+ if (p->mode == m_forward) {
836
+ str_assign(g->failure_str, "limit += ");
837
+ str_append(g->failure_str, varname);
838
+ str_append_ch(g->failure_str, ';');
839
+ } else {
840
+ str_assign(g->failure_str, "limit_backward = ");
841
+ str_append(g->failure_str, varname);
842
+ str_append_ch(g->failure_str, ';');
843
+ }
844
+ }
845
+ }
846
+
847
+ if (!g->unreachable) {
848
+ generate(g, p->aux);
849
+
850
+ if (!g->unreachable) {
851
+ write_margin(g);
852
+ write_str(g, g->failure_str);
853
+ write_newline(g);
854
+ }
855
+ }
856
+ str_delete(varname);
857
+ str_delete(savevar);
858
+ }
859
+
860
+ /* dollar sets snowball up to operate on a string variable as if it were the
861
+ * current string */
862
+ static void generate_dollar(struct generator * g, struct node * p) {
863
+
864
+ struct str * savevar = vars_newname(g);
865
+ g->B[0] = str_data(savevar);
866
+ writef(g, "~{~C~N"
867
+ "~MSnowballProgram ~B0 = new SnowballProgram(this);~N", p);
868
+
869
+ ++g->copy_from_count;
870
+ str_assign(g->failure_str, "copy_from(");
871
+ str_append(g->failure_str, savevar);
872
+ str_append_string(g->failure_str, ");");
873
+ g->V[0] = p->name;
874
+ writef(g, "~Mcurrent = ~V0;~N"
875
+ "~Mcursor = 0;~N"
876
+ "~Mlimit = current.length();~N", p);
877
+ generate(g, p->left);
878
+ if (!g->unreachable) {
879
+ write_margin(g);
880
+ write_str(g, g->failure_str);
881
+ write_newline(g);
882
+ }
883
+ w(g, "~}");
884
+ str_delete(savevar);
885
+ }
886
+
887
+ static void generate_integer_assign(struct generator * g, struct node * p, char * s) {
888
+
889
+ g->V[0] = p->name;
890
+ g->S[0] = s;
891
+ w(g, "~M~V0 ~S0 "); generate_AE(g, p->AE); w(g, ";~N");
892
+ }
893
+
894
+ static void generate_integer_test(struct generator * g, struct node * p, char * s) {
895
+
896
+ w(g, "~Mif (!(");
897
+ generate_AE(g, p->left);
898
+ write_char(g, ' ');
899
+ write_string(g, s);
900
+ write_char(g, ' ');
901
+ generate_AE(g, p->AE);
902
+ w(g, "))~N");
903
+ write_block_start(g);
904
+ write_failure(g);
905
+ write_block_end(g);
906
+ g->unreachable = false;
907
+ }
908
+
909
+ static void generate_call(struct generator * g, struct node * p) {
910
+
911
+ write_comment(g, p);
912
+ g->V[0] = p->name;
913
+ write_failure_if(g, "!~V0()", p);
914
+ }
915
+
916
+ static void generate_grouping(struct generator * g, struct node * p, int complement) {
917
+
918
+ struct grouping * q = p->name->grouping;
919
+ g->S[0] = p->mode == m_forward ? "" : "_b";
920
+ g->S[1] = complement ? "out" : "in";
921
+ g->V[0] = p->name;
922
+ g->I[0] = q->smallest_ch;
923
+ g->I[1] = q->largest_ch;
924
+ write_failure_if(g, "!(~S1_grouping~S0(~V0, ~I0, ~I1))", p);
925
+ }
926
+
927
+ static void generate_namedstring(struct generator * g, struct node * p) {
928
+
929
+ write_comment(g, p);
930
+ g->S[0] = p->mode == m_forward ? "" : "_b";
931
+ g->V[0] = p->name;
932
+ write_failure_if(g, "!(eq_s~S0(~V0))", p);
933
+ }
934
+
935
+ static void generate_literalstring(struct generator * g, struct node * p) {
936
+ symbol * b = p->literalstring;
937
+ write_comment(g, p);
938
+ g->S[0] = p->mode == m_forward ? "" : "_b";
939
+ g->L[0] = b;
940
+ write_failure_if(g, "!(eq_s~S0(~L0))", p);
941
+ }
942
+
943
+ static void generate_define(struct generator * g, struct node * p) {
944
+ struct name * q = p->name;
945
+
946
+ struct str * saved_output = g->outbuf;
947
+
948
+ /* We currently make functions used in among public as this seems to
949
+ * be required to allow the SnowballProgram base class to invoke them.
950
+ * FIXME: Is this avoidable?
951
+ */
952
+ if (q->type == t_routine && !q->used_in_among) {
953
+ g->S[0] = "private";
954
+ } else {
955
+ g->S[0] = "public";
956
+ }
957
+ g->V[0] = q;
958
+ w(g, "~N~M~S0 boolean ~V0() {~+~N");
959
+
960
+ g->outbuf = str_new();
961
+
962
+ g->next_label = 0;
963
+ g->var_number = 0;
964
+
965
+ if (p->amongvar_needed) w(g, "~Mint among_var;~N");
966
+ str_clear(g->failure_str);
967
+ g->failure_label = x_return;
968
+ g->unreachable = false;
969
+ generate(g, p->left);
970
+ if (!g->unreachable) w(g, "~Mreturn true;~N");
971
+ w(g, "~}");
972
+
973
+ str_append(saved_output, g->outbuf);
974
+ str_delete(g->outbuf);
975
+ g->outbuf = saved_output;
976
+ }
977
+
978
+ static void generate_substring(struct generator * g, struct node * p) {
979
+
980
+ struct among * x = p->among;
981
+
982
+ write_comment(g, p);
983
+
984
+ g->S[0] = p->mode == m_forward ? "" : "_b";
985
+ g->I[0] = x->number;
986
+
987
+ if (!x->amongvar_needed) {
988
+ write_failure_if(g, "find_among~S0(a_~I0) == 0", p);
989
+ } else {
990
+ writef(g, "~Mamong_var = find_among~S0(a_~I0);~N", p);
991
+ write_failure_if(g, "among_var == 0", p);
992
+ }
993
+ }
994
+
995
+ static void generate_among(struct generator * g, struct node * p) {
996
+
997
+ struct among * x = p->among;
998
+
999
+ if (x->substring == 0) generate_substring(g, p);
1000
+
1001
+ if (x->starter != 0) generate(g, x->starter);
1002
+
1003
+ if (x->command_count == 1 && x->nocommand_count == 0) {
1004
+ /* Only one outcome ("no match" already handled). */
1005
+ generate(g, x->commands[0]);
1006
+ } else if (x->command_count > 0) {
1007
+ int i;
1008
+ w(g, "~Mswitch (among_var) {~N~+");
1009
+ for (i = 1; i <= x->command_count; i++) {
1010
+ g->I[0] = i;
1011
+ w(g, "~Mcase ~I0:~N~+");
1012
+ generate(g, x->commands[i - 1]);
1013
+ if (!g->unreachable) w(g, "~Mbreak;~N");
1014
+ w(g, "~-");
1015
+ g->unreachable = false;
1016
+ }
1017
+ write_block_end(g);
1018
+ }
1019
+ }
1020
+
1021
+ static void generate_booltest(struct generator * g, struct node * p) {
1022
+
1023
+ write_comment(g, p);
1024
+ g->V[0] = p->name;
1025
+ write_failure_if(g, "!(~V0)", p);
1026
+ }
1027
+
1028
+ static void generate_false(struct generator * g, struct node * p) {
1029
+
1030
+ write_comment(g, p);
1031
+ write_failure(g);
1032
+ }
1033
+
1034
+ static void generate_debug(struct generator * g, struct node * p) {
1035
+
1036
+ write_comment(g, p);
1037
+ g->I[0] = g->debug_count++;
1038
+ g->I[1] = p->line_number;
1039
+ writef(g, "~Mdebug(~I0, ~I1);~N", p);
1040
+ }
1041
+
1042
+ static void generate(struct generator * g, struct node * p) {
1043
+
1044
+ int a0;
1045
+ struct str * a1;
1046
+
1047
+ if (g->unreachable) return;
1048
+
1049
+ a0 = g->failure_label;
1050
+ a1 = str_copy(g->failure_str);
1051
+
1052
+ switch (p->type) {
1053
+ case c_define: generate_define(g, p); break;
1054
+ case c_bra: generate_bra(g, p); break;
1055
+ case c_and: generate_and(g, p); break;
1056
+ case c_or: generate_or(g, p); break;
1057
+ case c_backwards: generate_backwards(g, p); break;
1058
+ case c_not: generate_not(g, p); break;
1059
+ case c_set: generate_set(g, p); break;
1060
+ case c_unset: generate_unset(g, p); break;
1061
+ case c_try: generate_try(g, p); break;
1062
+ case c_fail: generate_fail(g, p); break;
1063
+ case c_reverse:
1064
+ case c_test: generate_test(g, p); break;
1065
+ case c_do: generate_do(g, p); break;
1066
+ case c_goto: generate_GO(g, p, 1); break;
1067
+ case c_gopast: generate_GO(g, p, 0); break;
1068
+ case c_repeat: generate_repeat(g, p); break;
1069
+ case c_loop: generate_loop(g, p); break;
1070
+ case c_atleast: generate_atleast(g, p); break;
1071
+ case c_setmark: generate_setmark(g, p); break;
1072
+ case c_tomark: generate_tomark(g, p); break;
1073
+ case c_atmark: generate_atmark(g, p); break;
1074
+ case c_hop: generate_hop(g, p); break;
1075
+ case c_delete: generate_delete(g, p); break;
1076
+ case c_next: generate_next(g, p); break;
1077
+ case c_tolimit: generate_tolimit(g, p); break;
1078
+ case c_atlimit: generate_atlimit(g, p); break;
1079
+ case c_leftslice: generate_leftslice(g, p); break;
1080
+ case c_rightslice: generate_rightslice(g, p); break;
1081
+ case c_assignto: generate_assignto(g, p); break;
1082
+ case c_sliceto: generate_sliceto(g, p); break;
1083
+ case c_assign: generate_assignfrom(g, p); break;
1084
+ case c_insert:
1085
+ case c_attach: generate_insert(g, p, p->type); break;
1086
+ case c_slicefrom: generate_slicefrom(g, p); break;
1087
+ case c_setlimit: generate_setlimit(g, p); break;
1088
+ case c_dollar: generate_dollar(g, p); break;
1089
+ case c_mathassign: generate_integer_assign(g, p, "="); break;
1090
+ case c_plusassign: generate_integer_assign(g, p, "+="); break;
1091
+ case c_minusassign: generate_integer_assign(g, p, "-="); break;
1092
+ case c_multiplyassign:generate_integer_assign(g, p, "*="); break;
1093
+ case c_divideassign: generate_integer_assign(g, p, "/="); break;
1094
+ case c_eq: generate_integer_test(g, p, "=="); break;
1095
+ case c_ne: generate_integer_test(g, p, "!="); break;
1096
+ case c_gr: generate_integer_test(g, p, ">"); break;
1097
+ case c_ge: generate_integer_test(g, p, ">="); break;
1098
+ case c_ls: generate_integer_test(g, p, "<"); break;
1099
+ case c_le: generate_integer_test(g, p, "<="); break;
1100
+ case c_call: generate_call(g, p); break;
1101
+ case c_grouping: generate_grouping(g, p, false); break;
1102
+ case c_non: generate_grouping(g, p, true); break;
1103
+ case c_name: generate_namedstring(g, p); break;
1104
+ case c_literalstring: generate_literalstring(g, p); break;
1105
+ case c_among: generate_among(g, p); break;
1106
+ case c_substring: generate_substring(g, p); break;
1107
+ case c_booltest: generate_booltest(g, p); break;
1108
+ case c_false: generate_false(g, p); break;
1109
+ case c_true: break;
1110
+ case c_debug: generate_debug(g, p); break;
1111
+ default: fprintf(stderr, "%d encountered\n", p->type);
1112
+ exit(1);
1113
+ }
1114
+
1115
+ g->failure_label = a0;
1116
+ str_delete(g->failure_str);
1117
+ g->failure_str = a1;
1118
+ }
1119
+
1120
+ static void generate_class_begin(struct generator * g) {
1121
+
1122
+ w(g, "package ");
1123
+ w(g, g->options->package);
1124
+ w(g, ";~N~N");
1125
+
1126
+ if (g->analyser->among_count > 0) {
1127
+ w(g, "import ");
1128
+ w(g, g->options->among_class);
1129
+ w(g, ";~N~N");
1130
+ }
1131
+
1132
+ if (g->copy_from_count > 0) {
1133
+ w(g, "import org.tartarus.snowball.SnowballProgram;~N~N");
1134
+ }
1135
+
1136
+ w(g, "/**~N"
1137
+ " * This class implements the stemming algorithm defined by a snowball script.~N"
1138
+ " * <p>~N"
1139
+ " * ");
1140
+ write_generated_comment_content(g);
1141
+ w(g, "~N"
1142
+ " * </p>~N"
1143
+ " */~N"
1144
+ "@SuppressWarnings(\"unused\")~N"
1145
+ "public class ~n extends ");
1146
+
1147
+ w(g, g->options->parent_class_name);
1148
+ w(g, " {~+~N"
1149
+ "~N"
1150
+ "~Mprivate static final long serialVersionUID = 1L;~N"
1151
+ "~N");
1152
+ }
1153
+
1154
+ static void generate_class_end(struct generator * g) {
1155
+
1156
+ w(g, "~N}");
1157
+ w(g, "~N~N");
1158
+ }
1159
+
1160
+ static void generate_equals(struct generator * g) {
1161
+
1162
+ w(g, "~N"
1163
+ "@Override~N"
1164
+ "~Mpublic boolean equals( Object o ) {~N"
1165
+ "~+~Mreturn o instanceof ");
1166
+ w(g, g->options->name);
1167
+ w(g, ";~N~-~M}~N"
1168
+ "~N"
1169
+ "@Override~N"
1170
+ "~Mpublic int hashCode() {~N"
1171
+ "~+~Mreturn ");
1172
+ w(g, g->options->name);
1173
+ w(g, ".class.getName().hashCode();~N"
1174
+ "~-~M}~N");
1175
+ w(g, "~N~N");
1176
+ }
1177
+
1178
+ static void generate_among_table(struct generator * g, struct among * x) {
1179
+
1180
+ struct amongvec * v = x->b;
1181
+
1182
+ g->I[0] = x->number;
1183
+
1184
+ w(g, "~Mprivate final static Among a_~I0[] = {~N~+");
1185
+ {
1186
+ int i;
1187
+ for (i = 0; i < x->literalstring_count; i++) {
1188
+ g->I[0] = v->i;
1189
+ g->I[1] = v->result;
1190
+ g->L[0] = v->b;
1191
+ g->S[0] = i < x->literalstring_count - 1 ? "," : "";
1192
+
1193
+ w(g, "~Mnew Among(~L0, ~I0, ~I1");
1194
+ if (v->function != 0) {
1195
+ w(g, ", \"");
1196
+ write_varname(g, v->function);
1197
+ w(g, "\", ~n.class");
1198
+ }
1199
+ w(g, ")~S0~N");
1200
+ v++;
1201
+ }
1202
+ }
1203
+ w(g, "~-~M};~N~N");
1204
+ }
1205
+
1206
+ static void generate_amongs(struct generator * g) {
1207
+ struct among * x;
1208
+ for (x = g->analyser->amongs; x; x = x->next) {
1209
+ generate_among_table(g, x);
1210
+ }
1211
+ }
1212
+
1213
+ static void set_bit(symbol * b, int i) { b[i/8] |= 1 << i%8; }
1214
+
1215
+ static void generate_grouping_table(struct generator * g, struct grouping * q) {
1216
+
1217
+ int range = q->largest_ch - q->smallest_ch + 1;
1218
+ int size = (range + 7)/ 8; /* assume 8 bits per symbol */
1219
+ symbol * b = q->b;
1220
+ symbol * map = create_b(size);
1221
+ int i;
1222
+ for (i = 0; i < size; i++) map[i] = 0;
1223
+
1224
+ /* Using unicode would require revision here */
1225
+
1226
+ for (i = 0; i < SIZE(b); i++) set_bit(map, b[i] - q->smallest_ch);
1227
+
1228
+ g->V[0] = q->name;
1229
+
1230
+ w(g, "~Mprivate static final char ~V0[] = {");
1231
+ for (i = 0; i < size; i++) {
1232
+ write_int(g, map[i]);
1233
+ if (i < size - 1) w(g, ", ");
1234
+ }
1235
+ w(g, " };~N~N");
1236
+ lose_b(map);
1237
+ }
1238
+
1239
+ static void generate_groupings(struct generator * g) {
1240
+ struct grouping * q;
1241
+ for (q = g->analyser->groupings; q; q = q->next) {
1242
+ if (q->name->used)
1243
+ generate_grouping_table(g, q);
1244
+ }
1245
+ }
1246
+
1247
+ static void generate_members(struct generator * g) {
1248
+
1249
+ struct name * q;
1250
+ for (q = g->analyser->names; q; q = q->next) {
1251
+ g->V[0] = q;
1252
+ switch (q->type) {
1253
+ case t_string:
1254
+ w(g, "~Mprivate ");
1255
+ w(g, g->options->string_class);
1256
+ w(g, " ~W0 = new ");
1257
+ w(g, g->options->string_class);
1258
+ w(g, "();~N");
1259
+ break;
1260
+ case t_integer:
1261
+ w(g, "~Mprivate int ~W0;~N");
1262
+ break;
1263
+ case t_boolean:
1264
+ w(g, "~Mprivate boolean ~W0;~N");
1265
+ break;
1266
+ }
1267
+ }
1268
+ w(g, "~N");
1269
+ }
1270
+
1271
+ static void generate_methods(struct generator * g) {
1272
+
1273
+ struct node * p;
1274
+ for (p = g->analyser->program; p; p = p->right) {
1275
+ generate(g, p);
1276
+ g->unreachable = false;
1277
+ }
1278
+ }
1279
+
1280
+ extern void generate_program_java(struct generator * g) {
1281
+
1282
+ g->outbuf = str_new();
1283
+ g->failure_str = str_new();
1284
+
1285
+ generate_amongs(g);
1286
+ generate_groupings(g);
1287
+
1288
+ generate_members(g);
1289
+ generate_methods(g);
1290
+ generate_equals(g);
1291
+
1292
+ generate_class_end(g);
1293
+
1294
+ {
1295
+ /* We need to call generate_class_begin() after we've generated the
1296
+ * methods so we know if copy_from_count > 0.
1297
+ */
1298
+ struct str * body = g->outbuf;
1299
+
1300
+ g->outbuf = str_new();
1301
+
1302
+ write_start_comment(g, "// ", NULL);
1303
+ generate_class_begin(g);
1304
+
1305
+ str_append(g->outbuf, body);
1306
+
1307
+ str_delete(body);
1308
+ }
1309
+
1310
+ output_str(g->options->output_src, g->outbuf);
1311
+ str_delete(g->failure_str);
1312
+ str_delete(g->outbuf);
1313
+ }