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