ruco-cpp 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. checksums.yaml +7 -0
  2. data/Rakefile +17 -0
  3. data/bin/console +14 -0
  4. data/bin/ruco +30 -0
  5. data/bin/setup +7 -0
  6. data/data/ruco/Parser.frame +359 -0
  7. data/data/ruco/Scanner.frame +896 -0
  8. data/data/ruco/picojson/Changes +14 -0
  9. data/data/ruco/picojson/LICENSE +25 -0
  10. data/data/ruco/picojson/Makefile +8 -0
  11. data/data/ruco/picojson/README.mkdn +183 -0
  12. data/data/ruco/picojson/examples/github-issues.cc +110 -0
  13. data/data/ruco/picojson/examples/iostream.cc +70 -0
  14. data/data/ruco/picojson/examples/streaming.cc +76 -0
  15. data/data/ruco/picojson/picojson.h +1299 -0
  16. data/ext/cocor/Action.cpp +81 -0
  17. data/ext/cocor/Action.h +59 -0
  18. data/ext/cocor/ArrayList.cpp +79 -0
  19. data/ext/cocor/ArrayList.h +52 -0
  20. data/ext/cocor/BitArray.cpp +156 -0
  21. data/ext/cocor/BitArray.h +68 -0
  22. data/ext/cocor/CharClass.cpp +42 -0
  23. data/ext/cocor/CharClass.h +48 -0
  24. data/ext/cocor/CharSet.cpp +166 -0
  25. data/ext/cocor/CharSet.h +68 -0
  26. data/ext/cocor/Coco.atg +528 -0
  27. data/ext/cocor/Coco.cpp +173 -0
  28. data/ext/cocor/Comment.cpp +45 -0
  29. data/ext/cocor/Comment.h +51 -0
  30. data/ext/cocor/Copyright.frame +27 -0
  31. data/ext/cocor/DFA.cpp +865 -0
  32. data/ext/cocor/DFA.h +132 -0
  33. data/ext/cocor/Generator.cpp +182 -0
  34. data/ext/cocor/Generator.h +61 -0
  35. data/ext/cocor/Graph.h +59 -0
  36. data/ext/cocor/HashTable.cpp +115 -0
  37. data/ext/cocor/HashTable.h +84 -0
  38. data/ext/cocor/Makefile +11 -0
  39. data/ext/cocor/Melted.cpp +39 -0
  40. data/ext/cocor/Melted.h +51 -0
  41. data/ext/cocor/Node.cpp +69 -0
  42. data/ext/cocor/Node.h +86 -0
  43. data/ext/cocor/Parser.cpp +925 -0
  44. data/ext/cocor/Parser.frame +326 -0
  45. data/ext/cocor/Parser.h +153 -0
  46. data/ext/cocor/ParserGen.cpp +486 -0
  47. data/ext/cocor/ParserGen.h +99 -0
  48. data/ext/cocor/Position.cpp +37 -0
  49. data/ext/cocor/Position.h +46 -0
  50. data/ext/cocor/README.md +12 -0
  51. data/ext/cocor/Scanner.cpp +833 -0
  52. data/ext/cocor/Scanner.frame +897 -0
  53. data/ext/cocor/Scanner.h +291 -0
  54. data/ext/cocor/Sets.h +84 -0
  55. data/ext/cocor/SortedList.cpp +141 -0
  56. data/ext/cocor/SortedList.h +68 -0
  57. data/ext/cocor/State.cpp +77 -0
  58. data/ext/cocor/State.h +55 -0
  59. data/ext/cocor/StringBuilder.cpp +88 -0
  60. data/ext/cocor/StringBuilder.h +29 -0
  61. data/ext/cocor/Symbol.cpp +61 -0
  62. data/ext/cocor/Symbol.h +70 -0
  63. data/ext/cocor/Tab.cpp +1248 -0
  64. data/ext/cocor/Tab.h +245 -0
  65. data/ext/cocor/Target.cpp +41 -0
  66. data/ext/cocor/Target.h +48 -0
  67. data/ext/cocor/build.bat +3 -0
  68. data/ext/cocor/build.sh +4 -0
  69. data/ext/cocor/coc.bat +1 -0
  70. data/ext/cocor/coc.sh +2 -0
  71. data/ext/cocor/cocor_ruby_ext.cpp +124 -0
  72. data/ext/cocor/cygBuild.bat +1 -0
  73. data/ext/cocor/extconf.rb +5 -0
  74. data/ext/cocor/mingwbuild.bat +2 -0
  75. data/ext/cocor/mkmf.log +57 -0
  76. data/ext/cocor/zipsources.bat +1 -0
  77. data/lib/cocor.rb +14 -0
  78. data/lib/ruco/version.rb +3 -0
  79. data/lib/ruco.rb +728 -0
  80. metadata +195 -0
