mittens 0.3.0 → 0.3.2
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/Gemfile +2 -1
- data/README.md +2 -2
- data/Rakefile +12 -5
- data/ext/mittens/extconf.rb +3 -1
- data/lib/mittens/version.rb +1 -1
- data/vendor/snowball/.github/workflows/ci.yml +144 -17
- data/vendor/snowball/.github/workflows/coverage.yml +117 -0
- data/vendor/snowball/.github/workflows/runtime-tests.yml +26 -0
- data/vendor/snowball/.gitignore +33 -7
- data/vendor/snowball/CONTRIBUTING.rst +7 -0
- data/vendor/snowball/COPYING +1 -1
- data/vendor/snowball/GNUmakefile +736 -298
- data/vendor/snowball/NEWS +1394 -7
- data/vendor/snowball/README.rst +8 -8
- data/vendor/snowball/ada/generate/generate.adb +5 -5
- data/vendor/snowball/ada/src/stemmer.adb +177 -188
- data/vendor/snowball/ada/src/stemmer.ads +86 -89
- data/vendor/snowball/ada/src/stemwords.adb +21 -5
- data/vendor/snowball/algorithms/czech.sbl +255 -0
- data/vendor/snowball/algorithms/danish.sbl +22 -10
- data/vendor/snowball/algorithms/english.sbl +7 -4
- data/vendor/snowball/algorithms/esperanto.sbl +6 -7
- data/vendor/snowball/algorithms/estonian.sbl +9 -4
- data/vendor/snowball/algorithms/finnish.sbl +33 -21
- data/vendor/snowball/algorithms/german.sbl +5 -0
- data/vendor/snowball/algorithms/indonesian.sbl +115 -96
- data/vendor/snowball/algorithms/italian.sbl +26 -1
- data/vendor/snowball/algorithms/lithuanian.sbl +13 -13
- data/vendor/snowball/algorithms/norwegian.sbl +17 -6
- data/vendor/snowball/algorithms/persian.sbl +387 -0
- data/vendor/snowball/algorithms/polish.sbl +177 -0
- data/vendor/snowball/algorithms/sesotho.sbl +115 -0
- data/vendor/snowball/algorithms/turkish.sbl +4 -4
- data/vendor/snowball/compiler/analyser.c +2002 -711
- data/vendor/snowball/compiler/driver.c +460 -298
- data/vendor/snowball/compiler/generator.c +439 -1965
- data/vendor/snowball/compiler/generator_ada.c +605 -430
- data/vendor/snowball/compiler/generator_c.c +2227 -0
- data/vendor/snowball/compiler/generator_csharp.c +365 -274
- data/vendor/snowball/compiler/generator_dart.c +1476 -0
- data/vendor/snowball/compiler/generator_go.c +348 -270
- data/vendor/snowball/compiler/generator_java.c +330 -233
- data/vendor/snowball/compiler/generator_js.c +534 -385
- data/vendor/snowball/compiler/generator_pascal.c +361 -320
- data/vendor/snowball/compiler/generator_php.c +1445 -0
- data/vendor/snowball/compiler/generator_python.c +399 -299
- data/vendor/snowball/compiler/generator_rust.c +370 -261
- data/vendor/snowball/compiler/generator_zig.c +1474 -0
- data/vendor/snowball/compiler/header.h +153 -86
- data/vendor/snowball/compiler/space.c +121 -63
- data/vendor/snowball/compiler/tokeniser.c +286 -182
- data/vendor/snowball/compiler/tokens.h +71 -0
- data/vendor/snowball/csharp/Snowball/Among.cs +14 -26
- data/vendor/snowball/csharp/Snowball/AssemblyInfo.cs +3 -3
- data/vendor/snowball/csharp/Snowball/Stemmer.cs +41 -45
- data/vendor/snowball/csharp/Stemwords/Program.cs +20 -14
- data/vendor/snowball/cxx/.gitignore +4 -0
- data/vendor/snowball/cxx/generate_algorithms.pl +87 -0
- data/vendor/snowball/cxx/stemmer.h +12 -0
- data/vendor/snowball/cxx/stemwords.cxx +176 -0
- data/vendor/snowball/cxx/utilities.cxx +2 -0
- data/vendor/snowball/dart/.gitignore +4 -0
- data/vendor/snowball/dart/analysis_options.yaml +1 -0
- data/vendor/snowball/dart/example/test_app.dart +65 -0
- data/vendor/snowball/dart/generate_algorithms.pl +21 -0
- data/vendor/snowball/dart/lib/snowball.dart +18 -0
- data/vendor/snowball/dart/lib/src/snowball.dart +339 -0
- data/vendor/snowball/dart/pubspec.yaml +17 -0
- data/vendor/snowball/doc/libstemmer_dart_README +37 -0
- data/vendor/snowball/doc/libstemmer_js_README +2 -2
- data/vendor/snowball/doc/libstemmer_php_README +38 -0
- data/vendor/snowball/doc/libstemmer_python_README +3 -3
- data/vendor/snowball/examples/stemwords.c +18 -3
- data/vendor/snowball/go/README.md +12 -4
- data/vendor/snowball/go/env.go +12 -14
- data/vendor/snowball/go/stemwords/main.go +2 -1
- data/vendor/snowball/java/org/tartarus/snowball/CharArraySequence.java +36 -0
- data/vendor/snowball/java/org/tartarus/snowball/SnowballProgram.java +17 -34
- data/vendor/snowball/java/org/tartarus/snowball/SnowballStemmer.java +0 -2
- data/vendor/snowball/javascript/base-stemmer.js +219 -252
- data/vendor/snowball/javascript/stemwords.js +86 -58
- data/vendor/snowball/libstemmer/mkmodules.pl +1 -1
- data/vendor/snowball/libstemmer/modules.txt +4 -0
- data/vendor/snowball/pascal/SnowballProgram.pas +18 -31
- data/vendor/snowball/php/base-stemmer.php +453 -0
- data/vendor/snowball/php/stemwords.php +25 -0
- data/vendor/snowball/python/create_init.py +16 -21
- data/vendor/snowball/python/pyproject.toml +3 -0
- data/vendor/snowball/python/setup.py +5 -7
- data/vendor/snowball/python/snowballstemmer/among.py +1 -2
- data/vendor/snowball/python/snowballstemmer/basestemmer.py +24 -33
- data/vendor/snowball/python/stemwords.py +72 -63
- data/vendor/snowball/runtime/api.c +11 -42
- data/vendor/snowball/runtime/api.h +11 -9
- data/vendor/snowball/runtime/snowball_runtime.h +110 -0
- data/vendor/snowball/runtime/utilities.c +282 -106
- data/vendor/snowball/rust/src/main.rs +2 -2
- data/vendor/snowball/rust/src/snowball/snowball_env.rs +7 -9
- data/vendor/snowball/tests/compilertest +62 -0
- data/vendor/snowball/tests/errors/ae-errors.sbl +53 -0
- data/vendor/snowball/tests/errors/ae-errors.stderr +8 -0
- data/vendor/snowball/tests/errors/bad-dollar.sbl +14 -0
- data/vendor/snowball/tests/errors/bad-dollar.stderr +4 -0
- data/vendor/snowball/tests/errors/bad-grouping-definition.sbl +9 -0
- data/vendor/snowball/tests/errors/bad-grouping-definition.stderr +6 -0
- data/vendor/snowball/tests/errors/missing-bra.sbl +6 -0
- data/vendor/snowball/tests/errors/missing-bra.stderr +3 -0
- data/vendor/snowball/tests/errors/missing-command.sbl +9 -0
- data/vendor/snowball/tests/errors/missing-command.stderr +1 -0
- data/vendor/snowball/tests/errors/missing-ket-backwardmode.sbl +3 -0
- data/vendor/snowball/tests/errors/missing-ket-backwardmode.stderr +1 -0
- data/vendor/snowball/tests/errors/missing-ket.sbl +7 -0
- data/vendor/snowball/tests/errors/missing-ket.stderr +6 -0
- data/vendor/snowball/tests/errors/notdefined.sbl +4 -0
- data/vendor/snowball/tests/errors/notdefined.stderr +2 -0
- data/vendor/snowball/tests/errors/string-omitted.sbl +5 -0
- data/vendor/snowball/tests/errors/string-omitted.stderr +1 -0
- data/vendor/snowball/tests/errors/undeclared.sbl +20 -0
- data/vendor/snowball/tests/errors/undeclared.stderr +9 -0
- data/vendor/snowball/tests/errors/unexpected-token.sbl +24 -0
- data/vendor/snowball/tests/errors/unexpected-token.stderr +17 -0
- data/vendor/snowball/tests/errors/wrongdirection.sbl +14 -0
- data/vendor/snowball/tests/errors/wrongdirection.stderr +1 -0
- data/vendor/snowball/tests/runtime/among.sbl +19 -0
- data/vendor/snowball/tests/runtime/arithmeticexpr.sbl +86 -0
- data/vendor/snowball/tests/runtime/attachinsert.sbl +47 -0
- data/vendor/snowball/tests/runtime/booleans.sbl +19 -0
- data/vendor/snowball/tests/runtime/externals.sbl +22 -0
- data/vendor/snowball/tests/runtime/hop.sbl +12 -0
- data/vendor/snowball/tests/runtime/integertests.sbl +60 -0
- data/vendor/snowball/tests/runtime/intlimits.sbl +25 -0
- data/vendor/snowball/tests/runtime/naming.sbl +20 -0
- data/vendor/snowball/tests/runtime/not.sbl +30 -0
- data/vendor/snowball/tests/runtime/or.sbl +17 -0
- data/vendor/snowball/tests/runtime/repeat.sbl +16 -0
- data/vendor/snowball/tests/runtime/setlimit.sbl +24 -0
- data/vendor/snowball/tests/runtime/sizelen.sbl +56 -0
- data/vendor/snowball/tests/runtime/slice.sbl +27 -0
- data/vendor/snowball/tests/runtime/stringdollar.sbl +39 -0
- data/vendor/snowball/tests/runtime/strings.sbl +66 -0
- data/vendor/snowball/tests/runtime/test.sbl +19 -0
- data/vendor/snowball/tests/stemtest.c +41 -1
- data/vendor/snowball/tests/syntax/canon.sbl +32 -0
- data/vendor/snowball/tests/syntax/canon.stderr +0 -0
- data/vendor/snowball/tests/syntax/canon.syntax +57 -0
- data/vendor/snowball/tests/syntax/emptyprogram.sbl +2 -0
- data/vendor/snowball/tests/syntax/emptyprogram.syntax +0 -0
- data/vendor/snowball/tests/syntax/groupings.sbl +11 -0
- data/vendor/snowball/tests/syntax/inline.sbl +144 -0
- data/vendor/snowball/tests/syntax/inline.stderr +0 -0
- data/vendor/snowball/tests/syntax/inline.syntax +121 -0
- data/vendor/snowball/tests/syntax/legacy.sbl +17 -0
- data/vendor/snowball/tests/syntax/legacy.stderr +5 -0
- data/vendor/snowball/tests/syntax/legacy.syntax +19 -0
- data/vendor/snowball/tests/syntax/loops.sbl +14 -0
- data/vendor/snowball/tests/syntax/loops.stderr +9 -0
- data/vendor/snowball/tests/syntax/loops.syntax +29 -0
- data/vendor/snowball/tests/syntax/noops.sbl +76 -0
- data/vendor/snowball/tests/syntax/noops.stderr +27 -0
- data/vendor/snowball/tests/syntax/noops.syntax +135 -0
- data/vendor/snowball/tests/syntax/simplifyae.sbl +21 -0
- data/vendor/snowball/tests/syntax/simplifyae.stderr +0 -0
- data/vendor/snowball/tests/syntax/simplifyae.syntax +39 -0
- data/vendor/snowball/tests/syntax/unused.sbl +18 -0
- data/vendor/snowball/tests/syntax/unused.stderr +7 -0
- data/vendor/snowball/tests/syntax/unused.syntax +3 -0
- data/vendor/snowball/zig/env.zig +599 -0
- data/vendor/snowball/zig/generate_algorithms.pl +19 -0
- data/vendor/snowball/zig/stemwords.zig +123 -0
- metadata +102 -4
- data/vendor/snowball/compiler/syswords.h +0 -86
- data/vendor/snowball/runtime/header.h +0 -62
|
@@ -1,34 +1,67 @@
|
|
|
1
1
|
#include <assert.h>
|
|
2
|
+
#include <ctype.h>
|
|
3
|
+
#include <stdio.h> /* for fprintf etc */
|
|
2
4
|
#include <stdlib.h> /* for exit */
|
|
3
5
|
#include <string.h> /* for strlen */
|
|
4
|
-
#include <stdio.h> /* for fprintf etc */
|
|
5
|
-
#include <ctype.h>
|
|
6
6
|
#include "header.h"
|
|
7
7
|
|
|
8
|
-
/*
|
|
8
|
+
/* prototype functions for recursive use: */
|
|
9
9
|
|
|
10
10
|
static void generate(struct generator * g, struct node * p);
|
|
11
11
|
static void w(struct generator * g, const char * s);
|
|
12
12
|
static void writef(struct generator * g, const char * s, struct node * p);
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
return g->next_label++;
|
|
16
|
-
}
|
|
14
|
+
/* Write routines for items from the syntax tree */
|
|
17
15
|
|
|
18
|
-
static
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
16
|
+
static void write_relop(struct generator * g, int relop) {
|
|
17
|
+
// Relational operators are the same as C, save for (in-)equality.
|
|
18
|
+
switch (relop) {
|
|
19
|
+
case c_eq: write_string(g, " = "); break;
|
|
20
|
+
case c_ne: write_string(g, " /= "); break;
|
|
21
|
+
default: write_c_relop(g, relop);
|
|
22
|
+
}
|
|
25
23
|
}
|
|
26
24
|
|
|
27
|
-
/* Write routines for items from the syntax tree */
|
|
28
|
-
|
|
29
25
|
static void write_varname(struct generator * g, struct name * p) {
|
|
30
|
-
|
|
26
|
+
int ends_in_underscore = (p->s[SIZE(p->s) - 1] == '_');
|
|
27
|
+
if (p->type == t_external) {
|
|
28
|
+
if (g->options->externals_prefix) {
|
|
29
|
+
write_string(g, g->options->externals_prefix);
|
|
30
|
+
}
|
|
31
|
+
} else {
|
|
32
|
+
/* Ada identifiers are case-insensitive but Snowball identifiers
|
|
33
|
+
* should be case-sensitive. To address this, if any groups of
|
|
34
|
+
* identifiers of the same type have the same case, we insert a counter
|
|
35
|
+
* after the type-code for all but one of them. This count is unique
|
|
36
|
+
* within each type of variable so this avoid collisions while being
|
|
37
|
+
* minimally intrusive on the readability of the generated code.
|
|
38
|
+
*
|
|
39
|
+
* Ada also doesn't allow identifiers to end in an underscore,
|
|
40
|
+
* so we append a `E` to such identifiers. To avoid potential
|
|
41
|
+
* collisions from doing so, we also insert the counter after
|
|
42
|
+
* the type-code in this case (which may not be necessary, but this
|
|
43
|
+
* case seems more of a theoretical concern, whereas identifiers
|
|
44
|
+
* differing only by case has been seen in real-world Snowball code).
|
|
45
|
+
*
|
|
46
|
+
* So for example (noting that we upper-case the first character of
|
|
47
|
+
* the Snowball name below):
|
|
48
|
+
*
|
|
49
|
+
* Snowball integer `i` -> Ada `I_I`
|
|
50
|
+
* Snowball integer `I` -> Ada `I2_I`
|
|
51
|
+
* Snowball integer `i_` -> Ada `I3_I_E`
|
|
52
|
+
* Snowball integer `i_e` -> Ada `I_I_e`
|
|
53
|
+
*
|
|
54
|
+
* We don't try to solve this problem for external identifiers - it
|
|
55
|
+
* seems more helpful to leave those alone and encourage snowball
|
|
56
|
+
* program authors to avoid naming externals which only differ by
|
|
57
|
+
* case.
|
|
58
|
+
*
|
|
59
|
+
* We use the same naming scheme for both global and local variables.
|
|
60
|
+
*/
|
|
31
61
|
write_char(g, "SBIRXG"[p->type]);
|
|
62
|
+
if (ends_in_underscore || p->case_collision) {
|
|
63
|
+
write_int(g, p->count);
|
|
64
|
+
}
|
|
32
65
|
write_char(g, '_');
|
|
33
66
|
}
|
|
34
67
|
|
|
@@ -39,52 +72,61 @@ static void write_varname(struct generator * g, struct name * p) {
|
|
|
39
72
|
p->s[0] = save_initial;
|
|
40
73
|
}
|
|
41
74
|
|
|
42
|
-
if (
|
|
43
|
-
write_char(g, 'E');
|
|
44
|
-
}
|
|
75
|
+
if (ends_in_underscore) write_char(g, 'E');
|
|
45
76
|
}
|
|
46
77
|
|
|
47
|
-
|
|
48
|
-
|
|
78
|
+
/* Reference to variable, e.g. when assigning to or using in an expression. */
|
|
79
|
+
static void write_varref(struct generator * g, struct name * p) {
|
|
80
|
+
if (p->type < t_routine && p->local_to == NULL) {
|
|
81
|
+
write_string(g, "Z.");
|
|
82
|
+
}
|
|
49
83
|
write_varname(g, p);
|
|
50
84
|
}
|
|
51
85
|
|
|
52
86
|
static void write_literal_string(struct generator * g, symbol * p) {
|
|
87
|
+
if (SIZE(p) == 0) {
|
|
88
|
+
write_string(g, "\"\"");
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
53
91
|
// Ada supports UTF-8 literal strings, we only need to escape the quote and
|
|
54
92
|
// special characters.
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
93
|
+
bool in_quotes = false;
|
|
94
|
+
int i = 0;
|
|
95
|
+
while (i < SIZE(p)) {
|
|
96
|
+
int ch;
|
|
97
|
+
int w = get_utf8(p + i, &ch);
|
|
98
|
+
// Write out ASCII and lower Unicode printables as literal characters.
|
|
99
|
+
// Use escapes for anything over 0x590 as a crude way to avoid LTR
|
|
100
|
+
// characters affecting the rendering of source character order in
|
|
101
|
+
// confusing ways.
|
|
102
|
+
if ((32 <= ch && ch < 127) || (0xa0 < ch && ch < 0x590)) {
|
|
103
|
+
if (!in_quotes) {
|
|
104
|
+
if (i > 0) {
|
|
105
|
+
write_string(g, " & ");
|
|
106
|
+
}
|
|
107
|
+
write_char(g, '"');
|
|
108
|
+
in_quotes = true;
|
|
109
|
+
}
|
|
110
|
+
if (ch == '"') write_char(g, '\\');
|
|
111
|
+
write_wchar_as_utf8(g, ch);
|
|
65
112
|
} else {
|
|
66
|
-
|
|
67
|
-
|
|
113
|
+
if (in_quotes) {
|
|
114
|
+
write_char(g, '"');
|
|
115
|
+
in_quotes = false;
|
|
116
|
+
}
|
|
117
|
+
for (int j = i; j < i + w; ++j) {
|
|
118
|
+
if (j > 0) {
|
|
119
|
+
write_string(g, " & ");
|
|
120
|
+
}
|
|
121
|
+
write_string(g, "Character'Val(");
|
|
122
|
+
write_int(g, (int)p[j]);
|
|
123
|
+
write_string(g, ")");
|
|
124
|
+
}
|
|
68
125
|
}
|
|
126
|
+
i += w;
|
|
69
127
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
static void write_margin(struct generator * g) {
|
|
74
|
-
for (int i = 0; i < g->margin; i++) write_string(g, " ");
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
static void write_relop(struct generator * g, int relop) {
|
|
78
|
-
switch (relop) {
|
|
79
|
-
case c_eq: write_string(g, " = "); break;
|
|
80
|
-
case c_ne: write_string(g, " /= "); break;
|
|
81
|
-
case c_gt: write_string(g, " > "); break;
|
|
82
|
-
case c_ge: write_string(g, " >= "); break;
|
|
83
|
-
case c_lt: write_string(g, " < "); break;
|
|
84
|
-
case c_le: write_string(g, " <= "); break;
|
|
85
|
-
default:
|
|
86
|
-
fprintf(stderr, "Unexpected type #%d in generate_integer_test\n", relop);
|
|
87
|
-
exit(1);
|
|
128
|
+
if (in_quotes) {
|
|
129
|
+
write_char(g, '"');
|
|
88
130
|
}
|
|
89
131
|
}
|
|
90
132
|
|
|
@@ -96,7 +138,7 @@ static void write_declare(struct generator * g,
|
|
|
96
138
|
g->outbuf = g->declarations;
|
|
97
139
|
write_string(g, " ");
|
|
98
140
|
writef(g, declaration, p);
|
|
99
|
-
|
|
141
|
+
write_char(g, ';');
|
|
100
142
|
write_newline(g);
|
|
101
143
|
g->outbuf = temp;
|
|
102
144
|
}
|
|
@@ -105,7 +147,7 @@ static void write_comment(struct generator * g, struct node * p) {
|
|
|
105
147
|
if (!g->options->comments) return;
|
|
106
148
|
write_margin(g);
|
|
107
149
|
write_string(g, "-- ");
|
|
108
|
-
write_comment_content(g, p);
|
|
150
|
+
write_comment_content(g, p, NULL);
|
|
109
151
|
write_newline(g);
|
|
110
152
|
}
|
|
111
153
|
|
|
@@ -130,7 +172,7 @@ static void append_restore_string(struct node * p, struct str * out, struct str
|
|
|
130
172
|
str_append_string(out, "Z.C := ");
|
|
131
173
|
if (p->mode != m_forward) str_append_string(out, "Z.L - ");
|
|
132
174
|
str_append(out, savevar);
|
|
133
|
-
|
|
175
|
+
str_append_ch(out, ';');
|
|
134
176
|
}
|
|
135
177
|
|
|
136
178
|
static void write_restorecursor(struct generator * g, struct node * p, struct str * savevar) {
|
|
@@ -146,15 +188,6 @@ static void wsetl(struct generator * g, int n) {
|
|
|
146
188
|
write_int(g, n);
|
|
147
189
|
write_string(g, ">>");
|
|
148
190
|
write_newline(g);
|
|
149
|
-
g->line_labelled = g->line_count;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
static void wgotol(struct generator * g, int n) {
|
|
153
|
-
write_margin(g);
|
|
154
|
-
write_string(g, "goto lab");
|
|
155
|
-
write_int(g, n);
|
|
156
|
-
write_string(g, ";");
|
|
157
|
-
write_newline(g);
|
|
158
191
|
}
|
|
159
192
|
|
|
160
193
|
static void write_failure(struct generator * g) {
|
|
@@ -174,7 +207,7 @@ static void write_failure(struct generator * g) {
|
|
|
174
207
|
default:
|
|
175
208
|
write_string(g, "goto lab");
|
|
176
209
|
write_int(g, g->failure_label);
|
|
177
|
-
|
|
210
|
+
write_char(g, ';');
|
|
178
211
|
g->label_used = 1;
|
|
179
212
|
}
|
|
180
213
|
write_newline(g);
|
|
@@ -190,18 +223,8 @@ static void write_failure_if(struct generator * g, const char * s, struct node *
|
|
|
190
223
|
g->unreachable = false;
|
|
191
224
|
}
|
|
192
225
|
|
|
193
|
-
/* if at limit fail */
|
|
194
|
-
static void write_check_limit(struct generator * g, struct node * p) {
|
|
195
|
-
if (p->mode == m_forward) {
|
|
196
|
-
write_failure_if(g, "Z.C >= Z.L", p);
|
|
197
|
-
} else {
|
|
198
|
-
write_failure_if(g, "Z.C <= Z.Lb", p);
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
|
|
202
226
|
/* Formatted write. */
|
|
203
227
|
static void writef(struct generator * g, const char * input, struct node * p) {
|
|
204
|
-
(void)p;
|
|
205
228
|
int i = 0;
|
|
206
229
|
|
|
207
230
|
while (input[i]) {
|
|
@@ -246,26 +269,17 @@ static void writef(struct generator * g, const char * input, struct node * p) {
|
|
|
246
269
|
continue;
|
|
247
270
|
}
|
|
248
271
|
case 'V':
|
|
249
|
-
|
|
250
|
-
int j = input[i++] - '0';
|
|
251
|
-
if (j < 0 || j > (int)(sizeof(g->V) / sizeof(g->V[0])))
|
|
252
|
-
goto invalid_escape2;
|
|
253
|
-
if (ch == 'V')
|
|
254
|
-
write_varref(g, g->V[j]);
|
|
255
|
-
else
|
|
256
|
-
write_varname(g, g->V[j]);
|
|
272
|
+
write_varref(g, p->name);
|
|
257
273
|
continue;
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
write_literal_string(g, g->L[j]);
|
|
274
|
+
case 'W':
|
|
275
|
+
write_varname(g, p->name);
|
|
276
|
+
continue;
|
|
277
|
+
case 'L':
|
|
278
|
+
write_literal_string(g, p->literalstring);
|
|
264
279
|
continue;
|
|
265
|
-
}
|
|
266
280
|
case '+': g->margin++; continue;
|
|
267
281
|
case '-': g->margin--; continue;
|
|
268
|
-
case 'n':
|
|
282
|
+
case 'n': write_s(g, g->options->name); continue;
|
|
269
283
|
default:
|
|
270
284
|
printf("Invalid escape sequence ~%c in writef(g, \"%s\", p)\n",
|
|
271
285
|
ch, input);
|
|
@@ -302,7 +316,8 @@ static void generate_AE(struct generator * g, struct node * p) {
|
|
|
302
316
|
const char * s;
|
|
303
317
|
switch (p->type) {
|
|
304
318
|
case c_name:
|
|
305
|
-
write_varref(g, p->name);
|
|
319
|
+
write_varref(g, p->name);
|
|
320
|
+
break;
|
|
306
321
|
case c_number:
|
|
307
322
|
// Avoid `parentheses required for unary minus` error from gnat.
|
|
308
323
|
if (p->number < 0)
|
|
@@ -312,41 +327,51 @@ static void generate_AE(struct generator * g, struct node * p) {
|
|
|
312
327
|
write_char(g, ')');
|
|
313
328
|
break;
|
|
314
329
|
case c_maxint:
|
|
315
|
-
write_string(g, "Integer'Last");
|
|
330
|
+
write_string(g, "Integer'Last");
|
|
331
|
+
break;
|
|
316
332
|
case c_minint:
|
|
317
|
-
write_string(g, "Integer'First");
|
|
333
|
+
write_string(g, "Integer'First");
|
|
334
|
+
break;
|
|
318
335
|
case c_neg:
|
|
319
|
-
write_string(g, "(-");
|
|
336
|
+
write_string(g, "(-");
|
|
337
|
+
generate_AE(g, p->right);
|
|
338
|
+
write_char(g, ')');
|
|
339
|
+
break;
|
|
320
340
|
case c_multiply:
|
|
321
|
-
s = " * ";
|
|
322
|
-
|
|
323
|
-
s = " + "; goto label0;
|
|
324
|
-
case c_minus:
|
|
325
|
-
s = " - "; goto label0;
|
|
341
|
+
s = " * ";
|
|
342
|
+
goto label0;
|
|
326
343
|
case c_divide:
|
|
327
344
|
s = " / ";
|
|
345
|
+
goto label0;
|
|
346
|
+
case c_plus:
|
|
347
|
+
s = " + ";
|
|
348
|
+
goto label0;
|
|
349
|
+
case c_minus:
|
|
350
|
+
s = " - ";
|
|
328
351
|
label0:
|
|
329
|
-
write_char(g, '(');
|
|
330
|
-
|
|
352
|
+
write_char(g, '(');
|
|
353
|
+
generate_AE(g, p->left);
|
|
354
|
+
write_string(g, s);
|
|
355
|
+
generate_AE(g, p->right);
|
|
356
|
+
write_char(g, ')');
|
|
357
|
+
break;
|
|
331
358
|
case c_cursor:
|
|
332
|
-
w(g, "Z.C");
|
|
359
|
+
w(g, "Z.C");
|
|
360
|
+
break;
|
|
333
361
|
case c_limit:
|
|
334
|
-
w(g, p->mode == m_forward ? "Z.L" : "Z.Lb");
|
|
362
|
+
w(g, p->mode == m_forward ? "Z.L" : "Z.Lb");
|
|
363
|
+
break;
|
|
335
364
|
case c_len:
|
|
336
|
-
w(g, "Length_Utf8 (Z)");
|
|
365
|
+
w(g, "Length_Utf8 (Z.P, Z.Len)");
|
|
337
366
|
break;
|
|
338
367
|
case c_size:
|
|
339
368
|
w(g, "Z.Len");
|
|
340
369
|
break;
|
|
341
370
|
case c_lenof:
|
|
342
|
-
g
|
|
343
|
-
w(g, "Length_Utf8 (Ada.Strings.Unbounded.To_String (~V0))");
|
|
371
|
+
writef(g, "Length_Utf8 (~V, Z.L~W)", p);
|
|
344
372
|
break;
|
|
345
373
|
case c_sizeof:
|
|
346
|
-
g
|
|
347
|
-
w(g, "Ada.Strings.Unbounded.Length (~V0)");
|
|
348
|
-
break;
|
|
349
|
-
default:
|
|
374
|
+
writef(g, "Z.L~W", p);
|
|
350
375
|
break;
|
|
351
376
|
}
|
|
352
377
|
}
|
|
@@ -362,13 +387,15 @@ static void generate_bra(struct generator * g, struct node * p) {
|
|
|
362
387
|
|
|
363
388
|
static void generate_and(struct generator * g, struct node * p) {
|
|
364
389
|
struct str * savevar = NULL;
|
|
365
|
-
if (
|
|
390
|
+
if (K_needed_for_and(p->left)) {
|
|
366
391
|
savevar = vars_newname(g);
|
|
367
392
|
}
|
|
368
393
|
|
|
369
394
|
write_comment(g, p);
|
|
370
395
|
|
|
371
|
-
if (savevar)
|
|
396
|
+
if (savevar) {
|
|
397
|
+
write_savecursor(g, p, savevar);
|
|
398
|
+
}
|
|
372
399
|
|
|
373
400
|
p = p->left;
|
|
374
401
|
while (p) {
|
|
@@ -385,20 +412,22 @@ static void generate_and(struct generator * g, struct node * p) {
|
|
|
385
412
|
|
|
386
413
|
static void generate_or(struct generator * g, struct node * p) {
|
|
387
414
|
struct str * savevar = NULL;
|
|
388
|
-
if (
|
|
415
|
+
if (K_needed_for_or(p->left)) {
|
|
389
416
|
savevar = vars_newname(g);
|
|
390
417
|
}
|
|
391
|
-
int used = g->label_used;
|
|
392
418
|
|
|
419
|
+
int used = g->label_used;
|
|
393
420
|
int a0 = g->failure_label;
|
|
394
421
|
struct str * a1 = str_copy(g->failure_str);
|
|
395
422
|
|
|
396
|
-
|
|
397
|
-
int end_unreachable = true;
|
|
423
|
+
bool end_unreachable = true;
|
|
398
424
|
|
|
399
425
|
write_comment(g, p);
|
|
426
|
+
w(g, "~Mloop~N~+");
|
|
400
427
|
|
|
401
|
-
if (savevar
|
|
428
|
+
if (savevar && K_needed_node_on_f(p)) {
|
|
429
|
+
write_savecursor(g, p, savevar);
|
|
430
|
+
}
|
|
402
431
|
|
|
403
432
|
p = p->left;
|
|
404
433
|
str_clear(g->failure_str);
|
|
@@ -409,28 +438,36 @@ static void generate_or(struct generator * g, struct node * p) {
|
|
|
409
438
|
fprintf(stderr, "Error: \"or\" node without children nodes.");
|
|
410
439
|
exit(1);
|
|
411
440
|
}
|
|
412
|
-
while (p->right) {
|
|
413
|
-
|
|
441
|
+
while (p->right != NULL) {
|
|
442
|
+
int label = new_label(g);
|
|
443
|
+
g->failure_label = label;
|
|
414
444
|
g->label_used = 0;
|
|
415
445
|
generate(g, p);
|
|
416
446
|
if (!g->unreachable) {
|
|
417
|
-
|
|
447
|
+
w(g, "~Mexit;~N");
|
|
418
448
|
end_unreachable = false;
|
|
419
449
|
}
|
|
420
450
|
|
|
421
451
|
if (g->label_used)
|
|
422
452
|
wsetl(g, g->failure_label);
|
|
423
453
|
g->unreachable = false;
|
|
424
|
-
if (savevar)
|
|
454
|
+
if (savevar) {
|
|
455
|
+
write_restorecursor(g, p, savevar);
|
|
456
|
+
}
|
|
425
457
|
p = p->right;
|
|
426
458
|
}
|
|
459
|
+
|
|
427
460
|
g->label_used = used;
|
|
428
461
|
g->failure_label = a0;
|
|
429
462
|
str_delete(g->failure_str);
|
|
430
463
|
g->failure_str = a1;
|
|
431
464
|
|
|
432
465
|
generate(g, p);
|
|
433
|
-
|
|
466
|
+
|
|
467
|
+
if (!g->unreachable) {
|
|
468
|
+
w(g, "~Mexit;~N");
|
|
469
|
+
}
|
|
470
|
+
w(g, "~-~Mend loop;~N");
|
|
434
471
|
if (!end_unreachable) {
|
|
435
472
|
g->unreachable = false;
|
|
436
473
|
}
|
|
@@ -449,7 +486,7 @@ static void generate_backwards(struct generator * g, struct node * p) {
|
|
|
449
486
|
|
|
450
487
|
static void generate_not(struct generator * g, struct node * p) {
|
|
451
488
|
struct str * savevar = NULL;
|
|
452
|
-
if (
|
|
489
|
+
if (K_needed_node_on_f(p->left)) {
|
|
453
490
|
savevar = vars_newname(g);
|
|
454
491
|
}
|
|
455
492
|
|
|
@@ -461,7 +498,8 @@ static void generate_not(struct generator * g, struct node * p) {
|
|
|
461
498
|
write_savecursor(g, p, savevar);
|
|
462
499
|
}
|
|
463
500
|
|
|
464
|
-
|
|
501
|
+
int label = new_label(g);
|
|
502
|
+
g->failure_label = label;
|
|
465
503
|
str_clear(g->failure_str);
|
|
466
504
|
|
|
467
505
|
int l = g->failure_label;
|
|
@@ -487,11 +525,12 @@ static void generate_not(struct generator * g, struct node * p) {
|
|
|
487
525
|
|
|
488
526
|
static void generate_try(struct generator * g, struct node * p) {
|
|
489
527
|
struct str * savevar = NULL;
|
|
490
|
-
if (K_needed(
|
|
528
|
+
if (K_needed(p->left)) {
|
|
491
529
|
savevar = vars_newname(g);
|
|
492
530
|
}
|
|
493
531
|
|
|
494
|
-
|
|
532
|
+
int label = new_label(g);
|
|
533
|
+
g->failure_label = label;
|
|
495
534
|
g->label_used = 0;
|
|
496
535
|
str_clear(g->failure_str);
|
|
497
536
|
|
|
@@ -502,6 +541,7 @@ static void generate_try(struct generator * g, struct node * p) {
|
|
|
502
541
|
}
|
|
503
542
|
|
|
504
543
|
generate(g, p->left);
|
|
544
|
+
|
|
505
545
|
if (g->label_used)
|
|
506
546
|
wsetl(g, g->failure_label);
|
|
507
547
|
g->unreachable = false;
|
|
@@ -513,14 +553,12 @@ static void generate_try(struct generator * g, struct node * p) {
|
|
|
513
553
|
|
|
514
554
|
static void generate_set(struct generator * g, struct node * p) {
|
|
515
555
|
write_comment(g, p);
|
|
516
|
-
g
|
|
517
|
-
writef(g, "~M~V0 := True;~N", p);
|
|
556
|
+
writef(g, "~M~V := True;~N", p);
|
|
518
557
|
}
|
|
519
558
|
|
|
520
559
|
static void generate_unset(struct generator * g, struct node * p) {
|
|
521
560
|
write_comment(g, p);
|
|
522
|
-
g
|
|
523
|
-
writef(g, "~M~V0 := False;~N", p);
|
|
561
|
+
writef(g, "~M~V := False;~N", p);
|
|
524
562
|
}
|
|
525
563
|
|
|
526
564
|
static void generate_fail(struct generator * g, struct node * p) {
|
|
@@ -530,10 +568,9 @@ static void generate_fail(struct generator * g, struct node * p) {
|
|
|
530
568
|
}
|
|
531
569
|
|
|
532
570
|
/* generate_test() also implements 'reverse' */
|
|
533
|
-
|
|
534
571
|
static void generate_test(struct generator * g, struct node * p) {
|
|
535
572
|
struct str * savevar = NULL;
|
|
536
|
-
if (K_needed(
|
|
573
|
+
if (K_needed(p->left)) {
|
|
537
574
|
savevar = vars_newname(g);
|
|
538
575
|
}
|
|
539
576
|
|
|
@@ -555,23 +592,26 @@ static void generate_test(struct generator * g, struct node * p) {
|
|
|
555
592
|
|
|
556
593
|
static void generate_do(struct generator * g, struct node * p) {
|
|
557
594
|
struct str * savevar = NULL;
|
|
558
|
-
if (K_needed(
|
|
595
|
+
if (K_needed(p->left)) {
|
|
559
596
|
savevar = vars_newname(g);
|
|
560
597
|
}
|
|
561
598
|
|
|
562
599
|
write_comment(g, p);
|
|
563
|
-
if (savevar)
|
|
600
|
+
if (savevar) {
|
|
601
|
+
write_savecursor(g, p, savevar);
|
|
602
|
+
}
|
|
564
603
|
|
|
565
604
|
if (p->left->type == c_call) {
|
|
566
605
|
/* Optimise do <call> */
|
|
567
606
|
write_comment(g, p->left);
|
|
568
|
-
g
|
|
569
|
-
w(g, "~M~V0 (Z, Result);~N");
|
|
607
|
+
writef(g, "~M~V (Z, Result);~N", p->left);
|
|
570
608
|
} else {
|
|
571
|
-
|
|
609
|
+
int label = new_label(g);
|
|
610
|
+
g->failure_label = label;
|
|
572
611
|
str_clear(g->failure_str);
|
|
573
612
|
|
|
574
613
|
generate(g, p->left);
|
|
614
|
+
|
|
575
615
|
if (g->label_used)
|
|
576
616
|
wsetl(g, g->failure_label);
|
|
577
617
|
g->unreachable = false;
|
|
@@ -600,14 +640,13 @@ static void generate_GO_grouping(struct generator * g, struct node * p, int is_g
|
|
|
600
640
|
struct grouping * q = p->name->grouping;
|
|
601
641
|
g->S[0] = p->mode == m_forward ? "" : "_Backward";
|
|
602
642
|
g->S[1] = complement ? "In" : "Out";
|
|
603
|
-
g->V[0] = p->name;
|
|
604
643
|
g->I[0] = q->smallest_ch;
|
|
605
644
|
g->I[1] = q->largest_ch;
|
|
606
645
|
if (is_goto) {
|
|
607
|
-
writef(g, "~M~S1_Grouping~S0 (Z, ~
|
|
646
|
+
writef(g, "~M~S1_Grouping~S0 (Z, ~V, ~I0, ~I1, True, C);~N", p);
|
|
608
647
|
write_failure_if(g, "C < 0", p);
|
|
609
648
|
} else {
|
|
610
|
-
writef(g, "~M~S1_Grouping~S0 (Z, ~
|
|
649
|
+
writef(g, "~M~S1_Grouping~S0 (Z, ~V, ~I0, ~I1, True, C);~N", p);
|
|
611
650
|
write_failure_if(g, "C < 0", p);
|
|
612
651
|
|
|
613
652
|
if (p->mode == m_forward)
|
|
@@ -618,24 +657,24 @@ static void generate_GO_grouping(struct generator * g, struct node * p, int is_g
|
|
|
618
657
|
g->temporary_used = true;
|
|
619
658
|
}
|
|
620
659
|
|
|
621
|
-
static void generate_GO(struct generator * g, struct node * p, int
|
|
660
|
+
static void generate_GO(struct generator * g, struct node * p, int is_goto) {
|
|
622
661
|
write_comment(g, p);
|
|
623
662
|
|
|
624
663
|
int used = g->label_used;
|
|
625
|
-
|
|
626
664
|
int a0 = g->failure_label;
|
|
627
665
|
|
|
628
|
-
|
|
629
|
-
|
|
666
|
+
bool end_unreachable = false;
|
|
667
|
+
|
|
630
668
|
w(g, "~Mloop~N~+");
|
|
631
669
|
|
|
632
670
|
struct str * savevar = NULL;
|
|
633
|
-
if (
|
|
671
|
+
if (is_goto || repeat_restore(p->left)) {
|
|
634
672
|
savevar = vars_newname(g);
|
|
635
673
|
write_savecursor(g, p, savevar);
|
|
636
674
|
}
|
|
637
675
|
|
|
638
|
-
|
|
676
|
+
int label = new_label(g);
|
|
677
|
+
g->failure_label = label;
|
|
639
678
|
g->label_used = 0;
|
|
640
679
|
str_clear(g->failure_str);
|
|
641
680
|
generate(g, p->left);
|
|
@@ -646,10 +685,10 @@ static void generate_GO(struct generator * g, struct node * p, int style) {
|
|
|
646
685
|
end_unreachable = true;
|
|
647
686
|
} else {
|
|
648
687
|
/* include for goto; omit for gopast */
|
|
649
|
-
if (
|
|
650
|
-
g->I[0] = golab;
|
|
688
|
+
if (is_goto) write_restorecursor(g, p, savevar);
|
|
651
689
|
w(g, "~Mexit;~N");
|
|
652
690
|
}
|
|
691
|
+
|
|
653
692
|
g->unreachable = false;
|
|
654
693
|
if (g->label_used)
|
|
655
694
|
wsetl(g, g->failure_label);
|
|
@@ -657,10 +696,10 @@ static void generate_GO(struct generator * g, struct node * p, int style) {
|
|
|
657
696
|
write_restorecursor(g, p, savevar);
|
|
658
697
|
str_delete(savevar);
|
|
659
698
|
}
|
|
699
|
+
|
|
660
700
|
g->label_used = used;
|
|
661
701
|
g->failure_label = a0;
|
|
662
702
|
|
|
663
|
-
write_check_limit(g, p);
|
|
664
703
|
generate_next(g, p);
|
|
665
704
|
|
|
666
705
|
w(g, "~-~Mend loop;~N");
|
|
@@ -669,8 +708,8 @@ static void generate_GO(struct generator * g, struct node * p, int style) {
|
|
|
669
708
|
}
|
|
670
709
|
|
|
671
710
|
static void generate_loop(struct generator * g, struct node * p) {
|
|
672
|
-
struct str * loopvar = vars_newname(g);
|
|
673
711
|
write_comment(g, p);
|
|
712
|
+
struct str * loopvar = vars_newname(g);
|
|
674
713
|
g->B[0] = str_data(loopvar);
|
|
675
714
|
w(g, "~Mfor ~B0 in reverse 1 .. ");
|
|
676
715
|
generate_AE(g, p->AE);
|
|
@@ -686,16 +725,23 @@ static void generate_loop(struct generator * g, struct node * p) {
|
|
|
686
725
|
static void generate_repeat_or_atleast(struct generator * g, struct node * p, struct str * loopvar) {
|
|
687
726
|
int replab = new_label(g);
|
|
688
727
|
wsetl(g, replab);
|
|
728
|
+
// We only actually loop via `goto` to replab, but if we don't generate
|
|
729
|
+
// a dummy `loop` ... `exit; end loop;` structure then gnat emits:
|
|
730
|
+
//
|
|
731
|
+
// info: code between label and backwards goto rewritten as loop [enabled by default]
|
|
689
732
|
writef(g, "~N~Mloop~N~+", p);
|
|
690
733
|
|
|
691
734
|
struct str * savevar = NULL;
|
|
692
|
-
if (repeat_restore(
|
|
735
|
+
if (repeat_restore(p->left)) {
|
|
693
736
|
savevar = vars_newname(g);
|
|
694
737
|
write_savecursor(g, p, savevar);
|
|
695
738
|
}
|
|
696
739
|
|
|
697
|
-
|
|
740
|
+
int label = new_label(g);
|
|
741
|
+
g->failure_label = label;
|
|
698
742
|
g->label_used = 0;
|
|
743
|
+
str_clear(g->failure_str);
|
|
744
|
+
|
|
699
745
|
generate(g, p->left);
|
|
700
746
|
|
|
701
747
|
if (!g->unreachable) {
|
|
@@ -725,10 +771,10 @@ static void generate_repeat(struct generator * g, struct node * p) {
|
|
|
725
771
|
}
|
|
726
772
|
|
|
727
773
|
static void generate_atleast(struct generator * g, struct node * p) {
|
|
728
|
-
struct str * loopvar = vars_newname(g);
|
|
729
|
-
|
|
730
774
|
write_comment(g, p);
|
|
775
|
+
|
|
731
776
|
w(g, "~{");
|
|
777
|
+
struct str * loopvar = vars_newname(g);
|
|
732
778
|
g->B[0] = str_data(loopvar);
|
|
733
779
|
write_declare(g, "~B0 : Integer", p);
|
|
734
780
|
w(g, "~M~B0 := ");
|
|
@@ -747,12 +793,6 @@ static void generate_atleast(struct generator * g, struct node * p) {
|
|
|
747
793
|
str_delete(loopvar);
|
|
748
794
|
}
|
|
749
795
|
|
|
750
|
-
static void generate_setmark(struct generator * g, struct node * p) {
|
|
751
|
-
write_comment(g, p);
|
|
752
|
-
g->V[0] = p->name;
|
|
753
|
-
writef(g, "~M~V0 := Z.C;~N", p);
|
|
754
|
-
}
|
|
755
|
-
|
|
756
796
|
static void generate_tomark(struct generator * g, struct node * p) {
|
|
757
797
|
write_comment(g, p);
|
|
758
798
|
g->S[0] = p->mode == m_forward ? ">" : "<";
|
|
@@ -764,14 +804,6 @@ static void generate_tomark(struct generator * g, struct node * p) {
|
|
|
764
804
|
w(g, "~MZ.C := "); generate_AE(g, p->AE); writef(g, ";~N", p);
|
|
765
805
|
}
|
|
766
806
|
|
|
767
|
-
static void generate_atmark(struct generator * g, struct node * p) {
|
|
768
|
-
write_comment(g, p);
|
|
769
|
-
w(g, "~Mif Z.C /= "); generate_AE(g, p->AE); writef(g, " then~N~+", p);
|
|
770
|
-
write_failure(g);
|
|
771
|
-
w(g, "~-~Mend if;~N");
|
|
772
|
-
g->unreachable = false;
|
|
773
|
-
}
|
|
774
|
-
|
|
775
807
|
static void generate_hop(struct generator * g, struct node * p) {
|
|
776
808
|
write_comment(g, p);
|
|
777
809
|
g->S[0] = p->mode == m_forward ? "" : "_Backward";
|
|
@@ -783,24 +815,12 @@ static void generate_hop(struct generator * g, struct node * p) {
|
|
|
783
815
|
g->temporary_used = true;
|
|
784
816
|
}
|
|
785
817
|
|
|
786
|
-
static void generate_delete(struct generator * g, struct node * p) {
|
|
787
|
-
write_comment(g, p);
|
|
788
|
-
writef(g, "~MSlice_Del (Z);~N", p);
|
|
789
|
-
}
|
|
790
|
-
|
|
791
818
|
static void generate_tolimit(struct generator * g, struct node * p) {
|
|
792
819
|
write_comment(g, p);
|
|
793
820
|
g->S[0] = p->mode == m_forward ? "" : "b";
|
|
794
821
|
writef(g, "~MZ.C := Z.L~S0;~N", p);
|
|
795
822
|
}
|
|
796
823
|
|
|
797
|
-
static void generate_atlimit(struct generator * g, struct node * p) {
|
|
798
|
-
write_comment(g, p);
|
|
799
|
-
g->S[0] = p->mode == m_forward ? "" : "b";
|
|
800
|
-
g->S[1] = p->mode == m_forward ? "<" : ">";
|
|
801
|
-
write_failure_if(g, "Z.C ~S1 Z.L~S0", p);
|
|
802
|
-
}
|
|
803
|
-
|
|
804
824
|
static void generate_leftslice(struct generator * g, struct node * p) {
|
|
805
825
|
write_comment(g, p);
|
|
806
826
|
g->S[0] = p->mode == m_forward ? "Bra" : "Ket";
|
|
@@ -815,34 +835,35 @@ static void generate_rightslice(struct generator * g, struct node * p) {
|
|
|
815
835
|
|
|
816
836
|
static void generate_assignto(struct generator * g, struct node * p) {
|
|
817
837
|
write_comment(g, p);
|
|
818
|
-
g
|
|
819
|
-
|
|
820
|
-
write_failure_if(g, "~V0 == 0", p);
|
|
838
|
+
writef(g, "~M~V := Assign_To (Z, ~V);~N", p);
|
|
839
|
+
write_failure_if(g, "~V == 0", p);
|
|
821
840
|
}
|
|
822
841
|
|
|
823
842
|
static void generate_sliceto(struct generator * g, struct node * p) {
|
|
824
843
|
write_comment(g, p);
|
|
825
|
-
g
|
|
826
|
-
writef(g, "~M~
|
|
844
|
+
writef(g, "~MZ.L~W := Z.Ket - Z.Bra;~N", p);
|
|
845
|
+
writef(g, "~M~V (1 .. Z.L~W) := Z.P (Z.Bra + 1 .. Z.Ket);~N", p);
|
|
827
846
|
}
|
|
828
847
|
|
|
829
848
|
static void generate_address(struct generator * g, struct node * p) {
|
|
830
849
|
symbol * b = p->literalstring;
|
|
831
850
|
if (b != NULL) {
|
|
832
851
|
write_literal_string(g, b);
|
|
852
|
+
write_string(g, ", ");
|
|
853
|
+
write_int(g, SIZE(b));
|
|
833
854
|
} else {
|
|
834
|
-
w(g, "Ada.Strings.Unbounded.To_String (");
|
|
835
855
|
write_varref(g, p->name);
|
|
836
|
-
|
|
856
|
+
write_string(g, ", Z.L");
|
|
857
|
+
write_varname(g, p->name);
|
|
837
858
|
}
|
|
838
859
|
}
|
|
839
860
|
|
|
840
861
|
static void generate_insert(struct generator * g, struct node * p, int style) {
|
|
841
|
-
int keep_c = style == c_attach;
|
|
842
862
|
write_comment(g, p);
|
|
863
|
+
int keep_c = style == c_attach;
|
|
843
864
|
if (p->mode == m_backward) keep_c = !keep_c;
|
|
844
865
|
if (keep_c) w(g, "~MC := Z.C;~N");
|
|
845
|
-
writef(g, "~MInsert (Z,
|
|
866
|
+
writef(g, "~MInsert (Z, ", p);
|
|
846
867
|
generate_address(g, p);
|
|
847
868
|
writef(g, ");~N", p);
|
|
848
869
|
if (keep_c) {
|
|
@@ -851,34 +872,40 @@ static void generate_insert(struct generator * g, struct node * p, int style) {
|
|
|
851
872
|
}
|
|
852
873
|
}
|
|
853
874
|
|
|
854
|
-
static void
|
|
855
|
-
int keep_c = p->mode == m_forward; /* like 'attach' */
|
|
856
|
-
|
|
875
|
+
static void generate_stringassign(struct generator * g, struct node * p) {
|
|
857
876
|
write_comment(g, p);
|
|
858
|
-
|
|
877
|
+
int keep_c = p->mode == m_forward; /* like 'attach' */
|
|
878
|
+
if (keep_c) {
|
|
879
|
+
writef(g, "~MC := Z.C;~N", p);
|
|
880
|
+
g->temporary_used = true;
|
|
881
|
+
}
|
|
859
882
|
if (p->mode == m_forward) {
|
|
860
|
-
|
|
883
|
+
/* like 'attach' */
|
|
884
|
+
writef(g, "~MReplace (Z, Z.C, Z.L, ", p);
|
|
861
885
|
} else {
|
|
862
|
-
writef(g, "~
|
|
886
|
+
writef(g, "~MReplace (Z, Z.Lb, Z.C, ", p);
|
|
863
887
|
}
|
|
864
888
|
generate_address(g, p);
|
|
865
889
|
writef(g, ");~N", p);
|
|
866
890
|
if (keep_c) {
|
|
867
891
|
w(g, "~MZ.C := C;~N");
|
|
868
|
-
g->temporary_used = true;
|
|
869
892
|
}
|
|
870
893
|
}
|
|
871
894
|
|
|
872
895
|
static void generate_slicefrom(struct generator * g, struct node * p) {
|
|
873
896
|
write_comment(g, p);
|
|
897
|
+
if (p->literalstring && SIZE(p->literalstring) == 0) {
|
|
898
|
+
w(g, "~MSlice_Del (Z);~N");
|
|
899
|
+
return;
|
|
900
|
+
}
|
|
874
901
|
w(g, "~MSlice_From (Z, ");
|
|
875
902
|
generate_address(g, p);
|
|
876
|
-
|
|
903
|
+
w(g, ");~N");
|
|
877
904
|
}
|
|
878
905
|
|
|
879
906
|
static void generate_setlimit(struct generator * g, struct node * p) {
|
|
880
|
-
struct str * varname = vars_newname(g);
|
|
881
907
|
write_comment(g, p);
|
|
908
|
+
struct str * varname = vars_newname(g);
|
|
882
909
|
|
|
883
910
|
g->B[0] = str_data(varname);
|
|
884
911
|
write_declare(g, "~B0 : Integer", p);
|
|
@@ -895,21 +922,20 @@ static void generate_setlimit(struct generator * g, struct node * p) {
|
|
|
895
922
|
write_comment(g, q);
|
|
896
923
|
|
|
897
924
|
g->S[0] = q->mode == m_forward ? ">" : "<";
|
|
898
|
-
|
|
899
925
|
w(g, "~Mif Z.C ~S0 "); generate_AE(g, q->AE); writef(g, " then~N~+", q);
|
|
900
|
-
|
|
901
|
-
w(g, "
|
|
902
|
-
w(g, "~Mend if;~N");
|
|
903
|
-
w(g, "~M~B0");
|
|
926
|
+
write_failure(g);
|
|
927
|
+
w(g, "~-~Mend if;~N");
|
|
904
928
|
g->unreachable = false;
|
|
905
929
|
|
|
906
930
|
if (p->mode == m_forward) {
|
|
907
|
-
w(g, " := Z.L
|
|
931
|
+
w(g, "~M~B0 := Z.L; Z.L := ");
|
|
932
|
+
generate_AE(g, q->AE);
|
|
933
|
+
w(g, "; ~B0 := ~B0 - Z.L;~N");
|
|
908
934
|
} else {
|
|
909
|
-
w(g, " := Z.Lb; Z.Lb := ");
|
|
935
|
+
w(g, "~M~B0 := Z.Lb; Z.Lb := ");
|
|
936
|
+
generate_AE(g, q->AE);
|
|
937
|
+
w(g, ";~N");
|
|
910
938
|
}
|
|
911
|
-
generate_AE(g, q->AE);
|
|
912
|
-
w(g, ";~N");
|
|
913
939
|
|
|
914
940
|
if (p->mode == m_forward) {
|
|
915
941
|
str_assign(g->failure_str, "Z.L := Z.L + ");
|
|
@@ -967,62 +993,89 @@ static void generate_setlimit(struct generator * g, struct node * p) {
|
|
|
967
993
|
static void generate_dollar(struct generator * g, struct node * p) {
|
|
968
994
|
write_comment(g, p);
|
|
969
995
|
|
|
996
|
+
int used = g->label_used;
|
|
997
|
+
int a0 = g->failure_label;
|
|
998
|
+
struct str * a1 = str_copy(g->failure_str);
|
|
999
|
+
int label = new_label(g);
|
|
1000
|
+
g->failure_label = label;
|
|
1001
|
+
g->label_used = 0;
|
|
1002
|
+
str_clear(g->failure_str);
|
|
1003
|
+
|
|
970
1004
|
struct str * savevar = vars_newname(g);
|
|
971
1005
|
g->B[0] = str_data(savevar);
|
|
972
|
-
g->V[0] = p->name;
|
|
973
1006
|
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
"FLimit := ~B0_Limit; "
|
|
982
|
-
"FBkLimit := ~B0_BkLimit; "
|
|
983
|
-
"FBra := ~B0_Bra; "
|
|
984
|
-
"FKet := ~B0_Ket;", p);
|
|
985
|
-
g->failure_str = g->outbuf;
|
|
986
|
-
g->outbuf = saved_output;
|
|
987
|
-
}
|
|
988
|
-
|
|
989
|
-
write_declare(g, "~B0_Current : AnsiString", p);
|
|
990
|
-
write_declare(g, "~B0_Cursor : Integer", p);
|
|
991
|
-
write_declare(g, "~B0_Limit : Integer", p);
|
|
992
|
-
write_declare(g, "~B0_BkLimit : Integer", p);
|
|
993
|
-
write_declare(g, "~B0_Bra : Integer", p);
|
|
994
|
-
write_declare(g, "~B0_Ket : Integer", p);
|
|
1007
|
+
write_declare(g, "~B0_C : Char_Index", p);
|
|
1008
|
+
write_declare(g, "~B0_Len : Char_Index", p);
|
|
1009
|
+
write_declare(g, "~B0_L : Char_Index", p);
|
|
1010
|
+
write_declare(g, "~B0_Lb : Char_Index", p);
|
|
1011
|
+
write_declare(g, "~B0_Bra : Char_Index", p);
|
|
1012
|
+
write_declare(g, "~B0_Ket : Char_Index", p);
|
|
1013
|
+
write_declare(g, "~B0_P : String (1 .. WORD_MAX_LENGTH)", p);
|
|
995
1014
|
writef(g, "~{"
|
|
996
|
-
"~M~
|
|
997
|
-
"
|
|
998
|
-
"~M~
|
|
999
|
-
"~M~
|
|
1000
|
-
"~M~
|
|
1001
|
-
"~M~
|
|
1002
|
-
"~M~
|
|
1003
|
-
"~
|
|
1004
|
-
"~
|
|
1005
|
-
"~
|
|
1015
|
+
"~M~B0_C := Z.C;~N"
|
|
1016
|
+
"~M~B0_Len := Z.Len;~N"
|
|
1017
|
+
"~M~B0_L := Z.L;~N"
|
|
1018
|
+
"~M~B0_Lb := Z.Lb;~N"
|
|
1019
|
+
"~M~B0_Bra := Z.Bra;~N"
|
|
1020
|
+
"~M~B0_Ket := Z.Ket;~N"
|
|
1021
|
+
"~M~B0_P := Z.P;~N"
|
|
1022
|
+
"~MZ.P := ~V;~N"
|
|
1023
|
+
"~MZ.Len := Z.L~W;~N"
|
|
1024
|
+
"~MZ.C := 0;~N"
|
|
1025
|
+
"~MZ.Bra := 0;~N"
|
|
1026
|
+
"~MZ.Ket := 0;~N"
|
|
1027
|
+
"~MZ.L := Z.Len;~N", p);
|
|
1028
|
+
if (p->left->possible_signals == -1) {
|
|
1029
|
+
/* Assume failure. */
|
|
1030
|
+
write_declare(g, "~B0_F : Boolean", p);
|
|
1031
|
+
w(g, "~M~B0_F := True;~N");
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1006
1034
|
generate(g, p->left);
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1035
|
+
|
|
1036
|
+
if (!g->unreachable && p->left->possible_signals == -1) {
|
|
1037
|
+
/* Mark success. */
|
|
1038
|
+
g->B[0] = str_data(savevar);
|
|
1039
|
+
w(g, "~M~B0_F := False;~N");
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
if (g->label_used)
|
|
1043
|
+
wsetl(g, g->failure_label);
|
|
1044
|
+
|
|
1045
|
+
g->label_used = used;
|
|
1046
|
+
g->failure_label = a0;
|
|
1047
|
+
str_delete(g->failure_str);
|
|
1048
|
+
g->failure_str = a1;
|
|
1049
|
+
|
|
1050
|
+
g->B[0] = str_data(savevar);
|
|
1051
|
+
writef(g, "~M~V := Z.P;~N"
|
|
1052
|
+
"~MZ.L~W := Z.Len;~N"
|
|
1053
|
+
"~MZ.C := ~B0_C;~N"
|
|
1054
|
+
"~MZ.Len := ~B0_Len;~N"
|
|
1055
|
+
"~MZ.L := ~B0_L;~N"
|
|
1056
|
+
"~MZ.Lb := ~B0_Lb;~N"
|
|
1057
|
+
"~MZ.Bra := ~B0_Bra;~N"
|
|
1058
|
+
"~MZ.Ket := ~B0_Ket;~N"
|
|
1059
|
+
"~MZ.P := ~B0_P;~N", p);
|
|
1060
|
+
|
|
1061
|
+
if (p->left->possible_signals == 0) {
|
|
1062
|
+
// p->left always signals f.
|
|
1063
|
+
w(g, "~M~f~N");
|
|
1064
|
+
} else if (p->left->possible_signals == -1) {
|
|
1065
|
+
write_failure_if(g, "~B0_F", p);
|
|
1011
1066
|
}
|
|
1012
1067
|
w(g, "~}");
|
|
1068
|
+
|
|
1013
1069
|
str_delete(savevar);
|
|
1014
1070
|
}
|
|
1015
1071
|
|
|
1016
1072
|
static void generate_integer_assign(struct generator * g, struct node * p, const char * s) {
|
|
1017
1073
|
write_comment(g, p);
|
|
1018
|
-
g
|
|
1019
|
-
w(g, "~M~V0 := ");
|
|
1020
|
-
|
|
1074
|
+
writef(g, "~M~V := ", p);
|
|
1021
1075
|
if (s != NULL) {
|
|
1022
1076
|
g->S[0] = s;
|
|
1023
|
-
|
|
1077
|
+
writef(g, "~V ~S0 ", p);
|
|
1024
1078
|
}
|
|
1025
|
-
|
|
1026
1079
|
generate_AE(g, p->AE);
|
|
1027
1080
|
w(g, ";~N");
|
|
1028
1081
|
}
|
|
@@ -1030,7 +1083,7 @@ static void generate_integer_assign(struct generator * g, struct node * p, const
|
|
|
1030
1083
|
static void generate_integer_test(struct generator * g, struct node * p) {
|
|
1031
1084
|
write_comment(g, p);
|
|
1032
1085
|
int relop = p->type;
|
|
1033
|
-
int optimise_to_return = (g
|
|
1086
|
+
int optimise_to_return = tailcallable(g, p);
|
|
1034
1087
|
if (optimise_to_return) {
|
|
1035
1088
|
w(g, "~MResult := (");
|
|
1036
1089
|
p->right = NULL;
|
|
@@ -1053,31 +1106,30 @@ static void generate_integer_test(struct generator * g, struct node * p) {
|
|
|
1053
1106
|
}
|
|
1054
1107
|
|
|
1055
1108
|
static void generate_call(struct generator * g, struct node * p) {
|
|
1056
|
-
int signals =
|
|
1109
|
+
int signals = p->name->definition->possible_signals;
|
|
1057
1110
|
write_comment(g, p);
|
|
1058
|
-
g
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
}
|
|
1111
|
+
if (tailcallable(g, p)) {
|
|
1112
|
+
/* Tail call. */
|
|
1113
|
+
writef(g, "~M~V (Z, Result);~N", p);
|
|
1114
|
+
w(g, "~Mreturn;~N");
|
|
1115
|
+
p->right = NULL;
|
|
1116
|
+
return;
|
|
1117
|
+
}
|
|
1118
|
+
if (just_return_on_fail(g) && signals == 0) {
|
|
1119
|
+
/* Always fails. */
|
|
1120
|
+
writef(g, "~M~V (Z, Result);~N", p);
|
|
1121
|
+
w(g, "~Mreturn~N");
|
|
1122
|
+
return;
|
|
1071
1123
|
}
|
|
1072
1124
|
if (signals == 1) {
|
|
1073
1125
|
/* Always succeeds. */
|
|
1074
|
-
writef(g, "~M~
|
|
1126
|
+
writef(g, "~M~V (Z, Result);~N", p);
|
|
1075
1127
|
} else if (signals == 0) {
|
|
1076
1128
|
/* Always fails. */
|
|
1077
|
-
writef(g, "~M~
|
|
1129
|
+
writef(g, "~M~V (Z, Result);~N", p);
|
|
1078
1130
|
write_failure(g);
|
|
1079
1131
|
} else {
|
|
1080
|
-
writef(g, "~M~
|
|
1132
|
+
writef(g, "~M~V (Z, Result);~N", p);
|
|
1081
1133
|
write_failure_if(g, "not Result", p);
|
|
1082
1134
|
}
|
|
1083
1135
|
}
|
|
@@ -1088,52 +1140,54 @@ static void generate_grouping(struct generator * g, struct node * p, int complem
|
|
|
1088
1140
|
struct grouping * q = p->name->grouping;
|
|
1089
1141
|
g->S[0] = p->mode == m_forward ? "" : "_Backward";
|
|
1090
1142
|
g->S[1] = complement ? "Out_" : "In_";
|
|
1091
|
-
g->V[0] = p->name;
|
|
1092
1143
|
g->I[0] = q->smallest_ch;
|
|
1093
1144
|
g->I[1] = q->largest_ch;
|
|
1094
|
-
|
|
1095
|
-
|
|
1145
|
+
if (tailcallable(g, p)) {
|
|
1146
|
+
writef(g, "~M~S1Grouping~S0 (Z, ~V, ~I0, ~I1, False, C);~N", p);
|
|
1147
|
+
w(g, "~MResult := (C = 0);~N");
|
|
1148
|
+
p->right = NULL;
|
|
1149
|
+
} else {
|
|
1150
|
+
writef(g, "~M~S1Grouping~S0 (Z, ~V, ~I0, ~I1, False, C);~N", p);
|
|
1151
|
+
write_failure_if(g, "C /= 0", p);
|
|
1152
|
+
}
|
|
1096
1153
|
g->temporary_used = true;
|
|
1097
1154
|
}
|
|
1098
1155
|
|
|
1099
1156
|
static void generate_namedstring(struct generator * g, struct node * p) {
|
|
1100
1157
|
write_comment(g, p);
|
|
1101
1158
|
g->S[0] = p->mode == m_forward ? "" : "_Backward";
|
|
1102
|
-
g
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1159
|
+
if (tailcallable(g, p)) {
|
|
1160
|
+
writef(g, "~MEq_S~S0 (Z, ~V, Z.L~W, Result);~N", p);
|
|
1161
|
+
p->right = NULL;
|
|
1162
|
+
} else {
|
|
1163
|
+
writef(g, "~MEq_S~S0 (Z, ~V, Z.L~W, Result);~N", p);
|
|
1164
|
+
write_failure_if(g, "not Result", p);
|
|
1165
|
+
}
|
|
1106
1166
|
}
|
|
1107
1167
|
|
|
1108
1168
|
static void generate_literalstring(struct generator * g, struct node * p) {
|
|
1109
|
-
symbol * b = p->literalstring;
|
|
1110
1169
|
write_comment(g, p);
|
|
1111
1170
|
g->S[0] = p->mode == m_forward ? "" : "_Backward";
|
|
1112
|
-
g->
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
writef(g, "~MZ.C := Z.C + C;~N", p);
|
|
1171
|
+
g->I[0] = SIZE(p->literalstring);
|
|
1172
|
+
if (tailcallable(g, p)) {
|
|
1173
|
+
writef(g, "~MEq_S~S0 (Z, ~L, ~I0, Result);~N", p);
|
|
1174
|
+
p->right = NULL;
|
|
1117
1175
|
} else {
|
|
1118
|
-
writef(g, "~
|
|
1176
|
+
writef(g, "~MEq_S~S0 (Z, ~L, ~I0, Result);~N", p);
|
|
1177
|
+
write_failure_if(g, "not Result", p);
|
|
1119
1178
|
}
|
|
1120
|
-
g->temporary_used = true;
|
|
1121
1179
|
}
|
|
1122
1180
|
|
|
1123
1181
|
static void generate_define(struct generator * g, struct node * p) {
|
|
1124
|
-
struct name * q = p->name;
|
|
1125
|
-
if (q->type == t_routine && !q->used) return;
|
|
1126
|
-
|
|
1127
1182
|
write_newline(g);
|
|
1128
1183
|
write_comment(g, p);
|
|
1129
1184
|
|
|
1130
1185
|
/* Generate function header. */
|
|
1131
|
-
g
|
|
1132
|
-
w(g, "~Mprocedure ~W0 (Z : in out Context_Type; Result : out Boolean) is~N");
|
|
1186
|
+
writef(g, "~Mprocedure ~W (Z : in out Context_Type; Result : out Boolean) is~N", p);
|
|
1133
1187
|
|
|
1134
1188
|
/* Save output. */
|
|
1135
|
-
struct str *saved_output = g->outbuf;
|
|
1136
|
-
struct str *saved_declarations = g->declarations;
|
|
1189
|
+
struct str * saved_output = g->outbuf;
|
|
1190
|
+
struct str * saved_declarations = g->declarations;
|
|
1137
1191
|
g->outbuf = str_new();
|
|
1138
1192
|
g->declarations = str_new();
|
|
1139
1193
|
|
|
@@ -1145,7 +1199,7 @@ static void generate_define(struct generator * g, struct node * p) {
|
|
|
1145
1199
|
|
|
1146
1200
|
/* Generate function body. */
|
|
1147
1201
|
w(g, "~{");
|
|
1148
|
-
int signals =
|
|
1202
|
+
int signals = p->left->possible_signals;
|
|
1149
1203
|
g->temporary_used = false;
|
|
1150
1204
|
generate(g, p->left);
|
|
1151
1205
|
if (p->left->right) {
|
|
@@ -1154,17 +1208,50 @@ static void generate_define(struct generator * g, struct node * p) {
|
|
|
1154
1208
|
generate(g, p->left->right);
|
|
1155
1209
|
}
|
|
1156
1210
|
}
|
|
1157
|
-
g->V[0] = q;
|
|
1158
|
-
w(g, "~-~Mend ~W0;~N");
|
|
1159
1211
|
|
|
1160
|
-
|
|
1161
|
-
|
|
1212
|
+
#define FINAL_RETURN "\n return;\n"
|
|
1213
|
+
#define FINAL_RETURN_LEN (sizeof(FINAL_RETURN) - 1)
|
|
1214
|
+
if (memcmp(str_data(g->outbuf) + str_len(g->outbuf) - FINAL_RETURN_LEN,
|
|
1215
|
+
FINAL_RETURN, FINAL_RETURN_LEN) == 0) {
|
|
1216
|
+
// If generate_functionend() has just added a return we remove it again.
|
|
1217
|
+
// This is really only a cosmetic improvement.
|
|
1218
|
+
str_pop_n(g->outbuf, FINAL_RETURN_LEN - 1);
|
|
1162
1219
|
}
|
|
1163
1220
|
|
|
1221
|
+
writef(g, "~-~Mend ~W;~N", p);
|
|
1222
|
+
|
|
1164
1223
|
if (need_among_var(p->left)) {
|
|
1165
1224
|
str_append_string(saved_output, " A : Integer;\n");
|
|
1166
1225
|
}
|
|
1167
1226
|
|
|
1227
|
+
if (g->temporary_used) {
|
|
1228
|
+
str_append_string(saved_output, " C : Result_Index;\n");
|
|
1229
|
+
}
|
|
1230
|
+
|
|
1231
|
+
/* Declare localised variables. */
|
|
1232
|
+
struct str * temp = g->outbuf;
|
|
1233
|
+
g->outbuf = saved_output;
|
|
1234
|
+
for (struct name * name = g->analyser->names; name; name = name->next) {
|
|
1235
|
+
if (name->local_to == p->name) {
|
|
1236
|
+
switch (name->type) {
|
|
1237
|
+
case t_string:
|
|
1238
|
+
assert(0);
|
|
1239
|
+
break;
|
|
1240
|
+
case t_integer:
|
|
1241
|
+
w(g, " ");
|
|
1242
|
+
write_varname(g, name);
|
|
1243
|
+
w(g, " : Integer;\n");
|
|
1244
|
+
break;
|
|
1245
|
+
case t_boolean:
|
|
1246
|
+
w(g, " ");
|
|
1247
|
+
write_varname(g, name);
|
|
1248
|
+
w(g, " : Boolean;\n");
|
|
1249
|
+
break;
|
|
1250
|
+
}
|
|
1251
|
+
}
|
|
1252
|
+
}
|
|
1253
|
+
g->outbuf = temp;
|
|
1254
|
+
|
|
1168
1255
|
if (g->var_number) {
|
|
1169
1256
|
str_append(saved_output, g->declarations);
|
|
1170
1257
|
}
|
|
@@ -1178,7 +1265,7 @@ static void generate_define(struct generator * g, struct node * p) {
|
|
|
1178
1265
|
|
|
1179
1266
|
static void generate_functionend(struct generator * g, struct node * p) {
|
|
1180
1267
|
(void)p;
|
|
1181
|
-
w(g, "~MResult := True;~N");
|
|
1268
|
+
w(g, "~MResult := True;~N~Mreturn;~N");
|
|
1182
1269
|
}
|
|
1183
1270
|
|
|
1184
1271
|
static void generate_substring(struct generator * g, struct node * p) {
|
|
@@ -1192,8 +1279,7 @@ static void generate_substring(struct generator * g, struct node * p) {
|
|
|
1192
1279
|
int n_cases = 0;
|
|
1193
1280
|
symbol cases[2];
|
|
1194
1281
|
int shortest_size = x->shortest_size;
|
|
1195
|
-
int
|
|
1196
|
-
int need_among_handler = (x->function_count > 0);
|
|
1282
|
+
int block_opened = 0;
|
|
1197
1283
|
|
|
1198
1284
|
g->S[0] = p->mode == m_forward ? "" : "_Backward";
|
|
1199
1285
|
g->I[0] = x->number;
|
|
@@ -1240,7 +1326,8 @@ static void generate_substring(struct generator * g, struct node * p) {
|
|
|
1240
1326
|
}
|
|
1241
1327
|
}
|
|
1242
1328
|
|
|
1243
|
-
|
|
1329
|
+
int pre_check = (block != -1 || n_cases <= 2);
|
|
1330
|
+
if (pre_check) {
|
|
1244
1331
|
char buf[64];
|
|
1245
1332
|
char buf2[128];
|
|
1246
1333
|
char buf3[64];
|
|
@@ -1248,13 +1335,16 @@ static void generate_substring(struct generator * g, struct node * p) {
|
|
|
1248
1335
|
g->I[3] = bitmap;
|
|
1249
1336
|
g->I[4] = shortest_size - 1;
|
|
1250
1337
|
g->S[3] = buf3;
|
|
1251
|
-
|
|
1338
|
+
checked_snprintf(buf3, sizeof(buf3), "16#%x#", bitmap);
|
|
1252
1339
|
if (p->mode == m_forward) {
|
|
1253
|
-
if (shortest_size == 1)
|
|
1254
|
-
|
|
1255
|
-
else
|
|
1256
|
-
|
|
1257
|
-
|
|
1340
|
+
if (shortest_size == 1) {
|
|
1341
|
+
checked_snprintf(buf, sizeof(buf), "Z.C");
|
|
1342
|
+
} else {
|
|
1343
|
+
checked_snprintf(buf, sizeof(buf),
|
|
1344
|
+
"Z.C + %d", shortest_size - 1);
|
|
1345
|
+
}
|
|
1346
|
+
checked_snprintf(buf2, sizeof(buf2),
|
|
1347
|
+
"Character'Pos (Z.P (%s + 1))", buf);
|
|
1258
1348
|
g->S[1] = buf;
|
|
1259
1349
|
g->S[2] = buf2;
|
|
1260
1350
|
if (shortest_size == 1) {
|
|
@@ -1271,12 +1361,8 @@ static void generate_substring(struct generator * g, struct node * p) {
|
|
|
1271
1361
|
writef(g, "~Mif Z.C - ~I4 <= Z.Lb", p);
|
|
1272
1362
|
}
|
|
1273
1363
|
}
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
* This doesn't seem to be a useful construct, but it is
|
|
1277
|
-
* syntactically valid.
|
|
1278
|
-
*/
|
|
1279
|
-
} else if (n_cases == 1) {
|
|
1364
|
+
assert(n_cases > 0);
|
|
1365
|
+
if (n_cases == 1) {
|
|
1280
1366
|
g->I[4] = cases[0];
|
|
1281
1367
|
writef(g, " or else ~S2 /= ~I4", p);
|
|
1282
1368
|
} else if (n_cases == 2) {
|
|
@@ -1287,40 +1373,58 @@ static void generate_substring(struct generator * g, struct node * p) {
|
|
|
1287
1373
|
writef(g, " or else Check_Among (Z, ~S1, ~I2, ~S3)", p);
|
|
1288
1374
|
}
|
|
1289
1375
|
writef(g, " then~+~N", p);
|
|
1290
|
-
if (empty_case != -1) {
|
|
1376
|
+
if (empty_case != -1 && !among_cases[empty_case].function) {
|
|
1291
1377
|
/* If the among includes the empty string, it can never fail
|
|
1292
1378
|
* so not matching the bitmap means we match the empty string.
|
|
1293
1379
|
*/
|
|
1294
1380
|
g->I[4] = among_cases[empty_case].result;
|
|
1295
1381
|
writef(g, "~MA := ~I4;~-~N~Melse~+~N", p);
|
|
1296
|
-
|
|
1297
|
-
writef(g, "~MFind_Among~S0 (Z, A_~I0, Among_String, Among_Handler'Access, A);~N", p);
|
|
1298
|
-
} else {
|
|
1299
|
-
writef(g, "~MFind_Among~S0 (Z, A_~I0, Among_String, null, A);~N", p);
|
|
1300
|
-
}
|
|
1301
|
-
if (!x->always_matches) {
|
|
1302
|
-
write_failure_if(g, "A = 0", p);
|
|
1303
|
-
}
|
|
1304
|
-
call_done = 1;
|
|
1382
|
+
block_opened = 1;
|
|
1305
1383
|
} else {
|
|
1306
|
-
|
|
1384
|
+
writef(g, "~f", p);
|
|
1385
|
+
writef(g, "~-~Mend if;~N", p);
|
|
1307
1386
|
}
|
|
1308
|
-
writef(g, "~-~Mend if;~N", p);
|
|
1309
1387
|
} else {
|
|
1310
1388
|
#ifdef OPTIMISATION_WARNINGS
|
|
1311
1389
|
printf("Couldn't shortcut among %d\n", x->number);
|
|
1312
1390
|
#endif
|
|
1313
1391
|
}
|
|
1314
1392
|
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
writef(g, "~MFind_Among~S0 (Z, A_~I0, Among_String, null, A);~N", p);
|
|
1320
|
-
}
|
|
1393
|
+
g->S[1] = (x->function_count > 0) ? "Among_Handler'Access" : "null";
|
|
1394
|
+
|
|
1395
|
+
if (x->amongvar_needed) {
|
|
1396
|
+
writef(g, "~MFind_Among~S0 (Z, A_~I0, Among_String, ~S1, A);~N", p);
|
|
1321
1397
|
if (!x->always_matches) {
|
|
1322
1398
|
write_failure_if(g, "A = 0", p);
|
|
1323
1399
|
}
|
|
1400
|
+
if (block_opened) writef(g, "~-~Mend if;~N", p);
|
|
1401
|
+
return;
|
|
1402
|
+
}
|
|
1403
|
+
|
|
1404
|
+
if (pre_check && !x->function_count) {
|
|
1405
|
+
// If all cases are one symbol long (so one byte of UTF-8, one
|
|
1406
|
+
// character long in fixed-width encodings) then we don't need to call
|
|
1407
|
+
// the helper and can just inc/dec the cursor by 1.
|
|
1408
|
+
if (x->longest_size == 1 && !x->always_matches) {
|
|
1409
|
+
if (p->mode == m_forward) {
|
|
1410
|
+
w(g, "~MZ.C := Z.C + 1;~N");
|
|
1411
|
+
} else {
|
|
1412
|
+
w(g, "~MZ.C := Z.C - 1;~N");
|
|
1413
|
+
}
|
|
1414
|
+
// Suppress generating table for this among.
|
|
1415
|
+
x->used = false;
|
|
1416
|
+
return;
|
|
1417
|
+
}
|
|
1418
|
+
}
|
|
1419
|
+
|
|
1420
|
+
writef(g, "~MFind_Among~S0 (Z, A_~I0, Among_String, ~S1, A);~N", p);
|
|
1421
|
+
if (x->always_matches) {
|
|
1422
|
+
// The result in `A` can't be zero.
|
|
1423
|
+
} else if (x->command_count == 0 && tailcallable(g, p)) {
|
|
1424
|
+
writef(g, "~MResult := A /= 0;~N", p);
|
|
1425
|
+
x->node->right = NULL;
|
|
1426
|
+
} else {
|
|
1427
|
+
write_failure_if(g, "A = 0", p);
|
|
1324
1428
|
}
|
|
1325
1429
|
}
|
|
1326
1430
|
|
|
@@ -1352,10 +1456,23 @@ static void generate_among(struct generator * g, struct node * p) {
|
|
|
1352
1456
|
}
|
|
1353
1457
|
}
|
|
1354
1458
|
|
|
1355
|
-
static void generate_booltest(struct generator * g, struct node * p) {
|
|
1459
|
+
static void generate_booltest(struct generator * g, struct node * p, int inverted) {
|
|
1356
1460
|
write_comment(g, p);
|
|
1357
|
-
g
|
|
1358
|
-
|
|
1461
|
+
if (tailcallable(g, p)) {
|
|
1462
|
+
// Optimise at end of function.
|
|
1463
|
+
if (inverted) {
|
|
1464
|
+
writef(g, "~MResult := not ~V;~N", p);
|
|
1465
|
+
} else {
|
|
1466
|
+
writef(g, "~MResult := ~V;~N", p);
|
|
1467
|
+
}
|
|
1468
|
+
p->right = NULL;
|
|
1469
|
+
return;
|
|
1470
|
+
}
|
|
1471
|
+
if (inverted) {
|
|
1472
|
+
write_failure_if(g, "~V", p);
|
|
1473
|
+
} else {
|
|
1474
|
+
write_failure_if(g, "not ~V", p);
|
|
1475
|
+
}
|
|
1359
1476
|
}
|
|
1360
1477
|
|
|
1361
1478
|
static void generate_false(struct generator * g, struct node * p) {
|
|
@@ -1367,7 +1484,7 @@ static void generate_debug(struct generator * g, struct node * p) {
|
|
|
1367
1484
|
write_comment(g, p);
|
|
1368
1485
|
g->I[0] = g->debug_count++;
|
|
1369
1486
|
g->I[1] = p->line_number;
|
|
1370
|
-
writef(g, "~Mdebug(~I0, ~I1);~N", p);
|
|
1487
|
+
writef(g, "~Mdebug(Z, ~I0, ~I1);~N", p);
|
|
1371
1488
|
}
|
|
1372
1489
|
|
|
1373
1490
|
static void generate(struct generator * g, struct node * p) {
|
|
@@ -1400,25 +1517,21 @@ static void generate(struct generator * g, struct node * p) {
|
|
|
1400
1517
|
case c_repeat: generate_repeat(g, p); break;
|
|
1401
1518
|
case c_loop: generate_loop(g, p); break;
|
|
1402
1519
|
case c_atleast: generate_atleast(g, p); break;
|
|
1403
|
-
case c_setmark: generate_setmark(g, p); break;
|
|
1404
1520
|
case c_tomark: generate_tomark(g, p); break;
|
|
1405
|
-
case c_atmark: generate_atmark(g, p); break;
|
|
1406
1521
|
case c_hop: generate_hop(g, p); break;
|
|
1407
|
-
case c_delete: generate_delete(g, p); break;
|
|
1408
1522
|
case c_next: generate_next(g, p); break;
|
|
1409
1523
|
case c_tolimit: generate_tolimit(g, p); break;
|
|
1410
|
-
case c_atlimit: generate_atlimit(g, p); break;
|
|
1411
1524
|
case c_leftslice: generate_leftslice(g, p); break;
|
|
1412
1525
|
case c_rightslice: generate_rightslice(g, p); break;
|
|
1413
1526
|
case c_assignto: generate_assignto(g, p); break;
|
|
1414
1527
|
case c_sliceto: generate_sliceto(g, p); break;
|
|
1415
|
-
case
|
|
1528
|
+
case c_stringassign: generate_stringassign(g, p); break;
|
|
1416
1529
|
case c_insert:
|
|
1417
1530
|
case c_attach: generate_insert(g, p, p->type); break;
|
|
1418
1531
|
case c_slicefrom: generate_slicefrom(g, p); break;
|
|
1419
1532
|
case c_setlimit: generate_setlimit(g, p); break;
|
|
1420
1533
|
case c_dollar: generate_dollar(g, p); break;
|
|
1421
|
-
case
|
|
1534
|
+
case c_assign: generate_integer_assign(g, p, NULL); break;
|
|
1422
1535
|
case c_plusassign: generate_integer_assign(g, p, "+"); break;
|
|
1423
1536
|
case c_minusassign: generate_integer_assign(g, p, "-"); break;
|
|
1424
1537
|
case c_multiplyassign:generate_integer_assign(g, p, "*"); break;
|
|
@@ -1438,7 +1551,8 @@ static void generate(struct generator * g, struct node * p) {
|
|
|
1438
1551
|
case c_literalstring: generate_literalstring(g, p); break;
|
|
1439
1552
|
case c_among: generate_among(g, p); break;
|
|
1440
1553
|
case c_substring: generate_substring(g, p); break;
|
|
1441
|
-
case c_booltest: generate_booltest(g, p); break;
|
|
1554
|
+
case c_booltest: generate_booltest(g, p, false); break;
|
|
1555
|
+
case c_not_booltest: generate_booltest(g, p, true); break;
|
|
1442
1556
|
case c_false: generate_false(g, p); break;
|
|
1443
1557
|
case c_true: break;
|
|
1444
1558
|
case c_debug: generate_debug(g, p); break;
|
|
@@ -1454,57 +1568,53 @@ static void generate(struct generator * g, struct node * p) {
|
|
|
1454
1568
|
|
|
1455
1569
|
/* Class declaration generation. */
|
|
1456
1570
|
static void generate_unit_start(struct generator * g) {
|
|
1457
|
-
g->margin = 0;
|
|
1458
1571
|
write_start_comment(g, "-- ", NULL);
|
|
1459
1572
|
}
|
|
1460
1573
|
|
|
1461
1574
|
static void generate_method_decl(struct generator * g, struct name * q) {
|
|
1462
|
-
g
|
|
1463
|
-
|
|
1575
|
+
w(g, "~Mprocedure ");
|
|
1576
|
+
write_varref(g, q);
|
|
1577
|
+
w(g, " (Z : in out Context_Type; Result : out Boolean);~N");
|
|
1464
1578
|
}
|
|
1465
1579
|
|
|
1466
1580
|
static void generate_method_decls(struct generator * g, enum name_types type) {
|
|
1467
|
-
struct among * a = g->analyser->amongs;
|
|
1468
|
-
int need_among_handler = 0;
|
|
1469
|
-
|
|
1470
1581
|
for (struct name * q = g->analyser->names; q; q = q->next) {
|
|
1471
1582
|
if ((enum name_types)q->type == type) {
|
|
1472
1583
|
generate_method_decl(g, q);
|
|
1473
1584
|
}
|
|
1474
1585
|
}
|
|
1475
|
-
|
|
1476
|
-
while (a != NULL && need_among_handler == 0) {
|
|
1477
|
-
need_among_handler = (a->function_count > 0);
|
|
1478
|
-
a = a->next;
|
|
1479
|
-
}
|
|
1480
|
-
if (need_among_handler) {
|
|
1481
|
-
w(g, "~N~Mprocedure Among_Handler (Context : in out Stemmer.Context_Type'Class; Operation : in Operation_Index; Result : out Boolean);~N");
|
|
1482
|
-
}
|
|
1483
1586
|
}
|
|
1484
1587
|
|
|
1485
1588
|
static void generate_member_decls(struct generator * g) {
|
|
1486
1589
|
w(g, " type Context_Type is new Stemmer.Context_Type with");
|
|
1487
|
-
if (g->analyser->
|
|
1488
|
-
g->analyser->name_count[t_integer] > 0 ||
|
|
1489
|
-
g->analyser->name_count[t_boolean] > 0) {
|
|
1590
|
+
if (g->analyser->variable_count > 0) {
|
|
1490
1591
|
w(g, " record~N~+");
|
|
1491
1592
|
for (struct name * q = g->analyser->names; q; q = q->next) {
|
|
1492
|
-
|
|
1593
|
+
if (q->local_to) continue;
|
|
1493
1594
|
switch (q->type) {
|
|
1494
1595
|
case t_string:
|
|
1495
|
-
|
|
1596
|
+
write_margin(g);
|
|
1597
|
+
write_varname(g, q);
|
|
1598
|
+
w(g, " : String (1 .. WORD_MAX_LENGTH);~N");
|
|
1599
|
+
write_margin(g);
|
|
1600
|
+
write_char(g, 'L');
|
|
1601
|
+
write_varname(g, q);
|
|
1602
|
+
w(g, " : Char_Index := 0;~N");
|
|
1496
1603
|
break;
|
|
1497
1604
|
case t_integer:
|
|
1498
|
-
|
|
1605
|
+
write_margin(g);
|
|
1606
|
+
write_varname(g, q);
|
|
1607
|
+
w(g, " : Integer;~N");
|
|
1499
1608
|
break;
|
|
1500
1609
|
case t_boolean:
|
|
1501
|
-
|
|
1610
|
+
write_margin(g);
|
|
1611
|
+
write_varname(g, q);
|
|
1612
|
+
w(g, " : Boolean;~N");
|
|
1502
1613
|
break;
|
|
1503
1614
|
}
|
|
1504
1615
|
}
|
|
1505
1616
|
|
|
1506
|
-
w(g, "
|
|
1507
|
-
w(g, "~- end record;~N");
|
|
1617
|
+
w(g, "~-~Mend record;~N");
|
|
1508
1618
|
} else {
|
|
1509
1619
|
w(g, " null record;~N");
|
|
1510
1620
|
}
|
|
@@ -1518,7 +1628,6 @@ static int generate_among_string(struct generator * g, struct among * x, int cou
|
|
|
1518
1628
|
|
|
1519
1629
|
for (int i = 0; i < x->literalstring_count; i++, v++) {
|
|
1520
1630
|
/* Write among's string. */
|
|
1521
|
-
g->L[0] = v->b;
|
|
1522
1631
|
g->I[1] = i;
|
|
1523
1632
|
if (count + SIZE(v->b) > limit) {
|
|
1524
1633
|
w(g, "~N~M& ");
|
|
@@ -1527,7 +1636,7 @@ static int generate_among_string(struct generator * g, struct among * x, int cou
|
|
|
1527
1636
|
} else if (count > 0) {
|
|
1528
1637
|
w(g, " & ");
|
|
1529
1638
|
}
|
|
1530
|
-
|
|
1639
|
+
write_literal_string(g, v->b);
|
|
1531
1640
|
count += SIZE(v->b) + 5;
|
|
1532
1641
|
}
|
|
1533
1642
|
return count;
|
|
@@ -1541,7 +1650,7 @@ static int generate_among_table(struct generator * g, struct among * x, int star
|
|
|
1541
1650
|
g->I[0] = x->number;
|
|
1542
1651
|
|
|
1543
1652
|
g->I[1] = x->literalstring_count - 1;
|
|
1544
|
-
w(g, "~MA_~I0 : constant Among_Array_Type (0 .. ~I1) := ~+(~N");
|
|
1653
|
+
w(g, "~N~MA_~I0 : constant Among_Array_Type (0 .. ~I1) := ~+(~N");
|
|
1545
1654
|
|
|
1546
1655
|
v = x->b;
|
|
1547
1656
|
for (int i = 0; i < x->literalstring_count; i++) {
|
|
@@ -1575,47 +1684,37 @@ static int generate_among_table(struct generator * g, struct among * x, int star
|
|
|
1575
1684
|
w(g, ",~N");
|
|
1576
1685
|
}
|
|
1577
1686
|
}
|
|
1578
|
-
w(g, ");~-~N
|
|
1687
|
+
w(g, ");~-~N");
|
|
1579
1688
|
return start_pos;
|
|
1580
1689
|
}
|
|
1581
1690
|
|
|
1582
|
-
static
|
|
1583
|
-
|
|
1584
|
-
if (!a) return 0;
|
|
1585
|
-
int count;
|
|
1586
|
-
int start_pos;
|
|
1691
|
+
static void generate_amongs(struct generator * g) {
|
|
1692
|
+
if (!g->analyser->amongs) return;
|
|
1587
1693
|
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1694
|
+
struct str * s = g->outbuf;
|
|
1695
|
+
g->outbuf = g->declarations;
|
|
1696
|
+
|
|
1697
|
+
w(g, "~N~MAmong_String : constant String := ~+");
|
|
1698
|
+
int count = 0;
|
|
1699
|
+
for (struct among * x = g->analyser->amongs; x != NULL; x = x->next) {
|
|
1700
|
+
if (x->used) {
|
|
1701
|
+
count = generate_among_string(g, x, count);
|
|
1702
|
+
}
|
|
1593
1703
|
}
|
|
1594
|
-
w(g, ";~N
|
|
1704
|
+
w(g, ";~N~-");
|
|
1595
1705
|
|
|
1596
1706
|
int operation = 0;
|
|
1597
|
-
start_pos = 1;
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1707
|
+
int start_pos = 1;
|
|
1708
|
+
for (struct among * x = g->analyser->amongs; x != NULL; x = x->next) {
|
|
1709
|
+
if (x->used) {
|
|
1710
|
+
start_pos = generate_among_table(g, x, start_pos, &operation);
|
|
1711
|
+
}
|
|
1602
1712
|
}
|
|
1603
|
-
|
|
1604
|
-
}
|
|
1713
|
+
g->outbuf = s;
|
|
1605
1714
|
|
|
1606
|
-
|
|
1607
|
-
return generate_amongs(g);
|
|
1608
|
-
}
|
|
1715
|
+
if (operation == 0) return;
|
|
1609
1716
|
|
|
1610
|
-
|
|
1611
|
-
for (struct node * p = g->analyser->program; p; p = p->right) {
|
|
1612
|
-
generate(g, p);
|
|
1613
|
-
g->unreachable = false;
|
|
1614
|
-
}
|
|
1615
|
-
}
|
|
1616
|
-
|
|
1617
|
-
static int generate_operations_dispatcher(struct generator * g) {
|
|
1618
|
-
int operation = 0;
|
|
1717
|
+
operation = 0;
|
|
1619
1718
|
|
|
1620
1719
|
w(g, "~N~Mprocedure Among_Handler (Context : in out Stemmer.Context_Type'Class; Operation : in Operation_Index; Result : out Boolean) is~N");
|
|
1621
1720
|
w(g, "~Mbegin~+~N~M");
|
|
@@ -1626,50 +1725,51 @@ static int generate_operations_dispatcher(struct generator * g) {
|
|
|
1626
1725
|
if (v[i].function != NULL) {
|
|
1627
1726
|
operation++;
|
|
1628
1727
|
g->I[2] = operation;
|
|
1629
|
-
w(g, "when ~I2 =>~N~M");
|
|
1630
|
-
g
|
|
1631
|
-
w(g, "
|
|
1728
|
+
w(g, "when ~I2 =>~N~M ");
|
|
1729
|
+
write_varname(g, v[i].function);
|
|
1730
|
+
w(g, " (Context_Type (Context), Result);~N~M");
|
|
1632
1731
|
}
|
|
1633
1732
|
}
|
|
1634
1733
|
}
|
|
1635
1734
|
w(g, "when others =>~N~M");
|
|
1636
1735
|
w(g, " Result := False;~-~N~Mend case;~-~N~M");
|
|
1637
|
-
w(g, "end Among_Handler;~N
|
|
1638
|
-
|
|
1736
|
+
w(g, "end Among_Handler;~N");
|
|
1737
|
+
}
|
|
1738
|
+
|
|
1739
|
+
static void generate_methods(struct generator * g) {
|
|
1740
|
+
for (struct node * p = g->analyser->program; p; p = p->right) {
|
|
1741
|
+
generate(g, p);
|
|
1742
|
+
g->unreachable = false;
|
|
1743
|
+
}
|
|
1639
1744
|
}
|
|
1640
1745
|
|
|
1641
|
-
static void set_bit(symbol * b, int i) { b[i
|
|
1746
|
+
static void set_bit(symbol * b, int i) { b[i >> 3] |= 1 << (i & 7); }
|
|
1642
1747
|
|
|
1643
1748
|
static void generate_grouping_table(struct generator * g, struct grouping * q) {
|
|
1644
1749
|
int range = q->largest_ch - q->smallest_ch + 1;
|
|
1645
|
-
int size = (range + 7)/ 8; /* assume 8 bits per symbol */
|
|
1750
|
+
int size = (range + 7) / 8; /* assume 8 bits per symbol */
|
|
1646
1751
|
symbol * b = q->b;
|
|
1647
1752
|
symbol * map = create_b(size);
|
|
1648
|
-
int need_comma = 0;
|
|
1649
1753
|
|
|
1650
1754
|
for (int i = 0; i < size; i++) map[i] = 0;
|
|
1651
1755
|
|
|
1652
1756
|
for (int i = 0; i < SIZE(b); i++) set_bit(map, b[i] - q->smallest_ch);
|
|
1653
1757
|
|
|
1654
|
-
g->V[0] = q->name;
|
|
1655
1758
|
g->I[0] = 8 * size - 1;
|
|
1656
|
-
w(g, "~N~M
|
|
1759
|
+
w(g, "~N~M");
|
|
1760
|
+
write_varname(g, q->name);
|
|
1761
|
+
w(g, " : constant Grouping_Array (0 .. ~I0) := (~N~+~M");
|
|
1657
1762
|
for (int i = 0; i < size; i++) {
|
|
1658
1763
|
unsigned char m = map[i];
|
|
1659
|
-
if (i
|
|
1660
|
-
w(g, ",~N~M");
|
|
1661
|
-
need_comma = 0;
|
|
1662
|
-
}
|
|
1764
|
+
if (i) w(g, ",~N~M");
|
|
1663
1765
|
for (int j = 0; j < 8; j++) {
|
|
1664
|
-
if (
|
|
1665
|
-
w(g, ", ");
|
|
1766
|
+
if (j) w(g, ", ");
|
|
1666
1767
|
|
|
1667
1768
|
if (m & (1 << j)) {
|
|
1668
1769
|
w(g, "True");
|
|
1669
1770
|
} else {
|
|
1670
1771
|
w(g, "False");
|
|
1671
1772
|
}
|
|
1672
|
-
need_comma = 1;
|
|
1673
1773
|
}
|
|
1674
1774
|
}
|
|
1675
1775
|
w(g, "~N~-~M);~N");
|
|
@@ -1678,21 +1778,30 @@ static void generate_grouping_table(struct generator * g, struct grouping * q) {
|
|
|
1678
1778
|
}
|
|
1679
1779
|
|
|
1680
1780
|
static void generate_groupings(struct generator * g) {
|
|
1781
|
+
struct str * s = g->outbuf;
|
|
1782
|
+
g->outbuf = g->declarations;
|
|
1681
1783
|
for (struct grouping * q = g->analyser->groupings; q; q = q->next) {
|
|
1682
|
-
|
|
1683
|
-
generate_grouping_table(g, q);
|
|
1784
|
+
generate_grouping_table(g, q);
|
|
1684
1785
|
}
|
|
1786
|
+
g->outbuf = s;
|
|
1685
1787
|
}
|
|
1686
1788
|
|
|
1687
1789
|
extern void generate_program_ada(struct generator * g) {
|
|
1790
|
+
g->margin_indent = " ";
|
|
1791
|
+
|
|
1688
1792
|
g->outbuf = str_new();
|
|
1689
1793
|
g->failure_str = str_new();
|
|
1690
1794
|
|
|
1691
1795
|
generate_unit_start(g);
|
|
1692
1796
|
|
|
1693
1797
|
/* generate implementation. */
|
|
1798
|
+
if (g->analyser->debug_used) {
|
|
1799
|
+
// System.Io is GNAT-specific, but apparently we can't use Text_IO in a
|
|
1800
|
+
// preelaborated package.
|
|
1801
|
+
w(g, "with System.Io;~N");
|
|
1802
|
+
}
|
|
1694
1803
|
w(g, "package body Stemmer.");
|
|
1695
|
-
|
|
1804
|
+
write_string(g, g->options->package);
|
|
1696
1805
|
w(g, " is~N~+~N");
|
|
1697
1806
|
w(g, "~Mpragma Style_Checks (\"-mr\");~N");
|
|
1698
1807
|
w(g, "~Mpragma Warnings (Off, \"*variable*is never read and never assigned*\");~N");
|
|
@@ -1702,37 +1811,103 @@ extern void generate_program_ada(struct generator * g) {
|
|
|
1702
1811
|
w(g, "~Mpragma Warnings (Off, \"*is not referenced*\");~N");
|
|
1703
1812
|
w(g, "~N");
|
|
1704
1813
|
|
|
1814
|
+
if (g->analyser->debug_used) {
|
|
1815
|
+
w(g, "~N"
|
|
1816
|
+
"~Mprocedure Debug (Z : in Context_Type'Class; N : in Integer; Line : in Integer) is~N~+"
|
|
1817
|
+
"~MLen : Integer;~N"
|
|
1818
|
+
"~MCh : Integer;~N"
|
|
1819
|
+
"~-~Mbegin~N~+"
|
|
1820
|
+
"~Mif N < 10 then~N~+"
|
|
1821
|
+
"~MSystem.Io.Put (\" \");~N"
|
|
1822
|
+
"~-~Mend if;~N"
|
|
1823
|
+
"~Mif N < 100 then~N~+"
|
|
1824
|
+
"~MSystem.Io.Put (\" \");~N"
|
|
1825
|
+
"~-~Mend if;~N"
|
|
1826
|
+
"~MSystem.Io.Put (N);~N"
|
|
1827
|
+
"~MSystem.Io.Put (\" (line \");~N"
|
|
1828
|
+
"~Mif Line < 10 then~N~+"
|
|
1829
|
+
"~MSystem.Io.Put (\" \");~N"
|
|
1830
|
+
"~-~Mend if;~N"
|
|
1831
|
+
"~Mif Line < 100 then~N~+"
|
|
1832
|
+
"~MSystem.Io.Put (\" \");~N"
|
|
1833
|
+
"~-~Mend if;~N"
|
|
1834
|
+
"~Mif Line < 1000 then~N~+"
|
|
1835
|
+
"~MSystem.Io.Put (\" \");~N"
|
|
1836
|
+
"~-~Mend if;~N"
|
|
1837
|
+
"~MSystem.Io.Put (Line);~N"
|
|
1838
|
+
"~MSystem.Io.Put (\"): [\");~N"
|
|
1839
|
+
"~MSystem.Io.Put (Z.Len);~N"
|
|
1840
|
+
"~MSystem.Io.Put (\"]'\");~N"
|
|
1841
|
+
"~MLen := Z.Len;~N"
|
|
1842
|
+
"~Mfor I in 0 .. Len + 1 loop~N~+"
|
|
1843
|
+
"~Mif Z.Lb = I then~N~+"
|
|
1844
|
+
"~MSystem.Io.Put (\"{\");~N"
|
|
1845
|
+
"~-~Mend if;~N"
|
|
1846
|
+
"~Mif Z.Bra = I then~N~+"
|
|
1847
|
+
"~MSystem.Io.Put (\"[\");~N"
|
|
1848
|
+
"~-~Mend if;~N"
|
|
1849
|
+
"~Mif Z.C = I then~N~+"
|
|
1850
|
+
"~MSystem.Io.Put (\"|\");~N"
|
|
1851
|
+
"~-~Mend if;~N"
|
|
1852
|
+
"~Mif Z.Ket = I then~N~+"
|
|
1853
|
+
"~MSystem.Io.Put (\"]\");~N"
|
|
1854
|
+
"~-~Mend if;~N"
|
|
1855
|
+
"~Mif Z.L = I then~N~+"
|
|
1856
|
+
"~MSystem.Io.Put (\"}\");~N"
|
|
1857
|
+
"~-~Mend if;~N"
|
|
1858
|
+
"~Mif I < Len then~N~+"
|
|
1859
|
+
"~MCh := Character'Pos (Z.P (I + 1));~N"
|
|
1860
|
+
"~Mif Ch = 0 then~N~+"
|
|
1861
|
+
"~MSystem.Io.Put (\"#\");~N"
|
|
1862
|
+
"~-~Melse~N~+"
|
|
1863
|
+
"~MSystem.Io.Put (Z.P (I + 1 .. I + 1));~N"
|
|
1864
|
+
"~-~Mend if;~N"
|
|
1865
|
+
"~-~Mend if;~N"
|
|
1866
|
+
"~-~Mend loop;~N"
|
|
1867
|
+
"~MSystem.Io.Put_Line (\"'\");~N"
|
|
1868
|
+
"~-~Mend Debug;~N");
|
|
1869
|
+
}
|
|
1705
1870
|
generate_method_decls(g, t_routine);
|
|
1706
|
-
generate_groupings(g);
|
|
1707
1871
|
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1872
|
+
bool need_among_handler = false;
|
|
1873
|
+
for (struct among * a = g->analyser->amongs; a; a = a->next) {
|
|
1874
|
+
if (a->function_count > 0) {
|
|
1875
|
+
need_among_handler = true;
|
|
1876
|
+
break;
|
|
1877
|
+
}
|
|
1878
|
+
}
|
|
1879
|
+
if (need_among_handler) {
|
|
1880
|
+
w(g, "~N~Mprocedure Among_Handler (Context : in out Stemmer.Context_Type'Class; Operation : in Operation_Index; Result : out Boolean);~N");
|
|
1712
1881
|
}
|
|
1713
1882
|
|
|
1714
|
-
|
|
1715
|
-
|
|
1883
|
+
g->declarations = g->outbuf;
|
|
1884
|
+
g->outbuf = str_new();
|
|
1885
|
+
|
|
1886
|
+
generate_methods(g);
|
|
1887
|
+
|
|
1888
|
+
generate_amongs(g);
|
|
1889
|
+
generate_groupings(g);
|
|
1890
|
+
|
|
1891
|
+
w(g, "~-end Stemmer.");
|
|
1892
|
+
write_string(g, g->options->package);
|
|
1716
1893
|
w(g, ";~N");
|
|
1717
1894
|
|
|
1895
|
+
output_str(g->options->output_src, g->declarations);
|
|
1896
|
+
str_delete(g->declarations);
|
|
1718
1897
|
output_str(g->options->output_src, g->outbuf);
|
|
1719
|
-
|
|
1720
1898
|
str_clear(g->outbuf);
|
|
1721
1899
|
|
|
1722
|
-
g->margin = 0;
|
|
1723
1900
|
write_start_comment(g, "-- ", NULL);
|
|
1724
|
-
if (g->analyser->name_count[t_string]) {
|
|
1725
|
-
w(g, "private with Ada.Strings.Unbounded;~N");
|
|
1726
|
-
}
|
|
1727
1901
|
w(g, "package Stemmer.");
|
|
1728
|
-
|
|
1902
|
+
write_string(g, g->options->package);
|
|
1729
1903
|
w(g, " with SPARK_Mode is~N~+");
|
|
1730
1904
|
w(g, " type Context_Type is new Stemmer.Context_Type with private;~N");
|
|
1731
|
-
|
|
1905
|
+
generate_method_decls(g, t_external);
|
|
1906
|
+
|
|
1732
1907
|
w(g, "private~N");
|
|
1733
1908
|
generate_member_decls(g);
|
|
1734
1909
|
w(g, "end Stemmer.");
|
|
1735
|
-
|
|
1910
|
+
write_string(g, g->options->package);
|
|
1736
1911
|
w(g, ";~N");
|
|
1737
1912
|
output_str(g->options->output_h, g->outbuf);
|
|
1738
1913
|
str_delete(g->failure_str);
|