mittens 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/README.md +3 -3
  4. data/lib/mittens/version.rb +1 -1
  5. data/vendor/snowball/.github/workflows/ci.yml +216 -0
  6. data/vendor/snowball/CONTRIBUTING.rst +111 -62
  7. data/vendor/snowball/GNUmakefile +194 -136
  8. data/vendor/snowball/NEWS +798 -3
  9. data/vendor/snowball/README.rst +50 -1
  10. data/vendor/snowball/ada/src/stemmer.adb +25 -13
  11. data/vendor/snowball/ada/src/stemmer.ads +9 -9
  12. data/vendor/snowball/ada/stemmer_config.gpr +7 -7
  13. data/vendor/snowball/algorithms/basque.sbl +4 -19
  14. data/vendor/snowball/algorithms/catalan.sbl +2 -9
  15. data/vendor/snowball/algorithms/danish.sbl +1 -1
  16. data/vendor/snowball/algorithms/dutch.sbl +284 -122
  17. data/vendor/snowball/algorithms/dutch_porter.sbl +178 -0
  18. data/vendor/snowball/algorithms/english.sbl +52 -37
  19. data/vendor/snowball/algorithms/esperanto.sbl +157 -0
  20. data/vendor/snowball/algorithms/estonian.sbl +269 -0
  21. data/vendor/snowball/algorithms/finnish.sbl +2 -3
  22. data/vendor/snowball/algorithms/french.sbl +42 -16
  23. data/vendor/snowball/algorithms/german.sbl +35 -14
  24. data/vendor/snowball/algorithms/greek.sbl +76 -76
  25. data/vendor/snowball/algorithms/hungarian.sbl +8 -6
  26. data/vendor/snowball/algorithms/indonesian.sbl +14 -8
  27. data/vendor/snowball/algorithms/italian.sbl +11 -21
  28. data/vendor/snowball/algorithms/lithuanian.sbl +36 -37
  29. data/vendor/snowball/algorithms/lovins.sbl +0 -1
  30. data/vendor/snowball/algorithms/nepali.sbl +138 -37
  31. data/vendor/snowball/algorithms/norwegian.sbl +19 -5
  32. data/vendor/snowball/algorithms/porter.sbl +2 -2
  33. data/vendor/snowball/algorithms/portuguese.sbl +9 -13
  34. data/vendor/snowball/algorithms/romanian.sbl +17 -4
  35. data/vendor/snowball/algorithms/serbian.sbl +467 -468
  36. data/vendor/snowball/algorithms/spanish.sbl +5 -7
  37. data/vendor/snowball/algorithms/swedish.sbl +60 -6
  38. data/vendor/snowball/algorithms/tamil.sbl +207 -176
  39. data/vendor/snowball/algorithms/turkish.sbl +461 -445
  40. data/vendor/snowball/algorithms/yiddish.sbl +36 -38
  41. data/vendor/snowball/compiler/analyser.c +445 -192
  42. data/vendor/snowball/compiler/driver.c +109 -101
  43. data/vendor/snowball/compiler/generator.c +853 -464
  44. data/vendor/snowball/compiler/generator_ada.c +404 -366
  45. data/vendor/snowball/compiler/generator_csharp.c +297 -260
  46. data/vendor/snowball/compiler/generator_go.c +323 -254
  47. data/vendor/snowball/compiler/generator_java.c +326 -252
  48. data/vendor/snowball/compiler/generator_js.c +362 -252
  49. data/vendor/snowball/compiler/generator_pascal.c +349 -197
  50. data/vendor/snowball/compiler/generator_python.c +257 -240
  51. data/vendor/snowball/compiler/generator_rust.c +423 -251
  52. data/vendor/snowball/compiler/header.h +117 -71
  53. data/vendor/snowball/compiler/space.c +137 -68
  54. data/vendor/snowball/compiler/syswords.h +2 -2
  55. data/vendor/snowball/compiler/tokeniser.c +125 -107
  56. data/vendor/snowball/csharp/Snowball/Among.cs +14 -14
  57. data/vendor/snowball/csharp/Snowball/AssemblyInfo.cs +7 -7
  58. data/vendor/snowball/csharp/Snowball/Stemmer.cs +57 -37
  59. data/vendor/snowball/csharp/Stemwords/App.config +2 -2
  60. data/vendor/snowball/csharp/Stemwords/Program.cs +16 -12
  61. data/vendor/snowball/doc/libstemmer_c_README +7 -4
  62. data/vendor/snowball/doc/libstemmer_csharp_README +4 -1
  63. data/vendor/snowball/doc/libstemmer_java_README +12 -1
  64. data/vendor/snowball/doc/libstemmer_js_README +6 -4
  65. data/vendor/snowball/doc/libstemmer_python_README +9 -4
  66. data/vendor/snowball/examples/stemwords.c +12 -12
  67. data/vendor/snowball/go/env.go +107 -31
  68. data/vendor/snowball/go/util.go +0 -4
  69. data/vendor/snowball/include/libstemmer.h +4 -0
  70. data/vendor/snowball/java/org/tartarus/snowball/Among.java +32 -15
  71. data/vendor/snowball/java/org/tartarus/snowball/SnowballProgram.java +347 -261
  72. data/vendor/snowball/java/org/tartarus/snowball/SnowballStemmer.java +3 -0
  73. data/vendor/snowball/java/org/tartarus/snowball/TestApp.java +52 -37
  74. data/vendor/snowball/javascript/base-stemmer.js +186 -2
  75. data/vendor/snowball/javascript/stemwords.js +3 -6
  76. data/vendor/snowball/libstemmer/libstemmer_c.in +1 -1
  77. data/vendor/snowball/libstemmer/mkalgorithms.pl +6 -6
  78. data/vendor/snowball/libstemmer/mkmodules.pl +2 -2
  79. data/vendor/snowball/libstemmer/modules.txt +13 -10
  80. data/vendor/snowball/libstemmer/test.c +1 -1
  81. data/vendor/snowball/pascal/SnowballProgram.pas +84 -2
  82. data/vendor/snowball/pascal/generate.pl +13 -13
  83. data/vendor/snowball/python/create_init.py +4 -1
  84. data/vendor/snowball/python/setup.cfg +0 -3
  85. data/vendor/snowball/python/setup.py +8 -3
  86. data/vendor/snowball/python/snowballstemmer/basestemmer.py +20 -54
  87. data/vendor/snowball/python/stemwords.py +8 -12
  88. data/vendor/snowball/runtime/api.c +10 -5
  89. data/vendor/snowball/runtime/header.h +10 -9
  90. data/vendor/snowball/runtime/utilities.c +9 -9
  91. data/vendor/snowball/rust/build.rs +1 -1
  92. data/vendor/snowball/rust/src/snowball/snowball_env.rs +83 -5
  93. data/vendor/snowball/tests/stemtest.c +7 -4
  94. metadata +7 -7
  95. data/vendor/snowball/.travis.yml +0 -112
  96. data/vendor/snowball/algorithms/german2.sbl +0 -145
  97. data/vendor/snowball/algorithms/kraaij_pohlmann.sbl +0 -240
  98. data/vendor/snowball/compiler/syswords2.h +0 -13