data/ext/cocor/Tab.cpp ADDED
@@ -0,0 +1,1248 @@
1
+ /*-------------------------------------------------------------------------
2
+ Tab -- Symbol Table Management
3
+ Compiler Generator Coco/R,
4
+ Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz
5
+ extended by M. Loeberbauer & A. Woess, Univ. of Linz
6
+ ported to C++ by Csaba Balazs, University of Szeged
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 <wchar.h>
31
+ #include "Tab.h"
32
+ #include "Parser.h"
33
+ #include "BitArray.h"
34
+ #include "Scanner.h"
35
+
36
+ namespace Coco {
37
+
38
+ const char* Tab::nTyp[] =
39
+ {" ", "t ", "pr ", "nt ", "clas", "chr ", "wt ", "any ", "eps ",
40
+ "sync", "sem ", "alt ", "iter", "opt ", "rslv"};
41
+
42
+ const char* Tab::tKind[] = {"fixedToken", "classToken", "litToken", "classLitToken"};
43
+
44
+ Tab::Tab(Parser *parser) {
45
+ for (int i=0; i<10; i++) ddt[i] = false;
46
+
47
+ terminals = new ArrayList();
48
+ pragmas = new ArrayList();
49
+ nonterminals = new ArrayList();
50
+ nodes = new ArrayList();
51
+ dummyNode = NULL;
52
+ classes= new ArrayList();
53
+ dummyName = 'A';
54
+
55
+ this->parser = parser;
56
+ trace = parser->trace;
57
+ errors = parser->errors;
58
+ eofSy = NewSym(Node::t, L"EOF", 0);
59
+ dummyNode = NewNode(Node::eps, (Symbol*)NULL, 0);
60
+ literals = new HashTable();
61
+ checkEOF = true;
62
+ }
63
+
64
+
65
+ Symbol* Tab::NewSym(int typ, const wchar_t* name, int line) {
66
+ if (coco_string_length(name) == 2 && name[0] == '"') {
67
+ parser->SemErr(L"empty token not allowed");
68
+ name = coco_string_create(L"???");
69
+ }
70
+ Symbol *sym = new Symbol(typ, name, line);
71
+
72
+ if (typ == Node::t) {
73
+ sym->n = terminals->Count; terminals->Add(sym);
74
+ } else if (typ == Node::pr) {
75
+ pragmas->Add(sym);
76
+ } else if (typ == Node::nt) {
77
+ sym->n = nonterminals->Count; nonterminals->Add(sym);
78
+ }
79
+
80
+ return sym;
81
+ }
82
+
83
+ Symbol* Tab::FindSym(const wchar_t* name) {
84
+ Symbol *s;
85
+ int i;
86
+ for (i=0; i<terminals->Count; i++) {
87
+ s = (Symbol*)((*terminals)[i]);
88
+ if (coco_string_equal(s->name, name)) return s;
89
+ }
90
+ for (i=0; i<nonterminals->Count; i++) {
91
+ s = (Symbol*)((*nonterminals)[i]);
92
+ if (coco_string_equal(s->name, name)) return s;
93
+ }
94
+ return NULL;
95
+ }
96
+
97
+ int Tab::Num(Node *p) {
98
+ if (p == NULL) return 0; else return p->n;
99
+ }
100
+
101
+ void Tab::PrintSym(Symbol *sym) {
102
+ wchar_t *paddedName = Name(sym->name);
103
+ fwprintf(trace, L"%3d %14s %ls", sym->n, paddedName, nTyp[sym->typ]);
104
+ coco_string_delete(paddedName);
105
+
106
+ if (sym->attrPos==NULL) fwprintf(trace, L" false "); else fwprintf(trace, L" true ");
107
+ if (sym->typ == Node::nt) {
108
+ fwprintf(trace, L"%5d", Num(sym->graph));
109
+ if (sym->deletable) fwprintf(trace, L" true "); else fwprintf(trace, L" false ");
110
+ } else
111
+ fwprintf(trace, L" ");
112
+
113
+ fwprintf(trace, L"%5d %ls\n", sym->line, tKind[sym->tokenKind]);
114
+ }
115
+
116
+ void Tab::PrintSymbolTable() {
117
+ fwprintf(trace, L"Symbol Table:\n");
118
+ fwprintf(trace, L"------------\n\n");
119
+ fwprintf(trace, L" nr name typ hasAt graph del line tokenKind\n");
120
+
121
+ Symbol *sym;
122
+ int i;
123
+ for (i=0; i<terminals->Count; i++) {
124
+ sym = (Symbol*)((*terminals)[i]);
125
+ PrintSym(sym);
126
+ }
127
+ for (i=0; i<pragmas->Count; i++) {
128
+ sym = (Symbol*)((*pragmas)[i]);
129
+ PrintSym(sym);
130
+ }
131
+ for (i=0; i<nonterminals->Count; i++) {
132
+ sym = (Symbol*)((*nonterminals)[i]);
133
+ PrintSym(sym);
134
+ }
135
+
136
+
137
+ fwprintf(trace, L"\nLiteral Tokens:\n");
138
+ fwprintf(trace, L"--------------\n");
139
+
140
+ Iterator *iter = literals->GetIterator();
141
+ while (iter->HasNext()) {
142
+ DictionaryEntry *e = iter->Next();
143
+ fwprintf(trace, L"_%ls = %ls.\n", ((Symbol*) (e->val))->name, e->key);
144
+ }
145
+ fwprintf(trace, L"\n");
146
+ }
147
+
148
+ void Tab::PrintSet(BitArray *s, int indent) {
149
+ int col, len;
150
+ col = indent;
151
+ Symbol *sym;
152
+ for (int i=0; i<terminals->Count; i++) {
153
+ sym = (Symbol*)((*terminals)[i]);
154
+ if ((*s)[sym->n]) {
155
+ len = coco_string_length(sym->name);
156
+ if (col + len >= 80) {
157
+ fwprintf(trace, L"\n");
158
+ for (col = 1; col < indent; col++) fwprintf(trace, L" ");
159
+ }
160
+ fwprintf(trace, L"%ls ", sym->name);
161
+ col += len + 1;
162
+ }
163
+ }
164
+ if (col == indent) fwprintf(trace, L"-- empty set --");
165
+ fwprintf(trace, L"\n");
166
+ }
167
+
168
+ //---------------------------------------------------------------------
169
+ // Syntax graph management
170
+ //---------------------------------------------------------------------
171
+
172
+ Node* Tab::NewNode(int typ, Symbol *sym, int line) {
173
+ Node* node = new Node(typ, sym, line);
174
+ node->n = nodes->Count;
175
+ nodes->Add(node);
176
+ return node;
177
+ }
178
+
179
+
180
+ Node* Tab::NewNode(int typ, Node* sub) {
181
+ Node* node = NewNode(typ, (Symbol*)NULL, 0);
182
+ node->sub = sub;
183
+ return node;
184
+ }
185
+
186
+ Node* Tab::NewNode(int typ, int val, int line) {
187
+ Node* node = NewNode(typ, (Symbol*)NULL, line);
188
+ node->val = val;
189
+ return node;
190
+ }
191
+
192
+
193
+ void Tab::MakeFirstAlt(Graph *g) {
194
+ g->l = NewNode(Node::alt, g->l); g->l->line = g->l->sub->line;
195
+ g->r->up = true;
196
+ g->l->next = g->r;
197
+ g->r = g->l;
198
+ }
199
+
200
+ // The result will be in g1
201
+ void Tab::MakeAlternative(Graph *g1, Graph *g2) {
202
+ g2->l = NewNode(Node::alt, g2->l); g2->l->line = g2->l->sub->line;
203
+ g2->l->up = true;
204
+ g2->r->up = true;
205
+ Node *p = g1->l; while (p->down != NULL) p = p->down;
206
+ p->down = g2->l;
207
+ p = g1->r; while (p->next != NULL) p = p->next;
208
+ // append alternative to g1 end list
209
+ p->next = g2->l;
210
+ // append g2 end list to g1 end list
211
+ g2->l->next = g2->r;
212
+ }
213
+
214
+ // The result will be in g1
215
+ void Tab::MakeSequence(Graph *g1, Graph *g2) {
216
+ Node *p = g1->r->next; g1->r->next = g2->l; // link head node
217
+ while (p != NULL) { // link substructure
218
+ Node *q = p->next; p->next = g2->l;
219
+ p = q;
220
+ }
221
+ g1->r = g2->r;
222
+ }
223
+
224
+ void Tab::MakeIteration(Graph *g) {
225
+ g->l = NewNode(Node::iter, g->l);
226
+ g->r->up = true;
227
+ Node *p = g->r;
228
+ g->r = g->l;
229
+ while (p != NULL) {
230
+ Node *q = p->next; p->next = g->l;
231
+ p = q;
232
+ }
233
+ }
234
+
235
+ void Tab::MakeOption(Graph *g) {
236
+ g->l = NewNode(Node::opt, g->l);
237
+ g->r->up = true;
238
+ g->l->next = g->r;
239
+ g->r = g->l;
240
+ }
241
+
242
+ void Tab::Finish(Graph *g) {
243
+ Node *p = g->r;
244
+ while (p != NULL) {
245
+ Node *q = p->next; p->next = NULL;
246
+ p = q;
247
+ }
248
+ }
249
+
250
+ void Tab::DeleteNodes() {
251
+ nodes = new ArrayList();
252
+ dummyNode = NewNode(Node::eps, (Symbol*)NULL, 0);
253
+ }
254
+
255
+ Graph* Tab::StrToGraph(const wchar_t* str) {
256
+ wchar_t *subStr = coco_string_create(str, 1, coco_string_length(str)-2);
257
+ wchar_t *s = Unescape(subStr);
258
+ coco_string_delete(subStr);
259
+ if (coco_string_length(s) == 0) parser->SemErr(L"empty token not allowed");
260
+ Graph *g = new Graph();
261
+ g->r = dummyNode;
262
+ for (int i = 0; i < coco_string_length(s); i++) {
263
+ Node *p = NewNode(Node::chr, (int)s[i], 0);
264
+ g->r->next = p; g->r = p;
265
+ }
266
+ g->l = dummyNode->next; dummyNode->next = NULL;
267
+ coco_string_delete(s);
268
+ return g;
269
+ }
270
+
271
+
272
+ void Tab::SetContextTrans(Node *p) { // set transition code in the graph rooted at p
273
+ while (p != NULL) {
274
+ if (p->typ == Node::chr || p->typ == Node::clas) {
275
+ p->code = Node::contextTrans;
276
+ } else if (p->typ == Node::opt || p->typ == Node::iter) {
277
+ SetContextTrans(p->sub);
278
+ } else if (p->typ == Node::alt) {
279
+ SetContextTrans(p->sub); SetContextTrans(p->down);
280
+ }
281
+ if (p->up) break;
282
+ p = p->next;
283
+ }
284
+ }
285
+
286
+ //------------ graph deletability check -----------------
287
+
288
+ bool Tab::DelGraph(Node* p) {
289
+ return p == NULL || (DelNode(p) && DelGraph(p->next));
290
+ }
291
+
292
+ bool Tab::DelSubGraph(Node* p) {
293
+ return p == NULL || (DelNode(p) && (p->up || DelSubGraph(p->next)));
294
+ }
295
+
296
+ bool Tab::DelNode(Node* p) {
297
+ if (p->typ == Node::nt) {
298
+ return p->sym->deletable;
299
+ }
300
+ else if (p->typ == Node::alt) {
301
+ return DelSubGraph(p->sub) || (p->down != NULL && DelSubGraph(p->down));
302
+ }
303
+ else {
304
+ return p->typ == Node::iter || p->typ == Node::opt || p->typ == Node::sem
305
+ || p->typ == Node::eps || p->typ == Node::rslv || p->typ == Node::sync;
306
+ }
307
+ }
308
+
309
+ //----------------- graph printing ----------------------
310
+
311
+ int Tab::Ptr(Node *p, bool up) {
312
+ if (p == NULL) return 0;
313
+ else if (up) return -(p->n);
314
+ else return p->n;
315
+ }
316
+
317
+ wchar_t* Tab::Pos(Position *pos) {
318
+ wchar_t* format = new wchar_t[10];
319
+ if (pos == NULL) {
320
+ coco_swprintf(format, 10, L" ");
321
+ } else {
322
+ coco_swprintf(format, 10, L"%5d", pos->beg);
323
+ }
324
+ return format;
325
+ }
326
+
327
+ wchar_t* Tab::Name(const wchar_t *name) {
328
+ wchar_t *name2 = coco_string_create_append(name, L" ");
329
+ wchar_t *subName2 = coco_string_create(name2, 0, 12);
330
+ coco_string_delete(name2);
331
+ return subName2;
332
+ // found no simpler way to get the first 12 characters of the name
333
+ // padded with blanks on the right
334
+ }
335
+
336
+ void Tab::PrintNodes() {
337
+ fwprintf(trace, L"Graph nodes:\n");
338
+ fwprintf(trace, L"----------------------------------------------------\n");
339
+ fwprintf(trace, L" n type name next down sub pos line\n");
340
+ fwprintf(trace, L" val code\n");
341
+ fwprintf(trace, L"----------------------------------------------------\n");
342
+
343
+ Node *p;
344
+ for (int i=0; i<nodes->Count; i++) {
345
+ p = (Node*)((*nodes)[i]);
346
+ fwprintf(trace, L"%4d %ls ", p->n, (nTyp[p->typ]));
347
+ if (p->sym != NULL) {
348
+ wchar_t *paddedName = Name(p->sym->name);
349
+ fwprintf(trace, L"%12s ", paddedName);
350
+ coco_string_delete(paddedName);
351
+ } else if (p->typ == Node::clas) {
352
+ CharClass *c = (CharClass*)(*classes)[p->val];
353
+ wchar_t *paddedName = Name(c->name);
354
+ fwprintf(trace, L"%12s ", paddedName);
355
+ coco_string_delete(paddedName);
356
+ } else fwprintf(trace, L" ");
357
+ fwprintf(trace, L"%5d ", Ptr(p->next, p->up));
358
+
359
+ if (p->typ == Node::t || p->typ == Node::nt || p->typ == Node::wt) {
360
+ fwprintf(trace, L" %5s", Pos(p->pos));
361
+ } if (p->typ == Node::chr) {
362
+ fwprintf(trace, L"%5d %5d ", p->val, p->code);
363
+ } if (p->typ == Node::clas) {
364
+ fwprintf(trace, L" %5d ", p->code);
365
+ } if (p->typ == Node::alt || p->typ == Node::iter || p->typ == Node::opt) {
366
+ fwprintf(trace, L"%5d %5d ", Ptr(p->down, false), Ptr(p->sub, false));
367
+ } if (p->typ == Node::sem) {
368
+ fwprintf(trace, L" %5s", Pos(p->pos));
369
+ } if (p->typ == Node::eps || p->typ == Node::any || p->typ == Node::sync) {
370
+ fwprintf(trace, L" ");
371
+ }
372
+ fwprintf(trace, L"%5d\n", p->line);
373
+ }
374
+ fwprintf(trace, L"\n");
375
+ }
376
+
377
+ //---------------------------------------------------------------------
378
+ // Character class management
379
+ //---------------------------------------------------------------------
380
+
381
+
382
+ CharClass* Tab::NewCharClass(const wchar_t* name, CharSet *s) {
383
+ CharClass *c;
384
+ if (coco_string_equal(name, L"#")) {
385
+ wchar_t* temp = coco_string_create_append(name, (wchar_t) dummyName++);
386
+ c = new CharClass(temp, s);
387
+ coco_string_delete(temp);
388
+ } else {
389
+ c = new CharClass(name, s);
390
+ }
391
+ c->n = classes->Count;
392
+ classes->Add(c);
393
+ return c;
394
+ }
395
+
396
+ CharClass* Tab::FindCharClass(const wchar_t* name) {
397
+ CharClass *c;
398
+ for (int i=0; i<classes->Count; i++) {
399
+ c = (CharClass*)((*classes)[i]);
400
+ if (coco_string_equal(c->name, name)) return c;
401
+ }
402
+ return NULL;
403
+ }
404
+
405
+ CharClass* Tab::FindCharClass(CharSet *s) {
406
+ CharClass *c;
407
+ for (int i=0; i<classes->Count; i++) {
408
+ c = (CharClass*)((*classes)[i]);
409
+ if (s->Equals(c->set)) return c;
410
+ }
411
+ return NULL;
412
+ }
413
+
414
+ CharSet* Tab::CharClassSet(int i) {
415
+ return ((CharClass*)((*classes)[i]))->set;
416
+ }
417
+
418
+ //----------- character class printing
419
+
420
+ wchar_t* Tab::Ch(const wchar_t ch) {
421
+ wchar_t* format = new wchar_t[10];
422
+ if (ch < L' ' || ch >= 127 || ch == L'\'' || ch == L'\\') {
423
+ coco_swprintf(format, 10, L"%d", ch);
424
+ return format;
425
+ } else {
426
+ coco_swprintf(format, 10, L"'%lc'", ch);
427
+ return format;
428
+ }
429
+ }
430
+
431
+ void Tab::WriteCharSet(CharSet *s) {
432
+ for (CharSet::Range *r = s->head; r != NULL; r = r->next) {
433
+ if (r->from < r->to) {
434
+ wchar_t *from = Ch(r->from);
435
+ wchar_t *to = Ch(r->to);
436
+ fwprintf(trace, L"%ls .. %ls ", from, to);
437
+ delete [] from;
438
+ delete [] to;
439
+ }
440
+ else {
441
+ wchar_t *from = Ch(r->from);
442
+ fwprintf(trace, L"%ls ", from);
443
+ delete [] from;
444
+ }
445
+ }
446
+ }
447
+
448
+ void Tab::WriteCharClasses () {
449
+ CharClass *c;
450
+ for (int i=0; i<classes->Count; i++) {
451
+ c = (CharClass*)((*classes)[i]);
452
+
453
+ wchar_t* format2 = coco_string_create_append(c->name, L" ");
454
+ wchar_t* format = coco_string_create(format2, 0, 10);
455
+ coco_string_merge(format, L": ");
456
+ fwprintf(trace, format);
457
+
458
+ WriteCharSet(c->set);
459
+ fwprintf(trace, L"\n");
460
+ coco_string_delete(format);
461
+ coco_string_delete(format2);
462
+ }
463
+ fwprintf(trace, L"\n");
464
+ }
465
+
466
+ //---------------------------------------------------------------------
467
+ // Symbol set computations
468
+ //---------------------------------------------------------------------
469
+
470
+ /* Computes the first set for the given Node. */
471
+ BitArray* Tab::First0(Node *p, BitArray *mark) {
472
+ BitArray *fs = new BitArray(terminals->Count);
473
+ while (p != NULL && !((*mark)[p->n])) {
474
+ mark->Set(p->n, true);
475
+ if (p->typ == Node::nt) {
476
+ if (p->sym->firstReady) {
477
+ fs->Or(p->sym->first);
478
+ } else {
479
+ BitArray *fs0 = First0(p->sym->graph, mark);
480
+ fs->Or(fs0);
481
+ delete fs0;
482
+ }
483
+ }
484
+ else if (p->typ == Node::t || p->typ == Node::wt) {
485
+ fs->Set(p->sym->n, true);
486
+ }
487
+ else if (p->typ == Node::any) {
488
+ fs->Or(p->set);
489
+ }
490
+ else if (p->typ == Node::alt) {
491
+ BitArray *fs0 = First0(p->sub, mark);
492
+ fs->Or(fs0);
493
+ delete fs0;
494
+ fs0 = First0(p->down, mark);
495
+ fs->Or(fs0);
496
+ delete fs0;
497
+ }
498
+ else if (p->typ == Node::iter || p->typ == Node::opt) {
499
+ BitArray *fs0 = First0(p->sub, mark);
500
+ fs->Or(fs0);
501
+ delete fs0;
502
+ }
503
+
504
+ if (!DelNode(p)) break;
505
+ p = p->next;
506
+ }
507
+ return fs;
508
+ }
509
+
510
+ BitArray* Tab::First(Node *p) {
511
+ BitArray *mark = new BitArray(nodes->Count);
512
+ BitArray *fs = First0(p, mark);
513
+ delete mark;
514
+ if (ddt[3]) {
515
+ fwprintf(trace, L"\n");
516
+ if (p != NULL) fwprintf(trace, L"First: node = %d\n", p->n );
517
+ else fwprintf(trace, L"First: node = null\n");
518
+ PrintSet(fs, 0);
519
+ }
520
+ return fs;
521
+ }
522
+
523
+
524
+ void Tab::CompFirstSets() {
525
+ Symbol *sym;
526
+ int i;
527
+ for (i=0; i<nonterminals->Count; i++) {
528
+ sym = (Symbol*)((*nonterminals)[i]);
529
+ sym->first = new BitArray(terminals->Count);
530
+ sym->firstReady = false;
531
+ }
532
+ for (i=0; i<nonterminals->Count; i++) {
533
+ sym = (Symbol*)((*nonterminals)[i]);
534
+ sym->first = First(sym->graph);
535
+ sym->firstReady = true;
536
+ }
537
+ }
538
+
539
+ void Tab::CompFollow(Node *p) {
540
+ while (p != NULL && !((*visited)[p->n])) {
541
+ visited->Set(p->n, true);
542
+ if (p->typ == Node::nt) {
543
+ BitArray *s = First(p->next);
544
+ p->sym->follow->Or(s);
545
+ if (DelGraph(p->next))
546
+ p->sym->nts->Set(curSy->n, true);
547
+ } else if (p->typ == Node::opt || p->typ == Node::iter) {
548
+ CompFollow(p->sub);
549
+ } else if (p->typ == Node::alt) {
550
+ CompFollow(p->sub); CompFollow(p->down);
551
+ }
552
+ p = p->next;
553
+ }
554
+ }
555
+
556
+ void Tab::Complete(Symbol *sym) {
557
+ if (!((*visited)[sym->n])) {
558
+ visited->Set(sym->n, true);
559
+ Symbol *s;
560
+ for (int i=0; i<nonterminals->Count; i++) {
561
+ s = (Symbol*)((*nonterminals)[i]);
562
+ if ((*(sym->nts))[s->n]) {
563
+ Complete(s);
564
+ sym->follow->Or(s->follow);
565
+ if (sym == curSy) sym->nts->Set(s->n, false);
566
+ }
567
+ }
568
+ }
569
+ }
570
+
571
+ void Tab::CompFollowSets() {
572
+ Symbol *sym;
573
+ int i;
574
+ for (i=0; i<nonterminals->Count; i++) {
575
+ sym = (Symbol*)((*nonterminals)[i]);
576
+ sym->follow = new BitArray(terminals->Count);
577
+ sym->nts = new BitArray(nonterminals->Count);
578
+ }
579
+ gramSy->follow->Set(eofSy->n, true);
580
+ visited = new BitArray(nodes->Count);
581
+ for (i=0; i<nonterminals->Count; i++) { // get direct successors of nonterminals
582
+ sym = (Symbol*)((*nonterminals)[i]);
583
+ curSy = sym;
584
+ CompFollow(sym->graph);
585
+ }
586
+
587
+ for (i=0; i<nonterminals->Count; i++) { // add indirect successors to followers
588
+ sym = (Symbol*)((*nonterminals)[i]);
589
+ visited = new BitArray(nonterminals->Count);
590
+ curSy = sym;
591
+ Complete(sym);
592
+ }
593
+ }
594
+
595
+ Node* Tab::LeadingAny(Node *p) {
596
+ if (p == NULL) return NULL;
597
+ Node *a = NULL;
598
+ if (p->typ == Node::any) a = p;
599
+ else if (p->typ == Node::alt) {
600
+ a = LeadingAny(p->sub);
601
+ if (a == NULL) a = LeadingAny(p->down);
602
+ }
603
+ else if (p->typ == Node::opt || p->typ == Node::iter) a = LeadingAny(p->sub);
604
+ if (a == NULL && DelNode(p) && !p->up) a = LeadingAny(p->next);
605
+ return a;
606
+ }
607
+
608
+ void Tab::FindAS(Node *p) { // find ANY sets
609
+ Node *a;
610
+ while (p != NULL) {
611
+ if (p->typ == Node::opt || p->typ == Node::iter) {
612
+ FindAS(p->sub);
613
+ a = LeadingAny(p->sub);
614
+ if (a != NULL) Sets::Subtract(a->set, First(p->next));
615
+ } else if (p->typ == Node::alt) {
616
+ BitArray *s1 = new BitArray(terminals->Count);
617
+ Node *q = p;
618
+ while (q != NULL) {
619
+ FindAS(q->sub);
620
+ a = LeadingAny(q->sub);
621
+ if (a != NULL) {
622
+ BitArray *tmp = First(q->down);
623
+ tmp->Or(s1);
624
+ Sets::Subtract(a->set, tmp);
625
+ } else {
626
+ BitArray *f = First(q->sub);
627
+ s1->Or(f);
628
+ delete f;
629
+ }
630
+ q = q->down;
631
+ }
632
+ }
633
+
634
+ // Remove alternative terminals before ANY, in the following
635
+ // examples a and b must be removed from the ANY set:
636
+ // [a] ANY, or {a|b} ANY, or [a][b] ANY, or (a|) ANY, or
637
+ // A = [a]. A ANY
638
+ if (DelNode(p)) {
639
+ a = LeadingAny(p->next);
640
+ if (a != NULL) {
641
+ Node *q = (p->typ == Node::nt) ? p->sym->graph : p->sub;
642
+ Sets::Subtract(a->set, First(q));
643
+ }
644
+ }
645
+
646
+ if (p->up) break;
647
+ p = p->next;
648
+ }
649
+ }
650
+
651
+ void Tab::CompAnySets() {
652
+ Symbol *sym;
653
+ for (int i=0; i<nonterminals->Count; i++) {
654
+ sym = (Symbol*)((*nonterminals)[i]);
655
+ FindAS(sym->graph);
656
+ }
657
+ }
658
+
659
+ BitArray* Tab::Expected(Node *p, Symbol *curSy) {
660
+ BitArray *s = First(p);
661
+ if (DelGraph(p))
662
+ s->Or(curSy->follow);
663
+ return s;
664
+ }
665
+
666
+ // does not look behind resolvers; only called during LL(1) test and in CheckRes
667
+ BitArray* Tab::Expected0(Node *p, Symbol *curSy) {
668
+ if (p->typ == Node::rslv) return new BitArray(terminals->Count);
669
+ else return Expected(p, curSy);
670
+ }
671
+
672
+ void Tab::CompSync(Node *p) {
673
+ while (p != NULL && !(visited->Get(p->n))) {
674
+ visited->Set(p->n, true);
675
+ if (p->typ == Node::sync) {
676
+ BitArray *s = Expected(p->next, curSy);
677
+ s->Set(eofSy->n, true);
678
+ allSyncSets->Or(s);
679
+ p->set = s;
680
+ } else if (p->typ == Node::alt) {
681
+ CompSync(p->sub); CompSync(p->down);
682
+ } else if (p->typ == Node::opt || p->typ == Node::iter)
683
+ CompSync(p->sub);
684
+ p = p->next;
685
+ }
686
+ }
687
+
688
+ void Tab::CompSyncSets() {
689
+ allSyncSets = new BitArray(terminals->Count);
690
+ allSyncSets->Set(eofSy->n, true);
691
+ visited = new BitArray(nodes->Count);
692
+
693
+ Symbol *sym;
694
+ for (int i=0; i<nonterminals->Count; i++) {
695
+ sym = (Symbol*)((*nonterminals)[i]);
696
+ curSy = sym;
697
+ CompSync(curSy->graph);
698
+ }
699
+ }
700
+
701
+ void Tab::SetupAnys() {
702
+ Node *p;
703
+ for (int i=0; i<nodes->Count; i++) {
704
+ p = (Node*)((*nodes)[i]);
705
+ if (p->typ == Node::any) {
706
+ p->set = new BitArray(terminals->Count, true);
707
+ p->set->Set(eofSy->n, false);
708
+ }
709
+ }
710
+ }
711
+
712
+ void Tab::CompDeletableSymbols() {
713
+ bool changed;
714
+ Symbol *sym;
715
+ int i;
716
+ do {
717
+ changed = false;
718
+ for (i=0; i<nonterminals->Count; i++) {
719
+ sym = (Symbol*)((*nonterminals)[i]);
720
+ if (!sym->deletable && sym->graph != NULL && DelGraph(sym->graph)) {
721
+ sym->deletable = true; changed = true;
722
+ }
723
+ }
724
+ } while (changed);
725
+
726
+ for (i=0; i<nonterminals->Count; i++) {
727
+ sym = (Symbol*)((*nonterminals)[i]);
728
+ if (sym->deletable)
729
+ wprintf(L" %ls deletable\n", sym->name);
730
+ }
731
+ }
732
+
733
+ void Tab::RenumberPragmas() {
734
+ int n = terminals->Count;
735
+ Symbol *sym;
736
+ for (int i=0; i<pragmas->Count; i++) {
737
+ sym = (Symbol*)((*pragmas)[i]);
738
+ sym->n = n++;
739
+ }
740
+ }
741
+
742
+ void Tab::CompSymbolSets() {
743
+ CompDeletableSymbols();
744
+ CompFirstSets();
745
+ CompAnySets();
746
+ CompFollowSets();
747
+ CompSyncSets();
748
+ if (ddt[1]) {
749
+ fwprintf(trace, L"\n");
750
+ fwprintf(trace, L"First & follow symbols:\n");
751
+ fwprintf(trace, L"----------------------\n\n");
752
+
753
+ Symbol *sym;
754
+ for (int i=0; i<nonterminals->Count; i++) {
755
+ sym = (Symbol*)((*nonterminals)[i]);
756
+ fwprintf(trace, L"%ls\n", sym->name);
757
+ fwprintf(trace, L"first: "); PrintSet(sym->first, 10);
758
+ fwprintf(trace, L"follow: "); PrintSet(sym->follow, 10);
759
+ fwprintf(trace, L"\n");
760
+ }
761
+ }
762
+ if (ddt[4]) {
763
+ fwprintf(trace, L"\n");
764
+ fwprintf(trace, L"ANY and SYNC sets:\n");
765
+ fwprintf(trace, L"-----------------\n");
766
+
767
+ Node *p;
768
+ for (int i=0; i<nodes->Count; i++) {
769
+ p = (Node*)((*nodes)[i]);
770
+ if (p->typ == Node::any || p->typ == Node::sync) {
771
+ fwprintf(trace, L"%4d %4s ", p->n, nTyp[p->typ]);
772
+ PrintSet(p->set, 11);
773
+ }
774
+ }
775
+ }
776
+ }
777
+
778
+ //---------------------------------------------------------------------
779
+ // String handling
780
+ //---------------------------------------------------------------------
781
+
782
+ wchar_t Tab::Hex2Char(const wchar_t* s) {
783
+ int val = 0;
784
+ int len = coco_string_length(s);
785
+ for (int i = 0; i < len; i++) {
786
+ wchar_t ch = s[i];
787
+ if ('0' <= ch && ch <= '9') val = 16 * val + (ch - '0');
788
+ else if ('a' <= ch && ch <= 'f') val = 16 * val + (10 + ch - 'a');
789
+ else if ('A' <= ch && ch <= 'F') val = 16 * val + (10 + ch - 'A');
790
+ else parser->SemErr(L"bad escape sequence in string or character");
791
+ }
792
+ if (val >= COCO_WCHAR_MAX) {/* pdt */
793
+ parser->SemErr(L"bad escape sequence in string or character");
794
+ }
795
+ return (wchar_t) val;
796
+ }
797
+
798
+ wchar_t* Tab::Char2Hex(const wchar_t ch) {
799
+ wchar_t* format = new wchar_t[10];
800
+ coco_swprintf(format, 10, L"\\0x%04x", ch);
801
+ return format;
802
+ }
803
+
804
+ wchar_t* Tab::Unescape (const wchar_t* s) {
805
+ /* replaces escape sequences in s by their Unicode values. */
806
+ StringBuilder buf = StringBuilder();
807
+ int i = 0;
808
+ int len = coco_string_length(s);
809
+ while (i < len) {
810
+ if (s[i] == '\\') {
811
+ switch (s[i+1]) {
812
+ case L'\\': buf.Append(L'\\'); i += 2; break;
813
+ case L'\'': buf.Append(L'\''); i += 2; break;
814
+ case L'\"': buf.Append(L'\"'); i += 2; break;
815
+ case L'r': buf.Append(L'\r'); i += 2; break;
816
+ case L'n': buf.Append(L'\n'); i += 2; break;
817
+ case L't': buf.Append(L'\t'); i += 2; break;
818
+ case L'0': buf.Append(L'\0'); i += 2; break;
819
+ case L'a': buf.Append(L'\a'); i += 2; break;
820
+ case L'b': buf.Append(L'\b'); i += 2; break;
821
+ case L'f': buf.Append(L'\f'); i += 2; break;
822
+ case L'v': buf.Append(L'\v'); i += 2; break;
823
+ case L'u': case L'x':
824
+ if (i + 6 <= coco_string_length(s)) {
825
+ wchar_t *subS = coco_string_create(s, i+2, 4);
826
+ buf.Append(Hex2Char(subS)); i += 6; break;
827
+ coco_string_delete(subS);
828
+ } else {
829
+ parser->SemErr(L"bad escape sequence in string or character");
830
+ i = coco_string_length(s); break;
831
+ }
832
+ default:
833
+ parser->SemErr(L"bad escape sequence in string or character");
834
+ i += 2; break;
835
+ }
836
+ } else {
837
+ buf.Append(s[i]);
838
+ i++;
839
+ }
840
+ }
841
+
842
+ return buf.ToString();
843
+ }
844
+
845
+
846
+ wchar_t* Tab::Escape (const wchar_t* s) {
847
+ StringBuilder buf = StringBuilder();
848
+ wchar_t ch;
849
+ int len = coco_string_length(s);
850
+ for (int i=0; i < len; i++) {
851
+ ch = s[i];
852
+ switch(ch) {
853
+ case L'\\': buf.Append(L"\\\\"); break;
854
+ case L'\'': buf.Append(L"\\'"); break;
855
+ case L'\"': buf.Append(L"\\\""); break;
856
+ case L'\t': buf.Append(L"\\t"); break;
857
+ case L'\r': buf.Append(L"\\r"); break;
858
+ case L'\n': buf.Append(L"\\n"); break;
859
+ default:
860
+ if ((ch < L' ') || (ch > 0x7f)) {
861
+ wchar_t* res = Char2Hex(ch);
862
+ buf.Append(res);
863
+ delete [] res;
864
+ } else
865
+ buf.Append(ch);
866
+ break;
867
+ }
868
+ }
869
+ return buf.ToString();
870
+ }
871
+
872
+
873
+ //---------------------------------------------------------------------
874
+ // Grammar checks
875
+ //---------------------------------------------------------------------
876
+
877
+ bool Tab::GrammarOk() {
878
+ bool ok = NtsComplete()
879
+ && AllNtReached()
880
+ && NoCircularProductions()
881
+ && AllNtToTerm();
882
+ if (ok) { CheckResolvers(); CheckLL1(); }
883
+ return ok;
884
+ }
885
+
886
+
887
+ //--------------- check for circular productions ----------------------
888
+
889
+ void Tab::GetSingles(Node *p, ArrayList *singles) {
890
+ if (p == NULL) return; // end of graph
891
+ if (p->typ == Node::nt) {
892
+ if (p->up || DelGraph(p->next)) singles->Add(p->sym);
893
+ } else if (p->typ == Node::alt || p->typ == Node::iter || p->typ == Node::opt) {
894
+ if (p->up || DelGraph(p->next)) {
895
+ GetSingles(p->sub, singles);
896
+ if (p->typ == Node::alt) GetSingles(p->down, singles);
897
+ }
898
+ }
899
+ if (!p->up && DelNode(p)) GetSingles(p->next, singles);
900
+ }
901
+
902
+ bool Tab::NoCircularProductions() {
903
+ bool ok, changed, onLeftSide, onRightSide;
904
+ ArrayList *list = new ArrayList();
905
+
906
+
907
+ Symbol *sym;
908
+ int i;
909
+ for (i=0; i<nonterminals->Count; i++) {
910
+ sym = (Symbol*)((*nonterminals)[i]);
911
+ ArrayList *singles = new ArrayList();
912
+ GetSingles(sym->graph, singles); // get nonterminals s such that sym-->s
913
+ Symbol *s;
914
+ for (int j=0; j<singles->Count; j++) {
915
+ s = (Symbol*)((*singles)[j]);
916
+ list->Add(new CNode(sym, s));
917
+ }
918
+ }
919
+
920
+ CNode *n;
921
+ do {
922
+ changed = false;
923
+ for (i = 0; i < list->Count; i++) {
924
+ n = (CNode*)(*list)[i];
925
+ onLeftSide = false; onRightSide = false;
926
+ CNode *m;
927
+ for (int j=0; j<list->Count; j++) {
928
+ m = (CNode*)((*list)[j]);
929
+ if (n->left == m->right) onRightSide = true;
930
+ if (n->right == m->left) onLeftSide = true;
931
+ }
932
+ if (!onLeftSide || !onRightSide) {
933
+ list->Remove(n); i--; changed = true;
934
+ }
935
+ }
936
+ } while(changed);
937
+ ok = true;
938
+
939
+ for (i=0; i<list->Count; i++) {
940
+ n = (CNode*)((*list)[i]);
941
+ ok = false; errors->count++;
942
+ wprintf(L" %ls --> %ls", n->left->name, n->right->name);
943
+ }
944
+ return ok;
945
+ }
946
+
947
+
948
+ //--------------- check for LL(1) errors ----------------------
949
+
950
+ void Tab::LL1Error(int cond, Symbol *sym) {
951
+ wprintf(L" LL1 warning in %ls: ", curSy->name);
952
+ if (sym != NULL) wprintf(L"%ls is ", sym->name);
953
+ switch (cond) {
954
+ case 1: wprintf(L"start of several alternatives\n"); break;
955
+ case 2: wprintf(L"start & successor of deletable structure\n"); break;
956
+ case 3: wprintf(L"an ANY node that matches no symbol\n"); break;
957
+ case 4: wprintf(L"contents of [...] or {...} must not be deletable\n"); break;
958
+ }
959
+ }
960
+
961
+
962
+ void Tab::CheckOverlap(BitArray *s1, BitArray *s2, int cond) {
963
+ Symbol *sym;
964
+ for (int i=0; i<terminals->Count; i++) {
965
+ sym = (Symbol*)((*terminals)[i]);
966
+ if ((*s1)[sym->n] && (*s2)[sym->n]) {
967
+ LL1Error(cond, sym);
968
+ }
969
+ }
970
+ }
971
+
972
+ void Tab::CheckAlts(Node *p) {
973
+ BitArray *s1, *s2;
974
+ while (p != NULL) {
975
+ if (p->typ == Node::alt) {
976
+ Node *q = p;
977
+ s1 = new BitArray(terminals->Count);
978
+ while (q != NULL) { // for all alternatives
979
+ s2 = Expected0(q->sub, curSy);
980
+ CheckOverlap(s1, s2, 1);
981
+ s1->Or(s2);
982
+ CheckAlts(q->sub);
983
+ q = q->down;
984
+ }
985
+ } else if (p->typ == Node::opt || p->typ == Node::iter) {
986
+ if (DelSubGraph(p->sub)) LL1Error(4, NULL); // e.g. [[...]]
987
+ else {
988
+ s1 = Expected0(p->sub, curSy);
989
+ s2 = Expected(p->next, curSy);
990
+ CheckOverlap(s1, s2, 2);
991
+ }
992
+ CheckAlts(p->sub);
993
+ } else if (p->typ == Node::any) {
994
+ if (Sets::Elements(p->set) == 0) LL1Error(3, NULL);
995
+ // e.g. {ANY} ANY or [ANY] ANY or ( ANY | ANY )
996
+ }
997
+ if (p->up) break;
998
+ p = p->next;
999
+ }
1000
+ }
1001
+
1002
+ void Tab::CheckLL1() {
1003
+ Symbol *sym;
1004
+ for (int i=0; i<nonterminals->Count; i++) {
1005
+ sym = (Symbol*)((*nonterminals)[i]);
1006
+ curSy = sym;
1007
+ CheckAlts(curSy->graph);
1008
+ }
1009
+ }
1010
+
1011
+ //------------- check if resolvers are legal --------------------
1012
+
1013
+ void Tab::ResErr(Node *p, const wchar_t* msg) {
1014
+ errors->Warning(p->line, p->pos->col, msg);
1015
+ }
1016
+
1017
+ void Tab::CheckRes(Node *p, bool rslvAllowed) {
1018
+ while (p != NULL) {
1019
+
1020
+ Node *q;
1021
+ if (p->typ == Node::alt) {
1022
+ BitArray *expected = new BitArray(terminals->Count);
1023
+ for (q = p; q != NULL; q = q->down)
1024
+ expected->Or(Expected0(q->sub, curSy));
1025
+ BitArray *soFar = new BitArray(terminals->Count);
1026
+ for (q = p; q != NULL; q = q->down) {
1027
+ if (q->sub->typ == Node::rslv) {
1028
+ BitArray *fs = Expected(q->sub->next, curSy);
1029
+ if (Sets::Intersect(fs, soFar))
1030
+ ResErr(q->sub, L"Warning: Resolver will never be evaluated. Place it at previous conflicting alternative.");
1031
+ if (!Sets::Intersect(fs, expected))
1032
+ ResErr(q->sub, L"Warning: Misplaced resolver: no LL(1) conflict.");
1033
+ } else soFar->Or(Expected(q->sub, curSy));
1034
+ CheckRes(q->sub, true);
1035
+ }
1036
+ } else if (p->typ == Node::iter || p->typ == Node::opt) {
1037
+ if (p->sub->typ == Node::rslv) {
1038
+ BitArray *fs = First(p->sub->next);
1039
+ BitArray *fsNext = Expected(p->next, curSy);
1040
+ if (!Sets::Intersect(fs, fsNext))
1041
+ ResErr(p->sub, L"Warning: Misplaced resolver: no LL(1) conflict.");
1042
+ }
1043
+ CheckRes(p->sub, true);
1044
+ } else if (p->typ == Node::rslv) {
1045
+ if (!rslvAllowed)
1046
+ ResErr(p, L"Warning: Misplaced resolver: no alternative.");
1047
+ }
1048
+
1049
+ if (p->up) break;
1050
+ p = p->next;
1051
+ rslvAllowed = false;
1052
+ }
1053
+ }
1054
+
1055
+ void Tab::CheckResolvers() {
1056
+ for (int i=0; i<nonterminals->Count; i++) {
1057
+ curSy = (Symbol*)((*nonterminals)[i]);
1058
+ CheckRes(curSy->graph, false);
1059
+ }
1060
+ }
1061
+
1062
+
1063
+ //------------- check if every nts has a production --------------------
1064
+
1065
+ bool Tab::NtsComplete() {
1066
+ bool complete = true;
1067
+ Symbol *sym;
1068
+ for (int i=0; i<nonterminals->Count; i++) {
1069
+ sym = (Symbol*)((*nonterminals)[i]);
1070
+ if (sym->graph == NULL) {
1071
+ complete = false; errors->count++;
1072
+ wprintf(L" No production for %ls\n", sym->name);
1073
+ }
1074
+ }
1075
+ return complete;
1076
+ }
1077
+
1078
+ //-------------- check if every nts can be reached -----------------
1079
+
1080
+ void Tab::MarkReachedNts(Node *p) {
1081
+ while (p != NULL) {
1082
+ if (p->typ == Node::nt && !((*visited)[p->sym->n])) { // new nt reached
1083
+ visited->Set(p->sym->n, true);
1084
+ MarkReachedNts(p->sym->graph);
1085
+ } else if (p->typ == Node::alt || p->typ == Node::iter || p->typ == Node::opt) {
1086
+ MarkReachedNts(p->sub);
1087
+ if (p->typ == Node::alt) MarkReachedNts(p->down);
1088
+ }
1089
+ if (p->up) break;
1090
+ p = p->next;
1091
+ }
1092
+ }
1093
+
1094
+ bool Tab::AllNtReached() {
1095
+ bool ok = true;
1096
+ visited = new BitArray(nonterminals->Count);
1097
+ visited->Set(gramSy->n, true);
1098
+ MarkReachedNts(gramSy->graph);
1099
+ Symbol *sym;
1100
+ for (int i=0; i<nonterminals->Count; i++) {
1101
+ sym = (Symbol*)((*nonterminals)[i]);
1102
+ if (!((*visited)[sym->n])) {
1103
+ ok = false; errors->count++;
1104
+ wprintf(L" %ls cannot be reached\n", sym->name);
1105
+ }
1106
+ }
1107
+ return ok;
1108
+ }
1109
+
1110
+ //--------- check if every nts can be derived to terminals ------------
1111
+
1112
+ bool Tab::IsTerm(Node *p, BitArray *mark) { // true if graph can be derived to terminals
1113
+ while (p != NULL) {
1114
+ if (p->typ == Node::nt && !((*mark)[p->sym->n])) return false;
1115
+ if (p->typ == Node::alt && !IsTerm(p->sub, mark)
1116
+ && (p->down == NULL || !IsTerm(p->down, mark))) return false;
1117
+ if (p->up) break;
1118
+ p = p->next;
1119
+ }
1120
+ return true;
1121
+ }
1122
+
1123
+
1124
+ bool Tab::AllNtToTerm() {
1125
+ bool changed, ok = true;
1126
+ BitArray *mark = new BitArray(nonterminals->Count);
1127
+ // a nonterminal is marked if it can be derived to terminal symbols
1128
+ Symbol *sym;
1129
+ int i;
1130
+ do {
1131
+ changed = false;
1132
+
1133
+ for (i=0; i<nonterminals->Count; i++) {
1134
+ sym = (Symbol*)((*nonterminals)[i]);
1135
+ if (!((*mark)[sym->n]) && IsTerm(sym->graph, mark)) {
1136
+ mark->Set(sym->n, true); changed = true;
1137
+ }
1138
+ }
1139
+ } while (changed);
1140
+ for (i=0; i<nonterminals->Count; i++) {
1141
+ sym = (Symbol*)((*nonterminals)[i]);
1142
+ if (!((*mark)[sym->n])) {
1143
+ ok = false; errors->count++;
1144
+ wprintf(L" %ls cannot be derived to terminals\n", sym->name);
1145
+ }
1146
+ }
1147
+ return ok;
1148
+ }
1149
+
1150
+ //---------------------------------------------------------------------
1151
+ // Cross reference list
1152
+ //---------------------------------------------------------------------
1153
+
1154
+ void Tab::XRef() {
1155
+ SortedList *xref = new SortedList();
1156
+ // collect lines where symbols have been defined
1157
+ Symbol *sym;
1158
+ int i, j;
1159
+ for (i=0; i<nonterminals->Count; i++) {
1160
+ sym = (Symbol*)((*nonterminals)[i]);
1161
+ ArrayList *list = (ArrayList*)(xref->Get(sym));
1162
+ if (list == NULL) {list = new ArrayList(); xref->Set(sym, list);}
1163
+ int *intg = new int(- sym->line);
1164
+ list->Add(intg);
1165
+ }
1166
+ // collect lines where symbols have been referenced
1167
+ Node *n;
1168
+ for (i=0; i<nodes->Count; i++) {
1169
+ n = (Node*)((*nodes)[i]);
1170
+ if (n->typ == Node::t || n->typ == Node::wt || n->typ == Node::nt) {
1171
+ ArrayList *list = (ArrayList*)(xref->Get(n->sym));
1172
+ if (list == NULL) {list = new ArrayList(); xref->Set(n->sym, list);}
1173
+ int *intg = new int(n->line);
1174
+ list->Add(intg);
1175
+ }
1176
+ }
1177
+ // print cross reference list
1178
+ fwprintf(trace, L"\n");
1179
+ fwprintf(trace, L"Cross reference list:\n");
1180
+ fwprintf(trace, L"--------------------\n\n");
1181
+
1182
+ for (i=0; i<xref->Count; i++) {
1183
+ sym = (Symbol*)(xref->GetKey(i));
1184
+ wchar_t *paddedName = Name(sym->name);
1185
+ fwprintf(trace, L" %12ls", paddedName);
1186
+ coco_string_delete(paddedName);
1187
+ ArrayList *list = (ArrayList*)(xref->Get(sym));
1188
+ int col = 14;
1189
+ int line;
1190
+ for (j=0; j<list->Count; j++) {
1191
+ line = *(int*)((*list)[j]);
1192
+ if (col + 5 > 80) {
1193
+ fwprintf(trace, L"\n");
1194
+ for (col = 1; col <= 14; col++) fwprintf(trace, L" ");
1195
+ }
1196
+ fwprintf(trace, L"%5d", line); col += 5;
1197
+ }
1198
+ fwprintf(trace, L"\n");
1199
+ }
1200
+ fwprintf(trace, L"\n\n");
1201
+ }
1202
+
1203
+ void Tab::SetDDT(const wchar_t* s) {
1204
+ wchar_t* st = coco_string_create_upper(s);
1205
+ wchar_t ch;
1206
+ int len = coco_string_length(st);
1207
+ for (int i = 0; i < len; i++) {
1208
+ ch = st[i];
1209
+ if (L'0' <= ch && ch <= L'9') ddt[ch - L'0'] = true;
1210
+ else switch (ch) {
1211
+ case L'A' : ddt[0] = true; break; // trace automaton
1212
+ case L'F' : ddt[1] = true; break; // list first/follow sets
1213
+ case L'G' : ddt[2] = true; break; // print syntax graph
1214
+ case L'I' : ddt[3] = true; break; // trace computation of first sets
1215
+ case L'J' : ddt[4] = true; break; // print ANY and SYNC sets
1216
+ case L'P' : ddt[8] = true; break; // print statistics
1217
+ case L'S' : ddt[6] = true; break; // list symbol table
1218
+ case L'X' : ddt[7] = true; break; // list cross reference table
1219
+ default : break;
1220
+ }
1221
+ }
1222
+ coco_string_delete(st);
1223
+ }
1224
+
1225
+
1226
+ void Tab::SetOption(const wchar_t* s) {
1227
+ // example: $namespace=xxx
1228
+ // index of '=' is 10 => nameLenght = 10
1229
+ // start index of xxx = 11
1230
+
1231
+ int nameLenght = coco_string_indexof(s, '=');
1232
+ int valueIndex = nameLenght + 1;
1233
+
1234
+ wchar_t *name = coco_string_create(s, 0, nameLenght);
1235
+ wchar_t *value = coco_string_create(s, valueIndex);
1236
+
1237
+ if (coco_string_equal(L"$namespace", name)) {
1238
+ if (nsName == NULL) nsName = coco_string_create(value);
1239
+ } else if (coco_string_equal(L"$checkEOF", name)) {
1240
+ checkEOF = coco_string_equal(L"true", value);
1241
+ }
1242
+
1243
+ delete [] name;
1244
+ delete [] value;
1245
+ }
1246
+
1247
+
1248
+ }; // namespace