mittens 0.1.1 → 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 (100) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/LICENSE.txt +1 -1
  4. data/README.md +4 -4
  5. data/lib/mittens/version.rb +1 -1
  6. data/mittens.gemspec +1 -1
  7. data/vendor/snowball/.github/workflows/ci.yml +216 -0
  8. data/vendor/snowball/CONTRIBUTING.rst +111 -62
  9. data/vendor/snowball/GNUmakefile +194 -136
  10. data/vendor/snowball/NEWS +798 -3
  11. data/vendor/snowball/README.rst +50 -1
  12. data/vendor/snowball/ada/src/stemmer.adb +25 -13
  13. data/vendor/snowball/ada/src/stemmer.ads +9 -9
  14. data/vendor/snowball/ada/stemmer_config.gpr +7 -7
  15. data/vendor/snowball/algorithms/basque.sbl +4 -19
  16. data/vendor/snowball/algorithms/catalan.sbl +2 -9
  17. data/vendor/snowball/algorithms/danish.sbl +1 -1
  18. data/vendor/snowball/algorithms/dutch.sbl +284 -122
  19. data/vendor/snowball/algorithms/dutch_porter.sbl +178 -0
  20. data/vendor/snowball/algorithms/english.sbl +52 -37
  21. data/vendor/snowball/algorithms/esperanto.sbl +157 -0
  22. data/vendor/snowball/algorithms/estonian.sbl +269 -0
  23. data/vendor/snowball/algorithms/finnish.sbl +2 -3
  24. data/vendor/snowball/algorithms/french.sbl +42 -16
  25. data/vendor/snowball/algorithms/german.sbl +35 -14
  26. data/vendor/snowball/algorithms/greek.sbl +76 -76
  27. data/vendor/snowball/algorithms/hungarian.sbl +8 -6
  28. data/vendor/snowball/algorithms/indonesian.sbl +14 -8
  29. data/vendor/snowball/algorithms/italian.sbl +11 -21
  30. data/vendor/snowball/algorithms/lithuanian.sbl +36 -37
  31. data/vendor/snowball/algorithms/lovins.sbl +0 -1
  32. data/vendor/snowball/algorithms/nepali.sbl +138 -37
  33. data/vendor/snowball/algorithms/norwegian.sbl +19 -5
  34. data/vendor/snowball/algorithms/porter.sbl +2 -2
  35. data/vendor/snowball/algorithms/portuguese.sbl +9 -13
  36. data/vendor/snowball/algorithms/romanian.sbl +17 -4
  37. data/vendor/snowball/algorithms/serbian.sbl +467 -468
  38. data/vendor/snowball/algorithms/spanish.sbl +5 -7
  39. data/vendor/snowball/algorithms/swedish.sbl +60 -6
  40. data/vendor/snowball/algorithms/tamil.sbl +207 -176
  41. data/vendor/snowball/algorithms/turkish.sbl +461 -445
  42. data/vendor/snowball/algorithms/yiddish.sbl +36 -38
  43. data/vendor/snowball/compiler/analyser.c +445 -192
  44. data/vendor/snowball/compiler/driver.c +109 -101
  45. data/vendor/snowball/compiler/generator.c +853 -464
  46. data/vendor/snowball/compiler/generator_ada.c +404 -366
  47. data/vendor/snowball/compiler/generator_csharp.c +297 -260
  48. data/vendor/snowball/compiler/generator_go.c +323 -254
  49. data/vendor/snowball/compiler/generator_java.c +326 -252
  50. data/vendor/snowball/compiler/generator_js.c +362 -252
  51. data/vendor/snowball/compiler/generator_pascal.c +349 -197
  52. data/vendor/snowball/compiler/generator_python.c +257 -240
  53. data/vendor/snowball/compiler/generator_rust.c +423 -251
  54. data/vendor/snowball/compiler/header.h +117 -71
  55. data/vendor/snowball/compiler/space.c +137 -68
  56. data/vendor/snowball/compiler/syswords.h +2 -2
  57. data/vendor/snowball/compiler/tokeniser.c +125 -107
  58. data/vendor/snowball/csharp/Snowball/Among.cs +14 -14
  59. data/vendor/snowball/csharp/Snowball/AssemblyInfo.cs +7 -7
  60. data/vendor/snowball/csharp/Snowball/Stemmer.cs +57 -37
  61. data/vendor/snowball/csharp/Stemwords/App.config +2 -2
  62. data/vendor/snowball/csharp/Stemwords/Program.cs +16 -12
  63. data/vendor/snowball/doc/libstemmer_c_README +7 -4
  64. data/vendor/snowball/doc/libstemmer_csharp_README +4 -1
  65. data/vendor/snowball/doc/libstemmer_java_README +12 -1
  66. data/vendor/snowball/doc/libstemmer_js_README +6 -4
  67. data/vendor/snowball/doc/libstemmer_python_README +9 -4
  68. data/vendor/snowball/examples/stemwords.c +12 -12
  69. data/vendor/snowball/go/env.go +107 -31
  70. data/vendor/snowball/go/util.go +0 -4
  71. data/vendor/snowball/include/libstemmer.h +4 -0
  72. data/vendor/snowball/java/org/tartarus/snowball/Among.java +32 -15
  73. data/vendor/snowball/java/org/tartarus/snowball/SnowballProgram.java +347 -261
  74. data/vendor/snowball/java/org/tartarus/snowball/SnowballStemmer.java +3 -0
  75. data/vendor/snowball/java/org/tartarus/snowball/TestApp.java +52 -37
  76. data/vendor/snowball/javascript/base-stemmer.js +186 -2
  77. data/vendor/snowball/javascript/stemwords.js +3 -6
  78. data/vendor/snowball/libstemmer/libstemmer_c.in +1 -1
  79. data/vendor/snowball/libstemmer/mkalgorithms.pl +6 -6
  80. data/vendor/snowball/libstemmer/mkmodules.pl +2 -2
  81. data/vendor/snowball/libstemmer/modules.txt +13 -10
  82. data/vendor/snowball/libstemmer/test.c +1 -1
  83. data/vendor/snowball/pascal/SnowballProgram.pas +84 -2
  84. data/vendor/snowball/pascal/generate.pl +13 -13
  85. data/vendor/snowball/python/create_init.py +4 -1
  86. data/vendor/snowball/python/setup.cfg +0 -3
  87. data/vendor/snowball/python/setup.py +8 -3
  88. data/vendor/snowball/python/snowballstemmer/basestemmer.py +20 -54
  89. data/vendor/snowball/python/stemwords.py +8 -12
  90. data/vendor/snowball/runtime/api.c +10 -5
  91. data/vendor/snowball/runtime/header.h +10 -9
  92. data/vendor/snowball/runtime/utilities.c +9 -9
  93. data/vendor/snowball/rust/build.rs +1 -1
  94. data/vendor/snowball/rust/src/snowball/snowball_env.rs +83 -5
  95. data/vendor/snowball/tests/stemtest.c +7 -4
  96. metadata +8 -12
  97. data/vendor/snowball/.travis.yml +0 -112
  98. data/vendor/snowball/algorithms/german2.sbl +0 -145
  99. data/vendor/snowball/algorithms/kraaij_pohlmann.sbl +0 -240
  100. 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 */
