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,3 +1,4 @@
1
+ #include <assert.h>
1
2
  #include <stdlib.h> /* for exit */
2
3
  #include <string.h> /* for strlen */
3
4
  #include <stdio.h> /* for fprintf etc */
@@ -15,7 +16,6 @@ static int new_label(struct generator * g) {
15
16
  }
16
17
 
17
18
  static struct str * vars_newname(struct generator * g) {
18
-
19
19
  struct str * output;
20
20
  g->var_number++;
21
21
  output = str_new();
@@ -24,16 +24,17 @@ static struct str * vars_newname(struct generator * g) {
24
24
  return output;
25
25
  }
26
26
 
27
-
28
27
  /* Write routines for items from the syntax tree */
29
28
 
30
29
  static void write_varname(struct generator * g, struct name * p) {
31
-
32
30
  switch (p->type) {
33
- case t_external:
34
- write_char(g, toupper(p->b[0]));
35
- str_append_b_tail(g->outbuf, p->b, 1);
31
+ case t_external: {
32
+ char save_initial = p->s[0];
33
+ p->s[0] = toupper(save_initial);
34
+ str_append_s(g->outbuf, p->s);
35
+ p->s[0] = save_initial;
36
36
  return;
37
+ }
37
38
  default: {
38
39
  int ch = "SbirxG"[p->type];
39
40
  write_char(g, ch);
@@ -41,7 +42,7 @@ static void write_varname(struct generator * g, struct name * p) {
41
42
  break;
42
43
  }
43
44
  }
44
- write_b(g, p->b);
45
+ write_s(g, p->s);
45
46
  }
46
47
 
47
48
  static void write_varref(struct generator * g, struct name * p) {
@@ -49,41 +50,28 @@ static void write_varref(struct generator * g, struct name * p) {
49
50
  write_varname(g, p);
50
51
  }
51
52
 
52
- static void write_hexdigit(struct generator * g, int n) {
53
-
54
- write_char(g, n < 10 ? n + '0' : n - 10 + 'A');
55
- }
56
-
57
- static void write_hex(struct generator * g, int ch) {
58
-
59
- write_string(g, "\\u");
60
- {
61
- int i;
62
- for (i = 12; i >= 0; i -= 4) write_hexdigit(g, ch >> i & 0xf);
63
- }
64
- }
65
-
66
53
  static void write_literal_string(struct generator * g, symbol * p) {
67
-
68
54
  int i = 0;
69
55
  write_string(g, "\"");
70
56
  while (i < SIZE(p)) {
71
57
  int ch;
72
58
  i += get_utf8(p + i, &ch);
73
- if (32 <= ch && ch < 127) {
74
- if (ch == '\"' || ch == '\\') write_string(g, "\\");
75
- write_char(g, ch);
59
+ if (32 <= ch && ch < 0x590 && ch != 127) {
60
+ if (ch == '"' || ch == '\\') write_char(g, '\\');
61
+ write_wchar_as_utf8(g, ch);
76
62
  } else {
77
- write_hex(g, ch);
63
+ // Use escapes for anything over 0x590 as a crude way to avoid
64
+ // LTR characters affecting the rendering of source character
65
+ // order in confusing ways.
66
+ write_string(g, "\\u");
67
+ write_hex4(g, ch);
78
68
  }
79
69
  }
80
70
  write_string(g, "\"");
81
71
  }
82
72
 
83
73
  static void write_margin(struct generator * g) {
84
-
85
- int i;
86
- for (i = 0; i < g->margin; i++) write_string(g, " ");
74
+ for (int i = 0; i < g->margin; i++) write_string(g, " ");
87
75
  }
88
76
 
89
77
  static void write_comment(struct generator * g, struct node * p) {
@@ -96,52 +84,40 @@ static void write_comment(struct generator * g, struct node * p) {
96
84
  }
97
85
 
98
86
  static void write_block_start(struct generator * g) {
99
-
100
87
  w(g, "~+{~N");
101
88
  }
102
89
 
103
- static void write_block_end(struct generator * g) /* block end */ {
104
-
90
+ static void write_block_end(struct generator * g) {
105
91
  w(g, "~-~M}~N");
106
92
  }
107
93
 
108
94
  static void write_savecursor(struct generator * g, struct node * p,
109
95
  struct str * savevar) {
110
-
111
96
  g->B[0] = str_data(savevar);
112
97
  g->S[1] = "";
113
98
  if (p->mode != m_forward) g->S[1] = "env.Limit - ";
114
99
  writef(g, "~Mvar ~B0 = ~S1env.Cursor~N", p);
115
100
  }
116
101
 
117
- static void restore_string(struct node * p, struct str * out, struct str * savevar) {
118
-
119
- str_clear(out);
102
+ static void append_restore_string(struct node * p, struct str * out, struct str * savevar) {
120
103
  str_append_string(out, "env.Cursor = ");
121
104
  if (p->mode != m_forward) str_append_string(out, "env.Limit - ");
122
105
  str_append(out, savevar);
123
106
  }
124
107
 
125
- static void write_restorecursor(struct generator * g, struct node * p,
126
- struct str * savevar) {
127
-
128
- struct str * temp = str_new();
108
+ static void write_restorecursor(struct generator * g, struct node * p, struct str * savevar) {
129
109
  write_margin(g);
130
- restore_string(p, temp, savevar);
131
- write_str(g, temp);
110
+ append_restore_string(p, g->outbuf, savevar);
132
111
  write_newline(g);
133
- str_delete(temp);
134
112
  }
135
113
 
136
114
  static void write_inc_cursor(struct generator * g, struct node * p) {
137
-
138
115
  write_margin(g);
139
116
  write_string(g, p->mode == m_forward ? "env.NextChar();" : "env.PrevChar();");
140
117
  write_newline(g);
141
118
  }
142
119
 
143
120
  static void wsetlab_begin(struct generator * g, int n) {
144
-
145
121
  g->I[0] = n;
146
122
  w(g, "~Mlab~I0: for {~N~+");
147
123
  }
@@ -158,7 +134,6 @@ static void wgotol(struct generator * g, int n) {
158
134
  }
159
135
 
160
136
  static void write_failure(struct generator * g) {
161
-
162
137
  if (str_len(g->failure_str) != 0) {
163
138
  write_margin(g);
164
139
  write_str(g, g->failure_str);
@@ -176,8 +151,7 @@ static void write_failure(struct generator * g) {
176
151
  }
177
152
  }
178
153
 
179
- static void write_failure_if(struct generator * g, char * s, struct node * p) {
180
-
154
+ static void write_failure_if(struct generator * g, const char * s, struct node * p) {
181
155
  writef(g, "~Mif ", p);
182
156
  writef(g, s, p);
183
157
  writef(g, " ", p);
@@ -189,7 +163,6 @@ static void write_failure_if(struct generator * g, char * s, struct node * p) {
189
163
 
190
164
  /* if at limit fail */
191
165
  static void write_check_limit(struct generator * g, struct node * p) {
192
-
193
166
  if (p->mode == m_forward) {
194
167
  write_failure_if(g, "env.Cursor >= env.Limit", p);
195
168
  } else {
@@ -199,18 +172,18 @@ static void write_check_limit(struct generator * g, struct node * p) {
199
172
 
200
173
  /* Formatted write. */
201
174
  static void writef(struct generator * g, const char * input, struct node * p) {
175
+ (void)p;
202
176
  int i = 0;
203
- int l = strlen(input);
204
177
 
205
- while (i < l) {
178
+ while (input[i]) {
206
179
  int ch = input[i++];
207
180
  if (ch != '~') {
208
181
  write_char(g, ch);
209
182
  continue;
210
183
  }
211
- switch (input[i++]) {
212
- default: write_char(g, input[i - 1]); continue;
213
- case 'C': write_comment(g, p); continue;
184
+ ch = input[i++];
185
+ switch (ch) {
186
+ case '~': write_char(g, '~'); continue;
214
187
  case 'f': write_block_start(g);
215
188
  write_failure(g);
216
189
  g->unreachable = false;
@@ -220,21 +193,65 @@ static void writef(struct generator * g, const char * input, struct node * p) {
220
193
  case 'N': write_newline(g); continue;
221
194
  case '{': write_block_start(g); continue;
222
195
  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;
196
+ case 'S': {
197
+ int j = input[i++] - '0';
198
+ if (j < 0 || j > (int)(sizeof(g->S) / sizeof(g->S[0]))) {
199
+ printf("Invalid escape sequence ~%c%c in writef(g, \"%s\", p)\n",
200
+ ch, input[i - 1], input);
201
+ exit(1);
202
+ }
203
+ write_string(g, g->S[j]);
204
+ continue;
205
+ }
206
+ case 'B': {
207
+ int j = input[i++] - '0';
208
+ if (j < 0 || j > (int)(sizeof(g->B) / sizeof(g->B[0])))
209
+ goto invalid_escape2;
210
+ write_s(g, g->B[j]);
211
+ continue;
212
+ }
213
+ case 'I': {
214
+ int j = input[i++] - '0';
215
+ if (j < 0 || j > (int)(sizeof(g->I) / sizeof(g->I[0])))
216
+ goto invalid_escape2;
217
+ write_int(g, g->I[j]);
218
+ continue;
219
+ }
220
+ case 'V':
221
+ case 'W': {
222
+ int j = input[i++] - '0';
223
+ if (j < 0 || j > (int)(sizeof(g->V) / sizeof(g->V[0])))
224
+ goto invalid_escape2;
225
+ if (ch == 'V')
226
+ write_varref(g, g->V[j]);
227
+ else
228
+ write_varname(g, g->V[j]);
229
+ continue;
230
+ }
231
+ case 'L': {
232
+ int j = input[i++] - '0';
233
+ if (j < 0 || j > (int)(sizeof(g->L) / sizeof(g->L[0])))
234
+ goto invalid_escape2;
235
+ write_literal_string(g, g->L[j]);
236
+ continue;
237
+ }
229
238
  case '+': g->margin++; continue;
230
239
  case '-': g->margin--; continue;
231
240
  case 'n': write_string(g, g->options->name); continue;
241
+ default:
242
+ printf("Invalid escape sequence ~%c in writef(g, \"%s\", p)\n",
243
+ ch, input);
244
+ exit(1);
245
+ invalid_escape2:
246
+ printf("Invalid escape sequence ~%c%c in writef(g, \"%s\", p)\n",
247
+ ch, input[i - 1], input);
248
+ exit(1);
232
249
  }
233
250
  }
234
251
  }
235
252
 
236
253
  static void w(struct generator * g, const char * s) {
237
- writef(g, s, 0);
254
+ writef(g, s, NULL);
238
255
  }
239
256
 
240
257
  static void generate_AE(struct generator * g, struct node * p) {
@@ -283,7 +300,6 @@ static void generate_AE(struct generator * g, struct node * p) {
283
300
  }
284
301
 
285
302
  static void generate_bra(struct generator * g, struct node * p) {
286
-
287
303
  write_comment(g, p);
288
304
  p = p->left;
289
305
  while (p) {
@@ -293,28 +309,33 @@ static void generate_bra(struct generator * g, struct node * p) {
293
309
  }
294
310
 
295
311
  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);
312
+ struct str * savevar = NULL;
313
+ if (K_needed(g, p->left)) {
314
+ savevar = vars_newname(g);
315
+ }
299
316
 
300
317
  write_comment(g, p);
301
318
 
302
- if (keep_c) write_savecursor(g, p, savevar);
319
+ if (savevar) write_savecursor(g, p, savevar);
303
320
 
304
321
  p = p->left;
305
322
  while (p) {
306
323
  generate(g, p);
307
324
  if (g->unreachable) break;
308
- if (keep_c && p->right != 0) write_restorecursor(g, p, savevar);
325
+ if (savevar && p->right != NULL) write_restorecursor(g, p, savevar);
309
326
  p = p->right;
310
327
  }
311
- str_delete(savevar);
328
+
329
+ if (savevar) {
330
+ str_delete(savevar);
331
+ }
312
332
  }
313
333
 
314
334
  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);
335
+ struct str * savevar = NULL;
336
+ if (K_needed(g, p->left)) {
337
+ savevar = vars_newname(g);
338
+ }
318
339
 
319
340
  int a0 = g->failure_label;
320
341
  struct str * a1 = str_copy(g->failure_str);
@@ -325,18 +346,18 @@ static void generate_or(struct generator * g, struct node * p) {
325
346
  write_comment(g, p);
326
347
  wsetlab_begin(g, out_lab);
327
348
 
328
- if (keep_c) write_savecursor(g, p, savevar);
349
+ if (savevar) write_savecursor(g, p, savevar);
329
350
 
330
351
  p = p->left;
331
352
  str_clear(g->failure_str);
332
353
 
333
- if (p == 0) {
334
- /* p should never be 0 after an or: there should be at least two
354
+ if (p == NULL) {
355
+ /* p should never be NULL after an or: there should be at least two
335
356
  * sub nodes. */
336
357
  fprintf(stderr, "Error: \"or\" node without children nodes.");
337
358
  exit(1);
338
359
  }
339
- while (p->right != 0) {
360
+ while (p->right != NULL) {
340
361
  int label = new_label(g);
341
362
  g->failure_label = label;
342
363
  wsetlab_begin(g, label);
@@ -347,7 +368,7 @@ static void generate_or(struct generator * g, struct node * p) {
347
368
  }
348
369
  w(g, "~-~M}~N");
349
370
  g->unreachable = false;
350
- if (keep_c) write_restorecursor(g, p, savevar);
371
+ if (savevar) write_restorecursor(g, p, savevar);
351
372
  p = p->right;
352
373
  }
353
374
 
@@ -360,11 +381,13 @@ static void generate_or(struct generator * g, struct node * p) {
360
381
  if (!end_unreachable) {
361
382
  g->unreachable = false;
362
383
  }
363
- str_delete(savevar);
384
+
385
+ if (savevar) {
386
+ str_delete(savevar);
387
+ }
364
388
  }
365
389
 
366
390
  static void generate_backwards(struct generator * g, struct node * p) {
367
-
368
391
  write_comment(g, p);
369
392
  writef(g,"~Menv.LimitBackward = env.Cursor~N"
370
393
  "~Menv.Cursor = env.Limit~N", p);
@@ -374,9 +397,10 @@ static void generate_backwards(struct generator * g, struct node * p) {
374
397
 
375
398
 
376
399
  static void generate_not(struct generator * g, struct node * p) {
377
-
378
- struct str * savevar = vars_newname(g);
379
- int keep_c = K_needed(g, p->left);
400
+ struct str * savevar = NULL;
401
+ if (K_needed(g, p->left)) {
402
+ savevar = vars_newname(g);
403
+ }
380
404
 
381
405
  int a0 = g->failure_label;
382
406
  struct str * a1 = str_copy(g->failure_str);
@@ -384,7 +408,7 @@ static void generate_not(struct generator * g, struct node * p) {
384
408
  g->failure_label = label;
385
409
 
386
410
  write_comment(g, p);
387
- if (keep_c) {
411
+ if (savevar) {
388
412
  write_savecursor(g, p, savevar);
389
413
  }
390
414
 
@@ -403,48 +427,51 @@ static void generate_not(struct generator * g, struct node * p) {
403
427
 
404
428
  g->unreachable = false;
405
429
 
406
- if (keep_c) write_restorecursor(g, p, savevar);
407
- str_delete(savevar);
430
+ if (savevar) {
431
+ write_restorecursor(g, p, savevar);
432
+ str_delete(savevar);
433
+ }
408
434
  }
409
435
 
410
436
 
411
437
  static void generate_try(struct generator * g, struct node * p) {
438
+ struct str * savevar = NULL;
439
+ if (K_needed(g, p->left)) {
440
+ savevar = vars_newname(g);
441
+ }
412
442
 
413
- struct str * savevar = vars_newname(g);
414
- int keep_c = K_needed(g, p->left);
415
443
  int label = new_label(g);
416
444
  g->failure_label = label;
417
445
  str_clear(g->failure_str);
418
446
 
419
447
  write_comment(g, p);
420
- if (keep_c) {
448
+ if (savevar) {
421
449
  write_savecursor(g, p, savevar);
422
- restore_string(p, g->failure_str, savevar);
450
+ append_restore_string(p, g->failure_str, savevar);
423
451
  }
424
452
  wsetlab_begin(g, label);
425
453
  generate(g, p->left);
426
454
  wsetlab_end(g, label);
427
455
  g->unreachable = false;
428
456
 
429
- str_delete(savevar);
457
+ if (savevar) {
458
+ str_delete(savevar);
459
+ }
430
460
  }
431
461
 
432
462
  static void generate_set(struct generator * g, struct node * p) {
433
-
434
463
  write_comment(g, p);
435
464
  g->V[0] = p->name;
436
465
  writef(g, "~M~V0 = true~N", p);
437
466
  }
438
467
 
439
468
  static void generate_unset(struct generator * g, struct node * p) {
440
-
441
469
  write_comment(g, p);
442
470
  g->V[0] = p->name;
443
471
  writef(g, "~M~V0 = false~N", p);
444
472
  }
445
473
 
446
474
  static void generate_fail(struct generator * g, struct node * p) {
447
-
448
475
  write_comment(g, p);
449
476
  generate(g, p->left);
450
477
  if (!g->unreachable) write_failure(g);
@@ -453,32 +480,35 @@ static void generate_fail(struct generator * g, struct node * p) {
453
480
  /* generate_test() also implements 'reverse' */
454
481
 
455
482
  static void generate_test(struct generator * g, struct node * p) {
456
-
457
- struct str * savevar = vars_newname(g);
458
- int keep_c = K_needed(g, p->left);
483
+ struct str * savevar = NULL;
484
+ if (K_needed(g, p->left)) {
485
+ savevar = vars_newname(g);
486
+ }
459
487
 
460
488
  write_comment(g, p);
461
489
 
462
- if (keep_c) {
490
+ if (savevar) {
463
491
  write_savecursor(g, p, savevar);
464
492
  }
465
493
 
466
494
  generate(g, p->left);
467
495
 
468
- if (!g->unreachable) {
469
- if (keep_c) {
496
+ if (savevar) {
497
+ if (!g->unreachable) {
470
498
  write_restorecursor(g, p, savevar);
471
499
  }
500
+ str_delete(savevar);
472
501
  }
473
- str_delete(savevar);
474
502
  }
475
503
 
476
504
  static void generate_do(struct generator * g, struct node * p) {
505
+ struct str * savevar = NULL;
506
+ if (K_needed(g, p->left)) {
507
+ savevar = vars_newname(g);
508
+ }
477
509
 
478
- struct str * savevar = vars_newname(g);
479
- int keep_c = K_needed(g, p->left);
480
510
  write_comment(g, p);
481
- if (keep_c) write_savecursor(g, p, savevar);
511
+ if (savevar) write_savecursor(g, p, savevar);
482
512
 
483
513
  if (p->left->type == c_call) {
484
514
  /* Optimise do <call> */
@@ -496,24 +526,50 @@ static void generate_do(struct generator * g, struct node * p) {
496
526
  g->unreachable = false;
497
527
  }
498
528
 
499
- if (keep_c) write_restorecursor(g, p, savevar);
500
- str_delete(savevar);
529
+ if (savevar) {
530
+ write_restorecursor(g, p, savevar);
531
+ str_delete(savevar);
532
+ }
501
533
  }
502
534
 
503
- static void generate_GO(struct generator * g, struct node * p, int style) {
535
+ static void generate_next(struct generator * g, struct node * p) {
536
+ write_comment(g, p);
537
+ write_check_limit(g, p);
538
+ write_inc_cursor(g, p);
539
+ }
504
540
 
505
- int end_unreachable = false;
506
- struct str * savevar = vars_newname(g);
507
- int keep_c = style == 1 || repeat_restore(g, p->left);
541
+ static void generate_GO_grouping(struct generator * g, struct node * p, int is_goto, int complement) {
542
+ write_comment(g, p);
543
+
544
+ struct grouping * q = p->name->grouping;
545
+ g->S[0] = p->mode == m_forward ? "" : "B";
546
+ g->S[1] = complement ? "In" : "Out";
547
+ g->V[0] = p->name;
548
+ g->I[0] = q->smallest_ch;
549
+ g->I[1] = q->largest_ch;
550
+ write_failure_if(g, "!env.Go~S1Grouping~S0(~W0, ~I0, ~I1)", p);
551
+ if (!is_goto) {
552
+ write_string(g, p->mode == m_forward ? "env.NextChar();" : "env.PrevChar();");
553
+ }
554
+ }
555
+
556
+ static void generate_GO(struct generator * g, struct node * p, int style) {
557
+ write_comment(g, p);
508
558
 
509
559
  int a0 = g->failure_label;
510
560
  struct str * a1 = str_copy(g->failure_str);
511
561
 
562
+ int end_unreachable = false;
563
+
512
564
  int golab = new_label(g);
513
565
  g->I[0] = golab;
514
- write_comment(g, p);
515
566
  w(g, "~Mgolab~I0: for {~N~+");
516
- if (keep_c) write_savecursor(g, p, savevar);
567
+
568
+ struct str * savevar = NULL;
569
+ if (style == 1 || repeat_restore(g, p->left)) {
570
+ savevar = vars_newname(g);
571
+ write_savecursor(g, p, savevar);
572
+ }
517
573
 
518
574
  g->failure_label = new_label(g);
519
575
  str_clear(g->failure_str);
@@ -532,7 +588,10 @@ static void generate_GO(struct generator * g, struct node * p, int style) {
532
588
  }
533
589
  g->unreachable = false;
534
590
  w(g, "~-~M}~N");
535
- if (keep_c) write_restorecursor(g, p, savevar);
591
+ if (savevar) {
592
+ write_restorecursor(g, p, savevar);
593
+ str_delete(savevar);
594
+ }
536
595
 
537
596
  g->failure_label = a0;
538
597
  str_delete(g->failure_str);
@@ -541,35 +600,33 @@ static void generate_GO(struct generator * g, struct node * p, int style) {
541
600
  write_check_limit(g, p);
542
601
  write_inc_cursor(g, p);
543
602
  write_block_end(g);
544
-
545
- str_delete(savevar);
546
603
  g->unreachable = end_unreachable;
547
604
  }
548
605
 
549
606
  static void generate_loop(struct generator * g, struct node * p) {
550
-
551
607
  struct str * loopvar = vars_newname(g);
552
608
  write_comment(g, p);
553
609
  w(g, "~Mfor _ = range make([]struct{},");
554
610
  generate_AE(g, p->AE);
555
- writef(g, ") {~+~N", p);
611
+ writef(g, ") {~+", p);
556
612
 
557
613
  generate(g, p->left);
558
614
 
559
- w(g, "~-~M}~N");
615
+ w(g, "~}");
560
616
  str_delete(loopvar);
561
617
  g->unreachable = false;
562
618
  }
563
619
 
564
620
  static void generate_repeat_or_atleast(struct generator * g, struct node * p, struct str * loopvar) {
565
-
566
- struct str * savevar = vars_newname(g);
567
- int keep_c = repeat_restore(g, p->left);
568
621
  int replab = new_label(g);
569
622
  g->I[0] = replab;
570
623
  writef(g, "~Mreplab~I0: for{~N~+", p);
571
624
 
572
- if (keep_c) write_savecursor(g, p, savevar);
625
+ struct str * savevar = NULL;
626
+ if (repeat_restore(g, p->left)) {
627
+ savevar = vars_newname(g);
628
+ write_savecursor(g, p, savevar);
629
+ }
573
630
 
574
631
  g->failure_label = new_label(g);
575
632
  str_clear(g->failure_str);
@@ -578,7 +635,7 @@ static void generate_repeat_or_atleast(struct generator * g, struct node * p, st
578
635
  generate(g, p->left);
579
636
 
580
637
  if (!g->unreachable) {
581
- if (loopvar != 0) {
638
+ if (loopvar != NULL) {
582
639
  g->B[0] = str_data(loopvar);
583
640
  w(g, "~M~B0--~N");
584
641
  }
@@ -589,11 +646,13 @@ static void generate_repeat_or_atleast(struct generator * g, struct node * p, st
589
646
  w(g, "~-~M}~N");
590
647
  g->unreachable = false;
591
648
 
592
- if (keep_c) write_restorecursor(g, p, savevar);
649
+ if (savevar) {
650
+ write_restorecursor(g, p, savevar);
651
+ str_delete(savevar);
652
+ }
593
653
 
594
654
  g->I[0] = replab;
595
655
  w(g, "~Mbreak replab~I0~N~-~M}~N");
596
- str_delete(savevar);
597
656
  }
598
657
 
599
658
  static void generate_repeat(struct generator * g, struct node * p) {
@@ -602,8 +661,8 @@ static void generate_repeat(struct generator * g, struct node * p) {
602
661
  }
603
662
 
604
663
  static void generate_atleast(struct generator * g, struct node * p) {
605
-
606
664
  struct str * loopvar = vars_newname(g);
665
+
607
666
  write_comment(g, p);
608
667
  g->B[0] = str_data(loopvar);
609
668
  w(g, "~Mvar ~B0 = ");
@@ -625,19 +684,16 @@ static void generate_atleast(struct generator * g, struct node * p) {
625
684
  }
626
685
 
627
686
  static void generate_setmark(struct generator * g, struct node * p) {
628
-
629
687
  write_comment(g, p);
630
688
  g->V[0] = p->name;
631
689
  writef(g, "~M~V0 = env.Cursor~N", p);
632
690
  }
633
691
 
634
692
  static void generate_tomark(struct generator * g, struct node * p) {
635
-
636
693
  write_comment(g, p);
637
694
  g->S[0] = p->mode == m_forward ? ">" : "<";
638
695
 
639
- w(g, "~Mif env.Cursor ~S0 "); generate_AE(g, p->AE);
640
- writef(g, " ", p);
696
+ w(g, "~Mif env.Cursor ~S0 "); generate_AE(g, p->AE); writef(g, " ", p);
641
697
  write_block_start(g);
642
698
  write_failure(g);
643
699
  write_block_end(g);
@@ -646,10 +702,8 @@ static void generate_tomark(struct generator * g, struct node * p) {
646
702
  }
647
703
 
648
704
  static void generate_atmark(struct generator * g, struct node * p) {
649
-
650
705
  write_comment(g, p);
651
- w(g, "~Mif env.Cursor != "); generate_AE(g, p->AE);
652
- writef(g, " ", p);
706
+ w(g, "~Mif env.Cursor != "); generate_AE(g, p->AE); writef(g, " ", p);
653
707
  write_block_start(g);
654
708
  write_failure(g);
655
709
  write_block_end(g);
@@ -673,30 +727,19 @@ static void generate_hop(struct generator * g, struct node * p) {
673
727
  }
674
728
 
675
729
  static void generate_delete(struct generator * g, struct node * p) {
676
-
677
730
  write_comment(g, p);
678
731
  writef(g, "~Mif !env.SliceDel() {~N"
679
732
  "~+~Mreturn false~N~-"
680
733
  "~M}~N", p);
681
734
  }
682
735
 
683
-
684
- static void generate_next(struct generator * g, struct node * p) {
685
-
686
- write_comment(g, p);
687
- write_check_limit(g, p);
688
- write_inc_cursor(g, p);
689
- }
690
-
691
736
  static void generate_tolimit(struct generator * g, struct node * p) {
692
-
693
737
  write_comment(g, p);
694
738
  g->S[0] = p->mode == m_forward ? "env.Limit" : "env.LimitBackward";
695
739
  writef(g, "~Menv.Cursor = ~S0~N", p);
696
740
  }
697
741
 
698
742
  static void generate_atlimit(struct generator * g, struct node * p) {
699
-
700
743
  write_comment(g, p);
701
744
  g->S[0] = p->mode == m_forward ? "env.Limit" : "env.LimitBackward";
702
745
  g->S[1] = p->mode == m_forward ? "<" : ">";
@@ -704,28 +747,24 @@ static void generate_atlimit(struct generator * g, struct node * p) {
704
747
  }
705
748
 
706
749
  static void generate_leftslice(struct generator * g, struct node * p) {
707
-
708
750
  write_comment(g, p);
709
751
  g->S[0] = p->mode == m_forward ? "env.Bra" : "env.Ket";
710
752
  writef(g, "~M~S0 = env.Cursor~N", p);
711
753
  }
712
754
 
713
755
  static void generate_rightslice(struct generator * g, struct node * p) {
714
-
715
756
  write_comment(g, p);
716
757
  g->S[0] = p->mode == m_forward ? "env.Ket" : "env.Bra";
717
758
  writef(g, "~M~S0 = env.Cursor~N", p);
718
759
  }
719
760
 
720
761
  static void generate_assignto(struct generator * g, struct node * p) {
721
-
722
762
  write_comment(g, p);
723
763
  g->V[0] = p->name;
724
764
  writef(g, "~M~V0 = env.AssignTo()~N", p);
725
765
  }
726
766
 
727
767
  static void generate_sliceto(struct generator * g, struct node * p) {
728
-
729
768
  write_comment(g, p);
730
769
  g->V[0] = p->name;
731
770
  writef(g, "~M~V0 = env.SliceTo()~N"
@@ -734,9 +773,8 @@ static void generate_sliceto(struct generator * g, struct node * p) {
734
773
  }
735
774
 
736
775
  static void generate_address(struct generator * g, struct node * p) {
737
-
738
776
  symbol * b = p->literalstring;
739
- if (b != 0) {
777
+ if (b != NULL) {
740
778
  write_literal_string(g, b);
741
779
  } else {
742
780
  write_varref(g, p->name);
@@ -744,7 +782,6 @@ static void generate_address(struct generator * g, struct node * p) {
744
782
  }
745
783
 
746
784
  static void generate_insert(struct generator * g, struct node * p, int style) {
747
-
748
785
  int keep_c = style == c_attach;
749
786
 
750
787
  write_block_start(g);
@@ -760,7 +797,6 @@ static void generate_insert(struct generator * g, struct node * p, int style) {
760
797
  }
761
798
 
762
799
  static void generate_assignfrom(struct generator * g, struct node * p) {
763
-
764
800
  int keep_c = p->mode == m_forward; /* like 'attach' */
765
801
 
766
802
  write_block_start(g);
@@ -777,9 +813,7 @@ static void generate_assignfrom(struct generator * g, struct node * p) {
777
813
  write_block_end(g);
778
814
  }
779
815
 
780
-
781
816
  static void generate_slicefrom(struct generator * g, struct node * p) {
782
-
783
817
  write_comment(g, p);
784
818
  w(g, "~Mif !env.SliceFrom(");
785
819
  generate_address(g, p);
@@ -788,7 +822,6 @@ static void generate_slicefrom(struct generator * g, struct node * p) {
788
822
  }
789
823
 
790
824
  static void generate_setlimit(struct generator * g, struct node * p) {
791
- struct str * savevar = vars_newname(g);
792
825
  struct str * varname = vars_newname(g);
793
826
  write_comment(g, p);
794
827
  if (p->left && p->left->type == c_tomark) {
@@ -801,6 +834,7 @@ static void generate_setlimit(struct generator * g, struct node * p) {
801
834
  * restore c.
802
835
  */
803
836
  struct node * q = p->left;
837
+ write_comment(g, q);
804
838
  g->S[0] = q->mode == m_forward ? ">" : "<";
805
839
  w(g, "~Mif env.Cursor ~S0 "); generate_AE(g, q->AE); w(g, " ");
806
840
  write_block_start(g);
@@ -828,7 +862,9 @@ static void generate_setlimit(struct generator * g, struct node * p) {
828
862
  str_append_string(g->failure_str, ";");
829
863
  }
830
864
  } else {
865
+ struct str * savevar = vars_newname(g);
831
866
  write_savecursor(g, p, savevar);
867
+
832
868
  generate(g, p->left);
833
869
 
834
870
  if (!g->unreachable) {
@@ -852,6 +888,7 @@ static void generate_setlimit(struct generator * g, struct node * p) {
852
888
  str_append_string(g->failure_str, ";");
853
889
  }
854
890
  }
891
+ str_delete(savevar);
855
892
  }
856
893
 
857
894
  if (!g->unreachable) {
@@ -864,62 +901,89 @@ static void generate_setlimit(struct generator * g, struct node * p) {
864
901
  }
865
902
  }
866
903
  str_delete(varname);
867
- str_delete(savevar);
868
904
  }
869
905
 
870
906
  /* dollar sets snowball up to operate on a string variable as if it were the
871
907
  * current string */
872
908
  static void generate_dollar(struct generator * g, struct node * p) {
873
- struct str * savevar_env = vars_newname(g);
874
909
  write_comment(g, p);
910
+
911
+ struct str * savevar = vars_newname(g);
875
912
  g->V[0] = p->name;
876
- g->B[0] = str_data(savevar_env);
913
+ g->B[0] = str_data(savevar);
877
914
  writef(g, "~Mvar ~B0 = env.Clone()~N"
878
- "~Menv.SetCurrent(~V0)~N"
879
- "~Menv.Cursor = 0~N"
880
- "~Menv.Limit = len(env.Current())~N", p);
915
+ "~Menv.SetCurrent(~V0)~N", p);
881
916
  generate(g, p->left);
882
917
  if (!g->unreachable) {
883
918
  g->V[0] = p->name;
884
- g->B[0] = str_data(savevar_env);
919
+ g->B[0] = str_data(savevar);
885
920
  /* Update string variable. */
886
921
  w(g, "~M~V0 = env.Current()~N");
887
922
  /* Reset env */
888
923
  w(g, "~M*env = *~B0~N");
889
924
  }
890
- str_delete(savevar_env);
925
+ str_delete(savevar);
891
926
  }
892
927
 
893
- static void generate_integer_assign(struct generator * g, struct node * p, char * s) {
894
-
928
+ static void generate_integer_assign(struct generator * g, struct node * p, const char * s) {
929
+ write_comment(g, p);
895
930
  g->V[0] = p->name;
896
931
  g->S[0] = s;
897
- w(g, "~M~V0 ~S0 "); generate_AE(g, p->AE); w(g, "~N");
932
+ w(g, "~M~V0 ~S0 ");
933
+ generate_AE(g, p->AE);
934
+ w(g, "~N");
898
935
  }
899
936
 
900
- static void generate_integer_test(struct generator * g, struct node * p, char * s) {
901
-
902
- w(g, "~Mif !(");
937
+ static void generate_integer_test(struct generator * g, struct node * p) {
938
+ write_comment(g, p);
939
+ int relop = p->type;
940
+ int optimise_to_return = (g->failure_label == x_return && p->right && p->right->type == c_functionend);
941
+ if (optimise_to_return) {
942
+ w(g, "~Mreturn ");
943
+ p->right = NULL;
944
+ } else {
945
+ w(g, "~Mif ");
946
+ // We want the inverse of the snowball test here.
947
+ relop ^= 1;
948
+ }
903
949
  generate_AE(g, p->left);
904
- write_char(g, ' ');
905
- write_string(g, s);
906
- write_char(g, ' ');
950
+ // Relational operators are the same as C.
951
+ write_c_relop(g, relop);
907
952
  generate_AE(g, p->AE);
908
- w(g, ")");
909
- write_block_start(g);
910
- write_failure(g);
911
- write_block_end(g);
912
- g->unreachable = false;
953
+ if (optimise_to_return) {
954
+ w(g, "~N");
955
+ } else {
956
+ write_block_start(g);
957
+ write_failure(g);
958
+ write_block_end(g);
959
+ g->unreachable = false;
960
+ }
913
961
  }
914
962
 
915
963
  static void generate_call(struct generator * g, struct node * p) {
916
-
964
+ int signals = check_possible_signals_list(g, p->name->definition, c_define, 0);
917
965
  write_comment(g, p);
918
966
  g->V[0] = p->name;
919
- write_failure_if(g, "!~W0(env, context)", p);
967
+ if (g->failure_label == x_return &&
968
+ (signals == 0 || (p->right && p->right->type == c_functionend))) {
969
+ /* Always fails or tail call. */
970
+ writef(g, "~Mreturn ~W0(env, context)~N", p);
971
+ return;
972
+ }
973
+ if (signals == 1) {
974
+ /* Always succeeds. */
975
+ writef(g, "~M~W0(env, context)~N", p);
976
+ } else if (signals == 0) {
977
+ /* Always fails. */
978
+ writef(g, "~M~W0(env, context)~N", p);
979
+ write_failure(g);
980
+ } else {
981
+ write_failure_if(g, "!~W0(env, context)", p);
982
+ }
920
983
  }
921
984
 
922
985
  static void generate_grouping(struct generator * g, struct node * p, int complement) {
986
+ write_comment(g, p);
923
987
 
924
988
  struct grouping * q = p->name->grouping;
925
989
  g->S[0] = p->mode == m_forward ? "" : "B";
@@ -931,7 +995,6 @@ static void generate_grouping(struct generator * g, struct node * p, int complem
931
995
  }
932
996
 
933
997
  static void generate_namedstring(struct generator * g, struct node * p) {
934
-
935
998
  write_comment(g, p);
936
999
  g->S[0] = p->mode == m_forward ? "" : "B";
937
1000
  g->V[0] = p->name;
@@ -947,10 +1010,8 @@ static void generate_literalstring(struct generator * g, struct node * p) {
947
1010
  }
948
1011
 
949
1012
  static void generate_setup_context(struct generator * g) {
950
-
951
- struct name * q;
952
1013
  w(g, "~Mvar context = &Context {~+~N");
953
- for (q = g->analyser->names; q; q = q->next) {
1014
+ for (struct name * q = g->analyser->names; q; q = q->next) {
954
1015
  g->V[0] = q;
955
1016
  switch (q->type) {
956
1017
  case t_string:
@@ -970,20 +1031,25 @@ static void generate_setup_context(struct generator * g) {
970
1031
 
971
1032
  static void generate_define(struct generator * g, struct node * p) {
972
1033
  struct name * q = p->name;
1034
+ if (q->type == t_routine && !q->used) return;
973
1035
 
974
- struct str * saved_output = g->outbuf;
1036
+ write_newline(g);
1037
+ write_comment(g, p);
975
1038
 
976
1039
  g->V[0] = q;
977
1040
 
978
1041
  if (q->type == t_routine) {
979
- w(g, "~N~Mfunc ~W0(env *snowballRuntime.Env, ctx interface{}) bool {~+~N");
1042
+ w(g, "~Mfunc ~W0(env *snowballRuntime.Env, ctx interface{}) bool {~+~N");
980
1043
  w(g, "~Mcontext := ctx.(*Context)~N");
981
1044
  w(g, "~M_ = context~N");
982
1045
  } else {
983
- w(g, "~N~Mfunc ~W0(env *snowballRuntime.Env) bool {~+~N");
1046
+ w(g, "~Mfunc ~W0(env *snowballRuntime.Env) bool {~+~N");
984
1047
  generate_setup_context(g);
985
1048
  }
986
1049
  if (p->amongvar_needed) w(g, "~Mvar among_var int32~N");
1050
+
1051
+ /* Save output. */
1052
+ struct str * saved_output = g->outbuf;
987
1053
  g->outbuf = str_new();
988
1054
 
989
1055
  g->next_label = 0;
@@ -992,8 +1058,16 @@ static void generate_define(struct generator * g, struct node * p) {
992
1058
  str_clear(g->failure_str);
993
1059
  g->failure_label = x_return;
994
1060
  g->unreachable = false;
1061
+ int signals = check_possible_signals_list(g, p->left, c_define, 0);
1062
+
1063
+ /* Generate function body. */
995
1064
  generate(g, p->left);
996
- if (!g->unreachable) w(g, "~Mreturn true~N");
1065
+ if (p->left->right) {
1066
+ assert(p->left->right->type == c_functionend);
1067
+ if (signals) {
1068
+ generate(g, p->left->right);
1069
+ }
1070
+ }
997
1071
  w(g, "~-~M}~N");
998
1072
 
999
1073
  str_append(saved_output, g->outbuf);
@@ -1001,58 +1075,63 @@ static void generate_define(struct generator * g, struct node * p) {
1001
1075
  g->outbuf = saved_output;
1002
1076
  }
1003
1077
 
1078
+ static void generate_functionend(struct generator * g, struct node * p) {
1079
+ (void)p;
1080
+ w(g, "~Mreturn true~N");
1081
+ }
1082
+
1004
1083
  static void generate_substring(struct generator * g, struct node * p) {
1084
+ write_comment(g, p);
1005
1085
 
1006
1086
  struct among * x = p->among;
1007
1087
 
1008
- write_comment(g, p);
1009
-
1010
1088
  g->S[0] = p->mode == m_forward ? "" : "B";
1011
1089
  g->I[0] = x->number;
1012
1090
 
1013
- if (!x->amongvar_needed) {
1014
- write_failure_if(g, "env.FindAmong~S0(~A_~I0, context) == 0", p);
1091
+ if (x->amongvar_needed) {
1092
+ writef(g, "~Mamong_var = env.FindAmong~S0(A_~I0, context)~N", p);
1093
+ if (!x->always_matches) {
1094
+ write_failure_if(g, "among_var == 0", p);
1095
+ }
1096
+ } else if (x->always_matches) {
1097
+ writef(g, "~Menv.FindAmong~S0(A_~I0, context)~N", p);
1015
1098
  } else {
1016
- writef(g, "~Mamong_var = env.FindAmong~S0(~A_~I0, context)~N", p);
1017
- write_failure_if(g, "among_var == 0", p);
1099
+ write_failure_if(g, "env.FindAmong~S0(A_~I0, context) == 0", p);
1018
1100
  }
1019
1101
  }
1020
1102
 
1021
1103
  static void generate_among(struct generator * g, struct node * p) {
1022
-
1023
1104
  struct among * x = p->among;
1024
1105
 
1025
- if (x->substring == 0) generate_substring(g, p);
1026
-
1027
- if (x->starter != 0) generate(g, x->starter);
1106
+ if (x->substring == NULL) {
1107
+ generate_substring(g, p);
1108
+ } else {
1109
+ write_comment(g, p);
1110
+ }
1028
1111
 
1029
1112
  if (x->command_count == 1 && x->nocommand_count == 0) {
1030
1113
  /* Only one outcome ("no match" already handled). */
1031
1114
  generate(g, x->commands[0]);
1032
1115
  } else if (x->command_count > 0) {
1033
- int i;
1034
- w(g, "~M");
1035
- for (i = 1; i <= x->command_count; i++) {
1116
+ w(g, "~Mswitch among_var {~N");
1117
+ for (int i = 1; i <= x->command_count; i++) {
1036
1118
  g->I[0] = i;
1037
- if (i > 1) w(g, " else ");
1038
- w(g, "if among_var == ~I0 {~N~+");
1119
+ w(g, "~Mcase ~I0:~N~+");
1039
1120
  generate(g, x->commands[i - 1]);
1040
- w(g, "~-~M}");
1121
+ w(g, "~-");
1041
1122
  g->unreachable = false;
1042
1123
  }
1043
- w(g, "~N");
1124
+ w(g, "~M}~N");
1044
1125
  }
1045
1126
  }
1046
1127
 
1047
1128
  static void generate_booltest(struct generator * g, struct node * p) {
1048
-
1049
1129
  write_comment(g, p);
1050
1130
  g->V[0] = p->name;
1051
1131
  write_failure_if(g, "!~V0", p);
1052
1132
  }
1053
1133
 
1054
1134
  static void generate_false(struct generator * g, struct node * p) {
1055
-
1056
1135
  write_comment(g, p);
1057
1136
  write_failure(g);
1058
1137
  }
@@ -1065,14 +1144,10 @@ static void generate_debug(struct generator * g, struct node * p) {
1065
1144
  }
1066
1145
 
1067
1146
  static void generate(struct generator * g, struct node * p) {
1068
-
1069
- int a0;
1070
- struct str * a1;
1071
-
1072
1147
  if (g->unreachable) return;
1073
1148
 
1074
- a0 = g->failure_label;
1075
- a1 = str_copy(g->failure_str);
1149
+ int a0 = g->failure_label;
1150
+ struct str * a1 = str_copy(g->failure_str);
1076
1151
 
1077
1152
  switch (p->type) {
1078
1153
  case c_define: generate_define(g, p); break;
@@ -1090,6 +1165,11 @@ static void generate(struct generator * g, struct node * p) {
1090
1165
  case c_do: generate_do(g, p); break;
1091
1166
  case c_goto: generate_GO(g, p, 1); break;
1092
1167
  case c_gopast: generate_GO(g, p, 0); break;
1168
+ case c_goto_grouping: generate_GO_grouping(g, p, 1, 0); break;
1169
+ case c_gopast_grouping:
1170
+ generate_GO_grouping(g, p, 0, 0); break;
1171
+ case c_goto_non: generate_GO_grouping(g, p, 1, 1); break;
1172
+ case c_gopast_non: generate_GO_grouping(g, p, 0, 1); break;
1093
1173
  case c_repeat: generate_repeat(g, p); break;
1094
1174
  case c_loop: generate_loop(g, p); break;
1095
1175
  case c_atleast: generate_atleast(g, p); break;
@@ -1116,12 +1196,14 @@ static void generate(struct generator * g, struct node * p) {
1116
1196
  case c_minusassign: generate_integer_assign(g, p, "-="); break;
1117
1197
  case c_multiplyassign:generate_integer_assign(g, p, "*="); break;
1118
1198
  case c_divideassign: generate_integer_assign(g, p, "/="); break;
1119
- case c_eq: generate_integer_test(g, p, "=="); break;
1120
- case c_ne: generate_integer_test(g, p, "!="); break;
1121
- case c_gr: generate_integer_test(g, p, ">"); break;
1122
- case c_ge: generate_integer_test(g, p, ">="); break;
1123
- case c_ls: generate_integer_test(g, p, "<"); break;
1124
- case c_le: generate_integer_test(g, p, "<="); break;
1199
+ case c_eq:
1200
+ case c_ne:
1201
+ case c_gt:
1202
+ case c_ge:
1203
+ case c_lt:
1204
+ case c_le:
1205
+ generate_integer_test(g, p);
1206
+ break;
1125
1207
  case c_call: generate_call(g, p); break;
1126
1208
  case c_grouping: generate_grouping(g, p, false); break;
1127
1209
  case c_non: generate_grouping(g, p, true); break;
@@ -1133,6 +1215,7 @@ static void generate(struct generator * g, struct node * p) {
1133
1215
  case c_false: generate_false(g, p); break;
1134
1216
  case c_true: break;
1135
1217
  case c_debug: generate_debug(g, p); break;
1218
+ case c_functionend: generate_functionend(g, p); break;
1136
1219
  default: fprintf(stderr, "%d encountered\n", p->type);
1137
1220
  exit(1);
1138
1221
  }
@@ -1154,38 +1237,33 @@ static void generate_class_begin(struct generator * g) {
1154
1237
  }
1155
1238
 
1156
1239
  static void generate_among_table(struct generator * g, struct among * x) {
1240
+ write_comment(g, x->node);
1157
1241
 
1158
1242
  struct amongvec * v = x->b;
1159
1243
 
1160
1244
  g->I[0] = x->number;
1161
- g->I[1] = x->literalstring_count;
1162
-
1163
1245
  w(g, "~Mvar A_~I0 = []*snowballRuntime.Among{~N~+");
1164
- {
1165
- int i;
1166
- for (i = 0; i < x->literalstring_count; i++) {
1167
- g->I[0] = v->i;
1168
- g->I[1] = v->result;
1169
- g->L[0] = v->b;
1170
- g->S[0] = ",";
1171
-
1172
- w(g, "~M&snowballRuntime.Among{Str:~L0, A:~I0, B:~I1, ");
1173
- if (v->function != 0) {
1174
- w(g, "F:");
1175
- write_varname(g, v->function);
1176
- } else {
1177
- w(g, "F:nil");
1178
- }
1179
- w(g, "}~S0~N");
1180
- v++;
1246
+
1247
+ for (int i = 0; i < x->literalstring_count; i++) {
1248
+ g->I[0] = v[i].i;
1249
+ g->I[1] = v[i].result;
1250
+ g->L[0] = v[i].b;
1251
+ g->S[0] = ",";
1252
+
1253
+ w(g, "~M&snowballRuntime.Among{Str:~L0, A:~I0, B:~I1, ");
1254
+ if (v[i].function != NULL) {
1255
+ w(g, "F:");
1256
+ write_varname(g, v[i].function);
1257
+ } else {
1258
+ w(g, "F:nil");
1181
1259
  }
1260
+ w(g, "}~S0~N");
1182
1261
  }
1183
1262
  w(g, "~-~M}~N~N");
1184
1263
  }
1185
1264
 
1186
1265
  static void generate_amongs(struct generator * g) {
1187
- struct among * x;
1188
- for (x = g->analyser->amongs; x; x = x->next) {
1266
+ for (struct among * x = g->analyser->amongs; x; x = x->next) {
1189
1267
  generate_among_table(g, x);
1190
1268
  }
1191
1269
  }
@@ -1193,41 +1271,36 @@ static void generate_amongs(struct generator * g) {
1193
1271
  static void set_bit(symbol * b, int i) { b[i/8] |= 1 << i%8; }
1194
1272
 
1195
1273
  static void generate_grouping_table(struct generator * g, struct grouping * q) {
1196
-
1197
1274
  int range = q->largest_ch - q->smallest_ch + 1;
1198
1275
  int size = (range + 7)/ 8; /* assume 8 bits per symbol */
1199
1276
  symbol * b = q->b;
1200
1277
  symbol * map = create_b(size);
1201
- int i;
1202
- for (i = 0; i < size; i++) map[i] = 0;
1203
1278
 
1204
- for (i = 0; i < SIZE(b); i++) set_bit(map, b[i] - q->smallest_ch);
1279
+ for (int i = 0; i < size; i++) map[i] = 0;
1280
+
1281
+ for (int i = 0; i < SIZE(b); i++) set_bit(map, b[i] - q->smallest_ch);
1205
1282
 
1206
1283
  g->V[0] = q->name;
1207
- g->I[0] = size;
1208
1284
  w(g, "~Mvar ~W0 = []byte{");
1209
- for (i = 0; i < size; i++) {
1285
+ for (int i = 0; i < size; i++) {
1210
1286
  write_int(g, map[i]);
1211
1287
  if (i < size - 1) w(g, ", ");
1212
1288
  }
1213
1289
  w(g, "}~N~N");
1290
+
1214
1291
  lose_b(map);
1215
1292
  }
1216
1293
 
1217
1294
  static void generate_groupings(struct generator * g) {
1218
- struct grouping * q;
1219
- for (q = g->analyser->groupings; q; q = q->next) {
1295
+ for (struct grouping * q = g->analyser->groupings; q; q = q->next) {
1220
1296
  if (q->name->used)
1221
1297
  generate_grouping_table(g, q);
1222
1298
  }
1223
1299
  }
1224
1300
 
1225
-
1226
1301
  static void generate_members(struct generator * g) {
1227
-
1228
- struct name * q;
1229
1302
  w(g, "type Context struct {~+~N");
1230
- for (q = g->analyser->names; q; q = q->next) {
1303
+ for (struct name * q = g->analyser->names; q; q = q->next) {
1231
1304
  g->V[0] = q;
1232
1305
  switch (q->type) {
1233
1306
  case t_string:
@@ -1245,17 +1318,13 @@ static void generate_members(struct generator * g) {
1245
1318
  }
1246
1319
 
1247
1320
  static void generate_methods(struct generator * g) {
1248
-
1249
- struct node * p = g->analyser->program;
1250
- while (p != 0) {
1321
+ for (struct node * p = g->analyser->program; p; p = p->right) {
1251
1322
  generate(g, p);
1252
1323
  g->unreachable = false;
1253
- p = p->right;
1254
1324
  }
1255
1325
  }
1256
1326
 
1257
1327
  extern void generate_program_go(struct generator * g) {
1258
-
1259
1328
  g->outbuf = str_new();
1260
1329
  g->failure_str = str_new();
1261
1330