@@ -1,4 +1,4 @@
1
-
1
+ #include <assert.h>
2
2
  #include <stdlib.h> /* for exit */
3
3
  #include <string.h> /* for strlen */
4
4
  #include <stdio.h> /* for fprintf etc */
@@ -15,7 +15,6 @@ static int new_label(struct generator * g) {
15
15
  }
16
16
 
17
17
  static struct str * vars_newname(struct generator * g) {
18
-
19
18
  struct str * output;
20
19
  g->var_number++;
21
20
  output = str_new();
@@ -24,59 +23,43 @@ static struct str * vars_newname(struct generator * g) {
24
23
  return output;
25
24
  }
26
25
 
27
-
28
26
  /* Write routines for items from the syntax tree */
29
27
 
30
28
  static void write_varname(struct generator * g, struct name * p) {
31
-
32
29
  int ch = "SBIrxg"[p->type];
33
30
  if (p->type != t_external) {
34
31
  write_char(g, ch);
35
32
  write_char(g, '_');
36
33
  }
37
- write_b(g, p->b);
34
+ write_s(g, p->s);
38
35
  }
39
36
 
40
37
  static void write_varref(struct generator * g, struct name * p) {
41
-
42
38
  /* In c#, references look just the same */
43
39
  write_varname(g, p);
44
40
  }
45
41
 
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
42
  static void write_literal_string(struct generator * g, symbol * p) {
61
-
62
- int i;
63
43
  write_string(g, "\"");
64
- for (i = 0; i < SIZE(p); i++) {
44
+ for (int i = 0; i < SIZE(p); i++) {
65
45
  int ch = p[i];
66
- if (32 <= ch && ch < 127) {
67
- if (ch == '\"' || ch == '\\') write_string(g, "\\");
68
- write_char(g, ch);
46
+ if (32 <= ch && ch < 0x590 && ch != 127) {
47
+ if (ch == '"' || ch == '\\') write_char(g, '\\');
48
+ // Our C# generator uses ENC_WIDECHARS so we need to convert.
49
+ write_wchar_as_utf8(g, ch);
69
50
  } else {
70
- write_hex(g, ch);
51
+ // Use escapes for anything over 0x590 as a crude way to avoid
52
+ // LTR characters affecting the rendering of source character
53
+ // order in confusing ways.
54
+ write_string(g, "\\u");
55
+ write_hex4(g, ch);
71
56
  }
72
57
  }
73
58
  write_string(g, "\"");
74
59
  }
75
60
 
76
61
  static void write_margin(struct generator * g) {
77
-
78
- int i;
79
- for (i = 0; i < g->margin; i++) write_string(g, " ");
62
+ for (int i = 0; i < g->margin; i++) write_string(g, " ");
80
63
  }
81
64
 
82
65
  static void write_comment(struct generator * g, struct node * p) {
@@ -88,60 +71,47 @@ static void write_comment(struct generator * g, struct node * p) {
88
71
  }
89
72
 
90
73
  static void write_block_start(struct generator * g) {
91
-
92
74
  w(g, "~M{~+~N");
93
75
  }
94
76
 
95
- static void write_block_end(struct generator * g) /* block end */ {
96
-
77
+ static void write_block_end(struct generator * g) {
97
78
  w(g, "~-~M}~N");
98
79
  }
99
80
 
100
81
  static void write_savecursor(struct generator * g, struct node * p,
101
82
  struct str * savevar) {
102
-
103
83
  g->B[0] = str_data(savevar);
104
84
  g->S[1] = "";
105
85
  if (p->mode != m_forward) g->S[1] = "limit - ";
106
86
  writef(g, "~Mint ~B0 = ~S1cursor;~N", p);
107
87
  }
108
88
 
109
- static void restore_string(struct node * p, struct str * out, struct str * savevar) {
110
-
111
- str_clear(out);
89
+ static void append_restore_string(struct node * p, struct str * out, struct str * savevar) {
112
90
  str_append_string(out, "cursor = ");
113
91
  if (p->mode != m_forward) str_append_string(out, "limit - ");
114
92
  str_append(out, savevar);
115
93
  str_append_string(out, ";");
116
94
  }
117
95
 
118
- static void write_restorecursor(struct generator * g, struct node * p,
119
- struct str * savevar) {
120
-
121
- struct str * temp = str_new();
96
+ static void write_restorecursor(struct generator * g, struct node * p, struct str * savevar) {
122
97
  write_margin(g);
123
- restore_string(p, temp, savevar);
124
- write_str(g, temp);
98
+ append_restore_string(p, g->outbuf, savevar);
125
99
  write_newline(g);
126
- str_delete(temp);
127
100
  }
128
101
 
129
102
  static void write_inc_cursor(struct generator * g, struct node * p) {
130
-
131
103
  write_margin(g);
132
104
  write_string(g, p->mode == m_forward ? "cursor++;" : "cursor--;");
133
105
  write_newline(g);
134
106
  }
135
107
 
136
108
  static void wsetl(struct generator * g, int n) {
137
-
138
109
  w(g, "~-~Mlab~+");
139
110
  write_int(g, n);
140
111
  w(g, ": ; ~N");
141
112
  }
142
113
 
143
114
  static void wgotol(struct generator * g, int n) {
144
-
145
115
  write_margin(g);
146
116
  write_string(g, "goto lab");
147
117
  write_int(g, n);
@@ -150,7 +120,6 @@ static void wgotol(struct generator * g, int n) {
150
120
  }
151
121
 
152
122
  static void write_failure(struct generator * g) {
153
-
154
123
  if (str_len(g->failure_str) != 0) {
155
124
  write_block_start(g);
156
125
  write_margin(g);
@@ -173,8 +142,7 @@ static void write_failure(struct generator * g) {
173
142
  write_block_end(g);
174
143
  }
175
144
 
176
- static void write_failure_if(struct generator * g, char * s, struct node * p) {
177
-
145
+ static void write_failure_if(struct generator * g, const char * s, struct node * p) {
178
146
  writef(g, "~Mif (", p);
179
147
  writef(g, s, p);
180
148
  writef(g, ")~N", p);
@@ -185,7 +153,6 @@ static void write_failure_if(struct generator * g, char * s, struct node * p) {
185
153
 
186
154
  /* if at limit fail */
187
155
  static void write_check_limit(struct generator * g, struct node * p) {
188
-
189
156
  if (p->mode == m_forward) {
190
157
  write_failure_if(g, "cursor >= limit", p);
191
158
  } else {
@@ -195,18 +162,18 @@ static void write_check_limit(struct generator * g, struct node * p) {
195
162
 
196
163
  /* Formatted write. */
197
164
  static void writef(struct generator * g, const char * input, struct node * p) {
165
+ (void)p;
198
166
  int i = 0;
199
- int l = strlen(input);
200
167
 
201
- while (i < l) {
168
+ while (input[i]) {
202
169
  int ch = input[i++];
203
170
  if (ch != '~') {
204
171
  write_char(g, ch);
205
172
  continue;
206
173
  }
207
- switch (input[i++]) {
208
- default: write_char(g, input[i - 1]); continue;
209
- case 'C': write_comment(g, p); continue;
174
+ ch = input[i++];
175
+ switch (ch) {
176
+ case '~': write_char(g, '~'); continue;
210
177
  case 'f': write_block_start(g);
211
178
  write_failure(g);
212
179
  write_block_end(g);
@@ -215,21 +182,65 @@ static void writef(struct generator * g, const char * input, struct node * p) {
215
182
  case 'N': write_newline(g); continue;
216
183
  case '{': write_block_start(g); continue;
217
184
  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;
185
+ case 'S': {
186
+ int j = input[i++] - '0';
187
+ if (j < 0 || j > (int)(sizeof(g->S) / sizeof(g->S[0]))) {
188
+ printf("Invalid escape sequence ~%c%c in writef(g, \"%s\", p)\n",
189
+ ch, input[i - 1], input);
190
+ exit(1);
191
+ }
192
+ write_string(g, g->S[j]);
193
+ continue;
194
+ }
195
+ case 'B': {
196
+ int j = input[i++] - '0';
197
+ if (j < 0 || j > (int)(sizeof(g->B) / sizeof(g->B[0])))
198
+ goto invalid_escape2;
199
+ write_s(g, g->B[j]);
200
+ continue;
201
+ }
202
+ case 'I': {
203
+ int j = input[i++] - '0';
204
+ if (j < 0 || j > (int)(sizeof(g->I) / sizeof(g->I[0])))
205
+ goto invalid_escape2;
206
+ write_int(g, g->I[j]);
207
+ continue;
208
+ }
209
+ case 'V':
210
+ case 'W': {
211
+ int j = input[i++] - '0';
212
+ if (j < 0 || j > (int)(sizeof(g->V) / sizeof(g->V[0])))
213
+ goto invalid_escape2;
214
+ if (ch == 'V')
215
+ write_varref(g, g->V[j]);
216
+ else
217
+ write_varname(g, g->V[j]);
218
+ continue;
219
+ }
220
+ case 'L': {
221
+ int j = input[i++] - '0';
222
+ if (j < 0 || j > (int)(sizeof(g->L) / sizeof(g->L[0])))
223
+ goto invalid_escape2;
224
+ write_literal_string(g, g->L[j]);
225
+ continue;
226
+ }
224
227
  case '+': g->margin++; continue;
225
228
  case '-': g->margin--; continue;
226
229
  case 'n': write_string(g, g->options->name); continue;
230
+ default:
231
+ printf("Invalid escape sequence ~%c in writef(g, \"%s\", p)\n",
232
+ ch, input);
233
+ exit(1);
234
+ invalid_escape2:
235
+ printf("Invalid escape sequence ~%c%c in writef(g, \"%s\", p)\n",
236
+ ch, input[i - 1], input);
237
+ exit(1);
227
238
  }
228
239
  }
229
240
  }
230
241
 
231
242
  static void w(struct generator * g, const char * s) {
232
- writef(g, s, 0);
243
+ writef(g, s, NULL);
233
244
  }
234
245
 
235
246
  static void generate_AE(struct generator * g, struct node * p) {
@@ -273,7 +284,6 @@ static void generate_AE(struct generator * g, struct node * p) {
273
284
  }
274
285
 
275
286
  static void generate_bra(struct generator * g, struct node * p) {
276
-
277
287
  write_comment(g, p);
278
288
  p = p->left;
279
289
  while (p) {
@@ -283,27 +293,32 @@ static void generate_bra(struct generator * g, struct node * p) {
283
293
  }
284
294
 
285
295
  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);
296
+ struct str * savevar = NULL;
297
+ if (K_needed(g, p->left)) {
298
+ savevar = vars_newname(g);
299
+ }
289
300
 
290
301
  write_comment(g, p);
291
302
 
292
- if (keep_c) write_savecursor(g, p, savevar);
303
+ if (savevar) write_savecursor(g, p, savevar);
293
304
 
294
305
  p = p->left;
295
306
  while (p) {
296
307
  generate(g, p);
297
- if (keep_c && p->right != 0) write_restorecursor(g, p, savevar);
308
+ if (savevar && p->right != NULL) write_restorecursor(g, p, savevar);
298
309
  p = p->right;
299
310
  }
300
- str_delete(savevar);
311
+
312
+ if (savevar) {
313
+ str_delete(savevar);
314
+ }
301
315
  }
302
316
 
303
317
  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);
318
+ struct str * savevar = NULL;
319
+ if (K_needed(g, p->left)) {
320
+ savevar = vars_newname(g);
321
+ }
307
322
 
308
323
  int used = g->label_used;
309
324
  int a0 = g->failure_label;
@@ -312,7 +327,7 @@ static void generate_or(struct generator * g, struct node * p) {
312
327
  int out_lab = new_label(g);
313
328
  write_comment(g, p);
314
329
 
315
- if (keep_c) {
330
+ if (savevar) {
316
331
  write_block_start(g);
317
332
  write_savecursor(g, p, savevar);
318
333
  }
@@ -320,20 +335,20 @@ static void generate_or(struct generator * g, struct node * p) {
320
335
  p = p->left;
321
336
  str_clear(g->failure_str);
322
337
 
323
- if (p == 0) {
324
- /* p should never be 0 after an or: there should be at least two
338
+ if (p == NULL) {
339
+ /* p should never be NULL after an or: there should be at least two
325
340
  * sub nodes. */
326
341
  fprintf(stderr, "Error: \"or\" node without children nodes.");
327
342
  exit(1);
328
343
  }
329
- while (p->right != 0) {
344
+ while (p->right != NULL) {
330
345
  g->failure_label = new_label(g);
331
346
  g->label_used = 0;
332
347
  generate(g, p);
333
348
  wgotol(g, out_lab);
334
349
  if (g->label_used)
335
350
  wsetl(g, g->failure_label);
336
- if (keep_c) write_restorecursor(g, p, savevar);
351
+ if (savevar) write_restorecursor(g, p, savevar);
337
352
  p = p->right;
338
353
  }
339
354
 
@@ -344,15 +359,15 @@ static void generate_or(struct generator * g, struct node * p) {
344
359
 
345
360
  generate(g, p);
346
361
 
347
- if (keep_c)
362
+ if (savevar) {
348
363
  write_block_end(g);
364
+ str_delete(savevar);
365
+ }
349
366
 
350
367
  wsetl(g, out_lab);
351
- str_delete(savevar);
352
368
  }
353
369
 
354
370
  static void generate_backwards(struct generator * g, struct node * p) {
355
-
356
371
  write_comment(g, p);
357
372
  writef(g, "~Mlimit_backward = cursor;~N"
358
373
  "~Mcursor = limit;~N", p);
@@ -362,16 +377,17 @@ static void generate_backwards(struct generator * g, struct node * p) {
362
377
 
363
378
 
364
379
  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);
380
+ struct str * savevar = NULL;
381
+ if (K_needed(g, p->left)) {
382
+ savevar = vars_newname(g);
383
+ }
368
384
 
369
385
  int used = g->label_used;
370
386
  int a0 = g->failure_label;
371
387
  struct str * a1 = str_copy(g->failure_str);
372
388
 
373
389
  write_comment(g, p);
374
- if (keep_c) {
390
+ if (savevar) {
375
391
  write_block_start(g);
376
392
  write_savecursor(g, p, savevar);
377
393
  }
@@ -396,58 +412,55 @@ static void generate_not(struct generator * g, struct node * p) {
396
412
  wsetl(g, l);
397
413
  }
398
414
 
399
- if (keep_c) {
415
+ if (savevar) {
400
416
  write_restorecursor(g, p, savevar);
401
417
  write_block_end(g);
418
+ str_delete(savevar);
402
419
  }
403
- str_delete(savevar);
404
420
  }
405
421
 
406
422
 
407
423
  static void generate_try(struct generator * g, struct node * p) {
424
+ struct str * savevar = NULL;
425
+ if (K_needed(g, p->left)) {
426
+ savevar = vars_newname(g);
427
+ }
408
428
 
409
- struct str * savevar = vars_newname(g);
410
- int keep_c = K_needed(g, p->left);
429
+ g->failure_label = new_label(g);
430
+ g->label_used = 0;
431
+ str_clear(g->failure_str);
411
432
 
412
433
  write_comment(g, p);
413
-
414
- if (keep_c) {
434
+ if (savevar) {
415
435
  write_block_start(g);
416
436
  write_savecursor(g, p, savevar);
437
+ append_restore_string(p, g->failure_str, savevar);
417
438
  }
418
439
 
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
440
  generate(g, p->left);
425
441
 
426
442
  if (g->label_used)
427
443
  wsetl(g, g->failure_label);
428
444
 
429
- if (keep_c)
445
+ if (savevar) {
430
446
  write_block_end(g);
431
-
432
- str_delete(savevar);
447
+ str_delete(savevar);
448
+ }
433
449
  }
434
450
 
435
451
  static void generate_set(struct generator * g, struct node * p) {
436
-
437
452
  write_comment(g, p);
438
453
  g->V[0] = p->name;
439
454
  writef(g, "~M~V0 = true;~N", p);
440
455
  }
441
456
 
442
457
  static void generate_unset(struct generator * g, struct node * p) {
443
-
444
458
  write_comment(g, p);
445
459
  g->V[0] = p->name;
446
460
  writef(g, "~M~V0 = false;~N", p);
447
461
  }
448
462
 
449
463
  static void generate_fail(struct generator * g, struct node * p) {
450
-
451
464
  write_comment(g, p);
452
465
  generate(g, p->left);
453
466
  write_failure(g);
@@ -456,32 +469,35 @@ static void generate_fail(struct generator * g, struct node * p) {
456
469
  /* generate_test() also implements 'reverse' */
457
470
 
458
471
  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);
472
+ struct str * savevar = NULL;
473
+ if (K_needed(g, p->left)) {
474
+ savevar = vars_newname(g);
475
+ }
462
476
 
463
477
  write_comment(g, p);
464
478
 
465
- if (keep_c) {
479
+ if (savevar) {
466
480
  write_block_start(g);
467
481
  write_savecursor(g, p, savevar);
468
482
  }
469
483
 
470
484
  generate(g, p->left);
471
485
 
472
- if (keep_c) {
486
+ if (savevar) {
473
487
  write_restorecursor(g, p, savevar);
474
488
  write_block_end(g);
489
+ str_delete(savevar);
475
490
  }
476
- str_delete(savevar);
477
491
  }
478
492
 
479
493
  static void generate_do(struct generator * g, struct node * p) {
494
+ struct str * savevar = NULL;
495
+ if (K_needed(g, p->left)) {
496
+ savevar = vars_newname(g);
497
+ }
480
498
 
481
- struct str * savevar = vars_newname(g);
482
- int keep_c = K_needed(g, p->left);
483
499
  write_comment(g, p);
484
- if (keep_c) {
500
+ if (savevar) {
485
501
  write_block_start(g);
486
502
  write_savecursor(g, p, savevar);
487
503
  }
@@ -502,15 +518,21 @@ static void generate_do(struct generator * g, struct node * p) {
502
518
  wsetl(g, g->failure_label);
503
519
  }
504
520
 
505
- if (keep_c) {
521
+ if (savevar) {
506
522
  write_restorecursor(g, p, savevar);
507
523
  write_block_end(g);
524
+ str_delete(savevar);
508
525
  }
526
+ }
509
527
 
510
- str_delete(savevar);
528
+ static void generate_next(struct generator * g, struct node * p) {
529
+ write_comment(g, p);
530
+ write_check_limit(g, p);
531
+ write_inc_cursor(g, p);
511
532
  }
512
533
 
513
534
  static void generate_GO_grouping(struct generator * g, struct node * p, int is_goto, int complement) {
535
+ write_comment(g, p);
514
536
 
515
537
  struct grouping * q = p->name->grouping;
516
538
  g->S[0] = p->mode == m_forward ? "" : "_b";
@@ -533,35 +555,19 @@ static void generate_GO_grouping(struct generator * g, struct node * p, int is_g
533
555
  }
534
556
 
535
557
  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);
558
+ write_comment(g, p);
539
559
 
540
560
  int used = g->label_used;
541
561
  int a0 = g->failure_label;
542
562
  struct str * a1 = str_copy(g->failure_str);
543
563
 
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
564
  w(g, "~Mwhile (true)~N~{");
562
- write_comment(g, p);
563
565
 
564
- if (keep_c) write_savecursor(g, p, savevar);
566
+ struct str * savevar = NULL;
567
+ if (style == 1 || repeat_restore(g, p->left)) {
568
+ savevar = vars_newname(g);
569
+ write_savecursor(g, p, savevar);
570
+ }
565
571
 
566
572
  g->failure_label = new_label(g);
567
573
  g->label_used = 0;
@@ -576,8 +582,10 @@ static void generate_GO(struct generator * g, struct node * p, int style) {
576
582
  w(g, "~Mbreak;~N");
577
583
  if (g->label_used)
578
584
  wsetl(g, g->failure_label);
579
- if (keep_c)
585
+ if (savevar) {
580
586
  write_restorecursor(g, p, savevar);
587
+ str_delete(savevar);
588
+ }
581
589
 
582
590
  g->label_used = used;
583
591
  g->failure_label = a0;
@@ -586,12 +594,10 @@ static void generate_GO(struct generator * g, struct node * p, int style) {
586
594
 
587
595
  write_check_limit(g, p);
588
596
  write_inc_cursor(g, p);
589
- str_delete(savevar);
590
597
  w(g, "~}");
591
598
  }
592
599
 
593
600
  static void generate_loop(struct generator * g, struct node * p) {
594
-
595
601
  struct str * loopvar = vars_newname(g);
596
602
  write_comment(g, p);
597
603
  g->B[0] = str_data(loopvar);
@@ -608,19 +614,20 @@ static void generate_loop(struct generator * g, struct node * p) {
608
614
  }
609
615
 
610
616
  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
617
  writef(g, "~Mwhile (true)~N~{", p);
615
618
 
616
- if (keep_c) write_savecursor(g, p, savevar);
619
+ struct str * savevar = NULL;
620
+ if (repeat_restore(g, p->left)) {
621
+ savevar = vars_newname(g);
622
+ write_savecursor(g, p, savevar);
623
+ }
617
624
 
618
625
  g->failure_label = new_label(g);
619
626
  g->label_used = 0;
620
627
  str_clear(g->failure_str);
621
628
  generate(g, p->left);
622
629
 
623
- if (atleast_case != 0) {
630
+ if (atleast_case != NULL) {
624
631
  g->B[0] = str_data(atleast_case);
625
632
  w(g, "~M~B0--;~N");
626
633
  }
@@ -630,10 +637,12 @@ static void generate_repeat_or_atleast(struct generator * g, struct node * p, st
630
637
  if (g->label_used)
631
638
  wsetl(g, g->failure_label);
632
639
 
633
- if (keep_c) write_restorecursor(g, p, savevar);
640
+ if (savevar) {
641
+ write_restorecursor(g, p, savevar);
642
+ str_delete(savevar);
643
+ }
634
644
 
635
645
  w(g, "~Mbreak;~N~}");
636
- str_delete(savevar);
637
646
  }
638
647
 
639
648
  static void generate_repeat(struct generator * g, struct node * p) {
@@ -642,8 +651,8 @@ static void generate_repeat(struct generator * g, struct node * p) {
642
651
  }
643
652
 
644
653
  static void generate_atleast(struct generator * g, struct node * p) {
645
-
646
654
  struct str * loopvar = vars_newname(g);
655
+
647
656
  write_comment(g, p);
648
657
  w(g, "~{");
649
658
  g->B[0] = str_data(loopvar);
@@ -669,14 +678,12 @@ static void generate_atleast(struct generator * g, struct node * p) {
669
678
  }
670
679
 
671
680
  static void generate_setmark(struct generator * g, struct node * p) {
672
-
673
681
  write_comment(g, p);
674
682
  g->V[0] = p->name;
675
683
  writef(g, "~M~V0 = cursor;~N", p);
676
684
  }
677
685
 
678
686
  static void generate_tomark(struct generator * g, struct node * p) {
679
-
680
687
  write_comment(g, p);
681
688
  g->S[0] = p->mode == m_forward ? ">" : "<";
682
689
 
@@ -688,7 +695,6 @@ static void generate_tomark(struct generator * g, struct node * p) {
688
695
  }
689
696
 
690
697
  static void generate_atmark(struct generator * g, struct node * p) {
691
-
692
698
  write_comment(g, p);
693
699
  w(g, "~Mif (cursor != "); generate_AE(g, p->AE); writef(g, ")~N", p);
694
700
  write_block_start(g);
@@ -697,7 +703,6 @@ static void generate_atmark(struct generator * g, struct node * p) {
697
703
  }
698
704
 
699
705
  static void generate_hop(struct generator * g, struct node * p) {
700
-
701
706
  write_comment(g, p);
702
707
  g->S[0] = p->mode == m_forward ? "+" : "-";
703
708
 
@@ -721,28 +726,17 @@ static void generate_hop(struct generator * g, struct node * p) {
721
726
  }
722
727
 
723
728
  static void generate_delete(struct generator * g, struct node * p) {
724
-
725
729
  write_comment(g, p);
726
730
  writef(g, "~Mslice_del();~N", p);
727
731
  }
728
732
 
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
733
  static void generate_tolimit(struct generator * g, struct node * p) {
738
-
739
734
  write_comment(g, p);
740
735
  g->S[0] = p->mode == m_forward ? "limit" : "limit_backward";
741
736
  writef(g, "~Mcursor = ~S0;~N", p);
742
737
  }
743
738
 
744
739
  static void generate_atlimit(struct generator * g, struct node * p) {
745
-
746
740
  write_comment(g, p);
747
741
  g->S[0] = p->mode == m_forward ? "limit" : "limit_backward";
748
742
  g->S[1] = p->mode == m_forward ? "<" : ">";
@@ -750,37 +744,32 @@ static void generate_atlimit(struct generator * g, struct node * p) {
750
744
  }
751
745
 
752
746
  static void generate_leftslice(struct generator * g, struct node * p) {
753
-
754
747
  write_comment(g, p);
755
748
  g->S[0] = p->mode == m_forward ? "bra" : "ket";
756
749
  writef(g, "~M~S0 = cursor;~N", p);
757
750
  }
758
751
 
759
752
  static void generate_rightslice(struct generator * g, struct node * p) {
760
-
761
753
  write_comment(g, p);
762
754
  g->S[0] = p->mode == m_forward ? "ket" : "bra";
763
755
  writef(g, "~M~S0 = cursor;~N", p);
764
756
  }
765
757
 
766
758
  static void generate_assignto(struct generator * g, struct node * p) {
767
-
768
759
  write_comment(g, p);
769
760
  g->V[0] = p->name;
770
761
  writef(g, "~Massign_to(~V0);~N", p);
771
762
  }
772
763
 
773
764
  static void generate_sliceto(struct generator * g, struct node * p) {
774
-
775
765
  write_comment(g, p);
776
766
  g->V[0] = p->name;
777
767
  writef(g, "~Mslice_to(~V0);~N", p);
778
768
  }
779
769
 
780
770
  static void generate_address(struct generator * g, struct node * p) {
781
-
782
771
  symbol * b = p->literalstring;
783
- if (b != 0) {
772
+ if (b != NULL) {
784
773
  write_literal_string(g, b);
785
774
  } else {
786
775
  write_varref(g, p->name);
@@ -788,7 +777,6 @@ static void generate_address(struct generator * g, struct node * p) {
788
777
  }
789
778
 
790
779
  static void generate_insert(struct generator * g, struct node * p, int style) {
791
-
792
780
  int keep_c = style == c_attach;
793
781
  write_comment(g, p);
794
782
  if (p->mode == m_backward) keep_c = !keep_c;
@@ -800,7 +788,6 @@ static void generate_insert(struct generator * g, struct node * p, int style) {
800
788
  }
801
789
 
802
790
  static void generate_assignfrom(struct generator * g, struct node * p) {
803
-
804
791
  int keep_c = p->mode == m_forward; /* like 'attach' */
805
792
 
806
793
  write_comment(g, p);
@@ -815,9 +802,7 @@ static void generate_assignfrom(struct generator * g, struct node * p) {
815
802
  if (keep_c) w(g, "~Mcursor = c;~N~}");
816
803
  }
817
804
 
818
-
819
805
  static void generate_slicefrom(struct generator * g, struct node * p) {
820
-
821
806
  write_comment(g, p);
822
807
  w(g, "~Mslice_from(");
823
808
  generate_address(g, p);
@@ -825,7 +810,6 @@ static void generate_slicefrom(struct generator * g, struct node * p) {
825
810
  }
826
811
 
827
812
  static void generate_setlimit(struct generator * g, struct node * p) {
828
- struct str * savevar = vars_newname(g);
829
813
  struct str * varname = vars_newname(g);
830
814
  write_comment(g, p);
831
815
  if (p->left && p->left->type == c_tomark) {
@@ -838,6 +822,7 @@ static void generate_setlimit(struct generator * g, struct node * p) {
838
822
  * restore c.
839
823
  */
840
824
  struct node * q = p->left;
825
+ write_comment(g, q);
841
826
  g->S[0] = q->mode == m_forward ? ">" : "<";
842
827
  w(g, "~Mif (cursor ~S0 "); generate_AE(g, q->AE); w(g, ")~N");
843
828
  write_block_start(g);
@@ -864,7 +849,9 @@ static void generate_setlimit(struct generator * g, struct node * p) {
864
849
  str_append_ch(g->failure_str, ';');
865
850
  }
866
851
  } else {
852
+ struct str * savevar = vars_newname(g);
867
853
  write_savecursor(g, p, savevar);
854
+
868
855
  generate(g, p->left);
869
856
 
870
857
  g->B[0] = str_data(varname);
@@ -886,6 +873,7 @@ static void generate_setlimit(struct generator * g, struct node * p) {
886
873
  str_append(g->failure_str, varname);
887
874
  str_append_ch(g->failure_str, ';');
888
875
  }
876
+ str_delete(savevar);
889
877
  }
890
878
 
891
879
  generate(g, p->aux);
@@ -895,15 +883,14 @@ static void generate_setlimit(struct generator * g, struct node * p) {
895
883
  write_newline(g);
896
884
 
897
885
  str_delete(varname);
898
- str_delete(savevar);
899
886
  }
900
887
 
901
888
  /* dollar sets snowball up to operate on a string variable as if it were the
902
889
  * current string */
903
890
  static void generate_dollar(struct generator * g, struct node * p) {
891
+ write_comment(g, p);
904
892
 
905
893
  struct str * savevar = vars_newname(g);
906
- write_comment(g, p);
907
894
  g->V[0] = p->name;
908
895
 
909
896
  str_assign(g->failure_str, "copy_from(");
@@ -924,37 +911,67 @@ static void generate_dollar(struct generator * g, struct node * p) {
924
911
  str_delete(savevar);
925
912
  }
926
913
 
927
- static void generate_integer_assign(struct generator * g, struct node * p, char * s) {
928
-
914
+ static void generate_integer_assign(struct generator * g, struct node * p, const char * s) {
915
+ write_comment(g, p);
929
916
  g->V[0] = p->name;
930
917
  g->S[0] = s;
931
- w(g, "~M~V0 ~S0 "); generate_AE(g, p->AE); w(g, ";~N");
918
+ w(g, "~M~V0 ~S0 ");
919
+ generate_AE(g, p->AE);
920
+ w(g, ";~N");
932
921
  }
933
922
 
934
- static void generate_integer_test(struct generator * g, struct node * p, char * s) {
935
-
936
- w(g, "~Mif (!(");
923
+ static void generate_integer_test(struct generator * g, struct node * p) {
924
+ write_comment(g, p);
925
+ int relop = p->type;
926
+ int optimise_to_return = (g->failure_label == x_return && p->right && p->right->type == c_functionend);
927
+ if (optimise_to_return) {
928
+ w(g, "~Mreturn ");
929
+ p->right = NULL;
930
+ } else {
931
+ w(g, "~Mif (");
932
+ // We want the inverse of the snowball test here.
933
+ relop ^= 1;
934
+ }
937
935
  generate_AE(g, p->left);
938
- write_char(g, ' ');
939
- write_string(g, s);
940
- write_char(g, ' ');
936
+ // Relational operators are the same as C.
937
+ write_c_relop(g, relop);
941
938
  generate_AE(g, p->AE);
942
- w(g, "))~N");
943
- write_block_start(g);
944
- write_failure(g);
945
- write_block_end(g);
939
+ if (optimise_to_return) {
940
+ w(g, ";~N");
941
+ } else {
942
+ w(g, ")~N");
943
+ write_block_start(g);
944
+ write_failure(g);
945
+ write_block_end(g);
946
+ }
946
947
  }
947
948
 
948
949
  static void generate_call(struct generator * g, struct node * p) {
949
-
950
+ int signals = check_possible_signals_list(g, p->name->definition, c_define, 0);
950
951
  write_comment(g, p);
951
952
  g->V[0] = p->name;
952
- w(g, "~Mif (!~V0())~N~+");
953
- write_failure(g);
954
- w(g, "~-");
953
+ if (g->failure_label == x_return &&
954
+ (signals == 0 || (p->right && p->right->type == c_functionend))) {
955
+ /* Always fails or tail call. */
956
+ writef(g, "~Mreturn ~V0();~N", p);
957
+ return;
958
+ }
959
+ if (signals == 1) {
960
+ /* Always succeeds. */
961
+ writef(g, "~M~V0();~N", p);
962
+ } else if (signals == 0) {
963
+ /* Always fails. */
964
+ writef(g, "~M~V0();~N", p);
965
+ write_failure(g);
966
+ } else {
967
+ w(g, "~Mif (!~V0())~N~+");
968
+ write_failure(g);
969
+ w(g, "~-");
970
+ }
955
971
  }
956
972
 
957
973
  static void generate_grouping(struct generator * g, struct node * p, int complement) {
974
+ write_comment(g, p);
958
975
 
959
976
  struct grouping * q = p->name->grouping;
960
977
  g->S[0] = p->mode == m_forward ? "" : "_b";
@@ -966,7 +983,6 @@ static void generate_grouping(struct generator * g, struct node * p, int complem
966
983
  }
967
984
 
968
985
  static void generate_namedstring(struct generator * g, struct node * p) {
969
-
970
986
  write_comment(g, p);
971
987
  g->S[0] = p->mode == m_forward ? "" : "_b";
972
988
  g->V[0] = p->name;
@@ -983,8 +999,10 @@ static void generate_literalstring(struct generator * g, struct node * p) {
983
999
 
984
1000
  static void generate_define(struct generator * g, struct node * p) {
985
1001
  struct name * q = p->name;
1002
+ if (q->type == t_routine && !q->used) return;
986
1003
 
987
- struct str * saved_output = g->outbuf;
1004
+ write_newline(g);
1005
+ write_comment(g, p);
988
1006
 
989
1007
  if (q->type == t_routine) {
990
1008
  g->S[0] = "private";
@@ -992,8 +1010,10 @@ static void generate_define(struct generator * g, struct node * p) {
992
1010
  g->S[0] = "protected override";
993
1011
  }
994
1012
  g->V[0] = q;
995
- w(g, "~N~M~S0 bool ~V0()~N~M{~+~N");
1013
+ w(g, "~M~S0 bool ~V0()~N~M{~+~N");
996
1014
 
1015
+ /* Save output. */
1016
+ struct str * saved_output = g->outbuf;
997
1017
  g->outbuf = str_new();
998
1018
 
999
1019
  g->next_label = 0;
@@ -1003,9 +1023,16 @@ static void generate_define(struct generator * g, struct node * p) {
1003
1023
  str_clear(g->failure_str);
1004
1024
  g->failure_label = x_return;
1005
1025
  g->label_used = 0;
1006
- g->keep_count = 0;
1026
+ int signals = check_possible_signals_list(g, p->left, c_define, 0);
1027
+
1028
+ /* Generate function body. */
1007
1029
  generate(g, p->left);
1008
- w(g, "~Mreturn true;~N");
1030
+ if (p->left->right) {
1031
+ assert(p->left->right->type == c_functionend);
1032
+ if (signals) {
1033
+ generate(g, p->left->right);
1034
+ }
1035
+ }
1009
1036
  w(g, "~}");
1010
1037
 
1011
1038
  str_append(saved_output, g->outbuf);
@@ -1013,62 +1040,79 @@ static void generate_define(struct generator * g, struct node * p) {
1013
1040
  g->outbuf = saved_output;
1014
1041
  }
1015
1042
 
1043
+ static void generate_functionend(struct generator * g, struct node * p) {
1044
+ (void)p;
1045
+ w(g, "~Mreturn true;~N");
1046
+ }
1047
+
1016
1048
  static void generate_substring(struct generator * g, struct node * p) {
1049
+ write_comment(g, p);
1017
1050
 
1018
1051
  struct among * x = p->among;
1019
1052
 
1020
- write_comment(g, p);
1021
-
1022
1053
  g->S[0] = p->mode == m_forward ? "" : "_b";
1023
1054
  g->I[0] = x->number;
1024
1055
 
1025
- if (!x->amongvar_needed) {
1026
- write_failure_if(g, "find_among~S0(a_~I0) == 0", p);
1027
- } else {
1056
+ if (x->amongvar_needed) {
1028
1057
  writef(g, "~Mamong_var = find_among~S0(a_~I0);~N", p);
1029
- write_failure_if(g, "among_var == 0", p);
1058
+ if (!x->always_matches) {
1059
+ write_failure_if(g, "among_var == 0", p);
1060
+ }
1061
+ } else if (x->always_matches) {
1062
+ writef(g, "~Mfind_among~S0(a_~I0);~N", p);
1063
+ } else {
1064
+ write_failure_if(g, "find_among~S0(a_~I0) == 0", p);
1030
1065
  }
1031
1066
  }
1032
1067
 
1033
1068
  static void generate_among(struct generator * g, struct node * p) {
1034
-
1035
1069
  struct among * x = p->among;
1036
1070
 
1037
- if (x->substring == 0) generate_substring(g, p);
1038
-
1039
- if (x->starter != 0) generate(g, x->starter);
1071
+ if (x->substring == NULL) {
1072
+ generate_substring(g, p);
1073
+ } else {
1074
+ write_comment(g, p);
1075
+ }
1040
1076
 
1041
1077
  if (x->command_count == 1 && x->nocommand_count == 0) {
1042
1078
  /* Only one outcome ("no match" already handled). */
1043
1079
  generate(g, x->commands[0]);
1044
1080
  } else if (x->command_count > 0) {
1045
- int i;
1046
1081
  w(g, "~Mswitch (among_var) {~N~+");
1047
- for (i = 1; i <= x->command_count; i++) {
1082
+ for (int i = 1; i <= x->command_count; i++) {
1048
1083
  g->I[0] = i;
1049
- w(g, "~Mcase ~I0:~N~+");
1084
+ /* Put a block around each case which seems to workaround bogus
1085
+ * compiler errors (typically with repeat reports at the same
1086
+ * location):
1087
+ *
1088
+ * dutchStemmer.generated.cs(543,25): error CS0165: Use of unassigned local variable `c5'
1089
+ *
1090
+ * The c5 variable is initialised at point of declaration and we
1091
+ * don't `goto` into the block it is declared in from outside so
1092
+ * this seems to be buggy code flow analysis in the compiler.
1093
+ * Unclear where to usefully report mono bugs in 2025 so I've
1094
+ * not tried.
1095
+ */
1096
+ w(g, "~Mcase ~I0: {~N~+");
1050
1097
  generate(g, x->commands[i - 1]);
1051
- w(g, "~Mbreak;~N~-");
1098
+ w(g, "~Mbreak;~N~-~M}~N");
1052
1099
  }
1053
1100
  write_block_end(g);
1054
1101
  }
1055
1102
  }
1056
1103
 
1057
1104
  static void generate_booltest(struct generator * g, struct node * p) {
1058
-
1059
1105
  write_comment(g, p);
1060
1106
  g->V[0] = p->name;
1061
1107
  write_failure_if(g, "!(~V0)", p);
1062
1108
  }
1063
1109
 
1064
1110
  static void generate_false(struct generator * g, struct node * p) {
1065
-
1066
1111
  write_comment(g, p);
1067
1112
  write_failure(g);
1068
1113
  }
1069
1114
 
1070
1115
  static void generate_debug(struct generator * g, struct node * p) {
1071
-
1072
1116
  write_comment(g, p);
1073
1117
  g->I[0] = g->debug_count++;
1074
1118
  g->I[1] = p->line_number;
@@ -1076,7 +1120,6 @@ static void generate_debug(struct generator * g, struct node * p) {
1076
1120
  }
1077
1121
 
1078
1122
  static void generate(struct generator * g, struct node * p) {
1079
-
1080
1123
  int used = g->label_used;
1081
1124
  int a0 = g->failure_label;
1082
1125
  struct str * a1 = str_copy(g->failure_str);
@@ -1097,6 +1140,11 @@ static void generate(struct generator * g, struct node * p) {
1097
1140
  case c_do: generate_do(g, p); break;
1098
1141
  case c_goto: generate_GO(g, p, 1); break;
1099
1142
  case c_gopast: generate_GO(g, p, 0); break;
1143
+ case c_goto_grouping: generate_GO_grouping(g, p, 1, 0); break;
1144
+ case c_gopast_grouping:
1145
+ generate_GO_grouping(g, p, 0, 0); break;
1146
+ case c_goto_non: generate_GO_grouping(g, p, 1, 1); break;
1147
+ case c_gopast_non: generate_GO_grouping(g, p, 0, 1); break;
1100
1148
  case c_repeat: generate_repeat(g, p); break;
1101
1149
  case c_loop: generate_loop(g, p); break;
1102
1150
  case c_atleast: generate_atleast(g, p); break;
@@ -1123,12 +1171,14 @@ static void generate(struct generator * g, struct node * p) {
1123
1171
  case c_minusassign: generate_integer_assign(g, p, "-="); break;
1124
1172
  case c_multiplyassign:generate_integer_assign(g, p, "*="); break;
1125
1173
  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;
1174
+ case c_eq:
1175
+ case c_ne:
1176
+ case c_gt:
1177
+ case c_ge:
1178
+ case c_lt:
1179
+ case c_le:
1180
+ generate_integer_test(g, p);
1181
+ break;
1132
1182
  case c_call: generate_call(g, p); break;
1133
1183
  case c_grouping: generate_grouping(g, p, false); break;
1134
1184
  case c_non: generate_grouping(g, p, true); break;
@@ -1140,6 +1190,7 @@ static void generate(struct generator * g, struct node * p) {
1140
1190
  case c_false: generate_false(g, p); break;
1141
1191
  case c_true: break;
1142
1192
  case c_debug: generate_debug(g, p); break;
1193
+ case c_functionend: generate_functionend(g, p); break;
1143
1194
  default: fprintf(stderr, "%d encountered\n", p->type);
1144
1195
  exit(1);
1145
1196
  }
@@ -1153,7 +1204,6 @@ static void generate(struct generator * g, struct node * p) {
1153
1204
  }
1154
1205
 
1155
1206
  static void generate_class_begin(struct generator * g) {
1156
-
1157
1207
  w(g, "#pragma warning disable 0164~N");
1158
1208
  w(g, "#pragma warning disable 0162~N~N");
1159
1209
 
@@ -1179,7 +1229,6 @@ static void generate_class_begin(struct generator * g) {
1179
1229
  }
1180
1230
 
1181
1231
  static void generate_class_end(struct generator * g) {
1182
-
1183
1232
  w(g, "~N");
1184
1233
  w(g, "~}");
1185
1234
  w(g, "~}");
@@ -1187,71 +1236,60 @@ static void generate_class_end(struct generator * g) {
1187
1236
  }
1188
1237
 
1189
1238
  static void generate_among_table(struct generator * g, struct among * x, const char * type) {
1239
+ write_newline(g);
1240
+ write_comment(g, x->node);
1190
1241
 
1191
1242
  struct amongvec * v = x->b;
1192
1243
 
1193
1244
  g->I[0] = x->number;
1194
1245
  g->S[0] = type;
1195
1246
  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++;
1247
+ for (int i = 0; i < x->literalstring_count; i++) {
1248
+ g->I[0] = v[i].i;
1249
+ g->I[1] = v[i].result;
1250
+ g->L[0] = v[i].b;
1251
+ g->S[0] = i < x->literalstring_count - 1 ? "," : "";
1252
+
1253
+ w(g, "~Mnew Among(~L0, ~I0, ~I1");
1254
+ if (v[i].function != NULL) {
1255
+ w(g, ", ");
1256
+ write_varname(g, v[i].function);
1212
1257
  }
1258
+ w(g, ")~S0~N");
1213
1259
  }
1214
- w(g, "~-~M};~N~N");
1260
+ w(g, "~-~M};~N");
1215
1261
  }
1216
1262
 
1217
1263
  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) {
1264
+ for (struct among * x = g->analyser->amongs; x; x = x->next) {
1222
1265
  if (x->function_count) {
1223
1266
  g->I[0] = x->number;
1224
1267
  g->I[1] = x->literalstring_count;
1225
1268
 
1226
- w(g, "~Mprivate readonly Among[] a_~I0;~N");
1227
- ++amongs_with_functions;
1269
+ w(g, "~N~Mprivate readonly Among[] a_~I0;~N");
1228
1270
  } else {
1229
1271
  generate_among_table(g, x, "private static readonly Among[] ");
1230
1272
  }
1231
- x = x->next;
1232
1273
  }
1233
1274
  w(g, "~N");
1234
1275
 
1235
- if (!amongs_with_functions) return;
1276
+ if (g->analyser->among_with_function_count == 0) return;
1236
1277
 
1237
1278
  w(g, "~M/// <summary>~N");
1238
1279
  w(g, "~M/// Initializes a new instance of the <see cref=\"~n\"/> class.~N");
1239
1280
  w(g, "~M/// </summary>~N");
1240
1281
  w(g, "~M/// ~N");
1241
1282
  w(g, "~Mpublic ~n()~N~{");
1242
- x = g->analyser->amongs;
1243
- while (x != 0) {
1283
+ for (struct among * x = g->analyser->amongs; x; x = x->next) {
1244
1284
  if (x->function_count) {
1245
1285
  generate_among_table(g, x, "");
1246
1286
  }
1247
- x = x->next;
1248
1287
  }
1249
1288
 
1250
1289
  w(g, "~}~N~N");
1251
1290
  }
1252
1291
 
1253
1292
  static void generate_grouping_table(struct generator * g, struct grouping * q) {
1254
-
1255
1293
  symbol * b = q->b;
1256
1294
 
1257
1295
  g->V[0] = q->name;
@@ -1262,17 +1300,16 @@ static void generate_grouping_table(struct generator * g, struct grouping * q) {
1262
1300
  }
1263
1301
 
1264
1302
  static void generate_groupings(struct generator * g) {
1265
- struct grouping * q;
1266
- for (q = g->analyser->groupings; q; q = q->next) {
1303
+ for (struct grouping * q = g->analyser->groupings; q; q = q->next) {
1267
1304
  if (q->name->used)
1268
1305
  generate_grouping_table(g, q);
1269
1306
  }
1270
1307
  }
1271
1308
 
1272
1309
  static void generate_members(struct generator * g) {
1310
+ int wrote_members = false;
1273
1311
 
1274
- struct name * q;
1275
- for (q = g->analyser->names; q; q = q->next) {
1312
+ for (struct name * q = g->analyser->names; q; q = q->next) {
1276
1313
  g->V[0] = q;
1277
1314
  switch (q->type) {
1278
1315
  case t_string:
@@ -1281,28 +1318,28 @@ static void generate_members(struct generator * g) {
1281
1318
  w(g, " ~W0 = new ");
1282
1319
  w(g, g->options->string_class);
1283
1320
  w(g, "();~N");
1321
+ wrote_members = true;
1284
1322
  break;
1285
1323
  case t_integer:
1286
1324
  w(g, "~Mprivate int ~W0;~N");
1325
+ wrote_members = true;
1287
1326
  break;
1288
1327
  case t_boolean:
1289
1328
  w(g, "~Mprivate bool ~W0;~N");
1329
+ wrote_members = true;
1290
1330
  break;
1291
1331
  }
1292
1332
  }
1293
- w(g, "~N");
1333
+ if (wrote_members) w(g, "~N");
1294
1334
  }
1295
1335
 
1296
1336
  static void generate_methods(struct generator * g) {
1297
-
1298
- struct node * p;
1299
- for (p = g->analyser->program; p; p = p->right) {
1337
+ for (struct node * p = g->analyser->program; p; p = p->right) {
1300
1338
  generate(g, p);
1301
1339
  }
1302
1340
  }
1303
1341
 
1304
1342
  extern void generate_program_csharp(struct generator * g) {
1305
-
1306
1343
  g->outbuf = str_new();
1307
1344
  g->failure_str = str_new();
1308
1345