@@ -17,7 +18,6 @@ static int new_label(struct generator * g) {
17
18
  }
18
19
 
19
20
  static struct str * vars_newname(struct generator * g) {
20
-
21
21
  struct str * output;
22
22
  g->var_number++;
23
23
  output = str_new();
@@ -29,7 +29,6 @@ static struct str * vars_newname(struct generator * g) {
29
29
  /* Write routines for items from the syntax tree */
30
30
 
31
31
  static void write_varname(struct generator * g, struct name * p) {
32
-
33
32
  if (p->type != t_external) {
34
33
  /* Pascal identifiers are case-insensitive but Snowball identifiers
35
34
  * should be case-sensitive. To address this, we encode the case of
@@ -55,11 +54,11 @@ static void write_varname(struct generator * g, struct name * p) {
55
54
  * program authors to avoid naming externals which only differ by
56
55
  * case.
57
56
  */
58
- int i, len = SIZE(p->b);
57
+ int len = SIZE(p->s);
59
58
  int lower_pending = 0;
60
59
  write_char(g, "SBIrxg"[p->type]);
61
- for (i = 0; i != len; ++i) {
62
- int ch = p->b[i];
60
+ for (int i = 0; i != len; ++i) {
61
+ int ch = p->s[i];
63
62
  if (ch >= 'a' && ch <= 'z') {
64
63
  ++lower_pending;
65
64
  } else if (ch >= 'A' && ch <= 'Z') {
@@ -73,13 +72,12 @@ static void write_varname(struct generator * g, struct name * p) {
73
72
 
74
73
  write_char(g, '_');
75
74
  }
76
- write_b(g, p->b);
75
+ write_s(g, p->s);
77
76
  }
78
77
 
79
78
  static void write_literal_string(struct generator * g, symbol * p) {
80
- int i;
81
79
  write_char(g, '\'');
82
- for (i = 0; i < SIZE(p); i++) {
80
+ for (int i = 0; i < SIZE(p); i++) {
83
81
  int ch = p[i];
84
82
  if (ch == '\'') {
85
83
  write_string(g, "''");
@@ -96,13 +94,26 @@ static void write_literal_string(struct generator * g, symbol * p) {
96
94
  }
97
95
 
98
96
  static void write_margin(struct generator * g) {
99
- int i;
100
- for (i = 0; i < g->margin; i++) write_string(g, " ");
97
+ for (int i = 0; i < g->margin; i++) write_string(g, " ");
98
+ }
99
+
100
+ static void write_relop(struct generator * g, int relop) {
101
+ switch (relop) {
102
+ case c_eq: write_string(g, " = "); break;
103
+ case c_ne: write_string(g, " <> "); break;
104
+ case c_gt: write_string(g, " > "); break;
105
+ case c_ge: write_string(g, " >= "); break;
106
+ case c_lt: write_string(g, " < "); break;
107
+ case c_le: write_string(g, " <= "); break;
108
+ default:
109
+ fprintf(stderr, "Unexpected type #%d in generate_integer_test\n", relop);
110
+ exit(1);
111
+ }
101
112
  }
102
113
 
103
114
  /* Write a variable declaration. */
104
115
  static void write_declare(struct generator * g,
105
- char * declaration,
116
+ const char * declaration,
106
117
  struct node * p) {
107
118
  struct str * temp = g->outbuf;
108
119
  g->outbuf = g->declarations;
@@ -126,7 +137,7 @@ static void write_block_start(struct generator * g) {
126
137
  w(g, "~MBegin~+~N");
127
138
  }
128
139
 
129
- static void write_block_end(struct generator * g) { /* block end */
140
+ static void write_block_end(struct generator * g) {
130
141
  w(g, "~-~MEnd;~N");
131
142
  }
132
143
 
@@ -139,22 +150,17 @@ static void write_savecursor(struct generator * g, struct node * p,
139
150
  writef(g, "~M~B0 := ~S1FCursor;~N" , p);
140
151
  }
141
152
 
142
- static void restore_string(struct node * p, struct str * out, struct str * savevar) {
143
- str_clear(out);
153
+ static void append_restore_string(struct node * p, struct str * out, struct str * savevar) {
144
154
  str_append_string(out, "FCursor := ");
145
155
  if (p->mode != m_forward) str_append_string(out, "FLimit - ");
146
156
  str_append(out, savevar);
147
157
  str_append_string(out, ";");
148
158
  }
149
159
 
150
- static void write_restorecursor(struct generator * g, struct node * p,
151
- struct str * savevar) {
152
- struct str * temp = str_new();
160
+ static void write_restorecursor(struct generator * g, struct node * p, struct str * savevar) {
153
161
  write_margin(g);
154
- restore_string(p, temp, savevar);
155
- write_str(g, temp);
162
+ append_restore_string(p, g->outbuf, savevar);
156
163
  write_newline(g);
157
- str_delete(temp);
158
164
  }
159
165
 
160
166
  static void write_inc_cursor(struct generator * g, struct node * p) {
@@ -192,18 +198,18 @@ static void write_failure(struct generator * g) {
192
198
  switch (g->failure_label) {
193
199
  case x_return:
194
200
  write_string(g, "Begin Result := False; Exit; End;");
201
+ g->unreachable = true;
195
202
  break;
196
203
  default:
197
204
  write_string(g, "goto lab");
198
205
  write_int(g, g->failure_label);
199
206
  write_string(g, ";");
207
+ g->unreachable = true;
200
208
  }
201
209
  write_newline(g);
202
- g->unreachable = true;
203
210
  }
204
211
 
205
- static void write_failure_if(struct generator * g, char * s, struct node * p) {
206
-
212
+ static void write_failure_if(struct generator * g, const char * s, struct node * p) {
207
213
  writef(g, "~MIf (", p);
208
214
  writef(g, s, p);
209
215
  writef(g, ") Then~N", p);
@@ -224,18 +230,18 @@ static void write_check_limit(struct generator * g, struct node * p) {
224
230
 
225
231
  /* Formatted write. */
226
232
  static void writef(struct generator * g, const char * input, struct node * p) {
233
+ (void)p;
227
234
  int i = 0;
228
- int l = strlen(input);
229
235
 
230
- while (i < l) {
236
+ while (input[i]) {
231
237
  int ch = input[i++];
232
238
  if (ch != '~') {
233
239
  write_char(g, ch);
234
240
  continue;
235
241
  }
236
- switch (input[i++]) {
237
- default: write_char(g, input[i - 1]); continue;
238
- case 'C': write_comment(g, p); continue;
242
+ ch = input[i++];
243
+ switch (ch) {
244
+ case '~': write_char(g, '~'); continue;
239
245
  case 'f': write_block_start(g);
240
246
  write_failure(g);
241
247
  g->unreachable = false;
@@ -245,21 +251,62 @@ static void writef(struct generator * g, const char * input, struct node * p) {
245
251
  case 'N': write_newline(g); continue;
246
252
  case '{': write_block_start(g); continue;
247
253
  case '}': write_block_end(g); continue;
248
- case 'S': write_string(g, g->S[input[i++] - '0']); continue;
249
- case 'B': write_b(g, g->B[input[i++] - '0']); continue;
250
- case 'I': write_int(g, g->I[input[i++] - '0']); continue;
254
+ case 'S': {
255
+ int j = input[i++] - '0';
256
+ if (j < 0 || j > (int)(sizeof(g->S) / sizeof(g->S[0]))) {
257
+ printf("Invalid escape sequence ~%c%c in writef(g, \"%s\", p)\n",
258
+ ch, input[i - 1], input);
259
+ exit(1);
260
+ }
261
+ write_string(g, g->S[j]);
262
+ continue;
263
+ }
264
+ case 'B': {
265
+ int j = input[i++] - '0';
266
+ if (j < 0 || j > (int)(sizeof(g->B) / sizeof(g->B[0])))
267
+ goto invalid_escape2;
268
+ write_s(g, g->B[j]);
269
+ continue;
270
+ }
271
+ case 'I': {
272
+ int j = input[i++] - '0';
273
+ if (j < 0 || j > (int)(sizeof(g->I) / sizeof(g->I[0])))
274
+ goto invalid_escape2;
275
+ write_int(g, g->I[j]);
276
+ continue;
277
+ }
251
278
  case 'V':
252
- case 'W': write_varname(g, g->V[input[i++] - '0']); continue;
253
- case 'L': write_literal_string(g, g->L[input[i++] - '0']); continue;
279
+ case 'W': {
280
+ int j = input[i++] - '0';
281
+ if (j < 0 || j > (int)(sizeof(g->V) / sizeof(g->V[0])))
282
+ goto invalid_escape2;
283
+ write_varname(g, g->V[j]);
284
+ continue;
285
+ }
286
+ case 'L': {
287
+ int j = input[i++] - '0';
288
+ if (j < 0 || j > (int)(sizeof(g->L) / sizeof(g->L[0])))
289
+ goto invalid_escape2;
290
+ write_literal_string(g, g->L[j]);
291
+ continue;
292
+ }
254
293
  case '+': g->margin++; continue;
255
294
  case '-': g->margin--; continue;
256
295
  case 'n': write_string(g, g->options->name); continue;
296
+ default:
297
+ printf("Invalid escape sequence ~%c in writef(g, \"%s\", p)\n",
298
+ ch, input);
299
+ exit(1);
300
+ invalid_escape2:
301
+ printf("Invalid escape sequence ~%c%c in writef(g, \"%s\", p)\n",
302
+ ch, input[i - 1], input);
303
+ exit(1);
257
304
  }
258
305
  }
259
306
  }
260
307
 
261
308
  static void w(struct generator * g, const char * s) {
262
- writef(g, s, 0);
309
+ writef(g, s, NULL);
263
310
  }
264
311
 
265
312
  static void generate_AE(struct generator * g, struct node * p) {
@@ -312,26 +359,33 @@ static void generate_bra(struct generator * g, struct node * p) {
312
359
  }
313
360
 
314
361
  static void generate_and(struct generator * g, struct node * p) {
315
- struct str * savevar = vars_newname(g);
316
- int keep_c = K_needed(g, p->left);
362
+ struct str * savevar = NULL;
363
+ if (K_needed(g, p->left)) {
364
+ savevar = vars_newname(g);
365
+ }
317
366
 
318
367
  write_comment(g, p);
319
368
 
320
- if (keep_c) write_savecursor(g, p, savevar);
369
+ if (savevar) write_savecursor(g, p, savevar);
321
370
 
322
371
  p = p->left;
323
372
  while (p) {
324
373
  generate(g, p);
325
374
  if (g->unreachable) break;
326
- if (keep_c && p->right != 0) write_restorecursor(g, p, savevar);
375
+ if (savevar && p->right != NULL) write_restorecursor(g, p, savevar);
327
376
  p = p->right;
328
377
  }
329
- str_delete(savevar);
378
+
379
+ if (savevar) {
380
+ str_delete(savevar);
381
+ }
330
382
  }
331
383
 
332
384
  static void generate_or(struct generator * g, struct node * p) {
333
- struct str * savevar = vars_newname(g);
334
- int keep_c = K_needed(g, p->left);
385
+ struct str * savevar = NULL;
386
+ if (K_needed(g, p->left)) {
387
+ savevar = vars_newname(g);
388
+ }
335
389
 
336
390
  int a0 = g->failure_label;
337
391
  struct str * a1 = str_copy(g->failure_str);
@@ -342,13 +396,13 @@ static void generate_or(struct generator * g, struct node * p) {
342
396
  write_comment(g, p);
343
397
  wsetlab_begin(g);
344
398
 
345
- if (keep_c) write_savecursor(g, p, savevar);
399
+ if (savevar) write_savecursor(g, p, savevar);
346
400
 
347
401
  p = p->left;
348
402
  str_clear(g->failure_str);
349
403
 
350
- if (p == 0) {
351
- /* p should never be 0 after an or: there should be at least two
404
+ if (p == NULL) {
405
+ /* p should never be NULL after an or: there should be at least two
352
406
  * sub nodes. */
353
407
  fprintf(stderr, "Error: \"or\" node without children nodes.");
354
408
  exit(1);
@@ -363,7 +417,7 @@ static void generate_or(struct generator * g, struct node * p) {
363
417
  }
364
418
  wsetlab_end(g, g->failure_label);
365
419
  g->unreachable = false;
366
- if (keep_c) write_restorecursor(g, p, savevar);
420
+ if (savevar) write_restorecursor(g, p, savevar);
367
421
  p = p->right;
368
422
  }
369
423
 
@@ -376,7 +430,10 @@ static void generate_or(struct generator * g, struct node * p) {
376
430
  if (!end_unreachable) {
377
431
  g->unreachable = false;
378
432
  }
379
- str_delete(savevar);
433
+
434
+ if (savevar) {
435
+ str_delete(savevar);
436
+ }
380
437
  }
381
438
 
382
439
  static void generate_backwards(struct generator * g, struct node * p) {
@@ -388,14 +445,16 @@ static void generate_backwards(struct generator * g, struct node * p) {
388
445
 
389
446
 
390
447
  static void generate_not(struct generator * g, struct node * p) {
391
- struct str * savevar = vars_newname(g);
392
- int keep_c = K_needed(g, p->left);
448
+ struct str * savevar = NULL;
449
+ if (K_needed(g, p->left)) {
450
+ savevar = vars_newname(g);
451
+ }
393
452
 
394
- int a0 = g->failure_label, l;
453
+ int a0 = g->failure_label;
395
454
  struct str * a1 = str_copy(g->failure_str);
396
455
 
397
456
  write_comment(g, p);
398
- if (keep_c) {
457
+ if (savevar) {
399
458
  write_block_start(g);
400
459
  write_savecursor(g, p, savevar);
401
460
  }
@@ -404,7 +463,7 @@ static void generate_not(struct generator * g, struct node * p) {
404
463
  str_clear(g->failure_str);
405
464
 
406
465
  wsetlab_begin(g);
407
- l = g->failure_label;
466
+ int l = g->failure_label;
408
467
 
409
468
  generate(g, p->left);
410
469
 
@@ -417,29 +476,37 @@ static void generate_not(struct generator * g, struct node * p) {
417
476
  wsetlab_end(g, l);
418
477
  g->unreachable = false;
419
478
 
420
- if (keep_c) write_restorecursor(g, p, savevar);
421
- if (keep_c) write_block_end(g);
422
- str_delete(savevar);
479
+ if (savevar) {
480
+ write_restorecursor(g, p, savevar);
481
+ write_block_end(g);
482
+ str_delete(savevar);
483
+ }
423
484
  }
424
485
 
425
486
 
426
487
  static void generate_try(struct generator * g, struct node * p) {
427
- struct str * savevar = vars_newname(g);
428
- int keep_c = K_needed(g, p->left);
429
-
430
- write_comment(g, p);
431
- if (keep_c) write_savecursor(g, p, savevar);
488
+ struct str * savevar = NULL;
489
+ if (K_needed(g, p->left)) {
490
+ savevar = vars_newname(g);
491
+ }
432
492
 
433
493
  g->failure_label = new_label(g);
434
494
  str_clear(g->failure_str);
435
- if (keep_c) restore_string(p, g->failure_str, savevar);
495
+
496
+ write_comment(g, p);
497
+ if (savevar) {
498
+ write_savecursor(g, p, savevar);
499
+ append_restore_string(p, g->failure_str, savevar);
500
+ }
436
501
 
437
502
  wsetlab_begin(g);
438
503
  generate(g, p->left);
439
504
  wsetlab_end(g, g->failure_label);
440
505
  g->unreachable = false;
441
506
 
442
- str_delete(savevar);
507
+ if (savevar) {
508
+ str_delete(savevar);
509
+ }
443
510
  }
444
511
 
445
512
  static void generate_set(struct generator * g, struct node * p) {
@@ -463,30 +530,35 @@ static void generate_fail(struct generator * g, struct node * p) {
463
530
  /* generate_test() also implements 'reverse' */
464
531
 
465
532
  static void generate_test(struct generator * g, struct node * p) {
466
- struct str * savevar = vars_newname(g);
467
- int keep_c = K_needed(g, p->left);
533
+ struct str * savevar = NULL;
534
+ if (K_needed(g, p->left)) {
535
+ savevar = vars_newname(g);
536
+ }
468
537
 
469
538
  write_comment(g, p);
470
539
 
471
- if (keep_c) {
540
+ if (savevar) {
472
541
  write_savecursor(g, p, savevar);
473
542
  }
474
543
 
475
544
  generate(g, p->left);
476
545
 
477
- if (!g->unreachable) {
478
- if (keep_c) {
546
+ if (savevar) {
547
+ if (!g->unreachable) {
479
548
  write_restorecursor(g, p, savevar);
480
549
  }
550
+ str_delete(savevar);
481
551
  }
482
- str_delete(savevar);
483
552
  }
484
553
 
485
554
  static void generate_do(struct generator * g, struct node * p) {
486
- struct str * savevar = vars_newname(g);
487
- int keep_c = K_needed(g, p->left);
555
+ struct str * savevar = NULL;
556
+ if (K_needed(g, p->left)) {
557
+ savevar = vars_newname(g);
558
+ }
559
+
488
560
  write_comment(g, p);
489
- if (keep_c) write_savecursor(g, p, savevar);
561
+ if (savevar) write_savecursor(g, p, savevar);
490
562
 
491
563
  if (p->left->type == c_call) {
492
564
  /* Optimise do <call> */
@@ -503,24 +575,51 @@ static void generate_do(struct generator * g, struct node * p) {
503
575
  g->unreachable = false;
504
576
  }
505
577
 
506
- if (keep_c) write_restorecursor(g, p, savevar);
507
- str_delete(savevar);
578
+ if (savevar) {
579
+ write_restorecursor(g, p, savevar);
580
+ str_delete(savevar);
581
+ }
582
+ }
583
+
584
+ static void generate_next(struct generator * g, struct node * p) {
585
+ write_comment(g, p);
586
+ write_check_limit(g, p);
587
+ write_inc_cursor(g, p);
588
+ }
589
+
590
+ static void generate_GO_grouping(struct generator * g, struct node * p, int is_goto, int complement) {
591
+ write_comment(g, p);
592
+
593
+ struct grouping * q = p->name->grouping;
594
+ g->S[0] = p->mode == m_forward ? "" : "Bk";
595
+ g->S[1] = complement ? "In" : "Out";
596
+ g->V[0] = p->name;
597
+ g->I[0] = q->smallest_ch;
598
+ g->I[1] = q->largest_ch;
599
+ write_failure_if(g, "Not (Go~S1Grouping~S0(~V0, ~I0, ~I1))", p);
600
+ if (!is_goto) {
601
+ write_string(g, p->mode == m_forward ? "Inc(FCursor);" : "Dec(FCursor);");
602
+ }
508
603
  }
509
604
 
510
605
  static void generate_GO(struct generator * g, struct node * p, int style) {
511
- int end_unreachable = false;
512
- struct str * savevar = vars_newname(g);
513
- int keep_c = style == 1 || repeat_restore(g, p->left);
606
+ write_comment(g, p);
607
+
514
608
  int a0 = g->failure_label;
515
609
  struct str * a1 = str_copy(g->failure_str);
516
610
 
611
+ int end_unreachable = false;
612
+
517
613
  int golab = new_label(g);
518
614
 
519
- write_comment(g, p);
520
615
  w(g, "~MWhile True Do~N");
521
616
  w(g, "~{");
522
617
 
523
- if (keep_c) write_savecursor(g, p, savevar);
618
+ struct str * savevar = NULL;
619
+ if (style == 1 || repeat_restore(g, p->left)) {
620
+ savevar = vars_newname(g);
621
+ write_savecursor(g, p, savevar);
622
+ }
524
623
 
525
624
  g->failure_label = new_label(g);
526
625
  str_clear(g->failure_str);
@@ -539,7 +638,10 @@ static void generate_GO(struct generator * g, struct node * p, int style) {
539
638
  }
540
639
  g->unreachable = false;
541
640
  wsetlab_end(g, g->failure_label);
542
- if (keep_c) write_restorecursor(g, p, savevar);
641
+ if (savevar) {
642
+ write_restorecursor(g, p, savevar);
643
+ str_delete(savevar);
644
+ }
543
645
 
544
646
  g->failure_label = a0;
545
647
  str_delete(g->failure_str);
@@ -550,7 +652,6 @@ static void generate_GO(struct generator * g, struct node * p, int style) {
550
652
 
551
653
  g->I[0] = golab;
552
654
  w(g, "~}lab~I0:~N");
553
- str_delete(savevar);
554
655
  g->unreachable = end_unreachable;
555
656
  }
556
657
 
@@ -572,13 +673,15 @@ static void generate_loop(struct generator * g, struct node * p) {
572
673
  }
573
674
 
574
675
  static void generate_repeat_or_atleast(struct generator * g, struct node * p, struct str * loopvar) {
575
- struct str * savevar = vars_newname(g);
576
- int keep_c = repeat_restore(g, p->left);
577
676
  int replab = new_label(g);
578
677
  g->I[0] = replab;
579
678
  writef(g, "lab~I0:~N~MWhile True Do~N~{", p);
580
679
 
581
- if (keep_c) write_savecursor(g, p, savevar);
680
+ struct str * savevar = NULL;
681
+ if (repeat_restore(g, p->left)) {
682
+ savevar = vars_newname(g);
683
+ write_savecursor(g, p, savevar);
684
+ }
582
685
 
583
686
  g->failure_label = new_label(g);
584
687
  str_clear(g->failure_str);
@@ -586,7 +689,7 @@ static void generate_repeat_or_atleast(struct generator * g, struct node * p, st
586
689
  generate(g, p->left);
587
690
 
588
691
  if (!g->unreachable) {
589
- if (loopvar != 0) {
692
+ if (loopvar != NULL) {
590
693
  g->B[0] = str_data(loopvar);
591
694
  w(g, "~MDec(~B0);~N");
592
695
  }
@@ -598,10 +701,12 @@ static void generate_repeat_or_atleast(struct generator * g, struct node * p, st
598
701
  wsetlab_end(g, g->failure_label);
599
702
  g->unreachable = false;
600
703
 
601
- if (keep_c) write_restorecursor(g, p, savevar);
704
+ if (savevar) {
705
+ write_restorecursor(g, p, savevar);
706
+ str_delete(savevar);
707
+ }
602
708
 
603
709
  w(g, "~MBreak;~N~}");
604
- str_delete(savevar);
605
710
  }
606
711
 
607
712
  static void generate_repeat(struct generator * g, struct node * p) {
@@ -615,7 +720,6 @@ static void generate_atleast(struct generator * g, struct node * p) {
615
720
  write_comment(g, p);
616
721
  w(g, "~{");
617
722
  g->B[0] = str_data(loopvar);
618
-
619
723
  write_declare(g, "~B0 : Integer", p);
620
724
  w(g, "~M~B0 := ");
621
725
  generate_AE(g, p->AE);
@@ -683,8 +787,8 @@ static void generate_hop(struct generator * g, struct node * p) {
683
787
  write_failure_if(g, "(C ~S1) Or (C ~S2 FCursor)", p);
684
788
  }
685
789
  writef(g, "~MFCursor := C;~N", p);
686
- g->temporary_used = true;
687
790
  writef(g, "~}", p);
791
+ g->temporary_used = true;
688
792
  }
689
793
 
690
794
  static void generate_delete(struct generator * g, struct node * p) {
@@ -692,13 +796,6 @@ static void generate_delete(struct generator * g, struct node * p) {
692
796
  writef(g, "~MSliceDel;~N", p);
693
797
  }
694
798
 
695
-
696
- static void generate_next(struct generator * g, struct node * p) {
697
- write_comment(g, p);
698
- write_check_limit(g, p);
699
- write_inc_cursor(g, p);
700
- }
701
-
702
799
  static void generate_tolimit(struct generator * g, struct node * p) {
703
800
  write_comment(g, p);
704
801
  g->S[0] = p->mode == m_forward ? "FLimit" : "FBkLimit";
@@ -738,7 +835,7 @@ static void generate_sliceto(struct generator * g, struct node * p) {
738
835
 
739
836
  static void generate_address(struct generator * g, struct node * p) {
740
837
  symbol * b = p->literalstring;
741
- if (b != 0) {
838
+ if (b != NULL) {
742
839
  write_literal_string(g, b);
743
840
  } else {
744
841
  write_varname(g, p->name);
@@ -746,7 +843,6 @@ static void generate_address(struct generator * g, struct node * p) {
746
843
  }
747
844
 
748
845
  static void generate_insert(struct generator * g, struct node * p, int style) {
749
-
750
846
  int keep_c = style == c_attach;
751
847
  write_comment(g, p);
752
848
  if (p->mode == m_backward) keep_c = !keep_c;
@@ -786,7 +882,6 @@ static void generate_slicefrom(struct generator * g, struct node * p) {
786
882
  }
787
883
 
788
884
  static void generate_setlimit(struct generator * g, struct node * p) {
789
- struct str * savevar = vars_newname(g);
790
885
  struct str * varname = vars_newname(g);
791
886
  write_comment(g, p);
792
887
  if (p->left && p->left->type == c_tomark) {
@@ -799,6 +894,7 @@ static void generate_setlimit(struct generator * g, struct node * p) {
799
894
  * restore c.
800
895
  */
801
896
  struct node * q = p->left;
897
+ write_comment(g, q);
802
898
  g->S[0] = q->mode == m_forward ? ">" : "<";
803
899
  w(g, "~MIf (FCursor ~S0 "); generate_AE(g, q->AE); w(g, ") Then~N");
804
900
  write_block_start(g);
@@ -815,7 +911,8 @@ static void generate_setlimit(struct generator * g, struct node * p) {
815
911
  w(g, "~M~B0 := FBkLimit;~N");
816
912
  w(g, "~MFBkLimit := ");
817
913
  }
818
- generate_AE(g, q->AE); writef(g, ";~N", q);
914
+ generate_AE(g, q->AE);
915
+ writef(g, ";~N", q);
819
916
 
820
917
  if (p->mode == m_forward) {
821
918
  str_assign(g->failure_str, "FLimit := FLimit + ");
@@ -827,7 +924,9 @@ static void generate_setlimit(struct generator * g, struct node * p) {
827
924
  str_append_ch(g->failure_str, ';');
828
925
  }
829
926
  } else {
927
+ struct str * savevar = vars_newname(g);
830
928
  write_savecursor(g, p, savevar);
929
+
831
930
  generate(g, p->left);
832
931
 
833
932
  if (!g->unreachable) {
@@ -852,6 +951,7 @@ static void generate_setlimit(struct generator * g, struct node * p) {
852
951
  str_append_ch(g->failure_str, ';');
853
952
  }
854
953
  }
954
+ str_delete(savevar);
855
955
  }
856
956
 
857
957
  if (!g->unreachable) {
@@ -863,17 +963,16 @@ static void generate_setlimit(struct generator * g, struct node * p) {
863
963
  write_newline(g);
864
964
  }
865
965
  }
866
-
867
966
  str_delete(varname);
868
- str_delete(savevar);
869
967
  }
870
968
 
871
969
  /* dollar sets snowball up to operate on a string variable as if it were the
872
970
  * current string */
873
971
  static void generate_dollar(struct generator * g, struct node * p) {
972
+ write_comment(g, p);
973
+
874
974
  struct str * savevar = vars_newname(g);
875
975
  g->B[0] = str_data(savevar);
876
- write_comment(g, p);
877
976
  g->V[0] = p->name;
878
977
 
879
978
  {
@@ -899,7 +998,6 @@ static void generate_dollar(struct generator * g, struct node * p) {
899
998
  write_declare(g, "~B0_Ket : Integer", p);
900
999
  writef(g, "~{"
901
1000
  "~M~B0_Current := FCurrent;~N"
902
- "{ ~M~B0_Current := Copy(FCurrent, 1, FLimit); }~N"
903
1001
  "~M~B0_Cursor := FCursor;~N"
904
1002
  "~M~B0_Limit := FLimit;~N"
905
1003
  "~M~B0_BkLimit := FBkLimit;~N"
@@ -918,12 +1016,12 @@ static void generate_dollar(struct generator * g, struct node * p) {
918
1016
  str_delete(savevar);
919
1017
  }
920
1018
 
921
- static void generate_integer_assign(struct generator * g, struct node * p, char * s) {
922
-
1019
+ static void generate_integer_assign(struct generator * g, struct node * p, const char * s) {
1020
+ write_comment(g, p);
923
1021
  g->V[0] = p->name;
924
1022
  w(g, "~M~W0 := ");
925
1023
 
926
- if (s != 0) {
1024
+ if (s != NULL) {
927
1025
  g->S[0] = s;
928
1026
  w(g, "~W0 ~S0 ");
929
1027
  }
@@ -932,29 +1030,62 @@ static void generate_integer_assign(struct generator * g, struct node * p, char
932
1030
  w(g, ";~N");
933
1031
  }
934
1032
 
935
- static void generate_integer_test(struct generator * g, struct node * p, char * s) {
936
-
937
- w(g, "~MIf Not (");
1033
+ static void generate_integer_test(struct generator * g, struct node * p) {
1034
+ write_comment(g, p);
1035
+ int relop = p->type;
1036
+ int optimise_to_return = (g->failure_label == x_return && p->right && p->right->type == c_functionend);
1037
+ if (optimise_to_return) {
1038
+ w(g, "~MResult := ");
1039
+ p->right = NULL;
1040
+ } else {
1041
+ w(g, "~MIf ");
1042
+ // We want the inverse of the snowball test here.
1043
+ relop ^= 1;
1044
+ }
938
1045
  generate_AE(g, p->left);
939
- write_char(g, ' ');
940
- write_string(g, s);
941
- write_char(g, ' ');
1046
+ write_relop(g, relop);
942
1047
  generate_AE(g, p->AE);
943
- w(g, ") Then~N");
944
- write_block_start(g);
945
- write_failure(g);
946
- write_block_end(g);
947
- g->unreachable = false;
1048
+ if (optimise_to_return) {
1049
+ w(g, "~N");
1050
+ } else {
1051
+ w(g, " Then~N");
1052
+ write_block_start(g);
1053
+ write_failure(g);
1054
+ write_block_end(g);
1055
+ g->unreachable = false;
1056
+ }
948
1057
  }
949
1058
 
950
1059
  static void generate_call(struct generator * g, struct node * p) {
951
-
1060
+ int signals = check_possible_signals_list(g, p->name->definition, c_define, 0);
952
1061
  write_comment(g, p);
953
1062
  g->V[0] = p->name;
954
- write_failure_if(g, "Not ~V0", p);
1063
+ if (g->failure_label == x_return) {
1064
+ if (p->right && p->right->type == c_functionend) {
1065
+ /* Tail call. */
1066
+ writef(g, "~MResult = ~V0;~N", p);
1067
+ return;
1068
+ }
1069
+ if (signals == 0) {
1070
+ /* Always fails. */
1071
+ writef(g, "~MBegin; Result = ~V0; Exit; End;~N", p);
1072
+ return;
1073
+ }
1074
+ }
1075
+ if (signals == 1) {
1076
+ /* Always succeeds. */
1077
+ writef(g, "~M~V0;~N", p);
1078
+ } else if (signals == 0) {
1079
+ /* Always fails. */
1080
+ writef(g, "~M~V0;~N", p);
1081
+ write_failure(g);
1082
+ } else {
1083
+ write_failure_if(g, "Not ~V0", p);
1084
+ }
955
1085
  }
956
1086
 
957
1087
  static void generate_grouping(struct generator * g, struct node * p, int complement) {
1088
+ write_comment(g, p);
958
1089
 
959
1090
  struct grouping * q = p->name->grouping;
960
1091
  g->S[0] = p->mode == m_forward ? "" : "Bk";
@@ -966,7 +1097,6 @@ static void generate_grouping(struct generator * g, struct node * p, int complem
966
1097
  }
967
1098
 
968
1099
  static void generate_namedstring(struct generator * g, struct node * p) {
969
-
970
1100
  write_comment(g, p);
971
1101
  g->S[0] = p->mode == m_forward ? "" : "Bk";
972
1102
  g->V[0] = p->name;
@@ -983,17 +1113,19 @@ static void generate_literalstring(struct generator * g, struct node * p) {
983
1113
  }
984
1114
 
985
1115
  static void generate_define(struct generator * g, struct node * p) {
986
- struct str *saved_output;
987
- struct str *saved_declarations;
1116
+ struct name * q = p->name;
1117
+ if (q->type == t_routine && !q->used) return;
988
1118
 
989
- /* Generate function header. */
990
- g->V[0] = p->name;
991
- w(g, "~N~MFunction T~n.~W0 : Boolean;~N");
1119
+ write_newline(g);
1120
+ write_comment(g, p);
992
1121
 
993
- /* Save output*/
994
- saved_output = g->outbuf;
995
- saved_declarations = g->declarations;
1122
+ /* Generate function header. */
1123
+ g->V[0] = q;
1124
+ w(g, "~MFunction T~n.~W0 : Boolean;~N");
996
1125
 
1126
+ /* Save output. */
1127
+ struct str *saved_output = g->outbuf;
1128
+ struct str *saved_declarations = g->declarations;
997
1129
  g->outbuf = str_new();
998
1130
  g->declarations = str_new();
999
1131
 
@@ -1006,9 +1138,15 @@ static void generate_define(struct generator * g, struct node * p) {
1006
1138
 
1007
1139
  /* Generate function body. */
1008
1140
  w(g, "~{");
1141
+ int signals = check_possible_signals_list(g, p->left, c_define, 0);
1009
1142
  g->temporary_used = false;
1010
1143
  generate(g, p->left);
1011
- if (!g->unreachable) w(g, "~MResult := True;~N");
1144
+ if (p->left->right) {
1145
+ assert(p->left->right->type == c_functionend);
1146
+ if (signals) {
1147
+ generate(g, p->left->right);
1148
+ }
1149
+ }
1012
1150
  w(g, "~}");
1013
1151
 
1014
1152
  if (g->temporary_used) {
@@ -1025,11 +1163,10 @@ static void generate_define(struct generator * g, struct node * p) {
1025
1163
  }
1026
1164
 
1027
1165
  if (g->next_label) {
1028
- int i, num = g->next_label;
1029
-
1030
1166
  str_append_string(saved_output, "Label\n");
1031
1167
 
1032
- for (i = 0; i < num; ++i) {
1168
+ int num = g->next_label;
1169
+ for (int i = 0; i < num; ++i) {
1033
1170
  str_append_string(saved_output, " lab");
1034
1171
  str_append_int(saved_output, i);
1035
1172
  str_append_string(saved_output, i == num - 1 ? ";\n" : ",\n");
@@ -1043,39 +1180,47 @@ static void generate_define(struct generator * g, struct node * p) {
1043
1180
  g->outbuf = saved_output;
1044
1181
  }
1045
1182
 
1046
- static void generate_substring(struct generator * g, struct node * p) {
1047
- struct among * x = p->among;
1183
+ static void generate_functionend(struct generator * g, struct node * p) {
1184
+ (void)p;
1185
+ w(g, "~MResult := True;~N");
1186
+ }
1048
1187
 
1188
+ static void generate_substring(struct generator * g, struct node * p) {
1049
1189
  write_comment(g, p);
1050
1190
 
1191
+ struct among * x = p->among;
1192
+
1051
1193
  g->S[0] = p->mode == m_forward ? "" : "Bk";
1052
1194
  g->I[0] = x->number;
1053
1195
  g->I[1] = x->literalstring_count;
1054
1196
 
1055
- if (!x->amongvar_needed) {
1056
- write_failure_if(g, "FindAmong~S0(a_~I0, ~I1) = 0", p);
1057
- } else {
1197
+ if (x->amongvar_needed) {
1058
1198
  writef(g, "~MAmongVar := FindAmong~S0(a_~I0, ~I1);~N", p);
1059
- write_failure_if(g, "AmongVar = 0", p);
1199
+ if (!x->always_matches) {
1200
+ write_failure_if(g, "AmongVar = 0", p);
1201
+ }
1202
+ } else if (x->always_matches) {
1203
+ writef(g, "~MFindAmong~S0(a_~I0, ~I1);~N", p);
1204
+ } else {
1205
+ write_failure_if(g, "FindAmong~S0(a_~I0, ~I1) = 0", p);
1060
1206
  }
1061
1207
  }
1062
1208
 
1063
1209
  static void generate_among(struct generator * g, struct node * p) {
1064
-
1065
1210
  struct among * x = p->among;
1066
1211
 
1067
- if (x->substring == 0) generate_substring(g, p);
1068
-
1069
- if (x->starter != 0) generate(g, x->starter);
1212
+ if (x->substring == NULL) {
1213
+ generate_substring(g, p);
1214
+ } else {
1215
+ write_comment(g, p);
1216
+ }
1070
1217
 
1071
1218
  if (x->command_count == 1 && x->nocommand_count == 0) {
1072
1219
  /* Only one outcome ("no match" already handled). */
1073
1220
  generate(g, x->commands[0]);
1074
1221
  } else if (x->command_count > 0) {
1075
- int i;
1076
- write_comment(g, p);
1077
1222
  w(g, "~MCase AmongVar Of~N~+");
1078
- for (i = 1; i <= x->command_count; i++) {
1223
+ for (int i = 1; i <= x->command_count; i++) {
1079
1224
  g->I[0] = i;
1080
1225
  w(g, "~M~I0:~N~{");
1081
1226
  generate(g, x->commands[i - 1]);
@@ -1087,20 +1232,17 @@ static void generate_among(struct generator * g, struct node * p) {
1087
1232
  }
1088
1233
 
1089
1234
  static void generate_booltest(struct generator * g, struct node * p) {
1090
-
1091
1235
  write_comment(g, p);
1092
1236
  g->V[0] = p->name;
1093
1237
  write_failure_if(g, "Not (~V0)", p);
1094
1238
  }
1095
1239
 
1096
1240
  static void generate_false(struct generator * g, struct node * p) {
1097
-
1098
1241
  write_comment(g, p);
1099
1242
  write_failure(g);
1100
1243
  }
1101
1244
 
1102
1245
  static void generate_debug(struct generator * g, struct node * p) {
1103
-
1104
1246
  write_comment(g, p);
1105
1247
  g->I[0] = g->debug_count++;
1106
1248
  g->I[1] = p->line_number;
@@ -1108,14 +1250,10 @@ static void generate_debug(struct generator * g, struct node * p) {
1108
1250
  }
1109
1251
 
1110
1252
  static void generate(struct generator * g, struct node * p) {
1111
-
1112
- int a0;
1113
- struct str * a1;
1114
-
1115
1253
  if (g->unreachable) return;
1116
1254
 
1117
- a0 = g->failure_label;
1118
- a1 = str_copy(g->failure_str);
1255
+ int a0 = g->failure_label;
1256
+ struct str * a1 = str_copy(g->failure_str);
1119
1257
 
1120
1258
  switch (p->type) {
1121
1259
  case c_define: generate_define(g, p); break;
@@ -1133,6 +1271,11 @@ static void generate(struct generator * g, struct node * p) {
1133
1271
  case c_do: generate_do(g, p); break;
1134
1272
  case c_goto: generate_GO(g, p, 1); break;
1135
1273
  case c_gopast: generate_GO(g, p, 0); break;
1274
+ case c_goto_grouping: generate_GO_grouping(g, p, 1, 0); break;
1275
+ case c_gopast_grouping:
1276
+ generate_GO_grouping(g, p, 0, 0); break;
1277
+ case c_goto_non: generate_GO_grouping(g, p, 1, 1); break;
1278
+ case c_gopast_non: generate_GO_grouping(g, p, 0, 1); break;
1136
1279
  case c_repeat: generate_repeat(g, p); break;
1137
1280
  case c_loop: generate_loop(g, p); break;
1138
1281
  case c_atleast: generate_atleast(g, p); break;
@@ -1159,12 +1302,14 @@ static void generate(struct generator * g, struct node * p) {
1159
1302
  case c_minusassign: generate_integer_assign(g, p, "-"); break;
1160
1303
  case c_multiplyassign:generate_integer_assign(g, p, "*"); break;
1161
1304
  case c_divideassign: generate_integer_assign(g, p, "div"); break;
1162
- case c_eq: generate_integer_test(g, p, "="); break;
1163
- case c_ne: generate_integer_test(g, p, "<>"); break;
1164
- case c_gr: generate_integer_test(g, p, ">"); break;
1165
- case c_ge: generate_integer_test(g, p, ">="); break;
1166
- case c_ls: generate_integer_test(g, p, "<"); break;
1167
- case c_le: generate_integer_test(g, p, "<="); break;
1305
+ case c_eq:
1306
+ case c_ne:
1307
+ case c_gt:
1308
+ case c_ge:
1309
+ case c_lt:
1310
+ case c_le:
1311
+ generate_integer_test(g, p);
1312
+ break;
1168
1313
  case c_call: generate_call(g, p); break;
1169
1314
  case c_grouping: generate_grouping(g, p, false); break;
1170
1315
  case c_non: generate_grouping(g, p, true); break;
@@ -1176,6 +1321,7 @@ static void generate(struct generator * g, struct node * p) {
1176
1321
  case c_false: generate_false(g, p); break;
1177
1322
  case c_true: break;
1178
1323
  case c_debug: generate_debug(g, p); break;
1324
+ case c_functionend: generate_functionend(g, p); break;
1179
1325
  default: fprintf(stderr, "%d encountered\n", p->type);
1180
1326
  exit(1);
1181
1327
  }
@@ -1213,54 +1359,65 @@ static void generate_method_decl(struct generator * g, struct name * q) {
1213
1359
  }
1214
1360
 
1215
1361
  static void generate_method_decls(struct generator * g) {
1216
- struct name * q;
1217
-
1218
1362
  w(g, "~Mpublic~N~+");
1219
1363
  w(g, "~MConstructor Create;~N");
1220
1364
 
1221
- for (q = g->analyser->names; q; q = q->next) {
1365
+ for (struct name * q = g->analyser->names; q; q = q->next) {
1222
1366
  if (q->type == t_external) {
1223
1367
  generate_method_decl(g, q);
1224
1368
  }
1225
1369
  }
1226
1370
  w(g, "~-");
1227
1371
 
1228
- w(g, "~Mprivate~N~+");
1229
- for (q = g->analyser->names; q; q = q->next) {
1372
+ int first = true;
1373
+ for (struct name * q = g->analyser->names; q; q = q->next) {
1230
1374
  if (q->type == t_routine) {
1375
+ if (first) {
1376
+ w(g, "~Mprivate~N~+");
1377
+ first = false;
1378
+ }
1231
1379
  generate_method_decl(g, q);
1232
1380
  }
1233
1381
  }
1234
- w(g, "~-");
1382
+ if (!first) w(g, "~-");
1235
1383
  }
1236
1384
 
1237
1385
  static void generate_member_decls(struct generator * g) {
1238
- struct name * q;
1239
- w(g, "~Mprivate~N~+");
1240
- for (q = g->analyser->names; q; q = q->next) {
1386
+ int first = true;
1387
+ for (struct name * q = g->analyser->names; q; q = q->next) {
1241
1388
  g->V[0] = q;
1242
1389
  switch (q->type) {
1243
1390
  case t_string:
1244
- w(g, "~M~W0 : AnsiString;~N");
1245
- break;
1246
1391
  case t_integer:
1247
- w(g, "~M~W0 : Integer;~N");
1248
- break;
1249
1392
  case t_boolean:
1250
- w(g, "~M~W0 : Boolean;~N");
1251
- break;
1393
+ if (first) {
1394
+ w(g, "~Mprivate~N~+");
1395
+ first = false;
1396
+ }
1397
+ switch (q->type) {
1398
+ case t_string:
1399
+ w(g, "~M~W0 : AnsiString;~N");
1400
+ break;
1401
+ case t_integer:
1402
+ w(g, "~M~W0 : Integer;~N");
1403
+ break;
1404
+ case t_boolean:
1405
+ w(g, "~M~W0 : Boolean;~N");
1406
+ break;
1407
+ }
1252
1408
  }
1253
1409
  }
1254
1410
 
1255
- w(g, "~-");
1411
+ if (!first) w(g, "~-");
1256
1412
  }
1257
1413
 
1258
1414
  static void generate_among_decls(struct generator * g) {
1259
1415
  struct among *a = g->analyser->amongs;
1416
+ if (a == NULL) return;
1260
1417
 
1261
1418
  w(g, "~Mprivate~N~+");
1262
1419
 
1263
- while (a != 0) {
1420
+ while (a != NULL) {
1264
1421
  g->I[0] = a->number;
1265
1422
  w(g, "~Ma_~I0 : Array Of TAmong;~N");
1266
1423
  a = a->next;
@@ -1270,33 +1427,33 @@ static void generate_among_decls(struct generator * g) {
1270
1427
  }
1271
1428
 
1272
1429
  static void generate_among_table(struct generator * g, struct among * x) {
1273
- int i;
1430
+ write_comment(g, x->node);
1431
+
1274
1432
  struct amongvec * v = x->b;
1275
1433
 
1276
1434
  g->I[0] = x->number;
1277
1435
  g->I[1] = x->literalstring_count;
1278
1436
 
1279
1437
  w(g, "~MSetLength(a_~I0, ~I1);~N~+");
1280
-
1281
- for (i = 0; i < x->literalstring_count; i++, v++) {
1438
+ for (int i = 0; i < x->literalstring_count; i++) {
1282
1439
  g->I[1] = i;
1283
1440
 
1284
1441
  /* Write among's string. */
1285
- g->L[0] = v->b;
1442
+ g->L[0] = v[i].b;
1286
1443
  w(g, "~Ma_~I0[~I1].Str := ~L0;~N");
1287
1444
 
1288
1445
  /* Write among's index & result. */
1289
- g->I[2] = v->i;
1446
+ g->I[2] = v[i].i;
1290
1447
  w(g, "~Ma_~I0[~I1].Index := ~I2;~N");
1291
- g->I[2] = v->result;
1448
+ g->I[2] = v[i].result;
1292
1449
  w(g, "~Ma_~I0[~I1].Result := ~I2;~N");
1293
1450
 
1294
1451
  /* Write among's handler. */
1295
1452
  w(g, "~Ma_~I0[~I1].Method := ");
1296
- if (v->function == 0) {
1453
+ if (v[i].function == NULL) {
1297
1454
  w(g, "nil;~N~N");
1298
1455
  } else {
1299
- g->V[0] = v->function;
1456
+ g->V[0] = v[i].function;
1300
1457
  w(g, "Self.~W0;~N~N");
1301
1458
  }
1302
1459
  }
@@ -1304,10 +1461,8 @@ static void generate_among_table(struct generator * g, struct among * x) {
1304
1461
  }
1305
1462
 
1306
1463
  static void generate_amongs(struct generator * g) {
1307
- struct among * a = g->analyser->amongs;
1308
- while (a != 0) {
1309
- generate_among_table(g, a);
1310
- a = a->next;
1464
+ for (struct among * x = g->analyser->amongs; x; x = x->next) {
1465
+ generate_among_table(g, x);
1311
1466
  }
1312
1467
  }
1313
1468
 
@@ -1319,8 +1474,9 @@ static void generate_constructor(struct generator * g) {
1319
1474
 
1320
1475
  static void generate_methods(struct generator * g) {
1321
1476
  struct node * p = g->analyser->program;
1322
- while (p != 0) {
1477
+ while (p != NULL) {
1323
1478
  generate(g, p);
1479
+ g->unreachable = false;
1324
1480
  p = p->right;
1325
1481
  }
1326
1482
  }
@@ -1328,22 +1484,19 @@ static void generate_methods(struct generator * g) {
1328
1484
  static void set_bit(symbol * b, int i) { b[i/8] |= 1 << i%8; }
1329
1485
 
1330
1486
  static void generate_grouping_table(struct generator * g, struct grouping * q) {
1331
-
1332
1487
  int range = q->largest_ch - q->smallest_ch + 1;
1333
1488
  int size = (range + 7)/ 8; /* assume 8 bits per symbol */
1334
1489
  symbol * b = q->b;
1335
1490
  symbol * map = create_b(size);
1336
- int i;
1337
- for (i = 0; i < size; i++) map[i] = 0;
1338
1491
 
1339
- /* Using unicode would require revision here */
1492
+ for (int i = 0; i < size; i++) map[i] = 0;
1340
1493
 
1341
- for (i = 0; i < SIZE(b); i++) set_bit(map, b[i] - q->smallest_ch);
1494
+ for (int i = 0; i < SIZE(b); i++) set_bit(map, b[i] - q->smallest_ch);
1342
1495
 
1343
1496
  g->V[0] = q->name;
1344
1497
  g->I[0] = size - 1;
1345
1498
  w(g, "~N~MConst~+~N~M~W0 : Array [0..~I0] Of Char = (~N~+");
1346
- for (i = 0; i < size; i++) {
1499
+ for (int i = 0; i < size; i++) {
1347
1500
  if (i != 0) w(g, ",~N");
1348
1501
  g->I[0] = map[i];
1349
1502
  w(g, "~MChr(~I0)");
@@ -1354,8 +1507,7 @@ static void generate_grouping_table(struct generator * g, struct grouping * q) {
1354
1507
  }
1355
1508
 
1356
1509
  static void generate_groupings(struct generator * g) {
1357
- struct grouping * q;
1358
- for (q = g->analyser->groupings; q; q = q->next) {
1510
+ for (struct grouping * q = g->analyser->groupings; q; q = q->next) {
1359
1511
  if (q->name->used)
1360
1512
  generate_grouping_table(g, q);
1361
1513
  }