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,1337 @@
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
+ int next_label = g->next_label++;
15
+ g->max_label = (next_label > g->max_label) ? next_label : g->max_label;
16
+ return 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
+
30
+ /* Write routines for items from the syntax tree */
31
+
32
+ static void write_varname(struct generator * g, struct name * p) {
33
+
34
+ switch (p->type) {
35
+ case t_external:
36
+ write_char(g, '_');
37
+ break;
38
+ case t_routine:
39
+ write_string(g, "__");
40
+ /* FALLTHRU */
41
+ default: {
42
+ int ch = "SBIrxg"[p->type];
43
+ write_char(g, ch);
44
+ write_char(g, '_');
45
+ break;
46
+ }
47
+ }
48
+ write_b(g, p->b);
49
+ }
50
+
51
+ static void write_varref(struct generator * g, struct name * p) {
52
+ write_string(g, "self.");
53
+ write_varname(g, p);
54
+ }
55
+
56
+ static void write_hexdigit(struct generator * g, int n) {
57
+
58
+ write_char(g, n < 10 ? n + '0' : n - 10 + 'A');
59
+ }
60
+
61
+ static void write_hex(struct generator * g, int ch) {
62
+
63
+ write_string(g, "\\u");
64
+ {
65
+ int i;
66
+ for (i = 12; i >= 0; i -= 4) write_hexdigit(g, ch >> i & 0xf);
67
+ }
68
+ }
69
+
70
+ static void write_literal_string(struct generator * g, symbol * p) {
71
+
72
+ int i;
73
+ write_string(g, "u\"");
74
+ for (i = 0; i < SIZE(p); i++) {
75
+ int ch = p[i];
76
+ if (32 <= ch && ch < 127) {
77
+ if (ch == '\"' || ch == '\\') write_string(g, "\\");
78
+ write_char(g, ch);
79
+ } else {
80
+ write_hex(g, ch);
81
+ }
82
+ }
83
+ write_string(g, "\"");
84
+ }
85
+
86
+ static void write_margin(struct generator * g) {
87
+
88
+ int i;
89
+ for (i = 0; i < g->margin; i++) write_string(g, " ");
90
+ }
91
+
92
+ static void write_comment(struct generator * g, struct node * p) {
93
+ if (!g->options->comments) return;
94
+ write_margin(g);
95
+ write_string(g, "# ");
96
+ write_comment_content(g, p);
97
+ write_newline(g);
98
+ }
99
+
100
+ static void write_block_start(struct generator * g) {
101
+
102
+ w(g, "~+~N");
103
+ }
104
+
105
+ static void write_block_end(struct generator * g) /* block end */ {
106
+
107
+ w(g, "~-");
108
+ }
109
+
110
+ static void write_savecursor(struct generator * g, struct node * p,
111
+ struct str * savevar) {
112
+
113
+ g->B[0] = str_data(savevar);
114
+ g->S[1] = "";
115
+ if (p->mode != m_forward) g->S[1] = "self.limit - ";
116
+ writef(g, "~M~B0 = ~S1self.cursor~N", p);
117
+ }
118
+
119
+ static void restore_string(struct node * p, struct str * out, struct str * savevar) {
120
+
121
+ str_clear(out);
122
+ str_append_string(out, "self.cursor = ");
123
+ if (p->mode != m_forward) str_append_string(out, "self.limit - ");
124
+ str_append(out, savevar);
125
+ }
126
+
127
+ static void write_restorecursor(struct generator * g, struct node * p,
128
+ struct str * savevar) {
129
+
130
+ struct str * temp = str_new();
131
+ write_margin(g);
132
+ restore_string(p, temp, savevar);
133
+ write_str(g, temp);
134
+ write_newline(g);
135
+ str_delete(temp);
136
+ }
137
+
138
+ static void write_inc_cursor(struct generator * g, struct node * p) {
139
+
140
+ write_margin(g);
141
+ write_string(g, p->mode == m_forward ? "self.cursor += 1" : "self.cursor -= 1");
142
+ write_newline(g);
143
+ }
144
+
145
+ static void wsetlab_begin(struct generator * g) {
146
+
147
+ w(g, "~Mtry:~N~+");
148
+ }
149
+
150
+ static void wsetlab_end(struct generator * g, int n) {
151
+ g->I[0] = n;
152
+ w(g, "~-~Mexcept lab~I0: pass~N");
153
+ }
154
+
155
+ static void wgotol(struct generator * g, int n) {
156
+ g->I[0] = n;
157
+ w(g, "~Mraise lab~I0()~N");
158
+ }
159
+
160
+ static void write_failure(struct generator * g) {
161
+
162
+ if (str_len(g->failure_str) != 0) {
163
+ write_margin(g);
164
+ write_str(g, g->failure_str);
165
+ write_newline(g);
166
+ }
167
+ switch (g->failure_label) {
168
+ case x_return:
169
+ w(g, "~Mreturn False~N");
170
+ g->unreachable = true;
171
+ break;
172
+ default:
173
+ g->I[0] = g->failure_label;
174
+ w(g, "~Mraise lab~I0()~N");
175
+ g->unreachable = true;
176
+ }
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, ":", 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, "self.cursor >= self.limit", p);
195
+ } else {
196
+ write_failure_if(g, "self.cursor <= self.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, "sys.maxsize"); break;
249
+ case c_minint:
250
+ write_string(g, "(~sys.maxsize)"); 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 = " - ";
259
+ label0:
260
+ write_char(g, '('); generate_AE(g, p->left);
261
+ write_string(g, s); generate_AE(g, p->right); write_char(g, ')'); break;
262
+ case c_divide:
263
+ /* Snowball specifies integer division with semantics matching C,
264
+ * so Python's `/` or `//` isn't suitable (`//` would be in cases
265
+ * where we knew that the arguments had the same sign).
266
+ *
267
+ * The `float(`...`)` is needed for Python2.
268
+ */
269
+ write_string(g, "int(float(");
270
+ generate_AE(g, p->left);
271
+ write_string(g, ") / ");
272
+ generate_AE(g, p->right);
273
+ write_char(g, ')');
274
+ break;
275
+ case c_cursor:
276
+ w(g, "self.cursor"); break;
277
+ case c_limit:
278
+ w(g, p->mode == m_forward ? "self.limit" : "self.limit_backward"); break;
279
+ case c_lenof: /* Same as sizeof() for Python. */
280
+ case c_sizeof:
281
+ g->V[0] = p->name;
282
+ w(g, "len(~V0)");
283
+ break;
284
+ case c_len: /* Same as size() for Python. */
285
+ case c_size:
286
+ w(g, "len(self.current)");
287
+ break;
288
+ }
289
+ }
290
+
291
+ static void generate_bra(struct generator * g, struct node * p) {
292
+
293
+ write_comment(g, p);
294
+ p = p->left;
295
+ while (p) {
296
+ generate(g, p);
297
+ p = p->right;
298
+ }
299
+ }
300
+
301
+ static void generate_and(struct generator * g, struct node * p) {
302
+
303
+ struct str * savevar = vars_newname(g);
304
+ int keep_c = K_needed(g, p->left);
305
+
306
+ write_comment(g, p);
307
+
308
+ if (keep_c) write_savecursor(g, p, savevar);
309
+
310
+ p = p->left;
311
+ while (p) {
312
+ generate(g, p);
313
+ if (g->unreachable) break;
314
+ if (keep_c && p->right != 0) write_restorecursor(g, p, savevar);
315
+ p = p->right;
316
+ }
317
+ str_delete(savevar);
318
+ }
319
+
320
+ static void generate_or(struct generator * g, struct node * p) {
321
+
322
+ struct str * savevar = vars_newname(g);
323
+ int keep_c = K_needed(g, p->left);
324
+
325
+ int a0 = g->failure_label;
326
+ struct str * a1 = str_copy(g->failure_str);
327
+
328
+ int out_lab = new_label(g);
329
+ int end_unreachable = true;
330
+
331
+ write_comment(g, p);
332
+ wsetlab_begin(g);
333
+
334
+ if (keep_c) write_savecursor(g, p, savevar);
335
+
336
+ p = p->left;
337
+ str_clear(g->failure_str);
338
+
339
+ if (p == 0) {
340
+ /* p should never be 0 after an or: there should be at least two
341
+ * sub nodes. */
342
+ fprintf(stderr, "Error: \"or\" node without children nodes.");
343
+ exit(1);
344
+ }
345
+ while (p->right != 0) {
346
+ int label = new_label(g);
347
+ g->failure_label = label;
348
+ wsetlab_begin(g);
349
+ generate(g, p);
350
+ if (!g->unreachable) {
351
+ wgotol(g, out_lab);
352
+ end_unreachable = false;
353
+ }
354
+ wsetlab_end(g, label);
355
+ g->unreachable = false;
356
+ if (keep_c) write_restorecursor(g, p, savevar);
357
+ p = p->right;
358
+ }
359
+
360
+ g->failure_label = a0;
361
+ str_delete(g->failure_str);
362
+ g->failure_str = a1;
363
+
364
+ generate(g, p);
365
+ wsetlab_end(g, out_lab);
366
+ if (!end_unreachable) {
367
+ g->unreachable = false;
368
+ }
369
+ str_delete(savevar);
370
+ }
371
+
372
+ static void generate_backwards(struct generator * g, struct node * p) {
373
+
374
+ write_comment(g, p);
375
+ writef(g, "~Mself.limit_backward = self.cursor~N"
376
+ "~Mself.cursor = self.limit~N", p);
377
+ generate(g, p->left);
378
+ w(g, "~Mself.cursor = self.limit_backward~N");
379
+ }
380
+
381
+
382
+ static void generate_not(struct generator * g, struct node * p) {
383
+
384
+ struct str * savevar = vars_newname(g);
385
+ int keep_c = K_needed(g, p->left);
386
+
387
+ int a0 = g->failure_label;
388
+ struct str * a1 = str_copy(g->failure_str);
389
+ int label = new_label(g);
390
+ g->failure_label = label;
391
+ str_clear(g->failure_str);
392
+
393
+ write_comment(g, p);
394
+ if (keep_c) {
395
+ write_savecursor(g, p, savevar);
396
+ }
397
+
398
+ wsetlab_begin(g);
399
+
400
+ generate(g, p->left);
401
+
402
+ g->failure_label = a0;
403
+ str_delete(g->failure_str);
404
+ g->failure_str = a1;
405
+
406
+ if (!g->unreachable) write_failure(g);
407
+
408
+ wsetlab_end(g, label);
409
+ g->unreachable = false;
410
+
411
+ if (keep_c) write_restorecursor(g, p, savevar);
412
+ str_delete(savevar);
413
+ }
414
+
415
+
416
+ static void generate_try(struct generator * g, struct node * p) {
417
+
418
+ struct str * savevar = vars_newname(g);
419
+ int keep_c = K_needed(g, p->left);
420
+ int label = new_label(g);
421
+ g->failure_label = label;
422
+ str_clear(g->failure_str);
423
+
424
+ write_comment(g, p);
425
+ if (keep_c) {
426
+ write_savecursor(g, p, savevar);
427
+ restore_string(p, g->failure_str, savevar);
428
+ }
429
+
430
+ wsetlab_begin(g);
431
+ generate(g, p->left);
432
+ wsetlab_end(g, label);
433
+ g->unreachable = false;
434
+
435
+ str_delete(savevar);
436
+ }
437
+
438
+ static void generate_set(struct generator * g, struct node * p) {
439
+
440
+ write_comment(g, p);
441
+ g->V[0] = p->name;
442
+ writef(g, "~M~V0 = True~N", p);
443
+ }
444
+
445
+ static void generate_unset(struct generator * g, struct node * p) {
446
+
447
+ write_comment(g, p);
448
+ g->V[0] = p->name;
449
+ writef(g, "~M~V0 = False~N", p);
450
+ }
451
+
452
+ static void generate_fail(struct generator * g, struct node * p) {
453
+
454
+ write_comment(g, p);
455
+ generate(g, p->left);
456
+ if (!g->unreachable) write_failure(g);
457
+ }
458
+
459
+ /* generate_test() also implements 'reverse' */
460
+
461
+ static void generate_test(struct generator * g, struct node * p) {
462
+
463
+ struct str * savevar = vars_newname(g);
464
+ int keep_c = K_needed(g, p->left);
465
+
466
+ write_comment(g, p);
467
+
468
+ if (keep_c) {
469
+ write_savecursor(g, p, savevar);
470
+ }
471
+
472
+ generate(g, p->left);
473
+
474
+ if (!g->unreachable) {
475
+ if (keep_c) {
476
+ write_restorecursor(g, p, savevar);
477
+ }
478
+ }
479
+ str_delete(savevar);
480
+ }
481
+
482
+ static void generate_do(struct generator * g, struct node * p) {
483
+
484
+ struct str * savevar = vars_newname(g);
485
+ int keep_c = K_needed(g, p->left);
486
+ write_comment(g, p);
487
+ if (keep_c) write_savecursor(g, p, savevar);
488
+
489
+ if (p->left->type == c_call) {
490
+ /* Optimise do <call> */
491
+ write_comment(g, p->left);
492
+ g->V[0] = p->left->name;
493
+ w(g, "~M~V0()~N");
494
+ } else {
495
+ int label = new_label(g);
496
+ g->failure_label = label;
497
+ str_clear(g->failure_str);
498
+
499
+ wsetlab_begin(g);
500
+ generate(g, p->left);
501
+ wsetlab_end(g, label);
502
+ g->unreachable = false;
503
+ }
504
+
505
+ if (keep_c) write_restorecursor(g, p, savevar);
506
+ str_delete(savevar);
507
+ }
508
+
509
+ static void generate_GO_grouping(struct generator * g, struct node * p, int is_goto, int complement) {
510
+
511
+ struct grouping * q = p->name->grouping;
512
+ write_comment(g, p);
513
+ g->S[0] = p->mode == m_forward ? "" : "_b";
514
+ g->S[1] = complement ? "in" : "out";
515
+ g->S[2] = g->options->encoding == ENC_UTF8 ? "_U" : "";
516
+ g->V[0] = p->name;
517
+ g->I[0] = q->smallest_ch;
518
+ g->I[1] = q->largest_ch;
519
+ write_failure_if(g, "not self.go_~S1_grouping~S0~S2(~n.~W0, ~I0, ~I1)", p);
520
+ if (!is_goto) {
521
+ if (p->mode == m_forward)
522
+ w(g, "~Mself.cursor += 1~N");
523
+ else
524
+ w(g, "~Mself.cursor -= 1~N");
525
+ }
526
+ }
527
+
528
+ static void generate_GO(struct generator * g, struct node * p, int style) {
529
+ int end_unreachable;
530
+ struct str * savevar;
531
+ int keep_c;
532
+
533
+ int a0;
534
+ struct str * a1;
535
+
536
+ int golab;
537
+ int label;
538
+
539
+ if (p->left->type == c_grouping || p->left->type == c_non) {
540
+ /* Special case for "goto" or "gopast" when used on a grouping or an
541
+ * inverted grouping - the movement of c by the matching action is
542
+ * exactly what we want! */
543
+ #ifdef OPTIMISATION_WARNINGS
544
+ printf("Optimising %s %s\n", style ? "goto" : "gopast", p->left->type == c_non ? "non" : "grouping");
545
+ #endif
546
+ write_comment(g, p);
547
+ generate_GO_grouping(g, p->left, style, p->left->type == c_non);
548
+ return;
549
+ }
550
+
551
+ end_unreachable = false;
552
+ savevar = vars_newname(g);
553
+ keep_c = style == 1 || repeat_restore(g, p->left);
554
+
555
+ a0 = g->failure_label;
556
+ a1 = str_copy(g->failure_str);
557
+
558
+ golab = new_label(g);
559
+ write_comment(g, p);
560
+ w(g, "~Mtry:~N~+"
561
+ "~Mwhile True:~N~+");
562
+ if (keep_c) write_savecursor(g, p, savevar);
563
+
564
+ label = new_label(g);
565
+ g->failure_label = label;
566
+ str_clear(g->failure_str);
567
+ wsetlab_begin(g);
568
+ generate(g, p->left);
569
+
570
+ if (g->unreachable) {
571
+ /* Cannot break out of this loop: therefore the code after the
572
+ * end of the loop is unreachable.*/
573
+ end_unreachable = true;
574
+ } else {
575
+ /* include for goto; omit for gopast */
576
+ if (style == 1) write_restorecursor(g, p, savevar);
577
+ g->I[0] = golab;
578
+ w(g, "~Mraise lab~I0()~N");
579
+ }
580
+ g->unreachable = false;
581
+ wsetlab_end(g, label);
582
+ if (keep_c) write_restorecursor(g, p, savevar);
583
+
584
+ g->failure_label = a0;
585
+ str_delete(g->failure_str);
586
+ g->failure_str = a1;
587
+
588
+ write_check_limit(g, p);
589
+ write_inc_cursor(g, p);
590
+ w(g, "~-~-");
591
+ g->I[0] = golab;
592
+ w(g, "~Mexcept lab~I0: pass~N");
593
+ str_delete(savevar);
594
+ g->unreachable = end_unreachable;
595
+ }
596
+
597
+ static void generate_loop(struct generator * g, struct node * p) {
598
+
599
+ struct str * loopvar = vars_newname(g);
600
+ write_comment(g, p);
601
+ g->B[0] = str_data(loopvar);
602
+ w(g, "~Mfor ~B0 in range (");
603
+ generate_AE(g, p->AE);
604
+ g->B[0] = str_data(loopvar);
605
+ writef(g, ", 0, -1):~N", p);
606
+ writef(g, "~{", p);
607
+
608
+ generate(g, p->left);
609
+
610
+ w(g, "~}");
611
+ str_delete(loopvar);
612
+ g->unreachable = false;
613
+ }
614
+
615
+ static void generate_repeat_or_atleast(struct generator * g, struct node * p, struct str * loopvar) {
616
+
617
+ struct str * savevar = vars_newname(g);
618
+ int keep_c = repeat_restore(g, p->left);
619
+ int label = new_label(g);
620
+ g->failure_label = label;
621
+ writef(g, "~Mwhile True:~N~+", p);
622
+ if (keep_c) write_savecursor(g, p, savevar);
623
+
624
+ str_clear(g->failure_str);
625
+ wsetlab_begin(g);
626
+ generate(g, p->left);
627
+
628
+ if (!g->unreachable) {
629
+ if (loopvar != 0) {
630
+ g->B[0] = str_data(loopvar);
631
+ w(g, "~M~B0 -= 1~N");
632
+ }
633
+
634
+ w(g, "~Mcontinue~N");
635
+ }
636
+
637
+ wsetlab_end(g, label);
638
+ g->unreachable = false;
639
+
640
+ if (keep_c) write_restorecursor(g, p, savevar);
641
+
642
+ w(g, "~Mbreak~N~}");
643
+ str_delete(savevar);
644
+ }
645
+
646
+ static void generate_repeat(struct generator * g, struct node * p) {
647
+ write_comment(g, p);
648
+ generate_repeat_or_atleast(g, p, NULL);
649
+ }
650
+
651
+ static void generate_atleast(struct generator * g, struct node * p) {
652
+
653
+ struct str * loopvar = vars_newname(g);
654
+ write_comment(g, p);
655
+ g->B[0] = str_data(loopvar);
656
+ w(g, "~M~B0 = ");
657
+ generate_AE(g, p->AE);
658
+ w(g, "~N");
659
+ {
660
+ int a0 = g->failure_label;
661
+ struct str * a1 = str_copy(g->failure_str);
662
+
663
+ generate_repeat_or_atleast(g, p, loopvar);
664
+
665
+ g->failure_label = a0;
666
+ str_delete(g->failure_str);
667
+ g->failure_str = a1;
668
+ }
669
+ g->B[0] = str_data(loopvar);
670
+ write_failure_if(g, "~B0 > 0", p);
671
+ str_delete(loopvar);
672
+ }
673
+
674
+ static void generate_setmark(struct generator * g, struct node * p) {
675
+
676
+ write_comment(g, p);
677
+ g->V[0] = p->name;
678
+ writef(g, "~M~V0 = self.cursor~N", p);
679
+ }
680
+
681
+ static void generate_tomark(struct generator * g, struct node * p) {
682
+
683
+ write_comment(g, p);
684
+ g->S[0] = p->mode == m_forward ? ">" : "<";
685
+
686
+ w(g, "~Mif self.cursor ~S0 "); generate_AE(g, p->AE); w(g, ":");
687
+ write_block_start(g);
688
+ write_failure(g);
689
+ write_block_end(g);
690
+ g->unreachable = false;
691
+ w(g, "~Mself.cursor = "); generate_AE(g, p->AE); writef(g, "~N", p);
692
+ }
693
+
694
+ static void generate_atmark(struct generator * g, struct node * p) {
695
+
696
+ write_comment(g, p);
697
+ w(g, "~Mif self.cursor != "); generate_AE(g, p->AE); writef(g, ":", p);
698
+ write_block_start(g);
699
+ write_failure(g);
700
+ write_block_end(g);
701
+ g->unreachable = false;
702
+ }
703
+
704
+ static void generate_hop(struct generator * g, struct node * p) {
705
+
706
+ write_comment(g, p);
707
+ g->S[0] = p->mode == m_forward ? "+" : "-";
708
+
709
+ w(g, "~Mc = self.cursor ~S0 ");
710
+ generate_AE(g, p->AE);
711
+ w(g, "~N");
712
+
713
+ g->S[1] = p->mode == m_forward ? "> self.limit" : "< self.limit_backward";
714
+ g->S[2] = p->mode == m_forward ? "<" : ">";
715
+ if (p->AE->type == c_number) {
716
+ // Constant distance hop.
717
+ //
718
+ // No need to check for negative hop as that's converted to false by
719
+ // the analyser.
720
+ write_failure_if(g, "c ~S1", p);
721
+ } else {
722
+ write_failure_if(g, "c ~S1 or c ~S2 self.cursor", p);
723
+ }
724
+ writef(g, "~Mself.cursor = c~N", p);
725
+ }
726
+
727
+ static void generate_delete(struct generator * g, struct node * p) {
728
+
729
+ write_comment(g, p);
730
+ writef(g, "~Mif not self.slice_del():~N"
731
+ "~+~Mreturn False~N~-"
732
+ "~N", p);
733
+ }
734
+
735
+
736
+ static void generate_next(struct generator * g, struct node * p) {
737
+
738
+ write_comment(g, p);
739
+ write_check_limit(g, p);
740
+ write_inc_cursor(g, p);
741
+ }
742
+
743
+ static void generate_tolimit(struct generator * g, struct node * p) {
744
+
745
+ write_comment(g, p);
746
+ g->S[0] = p->mode == m_forward ? "self.limit" : "self.limit_backward";
747
+ writef(g, "~Mself.cursor = ~S0~N", p);
748
+ }
749
+
750
+ static void generate_atlimit(struct generator * g, struct node * p) {
751
+
752
+ write_comment(g, p);
753
+ g->S[0] = p->mode == m_forward ? "self.limit" : "self.limit_backward";
754
+ g->S[1] = p->mode == m_forward ? "<" : ">";
755
+ write_failure_if(g, "self.cursor ~S1 ~S0", p);
756
+ }
757
+
758
+ static void generate_leftslice(struct generator * g, struct node * p) {
759
+
760
+ write_comment(g, p);
761
+ g->S[0] = p->mode == m_forward ? "self.bra" : "self.ket";
762
+ writef(g, "~M~S0 = self.cursor~N", p);
763
+ }
764
+
765
+ static void generate_rightslice(struct generator * g, struct node * p) {
766
+
767
+ write_comment(g, p);
768
+ g->S[0] = p->mode == m_forward ? "self.ket" : "self.bra";
769
+ writef(g, "~M~S0 = self.cursor~N", p);
770
+ }
771
+
772
+ static void generate_assignto(struct generator * g, struct node * p) {
773
+
774
+ write_comment(g, p);
775
+ g->V[0] = p->name;
776
+ writef(g, "~M~V0 = self.assign_to()~N", p);
777
+ }
778
+
779
+ static void generate_sliceto(struct generator * g, struct node * p) {
780
+
781
+ write_comment(g, p);
782
+ g->V[0] = p->name;
783
+ writef(g, "~M~V0 = self.slice_to()~N"
784
+ "~Mif ~V0 == '':~N"
785
+ "~+~Mreturn False~N~-", p);
786
+ }
787
+
788
+ static void generate_address(struct generator * g, struct node * p) {
789
+
790
+ symbol * b = p->literalstring;
791
+ if (b != 0) {
792
+ write_literal_string(g, b);
793
+ } else {
794
+ write_varref(g, p->name);
795
+ }
796
+ }
797
+
798
+ static void generate_insert(struct generator * g, struct node * p, int style) {
799
+
800
+ int keep_c = style == c_attach;
801
+ write_comment(g, p);
802
+ if (p->mode == m_backward) keep_c = !keep_c;
803
+ if (keep_c) w(g, "~Mc = self.cursor~N");
804
+ writef(g, "~Mself.insert(self.cursor, self.cursor, ", p);
805
+ generate_address(g, p);
806
+ writef(g, ")~N", p);
807
+ if (keep_c) w(g, "~Mself.cursor = c~N");
808
+ }
809
+
810
+ static void generate_assignfrom(struct generator * g, struct node * p) {
811
+
812
+ int keep_c = p->mode == m_forward; /* like 'attach' */
813
+
814
+ write_comment(g, p);
815
+ if (keep_c) writef(g, "~Mc = self.cursor~N", p);
816
+ if (p->mode == m_forward) {
817
+ writef(g, "~Mself.insert(self.cursor, self.limit, ", p);
818
+ } else {
819
+ writef(g, "~Mself.insert(self.limit_backward, self.cursor, ", p);
820
+ }
821
+ generate_address(g, p);
822
+ writef(g, ")~N", p);
823
+ if (keep_c) w(g, "~Mself.cursor = c~N");
824
+ }
825
+
826
+
827
+ static void generate_slicefrom(struct generator * g, struct node * p) {
828
+
829
+ write_comment(g, p);
830
+ w(g, "~Mif not self.slice_from(");
831
+ generate_address(g, p);
832
+ writef(g, "):~N"
833
+ "~+~Mreturn False~N~-", p);
834
+ }
835
+
836
+ static void generate_setlimit(struct generator * g, struct node * p) {
837
+ struct str * savevar = vars_newname(g);
838
+ struct str * varname = vars_newname(g);
839
+ write_comment(g, p);
840
+ if (p->left && p->left->type == c_tomark) {
841
+ /* Special case for:
842
+ *
843
+ * setlimit tomark AE for C
844
+ *
845
+ * All uses of setlimit in the current stemmers we ship follow this
846
+ * pattern, and by special-casing we can avoid having to save and
847
+ * restore c.
848
+ */
849
+ struct node * q = p->left;
850
+ g->S[0] = q->mode == m_forward ? ">" : "<";
851
+ w(g, "~Mif self.cursor ~S0 "); generate_AE(g, q->AE); w(g, ":");
852
+ write_block_start(g);
853
+ write_failure(g);
854
+ write_block_end(g);
855
+ g->unreachable = false;
856
+
857
+ g->B[0] = str_data(varname);
858
+ if (p->mode == m_forward) {
859
+ w(g, "~M~B0 = self.limit - self.cursor~N");
860
+ w(g, "~Mself.limit = ");
861
+ } else {
862
+ w(g, "~M~B0 = self.limit_backward~N");
863
+ w(g, "~Mself.limit_backward = ");
864
+ }
865
+ generate_AE(g, q->AE); writef(g, "~N", q);
866
+
867
+ if (p->mode == m_forward) {
868
+ str_assign(g->failure_str, "self.limit += ");
869
+ str_append(g->failure_str, varname);
870
+ } else {
871
+ str_assign(g->failure_str, "self.limit_backward = ");
872
+ str_append(g->failure_str, varname);
873
+ }
874
+ } else {
875
+ write_savecursor(g, p, savevar);
876
+ generate(g, p->left);
877
+
878
+ if (!g->unreachable) {
879
+ g->B[0] = str_data(varname);
880
+ if (p->mode == m_forward) {
881
+ w(g, "~M~B0 = self.limit - self.cursor~N");
882
+ w(g, "~Mself.limit = self.cursor~N");
883
+ } else {
884
+ w(g, "~M~B0 = self.limit_backward~N");
885
+ w(g, "~Mself.limit_backward = self.cursor~N");
886
+ }
887
+ write_restorecursor(g, p, savevar);
888
+
889
+ if (p->mode == m_forward) {
890
+ str_assign(g->failure_str, "self.limit += ");
891
+ str_append(g->failure_str, varname);
892
+ } else {
893
+ str_assign(g->failure_str, "self.limit_backward = ");
894
+ str_append(g->failure_str, varname);
895
+ }
896
+ }
897
+ }
898
+
899
+ if (!g->unreachable) {
900
+ generate(g, p->aux);
901
+
902
+ if (!g->unreachable) {
903
+ write_margin(g);
904
+ write_str(g, g->failure_str);
905
+ write_newline(g);
906
+ }
907
+ }
908
+
909
+ str_delete(varname);
910
+ str_delete(savevar);
911
+ }
912
+
913
+ /* dollar sets snowball up to operate on a string variable as if it were the
914
+ * current string */
915
+ static void generate_dollar(struct generator * g, struct node * p) {
916
+
917
+ struct str * savevar = vars_newname(g);
918
+ g->B[0] = str_data(savevar);
919
+ write_comment(g, p);
920
+ writef(g, "~M~B0 = BaseStemmer()~N"
921
+ "~M~B0.copy_from(self)~N", p);
922
+
923
+ {
924
+ struct str * saved_output = g->outbuf;
925
+ str_clear(g->failure_str);
926
+ g->outbuf = g->failure_str;
927
+ g->V[0] = p->name;
928
+ writef(g, "~V0 = self.current; ", p);
929
+ /* For Python 3, this can just be: super().copy_from(~B0) */
930
+ writef(g, "super(~n, self).copy_from(~B0)", p);
931
+ g->failure_str = g->outbuf;
932
+ g->outbuf = saved_output;
933
+ }
934
+
935
+ writef(g, "~Mself.current = ~V0~N"
936
+ "~Mself.cursor = 0~N"
937
+ "~Mself.limit = len(self.current)~N", p);
938
+ generate(g, p->left);
939
+ if (!g->unreachable) {
940
+ write_margin(g);
941
+ write_str(g, g->failure_str);
942
+ write_newline(g);
943
+ }
944
+ str_delete(savevar);
945
+ }
946
+
947
+ static void generate_integer_assign(struct generator * g, struct node * p, char * s) {
948
+
949
+ g->V[0] = p->name;
950
+ g->S[0] = s;
951
+ w(g, "~M~V0 ~S0 "); generate_AE(g, p->AE); w(g, "~N");
952
+ }
953
+
954
+ static void generate_integer_test(struct generator * g, struct node * p, char * s) {
955
+
956
+ w(g, "~Mif not ");
957
+ generate_AE(g, p->left);
958
+ write_char(g, ' ');
959
+ write_string(g, s);
960
+ write_char(g, ' ');
961
+ generate_AE(g, p->AE);
962
+ w(g, ":");
963
+ write_block_start(g);
964
+ write_failure(g);
965
+ write_block_end(g);
966
+ g->unreachable = false;
967
+ }
968
+
969
+ static void generate_call(struct generator * g, struct node * p) {
970
+
971
+ write_comment(g, p);
972
+ g->V[0] = p->name;
973
+ write_failure_if(g, "not ~V0()", p);
974
+ }
975
+
976
+ static void generate_grouping(struct generator * g, struct node * p, int complement) {
977
+
978
+ struct grouping * q = p->name->grouping;
979
+ g->S[0] = p->mode == m_forward ? "" : "_b";
980
+ g->S[1] = complement ? "out" : "in";
981
+ g->V[0] = p->name;
982
+ g->I[0] = q->smallest_ch;
983
+ g->I[1] = q->largest_ch;
984
+ write_failure_if(g, "not self.~S1_grouping~S0(~n.~W0, ~I0, ~I1)", p);
985
+ }
986
+
987
+ static void generate_namedstring(struct generator * g, struct node * p) {
988
+
989
+ write_comment(g, p);
990
+ g->S[0] = p->mode == m_forward ? "" : "_b";
991
+ g->V[0] = p->name;
992
+ write_failure_if(g, "not self.eq_s~S0(~V0)", p);
993
+ }
994
+
995
+ static void generate_literalstring(struct generator * g, struct node * p) {
996
+ symbol * b = p->literalstring;
997
+ write_comment(g, p);
998
+ g->S[0] = p->mode == m_forward ? "" : "_b";
999
+ g->L[0] = b;
1000
+ write_failure_if(g, "not self.eq_s~S0(~L0)", p);
1001
+ }
1002
+
1003
+ static void generate_define(struct generator * g, struct node * p) {
1004
+ struct name * q = p->name;
1005
+
1006
+ struct str * saved_output = g->outbuf;
1007
+
1008
+ g->V[0] = q;
1009
+ w(g, "~N~Mdef ~W0(self):~+~N");
1010
+
1011
+ g->outbuf = str_new();
1012
+
1013
+ g->next_label = 0;
1014
+ g->var_number = 0;
1015
+
1016
+ str_clear(g->failure_str);
1017
+ g->failure_label = x_return;
1018
+ g->unreachable = false;
1019
+ generate(g, p->left);
1020
+ if (!g->unreachable) w(g, "~Mreturn True~N");
1021
+ w(g, "~-");
1022
+
1023
+ str_append(saved_output, g->outbuf);
1024
+ str_delete(g->outbuf);
1025
+ g->outbuf = saved_output;
1026
+ }
1027
+
1028
+ static void generate_substring(struct generator * g, struct node * p) {
1029
+
1030
+ struct among * x = p->among;
1031
+
1032
+ write_comment(g, p);
1033
+
1034
+ g->S[0] = p->mode == m_forward ? "" : "_b";
1035
+ g->I[0] = x->number;
1036
+
1037
+ if (!x->amongvar_needed) {
1038
+ write_failure_if(g, "self.find_among~S0(~n.a_~I0) == 0", p);
1039
+ } else {
1040
+ writef(g, "~Mamong_var = self.find_among~S0(~n.a_~I0)~N", p);
1041
+ write_failure_if(g, "among_var == 0", p);
1042
+ }
1043
+ }
1044
+
1045
+ static void generate_among(struct generator * g, struct node * p) {
1046
+
1047
+ struct among * x = p->among;
1048
+
1049
+ if (x->substring == 0) generate_substring(g, p);
1050
+
1051
+ if (x->starter != 0) generate(g, x->starter);
1052
+
1053
+ if (x->command_count == 1 && x->nocommand_count == 0) {
1054
+ /* Only one outcome ("no match" already handled). */
1055
+ generate(g, x->commands[0]);
1056
+ } else if (x->command_count > 0) {
1057
+ int i;
1058
+ for (i = 1; i <= x->command_count; i++) {
1059
+ if (i == x->command_count && x->nocommand_count == 0) {
1060
+ w(g, "~Melse:~N~+");
1061
+ } else {
1062
+ g->I[0] = i;
1063
+ w(g, (i > 1 ? "~Melif" : "~Mif"));
1064
+ w(g, " among_var == ~I0:~N~+");
1065
+ }
1066
+ generate(g, x->commands[i - 1]);
1067
+ w(g, "~-");
1068
+ g->unreachable = false;
1069
+ }
1070
+ }
1071
+ }
1072
+
1073
+ static void generate_booltest(struct generator * g, struct node * p) {
1074
+
1075
+ write_comment(g, p);
1076
+ g->V[0] = p->name;
1077
+ write_failure_if(g, "not ~V0", p);
1078
+ }
1079
+
1080
+ static void generate_false(struct generator * g, struct node * p) {
1081
+
1082
+ write_comment(g, p);
1083
+ write_failure(g);
1084
+ }
1085
+
1086
+ static void generate_debug(struct generator * g, struct node * p) {
1087
+
1088
+ write_comment(g, p);
1089
+ g->I[0] = g->debug_count++;
1090
+ g->I[1] = p->line_number;
1091
+ writef(g, "~Mself.debug(~I0, ~I1)~N", p);
1092
+ }
1093
+
1094
+ static void generate(struct generator * g, struct node * p) {
1095
+
1096
+ int a0;
1097
+ struct str * a1;
1098
+
1099
+ if (g->unreachable) return;
1100
+
1101
+ a0 = g->failure_label;
1102
+ a1 = str_copy(g->failure_str);
1103
+
1104
+ switch (p->type) {
1105
+ case c_define: generate_define(g, p); break;
1106
+ case c_bra: generate_bra(g, p); break;
1107
+ case c_and: generate_and(g, p); break;
1108
+ case c_or: generate_or(g, p); break;
1109
+ case c_backwards: generate_backwards(g, p); break;
1110
+ case c_not: generate_not(g, p); break;
1111
+ case c_set: generate_set(g, p); break;
1112
+ case c_unset: generate_unset(g, p); break;
1113
+ case c_try: generate_try(g, p); break;
1114
+ case c_fail: generate_fail(g, p); break;
1115
+ case c_reverse:
1116
+ case c_test: generate_test(g, p); break;
1117
+ case c_do: generate_do(g, p); break;
1118
+ case c_goto: generate_GO(g, p, 1); break;
1119
+ case c_gopast: generate_GO(g, p, 0); break;
1120
+ case c_repeat: generate_repeat(g, p); break;
1121
+ case c_loop: generate_loop(g, p); break;
1122
+ case c_atleast: generate_atleast(g, p); break;
1123
+ case c_setmark: generate_setmark(g, p); break;
1124
+ case c_tomark: generate_tomark(g, p); break;
1125
+ case c_atmark: generate_atmark(g, p); break;
1126
+ case c_hop: generate_hop(g, p); break;
1127
+ case c_delete: generate_delete(g, p); break;
1128
+ case c_next: generate_next(g, p); break;
1129
+ case c_tolimit: generate_tolimit(g, p); break;
1130
+ case c_atlimit: generate_atlimit(g, p); break;
1131
+ case c_leftslice: generate_leftslice(g, p); break;
1132
+ case c_rightslice: generate_rightslice(g, p); break;
1133
+ case c_assignto: generate_assignto(g, p); break;
1134
+ case c_sliceto: generate_sliceto(g, p); break;
1135
+ case c_assign: generate_assignfrom(g, p); break;
1136
+ case c_insert:
1137
+ case c_attach: generate_insert(g, p, p->type); break;
1138
+ case c_slicefrom: generate_slicefrom(g, p); break;
1139
+ case c_setlimit: generate_setlimit(g, p); break;
1140
+ case c_dollar: generate_dollar(g, p); break;
1141
+ case c_mathassign: generate_integer_assign(g, p, "="); break;
1142
+ case c_plusassign: generate_integer_assign(g, p, "+="); break;
1143
+ case c_minusassign: generate_integer_assign(g, p, "-="); break;
1144
+ case c_multiplyassign:generate_integer_assign(g, p, "*="); break;
1145
+ case c_divideassign:
1146
+ /* Snowball specifies integer division with semantics matching C,
1147
+ * so Python's `/=` or `//=` isn't suitable (`//=` would be in
1148
+ * cases where we knew that the arguments had the same sign).
1149
+ *
1150
+ * The `float(`...`)` is needed for Python2.
1151
+ */
1152
+ g->V[0] = p->name;
1153
+ w(g, "~M~V0 = int(float(~V0) / ");
1154
+ generate_AE(g, p->AE);
1155
+ w(g, ")~N");
1156
+ break;
1157
+ case c_eq: generate_integer_test(g, p, "=="); break;
1158
+ case c_ne: generate_integer_test(g, p, "!="); break;
1159
+ case c_gr: generate_integer_test(g, p, ">"); break;
1160
+ case c_ge: generate_integer_test(g, p, ">="); break;
1161
+ case c_ls: generate_integer_test(g, p, "<"); break;
1162
+ case c_le: generate_integer_test(g, p, "<="); break;
1163
+ case c_call: generate_call(g, p); break;
1164
+ case c_grouping: generate_grouping(g, p, false); break;
1165
+ case c_non: generate_grouping(g, p, true); break;
1166
+ case c_name: generate_namedstring(g, p); break;
1167
+ case c_literalstring: generate_literalstring(g, p); break;
1168
+ case c_among: generate_among(g, p); break;
1169
+ case c_substring: generate_substring(g, p); break;
1170
+ case c_booltest: generate_booltest(g, p); break;
1171
+ case c_false: generate_false(g, p); break;
1172
+ case c_true: break;
1173
+ case c_debug: generate_debug(g, p); break;
1174
+ default: fprintf(stderr, "%d encountered\n", p->type);
1175
+ exit(1);
1176
+ }
1177
+
1178
+ g->failure_label = a0;
1179
+ str_delete(g->failure_str);
1180
+ g->failure_str = a1;
1181
+ }
1182
+
1183
+ static void generate_class_begin(struct generator * g) {
1184
+
1185
+ w(g, "from .basestemmer import ");
1186
+ w(g, g->options->parent_class_name);
1187
+ w(g, "~N"
1188
+ "from .among import Among~N"
1189
+ "~N"
1190
+ "~N"
1191
+ "class ~n(");
1192
+ w(g, g->options->parent_class_name);
1193
+ w(g, "):~N"
1194
+ "~+~M'''~N"
1195
+ "~MThis class implements the stemming algorithm defined by a snowball script.~N"
1196
+ "~M");
1197
+ write_generated_comment_content(g);
1198
+ w(g, "~N"
1199
+ "~M'''~N"
1200
+ "~N");
1201
+ }
1202
+
1203
+ static void generate_among_table(struct generator * g, struct among * x) {
1204
+
1205
+ struct amongvec * v = x->b;
1206
+
1207
+ g->I[0] = x->number;
1208
+
1209
+ w(g, "~Ma_~I0 = [~N~+");
1210
+ {
1211
+ int i;
1212
+ for (i = 0; i < x->literalstring_count; i++) {
1213
+ g->I[0] = v->i;
1214
+ g->I[1] = v->result;
1215
+ g->L[0] = v->b;
1216
+ g->S[0] = i < x->literalstring_count - 1 ? "," : "";
1217
+
1218
+ w(g, "~MAmong(~L0, ~I0, ~I1");
1219
+ if (v->function != 0) {
1220
+ w(g, ", \"");
1221
+ if (v->function->type == t_routine) {
1222
+ /* Need to use mangled version of private name here. */
1223
+ w(g, "_~n");
1224
+ }
1225
+ write_varname(g, v->function);
1226
+ w(g, "\"");
1227
+ }
1228
+ w(g, ")~S0~N");
1229
+ v++;
1230
+ }
1231
+ }
1232
+ w(g, "~-~M]~N~N");
1233
+ }
1234
+
1235
+ static void generate_amongs(struct generator * g) {
1236
+ struct among * x;
1237
+ for (x = g->analyser->amongs; x; x = x->next) {
1238
+ generate_among_table(g, x);
1239
+ }
1240
+ }
1241
+
1242
+ static void set_bit(symbol * b, int i) { b[i/8] |= 1 << i%8; }
1243
+
1244
+ static void generate_grouping_table(struct generator * g, struct grouping * q) {
1245
+
1246
+ int range = q->largest_ch - q->smallest_ch + 1;
1247
+ int size = (range + 7)/ 8; /* assume 8 bits per symbol */
1248
+ symbol * b = q->b;
1249
+ symbol * map = create_b(size);
1250
+ int i;
1251
+ for (i = 0; i < size; i++) map[i] = 0;
1252
+
1253
+ /* Using unicode would require revision here */
1254
+
1255
+ for (i = 0; i < SIZE(b); i++) set_bit(map, b[i] - q->smallest_ch);
1256
+
1257
+ g->V[0] = q->name;
1258
+
1259
+ w(g, "~M~W0 = [");
1260
+ for (i = 0; i < size; i++) {
1261
+ write_int(g, map[i]);
1262
+ if (i < size - 1) w(g, ", ");
1263
+ }
1264
+ w(g, "]~N~N");
1265
+ lose_b(map);
1266
+ }
1267
+
1268
+ static void generate_groupings(struct generator * g) {
1269
+ struct grouping * q;
1270
+ for (q = g->analyser->groupings; q; q = q->next) {
1271
+ if (q->name->used)
1272
+ generate_grouping_table(g, q);
1273
+ }
1274
+ }
1275
+
1276
+ static void generate_members(struct generator * g) {
1277
+
1278
+ struct name * q;
1279
+ for (q = g->analyser->names; q; q = q->next) {
1280
+ g->V[0] = q;
1281
+ switch (q->type) {
1282
+ case t_string:
1283
+ w(g, " ~W0 = \"\"~N");
1284
+ break;
1285
+ case t_integer:
1286
+ w(g, " ~W0 = 0~N");
1287
+ break;
1288
+ case t_boolean:
1289
+ w(g, " ~W0 = False~N");
1290
+ break;
1291
+ }
1292
+ }
1293
+ }
1294
+
1295
+ static void generate_methods(struct generator * g) {
1296
+
1297
+ struct node * p = g->analyser->program;
1298
+ while (p != 0) {
1299
+ generate(g, p);
1300
+ g->unreachable = false;
1301
+ p = p->right;
1302
+ }
1303
+ }
1304
+
1305
+ static void generate_label_classes(struct generator * g)
1306
+ {
1307
+ int i;
1308
+ for (i = 0; i <= g->max_label; i++) {
1309
+ g->I[0] = i;
1310
+ w(g, "~N~Nclass lab~I0(BaseException): pass~N");
1311
+ }
1312
+ }
1313
+
1314
+ extern void generate_program_python(struct generator * g) {
1315
+
1316
+ g->outbuf = str_new();
1317
+ g->failure_str = str_new();
1318
+
1319
+ write_start_comment(g, "# ", NULL);
1320
+ if (g->analyser->int_limits_used) {
1321
+ /* sys.maxsize is used in the code generated for maxint and minint */
1322
+ w(g, "import sys~N~N");
1323
+ }
1324
+ generate_class_begin(g);
1325
+
1326
+ generate_amongs(g);
1327
+ generate_groupings(g);
1328
+
1329
+ generate_members(g);
1330
+ generate_methods(g);
1331
+
1332
+ generate_label_classes(g);
1333
+
1334
+ output_str(g->options->output_src, g->outbuf);
1335
+ str_delete(g->failure_str);
1336
+ str_delete(g->outbuf);
1337
+ }