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,57 +23,38 @@ 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
38
  write_varname(g, p);
42
39
  }
43
40
 
44
- static void write_hexdigit(struct generator * g, int n) {
45
-
46
- write_char(g, n < 10 ? n + '0' : n - 10 + 'A');
47
- }
48
-
49
- static void write_hex(struct generator * g, int ch) {
50
-
51
- write_string(g, "\\u");
52
- {
53
- int i;
54
- for (i = 12; i >= 0; i -= 4) write_hexdigit(g, ch >> i & 0xf);
55
- }
56
- }
57
-
58
41
  static void write_literal_string(struct generator * g, symbol * p) {
59
-
60
- int i;
61
42
  write_string(g, "\"");
62
- for (i = 0; i < SIZE(p); i++) {
43
+ for (int i = 0; i < SIZE(p); i++) {
63
44
  int ch = p[i];
64
45
  if (32 <= ch && ch < 127) {
65
46
  if (ch == '\"' || ch == '\\') write_string(g, "\\");
66
47
  write_char(g, ch);
67
48
  } else {
68
- write_hex(g, ch);
49
+ write_string(g, "\\u");
50
+ write_hex4(g, ch);
69
51
  }
70
52
  }
71
53
  write_string(g, "\"");
72
54
  }
73
55
 
74
56
  static void write_margin(struct generator * g) {
75
-
76
- int i;
77
- for (i = 0; i < g->margin; i++) write_string(g, " ");
57
+ for (int i = 0; i < g->margin; i++) write_string(g, " ");
78
58
  }
79
59
 
80
60
  static void write_comment(struct generator * g, struct node * p) {
@@ -86,46 +66,35 @@ static void write_comment(struct generator * g, struct node * p) {
86
66
  }
87
67
 
88
68
  static void write_block_start(struct generator * g) {
89
-
90
69
  w(g, "~M{~+~N");
91
70
  }
92
71
 
93
- static void write_block_end(struct generator * g) /* block end */ {
94
-
72
+ static void write_block_end(struct generator * g) {
95
73
  w(g, "~-~M}~N");
96
74
  }
97
75
 
98
76
  static void write_savecursor(struct generator * g, struct node * p,
99
77
  struct str * savevar) {
100
-
101
78
  g->B[0] = str_data(savevar);
102
79
  g->S[1] = "";
103
80
  if (p->mode != m_forward) g->S[1] = "base.limit - ";
104
- writef(g, "~Mvar /** number */ ~B0 = ~S1base.cursor;~N", p);
81
+ writef(g, "~M~C /** number */ ~B0 = ~S1base.cursor;~N", p);
105
82
  }
106
83
 
107
- static void restore_string(struct node * p, struct str * out, struct str * savevar) {
108
-
109
- str_clear(out);
84
+ static void append_restore_string(struct node * p, struct str * out, struct str * savevar) {
110
85
  str_append_string(out, "base.cursor = ");
111
86
  if (p->mode != m_forward) str_append_string(out, "base.limit - ");
112
87
  str_append(out, savevar);
113
88
  str_append_string(out, ";");
114
89
  }
115
90
 
116
- static void write_restorecursor(struct generator * g, struct node * p,
117
- struct str * savevar) {
118
-
119
- struct str * temp = str_new();
91
+ static void write_restorecursor(struct generator * g, struct node * p, struct str * savevar) {
120
92
  write_margin(g);
121
- restore_string(p, temp, savevar);
122
- write_str(g, temp);
93
+ append_restore_string(p, g->outbuf, savevar);
123
94
  write_newline(g);
124
- str_delete(temp);
125
95
  }
126
96
 
127
97
  static void write_inc_cursor(struct generator * g, struct node * p) {
128
-
129
98
  write_margin(g);
130
99
  write_string(g, p->mode == m_forward ? "base.cursor++;" : "base.cursor--;");
131
100
  write_newline(g);
@@ -137,12 +106,10 @@ static void wsetlab_begin(struct generator * g, int n) {
137
106
  }
138
107
 
139
108
  static void wsetlab_end(struct generator * g) {
140
-
141
109
  w(g, "~-~M}~N");
142
110
  }
143
111
 
144
112
  static void wgotol(struct generator * g, int n) {
145
-
146
113
  write_margin(g);
147
114
  write_string(g, "break lab");
148
115
  write_int(g, n);
@@ -151,7 +118,6 @@ static void wgotol(struct generator * g, int n) {
151
118
  }
152
119
 
153
120
  static void write_failure(struct generator * g) {
154
-
155
121
  if (str_len(g->failure_str) != 0) {
156
122
  write_margin(g);
157
123
  write_str(g, g->failure_str);
@@ -172,8 +138,7 @@ static void write_failure(struct generator * g) {
172
138
  write_newline(g);
173
139
  }
174
140
 
175
- static void write_failure_if(struct generator * g, char * s, struct node * p) {
176
-
141
+ static void write_failure_if(struct generator * g, const char * s, struct node * p) {
177
142
  writef(g, "~Mif (", p);
178
143
  writef(g, s, p);
179
144
  writef(g, ")~N", p);
@@ -185,7 +150,6 @@ static void write_failure_if(struct generator * g, char * s, struct node * p) {
185
150
 
186
151
  /* if at limit fail */
187
152
  static void write_check_limit(struct generator * g, struct node * p) {
188
-
189
153
  if (p->mode == m_forward) {
190
154
  write_failure_if(g, "base.cursor >= base.limit", p);
191
155
  } else {
@@ -195,18 +159,18 @@ static void write_check_limit(struct generator * g, struct node * p) {
195
159
 
196
160
  /* Formatted write. */
197
161
  static void writef(struct generator * g, const char * input, struct node * p) {
162
+ (void)p;
198
163
  int i = 0;
199
- int l = strlen(input);
200
164
 
201
- while (i < l) {
165
+ while (input[i]) {
202
166
  int ch = input[i++];
203
167
  if (ch != '~') {
204
168
  write_char(g, ch);
205
169
  continue;
206
170
  }
207
- switch (input[i++]) {
208
- default: write_char(g, input[i - 1]); continue;
209
- case 'C': write_comment(g, p); continue;
171
+ ch = input[i++];
172
+ switch (ch) {
173
+ case '~': write_char(g, '~'); continue;
210
174
  case 'f': write_block_start(g);
211
175
  write_failure(g);
212
176
  g->unreachable = false;
@@ -216,22 +180,82 @@ static void writef(struct generator * g, const char * input, struct node * p) {
216
180
  case 'N': write_newline(g); continue;
217
181
  case '{': write_block_start(g); continue;
218
182
  case '}': write_block_end(g); continue;
219
- case 'S': write_string(g, g->S[input[i++] - '0']); continue;
220
- case 'B': write_b(g, g->B[input[i++] - '0']); continue;
221
- case 'I': write_int(g, g->I[input[i++] - '0']); continue;
222
- case 'V': write_varref(g, g->V[input[i++] - '0']); continue;
223
- case 'W': write_varname(g, g->V[input[i++] - '0']); continue;
224
- case 'L': write_literal_string(g, g->L[input[i++] - '0']); continue;
183
+ case 'S': {
184
+ int j = input[i++] - '0';
185
+ if (j < 0 || j > (int)(sizeof(g->S) / sizeof(g->S[0]))) {
186
+ printf("Invalid escape sequence ~%c%c in writef(g, \"%s\", p)\n",
187
+ ch, input[i - 1], input);
188
+ exit(1);
189
+ }
190
+ write_string(g, g->S[j]);
191
+ continue;
192
+ }
193
+ case 'B': {
194
+ int j = input[i++] - '0';
195
+ if (j < 0 || j > (int)(sizeof(g->B) / sizeof(g->B[0])))
196
+ goto invalid_escape2;
197
+ write_s(g, g->B[j]);
198
+ continue;
199
+ }
200
+ case 'I': {
201
+ int j = input[i++] - '0';
202
+ if (j < 0 || j > (int)(sizeof(g->I) / sizeof(g->I[0])))
203
+ goto invalid_escape2;
204
+ write_int(g, g->I[j]);
205
+ continue;
206
+ }
207
+ case 'V':
208
+ case 'W': {
209
+ int j = input[i++] - '0';
210
+ if (j < 0 || j > (int)(sizeof(g->V) / sizeof(g->V[0])))
211
+ goto invalid_escape2;
212
+ if (ch == 'V')
213
+ write_varref(g, g->V[j]);
214
+ else
215
+ write_varname(g, g->V[j]);
216
+ continue;
217
+ }
218
+ case 'L': {
219
+ int j = input[i++] - '0';
220
+ if (j < 0 || j > (int)(sizeof(g->L) / sizeof(g->L[0])))
221
+ goto invalid_escape2;
222
+ write_literal_string(g, g->L[j]);
223
+ continue;
224
+ }
225
225
  case '+': g->margin++; continue;
226
226
  case '-': g->margin--; continue;
227
227
  case 'n': write_string(g, g->options->name); continue;
228
228
  case 'P': write_string(g, g->options->parent_class_name); continue;
229
+ case 'C': { // Constant.
230
+ if (g->options->js_esm) {
231
+ w(g, "const");
232
+ } else {
233
+ w(g, "/** @const */ var");
234
+ }
235
+ continue;
236
+ }
237
+ case 'D': { // Declare variable.
238
+ if (g->options->js_esm) {
239
+ w(g, "let");
240
+ } else {
241
+ w(g, "var");
242
+ }
243
+ continue;
244
+ }
245
+ default:
246
+ printf("Invalid escape sequence ~%c in writef(g, \"%s\", p)\n",
247
+ ch, input);
248
+ exit(1);
249
+ invalid_escape2:
250
+ printf("Invalid escape sequence ~%c%c in writef(g, \"%s\", p)\n",
251
+ ch, input[i - 1], input);
252
+ exit(1);
229
253
  }
230
254
  }
231
255
  }
232
256
 
233
257
  static void w(struct generator * g, const char * s) {
234
- writef(g, s, 0);
258
+ writef(g, s, NULL);
235
259
  }
236
260
 
237
261
  static void generate_AE(struct generator * g, struct node * p) {
@@ -283,7 +307,6 @@ static void generate_AE(struct generator * g, struct node * p) {
283
307
  }
284
308
 
285
309
  static void generate_bra(struct generator * g, struct node * p) {
286
-
287
310
  write_comment(g, p);
288
311
  p = p->left;
289
312
  while (p) {
@@ -293,28 +316,33 @@ static void generate_bra(struct generator * g, struct node * p) {
293
316
  }
294
317
 
295
318
  static void generate_and(struct generator * g, struct node * p) {
296
-
297
- struct str * savevar = vars_newname(g);
298
- int keep_c = K_needed(g, p->left);
319
+ struct str * savevar = NULL;
320
+ if (K_needed(g, p->left)) {
321
+ savevar = vars_newname(g);
322
+ }
299
323
 
300
324
  write_comment(g, p);
301
325
 
302
- if (keep_c) write_savecursor(g, p, savevar);
326
+ if (savevar) write_savecursor(g, p, savevar);
303
327
 
304
328
  p = p->left;
305
329
  while (p) {
306
330
  generate(g, p);
307
331
  if (g->unreachable) break;
308
- if (keep_c && p->right != 0) write_restorecursor(g, p, savevar);
332
+ if (savevar && p->right != NULL) write_restorecursor(g, p, savevar);
309
333
  p = p->right;
310
334
  }
311
- str_delete(savevar);
335
+
336
+ if (savevar) {
337
+ str_delete(savevar);
338
+ }
312
339
  }
313
340
 
314
341
  static void generate_or(struct generator * g, struct node * p) {
315
-
316
- struct str * savevar = vars_newname(g);
317
- int keep_c = K_needed(g, p->left);
342
+ struct str * savevar = NULL;
343
+ if (K_needed(g, p->left)) {
344
+ savevar = vars_newname(g);
345
+ }
318
346
 
319
347
  int a0 = g->failure_label;
320
348
  struct str * a1 = str_copy(g->failure_str);
@@ -325,18 +353,18 @@ static void generate_or(struct generator * g, struct node * p) {
325
353
  write_comment(g, p);
326
354
  wsetlab_begin(g, out_lab);
327
355
 
328
- if (keep_c) write_savecursor(g, p, savevar);
356
+ if (savevar) write_savecursor(g, p, savevar);
329
357
 
330
358
  p = p->left;
331
359
  str_clear(g->failure_str);
332
360
 
333
- if (p == 0) {
334
- /* p should never be 0 after an or: there should be at least two
361
+ if (p == NULL) {
362
+ /* p should never be NULL after an or: there should be at least two
335
363
  * sub nodes. */
336
364
  fprintf(stderr, "Error: \"or\" node without children nodes.");
337
365
  exit(1);
338
366
  }
339
- while (p->right != 0) {
367
+ while (p->right != NULL) {
340
368
  g->failure_label = new_label(g);
341
369
  wsetlab_begin(g, g->failure_label);
342
370
  generate(g, p);
@@ -346,7 +374,7 @@ static void generate_or(struct generator * g, struct node * p) {
346
374
  }
347
375
  wsetlab_end(g);
348
376
  g->unreachable = false;
349
- if (keep_c) write_restorecursor(g, p, savevar);
377
+ if (savevar) write_restorecursor(g, p, savevar);
350
378
  p = p->right;
351
379
  }
352
380
 
@@ -359,11 +387,13 @@ static void generate_or(struct generator * g, struct node * p) {
359
387
  if (!end_unreachable) {
360
388
  g->unreachable = false;
361
389
  }
362
- str_delete(savevar);
390
+
391
+ if (savevar) {
392
+ str_delete(savevar);
393
+ }
363
394
  }
364
395
 
365
396
  static void generate_backwards(struct generator * g, struct node * p) {
366
-
367
397
  write_comment(g, p);
368
398
  writef(g, "~Mbase.limit_backward = base.cursor; base.cursor = base.limit;~N", p);
369
399
  generate(g, p->left);
@@ -372,15 +402,16 @@ static void generate_backwards(struct generator * g, struct node * p) {
372
402
 
373
403
 
374
404
  static void generate_not(struct generator * g, struct node * p) {
375
-
376
- struct str * savevar = vars_newname(g);
377
- int keep_c = K_needed(g, p->left);
405
+ struct str * savevar = NULL;
406
+ if (K_needed(g, p->left)) {
407
+ savevar = vars_newname(g);
408
+ }
378
409
 
379
410
  int a0 = g->failure_label;
380
411
  struct str * a1 = str_copy(g->failure_str);
381
412
 
382
413
  write_comment(g, p);
383
- if (keep_c) {
414
+ if (savevar) {
384
415
  write_block_start(g);
385
416
  write_savecursor(g, p, savevar);
386
417
  }
@@ -401,48 +432,52 @@ static void generate_not(struct generator * g, struct node * p) {
401
432
  wsetlab_end(g);
402
433
  g->unreachable = false;
403
434
 
404
- if (keep_c) write_restorecursor(g, p, savevar);
405
- if (keep_c) write_block_end(g);
406
- str_delete(savevar);
435
+ if (savevar) {
436
+ write_restorecursor(g, p, savevar);
437
+ write_block_end(g);
438
+ str_delete(savevar);
439
+ }
407
440
  }
408
441
 
409
442
 
410
443
  static void generate_try(struct generator * g, struct node * p) {
411
-
412
- struct str * savevar = vars_newname(g);
413
- int keep_c = K_needed(g, p->left);
414
-
415
- write_comment(g, p);
416
- if (keep_c) write_savecursor(g, p, savevar);
444
+ struct str * savevar = NULL;
445
+ if (K_needed(g, p->left)) {
446
+ savevar = vars_newname(g);
447
+ }
417
448
 
418
449
  g->failure_label = new_label(g);
419
450
  str_clear(g->failure_str);
420
- if (keep_c) restore_string(p, g->failure_str, savevar);
451
+
452
+ write_comment(g, p);
453
+ if (savevar) {
454
+ write_savecursor(g, p, savevar);
455
+ append_restore_string(p, g->failure_str, savevar);
456
+ }
421
457
 
422
458
  wsetlab_begin(g, g->failure_label);
423
459
  generate(g, p->left);
424
460
  wsetlab_end(g);
425
461
  g->unreachable = false;
426
462
 
427
- str_delete(savevar);
463
+ if (savevar) {
464
+ str_delete(savevar);
465
+ }
428
466
  }
429
467
 
430
468
  static void generate_set(struct generator * g, struct node * p) {
431
-
432
469
  write_comment(g, p);
433
470
  g->V[0] = p->name;
434
471
  writef(g, "~M~V0 = true;~N", p);
435
472
  }
436
473
 
437
474
  static void generate_unset(struct generator * g, struct node * p) {
438
-
439
475
  write_comment(g, p);
440
476
  g->V[0] = p->name;
441
477
  writef(g, "~M~V0 = false;~N", p);
442
478
  }
443
479
 
444
480
  static void generate_fail(struct generator * g, struct node * p) {
445
-
446
481
  write_comment(g, p);
447
482
  generate(g, p->left);
448
483
  if (!g->unreachable) write_failure(g);
@@ -451,32 +486,35 @@ static void generate_fail(struct generator * g, struct node * p) {
451
486
  /* generate_test() also implements 'reverse' */
452
487
 
453
488
  static void generate_test(struct generator * g, struct node * p) {
454
-
455
- struct str * savevar = vars_newname(g);
456
- int keep_c = K_needed(g, p->left);
489
+ struct str * savevar = NULL;
490
+ if (K_needed(g, p->left)) {
491
+ savevar = vars_newname(g);
492
+ }
457
493
 
458
494
  write_comment(g, p);
459
495
 
460
- if (keep_c) {
496
+ if (savevar) {
461
497
  write_savecursor(g, p, savevar);
462
498
  }
463
499
 
464
500
  generate(g, p->left);
465
501
 
466
- if (!g->unreachable) {
467
- if (keep_c) {
502
+ if (savevar) {
503
+ if (!g->unreachable) {
468
504
  write_restorecursor(g, p, savevar);
469
505
  }
506
+ str_delete(savevar);
470
507
  }
471
- str_delete(savevar);
472
508
  }
473
509
 
474
510
  static void generate_do(struct generator * g, struct node * p) {
511
+ struct str * savevar = NULL;
512
+ if (K_needed(g, p->left)) {
513
+ savevar = vars_newname(g);
514
+ }
475
515
 
476
- struct str * savevar = vars_newname(g);
477
- int keep_c = K_needed(g, p->left);
478
516
  write_comment(g, p);
479
- if (keep_c) write_savecursor(g, p, savevar);
517
+ if (savevar) write_savecursor(g, p, savevar);
480
518
 
481
519
  if (p->left->type == c_call) {
482
520
  /* Optimise do <call> */
@@ -493,26 +531,53 @@ static void generate_do(struct generator * g, struct node * p) {
493
531
  g->unreachable = false;
494
532
  }
495
533
 
496
- if (keep_c) write_restorecursor(g, p, savevar);
497
- str_delete(savevar);
534
+ if (savevar) {
535
+ write_restorecursor(g, p, savevar);
536
+ str_delete(savevar);
537
+ }
498
538
  }
499
539
 
500
- static void generate_GO(struct generator * g, struct node * p, int style) {
540
+ static void generate_next(struct generator * g, struct node * p) {
541
+ write_comment(g, p);
542
+ write_check_limit(g, p);
543
+ write_inc_cursor(g, p);
544
+ }
501
545
 
502
- int end_unreachable = false;
503
- struct str * savevar = vars_newname(g);
504
- int keep_c = style == 1 || repeat_restore(g, p->left);
546
+ static void generate_GO_grouping(struct generator * g, struct node * p, int is_goto, int complement) {
547
+ write_comment(g, p);
548
+
549
+ struct grouping * q = p->name->grouping;
550
+ g->S[0] = p->mode == m_forward ? "" : "_b";
551
+ g->S[1] = complement ? "in" : "out";
552
+ g->V[0] = p->name;
553
+ g->I[0] = q->smallest_ch;
554
+ g->I[1] = q->largest_ch;
555
+ write_failure_if(g, "!base.go_~S1_grouping~S0(~V0, ~I0, ~I1)", p);
556
+ if (!is_goto) {
557
+ if (p->mode == m_forward)
558
+ w(g, "~Mbase.cursor++;~N");
559
+ else
560
+ w(g, "~Mbase.cursor--;~N");
561
+ }
562
+ }
563
+
564
+ static void generate_GO(struct generator * g, struct node * p, int style) {
565
+ write_comment(g, p);
505
566
 
506
567
  int a0 = g->failure_label;
507
568
  struct str * a1 = str_copy(g->failure_str);
508
569
 
570
+ int end_unreachable = false;
509
571
  int golab = new_label(g);
510
572
  g->I[0] = golab;
511
- write_comment(g, p);
512
573
  w(g, "~Mgolab~I0: while(true)~N");
513
574
  w(g, "~{");
514
575
 
515
- if (keep_c) write_savecursor(g, p, savevar);
576
+ struct str * savevar = NULL;
577
+ if (style == 1 || repeat_restore(g, p->left)) {
578
+ savevar = vars_newname(g);
579
+ write_savecursor(g, p, savevar);
580
+ }
516
581
 
517
582
  g->failure_label = new_label(g);
518
583
  str_clear(g->failure_str);
@@ -531,7 +596,10 @@ static void generate_GO(struct generator * g, struct node * p, int style) {
531
596
  }
532
597
  g->unreachable = false;
533
598
  wsetlab_end(g);
534
- if (keep_c) write_restorecursor(g, p, savevar);
599
+ if (savevar) {
600
+ write_restorecursor(g, p, savevar);
601
+ str_delete(savevar);
602
+ }
535
603
 
536
604
  g->failure_label = a0;
537
605
  str_delete(g->failure_str);
@@ -540,16 +608,14 @@ static void generate_GO(struct generator * g, struct node * p, int style) {
540
608
  write_check_limit(g, p);
541
609
  write_inc_cursor(g, p);
542
610
  write_block_end(g);
543
- str_delete(savevar);
544
611
  g->unreachable = end_unreachable;
545
612
  }
546
613
 
547
614
  static void generate_loop(struct generator * g, struct node * p) {
548
-
549
615
  struct str * loopvar = vars_newname(g);
550
616
  write_comment(g, p);
551
617
  g->B[0] = str_data(loopvar);
552
- w(g, "~Mfor (var /** number */ ~B0 = ");
618
+ w(g, "~Mfor (~D /** number */ ~B0 = ");
553
619
  generate_AE(g, p->AE);
554
620
  g->B[0] = str_data(loopvar);
555
621
  writef(g, "; ~B0 > 0; ~B0--)~N", p);
@@ -563,12 +629,13 @@ static void generate_loop(struct generator * g, struct node * p) {
563
629
  }
564
630
 
565
631
  static void generate_repeat_or_atleast(struct generator * g, struct node * p, struct str * loopvar) {
566
-
567
- struct str * savevar = vars_newname(g);
568
- int keep_c = repeat_restore(g, p->left);
569
632
  writef(g, "~Mwhile(true)~N~{", p);
570
633
 
571
- if (keep_c) write_savecursor(g, p, savevar);
634
+ struct str * savevar = NULL;
635
+ if (repeat_restore(g, p->left)) {
636
+ savevar = vars_newname(g);
637
+ write_savecursor(g, p, savevar);
638
+ }
572
639
 
573
640
  g->failure_label = new_label(g);
574
641
  str_clear(g->failure_str);
@@ -576,7 +643,7 @@ static void generate_repeat_or_atleast(struct generator * g, struct node * p, st
576
643
  generate(g, p->left);
577
644
 
578
645
  if (!g->unreachable) {
579
- if (loopvar != 0) {
646
+ if (loopvar != NULL) {
580
647
  g->B[0] = str_data(loopvar);
581
648
  w(g, "~M~B0--;~N");
582
649
  }
@@ -587,10 +654,12 @@ static void generate_repeat_or_atleast(struct generator * g, struct node * p, st
587
654
  wsetlab_end(g);
588
655
  g->unreachable = false;
589
656
 
590
- if (keep_c) write_restorecursor(g, p, savevar);
657
+ if (savevar) {
658
+ write_restorecursor(g, p, savevar);
659
+ str_delete(savevar);
660
+ }
591
661
 
592
662
  w(g, "~Mbreak;~N~}");
593
- str_delete(savevar);
594
663
  }
595
664
 
596
665
  static void generate_repeat(struct generator * g, struct node * p) {
@@ -599,12 +668,12 @@ static void generate_repeat(struct generator * g, struct node * p) {
599
668
  }
600
669
 
601
670
  static void generate_atleast(struct generator * g, struct node * p) {
602
-
603
671
  struct str * loopvar = vars_newname(g);
672
+
604
673
  write_comment(g, p);
605
674
  w(g, "~{");
606
675
  g->B[0] = str_data(loopvar);
607
- w(g, "~Mvar ~B0 = ");
676
+ w(g, "~M~D ~B0 = ");
608
677
  generate_AE(g, p->AE);
609
678
  w(g, ";~N");
610
679
  {
@@ -624,14 +693,12 @@ static void generate_atleast(struct generator * g, struct node * p) {
624
693
  }
625
694
 
626
695
  static void generate_setmark(struct generator * g, struct node * p) {
627
-
628
696
  write_comment(g, p);
629
697
  g->V[0] = p->name;
630
698
  writef(g, "~M~V0 = base.cursor;~N", p);
631
699
  }
632
700
 
633
701
  static void generate_tomark(struct generator * g, struct node * p) {
634
-
635
702
  write_comment(g, p);
636
703
  g->S[0] = p->mode == m_forward ? ">" : "<";
637
704
 
@@ -644,7 +711,6 @@ static void generate_tomark(struct generator * g, struct node * p) {
644
711
  }
645
712
 
646
713
  static void generate_atmark(struct generator * g, struct node * p) {
647
-
648
714
  write_comment(g, p);
649
715
  w(g, "~Mif (base.cursor != "); generate_AE(g, p->AE); writef(g, ")~N", p);
650
716
  write_block_start(g);
@@ -659,7 +725,7 @@ static void generate_hop(struct generator * g, struct node * p) {
659
725
  g->S[0] = p->mode == m_forward ? "+" : "-";
660
726
 
661
727
  g->I[0] = c_count;
662
- w(g, "~{~Mvar /** number */ c~I0 = base.cursor ~S0 ");
728
+ w(g, "~{~M~C /** number */ c~I0 = base.cursor ~S0 ");
663
729
  generate_AE(g, p->AE);
664
730
  w(g, ";~N");
665
731
 
@@ -680,7 +746,6 @@ static void generate_hop(struct generator * g, struct node * p) {
680
746
  }
681
747
 
682
748
  static void generate_delete(struct generator * g, struct node * p) {
683
-
684
749
  write_comment(g, p);
685
750
  writef(g, "~Mif (!base.slice_del())~N"
686
751
  "~M{~N"
@@ -688,16 +753,7 @@ static void generate_delete(struct generator * g, struct node * p) {
688
753
  "~M}~N", p);
689
754
  }
690
755
 
691
-
692
- static void generate_next(struct generator * g, struct node * p) {
693
-
694
- write_comment(g, p);
695
- write_check_limit(g, p);
696
- write_inc_cursor(g, p);
697
- }
698
-
699
756
  static void generate_tolimit(struct generator * g, struct node * p) {
700
-
701
757
  write_comment(g, p);
702
758
  if (p->mode == m_forward) {
703
759
  writef(g, "~Mbase.cursor = base.limit;~N", p);
@@ -707,7 +763,6 @@ static void generate_tolimit(struct generator * g, struct node * p) {
707
763
  }
708
764
 
709
765
  static void generate_atlimit(struct generator * g, struct node * p) {
710
-
711
766
  write_comment(g, p);
712
767
  if (p->mode == m_forward) {
713
768
  write_failure_if(g, "base.cursor < base.limit", p);
@@ -717,7 +772,6 @@ static void generate_atlimit(struct generator * g, struct node * p) {
717
772
  }
718
773
 
719
774
  static void generate_leftslice(struct generator * g, struct node * p) {
720
-
721
775
  write_comment(g, p);
722
776
  if (p->mode == m_forward) {
723
777
  writef(g, "~Mbase.bra = base.cursor;~N", p);
@@ -727,7 +781,6 @@ static void generate_leftslice(struct generator * g, struct node * p) {
727
781
  }
728
782
 
729
783
  static void generate_rightslice(struct generator * g, struct node * p) {
730
-
731
784
  write_comment(g, p);
732
785
  if (p->mode == m_forward) {
733
786
  writef(g, "~Mbase.ket = base.cursor;~N", p);
@@ -737,14 +790,12 @@ static void generate_rightslice(struct generator * g, struct node * p) {
737
790
  }
738
791
 
739
792
  static void generate_assignto(struct generator * g, struct node * p) {
740
-
741
793
  write_comment(g, p);
742
794
  g->V[0] = p->name;
743
795
  writef(g, "~M~V0 = base.assign_to();~N", p);
744
796
  }
745
797
 
746
798
  static void generate_sliceto(struct generator * g, struct node * p) {
747
-
748
799
  write_comment(g, p);
749
800
  g->V[0] = p->name;
750
801
  writef(g, "~M~V0 = base.slice_to();~N"
@@ -755,9 +806,8 @@ static void generate_sliceto(struct generator * g, struct node * p) {
755
806
  }
756
807
 
757
808
  static void generate_address(struct generator * g, struct node * p) {
758
-
759
809
  symbol * b = p->literalstring;
760
- if (b != 0) {
810
+ if (b != NULL) {
761
811
  write_literal_string(g, b);
762
812
  } else {
763
813
  write_varref(g, p->name);
@@ -772,7 +822,7 @@ static void generate_insert(struct generator * g, struct node * p, int style) {
772
822
  if (keep_c) {
773
823
  c_count = ++g->keep_count;
774
824
  g->I[0] = c_count;
775
- w(g, "~{~Mvar /** number */ c~I0 = base.cursor;~N");
825
+ w(g, "~{~M~C /** number */ c~I0 = base.cursor;~N");
776
826
  }
777
827
  writef(g, "~Mbase.insert(base.cursor, base.cursor, ", p);
778
828
  generate_address(g, p);
@@ -791,7 +841,7 @@ static void generate_assignfrom(struct generator * g, struct node * p) {
791
841
  if (keep_c) {
792
842
  c_count = ++g->keep_count;
793
843
  g->I[0] = c_count;
794
- w(g, "~{~Mvar /** number */ c~I0 = base.cursor;~N");
844
+ w(g, "~{~M~C /** number */ c~I0 = base.cursor;~N");
795
845
  }
796
846
  if (p->mode == m_forward) {
797
847
  writef(g, "~Mbase.insert(base.cursor, base.limit, ", p);
@@ -806,9 +856,7 @@ static void generate_assignfrom(struct generator * g, struct node * p) {
806
856
  }
807
857
  }
808
858
 
809
-
810
859
  static void generate_slicefrom(struct generator * g, struct node * p) {
811
-
812
860
  write_comment(g, p);
813
861
  w(g, "~Mif (!base.slice_from(");
814
862
  generate_address(g, p);
@@ -819,7 +867,6 @@ static void generate_slicefrom(struct generator * g, struct node * p) {
819
867
  }
820
868
 
821
869
  static void generate_setlimit(struct generator * g, struct node * p) {
822
- struct str * savevar = vars_newname(g);
823
870
  struct str * varname = vars_newname(g);
824
871
  write_comment(g, p);
825
872
  if (p->left && p->left->type == c_tomark) {
@@ -832,6 +879,7 @@ static void generate_setlimit(struct generator * g, struct node * p) {
832
879
  * restore c.
833
880
  */
834
881
  struct node * q = p->left;
882
+ write_comment(g, q);
835
883
  g->S[0] = q->mode == m_forward ? ">" : "<";
836
884
  w(g, "~Mif (base.cursor ~S0 "); generate_AE(g, q->AE); w(g, ")~N");
837
885
  write_block_start(g);
@@ -840,7 +888,7 @@ static void generate_setlimit(struct generator * g, struct node * p) {
840
888
  g->unreachable = false;
841
889
 
842
890
  g->B[0] = str_data(varname);
843
- w(g, "~Mvar /** number */ ~B0 = ");
891
+ w(g, "~M~C /** number */ ~B0 = ");
844
892
  if (p->mode == m_forward) {
845
893
  w(g, "base.limit - base.cursor;~N");
846
894
  w(g, "~Mbase.limit = ");
@@ -860,12 +908,14 @@ static void generate_setlimit(struct generator * g, struct node * p) {
860
908
  str_append_ch(g->failure_str, ';');
861
909
  }
862
910
  } else {
911
+ struct str * savevar = vars_newname(g);
863
912
  write_savecursor(g, p, savevar);
913
+
864
914
  generate(g, p->left);
865
915
 
866
916
  if (!g->unreachable) {
867
917
  g->B[0] = str_data(varname);
868
- w(g, "~Mvar /** number */ ~B0 = ");
918
+ w(g, "~M~C /** number */ ~B0 = ");
869
919
  if (p->mode == m_forward) {
870
920
  w(g, "base.limit - base.cursor;~N");
871
921
  w(g, "~Mbase.limit = base.cursor;~N");
@@ -885,6 +935,7 @@ static void generate_setlimit(struct generator * g, struct node * p) {
885
935
  str_append_ch(g->failure_str, ';');
886
936
  }
887
937
  }
938
+ str_delete(savevar);
888
939
  }
889
940
 
890
941
  if (!g->unreachable) {
@@ -897,17 +948,17 @@ static void generate_setlimit(struct generator * g, struct node * p) {
897
948
  }
898
949
  }
899
950
  str_delete(varname);
900
- str_delete(savevar);
901
951
  }
902
952
 
903
953
  /* dollar sets snowball up to operate on a string variable as if it were the
904
954
  * current string */
905
955
  static void generate_dollar(struct generator * g, struct node * p) {
956
+ write_comment(g, p);
906
957
 
907
958
  struct str * savevar = vars_newname(g);
908
959
  g->B[0] = str_data(savevar);
909
- writef(g, "~{~C~N"
910
- "~Mvar /** !Object */ ~B0 = new BaseStemmer();~N", p);
960
+ writef(g, "~{~N"
961
+ "~M~D /** !Object */ ~B0 = new ~P();~N", p);
911
962
  writef(g, "~M~B0.copy_from(base);~N", p);
912
963
 
913
964
  ++g->copy_from_count;
@@ -931,36 +982,66 @@ static void generate_dollar(struct generator * g, struct node * p) {
931
982
  str_delete(savevar);
932
983
  }
933
984
 
934
- static void generate_integer_assign(struct generator * g, struct node * p, char * s) {
935
-
985
+ static void generate_integer_assign(struct generator * g, struct node * p, const char * s) {
986
+ write_comment(g, p);
936
987
  g->V[0] = p->name;
937
988
  g->S[0] = s;
938
- w(g, "~M~V0 ~S0 "); generate_AE(g, p->AE); w(g, ";~N");
989
+ w(g, "~M~V0 ~S0 ");
990
+ generate_AE(g, p->AE);
991
+ w(g, ";~N");
939
992
  }
940
993
 
941
- static void generate_integer_test(struct generator * g, struct node * p, char * s) {
942
-
943
- w(g, "~Mif (!(");
994
+ static void generate_integer_test(struct generator * g, struct node * p) {
995
+ write_comment(g, p);
996
+ int relop = p->type;
997
+ int optimise_to_return = (g->failure_label == x_return && p->right && p->right->type == c_functionend);
998
+ if (optimise_to_return) {
999
+ w(g, "~Mreturn ");
1000
+ p->right = NULL;
1001
+ } else {
1002
+ w(g, "~Mif (");
1003
+ // We want the inverse of the snowball test here.
1004
+ relop ^= 1;
1005
+ }
944
1006
  generate_AE(g, p->left);
945
- write_char(g, ' ');
946
- write_string(g, s);
947
- write_char(g, ' ');
1007
+ // Relational operators are the same as C.
1008
+ write_c_relop(g, relop);
948
1009
  generate_AE(g, p->AE);
949
- w(g, "))~N");
950
- write_block_start(g);
951
- write_failure(g);
952
- write_block_end(g);
953
- g->unreachable = false;
1010
+ if (optimise_to_return) {
1011
+ w(g, ";~N");
1012
+ } else {
1013
+ w(g, ")~N");
1014
+ write_block_start(g);
1015
+ write_failure(g);
1016
+ write_block_end(g);
1017
+ g->unreachable = false;
1018
+ }
954
1019
  }
955
1020
 
956
1021
  static void generate_call(struct generator * g, struct node * p) {
957
-
1022
+ int signals = check_possible_signals_list(g, p->name->definition, c_define, 0);
958
1023
  write_comment(g, p);
959
1024
  g->V[0] = p->name;
960
- write_failure_if(g, "!~V0()", p);
1025
+ if (g->failure_label == x_return &&
1026
+ (signals == 0 || (p->right && p->right->type == c_functionend))) {
1027
+ /* Always fails or tail call. */
1028
+ writef(g, "~Mreturn ~V0();~N", p);
1029
+ return;
1030
+ }
1031
+ if (signals == 1) {
1032
+ /* Always succeeds. */
1033
+ writef(g, "~M~V0();~N", p);
1034
+ } else if (signals == 0) {
1035
+ /* Always fails. */
1036
+ writef(g, "~M~V0();~N", p);
1037
+ write_failure(g);
1038
+ } else {
1039
+ write_failure_if(g, "!~V0()", p);
1040
+ }
961
1041
  }
962
1042
 
963
1043
  static void generate_grouping(struct generator * g, struct node * p, int complement) {
1044
+ write_comment(g, p);
964
1045
 
965
1046
  struct grouping * q = p->name->grouping;
966
1047
  g->S[0] = p->mode == m_forward ? "" : "_b";
@@ -972,7 +1053,6 @@ static void generate_grouping(struct generator * g, struct node * p, int complem
972
1053
  }
973
1054
 
974
1055
  static void generate_namedstring(struct generator * g, struct node * p) {
975
-
976
1056
  write_comment(g, p);
977
1057
  g->S[0] = p->mode == m_forward ? "" : "_b";
978
1058
  g->V[0] = p->name;
@@ -989,18 +1069,22 @@ static void generate_literalstring(struct generator * g, struct node * p) {
989
1069
 
990
1070
  static void generate_define(struct generator * g, struct node * p) {
991
1071
  struct name * q = p->name;
1072
+ if (q->type == t_routine && !q->used) return;
992
1073
 
993
- struct str * saved_output = g->outbuf;
994
- struct str * saved_declarations = g->declarations;
1074
+ write_newline(g);
1075
+ write_comment(g, p);
995
1076
 
996
1077
  g->V[0] = q;
997
1078
  if (q->type == t_routine) {
998
- w(g, "~N~M/** @return {boolean} */~N"
1079
+ w(g, "~M/** @return {boolean} */~N"
999
1080
  "~Mfunction ~W0() {~+~N");
1000
1081
  } else {
1001
- w(g, "~N~Mthis.~W0 = /** @return {boolean} */ function() {~+~N");
1082
+ w(g, "~Mthis.~W0 = /** @return {boolean} */ function() {~+~N");
1002
1083
  }
1003
1084
 
1085
+ /* Save output. */
1086
+ struct str * saved_output = g->outbuf;
1087
+ struct str * saved_declarations = g->declarations;
1004
1088
  g->outbuf = str_new();
1005
1089
  g->declarations = str_new();
1006
1090
 
@@ -1008,14 +1092,22 @@ static void generate_define(struct generator * g, struct node * p) {
1008
1092
  g->var_number = 0;
1009
1093
 
1010
1094
  if (p->amongvar_needed) {
1011
- w(g, "~Mvar /** number */ among_var;~N");
1095
+ w(g, "~M~D /** number */ among_var;~N");
1012
1096
  }
1013
1097
  str_clear(g->failure_str);
1014
1098
  g->failure_label = x_return;
1015
1099
  g->unreachable = false;
1016
1100
  g->keep_count = 0;
1101
+ int signals = check_possible_signals_list(g, p->left, c_define, 0);
1102
+
1103
+ /* Generate function body. */
1017
1104
  generate(g, p->left);
1018
- if (!g->unreachable) w(g, "~Mreturn true;~N");
1105
+ if (p->left->right) {
1106
+ assert(p->left->right->type == c_functionend);
1107
+ if (signals) {
1108
+ generate(g, p->left->right);
1109
+ }
1110
+ }
1019
1111
  w(g, "~-~M};~N");
1020
1112
 
1021
1113
  str_append(saved_output, g->declarations);
@@ -1026,38 +1118,46 @@ static void generate_define(struct generator * g, struct node * p) {
1026
1118
  g->outbuf = saved_output;
1027
1119
  }
1028
1120
 
1121
+ static void generate_functionend(struct generator * g, struct node * p) {
1122
+ (void)p;
1123
+ w(g, "~Mreturn true;~N");
1124
+ }
1125
+
1029
1126
  static void generate_substring(struct generator * g, struct node * p) {
1127
+ write_comment(g, p);
1030
1128
 
1031
1129
  struct among * x = p->among;
1032
1130
 
1033
- write_comment(g, p);
1034
-
1035
1131
  g->S[0] = p->mode == m_forward ? "" : "_b";
1036
1132
  g->I[0] = x->number;
1037
1133
 
1038
- if (!x->amongvar_needed) {
1039
- write_failure_if(g, "base.find_among~S0(a_~I0) == 0", p);
1040
- } else {
1134
+ if (x->amongvar_needed) {
1041
1135
  writef(g, "~Mamong_var = base.find_among~S0(a_~I0);~N", p);
1042
- write_failure_if(g, "among_var == 0", p);
1136
+ if (!x->always_matches) {
1137
+ write_failure_if(g, "among_var == 0", p);
1138
+ }
1139
+ } else if (x->always_matches) {
1140
+ writef(g, "~Mbase.find_among~S0(a_~I0);~N", p);
1141
+ } else {
1142
+ write_failure_if(g, "base.find_among~S0(a_~I0) == 0", p);
1043
1143
  }
1044
1144
  }
1045
1145
 
1046
1146
  static void generate_among(struct generator * g, struct node * p) {
1047
-
1048
1147
  struct among * x = p->among;
1049
1148
 
1050
- if (x->substring == 0) generate_substring(g, p);
1051
-
1052
- if (x->starter != 0) generate(g, x->starter);
1149
+ if (x->substring == NULL) {
1150
+ generate_substring(g, p);
1151
+ } else {
1152
+ write_comment(g, p);
1153
+ }
1053
1154
 
1054
1155
  if (x->command_count == 1 && x->nocommand_count == 0) {
1055
1156
  /* Only one outcome ("no match" already handled). */
1056
1157
  generate(g, x->commands[0]);
1057
1158
  } else if (x->command_count > 0) {
1058
- int i;
1059
1159
  w(g, "~Mswitch (among_var) {~N~+");
1060
- for (i = 1; i <= x->command_count; i++) {
1160
+ for (int i = 1; i <= x->command_count; i++) {
1061
1161
  g->I[0] = i;
1062
1162
  w(g, "~Mcase ~I0:~N~+");
1063
1163
  generate(g, x->commands[i - 1]);
@@ -1070,20 +1170,17 @@ static void generate_among(struct generator * g, struct node * p) {
1070
1170
  }
1071
1171
 
1072
1172
  static void generate_booltest(struct generator * g, struct node * p) {
1073
-
1074
1173
  write_comment(g, p);
1075
1174
  g->V[0] = p->name;
1076
1175
  write_failure_if(g, "!~V0", p);
1077
1176
  }
1078
1177
 
1079
1178
  static void generate_false(struct generator * g, struct node * p) {
1080
-
1081
1179
  write_comment(g, p);
1082
1180
  write_failure(g);
1083
1181
  }
1084
1182
 
1085
1183
  static void generate_debug(struct generator * g, struct node * p) {
1086
-
1087
1184
  write_comment(g, p);
1088
1185
  g->I[0] = g->debug_count++;
1089
1186
  g->I[1] = p->line_number;
@@ -1091,14 +1188,10 @@ static void generate_debug(struct generator * g, struct node * p) {
1091
1188
  }
1092
1189
 
1093
1190
  static void generate(struct generator * g, struct node * p) {
1094
-
1095
- int a0;
1096
- struct str * a1;
1097
-
1098
1191
  if (g->unreachable) return;
1099
1192
 
1100
- a0 = g->failure_label;
1101
- a1 = str_copy(g->failure_str);
1193
+ int a0 = g->failure_label;
1194
+ struct str * a1 = str_copy(g->failure_str);
1102
1195
 
1103
1196
  switch (p->type) {
1104
1197
  case c_define: generate_define(g, p); break;
@@ -1116,6 +1209,11 @@ static void generate(struct generator * g, struct node * p) {
1116
1209
  case c_do: generate_do(g, p); break;
1117
1210
  case c_goto: generate_GO(g, p, 1); break;
1118
1211
  case c_gopast: generate_GO(g, p, 0); break;
1212
+ case c_goto_grouping: generate_GO_grouping(g, p, 1, 0); break;
1213
+ case c_gopast_grouping:
1214
+ generate_GO_grouping(g, p, 0, 0); break;
1215
+ case c_goto_non: generate_GO_grouping(g, p, 1, 1); break;
1216
+ case c_gopast_non: generate_GO_grouping(g, p, 0, 1); break;
1119
1217
  case c_repeat: generate_repeat(g, p); break;
1120
1218
  case c_loop: generate_loop(g, p); break;
1121
1219
  case c_atleast: generate_atleast(g, p); break;
@@ -1150,12 +1248,14 @@ static void generate(struct generator * g, struct node * p) {
1150
1248
  generate_AE(g, p->AE);
1151
1249
  w(g, ");~N");
1152
1250
  break;
1153
- case c_eq: generate_integer_test(g, p, "=="); break;
1154
- case c_ne: generate_integer_test(g, p, "!="); break;
1155
- case c_gr: generate_integer_test(g, p, ">"); break;
1156
- case c_ge: generate_integer_test(g, p, ">="); break;
1157
- case c_ls: generate_integer_test(g, p, "<"); break;
1158
- case c_le: generate_integer_test(g, p, "<="); break;
1251
+ case c_eq:
1252
+ case c_ne:
1253
+ case c_gt:
1254
+ case c_ge:
1255
+ case c_lt:
1256
+ case c_le:
1257
+ generate_integer_test(g, p);
1258
+ break;
1159
1259
  case c_call: generate_call(g, p); break;
1160
1260
  case c_grouping: generate_grouping(g, p, false); break;
1161
1261
  case c_non: generate_grouping(g, p, true); break;
@@ -1167,6 +1267,7 @@ static void generate(struct generator * g, struct node * p) {
1167
1267
  case c_false: generate_false(g, p); break;
1168
1268
  case c_true: break;
1169
1269
  case c_debug: generate_debug(g, p); break;
1270
+ case c_functionend: generate_functionend(g, p); break;
1170
1271
  default: fprintf(stderr, "%d encountered\n", p->type);
1171
1272
  exit(1);
1172
1273
  }
@@ -1177,10 +1278,22 @@ static void generate(struct generator * g, struct node * p) {
1177
1278
  }
1178
1279
 
1179
1280
  static void generate_class_begin(struct generator * g) {
1180
-
1181
- w(g, "/**@constructor*/~N");
1182
- w(g, "~n = function() {~+~N"
1183
- "~Mvar base = new ~P();~N");
1281
+ if (g->options->js_esm) {
1282
+ w(g, "// deno-lint-ignore-file~N"
1283
+ "import ~P from './base-stemmer.mjs'~N"
1284
+ "~N"
1285
+ "/** @typedef {{ stemWord(word: string): string }} Stemmer */~N"
1286
+ "~N"
1287
+ "/** @type {{ new(): Stemmer }} */~N"
1288
+ "~C ~n = function() {~+~N"
1289
+ "~M~D base = new ~P();~N");
1290
+ } else {
1291
+ w(g, "/**@constructor*/~N"
1292
+ "~D ~n = function() {~+~N"
1293
+ "~M~C ~P = require('./base-stemmer.js');~N"
1294
+ "~M~D base = new ~P();~N");
1295
+ }
1296
+ write_newline(g);
1184
1297
  }
1185
1298
 
1186
1299
  static void generate_class_end(struct generator * g) {
@@ -1192,39 +1305,41 @@ static void generate_class_end(struct generator * g) {
1192
1305
  w(g, "~Mreturn base.getCurrent();~N");
1193
1306
  w(g, "~-~M};~N");
1194
1307
  w(g, "~-};~N");
1195
- /* w(g, "window['~n'] = ~n;~N"); */
1308
+ if (g->options->js_esm) {
1309
+ w(g, "~N"
1310
+ "export default ~n~N");
1311
+ } else {
1312
+ w(g, "~N"
1313
+ "if (typeof module === 'object' && module.exports) module.exports = ~n;~N");
1314
+ }
1196
1315
  }
1197
1316
 
1198
1317
  static void generate_among_table(struct generator * g, struct among * x) {
1318
+ write_comment(g, x->node);
1199
1319
 
1200
1320
  struct amongvec * v = x->b;
1201
1321
 
1202
1322
  g->I[0] = x->number;
1203
-
1204
- w(g, "~M/** @const */ var a_~I0 = [~N~+");
1205
- {
1206
- int i;
1207
- for (i = 0; i < x->literalstring_count; i++) {
1208
- g->I[0] = v->i;
1209
- g->I[1] = v->result;
1210
- g->L[0] = v->b;
1211
- g->S[0] = i < x->literalstring_count - 1 ? "," : "";
1212
-
1213
- w(g, "~M[~L0, ~I0, ~I1");
1214
- if (v->function != 0) {
1215
- w(g, ", ");
1216
- write_varname(g, v->function);
1217
- }
1218
- w(g, "]~S0~N");
1219
- v++;
1323
+ w(g, "~M~C a_~I0 = [~N~+");
1324
+
1325
+ for (int i = 0; i < x->literalstring_count; i++) {
1326
+ g->I[0] = v[i].i;
1327
+ g->I[1] = v[i].result;
1328
+ g->L[0] = v[i].b;
1329
+ g->S[0] = i < x->literalstring_count - 1 ? "," : "";
1330
+
1331
+ w(g, "~M[~L0, ~I0, ~I1");
1332
+ if (v[i].function != NULL) {
1333
+ w(g, ", ");
1334
+ write_varname(g, v[i].function);
1220
1335
  }
1336
+ w(g, "]~S0~N");
1221
1337
  }
1222
1338
  w(g, "~-~M];~N~N");
1223
1339
  }
1224
1340
 
1225
1341
  static void generate_amongs(struct generator * g) {
1226
- struct among * x;
1227
- for (x = g->analyser->amongs; x; x = x->next) {
1342
+ for (struct among * x = g->analyser->amongs; x; x = x->next) {
1228
1343
  generate_among_table(g, x);
1229
1344
  }
1230
1345
  }
@@ -1232,69 +1347,64 @@ static void generate_amongs(struct generator * g) {
1232
1347
  static void set_bit(symbol * b, int i) { b[i/8] |= 1 << i%8; }
1233
1348
 
1234
1349
  static void generate_grouping_table(struct generator * g, struct grouping * q) {
1235
-
1236
1350
  int range = q->largest_ch - q->smallest_ch + 1;
1237
1351
  int size = (range + 7)/ 8; /* assume 8 bits per symbol */
1238
1352
  symbol * b = q->b;
1239
1353
  symbol * map = create_b(size);
1240
- int i;
1241
- for (i = 0; i < size; i++) map[i] = 0;
1242
1354
 
1243
- /* Using unicode would require revision here */
1355
+ for (int i = 0; i < size; i++) map[i] = 0;
1244
1356
 
1245
- for (i = 0; i < SIZE(b); i++) set_bit(map, b[i] - q->smallest_ch);
1357
+ for (int i = 0; i < SIZE(b); i++) set_bit(map, b[i] - q->smallest_ch);
1246
1358
 
1247
1359
  g->V[0] = q->name;
1248
-
1249
- w(g, "~M/** @const */ var /** Array<int> */ ~W0 = [");
1250
- for (i = 0; i < size; i++) {
1360
+ w(g, "~M~C /** Array<int> */ ~W0 = [");
1361
+ for (int i = 0; i < size; i++) {
1251
1362
  write_int(g, map[i]);
1252
1363
  if (i < size - 1) w(g, ", ");
1253
1364
  }
1254
1365
  w(g, "];~N~N");
1366
+
1255
1367
  lose_b(map);
1256
1368
  }
1257
1369
 
1258
1370
  static void generate_groupings(struct generator * g) {
1259
- struct grouping * q;
1260
- for (q = g->analyser->groupings; q; q = q->next) {
1371
+ for (struct grouping * q = g->analyser->groupings; q; q = q->next) {
1261
1372
  if (q->name->used)
1262
1373
  generate_grouping_table(g, q);
1263
1374
  }
1264
1375
  }
1265
1376
 
1266
1377
  static void generate_members(struct generator * g) {
1378
+ int wrote_members = false;
1267
1379
 
1268
- struct name * q;
1269
- for (q = g->analyser->names; q; q = q->next) {
1380
+ for (struct name * q = g->analyser->names; q; q = q->next) {
1270
1381
  g->V[0] = q;
1271
1382
  switch (q->type) {
1272
1383
  case t_string:
1273
- w(g, "~Mvar /** string */ ~W0 = '';~N");
1384
+ w(g, "~M~D /** string */ ~W0 = '';~N");
1385
+ wrote_members = true;
1274
1386
  break;
1275
1387
  case t_integer:
1276
- w(g, "~Mvar /** number */ ~W0 = 0;~N");
1388
+ w(g, "~M~D /** number */ ~W0 = 0;~N");
1389
+ wrote_members = true;
1277
1390
  break;
1278
1391
  case t_boolean:
1279
- w(g, "~Mvar /** boolean */ ~W0 = false;~N");
1392
+ w(g, "~M~D /** boolean */ ~W0 = false;~N");
1393
+ wrote_members = true;
1280
1394
  break;
1281
1395
  }
1282
1396
  }
1283
- w(g, "~N");
1397
+ if (wrote_members) w(g, "~N");
1284
1398
  }
1285
1399
 
1286
1400
  static void generate_methods(struct generator * g) {
1287
-
1288
- struct node * p = g->analyser->program;
1289
- while (p != 0) {
1401
+ for (struct node * p = g->analyser->program; p; p = p->right) {
1290
1402
  generate(g, p);
1291
1403
  g->unreachable = false;
1292
- p = p->right;
1293
1404
  }
1294
1405
  }
1295
1406
 
1296
1407
  extern void generate_program_js(struct generator * g) {
1297
-
1298
1408
  g->outbuf = str_new();
1299
1409
  g->failure_str = str_new();
1300
1410