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
@@ -0,0 +1,528 @@
1
+ /*-------------------------------------------------------------------------
2
+ Coco.ATG -- Attributed Grammar
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
+ compile with:
31
+ Coco Coco.ATG -namespace Coco
32
+ -------------------------------------------------------------------------*/
33
+ $namespace=Coco
34
+
35
+ #include "Tab.h"
36
+ #include "DFA.h"
37
+ #include "ParserGen.h"
38
+
39
+ COMPILER Coco
40
+
41
+ int id;
42
+ int str;
43
+
44
+ FILE* trace; // other Coco objects referenced in this ATG
45
+ Tab *tab;
46
+ DFA *dfa;
47
+ ParserGen *pgen;
48
+
49
+ bool genScanner;
50
+ wchar_t* tokenString; // used in declarations of literal tokens
51
+ wchar_t* noString; // used in declarations of literal tokens
52
+
53
+ // This method will be called by the contructor if it exits.
54
+ // This support is specific to the C++ version of Coco/R.
55
+ void Init() {
56
+ tab = NULL;
57
+ dfa = NULL;
58
+ pgen = NULL;
59
+ id = 0;
60
+ str = 1;
61
+ tokenString = NULL;
62
+ noString = coco_string_create(L"-none-");
63
+ }
64
+
65
+ // Uncomment this method if cleanup is necessary,
66
+ // this method will be called by the destructor if it exists.
67
+ // This support is specific to the C++ version of Coco/R.
68
+ // void Destroy() {
69
+ // nothing to do
70
+ // }
71
+ /*-------------------------------------------------------------------------*/
72
+
73
+ CHARACTERS
74
+ letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_".
75
+ digit = "0123456789".
76
+ cr = '\r'.
77
+ lf = '\n'.
78
+ tab = '\t'.
79
+ stringCh = ANY - '"' - '\\' - cr - lf.
80
+ charCh = ANY - '\'' - '\\' - cr - lf.
81
+ printable = '\u0020' .. '\u007e'.
82
+ hex = "0123456789abcdef".
83
+
84
+ TOKENS
85
+ ident = letter { letter | digit }.
86
+ number = digit { digit }.
87
+ string = '"' { stringCh | '\\' printable } '"'.
88
+ badString = '"' { stringCh | '\\' printable } (cr | lf).
89
+ char = '\'' ( charCh | '\\' printable { hex } ) '\''.
90
+
91
+ PRAGMAS
92
+ ddtSym = '$' { digit | letter }. (. tab->SetDDT(la->val); .)
93
+ optionSym = '$' letter { letter } '='
94
+ { digit | letter
95
+ | '-' | '.' | ':'
96
+ }. (. tab->SetOption(la->val); .)
97
+
98
+
99
+ COMMENTS FROM "/*" TO "*/" NESTED
100
+ COMMENTS FROM "//" TO lf
101
+
102
+ IGNORE cr + lf + tab
103
+
104
+ /*-------------------------------------------------------------------------*/
105
+
106
+ PRODUCTIONS
107
+
108
+ Coco (. Symbol *sym; Graph *g, *g1, *g2; wchar_t* gramName = NULL; CharSet *s; .)
109
+ =
110
+ (. int beg = la->pos; int line = la->line; .)
111
+ { // this section can be used
112
+ // for #include statements
113
+ ANY
114
+ } (. if (la->pos != beg) {
115
+ pgen->usingPos = new Position(beg, t->pos + coco_string_length(t->val), 0, line);
116
+ }
117
+ .)
118
+
119
+ "COMPILER" (. genScanner = true;
120
+ tab->ignored = new CharSet(); .)
121
+ ident (. gramName = coco_string_create(t->val);
122
+ beg = la->pos;
123
+ line = la->line;
124
+ .)
125
+ { ANY } (. tab->semDeclPos = new Position(beg, la->pos, 0, line); .)
126
+ [ "IGNORECASE" (. dfa->ignoreCase = true; .) ] /* pdt */
127
+ [ "CHARACTERS" { SetDecl }]
128
+ [ "TOKENS" { TokenDecl<Node::t> }]
129
+ [ "PRAGMAS" { TokenDecl<Node::pr> }]
130
+ { "COMMENTS" (. bool nested = false; .)
131
+ "FROM" TokenExpr<g1>
132
+ "TO" TokenExpr<g2>
133
+ [ "NESTED" (. nested = true; .)
134
+ ] (. dfa->NewComment(g1->l, g2->l, nested); .)
135
+ }
136
+ { "IGNORE" Set<s> (. tab->ignored->Or(s); .)
137
+ }
138
+
139
+ SYNC
140
+ "PRODUCTIONS" (. if (genScanner) dfa->MakeDeterministic();
141
+ tab->DeleteNodes();
142
+ .)
143
+ { ident (. sym = tab->FindSym(t->val);
144
+ bool undef = (sym == NULL);
145
+ if (undef) sym = tab->NewSym(Node::nt, t->val, t->line);
146
+ else {
147
+ if (sym->typ == Node::nt) {
148
+ if (sym->graph != NULL) SemErr(L"name declared twice");
149
+ } else SemErr(L"this symbol kind not allowed on left side of production");
150
+ sym->line = t->line;
151
+ }
152
+ bool noAttrs = (sym->attrPos == NULL);
153
+ sym->attrPos = NULL;
154
+ .)
155
+ [ AttrDecl<sym> ] (. if (!undef)
156
+ if (noAttrs != (sym->attrPos == NULL))
157
+ SemErr(L"attribute mismatch between declaration and use of this symbol");
158
+ .)
159
+ [ SemText<.sym->semPos.> ] WEAK
160
+ '='
161
+ Expression<g> (. sym->graph = g->l;
162
+ tab->Finish(g);
163
+ .)
164
+ WEAK
165
+ '.'
166
+ }
167
+ "END" ident (. if (!coco_string_equal(gramName, t->val))
168
+ SemErr(L"name does not match grammar name");
169
+ tab->gramSy = tab->FindSym(gramName);
170
+ if (tab->gramSy == NULL)
171
+ SemErr(L"missing production for grammar name");
172
+ else {
173
+ sym = tab->gramSy;
174
+ if (sym->attrPos != NULL)
175
+ SemErr(L"grammar symbol must not have attributes");
176
+ }
177
+ tab->noSym = tab->NewSym(Node::t, L"???", 0); // noSym gets highest number
178
+ tab->SetupAnys();
179
+ tab->RenumberPragmas();
180
+ if (tab->ddt[2]) tab->PrintNodes();
181
+ if (errors->count == 0) {
182
+ wprintf(L"checking\n");
183
+ tab->CompSymbolSets();
184
+ if (tab->ddt[7]) tab->XRef();
185
+ if (tab->GrammarOk()) {
186
+ wprintf(L"parser");
187
+ pgen->WriteParser();
188
+ if (genScanner) {
189
+ wprintf(L" + scanner");
190
+ dfa->WriteScanner();
191
+ if (tab->ddt[0]) dfa->PrintStates();
192
+ }
193
+ wprintf(L" generated\n");
194
+ if (tab->ddt[8]) pgen->WriteStatistics();
195
+ }
196
+ }
197
+ if (tab->ddt[6]) tab->PrintSymbolTable();
198
+ .)
199
+ '.'
200
+ .
201
+
202
+ /*------------------------------------------------------------------------------------*/
203
+
204
+ SetDecl (. CharSet *s; .)
205
+ =
206
+ ident (. wchar_t *name = coco_string_create(t->val);
207
+ CharClass *c = tab->FindCharClass(name);
208
+ if (c != NULL) SemErr(L"name declared twice");
209
+ .)
210
+ '=' Set<s> (. if (s->Elements() == 0) SemErr(L"character set must not be empty");
211
+ tab->NewCharClass(name, s);
212
+ .)
213
+ '.'
214
+ .
215
+
216
+ /*------------------------------------------------------------------------------------*/
217
+
218
+ Set<CharSet* &s> (. CharSet *s2; .)
219
+ =
220
+ SimSet<s>
221
+ { '+' SimSet<s2> (. s->Or(s2); .)
222
+ | '-' SimSet<s2> (. s->Subtract(s2); .)
223
+ }
224
+ .
225
+
226
+ /*------------------------------------------------------------------------------------*/
227
+
228
+ SimSet<CharSet* &s> (. int n1, n2; .)
229
+ = (. s = new CharSet(); .)
230
+ ( ident (. CharClass *c = tab->FindCharClass(t->val);
231
+ if (c == NULL) SemErr(L"undefined name"); else s->Or(c->set);
232
+ .)
233
+ | string (.
234
+ wchar_t *subName2 = coco_string_create(t->val, 1, coco_string_length(t->val)-2);
235
+ wchar_t *name = tab->Unescape(subName2);
236
+ coco_string_delete(subName2);
237
+ wchar_t ch;
238
+ int len = coco_string_length(name);
239
+ for(int i=0; i < len; i++) {
240
+ ch = name[i];
241
+ if (dfa->ignoreCase) {
242
+ if ((L'A' <= ch) && (ch <= L'Z')) ch = ch - (L'A' - L'a'); // ch.ToLower()
243
+ }
244
+ s->Set(ch);
245
+ }
246
+ coco_string_delete(name);
247
+ .)
248
+ | Char<n1> (. s->Set(n1); .)
249
+ [ ".." Char<n2> (. for (int i = n1; i <= n2; i++) s->Set(i); .)
250
+ ]
251
+ | "ANY" (. s = new CharSet(); s->Fill(); .)
252
+ )
253
+ .
254
+
255
+ /*--------------------------------------------------------------------------------------*/
256
+
257
+ Char<int &n>
258
+ =
259
+ char (. n = 0;
260
+ wchar_t* subName = coco_string_create(t->val, 1, coco_string_length(t->val)-2);
261
+ wchar_t* name = tab->Unescape(subName);
262
+ coco_string_delete(subName);
263
+
264
+ // "<= 1" instead of "== 1" to allow the escape sequence '\0' in c++
265
+ if (coco_string_length(name) <= 1) n = name[0];
266
+ else SemErr(L"unacceptable character value");
267
+ coco_string_delete(name);
268
+ if (dfa->ignoreCase && (((wchar_t) n) >= 'A') && (((wchar_t) n) <= 'Z')) n += 32;
269
+ .)
270
+ .
271
+
272
+ /*------------------------------------------------------------------------------------*/
273
+
274
+ TokenDecl<int typ> (. wchar_t* name = NULL; int kind; Symbol *sym; Graph *g; .)
275
+ =
276
+ Sym<name, kind> (. sym = tab->FindSym(name);
277
+ if (sym != NULL) SemErr(L"name declared twice");
278
+ else {
279
+ sym = tab->NewSym(typ, name, t->line);
280
+ sym->tokenKind = Symbol::fixedToken;
281
+ }
282
+ tokenString = NULL;
283
+ .)
284
+ SYNC
285
+ ( '=' TokenExpr<g> '.' (. if (kind == str) SemErr(L"a literal must not be declared with a structure");
286
+ tab->Finish(g);
287
+ if (tokenString == NULL || coco_string_equal(tokenString, noString))
288
+ dfa->ConvertToStates(g->l, sym);
289
+ else { // TokenExpr is a single string
290
+ if ((*(tab->literals))[tokenString] != NULL)
291
+ SemErr(L"token string declared twice");
292
+ tab->literals->Set(tokenString, sym);
293
+ dfa->MatchLiteral(tokenString, sym);
294
+ }
295
+ .)
296
+ | (. if (kind == id) genScanner = false;
297
+ else dfa->MatchLiteral(sym->name, sym);
298
+ .)
299
+ )
300
+ [ SemText<.sym->semPos.> (. if (typ != Node::pr) SemErr(L"semantic action not allowed here"); .)
301
+ ]
302
+ .
303
+
304
+ /*------------------------------------------------------------------------------------*/
305
+
306
+ AttrDecl<Symbol *sym>
307
+ =
308
+ '<' (. int beg = la->pos; int col = la->col; int line = la->line; .)
309
+ { ANY
310
+ | badString (. SemErr(L"bad string in attributes"); .)
311
+ }
312
+ '>' (. if (t->pos > beg)
313
+ sym->attrPos = new Position(beg, t->pos, col, line); .)
314
+ | "<." (. int beg = la->pos; int col = la->col; int line = la->line; .)
315
+ { ANY
316
+ | badString (. SemErr(L"bad string in attributes"); .)
317
+ }
318
+ ".>" (. if (t->pos > beg)
319
+ sym->attrPos = new Position(beg, t->pos, col, line); .)
320
+ .
321
+
322
+ /*------------------------------------------------------------------------------------*/
323
+
324
+ Expression<Graph* &g> (. Graph *g2; .)
325
+ =
326
+ Term<g> (. bool first = true; .)
327
+ { WEAK
328
+ '|'
329
+ Term<g2> (. if (first) { tab->MakeFirstAlt(g); first = false; }
330
+ tab->MakeAlternative(g, g2);
331
+ .)
332
+ }
333
+ .
334
+
335
+ /*------------------------------------------------------------------------------------*/
336
+
337
+ Term<Graph* &g> (. Graph *g2; Node *rslv = NULL; g = NULL; .)
338
+ =
339
+ ( [ (. rslv = tab->NewNode(Node::rslv, (Symbol*)NULL, la->line); .)
340
+ Resolver<.rslv->pos.> (. g = new Graph(rslv); .)
341
+ ]
342
+ Factor<g2> (. if (rslv != NULL) tab->MakeSequence(g, g2);
343
+ else g = g2; .)
344
+ { Factor<g2> (. tab->MakeSequence(g, g2); .)
345
+ }
346
+ | (. g = new Graph(tab->NewNode(Node::eps, (Symbol*)NULL, 0)); .)
347
+ ) (. if (g == NULL) // invalid start of Term
348
+ g = new Graph(tab->NewNode(Node::eps, (Symbol*)NULL, 0)); .)
349
+ .
350
+
351
+ /*------------------------------------------------------------------------------------*/
352
+
353
+ Factor<Graph* &g> (. wchar_t* name = NULL; int kind; Position *pos; bool weak = false;
354
+ g = NULL;
355
+ .)
356
+ =
357
+ ( [ "WEAK" (. weak = true; .)
358
+ ]
359
+ Sym<name, kind> (. Symbol *sym = tab->FindSym(name);
360
+ if (sym == NULL && kind == str)
361
+ sym = (Symbol*)((*(tab->literals))[name]);
362
+ bool undef = (sym == NULL);
363
+ if (undef) {
364
+ if (kind == id)
365
+ sym = tab->NewSym(Node::nt, name, 0); // forward nt
366
+ else if (genScanner) {
367
+ sym = tab->NewSym(Node::t, name, t->line);
368
+ dfa->MatchLiteral(sym->name, sym);
369
+ } else { // undefined string in production
370
+ SemErr(L"undefined string in production");
371
+ sym = tab->eofSy; // dummy
372
+ }
373
+ }
374
+ int typ = sym->typ;
375
+ if (typ != Node::t && typ != Node::nt)
376
+ SemErr(L"this symbol kind is not allowed in a production");
377
+ if (weak) {
378
+ if (typ == Node::t) typ = Node::wt;
379
+ else SemErr(L"only terminals may be weak");
380
+ }
381
+ Node *p = tab->NewNode(typ, sym, t->line);
382
+ g = new Graph(p);
383
+ .)
384
+ [ Attribs<p> (. if (kind != id) SemErr(L"a literal must not have attributes"); .)
385
+ ] (. if (undef)
386
+ sym->attrPos = p->pos; // dummy
387
+ else if ((p->pos == NULL) != (sym->attrPos == NULL))
388
+ SemErr(L"attribute mismatch between declaration and use of this symbol");
389
+ .)
390
+ | '(' Expression<g> ')'
391
+ | '[' Expression<g> ']' (. tab->MakeOption(g); .)
392
+ | '{' Expression<g> '}' (. tab->MakeIteration(g); .)
393
+ | SemText<pos> (. Node *p = tab->NewNode(Node::sem, (Symbol*)NULL, 0);
394
+ p->pos = pos;
395
+ g = new Graph(p);
396
+ .)
397
+ | "ANY" (. Node *p = tab->NewNode(Node::any, (Symbol*)NULL, 0); // p.set is set in tab->SetupAnys
398
+ g = new Graph(p);
399
+ .)
400
+ | "SYNC" (. Node *p = tab->NewNode(Node::sync, (Symbol*)NULL, 0);
401
+ g = new Graph(p);
402
+ .)
403
+ ) (. if (g == NULL) // invalid start of Factor
404
+ g = new Graph(tab->NewNode(Node::eps, (Symbol*)NULL, 0));
405
+ .)
406
+ .
407
+
408
+ /*------------------------------------------------------------------------------------*/
409
+
410
+ Resolver<Position* &pos>
411
+ =
412
+ "IF" "(" (. int beg = la->pos; int col = la->col; int line = la->line; .)
413
+ Condition (. pos = new Position(beg, t->pos, col, line); .)
414
+ .
415
+
416
+ /*------------------------------------------------------------------------------------*/
417
+
418
+ Condition = { "(" Condition | ANY } ")" .
419
+
420
+ /*------------------------------------------------------------------------------------*/
421
+
422
+ TokenExpr<Graph* &g> (. Graph *g2; .)
423
+ =
424
+ TokenTerm<g> (. bool first = true; .)
425
+ { WEAK
426
+ '|'
427
+ TokenTerm<g2> (. if (first) { tab->MakeFirstAlt(g); first = false; }
428
+ tab->MakeAlternative(g, g2);
429
+ .)
430
+ }
431
+ .
432
+
433
+ /*------------------------------------------------------------------------------------*/
434
+
435
+ TokenTerm<Graph* &g> (. Graph *g2; .)
436
+ =
437
+ TokenFactor<g>
438
+ { TokenFactor<g2> (. tab->MakeSequence(g, g2); .)
439
+ }
440
+ [ "CONTEXT"
441
+ '(' TokenExpr<g2> (. tab->SetContextTrans(g2->l); dfa->hasCtxMoves = true;
442
+ tab->MakeSequence(g, g2); .)
443
+ ')'
444
+ ]
445
+ .
446
+
447
+ /*------------------------------------------------------------------------------------*/
448
+
449
+ TokenFactor<Graph* &g> (. wchar_t* name = NULL; int kind; .)
450
+ =
451
+ (. g = NULL; .)
452
+ ( Sym<name, kind> (. if (kind == id) {
453
+ CharClass *c = tab->FindCharClass(name);
454
+ if (c == NULL) {
455
+ SemErr(L"undefined name");
456
+ c = tab->NewCharClass(name, new CharSet());
457
+ }
458
+ Node *p = tab->NewNode(Node::clas, (Symbol*)NULL, 0); p->val = c->n;
459
+ g = new Graph(p);
460
+ tokenString = coco_string_create(noString);
461
+ } else { // str
462
+ g = tab->StrToGraph(name);
463
+ if (tokenString == NULL) tokenString = coco_string_create(name);
464
+ else tokenString = coco_string_create(noString);
465
+ }
466
+ .)
467
+ | '(' TokenExpr<g> ')'
468
+ | '[' TokenExpr<g> ']' (. tab->MakeOption(g); tokenString = coco_string_create(noString); .)
469
+ | '{' TokenExpr<g> '}' (. tab->MakeIteration(g); tokenString = coco_string_create(noString); .)
470
+ ) (. if (g == NULL) // invalid start of TokenFactor
471
+ g = new Graph(tab->NewNode(Node::eps, (Symbol*)NULL, 0)); .)
472
+ .
473
+
474
+ /*------------------------------------------------------------------------------------*/
475
+
476
+ Sym<wchar_t* &name, int &kind>
477
+ = (. name = coco_string_create(L"???"); kind = id; .)
478
+ ( ident (. kind = id; coco_string_delete(name); name = coco_string_create(t->val); .)
479
+ | (string (. coco_string_delete(name); name = coco_string_create(t->val); .)
480
+ | char (.
481
+ wchar_t *subName = coco_string_create(t->val, 1, coco_string_length(t->val)-2);
482
+ coco_string_delete(name);
483
+ name = coco_string_create_append(L"\"", subName);
484
+ coco_string_delete(subName);
485
+ coco_string_merge(name, L"\"");
486
+ .)
487
+ ) (. kind = str;
488
+ if (dfa->ignoreCase) {
489
+ wchar_t *oldName = name;
490
+ name = coco_string_create_lower(name);
491
+ coco_string_delete(oldName);
492
+ }
493
+ if (coco_string_indexof(name, ' ') >= 0)
494
+ SemErr(L"literal tokens must not contain blanks"); .)
495
+ )
496
+ .
497
+
498
+ /*------------------------------------------------------------------------------------*/
499
+
500
+ Attribs<Node *p>
501
+ =
502
+ '<' (. int beg = la->pos; int col = la->col; int line = la->line; .)
503
+ { ANY
504
+ | badString (. SemErr(L"bad string in attributes"); .)
505
+ }
506
+ '>' (. if (t->pos > beg) p->pos = new Position(beg, t->pos, col, line); .)
507
+ | "<." (. int beg = la->pos; int col = la->col; int line = la->line; .)
508
+ { ANY
509
+ | badString (. SemErr(L"bad string in attributes"); .)
510
+ }
511
+ ".>" (. if (t->pos > beg) p->pos = new Position(beg, t->pos, col, line); .)
512
+ .
513
+
514
+ /*------------------------------------------------------------------------------------*/
515
+
516
+ SemText<Position* &pos>
517
+ =
518
+ "(." (. int beg = la->pos; int col = la->col; int line = t->line; .)
519
+ { ANY
520
+ | badString (. SemErr(L"bad string in semantic action"); .)
521
+ | "(." (. SemErr(L"missing end of previous semantic action"); .)
522
+ }
523
+ ".)" (. pos = new Position(beg, t->pos, col, line); .)
524
+ .
525
+
526
+ /*------------------------------------------------------------------------------------*/
527
+
528
+ END Coco.