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