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,39 @@ 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 java, 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
46
  if (32 <= ch && ch < 127) {
67
47
  if (ch == '\"' || ch == '\\') write_string(g, "\\");
68
48
  write_char(g, ch);
69
49
  } else {
70
- write_hex(g, ch);
50
+ write_string(g, "\\u");
51
+ write_hex4(g, ch);
71
52
  }
72
53
  }
73
54
  write_string(g, "\"");
74
55
  }
75
56
 
76
57
  static void write_margin(struct generator * g) {
77
-
78
- int i;
79
- for (i = 0; i < g->margin; i++) write_string(g, " ");
58
+ for (int i = 0; i < g->margin; i++) write_string(g, " ");
80
59
  }
81
60
 
82
61
  static void write_comment(struct generator * g, struct node * p) {
@@ -88,65 +67,51 @@ static void write_comment(struct generator * g, struct node * p) {
88
67
  }
89
68
 
90
69
  static void write_block_start(struct generator * g) {
91
-
92
70
  w(g, "~M{~+~N");
93
71
  }
94
72
 
95
- static void write_block_end(struct generator * g) /* block end */ {
96
-
73
+ static void write_block_end(struct generator * g) {
97
74
  w(g, "~-~M}~N");
98
75
  }
99
76
 
100
77
  static void write_savecursor(struct generator * g, struct node * p,
101
78
  struct str * savevar) {
102
-
103
79
  g->B[0] = str_data(savevar);
104
80
  g->S[1] = "";
105
81
  if (p->mode != m_forward) g->S[1] = "limit - ";
106
82
  writef(g, "~Mint ~B0 = ~S1cursor;~N", p);
107
83
  }
108
84
 
109
- static void restore_string(struct node * p, struct str * out, struct str * savevar) {
110
-
111
- str_clear(out);
85
+ static void append_restore_string(struct node * p, struct str * out, struct str * savevar) {
112
86
  str_append_string(out, "cursor = ");
113
87
  if (p->mode != m_forward) str_append_string(out, "limit - ");
114
88
  str_append(out, savevar);
115
89
  str_append_string(out, ";");
116
90
  }
117
91
 
118
- static void write_restorecursor(struct generator * g, struct node * p,
119
- struct str * savevar) {
120
-
121
- struct str * temp = str_new();
92
+ static void write_restorecursor(struct generator * g, struct node * p, struct str * savevar) {
122
93
  write_margin(g);
123
- restore_string(p, temp, savevar);
124
- write_str(g, temp);
94
+ append_restore_string(p, g->outbuf, savevar);
125
95
  write_newline(g);
126
- str_delete(temp);
127
96
  }
128
97
 
129
98
  static void write_inc_cursor(struct generator * g, struct node * p) {
130
-
131
99
  write_margin(g);
132
100
  write_string(g, p->mode == m_forward ? "cursor++;" : "cursor--;");
133
101
  write_newline(g);
134
102
  }
135
103
 
136
104
  static void wsetlab_begin(struct generator * g, int n) {
137
-
138
105
  w(g, "~Mlab");
139
106
  write_int(g, n);
140
107
  w(g, ": {~+~N");
141
108
  }
142
109
 
143
110
  static void wsetlab_end(struct generator * g) {
144
-
145
111
  w(g, "~-~M}~N");
146
112
  }
147
113
 
148
114
  static void wgotol(struct generator * g, int n) {
149
-
150
115
  write_margin(g);
151
116
  write_string(g, "break lab");
152
117
  write_int(g, n);
@@ -155,7 +120,6 @@ static void wgotol(struct generator * g, int n) {
155
120
  }
156
121
 
157
122
  static void write_failure(struct generator * g) {
158
-
159
123
  if (str_len(g->failure_str) != 0) {
160
124
  write_margin(g);
161
125
  write_str(g, g->failure_str);
@@ -176,8 +140,7 @@ static void write_failure(struct generator * g) {
176
140
  write_newline(g);
177
141
  }
178
142
 
179
- static void write_failure_if(struct generator * g, char * s, struct node * p) {
180
-
143
+ static void write_failure_if(struct generator * g, const char * s, struct node * p) {
181
144
  writef(g, "~Mif (", p);
182
145
  writef(g, s, p);
183
146
  writef(g, ")~N", p);
@@ -189,7 +152,6 @@ static void write_failure_if(struct generator * g, char * s, struct node * p) {
189
152
 
190
153
  /* if at limit fail */
191
154
  static void write_check_limit(struct generator * g, struct node * p) {
192
-
193
155
  if (p->mode == m_forward) {
194
156
  write_failure_if(g, "cursor >= limit", p);
195
157
  } else {
@@ -199,18 +161,18 @@ static void write_check_limit(struct generator * g, struct node * p) {
199
161
 
200
162
  /* Formatted write. */
201
163
  static void writef(struct generator * g, const char * input, struct node * p) {
164
+ (void)p;
202
165
  int i = 0;
203
- int l = strlen(input);
204
166
 
205
- while (i < l) {
167
+ while (input[i]) {
206
168
  int ch = input[i++];
207
169
  if (ch != '~') {
208
170
  write_char(g, ch);
209
171
  continue;
210
172
  }
211
- switch (input[i++]) {
212
- default: write_char(g, input[i - 1]); continue;
213
- case 'C': write_comment(g, p); continue;
173
+ ch = input[i++];
174
+ switch (ch) {
175
+ case '~': write_char(g, '~'); continue;
214
176
  case 'f': write_block_start(g);
215
177
  write_failure(g);
216
178
  g->unreachable = false;
@@ -220,21 +182,65 @@ static void writef(struct generator * g, const char * input, struct node * p) {
220
182
  case 'N': write_newline(g); continue;
221
183
  case '{': write_block_start(g); continue;
222
184
  case '}': write_block_end(g); continue;
223
- case 'S': write_string(g, g->S[input[i++] - '0']); continue;
224
- case 'B': write_b(g, g->B[input[i++] - '0']); continue;
225
- case 'I': write_int(g, g->I[input[i++] - '0']); continue;
226
- case 'V': write_varref(g, g->V[input[i++] - '0']); continue;
227
- case 'W': write_varname(g, g->V[input[i++] - '0']); continue;
228
- case 'L': write_literal_string(g, g->L[input[i++] - '0']); continue;
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
+ }
229
227
  case '+': g->margin++; continue;
230
228
  case '-': g->margin--; continue;
231
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);
232
238
  }
233
239
  }
234
240
  }
235
241
 
236
242
  static void w(struct generator * g, const char * s) {
237
- writef(g, s, 0);
243
+ writef(g, s, NULL);
238
244
  }
239
245
 
240
246
  static void generate_AE(struct generator * g, struct node * p) {
@@ -272,13 +278,12 @@ static void generate_AE(struct generator * g, struct node * p) {
272
278
  break;
273
279
  case c_len: /* Same as size() for Java. */
274
280
  case c_size:
275
- w(g, "current.length()");
281
+ w(g, "length");
276
282
  break;
277
283
  }
278
284
  }
279
285
 
280
286
  static void generate_bra(struct generator * g, struct node * p) {
281
-
282
287
  write_comment(g, p);
283
288
  p = p->left;
284
289
  while (p) {
@@ -288,28 +293,33 @@ static void generate_bra(struct generator * g, struct node * p) {
288
293
  }
289
294
 
290
295
  static void generate_and(struct generator * g, struct node * p) {
291
-
292
- struct str * savevar = vars_newname(g);
293
- int keep_c = K_needed(g, p->left);
296
+ struct str * savevar = NULL;
297
+ if (K_needed(g, p->left)) {
298
+ savevar = vars_newname(g);
299
+ }
294
300
 
295
301
  write_comment(g, p);
296
302
 
297
- if (keep_c) write_savecursor(g, p, savevar);
303
+ if (savevar) write_savecursor(g, p, savevar);
298
304
 
299
305
  p = p->left;
300
306
  while (p) {
301
307
  generate(g, p);
302
308
  if (g->unreachable) break;
303
- if (keep_c && p->right != 0) write_restorecursor(g, p, savevar);
309
+ if (savevar && p->right != NULL) write_restorecursor(g, p, savevar);
304
310
  p = p->right;
305
311
  }
306
- str_delete(savevar);
312
+
313
+ if (savevar) {
314
+ str_delete(savevar);
315
+ }
307
316
  }
308
317
 
309
318
  static void generate_or(struct generator * g, struct node * p) {
310
-
311
- struct str * savevar = vars_newname(g);
312
- int keep_c = K_needed(g, p->left);
319
+ struct str * savevar = NULL;
320
+ if (K_needed(g, p->left)) {
321
+ savevar = vars_newname(g);
322
+ }
313
323
 
314
324
  int a0 = g->failure_label;
315
325
  struct str * a1 = str_copy(g->failure_str);
@@ -320,18 +330,18 @@ static void generate_or(struct generator * g, struct node * p) {
320
330
  write_comment(g, p);
321
331
  wsetlab_begin(g, out_lab);
322
332
 
323
- if (keep_c) write_savecursor(g, p, savevar);
333
+ if (savevar) write_savecursor(g, p, savevar);
324
334
 
325
335
  p = p->left;
326
336
  str_clear(g->failure_str);
327
337
 
328
- if (p == 0) {
329
- /* 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
330
340
  * sub nodes. */
331
341
  fprintf(stderr, "Error: \"or\" node without children nodes.");
332
342
  exit(1);
333
343
  }
334
- while (p->right != 0) {
344
+ while (p->right != NULL) {
335
345
  g->failure_label = new_label(g);
336
346
  wsetlab_begin(g, g->failure_label);
337
347
  generate(g, p);
@@ -341,7 +351,7 @@ static void generate_or(struct generator * g, struct node * p) {
341
351
  }
342
352
  wsetlab_end(g);
343
353
  g->unreachable = false;
344
- if (keep_c) write_restorecursor(g, p, savevar);
354
+ if (savevar) write_restorecursor(g, p, savevar);
345
355
  p = p->right;
346
356
  }
347
357
 
@@ -354,11 +364,13 @@ static void generate_or(struct generator * g, struct node * p) {
354
364
  if (!end_unreachable) {
355
365
  g->unreachable = false;
356
366
  }
357
- str_delete(savevar);
367
+
368
+ if (savevar) {
369
+ str_delete(savevar);
370
+ }
358
371
  }
359
372
 
360
373
  static void generate_backwards(struct generator * g, struct node * p) {
361
-
362
374
  write_comment(g, p);
363
375
  writef(g, "~Mlimit_backward = cursor;~N"
364
376
  "~Mcursor = limit;~N", p);
@@ -368,15 +380,16 @@ static void generate_backwards(struct generator * g, struct node * p) {
368
380
 
369
381
 
370
382
  static void generate_not(struct generator * g, struct node * p) {
371
-
372
- struct str * savevar = vars_newname(g);
373
- int keep_c = K_needed(g, p->left);
383
+ struct str * savevar = NULL;
384
+ if (K_needed(g, p->left)) {
385
+ savevar = vars_newname(g);
386
+ }
374
387
 
375
388
  int a0 = g->failure_label;
376
389
  struct str * a1 = str_copy(g->failure_str);
377
390
 
378
391
  write_comment(g, p);
379
- if (keep_c) {
392
+ if (savevar) {
380
393
  write_block_start(g);
381
394
  write_savecursor(g, p, savevar);
382
395
  }
@@ -397,48 +410,52 @@ static void generate_not(struct generator * g, struct node * p) {
397
410
  wsetlab_end(g);
398
411
  g->unreachable = false;
399
412
 
400
- if (keep_c) write_restorecursor(g, p, savevar);
401
- if (keep_c) write_block_end(g);
402
- str_delete(savevar);
413
+ if (savevar) {
414
+ write_restorecursor(g, p, savevar);
415
+ write_block_end(g);
416
+ str_delete(savevar);
417
+ }
403
418
  }
404
419
 
405
420
 
406
421
  static void generate_try(struct generator * g, struct node * p) {
407
-
408
- struct str * savevar = vars_newname(g);
409
- int keep_c = K_needed(g, p->left);
410
-
411
- write_comment(g, p);
412
- if (keep_c) write_savecursor(g, p, savevar);
422
+ struct str * savevar = NULL;
423
+ if (K_needed(g, p->left)) {
424
+ savevar = vars_newname(g);
425
+ }
413
426
 
414
427
  g->failure_label = new_label(g);
415
428
  str_clear(g->failure_str);
416
- if (keep_c) restore_string(p, g->failure_str, savevar);
429
+
430
+ write_comment(g, p);
431
+ if (savevar) {
432
+ write_savecursor(g, p, savevar);
433
+ append_restore_string(p, g->failure_str, savevar);
434
+ }
417
435
 
418
436
  wsetlab_begin(g, g->failure_label);
419
437
  generate(g, p->left);
420
438
  wsetlab_end(g);
421
439
  g->unreachable = false;
422
440
 
423
- str_delete(savevar);
441
+ if (savevar) {
442
+ str_delete(savevar);
443
+ }
424
444
  }
425
445
 
426
446
  static void generate_set(struct generator * g, struct node * p) {
427
-
428
447
  write_comment(g, p);
429
448
  g->V[0] = p->name;
430
449
  writef(g, "~M~V0 = true;~N", p);
431
450
  }
432
451
 
433
452
  static void generate_unset(struct generator * g, struct node * p) {
434
-
435
453
  write_comment(g, p);
436
454
  g->V[0] = p->name;
437
455
  writef(g, "~M~V0 = false;~N", p);
438
456
  }
439
457
 
440
458
  static void generate_fail(struct generator * g, struct node * p) {
441
-
442
459
  write_comment(g, p);
443
460
  generate(g, p->left);
444
461
  if (!g->unreachable) write_failure(g);
@@ -447,32 +464,35 @@ static void generate_fail(struct generator * g, struct node * p) {
447
464
  /* generate_test() also implements 'reverse' */
448
465
 
449
466
  static void generate_test(struct generator * g, struct node * p) {
450
-
451
- struct str * savevar = vars_newname(g);
452
- int keep_c = K_needed(g, p->left);
467
+ struct str * savevar = NULL;
468
+ if (K_needed(g, p->left)) {
469
+ savevar = vars_newname(g);
470
+ }
453
471
 
454
472
  write_comment(g, p);
455
473
 
456
- if (keep_c) {
474
+ if (savevar) {
457
475
  write_savecursor(g, p, savevar);
458
476
  }
459
477
 
460
478
  generate(g, p->left);
461
479
 
462
- if (!g->unreachable) {
463
- if (keep_c) {
480
+ if (savevar) {
481
+ if (!g->unreachable) {
464
482
  write_restorecursor(g, p, savevar);
465
483
  }
484
+ str_delete(savevar);
466
485
  }
467
- str_delete(savevar);
468
486
  }
469
487
 
470
488
  static void generate_do(struct generator * g, struct node * p) {
489
+ struct str * savevar = NULL;
490
+ if (K_needed(g, p->left)) {
491
+ savevar = vars_newname(g);
492
+ }
471
493
 
472
- struct str * savevar = vars_newname(g);
473
- int keep_c = K_needed(g, p->left);
474
494
  write_comment(g, p);
475
- if (keep_c) write_savecursor(g, p, savevar);
495
+ if (savevar) write_savecursor(g, p, savevar);
476
496
 
477
497
  if (p->left->type == c_call) {
478
498
  /* Optimise do <call> */
@@ -489,26 +509,54 @@ static void generate_do(struct generator * g, struct node * p) {
489
509
  g->unreachable = false;
490
510
  }
491
511
 
492
- if (keep_c) write_restorecursor(g, p, savevar);
493
- str_delete(savevar);
512
+ if (savevar) {
513
+ write_restorecursor(g, p, savevar);
514
+ str_delete(savevar);
515
+ }
494
516
  }
495
517
 
496
- static void generate_GO(struct generator * g, struct node * p, int style) {
518
+ static void generate_next(struct generator * g, struct node * p) {
519
+ write_comment(g, p);
520
+ write_check_limit(g, p);
521
+ write_inc_cursor(g, p);
522
+ }
497
523
 
498
- int end_unreachable = false;
499
- struct str * savevar = vars_newname(g);
500
- int keep_c = style == 1 || repeat_restore(g, p->left);
524
+ static void generate_GO_grouping(struct generator * g, struct node * p, int is_goto, int complement) {
525
+ write_comment(g, p);
526
+
527
+ struct grouping * q = p->name->grouping;
528
+ g->S[0] = p->mode == m_forward ? "" : "_b";
529
+ g->S[1] = complement ? "in" : "out";
530
+ g->V[0] = p->name;
531
+ g->I[0] = q->smallest_ch;
532
+ g->I[1] = q->largest_ch;
533
+ write_failure_if(g, "!go_~S1_grouping~S0(~V0, ~I0, ~I1)", p);
534
+ if (!is_goto) {
535
+ if (p->mode == m_forward)
536
+ w(g, "~Mcursor++;~N");
537
+ else
538
+ w(g, "~Mcursor--;~N");
539
+ }
540
+ }
541
+
542
+ static void generate_GO(struct generator * g, struct node * p, int style) {
543
+ write_comment(g, p);
501
544
 
502
545
  int a0 = g->failure_label;
503
546
  struct str * a1 = str_copy(g->failure_str);
504
547
 
548
+ int end_unreachable = false;
549
+
505
550
  int golab = new_label(g);
506
551
  g->I[0] = golab;
507
- write_comment(g, p);
508
552
  w(g, "~Mgolab~I0: while(true)~N");
509
553
  w(g, "~{");
510
554
 
511
- if (keep_c) write_savecursor(g, p, savevar);
555
+ struct str * savevar = NULL;
556
+ if (style == 1 || repeat_restore(g, p->left)) {
557
+ savevar = vars_newname(g);
558
+ write_savecursor(g, p, savevar);
559
+ }
512
560
 
513
561
  g->failure_label = new_label(g);
514
562
  str_clear(g->failure_str);
@@ -527,7 +575,10 @@ static void generate_GO(struct generator * g, struct node * p, int style) {
527
575
  }
528
576
  g->unreachable = false;
529
577
  wsetlab_end(g);
530
- if (keep_c) write_restorecursor(g, p, savevar);
578
+ if (savevar) {
579
+ write_restorecursor(g, p, savevar);
580
+ str_delete(savevar);
581
+ }
531
582
 
532
583
  g->failure_label = a0;
533
584
  str_delete(g->failure_str);
@@ -536,12 +587,10 @@ static void generate_GO(struct generator * g, struct node * p, int style) {
536
587
  write_check_limit(g, p);
537
588
  write_inc_cursor(g, p);
538
589
  write_block_end(g);
539
- str_delete(savevar);
540
590
  g->unreachable = end_unreachable;
541
591
  }
542
592
 
543
593
  static void generate_loop(struct generator * g, struct node * p) {
544
-
545
594
  struct str * loopvar = vars_newname(g);
546
595
  write_comment(g, p);
547
596
  g->B[0] = str_data(loopvar);
@@ -559,12 +608,13 @@ static void generate_loop(struct generator * g, struct node * p) {
559
608
  }
560
609
 
561
610
  static void generate_repeat_or_atleast(struct generator * g, struct node * p, struct str * loopvar) {
562
-
563
- struct str * savevar = vars_newname(g);
564
- int keep_c = repeat_restore(g, p->left);
565
611
  writef(g, "~Mwhile(true)~N~{", p);
566
612
 
567
- if (keep_c) write_savecursor(g, p, savevar);
613
+ struct str * savevar = NULL;
614
+ if (repeat_restore(g, p->left)) {
615
+ savevar = vars_newname(g);
616
+ write_savecursor(g, p, savevar);
617
+ }
568
618
 
569
619
  g->failure_label = new_label(g);
570
620
  str_clear(g->failure_str);
@@ -572,7 +622,7 @@ static void generate_repeat_or_atleast(struct generator * g, struct node * p, st
572
622
  generate(g, p->left);
573
623
 
574
624
  if (!g->unreachable) {
575
- if (loopvar != 0) {
625
+ if (loopvar != NULL) {
576
626
  g->B[0] = str_data(loopvar);
577
627
  w(g, "~M~B0--;~N");
578
628
  }
@@ -583,10 +633,12 @@ static void generate_repeat_or_atleast(struct generator * g, struct node * p, st
583
633
  wsetlab_end(g);
584
634
  g->unreachable = false;
585
635
 
586
- if (keep_c) write_restorecursor(g, p, savevar);
636
+ if (savevar) {
637
+ write_restorecursor(g, p, savevar);
638
+ str_delete(savevar);
639
+ }
587
640
 
588
641
  w(g, "~Mbreak;~N~}");
589
- str_delete(savevar);
590
642
  }
591
643
 
592
644
  static void generate_repeat(struct generator * g, struct node * p) {
@@ -595,8 +647,8 @@ static void generate_repeat(struct generator * g, struct node * p) {
595
647
  }
596
648
 
597
649
  static void generate_atleast(struct generator * g, struct node * p) {
598
-
599
650
  struct str * loopvar = vars_newname(g);
651
+
600
652
  write_comment(g, p);
601
653
  w(g, "~{");
602
654
  g->B[0] = str_data(loopvar);
@@ -620,14 +672,12 @@ static void generate_atleast(struct generator * g, struct node * p) {
620
672
  }
621
673
 
622
674
  static void generate_setmark(struct generator * g, struct node * p) {
623
-
624
675
  write_comment(g, p);
625
676
  g->V[0] = p->name;
626
677
  writef(g, "~M~V0 = cursor;~N", p);
627
678
  }
628
679
 
629
680
  static void generate_tomark(struct generator * g, struct node * p) {
630
-
631
681
  write_comment(g, p);
632
682
  g->S[0] = p->mode == m_forward ? ">" : "<";
633
683
 
@@ -640,7 +690,6 @@ static void generate_tomark(struct generator * g, struct node * p) {
640
690
  }
641
691
 
642
692
  static void generate_atmark(struct generator * g, struct node * p) {
643
-
644
693
  write_comment(g, p);
645
694
  w(g, "~Mif (cursor != "); generate_AE(g, p->AE); writef(g, ")~N", p);
646
695
  write_block_start(g);
@@ -650,7 +699,6 @@ static void generate_atmark(struct generator * g, struct node * p) {
650
699
  }
651
700
 
652
701
  static void generate_hop(struct generator * g, struct node * p) {
653
-
654
702
  write_comment(g, p);
655
703
  g->S[0] = p->mode == m_forward ? "+" : "-";
656
704
 
@@ -674,28 +722,17 @@ static void generate_hop(struct generator * g, struct node * p) {
674
722
  }
675
723
 
676
724
  static void generate_delete(struct generator * g, struct node * p) {
677
-
678
725
  write_comment(g, p);
679
726
  writef(g, "~Mslice_del();~N", p);
680
727
  }
681
728
 
682
-
683
- static void generate_next(struct generator * g, struct node * p) {
684
-
685
- write_comment(g, p);
686
- write_check_limit(g, p);
687
- write_inc_cursor(g, p);
688
- }
689
-
690
729
  static void generate_tolimit(struct generator * g, struct node * p) {
691
-
692
730
  write_comment(g, p);
693
731
  g->S[0] = p->mode == m_forward ? "limit" : "limit_backward";
694
732
  writef(g, "~Mcursor = ~S0;~N", p);
695
733
  }
696
734
 
697
735
  static void generate_atlimit(struct generator * g, struct node * p) {
698
-
699
736
  write_comment(g, p);
700
737
  g->S[0] = p->mode == m_forward ? "limit" : "limit_backward";
701
738
  g->S[1] = p->mode == m_forward ? "<" : ">";
@@ -703,37 +740,32 @@ static void generate_atlimit(struct generator * g, struct node * p) {
703
740
  }
704
741
 
705
742
  static void generate_leftslice(struct generator * g, struct node * p) {
706
-
707
743
  write_comment(g, p);
708
744
  g->S[0] = p->mode == m_forward ? "bra" : "ket";
709
745
  writef(g, "~M~S0 = cursor;~N", p);
710
746
  }
711
747
 
712
748
  static void generate_rightslice(struct generator * g, struct node * p) {
713
-
714
749
  write_comment(g, p);
715
750
  g->S[0] = p->mode == m_forward ? "ket" : "bra";
716
751
  writef(g, "~M~S0 = cursor;~N", p);
717
752
  }
718
753
 
719
754
  static void generate_assignto(struct generator * g, struct node * p) {
720
-
721
755
  write_comment(g, p);
722
756
  g->V[0] = p->name;
723
757
  writef(g, "~Massign_to(~V0);~N", p);
724
758
  }
725
759
 
726
760
  static void generate_sliceto(struct generator * g, struct node * p) {
727
-
728
761
  write_comment(g, p);
729
762
  g->V[0] = p->name;
730
763
  writef(g, "~Mslice_to(~V0);~N", p);
731
764
  }
732
765
 
733
766
  static void generate_address(struct generator * g, struct node * p) {
734
-
735
767
  symbol * b = p->literalstring;
736
- if (b != 0) {
768
+ if (b != NULL) {
737
769
  write_literal_string(g, b);
738
770
  } else {
739
771
  write_varref(g, p->name);
@@ -741,7 +773,6 @@ static void generate_address(struct generator * g, struct node * p) {
741
773
  }
742
774
 
743
775
  static void generate_insert(struct generator * g, struct node * p, int style) {
744
-
745
776
  int keep_c = style == c_attach;
746
777
  write_comment(g, p);
747
778
  if (p->mode == m_backward) keep_c = !keep_c;
@@ -753,7 +784,6 @@ static void generate_insert(struct generator * g, struct node * p, int style) {
753
784
  }
754
785
 
755
786
  static void generate_assignfrom(struct generator * g, struct node * p) {
756
-
757
787
  int keep_c = p->mode == m_forward; /* like 'attach' */
758
788
 
759
789
  write_comment(g, p);
@@ -768,9 +798,7 @@ static void generate_assignfrom(struct generator * g, struct node * p) {
768
798
  if (keep_c) w(g, "~Mcursor = c;~N~}");
769
799
  }
770
800
 
771
-
772
801
  static void generate_slicefrom(struct generator * g, struct node * p) {
773
-
774
802
  write_comment(g, p);
775
803
  w(g, "~Mslice_from(");
776
804
  generate_address(g, p);
@@ -778,7 +806,6 @@ static void generate_slicefrom(struct generator * g, struct node * p) {
778
806
  }
779
807
 
780
808
  static void generate_setlimit(struct generator * g, struct node * p) {
781
- struct str * savevar = vars_newname(g);
782
809
  struct str * varname = vars_newname(g);
783
810
  write_comment(g, p);
784
811
  if (p->left && p->left->type == c_tomark) {
@@ -791,6 +818,7 @@ static void generate_setlimit(struct generator * g, struct node * p) {
791
818
  * restore c.
792
819
  */
793
820
  struct node * q = p->left;
821
+ write_comment(g, q);
794
822
  g->S[0] = q->mode == m_forward ? ">" : "<";
795
823
  w(g, "~Mif (cursor ~S0 "); generate_AE(g, q->AE); w(g, ")~N");
796
824
  write_block_start(g);
@@ -806,7 +834,8 @@ static void generate_setlimit(struct generator * g, struct node * p) {
806
834
  w(g, "~Mint ~B0 = limit_backward;~N");
807
835
  w(g, "~Mlimit_backward = ");
808
836
  }
809
- generate_AE(g, q->AE); writef(g, ";~N", q);
837
+ generate_AE(g, q->AE);
838
+ writef(g, ";~N", q);
810
839
 
811
840
  if (p->mode == m_forward) {
812
841
  str_assign(g->failure_str, "limit += ");
@@ -818,7 +847,9 @@ static void generate_setlimit(struct generator * g, struct node * p) {
818
847
  str_append_ch(g->failure_str, ';');
819
848
  }
820
849
  } else {
850
+ struct str * savevar = vars_newname(g);
821
851
  write_savecursor(g, p, savevar);
852
+
822
853
  generate(g, p->left);
823
854
 
824
855
  if (!g->unreachable) {
@@ -842,6 +873,7 @@ static void generate_setlimit(struct generator * g, struct node * p) {
842
873
  str_append_ch(g->failure_str, ';');
843
874
  }
844
875
  }
876
+ str_delete(savevar);
845
877
  }
846
878
 
847
879
  if (!g->unreachable) {
@@ -854,16 +886,16 @@ static void generate_setlimit(struct generator * g, struct node * p) {
854
886
  }
855
887
  }
856
888
  str_delete(varname);
857
- str_delete(savevar);
858
889
  }
859
890
 
860
891
  /* dollar sets snowball up to operate on a string variable as if it were the
861
892
  * current string */
862
893
  static void generate_dollar(struct generator * g, struct node * p) {
894
+ write_comment(g, p);
863
895
 
864
896
  struct str * savevar = vars_newname(g);
865
897
  g->B[0] = str_data(savevar);
866
- writef(g, "~{~C~N"
898
+ writef(g, "~{~N"
867
899
  "~MSnowballProgram ~B0 = new SnowballProgram(this);~N", p);
868
900
 
869
901
  ++g->copy_from_count;
@@ -884,36 +916,66 @@ static void generate_dollar(struct generator * g, struct node * p) {
884
916
  str_delete(savevar);
885
917
  }
886
918
 
887
- static void generate_integer_assign(struct generator * g, struct node * p, char * s) {
888
-
919
+ static void generate_integer_assign(struct generator * g, struct node * p, const char * s) {
920
+ write_comment(g, p);
889
921
  g->V[0] = p->name;
890
922
  g->S[0] = s;
891
- w(g, "~M~V0 ~S0 "); generate_AE(g, p->AE); w(g, ";~N");
923
+ w(g, "~M~V0 ~S0 ");
924
+ generate_AE(g, p->AE);
925
+ w(g, ";~N");
892
926
  }
893
927
 
894
- static void generate_integer_test(struct generator * g, struct node * p, char * s) {
895
-
896
- w(g, "~Mif (!(");
928
+ static void generate_integer_test(struct generator * g, struct node * p) {
929
+ write_comment(g, p);
930
+ int relop = p->type;
931
+ int optimise_to_return = (g->failure_label == x_return && p->right && p->right->type == c_functionend);
932
+ if (optimise_to_return) {
933
+ w(g, "~Mreturn ");
934
+ p->right = NULL;
935
+ } else {
936
+ w(g, "~Mif (");
937
+ // We want the inverse of the snowball test here.
938
+ relop ^= 1;
939
+ }
897
940
  generate_AE(g, p->left);
898
- write_char(g, ' ');
899
- write_string(g, s);
900
- write_char(g, ' ');
941
+ // Relational operators are the same as C.
942
+ write_c_relop(g, relop);
901
943
  generate_AE(g, p->AE);
902
- w(g, "))~N");
903
- write_block_start(g);
904
- write_failure(g);
905
- write_block_end(g);
906
- g->unreachable = false;
944
+ if (optimise_to_return) {
945
+ w(g, ";~N");
946
+ } else {
947
+ w(g, ")~N");
948
+ write_block_start(g);
949
+ write_failure(g);
950
+ write_block_end(g);
951
+ g->unreachable = false;
952
+ }
907
953
  }
908
954
 
909
955
  static void generate_call(struct generator * g, struct node * p) {
910
-
956
+ int signals = check_possible_signals_list(g, p->name->definition, c_define, 0);
911
957
  write_comment(g, p);
912
958
  g->V[0] = p->name;
913
- write_failure_if(g, "!~V0()", p);
959
+ if (g->failure_label == x_return &&
960
+ (signals == 0 || (p->right && p->right->type == c_functionend))) {
961
+ /* Always fails or tail call. */
962
+ writef(g, "~Mreturn ~V0();~N", p);
963
+ return;
964
+ }
965
+ if (signals == 1) {
966
+ /* Always succeeds. */
967
+ writef(g, "~M~V0();~N", p);
968
+ } else if (signals == 0) {
969
+ /* Always fails. */
970
+ writef(g, "~M~V0();~N", p);
971
+ write_failure(g);
972
+ } else {
973
+ write_failure_if(g, "!~V0()", p);
974
+ }
914
975
  }
915
976
 
916
977
  static void generate_grouping(struct generator * g, struct node * p, int complement) {
978
+ write_comment(g, p);
917
979
 
918
980
  struct grouping * q = p->name->grouping;
919
981
  g->S[0] = p->mode == m_forward ? "" : "_b";
@@ -925,7 +987,6 @@ static void generate_grouping(struct generator * g, struct node * p, int complem
925
987
  }
926
988
 
927
989
  static void generate_namedstring(struct generator * g, struct node * p) {
928
-
929
990
  write_comment(g, p);
930
991
  g->S[0] = p->mode == m_forward ? "" : "_b";
931
992
  g->V[0] = p->name;
@@ -942,21 +1003,22 @@ static void generate_literalstring(struct generator * g, struct node * p) {
942
1003
 
943
1004
  static void generate_define(struct generator * g, struct node * p) {
944
1005
  struct name * q = p->name;
1006
+ if (q->type == t_routine && !q->used) return;
945
1007
 
946
- struct str * saved_output = g->outbuf;
1008
+ write_newline(g);
1009
+ write_comment(g, p);
947
1010
 
948
- /* We currently make functions used in among public as this seems to
949
- * be required to allow the SnowballProgram base class to invoke them.
950
- * FIXME: Is this avoidable?
951
- */
952
- if (q->type == t_routine && !q->used_in_among) {
1011
+ if (q->type == t_routine) {
953
1012
  g->S[0] = "private";
954
1013
  } else {
1014
+ w(g, "~M@Override~N");
955
1015
  g->S[0] = "public";
956
1016
  }
957
1017
  g->V[0] = q;
958
- w(g, "~N~M~S0 boolean ~V0() {~+~N");
1018
+ w(g, "~M~S0 boolean ~V0() {~+~N");
959
1019
 
1020
+ /* Save output. */
1021
+ struct str * saved_output = g->outbuf;
960
1022
  g->outbuf = str_new();
961
1023
 
962
1024
  g->next_label = 0;
@@ -966,8 +1028,16 @@ static void generate_define(struct generator * g, struct node * p) {
966
1028
  str_clear(g->failure_str);
967
1029
  g->failure_label = x_return;
968
1030
  g->unreachable = false;
1031
+ int signals = check_possible_signals_list(g, p->left, c_define, 0);
1032
+
1033
+ /* Generate function body. */
969
1034
  generate(g, p->left);
970
- if (!g->unreachable) w(g, "~Mreturn true;~N");
1035
+ if (p->left->right) {
1036
+ assert(p->left->right->type == c_functionend);
1037
+ if (signals) {
1038
+ generate(g, p->left->right);
1039
+ }
1040
+ }
971
1041
  w(g, "~}");
972
1042
 
973
1043
  str_append(saved_output, g->outbuf);
@@ -975,38 +1045,46 @@ static void generate_define(struct generator * g, struct node * p) {
975
1045
  g->outbuf = saved_output;
976
1046
  }
977
1047
 
1048
+ static void generate_functionend(struct generator * g, struct node * p) {
1049
+ (void)p;
1050
+ w(g, "~Mreturn true;~N");
1051
+ }
1052
+
978
1053
  static void generate_substring(struct generator * g, struct node * p) {
1054
+ write_comment(g, p);
979
1055
 
980
1056
  struct among * x = p->among;
981
1057
 
982
- write_comment(g, p);
983
-
984
1058
  g->S[0] = p->mode == m_forward ? "" : "_b";
985
1059
  g->I[0] = x->number;
986
1060
 
987
- if (!x->amongvar_needed) {
988
- write_failure_if(g, "find_among~S0(a_~I0) == 0", p);
989
- } else {
1061
+ if (x->amongvar_needed) {
990
1062
  writef(g, "~Mamong_var = find_among~S0(a_~I0);~N", p);
991
- write_failure_if(g, "among_var == 0", p);
1063
+ if (!x->always_matches) {
1064
+ write_failure_if(g, "among_var == 0", p);
1065
+ }
1066
+ } else if (x->always_matches) {
1067
+ writef(g, "~Mfind_among~S0(a_~I0);~N", p);
1068
+ } else {
1069
+ write_failure_if(g, "find_among~S0(a_~I0) == 0", p);
992
1070
  }
993
1071
  }
994
1072
 
995
1073
  static void generate_among(struct generator * g, struct node * p) {
996
-
997
1074
  struct among * x = p->among;
998
1075
 
999
- if (x->substring == 0) generate_substring(g, p);
1000
-
1001
- if (x->starter != 0) generate(g, x->starter);
1076
+ if (x->substring == NULL) {
1077
+ generate_substring(g, p);
1078
+ } else {
1079
+ write_comment(g, p);
1080
+ }
1002
1081
 
1003
1082
  if (x->command_count == 1 && x->nocommand_count == 0) {
1004
1083
  /* Only one outcome ("no match" already handled). */
1005
1084
  generate(g, x->commands[0]);
1006
1085
  } else if (x->command_count > 0) {
1007
- int i;
1008
1086
  w(g, "~Mswitch (among_var) {~N~+");
1009
- for (i = 1; i <= x->command_count; i++) {
1087
+ for (int i = 1; i <= x->command_count; i++) {
1010
1088
  g->I[0] = i;
1011
1089
  w(g, "~Mcase ~I0:~N~+");
1012
1090
  generate(g, x->commands[i - 1]);
@@ -1019,20 +1097,17 @@ static void generate_among(struct generator * g, struct node * p) {
1019
1097
  }
1020
1098
 
1021
1099
  static void generate_booltest(struct generator * g, struct node * p) {
1022
-
1023
1100
  write_comment(g, p);
1024
1101
  g->V[0] = p->name;
1025
1102
  write_failure_if(g, "!(~V0)", p);
1026
1103
  }
1027
1104
 
1028
1105
  static void generate_false(struct generator * g, struct node * p) {
1029
-
1030
1106
  write_comment(g, p);
1031
1107
  write_failure(g);
1032
1108
  }
1033
1109
 
1034
1110
  static void generate_debug(struct generator * g, struct node * p) {
1035
-
1036
1111
  write_comment(g, p);
1037
1112
  g->I[0] = g->debug_count++;
1038
1113
  g->I[1] = p->line_number;
@@ -1040,14 +1115,10 @@ static void generate_debug(struct generator * g, struct node * p) {
1040
1115
  }
1041
1116
 
1042
1117
  static void generate(struct generator * g, struct node * p) {
1043
-
1044
- int a0;
1045
- struct str * a1;
1046
-
1047
1118
  if (g->unreachable) return;
1048
1119
 
1049
- a0 = g->failure_label;
1050
- a1 = str_copy(g->failure_str);
1120
+ int a0 = g->failure_label;
1121
+ struct str * a1 = str_copy(g->failure_str);
1051
1122
 
1052
1123
  switch (p->type) {
1053
1124
  case c_define: generate_define(g, p); break;
@@ -1065,6 +1136,11 @@ static void generate(struct generator * g, struct node * p) {
1065
1136
  case c_do: generate_do(g, p); break;
1066
1137
  case c_goto: generate_GO(g, p, 1); break;
1067
1138
  case c_gopast: generate_GO(g, p, 0); break;
1139
+ case c_goto_grouping: generate_GO_grouping(g, p, 1, 0); break;
1140
+ case c_gopast_grouping:
1141
+ generate_GO_grouping(g, p, 0, 0); break;
1142
+ case c_goto_non: generate_GO_grouping(g, p, 1, 1); break;
1143
+ case c_gopast_non: generate_GO_grouping(g, p, 0, 1); break;
1068
1144
  case c_repeat: generate_repeat(g, p); break;
1069
1145
  case c_loop: generate_loop(g, p); break;
1070
1146
  case c_atleast: generate_atleast(g, p); break;
@@ -1091,12 +1167,14 @@ static void generate(struct generator * g, struct node * p) {
1091
1167
  case c_minusassign: generate_integer_assign(g, p, "-="); break;
1092
1168
  case c_multiplyassign:generate_integer_assign(g, p, "*="); break;
1093
1169
  case c_divideassign: generate_integer_assign(g, p, "/="); break;
1094
- case c_eq: generate_integer_test(g, p, "=="); break;
1095
- case c_ne: generate_integer_test(g, p, "!="); break;
1096
- case c_gr: generate_integer_test(g, p, ">"); break;
1097
- case c_ge: generate_integer_test(g, p, ">="); break;
1098
- case c_ls: generate_integer_test(g, p, "<"); break;
1099
- case c_le: generate_integer_test(g, p, "<="); break;
1170
+ case c_eq:
1171
+ case c_ne:
1172
+ case c_gt:
1173
+ case c_ge:
1174
+ case c_lt:
1175
+ case c_le:
1176
+ generate_integer_test(g, p);
1177
+ break;
1100
1178
  case c_call: generate_call(g, p); break;
1101
1179
  case c_grouping: generate_grouping(g, p, false); break;
1102
1180
  case c_non: generate_grouping(g, p, true); break;
@@ -1108,6 +1186,7 @@ static void generate(struct generator * g, struct node * p) {
1108
1186
  case c_false: generate_false(g, p); break;
1109
1187
  case c_true: break;
1110
1188
  case c_debug: generate_debug(g, p); break;
1189
+ case c_functionend: generate_functionend(g, p); break;
1111
1190
  default: fprintf(stderr, "%d encountered\n", p->type);
1112
1191
  exit(1);
1113
1192
  }
@@ -1118,7 +1197,6 @@ static void generate(struct generator * g, struct node * p) {
1118
1197
  }
1119
1198
 
1120
1199
  static void generate_class_begin(struct generator * g) {
1121
-
1122
1200
  w(g, "package ");
1123
1201
  w(g, g->options->package);
1124
1202
  w(g, ";~N~N");
@@ -1147,65 +1225,61 @@ static void generate_class_begin(struct generator * g) {
1147
1225
  w(g, g->options->parent_class_name);
1148
1226
  w(g, " {~+~N"
1149
1227
  "~N"
1150
- "~Mprivate static final long serialVersionUID = 1L;~N"
1151
- "~N");
1228
+ "~Mprivate static final long serialVersionUID = 1L;~N");
1229
+ if (g->analyser->among_with_function_count > 0) {
1230
+ w(g, "~Mprivate static final java.lang.invoke.MethodHandles.Lookup methodObject = java.lang.invoke.MethodHandles.lookup();~N");
1231
+ }
1232
+ write_newline(g);
1152
1233
  }
1153
1234
 
1154
1235
  static void generate_class_end(struct generator * g) {
1155
-
1156
1236
  w(g, "~N}");
1157
- w(g, "~N~N");
1237
+ w(g, "~N");
1158
1238
  }
1159
1239
 
1160
1240
  static void generate_equals(struct generator * g) {
1161
-
1162
1241
  w(g, "~N"
1163
- "@Override~N"
1242
+ "~M@Override~N"
1164
1243
  "~Mpublic boolean equals( Object o ) {~N"
1165
1244
  "~+~Mreturn o instanceof ");
1166
1245
  w(g, g->options->name);
1167
1246
  w(g, ";~N~-~M}~N"
1168
1247
  "~N"
1169
- "@Override~N"
1248
+ "~M@Override~N"
1170
1249
  "~Mpublic int hashCode() {~N"
1171
1250
  "~+~Mreturn ");
1172
1251
  w(g, g->options->name);
1173
1252
  w(g, ".class.getName().hashCode();~N"
1174
1253
  "~-~M}~N");
1175
- w(g, "~N~N");
1176
1254
  }
1177
1255
 
1178
1256
  static void generate_among_table(struct generator * g, struct among * x) {
1257
+ write_comment(g, x->node);
1179
1258
 
1180
1259
  struct amongvec * v = x->b;
1181
1260
 
1182
1261
  g->I[0] = x->number;
1183
1262
 
1184
- w(g, "~Mprivate final static Among a_~I0[] = {~N~+");
1185
- {
1186
- int i;
1187
- for (i = 0; i < x->literalstring_count; i++) {
1188
- g->I[0] = v->i;
1189
- g->I[1] = v->result;
1190
- g->L[0] = v->b;
1191
- g->S[0] = i < x->literalstring_count - 1 ? "," : "";
1192
-
1193
- w(g, "~Mnew Among(~L0, ~I0, ~I1");
1194
- if (v->function != 0) {
1195
- w(g, ", \"");
1196
- write_varname(g, v->function);
1197
- w(g, "\", ~n.class");
1198
- }
1199
- w(g, ")~S0~N");
1200
- v++;
1263
+ w(g, "~Mprivate final static Among[] a_~I0 = {~N~+");
1264
+ for (int i = 0; i < x->literalstring_count; i++) {
1265
+ g->I[0] = v[i].i;
1266
+ g->I[1] = v[i].result;
1267
+ g->L[0] = v[i].b;
1268
+ g->S[0] = i < x->literalstring_count - 1 ? "," : "";
1269
+
1270
+ w(g, "~Mnew Among(~L0, ~I0, ~I1");
1271
+ if (v[i].function != NULL) {
1272
+ w(g, ", \"");
1273
+ write_varname(g, v[i].function);
1274
+ w(g, "\", methodObject");
1201
1275
  }
1276
+ w(g, ")~S0~N");
1202
1277
  }
1203
1278
  w(g, "~-~M};~N~N");
1204
1279
  }
1205
1280
 
1206
1281
  static void generate_amongs(struct generator * g) {
1207
- struct among * x;
1208
- for (x = g->analyser->amongs; x; x = x->next) {
1282
+ for (struct among * x = g->analyser->amongs; x; x = x->next) {
1209
1283
  generate_among_table(g, x);
1210
1284
  }
1211
1285
  }
@@ -1213,41 +1287,37 @@ static void generate_amongs(struct generator * g) {
1213
1287
  static void set_bit(symbol * b, int i) { b[i/8] |= 1 << i%8; }
1214
1288
 
1215
1289
  static void generate_grouping_table(struct generator * g, struct grouping * q) {
1216
-
1217
1290
  int range = q->largest_ch - q->smallest_ch + 1;
1218
1291
  int size = (range + 7)/ 8; /* assume 8 bits per symbol */
1219
1292
  symbol * b = q->b;
1220
1293
  symbol * map = create_b(size);
1221
- int i;
1222
- for (i = 0; i < size; i++) map[i] = 0;
1223
1294
 
1224
- /* Using unicode would require revision here */
1295
+ for (int i = 0; i < size; i++) map[i] = 0;
1225
1296
 
1226
- for (i = 0; i < SIZE(b); i++) set_bit(map, b[i] - q->smallest_ch);
1297
+ for (int i = 0; i < SIZE(b); i++) set_bit(map, b[i] - q->smallest_ch);
1227
1298
 
1228
1299
  g->V[0] = q->name;
1229
-
1230
- w(g, "~Mprivate static final char ~V0[] = {");
1231
- for (i = 0; i < size; i++) {
1300
+ w(g, "~Mprivate static final char[] ~V0 = {");
1301
+ for (int i = 0; i < size; i++) {
1232
1302
  write_int(g, map[i]);
1233
1303
  if (i < size - 1) w(g, ", ");
1234
1304
  }
1235
1305
  w(g, " };~N~N");
1306
+
1236
1307
  lose_b(map);
1237
1308
  }
1238
1309
 
1239
1310
  static void generate_groupings(struct generator * g) {
1240
- struct grouping * q;
1241
- for (q = g->analyser->groupings; q; q = q->next) {
1311
+ for (struct grouping * q = g->analyser->groupings; q; q = q->next) {
1242
1312
  if (q->name->used)
1243
1313
  generate_grouping_table(g, q);
1244
1314
  }
1245
1315
  }
1246
1316
 
1247
1317
  static void generate_members(struct generator * g) {
1318
+ int wrote_members = false;
1248
1319
 
1249
- struct name * q;
1250
- for (q = g->analyser->names; q; q = q->next) {
1320
+ for (struct name * q = g->analyser->names; q; q = q->next) {
1251
1321
  g->V[0] = q;
1252
1322
  switch (q->type) {
1253
1323
  case t_string:
@@ -1256,32 +1326,34 @@ static void generate_members(struct generator * g) {
1256
1326
  w(g, " ~W0 = new ");
1257
1327
  w(g, g->options->string_class);
1258
1328
  w(g, "();~N");
1329
+ wrote_members = true;
1259
1330
  break;
1260
1331
  case t_integer:
1261
1332
  w(g, "~Mprivate int ~W0;~N");
1333
+ wrote_members = true;
1262
1334
  break;
1263
1335
  case t_boolean:
1264
1336
  w(g, "~Mprivate boolean ~W0;~N");
1337
+ wrote_members = true;
1265
1338
  break;
1266
1339
  }
1267
1340
  }
1268
- w(g, "~N");
1341
+ if (wrote_members) w(g, "~N");
1269
1342
  }
1270
1343
 
1271
1344
  static void generate_methods(struct generator * g) {
1272
-
1273
- struct node * p;
1274
- for (p = g->analyser->program; p; p = p->right) {
1345
+ for (struct node * p = g->analyser->program; p; p = p->right) {
1275
1346
  generate(g, p);
1276
1347
  g->unreachable = false;
1277
1348
  }
1278
1349
  }
1279
1350
 
1280
1351
  extern void generate_program_java(struct generator * g) {
1281
-
1282
1352
  g->outbuf = str_new();
1283
1353
  g->failure_str = str_new();
1284
1354
 
1355
+ w(g, "~+");
1356
+
1285
1357
  generate_amongs(g);
1286
1358
  generate_groupings(g);
1287
1359
 
@@ -1291,6 +1363,8 @@ extern void generate_program_java(struct generator * g) {
1291
1363
 
1292
1364
  generate_class_end(g);
1293
1365
 
1366
+ w(g, "~-");
1367
+
1294
1368
  {
1295
1369
  /* We need to call generate_class_begin() after we've generated the
1296
1370
  * methods so we know if copy_from_count > 0.