ruco-cpp 0.2.1
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 +7 -0
- data/Rakefile +17 -0
- data/bin/console +14 -0
- data/bin/ruco +30 -0
- data/bin/setup +7 -0
- data/data/ruco/Parser.frame +359 -0
- data/data/ruco/Scanner.frame +896 -0
- data/data/ruco/picojson/Changes +14 -0
- data/data/ruco/picojson/LICENSE +25 -0
- data/data/ruco/picojson/Makefile +8 -0
- data/data/ruco/picojson/README.mkdn +183 -0
- data/data/ruco/picojson/examples/github-issues.cc +110 -0
- data/data/ruco/picojson/examples/iostream.cc +70 -0
- data/data/ruco/picojson/examples/streaming.cc +76 -0
- data/data/ruco/picojson/picojson.h +1299 -0
- data/ext/cocor/Action.cpp +81 -0
- data/ext/cocor/Action.h +59 -0
- data/ext/cocor/ArrayList.cpp +79 -0
- data/ext/cocor/ArrayList.h +52 -0
- data/ext/cocor/BitArray.cpp +156 -0
- data/ext/cocor/BitArray.h +68 -0
- data/ext/cocor/CharClass.cpp +42 -0
- data/ext/cocor/CharClass.h +48 -0
- data/ext/cocor/CharSet.cpp +166 -0
- data/ext/cocor/CharSet.h +68 -0
- data/ext/cocor/Coco.atg +528 -0
- data/ext/cocor/Coco.cpp +173 -0
- data/ext/cocor/Comment.cpp +45 -0
- data/ext/cocor/Comment.h +51 -0
- data/ext/cocor/Copyright.frame +27 -0
- data/ext/cocor/DFA.cpp +865 -0
- data/ext/cocor/DFA.h +132 -0
- data/ext/cocor/Generator.cpp +182 -0
- data/ext/cocor/Generator.h +61 -0
- data/ext/cocor/Graph.h +59 -0
- data/ext/cocor/HashTable.cpp +115 -0
- data/ext/cocor/HashTable.h +84 -0
- data/ext/cocor/Makefile +11 -0
- data/ext/cocor/Melted.cpp +39 -0
- data/ext/cocor/Melted.h +51 -0
- data/ext/cocor/Node.cpp +69 -0
- data/ext/cocor/Node.h +86 -0
- data/ext/cocor/Parser.cpp +925 -0
- data/ext/cocor/Parser.frame +326 -0
- data/ext/cocor/Parser.h +153 -0
- data/ext/cocor/ParserGen.cpp +486 -0
- data/ext/cocor/ParserGen.h +99 -0
- data/ext/cocor/Position.cpp +37 -0
- data/ext/cocor/Position.h +46 -0
- data/ext/cocor/README.md +12 -0
- data/ext/cocor/Scanner.cpp +833 -0
- data/ext/cocor/Scanner.frame +897 -0
- data/ext/cocor/Scanner.h +291 -0
- data/ext/cocor/Sets.h +84 -0
- data/ext/cocor/SortedList.cpp +141 -0
- data/ext/cocor/SortedList.h +68 -0
- data/ext/cocor/State.cpp +77 -0
- data/ext/cocor/State.h +55 -0
- data/ext/cocor/StringBuilder.cpp +88 -0
- data/ext/cocor/StringBuilder.h +29 -0
- data/ext/cocor/Symbol.cpp +61 -0
- data/ext/cocor/Symbol.h +70 -0
- data/ext/cocor/Tab.cpp +1248 -0
- data/ext/cocor/Tab.h +245 -0
- data/ext/cocor/Target.cpp +41 -0
- data/ext/cocor/Target.h +48 -0
- data/ext/cocor/build.bat +3 -0
- data/ext/cocor/build.sh +4 -0
- data/ext/cocor/coc.bat +1 -0
- data/ext/cocor/coc.sh +2 -0
- data/ext/cocor/cocor_ruby_ext.cpp +124 -0
- data/ext/cocor/cygBuild.bat +1 -0
- data/ext/cocor/extconf.rb +5 -0
- data/ext/cocor/mingwbuild.bat +2 -0
- data/ext/cocor/mkmf.log +57 -0
- data/ext/cocor/zipsources.bat +1 -0
- data/lib/cocor.rb +14 -0
- data/lib/ruco/version.rb +3 -0
- data/lib/ruco.rb +728 -0
- metadata +195 -0
@@ -0,0 +1,486 @@
|
|
1
|
+
/*-------------------------------------------------------------------------
|
2
|
+
ParserGen -- Generation of the Recursive Descent Parser
|
3
|
+
Compiler Generator Coco/R,
|
4
|
+
Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz
|
5
|
+
ported to C++ by Csaba Balazs, University of Szeged
|
6
|
+
extended by M. Loeberbauer & A. Woess, Univ. of Linz
|
7
|
+
with improvements by Pat Terry, Rhodes University
|
8
|
+
|
9
|
+
This program is free software; you can redistribute it and/or modify it
|
10
|
+
under the terms of the GNU General Public License as published by the
|
11
|
+
Free Software Foundation; either version 2, or (at your option) any
|
12
|
+
later version.
|
13
|
+
|
14
|
+
This program is distributed in the hope that it will be useful, but
|
15
|
+
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
16
|
+
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
17
|
+
for more details.
|
18
|
+
|
19
|
+
You should have received a copy of the GNU General Public License along
|
20
|
+
with this program; if not, write to the Free Software Foundation, Inc.,
|
21
|
+
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
22
|
+
|
23
|
+
As an exception, it is allowed to write an extension of Coco/R that is
|
24
|
+
used as a plugin in non-free software.
|
25
|
+
|
26
|
+
If not otherwise stated, any source code generated by Coco/R (other than
|
27
|
+
Coco/R itself) does not fall under the GNU General Public License.
|
28
|
+
-------------------------------------------------------------------------*/
|
29
|
+
|
30
|
+
#include <ctype.h>
|
31
|
+
#include "ArrayList.h"
|
32
|
+
#include "ParserGen.h"
|
33
|
+
#include "Parser.h"
|
34
|
+
#include "BitArray.h"
|
35
|
+
#include "Scanner.h"
|
36
|
+
#include "Generator.h"
|
37
|
+
|
38
|
+
namespace Coco {
|
39
|
+
|
40
|
+
void ParserGen::Indent (int n) {
|
41
|
+
for (int i = 1; i <= n; i++) fwprintf(gen, L"\t");
|
42
|
+
}
|
43
|
+
|
44
|
+
// use a switch if more than 5 alternatives and none starts with a resolver, and no LL1 warning
|
45
|
+
bool ParserGen::UseSwitch (Node *p) {
|
46
|
+
BitArray *s1, *s2;
|
47
|
+
if (p->typ != Node::alt) return false;
|
48
|
+
int nAlts = 0;
|
49
|
+
s1 = new BitArray(tab->terminals->Count);
|
50
|
+
while (p != NULL) {
|
51
|
+
s2 = tab->Expected0(p->sub, curSy);
|
52
|
+
// must not optimize with switch statement, if there are ll1 warnings
|
53
|
+
if (s1->Overlaps(s2)) { return false; }
|
54
|
+
s1->Or(s2);
|
55
|
+
++nAlts;
|
56
|
+
// must not optimize with switch-statement, if alt uses a resolver expression
|
57
|
+
if (p->sub->typ == Node::rslv) return false;
|
58
|
+
p = p->down;
|
59
|
+
}
|
60
|
+
return nAlts > 5;
|
61
|
+
}
|
62
|
+
|
63
|
+
int ParserGen::GenNamespaceOpen(const wchar_t *nsName) {
|
64
|
+
if (nsName == NULL || coco_string_length(nsName) == 0) {
|
65
|
+
return 0;
|
66
|
+
}
|
67
|
+
const int len = coco_string_length(nsName);
|
68
|
+
int startPos = 0;
|
69
|
+
int nrOfNs = 0;
|
70
|
+
do {
|
71
|
+
int curLen = coco_string_indexof(nsName + startPos, COCO_CPP_NAMESPACE_SEPARATOR);
|
72
|
+
if (curLen == -1) { curLen = len - startPos; }
|
73
|
+
wchar_t *curNs = coco_string_create(nsName, startPos, curLen);
|
74
|
+
fwprintf(gen, L"namespace %ls {\n", curNs);
|
75
|
+
coco_string_delete(curNs);
|
76
|
+
startPos = startPos + curLen + 1;
|
77
|
+
if (startPos < len && nsName[startPos] == COCO_CPP_NAMESPACE_SEPARATOR) {
|
78
|
+
++startPos;
|
79
|
+
}
|
80
|
+
++nrOfNs;
|
81
|
+
} while (startPos < len);
|
82
|
+
return nrOfNs;
|
83
|
+
}
|
84
|
+
|
85
|
+
void ParserGen::GenNamespaceClose(int nrOfNs) {
|
86
|
+
for (int i = 0; i < nrOfNs; ++i) {
|
87
|
+
fwprintf(gen, L"} // namespace\n");
|
88
|
+
}
|
89
|
+
}
|
90
|
+
|
91
|
+
void ParserGen::CopySourcePart (Position *pos, int indent) {
|
92
|
+
// Copy text described by pos from atg to gen
|
93
|
+
int ch, i;
|
94
|
+
if (pos != NULL) {
|
95
|
+
buffer->SetPos(pos->beg); ch = buffer->Read();
|
96
|
+
if (tab->emitLines && pos->line) {
|
97
|
+
fwprintf(gen, L"\n#line %d \"%ls\"\n", pos->line, tab->srcName);
|
98
|
+
}
|
99
|
+
Indent(indent);
|
100
|
+
while (buffer->GetPos() <= pos->end) {
|
101
|
+
while (ch == CR || ch == LF) { // eol is either CR or CRLF or LF
|
102
|
+
fwprintf(gen, L"\n"); Indent(indent);
|
103
|
+
if (ch == CR) { ch = buffer->Read(); } // skip CR
|
104
|
+
if (ch == LF) { ch = buffer->Read(); } // skip LF
|
105
|
+
for (i = 1; i <= pos->col && (ch == ' ' || ch == '\t'); i++) {
|
106
|
+
// skip blanks at beginning of line
|
107
|
+
ch = buffer->Read();
|
108
|
+
}
|
109
|
+
if (buffer->GetPos() > pos->end) goto done;
|
110
|
+
}
|
111
|
+
fwprintf(gen, L"%lc", ch);
|
112
|
+
ch = buffer->Read();
|
113
|
+
}
|
114
|
+
done:
|
115
|
+
if (indent > 0) fwprintf(gen, L"\n");
|
116
|
+
}
|
117
|
+
}
|
118
|
+
|
119
|
+
void ParserGen::GenErrorMsg (int errTyp, Symbol *sym) {
|
120
|
+
errorNr++;
|
121
|
+
const int formatLen = 1000;
|
122
|
+
wchar_t format[formatLen];
|
123
|
+
coco_swprintf(format, formatLen, L"\t\t\tcase %d: s = coco_string_create(L\"", errorNr);
|
124
|
+
coco_string_merge(err, format);
|
125
|
+
if (errTyp == tErr) {
|
126
|
+
if (sym->name[0] == L'"') {
|
127
|
+
coco_swprintf(format, formatLen, L"%ls expected", tab->Escape(sym->name));
|
128
|
+
coco_string_merge(err, format);
|
129
|
+
} else {
|
130
|
+
coco_swprintf(format, formatLen, L"%ls expected", sym->name);
|
131
|
+
coco_string_merge(err, format);
|
132
|
+
}
|
133
|
+
} else if (errTyp == altErr) {
|
134
|
+
coco_swprintf(format, formatLen, L"invalid %ls", sym->name);
|
135
|
+
coco_string_merge(err, format);
|
136
|
+
} else if (errTyp == syncErr) {
|
137
|
+
coco_swprintf(format, formatLen, L"this symbol not expected in %ls", sym->name);
|
138
|
+
coco_string_merge(err, format);
|
139
|
+
}
|
140
|
+
coco_swprintf(format, formatLen, L"\"); break;\n");
|
141
|
+
coco_string_merge(err, format);
|
142
|
+
}
|
143
|
+
|
144
|
+
int ParserGen::NewCondSet (BitArray *s) {
|
145
|
+
for (int i = 1; i < symSet->Count; i++) // skip symSet[0] (reserved for union of SYNC sets)
|
146
|
+
if (Sets::Equals(s, (BitArray*)(*symSet)[i])) return i;
|
147
|
+
symSet->Add(s->Clone());
|
148
|
+
return symSet->Count - 1;
|
149
|
+
}
|
150
|
+
|
151
|
+
void ParserGen::GenCond (BitArray *s, Node *p) {
|
152
|
+
if (p->typ == Node::rslv) CopySourcePart(p->pos, 0);
|
153
|
+
else {
|
154
|
+
int n = Sets::Elements(s);
|
155
|
+
if (n == 0) fwprintf(gen, L"false"); // happens if an ANY set matches no symbol
|
156
|
+
else if (n <= maxTerm) {
|
157
|
+
Symbol *sym;
|
158
|
+
for (int i=0; i<tab->terminals->Count; i++) {
|
159
|
+
sym = (Symbol*)((*(tab->terminals))[i]);
|
160
|
+
if ((*s)[sym->n]) {
|
161
|
+
fwprintf(gen, L"la->kind == ");
|
162
|
+
WriteSymbolOrCode(gen, sym);
|
163
|
+
--n;
|
164
|
+
if (n > 0) fwprintf(gen, L" || ");
|
165
|
+
}
|
166
|
+
}
|
167
|
+
} else
|
168
|
+
fwprintf(gen, L"StartOf(%d)", NewCondSet(s));
|
169
|
+
}
|
170
|
+
}
|
171
|
+
|
172
|
+
void ParserGen::PutCaseLabels (BitArray *s) {
|
173
|
+
Symbol *sym;
|
174
|
+
for (int i=0; i<tab->terminals->Count; i++) {
|
175
|
+
sym = (Symbol*)((*(tab->terminals))[i]);
|
176
|
+
if ((*s)[sym->n]) {
|
177
|
+
fwprintf(gen, L"case ");
|
178
|
+
WriteSymbolOrCode(gen, sym);
|
179
|
+
fwprintf(gen, L": ");
|
180
|
+
}
|
181
|
+
}
|
182
|
+
}
|
183
|
+
|
184
|
+
void ParserGen::GenCode (Node *p, int indent, BitArray *isChecked) {
|
185
|
+
Node *p2;
|
186
|
+
BitArray *s1, *s2;
|
187
|
+
while (p != NULL) {
|
188
|
+
if (p->typ == Node::nt) {
|
189
|
+
Indent(indent);
|
190
|
+
fwprintf(gen, L"%ls(", p->sym->name);
|
191
|
+
CopySourcePart(p->pos, 0);
|
192
|
+
fwprintf(gen, L");\n");
|
193
|
+
} else if (p->typ == Node::t) {
|
194
|
+
Indent(indent);
|
195
|
+
// assert: if isChecked[p->sym->n] is true, then isChecked contains only p->sym->n
|
196
|
+
if ((*isChecked)[p->sym->n]) fwprintf(gen, L"Get();\n");
|
197
|
+
else {
|
198
|
+
fwprintf(gen, L"Expect(");
|
199
|
+
WriteSymbolOrCode(gen, p->sym);
|
200
|
+
fwprintf(gen, L");\n");
|
201
|
+
}
|
202
|
+
} if (p->typ == Node::wt) {
|
203
|
+
Indent(indent);
|
204
|
+
s1 = tab->Expected(p->next, curSy);
|
205
|
+
s1->Or(tab->allSyncSets);
|
206
|
+
fwprintf(gen, L"ExpectWeak(");
|
207
|
+
WriteSymbolOrCode(gen, p->sym);
|
208
|
+
fwprintf(gen, L", %d);\n", NewCondSet(s1));
|
209
|
+
} if (p->typ == Node::any) {
|
210
|
+
Indent(indent);
|
211
|
+
int acc = Sets::Elements(p->set);
|
212
|
+
if (tab->terminals->Count == (acc + 1) || (acc > 0 && Sets::Equals(p->set, isChecked))) {
|
213
|
+
// either this ANY accepts any terminal (the + 1 = end of file), or exactly what's allowed here
|
214
|
+
fwprintf(gen, L"Get();\n");
|
215
|
+
} else {
|
216
|
+
GenErrorMsg(altErr, curSy);
|
217
|
+
if (acc > 0) {
|
218
|
+
fwprintf(gen, L"if ("); GenCond(p->set, p); fwprintf(gen, L") Get(); else SynErr(%d);\n", errorNr);
|
219
|
+
} else fwprintf(gen, L"SynErr(%d); // ANY node that matches no symbol\n", errorNr);
|
220
|
+
}
|
221
|
+
} if (p->typ == Node::eps) { // nothing
|
222
|
+
} if (p->typ == Node::rslv) { // nothing
|
223
|
+
} if (p->typ == Node::sem) {
|
224
|
+
CopySourcePart(p->pos, indent);
|
225
|
+
} if (p->typ == Node::sync) {
|
226
|
+
Indent(indent);
|
227
|
+
GenErrorMsg(syncErr, curSy);
|
228
|
+
s1 = p->set->Clone();
|
229
|
+
fwprintf(gen, L"while (!("); GenCond(s1, p); fwprintf(gen, L")) {");
|
230
|
+
fwprintf(gen, L"SynErr(%d); Get();", errorNr); fwprintf(gen, L"}\n");
|
231
|
+
} if (p->typ == Node::alt) {
|
232
|
+
s1 = tab->First(p);
|
233
|
+
bool equal = Sets::Equals(s1, isChecked);
|
234
|
+
bool useSwitch = UseSwitch(p);
|
235
|
+
if (useSwitch) { Indent(indent); fwprintf(gen, L"switch (la->kind) {\n"); }
|
236
|
+
p2 = p;
|
237
|
+
while (p2 != NULL) {
|
238
|
+
s1 = tab->Expected(p2->sub, curSy);
|
239
|
+
Indent(indent);
|
240
|
+
if (useSwitch) {
|
241
|
+
PutCaseLabels(s1); fwprintf(gen, L"{\n");
|
242
|
+
} else if (p2 == p) {
|
243
|
+
fwprintf(gen, L"if ("); GenCond(s1, p2->sub); fwprintf(gen, L") {\n");
|
244
|
+
} else if (p2->down == NULL && equal) { fwprintf(gen, L"} else {\n");
|
245
|
+
} else {
|
246
|
+
fwprintf(gen, L"} else if ("); GenCond(s1, p2->sub); fwprintf(gen, L") {\n");
|
247
|
+
}
|
248
|
+
GenCode(p2->sub, indent + 1, s1);
|
249
|
+
if (useSwitch) {
|
250
|
+
Indent(indent); fwprintf(gen, L"\tbreak;\n");
|
251
|
+
Indent(indent); fwprintf(gen, L"}\n");
|
252
|
+
}
|
253
|
+
p2 = p2->down;
|
254
|
+
}
|
255
|
+
Indent(indent);
|
256
|
+
if (equal) {
|
257
|
+
fwprintf(gen, L"}\n");
|
258
|
+
} else {
|
259
|
+
GenErrorMsg(altErr, curSy);
|
260
|
+
if (useSwitch) {
|
261
|
+
fwprintf(gen, L"default: SynErr(%d); break;\n", errorNr);
|
262
|
+
Indent(indent); fwprintf(gen, L"}\n");
|
263
|
+
} else {
|
264
|
+
fwprintf(gen, L"} "); fwprintf(gen, L"else SynErr(%d);\n", errorNr);
|
265
|
+
}
|
266
|
+
}
|
267
|
+
} if (p->typ == Node::iter) {
|
268
|
+
Indent(indent);
|
269
|
+
p2 = p->sub;
|
270
|
+
fwprintf(gen, L"while (");
|
271
|
+
if (p2->typ == Node::wt) {
|
272
|
+
s1 = tab->Expected(p2->next, curSy);
|
273
|
+
s2 = tab->Expected(p->next, curSy);
|
274
|
+
fwprintf(gen, L"WeakSeparator(");
|
275
|
+
WriteSymbolOrCode(gen, p2->sym);
|
276
|
+
fwprintf(gen, L",%d,%d) ", NewCondSet(s1), NewCondSet(s2));
|
277
|
+
s1 = new BitArray(tab->terminals->Count); // for inner structure
|
278
|
+
if (p2->up || p2->next == NULL) p2 = NULL; else p2 = p2->next;
|
279
|
+
} else {
|
280
|
+
s1 = tab->First(p2);
|
281
|
+
GenCond(s1, p2);
|
282
|
+
}
|
283
|
+
fwprintf(gen, L") {\n");
|
284
|
+
GenCode(p2, indent + 1, s1);
|
285
|
+
Indent(indent); fwprintf(gen, L"}\n");
|
286
|
+
} if (p->typ == Node::opt) {
|
287
|
+
s1 = tab->First(p->sub);
|
288
|
+
Indent(indent);
|
289
|
+
fwprintf(gen, L"if ("); GenCond(s1, p->sub); fwprintf(gen, L") {\n");
|
290
|
+
GenCode(p->sub, indent + 1, s1);
|
291
|
+
Indent(indent); fwprintf(gen, L"}\n");
|
292
|
+
}
|
293
|
+
if (p->typ != Node::eps && p->typ != Node::sem && p->typ != Node::sync)
|
294
|
+
isChecked->SetAll(false); // = new BitArray(Symbol.terminals.Count);
|
295
|
+
if (p->up) break;
|
296
|
+
p = p->next;
|
297
|
+
}
|
298
|
+
}
|
299
|
+
|
300
|
+
|
301
|
+
void ParserGen::GenTokensHeader() {
|
302
|
+
Symbol *sym;
|
303
|
+
int i;
|
304
|
+
bool isFirst = true;
|
305
|
+
|
306
|
+
fwprintf(gen, L"\tenum {\n");
|
307
|
+
|
308
|
+
// tokens
|
309
|
+
for (i=0; i<tab->terminals->Count; i++) {
|
310
|
+
sym = (Symbol*)((*(tab->terminals))[i]);
|
311
|
+
if (!isalpha(sym->name[0])) { continue; }
|
312
|
+
|
313
|
+
if (isFirst) { isFirst = false; }
|
314
|
+
else { fwprintf(gen , L",\n"); }
|
315
|
+
|
316
|
+
fwprintf(gen , L"\t\t_%ls=%d", sym->name, sym->n);
|
317
|
+
}
|
318
|
+
|
319
|
+
// pragmas
|
320
|
+
for (i=0; i<tab->pragmas->Count; i++) {
|
321
|
+
if (isFirst) { isFirst = false; }
|
322
|
+
else { fwprintf(gen , L",\n"); }
|
323
|
+
|
324
|
+
sym = (Symbol*)((*(tab->pragmas))[i]);
|
325
|
+
fwprintf(gen , L"\t\t_%ls=%d", sym->name, sym->n);
|
326
|
+
}
|
327
|
+
|
328
|
+
fwprintf(gen, L"\n\t};\n");
|
329
|
+
}
|
330
|
+
|
331
|
+
void ParserGen::GenCodePragmas() {
|
332
|
+
Symbol *sym;
|
333
|
+
for (int i=0; i<tab->pragmas->Count; i++) {
|
334
|
+
sym = (Symbol*)((*(tab->pragmas))[i]);
|
335
|
+
fwprintf(gen, L"\t\tif (la->kind == ");
|
336
|
+
WriteSymbolOrCode(gen, sym);
|
337
|
+
fwprintf(gen, L") {\n");
|
338
|
+
CopySourcePart(sym->semPos, 4);
|
339
|
+
fwprintf(gen, L"\t\t}\n");
|
340
|
+
}
|
341
|
+
}
|
342
|
+
|
343
|
+
void ParserGen::WriteSymbolOrCode(FILE *gen, const Symbol *sym) {
|
344
|
+
if (!isalpha(sym->name[0])) {
|
345
|
+
fwprintf(gen, L"%d /* %ls */", sym->n, sym->name);
|
346
|
+
} else {
|
347
|
+
fwprintf(gen, L"_%ls", sym->name);
|
348
|
+
}
|
349
|
+
}
|
350
|
+
|
351
|
+
void ParserGen::GenProductionsHeader() {
|
352
|
+
Symbol *sym;
|
353
|
+
for (int i=0; i<tab->nonterminals->Count; i++) {
|
354
|
+
sym = (Symbol*)((*(tab->nonterminals))[i]);
|
355
|
+
curSy = sym;
|
356
|
+
fwprintf(gen, L"\tvoid %ls(", sym->name);
|
357
|
+
CopySourcePart(sym->attrPos, 0);
|
358
|
+
fwprintf(gen, L");\n");
|
359
|
+
}
|
360
|
+
}
|
361
|
+
|
362
|
+
void ParserGen::GenProductions() {
|
363
|
+
Symbol *sym;
|
364
|
+
for (int i=0; i<tab->nonterminals->Count; i++) {
|
365
|
+
sym = (Symbol*)((*(tab->nonterminals))[i]);
|
366
|
+
curSy = sym;
|
367
|
+
fwprintf(gen, L"void Parser::%ls(", sym->name);
|
368
|
+
CopySourcePart(sym->attrPos, 0);
|
369
|
+
fwprintf(gen, L") {\n");
|
370
|
+
CopySourcePart(sym->semPos, 2);
|
371
|
+
GenCode(sym->graph, 2, new BitArray(tab->terminals->Count));
|
372
|
+
fwprintf(gen, L"}\n"); fwprintf(gen, L"\n");
|
373
|
+
}
|
374
|
+
}
|
375
|
+
|
376
|
+
void ParserGen::InitSets() {
|
377
|
+
fwprintf(gen, L"\tstatic bool set[%d][%d] = {\n", symSet->Count, tab->terminals->Count+1);
|
378
|
+
|
379
|
+
for (int i = 0; i < symSet->Count; i++) {
|
380
|
+
BitArray *s = (BitArray*)(*symSet)[i];
|
381
|
+
fwprintf(gen, L"\t\t{");
|
382
|
+
int j = 0;
|
383
|
+
Symbol *sym;
|
384
|
+
for (int k=0; k<tab->terminals->Count; k++) {
|
385
|
+
sym = (Symbol*)((*(tab->terminals))[k]);
|
386
|
+
if ((*s)[sym->n]) fwprintf(gen, L"T,"); else fwprintf(gen, L"x,");
|
387
|
+
++j;
|
388
|
+
if (j%4 == 0) fwprintf(gen, L" ");
|
389
|
+
}
|
390
|
+
if (i == symSet->Count-1) fwprintf(gen, L"x}\n"); else fwprintf(gen, L"x},\n");
|
391
|
+
}
|
392
|
+
fwprintf(gen, L"\t};\n\n");
|
393
|
+
}
|
394
|
+
|
395
|
+
void ParserGen::WriteParser () {
|
396
|
+
Generator g = Generator(tab, errors);
|
397
|
+
int oldPos = buffer->GetPos(); // Pos is modified by CopySourcePart
|
398
|
+
symSet->Add(tab->allSyncSets);
|
399
|
+
|
400
|
+
fram = g.OpenFrame(L"Parser.frame");
|
401
|
+
gen = g.OpenGen(L"Parser.h");
|
402
|
+
|
403
|
+
Symbol *sym;
|
404
|
+
for (int i=0; i<tab->terminals->Count; i++) {
|
405
|
+
sym = (Symbol*)((*(tab->terminals))[i]);
|
406
|
+
GenErrorMsg(tErr, sym);
|
407
|
+
}
|
408
|
+
|
409
|
+
g.GenCopyright();
|
410
|
+
g.SkipFramePart(L"-->begin");
|
411
|
+
|
412
|
+
g.CopyFramePart(L"-->prefix");
|
413
|
+
g.GenPrefixFromNamespace();
|
414
|
+
|
415
|
+
g.CopyFramePart(L"-->prefix");
|
416
|
+
g.GenPrefixFromNamespace();
|
417
|
+
|
418
|
+
g.CopyFramePart(L"-->headerdef");
|
419
|
+
|
420
|
+
if (usingPos != NULL) {CopySourcePart(usingPos, 0); fwprintf(gen, L"\n");}
|
421
|
+
g.CopyFramePart(L"-->namespace_open");
|
422
|
+
int nrOfNs = GenNamespaceOpen(tab->nsName);
|
423
|
+
|
424
|
+
g.CopyFramePart(L"-->constantsheader");
|
425
|
+
GenTokensHeader(); /* ML 2002/09/07 write the token kinds */
|
426
|
+
fwprintf(gen, L"\tint maxT;\n");
|
427
|
+
g.CopyFramePart(L"-->declarations"); CopySourcePart(tab->semDeclPos, 0);
|
428
|
+
g.CopyFramePart(L"-->productionsheader"); GenProductionsHeader();
|
429
|
+
g.CopyFramePart(L"-->namespace_close");
|
430
|
+
GenNamespaceClose(nrOfNs);
|
431
|
+
|
432
|
+
g.CopyFramePart(L"-->implementation");
|
433
|
+
fclose(gen);
|
434
|
+
|
435
|
+
// Source
|
436
|
+
gen = g.OpenGen(L"Parser.cpp");
|
437
|
+
|
438
|
+
g.GenCopyright();
|
439
|
+
g.SkipFramePart(L"-->begin");
|
440
|
+
g.CopyFramePart(L"-->namespace_open");
|
441
|
+
nrOfNs = GenNamespaceOpen(tab->nsName);
|
442
|
+
|
443
|
+
g.CopyFramePart(L"-->pragmas"); GenCodePragmas();
|
444
|
+
g.CopyFramePart(L"-->productions"); GenProductions();
|
445
|
+
g.CopyFramePart(L"-->parseRoot"); fwprintf(gen, L"\t%ls();\n", tab->gramSy->name); if (tab->checkEOF) fwprintf(gen, L"\tExpect(0);");
|
446
|
+
g.CopyFramePart(L"-->constants");
|
447
|
+
fwprintf(gen, L"\tmaxT = %d;\n", tab->terminals->Count-1);
|
448
|
+
g.CopyFramePart(L"-->initialization"); InitSets();
|
449
|
+
g.CopyFramePart(L"-->errors"); fwprintf(gen, L"%ls", err);
|
450
|
+
g.CopyFramePart(L"-->namespace_close");
|
451
|
+
GenNamespaceClose(nrOfNs);
|
452
|
+
g.CopyFramePart(NULL);
|
453
|
+
fclose(gen);
|
454
|
+
buffer->SetPos(oldPos);
|
455
|
+
}
|
456
|
+
|
457
|
+
|
458
|
+
void ParserGen::WriteStatistics () {
|
459
|
+
fwprintf(trace, L"\n");
|
460
|
+
fwprintf(trace, L"%d terminals\n", tab->terminals->Count);
|
461
|
+
fwprintf(trace, L"%d symbols\n", tab->terminals->Count + tab->pragmas->Count +
|
462
|
+
tab->nonterminals->Count);
|
463
|
+
fwprintf(trace, L"%d nodes\n", tab->nodes->Count);
|
464
|
+
fwprintf(trace, L"%d sets\n", symSet->Count);
|
465
|
+
}
|
466
|
+
|
467
|
+
|
468
|
+
ParserGen::ParserGen (Parser *parser) {
|
469
|
+
maxTerm = 3;
|
470
|
+
CR = '\r';
|
471
|
+
LF = '\n';
|
472
|
+
tErr = 0;
|
473
|
+
altErr = 1;
|
474
|
+
syncErr = 2;
|
475
|
+
tab = parser->tab;
|
476
|
+
errors = parser->errors;
|
477
|
+
trace = parser->trace;
|
478
|
+
buffer = parser->scanner->buffer;
|
479
|
+
errorNr = -1;
|
480
|
+
usingPos = NULL;
|
481
|
+
|
482
|
+
symSet = new ArrayList();
|
483
|
+
err = NULL;
|
484
|
+
}
|
485
|
+
|
486
|
+
}; // namespace
|
@@ -0,0 +1,99 @@
|
|
1
|
+
/*-------------------------------------------------------------------------
|
2
|
+
ParserGen -- Generation of the Recursive Descent Parser
|
3
|
+
Compiler Generator Coco/R,
|
4
|
+
Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz
|
5
|
+
ported to C++ by Csaba Balazs, University of Szeged
|
6
|
+
extended by M. Loeberbauer & A. Woess, Univ. of Linz
|
7
|
+
with improvements by Pat Terry, Rhodes University
|
8
|
+
|
9
|
+
This program is free software; you can redistribute it and/or modify it
|
10
|
+
under the terms of the GNU General Public License as published by the
|
11
|
+
Free Software Foundation; either version 2, or (at your option) any
|
12
|
+
later version.
|
13
|
+
|
14
|
+
This program is distributed in the hope that it will be useful, but
|
15
|
+
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
16
|
+
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
17
|
+
for more details.
|
18
|
+
|
19
|
+
You should have received a copy of the GNU General Public License along
|
20
|
+
with this program; if not, write to the Free Software Foundation, Inc.,
|
21
|
+
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
22
|
+
|
23
|
+
As an exception, it is allowed to write an extension of Coco/R that is
|
24
|
+
used as a plugin in non-free software.
|
25
|
+
|
26
|
+
If not otherwise stated, any source code generated by Coco/R (other than
|
27
|
+
Coco/R itself) does not fall under the GNU General Public License.
|
28
|
+
-------------------------------------------------------------------------*/
|
29
|
+
|
30
|
+
#if !defined(COCO_PARSERGEN_H__)
|
31
|
+
#define COCO_PARSERGEN_H__
|
32
|
+
|
33
|
+
#include "Position.h"
|
34
|
+
#include "Tab.h"
|
35
|
+
#include "Symbol.h"
|
36
|
+
#include "Scanner.h"
|
37
|
+
#include "DFA.h"
|
38
|
+
|
39
|
+
namespace Coco {
|
40
|
+
|
41
|
+
class Errors;
|
42
|
+
class Parser;
|
43
|
+
class BitArray;
|
44
|
+
|
45
|
+
class ParserGen
|
46
|
+
{
|
47
|
+
public:
|
48
|
+
int maxTerm; // sets of size < maxTerm are enumerated
|
49
|
+
char CR;
|
50
|
+
char LF;
|
51
|
+
|
52
|
+
int tErr; // error codes
|
53
|
+
int altErr;
|
54
|
+
int syncErr;
|
55
|
+
|
56
|
+
Position *usingPos; // "using" definitions from the attributed grammar
|
57
|
+
|
58
|
+
int errorNr; // highest parser error number
|
59
|
+
Symbol *curSy; // symbol whose production is currently generated
|
60
|
+
FILE* fram; // parser frame file
|
61
|
+
FILE* gen; // generated parser source file
|
62
|
+
wchar_t* err; // generated parser error messages
|
63
|
+
ArrayList *symSet;
|
64
|
+
|
65
|
+
Tab *tab; // other Coco objects
|
66
|
+
FILE* trace;
|
67
|
+
Errors *errors;
|
68
|
+
Buffer *buffer;
|
69
|
+
|
70
|
+
void Indent(int n);
|
71
|
+
bool UseSwitch(Node *p);
|
72
|
+
void CopyFramePart(const wchar_t* stop);
|
73
|
+
void CopySourcePart(Position *pos, int indent);
|
74
|
+
int GenNamespaceOpen(const wchar_t* nsName);
|
75
|
+
void GenNamespaceClose(int nrOfNs);
|
76
|
+
void GenErrorMsg(int errTyp, Symbol *sym);
|
77
|
+
int NewCondSet(BitArray *s);
|
78
|
+
void GenCond(BitArray *s, Node *p);
|
79
|
+
void PutCaseLabels(BitArray *s);
|
80
|
+
void GenCode(Node *p, int indent, BitArray *isChecked);
|
81
|
+
void GenTokens();
|
82
|
+
void GenTokensHeader();
|
83
|
+
void GenPragmas();
|
84
|
+
void GenPragmasHeader();
|
85
|
+
void GenCodePragmas();
|
86
|
+
void GenProductions();
|
87
|
+
void GenProductionsHeader();
|
88
|
+
void InitSets();
|
89
|
+
void OpenGen(const wchar_t* genName, bool backUp);
|
90
|
+
void WriteParser();
|
91
|
+
void WriteStatistics();
|
92
|
+
void WriteSymbolOrCode(FILE *gen, const Symbol *sym);
|
93
|
+
ParserGen (Parser *parser);
|
94
|
+
|
95
|
+
};
|
96
|
+
|
97
|
+
}; // namespace
|
98
|
+
|
99
|
+
#endif // !defined(COCO_PARSERGEN_H__)
|
@@ -0,0 +1,37 @@
|
|
1
|
+
/*-------------------------------------------------------------------------
|
2
|
+
Compiler Generator Coco/R,
|
3
|
+
Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz
|
4
|
+
extended by M. Loeberbauer & A. Woess, Univ. of Linz
|
5
|
+
ported to C++ by Csaba Balazs, University of Szeged
|
6
|
+
with improvements by Pat Terry, Rhodes University
|
7
|
+
|
8
|
+
This program is free software; you can redistribute it and/or modify it
|
9
|
+
under the terms of the GNU General Public License as published by the
|
10
|
+
Free Software Foundation; either version 2, or (at your option) any
|
11
|
+
later version.
|
12
|
+
|
13
|
+
This program is distributed in the hope that it will be useful, but
|
14
|
+
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
15
|
+
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
16
|
+
for more details.
|
17
|
+
|
18
|
+
You should have received a copy of the GNU General Public License along
|
19
|
+
with this program; if not, write to the Free Software Foundation, Inc.,
|
20
|
+
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
21
|
+
|
22
|
+
As an exception, it is allowed to write an extension of Coco/R that is
|
23
|
+
used as a plugin in non-free software.
|
24
|
+
|
25
|
+
If not otherwise stated, any source code generated by Coco/R (other than
|
26
|
+
Coco/R itself) does not fall under the GNU General Public License.
|
27
|
+
-------------------------------------------------------------------------*/
|
28
|
+
|
29
|
+
#include "Position.h"
|
30
|
+
|
31
|
+
namespace Coco {
|
32
|
+
|
33
|
+
Position::Position(int beg, int end, int col, int line) {
|
34
|
+
this->beg = beg; this->end = end; this->col = col; this->line = line;
|
35
|
+
}
|
36
|
+
|
37
|
+
}; // namespace
|
@@ -0,0 +1,46 @@
|
|
1
|
+
/*-------------------------------------------------------------------------
|
2
|
+
Compiler Generator Coco/R,
|
3
|
+
Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz
|
4
|
+
extended by M. Loeberbauer & A. Woess, Univ. of Linz
|
5
|
+
ported to C++ by Csaba Balazs, University of Szeged
|
6
|
+
with improvements by Pat Terry, Rhodes University
|
7
|
+
|
8
|
+
This program is free software; you can redistribute it and/or modify it
|
9
|
+
under the terms of the GNU General Public License as published by the
|
10
|
+
Free Software Foundation; either version 2, or (at your option) any
|
11
|
+
later version.
|
12
|
+
|
13
|
+
This program is distributed in the hope that it will be useful, but
|
14
|
+
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
15
|
+
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
16
|
+
for more details.
|
17
|
+
|
18
|
+
You should have received a copy of the GNU General Public License along
|
19
|
+
with this program; if not, write to the Free Software Foundation, Inc.,
|
20
|
+
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
21
|
+
|
22
|
+
As an exception, it is allowed to write an extension of Coco/R that is
|
23
|
+
used as a plugin in non-free software.
|
24
|
+
|
25
|
+
If not otherwise stated, any source code generated by Coco/R (other than
|
26
|
+
Coco/R itself) does not fall under the GNU General Public License.
|
27
|
+
-------------------------------------------------------------------------*/
|
28
|
+
|
29
|
+
#if !defined(COCO_POSITION_H__)
|
30
|
+
#define COCO_POSITION_H__
|
31
|
+
|
32
|
+
namespace Coco {
|
33
|
+
|
34
|
+
class Position { // position of source code stretch (e.g. semantic action, resolver expressions)
|
35
|
+
public:
|
36
|
+
int beg; // start relative to the beginning of the file
|
37
|
+
int end; // end of stretch
|
38
|
+
int col; // column number of start position
|
39
|
+
int line; // line number of beginnnig of source code stretch
|
40
|
+
|
41
|
+
Position(int beg, int end, int col, int line);
|
42
|
+
};
|
43
|
+
|
44
|
+
}; // namespace
|
45
|
+
|
46
|
+
#endif // !defined(COCO_POSITION_H__)
|
data/ext/cocor/README.md
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
Coco/R
|
2
|
+
------
|
3
|
+
|
4
|
+
This is a compiler generator for C++. To build the binary, run
|
5
|
+
|
6
|
+
make
|
7
|
+
|
8
|
+
The executable will be in this directory. Use it as you want.
|
9
|
+
|
10
|
+
Documentation is available at the original site for Coco/R.
|
11
|
+
|
12
|
+
[The Compiler Generator Coco/R website](http://www.ssw.uni-linz.ac.at/Coco/)
|