]>
Commit | Line | Data |
---|---|---|
1 | /*\r | |
2 | * gen.c\r | |
3 | *\r | |
4 | * Generate C code (ANSI, K&R, C++)\r | |
5 | *\r | |
6 | * SOFTWARE RIGHTS\r | |
7 | *\r | |
8 | * We reserve no LEGAL rights to the Purdue Compiler Construction Tool\r | |
9 | * Set (PCCTS) -- PCCTS is in the public domain. An individual or\r | |
10 | * company may do whatever they wish with source code distributed with\r | |
11 | * PCCTS or the code generated by PCCTS, including the incorporation of\r | |
12 | * PCCTS, or its output, into commerical software.\r | |
13 | *\r | |
14 | * We encourage users to develop software with PCCTS. However, we do ask\r | |
15 | * that credit is given to us for developing PCCTS. By "credit",\r | |
16 | * we mean that if you incorporate our source code into one of your\r | |
17 | * programs (commercial product, research project, or otherwise) that you\r | |
18 | * acknowledge this fact somewhere in the documentation, research report,\r | |
19 | * etc... If you like PCCTS and have developed a nice tool with the\r | |
20 | * output, please mention that you developed it using PCCTS. In\r | |
21 | * addition, we ask that this header remain intact in our source code.\r | |
22 | * As long as these guidelines are kept, we expect to continue enhancing\r | |
23 | * this system and expect to make other tools available as they are\r | |
24 | * completed.\r | |
25 | *\r | |
26 | * ANTLR 1.33\r | |
27 | * Terence Parr\r | |
28 | * Parr Research Corporation\r | |
29 | * with Purdue University and AHPCRC, University of Minnesota\r | |
30 | * 1989-2001\r | |
31 | */\r | |
32 | \r | |
33 | #include <stdio.h>\r | |
34 | #include <stdlib.h>\r | |
35 | #include <ctype.h>\r | |
36 | #include "pcctscfg.h"\r | |
37 | #include "set.h"\r | |
38 | #include "syn.h"\r | |
39 | #include "hash.h"\r | |
40 | #include "generic.h"\r | |
41 | #include "dlgdef.h"\r | |
42 | \r | |
43 | #define NumExprPerLine 4\r | |
44 | static int on1line=0;\r | |
45 | static set tokensRefdInBlock;\r | |
46 | \r | |
47 | /* T r a n s l a t i o n T a b l e s */\r | |
48 | \r | |
49 | /* C_Trans[node type] == pointer to function that knows how to translate that node. */\r | |
50 | #ifdef __cplusplus\r | |
51 | void (*C_Trans[NumNodeTypes+1])(...) = {\r | |
52 | NULL,\r | |
53 | NULL, /* See next table.\r | |
54 | Junctions have many types */\r | |
55 | (void (*)(...)) genRuleRef,\r | |
56 | (void (*)(...)) genToken,\r | |
57 | (void (*)(...)) genAction\r | |
58 | };\r | |
59 | #else\r | |
60 | void (*C_Trans[NumNodeTypes+1])() = {\r | |
61 | NULL,\r | |
62 | NULL, /* See next table.\r | |
63 | Junctions have many types */\r | |
64 | genRuleRef,\r | |
65 | genToken,\r | |
66 | genAction\r | |
67 | };\r | |
68 | #endif\r | |
69 | \r | |
70 | /* C_JTrans[Junction type] == pointer to function that knows how to translate that\r | |
71 | * kind of junction node.\r | |
72 | */\r | |
73 | #ifdef __cplusplus\r | |
74 | void (*C_JTrans[NumJuncTypes+1])(...) = {\r | |
75 | NULL,\r | |
76 | (void (*)(...)) genSubBlk,\r | |
77 | (void (*)(...)) genOptBlk,\r | |
78 | (void (*)(...)) genLoopBlk,\r | |
79 | (void (*)(...)) genEndBlk,\r | |
80 | (void (*)(...)) genRule,\r | |
81 | (void (*)(...)) genJunction,\r | |
82 | (void (*)(...)) genEndRule,\r | |
83 | (void (*)(...)) genPlusBlk,\r | |
84 | (void (*)(...)) genLoopBegin\r | |
85 | };\r | |
86 | #else\r | |
87 | void (*C_JTrans[NumJuncTypes+1])() = {\r | |
88 | NULL,\r | |
89 | genSubBlk,\r | |
90 | genOptBlk,\r | |
91 | genLoopBlk,\r | |
92 | genEndBlk,\r | |
93 | genRule,\r | |
94 | genJunction,\r | |
95 | genEndRule,\r | |
96 | genPlusBlk,\r | |
97 | genLoopBegin\r | |
98 | };\r | |
99 | #endif\r | |
100 | \r | |
101 | #define PastWhiteSpace(s) while (*(s) == ' ' || *(s) == '\t') {s++;}\r | |
102 | \r | |
103 | static int tabs = 0;\r | |
104 | \r | |
105 | /* MR6 Got tired of text running off page when using standard tab stops */\r | |
106 | \r | |
107 | #define TAB { int i; \\r | |
108 | if (TabWidth==0) { \\r | |
109 | for (i=0; i<tabs; i++) fputc('\t', output); \\r | |
110 | } else { \\r | |
111 | for (i=0; i<tabs*TabWidth; i++) fputc(' ',output); \\r | |
112 | }; \\r | |
113 | }\r | |
114 | \r | |
115 | static void\r | |
116 | #ifdef __USE_PROTOS\r | |
117 | tab( void )\r | |
118 | #else\r | |
119 | tab( )\r | |
120 | #endif\r | |
121 | TAB\r | |
122 | \r | |
123 | #ifdef __USE_PROTOS\r | |
124 | static char *tokenFollowSet(TokNode *);\r | |
125 | static ActionNode *findImmedAction( Node * );\r | |
126 | static void dumpRetValAssign(char *, char *, RuleRefNode *); /* MR30 */\r | |
127 | static void dumpAfterActions(FILE *output);\r | |
128 | static set ComputeErrorSet(Junction *, int, int);\r | |
129 | static void makeErrorClause(Junction *, set, int, int);\r | |
130 | static void DumpFuncHeader( Junction *, RuleEntry * );\r | |
131 | static int has_guess_block_as_first_item(Junction *);\r | |
132 | static int genExprSets(set *, int);\r | |
133 | static void genExprTree( Tree *t, int k );\r | |
134 | static void genExprTreeOriginal( Tree *t, int k ); /* MR10 */\r | |
135 | static char * findOuterHandlerLabel(ExceptionGroup *eg); /* MR7 */\r | |
136 | static void OutLineInfo(FILE *file,int line,char *fileName); /* MR14 */\r | |
137 | #else\r | |
138 | static char *tokenFollowSet();\r | |
139 | static ActionNode *findImmedAction();\r | |
140 | static void dumpRetValAssign();\r | |
141 | static void dumpAfterActions();\r | |
142 | static set ComputeErrorSet();\r | |
143 | static void makeErrorClause();\r | |
144 | static void DumpFuncHeader();\r | |
145 | static int has_guess_block_as_first_item();\r | |
146 | static int genExprSets();\r | |
147 | static void genExprTree();\r | |
148 | static void genExprTreeOriginal(); /* MR10 */\r | |
149 | static char * findOuterHandlerLabel(); /* MR7 */\r | |
150 | static void OutLineInfo(); /* MR14 */\r | |
151 | #endif\r | |
152 | \r | |
153 | #define gen(s) {tab(); fprintf(output, s);}\r | |
154 | #define gen1(s,a) {tab(); fprintf(output, s,a);}\r | |
155 | #define gen2(s,a,b) {tab(); fprintf(output, s,a,b);}\r | |
156 | #define gen3(s,a,b,c) {tab(); fprintf(output, s,a,b,c);}\r | |
157 | #define gen4(s,a,b,c,d) {tab(); fprintf(output, s,a,b,c,d);}\r | |
158 | #define gen5(s,a,b,c,d,e) {tab(); fprintf(output, s,a,b,c,d,e);}\r | |
159 | #define gen6(s,a,b,c,d,e,f) {tab(); fprintf(output, s,a,b,c,d,e,f);}\r | |
160 | #define gen7(s,a,b,c,d,e,f,g) {tab(); fprintf(output, s,a,b,c,d,e,f,g);}\r | |
161 | \r | |
162 | #define _gen(s) {fprintf(output, s);}\r | |
163 | #define _gen1(s,a) {fprintf(output, s,a);}\r | |
164 | #define _gen2(s,a,b) {fprintf(output, s,a,b);}\r | |
165 | #define _gen3(s,a,b,c) {fprintf(output, s,a,b,c);}\r | |
166 | #define _gen4(s,a,b,c,d){fprintf(output, s,a,b,c,d);}\r | |
167 | #define _gen5(s,a,b,c,d,e){fprintf(output, s,a,b,c,d,e);}\r | |
168 | #define _gen6(s,a,b,c,d,e,f){fprintf(output, s,a,b,c,d,e,f);}\r | |
169 | #define _gen7(s,a,b,c,d,e,f,g){fprintf(output, s,a,b,c,d,e,f,g);}\r | |
170 | \r | |
171 | \r | |
172 | /* MR11 a convenient place to set a break point */\r | |
173 | \r | |
174 | #ifdef __USE_PROTOS\r | |
175 | void MR_break(void) \r | |
176 | #else\r | |
177 | void MR_break() \r | |
178 | #endif\r | |
179 | {\r | |
180 | return;\r | |
181 | }\r | |
182 | \r | |
183 | /* MR10 genTraceOut(Junction *) */\r | |
184 | \r | |
185 | #ifdef __USE_PROTOS\r | |
186 | static void genTraceOut(Junction *q)\r | |
187 | #else\r | |
188 | static void genTraceOut(q)\r | |
189 | Junction *q;\r | |
190 | #endif\r | |
191 | {\r | |
192 | if ( TraceGen ) {\r | |
193 | if ( GenCC ) {gen1("zzTRACEOUT(\"%s\");\n", q->rname);}\r | |
194 | else gen1("zzTRACEOUT((ANTLRChar *)\"%s\");\n", q->rname);\r | |
195 | }\r | |
196 | }\r | |
197 | \r | |
198 | static void\r | |
199 | #ifdef __USE_PROTOS\r | |
200 | warn_about_using_gk_option(void)\r | |
201 | #else\r | |
202 | warn_about_using_gk_option()\r | |
203 | #endif\r | |
204 | {\r | |
205 | static int warned_already=0;\r | |
206 | \r | |
207 | if ( !DemandLookahead || warned_already ) return;\r | |
208 | warned_already = 1;\r | |
209 | warnNoFL("-gk option could cause trouble for <<...>>? predicates");\r | |
210 | }\r | |
211 | \r | |
212 | void\r | |
213 | #ifdef __USE_PROTOS\r | |
214 | freeBlkFsets( Junction *q )\r | |
215 | #else\r | |
216 | freeBlkFsets( q )\r | |
217 | Junction *q;\r | |
218 | #endif\r | |
219 | {\r | |
220 | int i;\r | |
221 | Junction *alt;\r | |
222 | require(q!=NULL, "freeBlkFsets: invalid node");\r | |
223 | \r | |
224 | for (alt=q; alt != NULL; alt= (Junction *) alt->p2 )\r | |
225 | {\r | |
226 | for (i=1; i<=CLL_k; i++) set_free(alt->fset[i]);\r | |
227 | }\r | |
228 | }\r | |
229 | \r | |
230 | /*\r | |
231 | * Generate a local variable allocation for each token references\r | |
232 | * in this block.\r | |
233 | */\r | |
234 | static void\r | |
235 | #ifdef __USE_PROTOS\r | |
236 | genTokenPointers( Junction *q )\r | |
237 | #else\r | |
238 | genTokenPointers( q )\r | |
239 | Junction *q;\r | |
240 | #endif\r | |
241 | {\r | |
242 | /* Rule refs are counted and can be referenced, but their\r | |
243 | * value is not set to anything useful ever.\r | |
244 | *\r | |
245 | * The ptrs are to be named _tij where i is the current level\r | |
246 | * and j is the element number within an alternative.\r | |
247 | */\r | |
248 | int first=1, t=0;\r | |
249 | set a;\r | |
250 | tokensRefdInBlock = q->tokrefs;\r | |
251 | \r | |
252 | if ( set_deg(q->tokrefs) == 0 ) return;\r | |
253 | a = set_dup(q->tokrefs);\r | |
254 | gen("ANTLRTokenPtr ");\r | |
255 | for (; !set_nil(a); set_rm(t, a))\r | |
256 | {\r | |
257 | t = set_int(a);\r | |
258 | if ( first ) first = 0;\r | |
259 | else _gen(",");\r | |
260 | if ( !DontCopyTokens ) _gen2("_tv%d%d,", BlkLevel, t);\r | |
261 | _gen2("_t%d%d", BlkLevel, t);\r | |
262 | if ( !DontCopyTokens ) {_gen2("= &_tv%d%d", BlkLevel, t);}\r | |
263 | else _gen("=NULL");\r | |
264 | }\r | |
265 | _gen(";\n");\r | |
266 | set_free(a);\r | |
267 | }\r | |
268 | \r | |
269 | static int\r | |
270 | #ifdef __USE_PROTOS\r | |
271 | hasDefaultException(ExceptionGroup *eg)\r | |
272 | #else\r | |
273 | hasDefaultException(eg)\r | |
274 | ExceptionGroup *eg;\r | |
275 | #endif\r | |
276 | {\r | |
277 | ListNode *q;\r | |
278 | \r | |
279 | for (q = eg->handlers->next; q!=NULL; q=q->next)\r | |
280 | {\r | |
281 | ExceptionHandler *eh = (ExceptionHandler *)q->elem;\r | |
282 | if ( strcmp("default", eh->signalname)==0 ) {\r | |
283 | return 1;\r | |
284 | }\r | |
285 | }\r | |
286 | return 0;\r | |
287 | }\r | |
288 | static void\r | |
289 | #ifdef __USE_PROTOS\r | |
290 | dumpException(ExceptionGroup *eg, int no_default_case)\r | |
291 | #else\r | |
292 | dumpException(eg, no_default_case)\r | |
293 | ExceptionGroup *eg;\r | |
294 | int no_default_case;\r | |
295 | #endif\r | |
296 | {\r | |
297 | char *outerLabel; /* MR7 */\r | |
298 | int altHandler=0; /* MR7 */\r | |
299 | int namedHandler=0; /* MR7 */\r | |
300 | \r | |
301 | outerLabel=findOuterHandlerLabel(eg); /* MR7 */\r | |
302 | \r | |
303 | if (eg->label != NULL) { /* MR7 */\r | |
304 | namedHandler=1; /* MR7 */\r | |
305 | } else if (eg->forRule) { /* MR7 */\r | |
306 | /* nothing */ /* MR20 */\r | |
307 | } else { /* MR7 */\r | |
308 | altHandler=1; /* MR7 */\r | |
309 | }; /* MR7 */\r | |
310 | \r | |
311 | #if 0\r | |
312 | ** if (! eg->used) { /* MR7 */\r | |
313 | ** warnFL("exception group never used", /* MR7 */\r | |
314 | ** FileStr[eg->altstart->file],eg->altstart->line); /* MR7 */\r | |
315 | ** }; /* MR7 */\r | |
316 | #endif\r | |
317 | \r | |
318 | if (namedHandler) { /* MR7 */\r | |
319 | gen1("switch ( _signal ) { /* [%s] */\n",eg->label); /* MR7 */\r | |
320 | } else { /* MR7 */\r | |
321 | gen("switch ( _signal ) {\n"); /* MR7 */\r | |
322 | gen("case NoSignal: break; /* MR7 */\n"); /* MR7 */\r | |
323 | }; /* MR7 */\r | |
324 | {\r | |
325 | ListNode *q;\r | |
326 | for (q = eg->handlers->next; q!=NULL; q=q->next)\r | |
327 | {\r | |
328 | ExceptionHandler *eh = (ExceptionHandler *)q->elem;\r | |
329 | if ( strcmp("default", eh->signalname)==0 ) {\r | |
330 | gen("default :\n");\r | |
331 | tabs++;\r | |
332 | dumpAction(eh->action, output, tabs, -1, 1, 1);\r | |
333 | gen("_signal=NoSignal; /* MR7 */\n"); /* MR7 */\r | |
334 | gen("break; /* MR7 */\n"); /* MR7 */\r | |
335 | tabs--;\r | |
336 | gen("}\n");\r | |
337 | \r | |
338 | /* copied from later code in dumpException */ /* MR7 */\r | |
339 | \r | |
340 | if (namedHandler) { /* MR7 */\r | |
341 | gen("if (_signal != NoSignal)"); /* MR7 */\r | |
342 | _gen1(" goto %s_handler; /* MR7 */\n",outerLabel);/* MR7 */\r | |
343 | } else if (altHandler) { /* MR7 */\r | |
344 | gen1("goto %s_handler; /* MR7 */\n",outerLabel); /* MR7 */\r | |
345 | };\r | |
346 | return;\r | |
347 | }\r | |
348 | gen1("case %s :\n", eh->signalname);\r | |
349 | tabs++;\r | |
350 | if ( eh->action != NULL )\r | |
351 | {\r | |
352 | dumpAction(eh->action, output, tabs, -1, 1, 1);\r | |
353 | gen("break; /* MR7 */\n"); /* MR7 */\r | |
354 | }\r | |
355 | tabs--;\r | |
356 | }\r | |
357 | }\r | |
358 | if ( no_default_case ) return;\r | |
359 | \r | |
360 | gen("default :\n");\r | |
361 | tabs++; /* MR7 */\r | |
362 | gen("break; /* MR7 */\n"); /* MR7 */\r | |
363 | tabs--; /* MR7 */\r | |
364 | \r | |
365 | tabs++;\r | |
366 | /***** gen("*_retsignal = _signal;\n"); *****/\r | |
367 | \r | |
368 | tabs--;\r | |
369 | gen("}\n");\r | |
370 | \r | |
371 | if (namedHandler) { /* MR7 */\r | |
372 | gen("if (_signal != NoSignal)"); /* MR7 */\r | |
373 | _gen1(" goto %s_handler; /* MR7 */\n",outerLabel); /* MR7 */\r | |
374 | } else if (altHandler) { /* MR7 */\r | |
375 | gen1("goto %s_handler; /* MR7 */\n",outerLabel); /* MR7 */\r | |
376 | };\r | |
377 | \r | |
378 | }\r | |
379 | \r | |
380 | static void\r | |
381 | #ifdef __USE_PROTOS\r | |
382 | dumpExceptions(ListNode *list)\r | |
383 | #else\r | |
384 | dumpExceptions(list)\r | |
385 | ListNode *list;\r | |
386 | #endif\r | |
387 | {\r | |
388 | ListNode *p;\r | |
389 | \r | |
390 | for (p = list->next; p!=NULL; p=p->next)\r | |
391 | {\r | |
392 | ExceptionGroup *eg = (ExceptionGroup *) p->elem;\r | |
393 | _gen2("%s%s_handler:\n",\r | |
394 | eg->label==NULL?"":eg->label,\r | |
395 | eg->altID==NULL?"":eg->altID);\r | |
396 | if ( eg->altID!=NULL ) dumpException(eg, 0);\r | |
397 | else {\r | |
398 | /* This must be the rule exception handler */\r | |
399 | dumpException(eg, 1);\r | |
400 | if ( !hasDefaultException(eg) )\r | |
401 | {\r | |
402 | gen("default :\n");\r | |
403 | tabs++;\r | |
404 | gen("zzdflthandlers(_signal,_retsignal);\n");\r | |
405 | tabs--;\r | |
406 | gen("}\n");\r | |
407 | }\r | |
408 | }\r | |
409 | }\r | |
410 | }\r | |
411 | \r | |
412 | /* For each element label that is found in a rule, generate a unique\r | |
413 | * Attribute (and AST pointer if GenAST) variable.\r | |
414 | */\r | |
415 | void\r | |
416 | #ifdef __USE_PROTOS\r | |
417 | genElementLabels(ListNode *list)\r | |
418 | #else\r | |
419 | genElementLabels(list)\r | |
420 | ListNode *list;\r | |
421 | #endif\r | |
422 | {\r | |
423 | int first=1;\r | |
424 | ListNode *p;\r | |
425 | \r | |
426 | if ( GenCC ) {gen("ANTLRTokenPtr");}\r | |
427 | else {gen("Attrib");}\r | |
428 | for (p = list->next; p!=NULL; p=p->next)\r | |
429 | {\r | |
430 | char *ep = (char *)p->elem;\r | |
431 | if ( first ) first = 0;\r | |
432 | else _gen(",");\r | |
433 | if ( GenCC ) {_gen1(" %s=NULL",ep);}\r | |
434 | else {_gen1(" %s",ep);}\r | |
435 | }\r | |
436 | _gen(";\n");\r | |
437 | \r | |
438 | if ( !GenAST ) return;\r | |
439 | \r | |
440 | first = 1;\r | |
441 | gen("AST");\r | |
442 | for (p = list->next; p!=NULL; p=p->next)\r | |
443 | {\r | |
444 | char *ep = (char *)p->elem;\r | |
445 | if ( first ) first = 0;\r | |
446 | else _gen(",");\r | |
447 | _gen1(" *%s_ast=NULL",ep);\r | |
448 | }\r | |
449 | _gen(";\n");\r | |
450 | }\r | |
451 | \r | |
452 | /*\r | |
453 | * Generate a local variable allocation for each token or rule reference\r | |
454 | * in this block.\r | |
455 | */\r | |
456 | static void\r | |
457 | #ifdef __USE_PROTOS\r | |
458 | genASTPointers( Junction *q )\r | |
459 | #else\r | |
460 | genASTPointers( q )\r | |
461 | Junction *q;\r | |
462 | #endif\r | |
463 | {\r | |
464 | int first=1, t;\r | |
465 | set a;\r | |
466 | \r | |
467 | a = set_or(q->tokrefs, q->rulerefs);\r | |
468 | if ( set_deg(a) > 0 )\r | |
469 | {\r | |
470 | gen("AST ");\r | |
471 | for (; !set_nil(a); set_rm(t, a))\r | |
472 | {\r | |
473 | t = set_int(a);\r | |
474 | if ( first ) first = 0;\r | |
475 | else _gen(",");\r | |
476 | _gen2("*_ast%d%d=NULL", BlkLevel, t);\r | |
477 | }\r | |
478 | set_free(a);\r | |
479 | }\r | |
480 | _gen(";\n");\r | |
481 | }\r | |
482 | \r | |
483 | static void\r | |
484 | #ifdef __USE_PROTOS\r | |
485 | BLOCK_Head( void )\r | |
486 | #else\r | |
487 | BLOCK_Head( )\r | |
488 | #endif\r | |
489 | {\r | |
490 | gen("{\n");\r | |
491 | tabs++;\r | |
492 | if ( !GenCC ) gen1("zzBLOCK(zztasp%d);\n", BlkLevel);\r | |
493 | }\r | |
494 | \r | |
495 | static void\r | |
496 | #ifdef __USE_PROTOS\r | |
497 | BLOCK_Tail( void )\r | |
498 | #else\r | |
499 | BLOCK_Tail( )\r | |
500 | #endif\r | |
501 | {\r | |
502 | if ( !GenCC ) gen1("zzEXIT(zztasp%d);\n", BlkLevel);\r | |
503 | if ( !GenCC ) gen("}\n");\r | |
504 | tabs--;\r | |
505 | gen("}\n");\r | |
506 | }\r | |
507 | \r | |
508 | static void\r | |
509 | #ifdef __USE_PROTOS\r | |
510 | BLOCK_Preamble( Junction *q )\r | |
511 | #else\r | |
512 | BLOCK_Preamble( q )\r | |
513 | Junction *q;\r | |
514 | #endif\r | |
515 | {\r | |
516 | ActionNode *a;\r | |
517 | Junction *begin;\r | |
518 | \r | |
519 | BLOCK_Head();\r | |
520 | if ( GenCC ) genTokenPointers(q);\r | |
521 | if ( GenCC&&GenAST ) genASTPointers(q);\r | |
522 | if ( q->jtype == aPlusBlk ) gen("int zzcnt=1;\n");\r | |
523 | if ( q->parm != NULL && !q->predparm ) gen1("zzaPush(%s);\n", q->parm)\r | |
524 | else if ( !GenCC ) gen("zzMake0;\n");\r | |
525 | if ( !GenCC ) gen("{\n");\r | |
526 | if ( q->jtype == aLoopBegin ) begin = (Junction *) ((Junction *)q->p1);\r | |
527 | else begin = q;\r | |
528 | if ( has_guess_block_as_first_item(begin) )\r | |
529 | {\r | |
530 | gen("zzGUESS_BLOCK\n");\r | |
531 | }\r | |
532 | if ( q->jtype == aLoopBegin )\r | |
533 | a = findImmedAction( ((Junction *)q->p1)->p1 ); /* look at aLoopBlk */\r | |
534 | else\r | |
535 | a = findImmedAction( q->p1 );\r | |
536 | if ( a!=NULL && !a->is_predicate) {\r | |
537 | /* MR21 */ if (!a->noHoist) dumpActionPlus(a, a->action, output, tabs, a->file, a->line, 1);\r | |
538 | a->done = 1; /* remove action. We have already handled it */\r | |
539 | }\r | |
540 | }\r | |
541 | \r | |
542 | void\r | |
543 | #ifdef __USE_PROTOS\r | |
544 | genCombinedPredTreeContextOrig( Predicate *p )\r | |
545 | #else\r | |
546 | genCombinedPredTreeContextOrig( p )\r | |
547 | Predicate *p;\r | |
548 | #endif\r | |
549 | {\r | |
550 | static set *ctx=NULL; /* genExprSets() is destructive, make copy*/\r | |
551 | require(p!=NULL, "can't make context tree for NULL pred tree");\r | |
552 | \r | |
553 | #ifdef DBG_PRED\r | |
554 | fprintf(stderr, "enter genCombinedPredTreeContextOrig(%s,0x%x) with sets:\n", p->expr, p);\r | |
555 | s_fprT(stderr, p->scontext[1]);\r | |
556 | fprintf(stderr, "\n");\r | |
557 | #endif\r | |
558 | if ( p->down == NULL )\r | |
559 | {\r | |
560 | /*** if ( p->k>1 && p->tcontext!=NULL ) ***/\r | |
561 | if ( p->tcontext!=NULL )\r | |
562 | {\r | |
563 | _gen("(");\r | |
564 | genExprTree(p->tcontext, 1);\r | |
565 | _gen(")");\r | |
566 | }\r | |
567 | /*** else if ( p->k==1 && set_deg(p->scontext[1])>0 ) ***/\r | |
568 | else if ( set_deg(p->scontext[1])>0 )\r | |
569 | {\r | |
570 | if ( ctx==NULL ) ctx = (set *)calloc(CLL_k+1, sizeof(set));\r | |
571 | require(ctx!=NULL, "ctx cannot allocate");\r | |
572 | ctx[0]=empty;\r | |
573 | ctx[1]=set_dup(p->scontext[1]);\r | |
574 | _gen("(");\r | |
575 | genExprSets(&(ctx[0]), p->k);\r | |
576 | _gen(")");\r | |
577 | set_free(ctx[1]);\r | |
578 | }\r | |
579 | else if ( p->expr==PRED_AND_LIST || p->expr==PRED_OR_LIST ) {\r | |
580 | fatal_internal("pred tree is orphan OR or AND list");\r | |
581 | }\r | |
582 | else {\r | |
583 | if (! HoistPredicateContext) {\r | |
584 | _gen(" 1 /* no context: prc is off */ ");\r | |
585 | } else {\r | |
586 | fatal_internal("pred tree context is empty");\r | |
587 | };\r | |
588 | }\r | |
589 | return;\r | |
590 | }\r | |
591 | \r | |
592 | /* MR10 - make AND just like OR */\r | |
593 | \r | |
594 | if ( p->expr == PRED_AND_LIST )\r | |
595 | {\r | |
596 | Predicate *list = p->down;\r | |
597 | for (; list!=NULL; list=list->right)\r | |
598 | {\r | |
599 | genCombinedPredTreeContextOrig(list);\r | |
600 | if ( list->right!=NULL ) _gen("|| /* MR10 was wrong */ ");\r | |
601 | };\r | |
602 | return;\r | |
603 | }\r | |
604 | \r | |
605 | if ( p->expr == PRED_OR_LIST )\r | |
606 | {\r | |
607 | Predicate *list = p->down;\r | |
608 | for (; list!=NULL; list=list->right)\r | |
609 | {\r | |
610 | genCombinedPredTreeContextOrig(list);\r | |
611 | if ( list->right!=NULL ) _gen("||");\r | |
612 | };\r | |
613 | return;\r | |
614 | };\r | |
615 | \r | |
616 | fatal("pred tree is really wacked");\r | |
617 | }\r | |
618 | \r | |
619 | /* [genCombinedPredTreeContext] */\r | |
620 | \r | |
621 | void\r | |
622 | #ifdef __USE_PROTOS\r | |
623 | genCombinedPredTreeContext( Predicate *p )\r | |
624 | #else\r | |
625 | genCombinedPredTreeContext( p )\r | |
626 | Predicate *p;\r | |
627 | #endif\r | |
628 | {\r | |
629 | Tree *t;\r | |
630 | int predDepth=0;\r | |
631 | \r | |
632 | if (0 && ! MR_usingPredNames && ! MRhoisting) {\r | |
633 | genCombinedPredTreeContextOrig(p);\r | |
634 | } else {\r | |
635 | /* MR13 */ MR_pred_depth(p,&predDepth);\r | |
636 | /* MR13 */ if (predDepth == 1) {\r | |
637 | /* MR13 */\r | |
638 | /* MR13 */ set scontext[2];\r | |
639 | /* MR13 */ scontext[0]=empty;\r | |
640 | /* MR13 */ scontext[1]=MR_compute_pred_set(p);\r | |
641 | /* MR13 */ if (set_nil(scontext[1])) {\r | |
642 | /* MR13 */ _gen(" 1 /* MR12 no context (-prc off) */ ");\r | |
643 | /* MR13 */ } else {\r | |
644 | /* MR13 */ _gen("(");\r | |
645 | /* MR13 */ genExprSets(&scontext[0], 1);\r | |
646 | /* MR13 */ set_free(scontext[1]);\r | |
647 | /* MR13 */ _gen(")");\r | |
648 | /* MR13 */ };\r | |
649 | \r | |
650 | } else {\r | |
651 | t=MR_compute_pred_tree_context(p);\r | |
652 | if (t == NULL) {\r | |
653 | _gen(" 1 /* MR12 no context (-prc off) */ ");\r | |
654 | } else {\r | |
655 | _gen("(");\r | |
656 | genExprTree(t, 1);\r | |
657 | Tfree(t); /* MR10 */\r | |
658 | _gen(")");\r | |
659 | };\r | |
660 | };\r | |
661 | };\r | |
662 | }\r | |
663 | \r | |
664 | /* [genPredTreeGate] */\r | |
665 | \r | |
666 | void\r | |
667 | #ifdef __USE_PROTOS\r | |
668 | genPredTreeGate( Predicate *p, int in_and_expr )\r | |
669 | #else\r | |
670 | genPredTreeGate( p, in_and_expr )\r | |
671 | Predicate *p;\r | |
672 | int in_and_expr;\r | |
673 | #endif\r | |
674 | {\r | |
675 | if ( in_and_expr )\r | |
676 | {\r | |
677 | _gen("!(");\r | |
678 | genCombinedPredTreeContext(p);\r | |
679 | _gen(")||");\r | |
680 | if ( p->down!=NULL ) _gen("\n");\r | |
681 | }\r | |
682 | else\r | |
683 | {\r | |
684 | _gen("(");\r | |
685 | genCombinedPredTreeContext(p);\r | |
686 | _gen(")&&");\r | |
687 | if ( p->down!=NULL ) _gen("\n");\r | |
688 | }\r | |
689 | }\r | |
690 | \r | |
691 | #ifdef __USE_PROTOS\r | |
692 | void genPredEntry(Predicate *p,int outer)\r | |
693 | #else\r | |
694 | void genPredEntry(p,outer)\r | |
695 | Predicate *p;\r | |
696 | int outer;\r | |
697 | #endif\r | |
698 | {\r | |
699 | int inverted=0;\r | |
700 | Predicate *q;\r | |
701 | int localOuter=outer;\r | |
702 | int needRP=0;\r | |
703 | \r | |
704 | if (p == NULL) return;\r | |
705 | \r | |
706 | if (p->predEntry != NULL && p->predEntry->predLiteral != NULL) {\r | |
707 | if (p->inverted != p->predEntry->pred->inverted) {\r | |
708 | _gen("! /* inverted pred */ (");\r | |
709 | needRP=1;\r | |
710 | } else {\r | |
711 | if (!localOuter) _gen("(");\r | |
712 | needRP=1;\r | |
713 | };\r | |
714 | dumpAction(p->predEntry->predLiteral,output,0,p->source->file,p->source->line,0);\r | |
715 | if (needRP) _gen(")");\r | |
716 | return;\r | |
717 | };\r | |
718 | \r | |
719 | inverted=p->inverted;\r | |
720 | \r | |
721 | if (inverted) {\r | |
722 | _gen(" ! /* inverted pred */ (");\r | |
723 | localOuter=1;\r | |
724 | };\r | |
725 | \r | |
726 | if (p->expr == PRED_OR_LIST) {\r | |
727 | if (!localOuter) _gen("(");\r | |
728 | for (q=p->down; q != NULL ; q=q->right) {\r | |
729 | genPredEntry(q,0);\r | |
730 | if (q->right != NULL) _gen(" || ");\r | |
731 | };\r | |
732 | if (!localOuter) _gen(")");\r | |
733 | } else if (p->expr == PRED_AND_LIST) {\r | |
734 | if (!localOuter) _gen("(");\r | |
735 | for (q=p->down; q != NULL ; q=q->right) {\r | |
736 | genPredEntry(q,0);\r | |
737 | if (q->right != NULL) _gen(" && ");\r | |
738 | };\r | |
739 | if (!localOuter) _gen(")");\r | |
740 | } else {\r | |
741 | if (!localOuter) _gen("(");\r | |
742 | require (p->source != NULL,"predEntry->source == NULL");\r | |
743 | require (p->source->inverted == 0,"dumpPredEntry p->source->inverted != 0");\r | |
744 | dumpAction(p->source->action,output,0,p->source->file,p->source->line,0);\r | |
745 | if (!localOuter) _gen(")");\r | |
746 | };\r | |
747 | \r | |
748 | if (inverted) {\r | |
749 | _gen(")");\r | |
750 | }\r | |
751 | }\r | |
752 | \r | |
753 | void\r | |
754 | #ifdef __USE_PROTOS\r | |
755 | dumpPredAction(ActionNode *anode,\r | |
756 | char *s,FILE *output,int tabs,int file,int line,int final_newline)\r | |
757 | #else\r | |
758 | dumpPredAction(anode,\r | |
759 | s,output,tabs,file,line,final_newline)\r | |
760 | \r | |
761 | ActionNode *anode;\r | |
762 | char *s;\r | |
763 | FILE *output;\r | |
764 | int tabs;\r | |
765 | int file;\r | |
766 | int line;\r | |
767 | int final_newline;\r | |
768 | #endif\r | |
769 | {\r | |
770 | PredEntry *predEntry=anode->predEntry;\r | |
771 | int inverted=anode->inverted;\r | |
772 | Predicate *workPred;\r | |
773 | \r | |
774 | if (predEntry == NULL) {\r | |
775 | \r | |
776 | /* inline predicate literal */\r | |
777 | \r | |
778 | require(inverted == 0,"dumpPredAction action->inverted");\r | |
779 | dumpAction(s,output,tabs,file,line,final_newline);\r | |
780 | \r | |
781 | } else {\r | |
782 | \r | |
783 | /* a reference to a predicate - possibly with an inverted source */\r | |
784 | \r | |
785 | if (predEntry->predLiteral != NULL) {\r | |
786 | if (inverted) _gen("! /* inverted pred */ (");\r | |
787 | dumpAction(predEntry->predLiteral,output,0,anode->file,anode->line,0);\r | |
788 | if (inverted) _gen(")");\r | |
789 | } else {\r | |
790 | workPred=predicate_dup(predEntry->pred);\r | |
791 | if (inverted) workPred->inverted=!workPred->inverted;\r | |
792 | genPredEntry(workPred,1);\r | |
793 | predicate_free(workPred);\r | |
794 | };\r | |
795 | };\r | |
796 | }\r | |
797 | \r | |
798 | /* [genPred] */\r | |
799 | \r | |
800 | void\r | |
801 | #ifdef __USE_PROTOS\r | |
802 | genPred(Predicate *p, Node *j,int suppress_sva)\r | |
803 | #else\r | |
804 | genPred(p,j,suppress_sva)\r | |
805 | Predicate *p;\r | |
806 | Node *j;\r | |
807 | int suppress_sva;\r | |
808 | #endif\r | |
809 | {\r | |
810 | if ( FoundException && !suppress_sva) {_gen("(_sva=(");} /* MR11 suppress_sva */\r | |
811 | else {_gen("(");}\r | |
812 | if ( GenLineInfo && j->file != -1 ) _gen("\n");\r | |
813 | if (p->source != NULL && p->source->ampersandPred != NULL) {\r | |
814 | if (p->source->ampersandPred->k == 1) {\r | |
815 | \r | |
816 | set ctx[2];\r | |
817 | \r | |
818 | ctx[0]=empty;\r | |
819 | ctx[1]=set_dup(p->source->ampersandPred->scontext[1]);\r | |
820 | \r | |
821 | _gen("(");\r | |
822 | genExprSets(&(ctx[0]), p->k);\r | |
823 | _gen(") && ");\r | |
824 | set_free(ctx[1]);\r | |
825 | } else {\r | |
826 | _gen("( ");\r | |
827 | genExprTree(p->source->ampersandPred->tcontext,1);\r | |
828 | _gen(" ) && ");\r | |
829 | };\r | |
830 | };\r | |
831 | \r | |
832 | dumpPredAction((ActionNode *)p->source,\r | |
833 | p->expr, output, 0, -1 /*indicates no line info*/, j->line, 0);\r | |
834 | \r | |
835 | if ( FoundException && !suppress_sva) /* MR11 suppress_sva */\r | |
836 | {_gen("),_sva)");} /* MR10 - get red of "meant ==" messages */\r | |
837 | else {_gen(")");}\r | |
838 | }\r | |
839 | \r | |
840 | void\r | |
841 | #ifdef __USE_PROTOS\r | |
842 | MR_distinctORcontextOpt(Predicate *p,Node *j,int in_and_expr)\r | |
843 | #else\r | |
844 | MR_distinctORcontextOpt(p,j,in_and_expr)\r | |
845 | Predicate *p;\r | |
846 | Node *j;\r | |
847 | int in_and_expr;\r | |
848 | #endif\r | |
849 | {\r | |
850 | Predicate *q;\r | |
851 | \r | |
852 | _gen(" /* MR10 Distinct OR context optimization */ \n");\r | |
853 | \r | |
854 | if (in_and_expr) {\r | |
855 | gen("zzpf=0,\n");\r | |
856 | for (q=p->down; q != NULL; q=q->right) {\r | |
857 | gen("( ");\r | |
858 | genCombinedPredTreeContext(q);\r | |
859 | _gen(" && (zzpf=1, ");\r | |
860 | genPred(q,j,0);\r | |
861 | _gen(" )) ||\n");\r | |
862 | };\r | |
863 | gen("!zzpf)");\r | |
864 | } else {\r | |
865 | require (0,\r | |
866 | "MR_distinctORcontextOpt: can't get here when using MR_predSimplify");\r | |
867 | #if 0\r | |
868 | ** for (q=p->down; q != NULL; q=q->right) {\r | |
869 | ** gen("( ");\r | |
870 | ** genCombinedPredTreeContext(q);\r | |
871 | ** _gen(" && ");\r | |
872 | ** genPred(q,j);\r | |
873 | ** if (q->right != NULL) {\r | |
874 | ** _gen(" ) ||\n");\r | |
875 | ** };\r | |
876 | ** };\r | |
877 | ** gen(")");\r | |
878 | #endif\r | |
879 | };\r | |
880 | }\r | |
881 | \r | |
882 | void\r | |
883 | #ifdef __USE_PROTOS\r | |
884 | genPredTreeOrig( Predicate *p, Node *j, int in_and_expr )\r | |
885 | #else\r | |
886 | genPredTreeOrig( p, j, in_and_expr )\r | |
887 | Predicate *p;\r | |
888 | Node *j;\r | |
889 | int in_and_expr;\r | |
890 | #endif\r | |
891 | {\r | |
892 | \r | |
893 | /* MR10 */ int allHaveContext=1;\r | |
894 | /* MR10 */ int noneHaveContext=1;\r | |
895 | \r | |
896 | /* MR10 */ MR_predContextPresent(p,&allHaveContext,&noneHaveContext);\r | |
897 | \r | |
898 | if ( ! noneHaveContext ) /* MR10 context guards ignored when -prc off */\r | |
899 | {\r | |
900 | _gen("(");\r | |
901 | genPredTreeGate(p, in_and_expr);\r | |
902 | }\r | |
903 | \r | |
904 | /* if leaf node, just gen predicate */\r | |
905 | \r | |
906 | if ( p->down==NULL )\r | |
907 | {\r | |
908 | genPred(p,j,0);\r | |
909 | if ( ! noneHaveContext ) _gen(")"); /* MR10 context guards ignored when -prc off */\r | |
910 | return;\r | |
911 | }\r | |
912 | \r | |
913 | /* if AND list, do both preds (only two possible) */\r | |
914 | if ( p->expr == PRED_AND_LIST )\r | |
915 | {\r | |
916 | #if 0\r | |
917 | ** _gen("(");\r | |
918 | ** genPredTreeOrig(p->down, j, 1);\r | |
919 | ** _gen("&&");\r | |
920 | ** genPredTreeOrig(p->down->right, j, 1);\r | |
921 | ** _gen(")");\r | |
922 | ** if ( ! noneHaveContext ) _gen(")"); /* MR10 context guards ignored when -prc off */\r | |
923 | ** return;\r | |
924 | #endif\r | |
925 | /* MR11 - make it work with AND with more than two children - like OR */\r | |
926 | \r | |
927 | Predicate *list;\r | |
928 | _gen("(");\r | |
929 | list = p->down;\r | |
930 | for (; list!=NULL; list=list->right)\r | |
931 | {\r | |
932 | genPredTreeOrig(list, j, 1);\r | |
933 | if ( list->right!=NULL ) _gen("&&");\r | |
934 | }\r | |
935 | _gen(")");\r | |
936 | if ( ! noneHaveContext ) _gen(")"); /* MR10 context guards ignored when -prc off */\r | |
937 | return;\r | |
938 | };\r | |
939 | \r | |
940 | if ( p->expr == PRED_OR_LIST )\r | |
941 | {\r | |
942 | Predicate *list;\r | |
943 | _gen("(");\r | |
944 | list = p->down;\r | |
945 | for (; list!=NULL; list=list->right)\r | |
946 | {\r | |
947 | genPredTreeOrig(list, j, 0);\r | |
948 | if ( list->right!=NULL ) _gen("||");\r | |
949 | }\r | |
950 | _gen(")");\r | |
951 | if ( ! noneHaveContext ) _gen(")"); /* MR10 context guards ignored when -prc off */\r | |
952 | return;\r | |
953 | }\r | |
954 | \r | |
955 | fatal_internal("genPredTreeOrig: predicate tree is wacked");\r | |
956 | }\r | |
957 | \r | |
958 | #if 0\r | |
959 | ** Predicate member dummyPredDepth is no longer used in MR10\r | |
960 | ** but we might need it again in the future\r | |
961 | **\r | |
962 | ** if (MRhoisting) {\r | |
963 | ** if ( !noneHaveContext &&\r | |
964 | ** ! in_and_expr &&\r | |
965 | ** p->source != NULL &&\r | |
966 | ** p->source->dummyPredicateDepth > 0 &&\r | |
967 | ** p->down == NULL) {\r | |
968 | ** _gen("(");\r | |
969 | ** genCombinedPredTreeContext(p);\r | |
970 | ** _gen(" )\n");\r | |
971 | ** return;\r | |
972 | ** };\r | |
973 | ** };\r | |
974 | #endif\r | |
975 | \r | |
976 | /* [genPredTree] */\r | |
977 | \r | |
978 | /* in_and_expr\r | |
979 | \r | |
980 | what to do if the context is wrong\r | |
981 | what to do if the context is correct but the predicate is false\r | |
982 | \r | |
983 | remember: if the context is wrong it's the same as if the\r | |
984 | predicate is true as far as enabling an alternative\r | |
985 | \r | |
986 | Consider (AND p q r)\r | |
987 | \r | |
988 | if in an ... && ... expression then you don't want\r | |
989 | the entire predicate chain to fail just because the\r | |
990 | context for one component is wrong: so return true\r | |
991 | \r | |
992 | Consider (OR p q r)\r | |
993 | \r | |
994 | if in an ... || ... expression then you don't want\r | |
995 | the entire predicate chain to succeed just because\r | |
996 | the context for one component is correct when the\r | |
997 | corresponding test is false: so return false when\r | |
998 | the context is correct but the test is false.\r | |
999 | */\r | |
1000 | \r | |
1001 | void\r | |
1002 | #ifdef __USE_PROTOS\r | |
1003 | genPredTree( Predicate *p, Node *j, int in_and_expr, int suppress_sva )\r | |
1004 | #else\r | |
1005 | genPredTree( p, j, in_and_expr, suppress_sva)\r | |
1006 | Predicate *p;\r | |
1007 | Node *j;\r | |
1008 | int in_and_expr;\r | |
1009 | int suppress_sva;\r | |
1010 | #endif\r | |
1011 | {\r | |
1012 | \r | |
1013 | int allHaveContext=1;\r | |
1014 | int noneHaveContext=1;\r | |
1015 | Tree *groupTree;\r | |
1016 | Tree *oneTree;\r | |
1017 | Predicate *q;\r | |
1018 | int identicalORcontextOptimization=0;\r | |
1019 | int identicalANDcontextOptimization=0;\r | |
1020 | \r | |
1021 | if (0 && !MR_usingPredNames && !MRhoisting) {\r | |
1022 | genPredTreeOrig(p,j,in_and_expr);\r | |
1023 | return;\r | |
1024 | };\r | |
1025 | \r | |
1026 | MR_predContextPresent(p,&allHaveContext,&noneHaveContext);\r | |
1027 | \r | |
1028 | if ( ! noneHaveContext ) { /* MR10 context guards ignored when -prc off */\r | |
1029 | \r | |
1030 | _gen("(");\r | |
1031 | \r | |
1032 | /* MR10 optimize OR predicates which are all leaves */\r | |
1033 | \r | |
1034 | if (p->expr == PRED_OR_LIST && MR_allPredLeaves(p->down)) {\r | |
1035 | groupTree=MR_compute_pred_tree_context(p);\r | |
1036 | for (q=p->down ; q != NULL ; q=q->right) {\r | |
1037 | oneTree=MR_compute_pred_tree_context(q);\r | |
1038 | if (! MR_tree_equ(groupTree,oneTree)) {\r | |
1039 | Tfree(oneTree);\r | |
1040 | break;\r | |
1041 | };\r | |
1042 | Tfree(oneTree);\r | |
1043 | };\r | |
1044 | Tfree(groupTree);\r | |
1045 | if (q == NULL) {\r | |
1046 | _gen("/* MR10 individual OR gates suppressed when all predicates are leaves");\r | |
1047 | _gen(" with identical context */\n");\r | |
1048 | genPredTreeGate(p,in_and_expr); /* use the parent's in_and_expr for this gate */\r | |
1049 | identicalORcontextOptimization=1;\r | |
1050 | } else {\r | |
1051 | MR_distinctORcontextOpt(p,j,in_and_expr);\r | |
1052 | return;\r | |
1053 | };\r | |
1054 | } else if (p->expr == PRED_AND_LIST && MR_allPredLeaves(p->down)) {\r | |
1055 | \r | |
1056 | /* MR12 optimize AND predicates which are all leaves */\r | |
1057 | \r | |
1058 | groupTree=MR_compute_pred_tree_context(p);\r | |
1059 | for (q=p->down ; q != NULL ; q=q->right) {\r | |
1060 | oneTree=MR_compute_pred_tree_context(q);\r | |
1061 | if (! MR_tree_equ(groupTree,oneTree)) {\r | |
1062 | Tfree(oneTree);\r | |
1063 | break;\r | |
1064 | };\r | |
1065 | Tfree(oneTree);\r | |
1066 | };\r | |
1067 | Tfree(groupTree);\r | |
1068 | if (q == NULL) {\r | |
1069 | _gen("/* MR12 individual AND gates suppressed when all predicates are leaves");\r | |
1070 | _gen(" with identical context */\n");\r | |
1071 | genPredTreeGate(p,in_and_expr); /* use the parent's in_and_expr for this gate */\r | |
1072 | identicalANDcontextOptimization=1;\r | |
1073 | } else {\r | |
1074 | genPredTreeGate(p, in_and_expr);\r | |
1075 | };\r | |
1076 | } else {\r | |
1077 | genPredTreeGate(p, in_and_expr);\r | |
1078 | };\r | |
1079 | }\r | |
1080 | \r | |
1081 | /* if leaf node, just gen predicate */\r | |
1082 | \r | |
1083 | if ( p->down==NULL )\r | |
1084 | {\r | |
1085 | genPred(p,j,suppress_sva);\r | |
1086 | if ( ! noneHaveContext ) _gen(")"); /* MR10 context guards ignored when -prc off */\r | |
1087 | return;\r | |
1088 | }\r | |
1089 | \r | |
1090 | /* if AND list, do both preds (only two possible) */\r | |
1091 | /* MR10 not any more ! */\r | |
1092 | \r | |
1093 | if ( p->expr == PRED_AND_LIST )\r | |
1094 | {\r | |
1095 | Predicate *list;\r | |
1096 | _gen("(");\r | |
1097 | list = p->down;\r | |
1098 | for (; list != NULL; list=list->right) {\r | |
1099 | if (identicalANDcontextOptimization) {\r | |
1100 | genPred(list, j,suppress_sva);\r | |
1101 | } else {\r | |
1102 | genPredTree(list, j, 1, suppress_sva); /* in and context */\r | |
1103 | };\r | |
1104 | if ( list->right!=NULL ) _gen("&&");\r | |
1105 | };\r | |
1106 | _gen(")");\r | |
1107 | if ( ! noneHaveContext ) _gen(")"); /* MR10 context guards ignored when -prc off */\r | |
1108 | return;\r | |
1109 | }\r | |
1110 | \r | |
1111 | if ( p->expr == PRED_OR_LIST )\r | |
1112 | {\r | |
1113 | Predicate *list;\r | |
1114 | _gen("(");\r | |
1115 | list = p->down;\r | |
1116 | for (; list!=NULL; list=list->right)\r | |
1117 | {\r | |
1118 | if (identicalORcontextOptimization) {\r | |
1119 | genPred(list, j,suppress_sva);\r | |
1120 | } else {\r | |
1121 | genPredTree(list, j, 0, suppress_sva);\r | |
1122 | };\r | |
1123 | if ( list->right!=NULL ) _gen("||");\r | |
1124 | }\r | |
1125 | _gen(")");\r | |
1126 | if ( ! noneHaveContext ) _gen(")"); /* MR10 context guards ignored when -prc off */\r | |
1127 | return;\r | |
1128 | }\r | |
1129 | \r | |
1130 | fatal_internal("predicate tree is wacked");\r | |
1131 | }\r | |
1132 | \r | |
1133 | /* [genPredTreeMainXX] */\r | |
1134 | \r | |
1135 | Predicate * /* MR10 */\r | |
1136 | #ifdef __USE_PROTOS\r | |
1137 | genPredTreeMainXX( Predicate *p, Node *j ,int in_and_expr)\r | |
1138 | #else\r | |
1139 | genPredTreeMainXX( p, j ,in_and_expr)\r | |
1140 | Predicate *p;\r | |
1141 | Node *j;\r | |
1142 | int in_and_expr;\r | |
1143 | #endif\r | |
1144 | {\r | |
1145 | \r | |
1146 | int allHaveContext=1;\r | |
1147 | int noneHaveContext=1;\r | |
1148 | \r | |
1149 | #if 0\r | |
1150 | fprintf(stderr,"Pred before\n");\r | |
1151 | dumppred(p);\r | |
1152 | fprintf(stderr,"\n");\r | |
1153 | fprintf(stderr,"Pred after\n");\r | |
1154 | dumppred(p);\r | |
1155 | fprintf(stderr,"\n");\r | |
1156 | #endif\r | |
1157 | \r | |
1158 | p=MR_predSimplifyALL(p); /* MR10 */\r | |
1159 | \r | |
1160 | require (MR_predicate_context_completed(p),"predicate context is not complete");\r | |
1161 | \r | |
1162 | MR_cleanup_pred_trees(p); /* MR10 */\r | |
1163 | \r | |
1164 | MR_predContextPresent(p,&allHaveContext,&noneHaveContext);\r | |
1165 | if (!noneHaveContext & !allHaveContext) {\r | |
1166 | warnFL("predicate contains elements both with and without context",\r | |
1167 | FileStr[j->file],j->line);\r | |
1168 | };\r | |
1169 | \r | |
1170 | if (InfoP) {\r | |
1171 | _gen("\n#if 0\n\n");\r | |
1172 | MR_dumpPred(p,1);\r | |
1173 | _gen("#endif\n");\r | |
1174 | };\r | |
1175 | genPredTree(p,j,in_and_expr,0);\r | |
1176 | return p;\r | |
1177 | }\r | |
1178 | \r | |
1179 | Predicate * /* MR10 */\r | |
1180 | #ifdef __USE_PROTOS\r | |
1181 | genPredTreeMain( Predicate *p, Node *j)\r | |
1182 | #else\r | |
1183 | genPredTreeMain( p, j)\r | |
1184 | Predicate *p;\r | |
1185 | Node *j;\r | |
1186 | #endif\r | |
1187 | {\r | |
1188 | return genPredTreeMainXX(p,j,1);\r | |
1189 | }\r | |
1190 | \r | |
1191 | static void\r | |
1192 | #ifdef __USE_PROTOS\r | |
1193 | genExprTreeOriginal( Tree *t, int k )\r | |
1194 | #else\r | |
1195 | genExprTreeOriginal( t, k )\r | |
1196 | Tree *t;\r | |
1197 | int k;\r | |
1198 | #endif\r | |
1199 | {\r | |
1200 | require(t!=NULL, "genExprTreeOriginal: NULL tree");\r | |
1201 | \r | |
1202 | if ( t->token == ALT )\r | |
1203 | {\r | |
1204 | _gen("("); genExprTreeOriginal(t->down, k); _gen(")");\r | |
1205 | if ( t->right!=NULL )\r | |
1206 | {\r | |
1207 | _gen("||");\r | |
1208 | on1line++;\r | |
1209 | if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }\r | |
1210 | _gen("("); genExprTreeOriginal(t->right, k); _gen(")");\r | |
1211 | }\r | |
1212 | return;\r | |
1213 | }\r | |
1214 | if ( t->down!=NULL ) _gen("(");\r | |
1215 | _gen1("LA(%d)==",k);\r | |
1216 | if ( TokenString(t->token) == NULL ) _gen1("%d", t->token)\r | |
1217 | else _gen1("%s", TokenString(t->token));\r | |
1218 | if ( t->down!=NULL )\r | |
1219 | {\r | |
1220 | _gen("&&");\r | |
1221 | on1line++;\r | |
1222 | if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }\r | |
1223 | _gen("("); genExprTreeOriginal(t->down, k+1); _gen(")");\r | |
1224 | }\r | |
1225 | if ( t->down!=NULL ) _gen(")");\r | |
1226 | if ( t->right!=NULL )\r | |
1227 | {\r | |
1228 | _gen("||");\r | |
1229 | on1line++;\r | |
1230 | if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }\r | |
1231 | _gen("("); genExprTreeOriginal(t->right, k); _gen(")");\r | |
1232 | }\r | |
1233 | }\r | |
1234 | \r | |
1235 | #ifdef __USE_PROTOS\r | |
1236 | static void MR_LAtokenString(int k,int token)\r | |
1237 | #else\r | |
1238 | static void MR_LAtokenString(k,token)\r | |
1239 | int k;\r | |
1240 | int token;\r | |
1241 | #endif\r | |
1242 | {\r | |
1243 | char *ts;\r | |
1244 | \r | |
1245 | ts=TokenString(token);\r | |
1246 | if (ts == NULL) {\r | |
1247 | _gen2(" LA(%d)==%d",k,token);\r | |
1248 | } else {\r | |
1249 | _gen2(" LA(%d)==%s",k,ts);\r | |
1250 | };\r | |
1251 | }\r | |
1252 | \r | |
1253 | \r | |
1254 | #ifdef __USE_PROTOS\r | |
1255 | static int MR_countLeaves(Tree *t)\r | |
1256 | #else\r | |
1257 | static int MR_countLeaves(t)\r | |
1258 | Tree *t;\r | |
1259 | #endif\r | |
1260 | {\r | |
1261 | if (t == NULL) return 0;\r | |
1262 | if (t->token == ALT) {\r | |
1263 | return MR_countLeaves(t->down)+MR_countLeaves(t->right);\r | |
1264 | } else {\r | |
1265 | return 1+MR_countLeaves(t->down)+MR_countLeaves(t->right);\r | |
1266 | };\r | |
1267 | }\r | |
1268 | \r | |
1269 | #ifdef __USE_PROTOS\r | |
1270 | static void MR_genOneLine(Tree *tree,int k)\r | |
1271 | #else\r | |
1272 | static void MR_genOneLine(tree,k)\r | |
1273 | Tree *tree;\r | |
1274 | int k;\r | |
1275 | #endif\r | |
1276 | {\r | |
1277 | if (tree == NULL) return;\r | |
1278 | if (tree->token == ALT) {\r | |
1279 | MR_genOneLine(tree->down,k);\r | |
1280 | } else {\r | |
1281 | MR_LAtokenString(k,tree->token);\r | |
1282 | if (tree->down != NULL &&\r | |
1283 | tree->down->right == NULL) {\r | |
1284 | _gen(" &&");\r | |
1285 | MR_genOneLine(tree->down,k+1);\r | |
1286 | } else if (tree->down != NULL) {\r | |
1287 | _gen(" && (");\r | |
1288 | MR_genOneLine(tree->down,k+1);\r | |
1289 | _gen(")");\r | |
1290 | };\r | |
1291 | };\r | |
1292 | if (tree->right != NULL) {\r | |
1293 | _gen(" ||");\r | |
1294 | MR_genOneLine(tree->right,k);\r | |
1295 | };\r | |
1296 | }\r | |
1297 | \r | |
1298 | static int across;\r | |
1299 | static int depth;\r | |
1300 | static int lastkonline;\r | |
1301 | \r | |
1302 | #ifdef __USE_PROTOS\r | |
1303 | static void MR_genMultiLine(Tree *tree,int k)\r | |
1304 | #else\r | |
1305 | static void MR_genMultiLine(tree,k)\r | |
1306 | Tree *tree;\r | |
1307 | int k;\r | |
1308 | #endif\r | |
1309 | {\r | |
1310 | int i;\r | |
1311 | \r | |
1312 | if (tree == NULL) return;\r | |
1313 | if (tree->token == ALT) {\r | |
1314 | MR_genMultiLine(tree,k);\r | |
1315 | } else {\r | |
1316 | MR_LAtokenString(k,tree->token);\r | |
1317 | lastkonline=k;\r | |
1318 | across++;\r | |
1319 | if (tree->down != NULL && tree->down->right == NULL) {\r | |
1320 | if (across > 3) {\r | |
1321 | _gen("\n");\r | |
1322 | across=0;\r | |
1323 | lastkonline=0;\r | |
1324 | for (i=0 ; i < depth+k ; i++) _gen(" ");\r | |
1325 | _gen("&&");\r | |
1326 | } else {\r | |
1327 | _gen(" &&");\r | |
1328 | };\r | |
1329 | MR_genMultiLine(tree->down,k+1);\r | |
1330 | } else if (tree->down != NULL) {\r | |
1331 | _gen("\n");\r | |
1332 | lastkonline=0;\r | |
1333 | across=0;\r | |
1334 | for (i=0 ; i < depth+k ; i++) _gen(" ");\r | |
1335 | _gen("&& (");\r | |
1336 | MR_genMultiLine(tree->down,k+1);\r | |
1337 | _gen(")");\r | |
1338 | };\r | |
1339 | };\r | |
1340 | if (tree->right != NULL) {\r | |
1341 | if (k < lastkonline) {\r | |
1342 | _gen("\n");\r | |
1343 | across=0;\r | |
1344 | lastkonline=0;\r | |
1345 | for (i=0; i < depth+k-1 ; i++) _gen(" ");\r | |
1346 | _gen("||");\r | |
1347 | } else if (across > 3 ) {\r | |
1348 | _gen("\n");\r | |
1349 | across=0;\r | |
1350 | lastkonline=0;\r | |
1351 | for (i=0; i < depth+k ; i++) _gen(" ");\r | |
1352 | _gen("||");\r | |
1353 | } else {\r | |
1354 | _gen(" ||");\r | |
1355 | };\r | |
1356 | MR_genMultiLine(tree->right,k);\r | |
1357 | };\r | |
1358 | }\r | |
1359 | \r | |
1360 | #ifdef __USE_PROTOS\r | |
1361 | static void genExprTree(Tree *tree,int k)\r | |
1362 | #else\r | |
1363 | static void genExprTree(tree,k)\r | |
1364 | Tree *tree;\r | |
1365 | int k;\r | |
1366 | #endif\r | |
1367 | {\r | |
1368 | int count;\r | |
1369 | \r | |
1370 | #if 0\r | |
1371 | /* MR20 THM This was probably an error.\r | |
1372 | The routine should probably reference that static \r | |
1373 | "across" and this declaration hides it.\r | |
1374 | */\r | |
1375 | \r | |
1376 | int across;\r | |
1377 | #endif\r | |
1378 | \r | |
1379 | require (tree != NULL,"genExprTree: tree is NULL");\r | |
1380 | require (k > 0,"genExprTree: k <= 0");\r | |
1381 | \r | |
1382 | if (0 && !MRhoisting) { /* MR11 make new version standard */\r | |
1383 | genExprTreeOriginal(tree,k);\r | |
1384 | } else {\r | |
1385 | count=MR_countLeaves(tree);\r | |
1386 | if (count < 5) {\r | |
1387 | MR_genOneLine(tree,k);\r | |
1388 | } else {\r | |
1389 | _gen("\n");\r | |
1390 | across=0;\r | |
1391 | depth=0;\r | |
1392 | lastkonline=0;\r | |
1393 | MR_genMultiLine(tree,k);\r | |
1394 | _gen("\n");\r | |
1395 | };\r | |
1396 | };\r | |
1397 | }\r | |
1398 | \r | |
1399 | \r | |
1400 | /*\r | |
1401 | * Generate LL(k) type expressions of the form:\r | |
1402 | *\r | |
1403 | * (LA(1) == T1 || LA(1) == T2 || ... || LA(1) == Tn) &&\r | |
1404 | * (LA(2) == T1 || LA(2) == T2 || ... || LA(2) == Tn) &&\r | |
1405 | * .....\r | |
1406 | * (LA(k) == T1 || LA(k) == T2 || ... || LA(k) == Tn)\r | |
1407 | *\r | |
1408 | * If GenExprSetsOpt generate:\r | |
1409 | *\r | |
1410 | * (setwdi[LA(1)]&(1<<j)) && (setwdi[LA(2)]&(1<<j)) ...\r | |
1411 | *\r | |
1412 | * where n is set_deg(expr) and Ti is some random token and k is the last nonempty\r | |
1413 | * set in fset <=CLL_k.\r | |
1414 | * k=1..CLL_k where CLL_k >= 1.\r | |
1415 | *\r | |
1416 | * This routine is visible only to this file and cannot answer a TRANS message.\r | |
1417 | *\r | |
1418 | */\r | |
1419 | \r | |
1420 | /* [genExpr] */\r | |
1421 | \r | |
1422 | static int\r | |
1423 | #ifdef __USE_PROTOS\r | |
1424 | genExpr( Junction *j )\r | |
1425 | #else\r | |
1426 | genExpr( j )\r | |
1427 | Junction *j;\r | |
1428 | #endif\r | |
1429 | {\r | |
1430 | int max_k;\r | |
1431 | \r | |
1432 | /* if full LL(k) is sufficient, then don't use approximate (-ck) lookahead\r | |
1433 | * from CLL_k..LL_k\r | |
1434 | */\r | |
1435 | {\r | |
1436 | int limit;\r | |
1437 | if ( j->ftree!=NULL ) limit = LL_k;\r | |
1438 | else limit = CLL_k;\r | |
1439 | max_k = genExprSets(j->fset, limit);\r | |
1440 | }\r | |
1441 | \r | |
1442 | /* Do tests for real tuples from other productions that conflict with\r | |
1443 | * artificial tuples generated by compression (using sets of tokens\r | |
1444 | * rather than k-trees).\r | |
1445 | */\r | |
1446 | if ( j->ftree != NULL )\r | |
1447 | {\r | |
1448 | _gen(" && !("); genExprTree(j->ftree, 1); _gen(")");\r | |
1449 | }\r | |
1450 | \r | |
1451 | if ( ParseWithPredicates && j->predicate!=NULL )\r | |
1452 | {\r | |
1453 | Predicate *p = j->predicate;\r | |
1454 | warn_about_using_gk_option();\r | |
1455 | _gen("&&");\r | |
1456 | j->predicate=genPredTreeMain(p, (Node *)j); /* MR10 */\r | |
1457 | }\r | |
1458 | \r | |
1459 | return max_k;\r | |
1460 | }\r | |
1461 | \r | |
1462 | static int\r | |
1463 | #ifdef __USE_PROTOS\r | |
1464 | genExprSets( set *fset, int limit )\r | |
1465 | #else\r | |
1466 | genExprSets( fset, limit )\r | |
1467 | set *fset;\r | |
1468 | int limit;\r | |
1469 | #endif\r | |
1470 | {\r | |
1471 | int k = 1;\r | |
1472 | int max_k = 0;\r | |
1473 | unsigned *e, *g, firstTime=1;\r | |
1474 | \r | |
1475 | if (set_nil(fset[1])) {\r | |
1476 | _gen(" 0 /* MR13 empty set expression - undefined rule ? infinite left recursion ? */ ");\r | |
1477 | MR_BadExprSets++;\r | |
1478 | };\r | |
1479 | \r | |
1480 | if ( GenExprSetsOpt )\r | |
1481 | {\r | |
1482 | while ( k <= limit && !set_nil(fset[k]) ) /* MR11 */\r | |
1483 | {\r | |
1484 | if ( set_deg(fset[k])==1 ) /* too simple for a set? */\r | |
1485 | {\r | |
1486 | int e;\r | |
1487 | _gen1("(LA(%d)==",k);\r | |
1488 | e = set_int(fset[k]);\r | |
1489 | if ( TokenString(e) == NULL ) _gen1("%d)", e)\r | |
1490 | else _gen1("%s)", TokenString(e));\r | |
1491 | }\r | |
1492 | else\r | |
1493 | {\r | |
1494 | NewSet();\r | |
1495 | FillSet( fset[k] );\r | |
1496 | _gen3("(setwd%d[LA(%d)]&0x%x)", wordnum, k, 1<<setnum);\r | |
1497 | }\r | |
1498 | if ( k>max_k ) max_k = k;\r | |
1499 | if ( k == CLL_k ) break;\r | |
1500 | k++;\r | |
1501 | if ( k<=limit && !set_nil(fset[k]) ) _gen(" && "); /* MR11 */\r | |
1502 | on1line++;\r | |
1503 | if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }\r | |
1504 | }\r | |
1505 | return max_k;\r | |
1506 | }\r | |
1507 | \r | |
1508 | while ( k<= limit && !set_nil(fset[k]) ) /* MR11 */\r | |
1509 | {\r | |
1510 | if ( (e=g=set_pdq(fset[k])) == NULL ) fatal_internal("genExpr: cannot allocate IF expr pdq set");\r | |
1511 | for (; *e!=nil; e++)\r | |
1512 | {\r | |
1513 | if ( !firstTime ) _gen(" || ") else { _gen("("); firstTime = 0; }\r | |
1514 | on1line++;\r | |
1515 | if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }\r | |
1516 | _gen1("LA(%d)==",k);\r | |
1517 | if ( TokenString(*e) == NULL ) _gen1("%d", *e)\r | |
1518 | else _gen1("%s", TokenString(*e));\r | |
1519 | }\r | |
1520 | free( (char *)g );\r | |
1521 | _gen(")");\r | |
1522 | if ( k>max_k ) max_k = k;\r | |
1523 | if ( k == CLL_k ) break;\r | |
1524 | k++;\r | |
1525 | if ( k <= limit && !set_nil(fset[k]) ) { firstTime=1; _gen(" && "); } /* MR11 */\r | |
1526 | on1line++;\r | |
1527 | if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }\r | |
1528 | }\r | |
1529 | return max_k;\r | |
1530 | }\r | |
1531 | \r | |
1532 | /*\r | |
1533 | * Generate code for any type of block. If the last alternative in the block is\r | |
1534 | * empty (not even an action) don't bother doing it. This permits us to handle\r | |
1535 | * optional and loop blocks as well.\r | |
1536 | *\r | |
1537 | * Only do this block, return after completing the block.\r | |
1538 | * This routine is visible only to this file and cannot answer a TRANS message.\r | |
1539 | */\r | |
1540 | static set\r | |
1541 | #ifdef __USE_PROTOS\r | |
1542 | genBlk( Junction *q, int jtype, int *max_k, int *need_right_curly, int * lastAltEmpty /* MR23 */)\r | |
1543 | #else\r | |
1544 | genBlk( q, jtype, max_k, need_right_curly, lastAltEmpty /* MR23 */)\r | |
1545 | Junction *q;\r | |
1546 | int jtype;\r | |
1547 | int *max_k;\r | |
1548 | int *need_right_curly;\r | |
1549 | int *lastAltEmpty; /* MR23 */\r | |
1550 | #endif\r | |
1551 | {\r | |
1552 | set f;\r | |
1553 | Junction *alt;\r | |
1554 | int a_guess_in_block = 0;\r | |
1555 | require(q!=NULL, "genBlk: invalid node");\r | |
1556 | require(q->ntype == nJunction, "genBlk: not junction");\r | |
1557 | *need_right_curly=0;\r | |
1558 | *lastAltEmpty = 0; /* MR23 */\r | |
1559 | if ( q->p2 == NULL ) /* only one alternative? Then don't need if */\r | |
1560 | { \r | |
1561 | if (first_item_is_guess_block((Junction *)q->p1)!=NULL )\r | |
1562 | {\r | |
1563 | if (jtype != aLoopBlk && jtype != aOptBlk && jtype != aPlusBlk) {\r | |
1564 | warnFL("(...)? as only alternative of block is unnecessary", FileStr[q->file], q->line);\r | |
1565 | };\r | |
1566 | gen("zzGUESS\n"); /* guess anyway to make output code consistent */\r | |
1567 | /* MR10 disable */ /**** gen("if ( !zzrv )\n"); ****/\r | |
1568 | /* MR10 */ gen("if ( !zzrv ) {\n"); tabs++; (*need_right_curly)++;\r | |
1569 | };\r | |
1570 | TRANS(q->p1);\r | |
1571 | return empty; /* no decision to be made-->no error set */\r | |
1572 | }\r | |
1573 | \r | |
1574 | f = First(q, 1, jtype, max_k);\r | |
1575 | for (alt=q; alt != NULL; alt= (Junction *) alt->p2 )\r | |
1576 | {\r | |
1577 | if ( alt->p2 == NULL ) /* chk for empty alt */\r | |
1578 | { \r | |
1579 | Node *p = alt->p1;\r | |
1580 | if ( p->ntype == nJunction )\r | |
1581 | {\r | |
1582 | /* we have empty alt */\r | |
1583 | /* MR23\r | |
1584 | There is a conflict between giving good error information for non-exceptions\r | |
1585 | and making life easy for those using parser exception handling. Consider:\r | |
1586 | \r | |
1587 | r: { A } b;\r | |
1588 | b: B;\r | |
1589 | \r | |
1590 | with input "C"\r | |
1591 | \r | |
1592 | Before MR21 the error message would be "expecting B - found C". After MR21\r | |
1593 | the error message would be "expect A, B - found C". This was good, but it\r | |
1594 | caused problems for those using parser exceptions because the reference to\r | |
1595 | B was generated inside the {...} where B really wasn't part of the block.\r | |
1596 | \r | |
1597 | In MR23 this has been changed for the case where exceptions are in use to\r | |
1598 | not generate the extra check in the tail of the {A} block.\r | |
1599 | */\r | |
1600 | \r | |
1601 | \r | |
1602 | /* MR23 */ if (isEmptyAlt( ((Junction *)p)->p1, (Node *)q->end)) {\r | |
1603 | /* MR23 */ *lastAltEmpty = 1;\r | |
1604 | /* MR23 */ if (FoundException) {\r | |
1605 | /* MR23 */ /* code to restore state if a prev alt didn't follow guess */\r | |
1606 | /* MR23 */ if ( a_guess_in_block && jtype != aPlusBlk) {\r | |
1607 | /* MR23 */ gen("if ( !zzrv ) zzGUESS_DONE; /* MR28 */\n");\r | |
1608 | /* MR23 */ }\r | |
1609 | /* MR23 */ break;\r | |
1610 | /* MR23 */ };\r | |
1611 | /* MR28 */ if (jtype == aPlusBlk) {\r | |
1612 | /* MR28 */ break;\r | |
1613 | /* MR28 */ }\r | |
1614 | /* MR23 */ }\r | |
1615 | }\r | |
1616 | } /* end of for loop on alt */\r | |
1617 | \r | |
1618 | /* MR10 */ if (alt->p2 == NULL &&\r | |
1619 | /* MR10 */ ( q->jtype == aSubBlk || q->jtype == RuleBlk) ) {\r | |
1620 | /* MR10 */ if (first_item_is_guess_block(alt)) {\r | |
1621 | /* MR10 */ warnFL("(...)? as last alternative of block is unnecessary",\r | |
1622 | /* MR10 */ FileStr[alt->file],alt->line);\r | |
1623 | /* MR10 */ };\r | |
1624 | /* MR10 */ };\r | |
1625 | \r | |
1626 | if ( alt != q ) gen("else ")\r | |
1627 | else\r | |
1628 | {\r | |
1629 | if ( DemandLookahead ) {\r | |
1630 | if ( !GenCC ) {gen1("LOOK(%d);\n", *max_k);}\r | |
1631 | else gen1("look(%d);\n", *max_k);\r | |
1632 | }\r | |
1633 | }\r | |
1634 | \r | |
1635 | if ( alt!=q )\r | |
1636 | {\r | |
1637 | _gen("{\n");\r | |
1638 | tabs++;\r | |
1639 | (*need_right_curly)++;\r | |
1640 | /* code to restore state if a prev alt didn't follow guess */\r | |
1641 | if ( a_guess_in_block )\r | |
1642 | gen("if ( !zzrv ) zzGUESS_DONE;\n");\r | |
1643 | }\r | |
1644 | if ( first_item_is_guess_block((Junction *)alt->p1)!=NULL )\r | |
1645 | {\r | |
1646 | a_guess_in_block = 1;\r | |
1647 | gen("zzGUESS\n");\r | |
1648 | }\r | |
1649 | gen("if ( ");\r | |
1650 | if ( first_item_is_guess_block((Junction *)alt->p1)!=NULL ) _gen("!zzrv && ");\r | |
1651 | genExpr(alt);\r | |
1652 | _gen(" ) ");\r | |
1653 | _gen("{\n");\r | |
1654 | tabs++;\r | |
1655 | TRANS(alt->p1);\r | |
1656 | --tabs;\r | |
1657 | gen("}\n");\r | |
1658 | /* MR10 */ if (alt->p2 == NULL) {\r | |
1659 | /* MR10 */ if (first_item_is_guess_block(alt)) {\r | |
1660 | /* MR10 */ gen("/* MR10 */ else {\n");\r | |
1661 | /* MR10 */ tabs++;\r | |
1662 | /* MR10 */ (*need_right_curly)++;\r | |
1663 | /* MR10 */ /* code to restore state if a prev alt didn't follow guess */\r | |
1664 | /* MR10 */ gen("/* MR10 */ if ( !zzrv ) zzGUESS_DONE;\n");\r | |
1665 | /* MR10 */ gen("/* MR10 */ if (0) {} /* last alternative of block is guess block */\n");\r | |
1666 | /* MR10 */ };\r | |
1667 | /* MR10 */ };\r | |
1668 | }\r | |
1669 | return f;\r | |
1670 | }\r | |
1671 | \r | |
1672 | static int\r | |
1673 | #ifdef __USE_PROTOS\r | |
1674 | has_guess_block_as_first_item( Junction *q )\r | |
1675 | #else\r | |
1676 | has_guess_block_as_first_item( q )\r | |
1677 | Junction *q;\r | |
1678 | #endif\r | |
1679 | {\r | |
1680 | Junction *alt;\r | |
1681 | \r | |
1682 | for (alt=q; alt != NULL; alt= (Junction *) alt->p2 )\r | |
1683 | {\r | |
1684 | if ( first_item_is_guess_block((Junction *)alt->p1)!=NULL ) return 1;\r | |
1685 | }\r | |
1686 | return 0;\r | |
1687 | }\r | |
1688 | \r | |
1689 | static int\r | |
1690 | #ifdef __USE_PROTOS\r | |
1691 | has_guess_block_as_last_item( Junction *q )\r | |
1692 | #else\r | |
1693 | has_guess_block_as_last_item( q )\r | |
1694 | Junction *q;\r | |
1695 | #endif\r | |
1696 | {\r | |
1697 | Junction *alt;\r | |
1698 | \r | |
1699 | if (q == NULL) return 0;\r | |
1700 | for (alt=q; alt->p2 != NULL && !( (Junction *) alt->p2)->ignore; alt= (Junction *) alt->p2 ) {};\r | |
1701 | return first_item_is_guess_block( (Junction *) alt->p1) != NULL;\r | |
1702 | }\r | |
1703 | \r | |
1704 | /* MR30 See description of first_item_is_guess_block for background */\r | |
1705 | \r | |
1706 | Junction *\r | |
1707 | #ifdef __USE_PROTOS\r | |
1708 | first_item_is_guess_block_extra(Junction *q )\r | |
1709 | #else\r | |
1710 | first_item_is_guess_block_extra(q)\r | |
1711 | Junction *q;\r | |
1712 | #endif\r | |
1713 | {\r | |
1714 | while ( q!=NULL &&\r | |
1715 | ( ( q->ntype==nAction ) ||\r | |
1716 | ( q->ntype==nJunction &&\r | |
1717 | (q->jtype==Generic || q->jtype == aLoopBlk) \r | |
1718 | )\r | |
1719 | )\r | |
1720 | )\r | |
1721 | {\r | |
1722 | if ( q->ntype==nJunction ) q = (Junction *)q->p1;\r | |
1723 | else q = (Junction *) ((ActionNode *)q)->next;\r | |
1724 | }\r | |
1725 | \r | |
1726 | if ( q==NULL ) return NULL;\r | |
1727 | if ( q->ntype!=nJunction ) return NULL;\r | |
1728 | if ( q->jtype!=aSubBlk ) return NULL;\r | |
1729 | if ( !q->guess ) return NULL;\r | |
1730 | \r | |
1731 | return q;\r | |
1732 | }\r | |
1733 | \r | |
1734 | /* return NULL if 1st item of alt is NOT (...)? block; else return ptr to aSubBlk node\r | |
1735 | * of (...)?; This function ignores actions and predicates.\r | |
1736 | */\r | |
1737 | \r | |
1738 | Junction *\r | |
1739 | #ifdef __USE_PROTOS\r | |
1740 | first_item_is_guess_block( Junction *q )\r | |
1741 | #else\r | |
1742 | first_item_is_guess_block( q )\r | |
1743 | Junction *q;\r | |
1744 | #endif\r | |
1745 | {\r | |
1746 | Junction * qOriginal = q; /* DEBUG */\r | |
1747 | \r | |
1748 | /* MR14 Couldn't find aSubBlock which was a guess block when it lay\r | |
1749 | behind aLoopBlk. The aLoopBlk only appear in conjunction with\r | |
1750 | aLoopBegin, but the routine didn't know that. I think.\r | |
1751 | \r | |
1752 | MR14a Added extra parentheses to clarify precedence\r | |
1753 | \r | |
1754 | MR30 This appears to have been a mistake. The First set was then\r | |
1755 | computed incorrectly for:\r | |
1756 | \r | |
1757 | r : ( (A)? B\r | |
1758 | | C\r | |
1759 | )*\r | |
1760 | \r | |
1761 | The routine analysis_point was seeing the guess block when\r | |
1762 | it was still analyzing the loopBegin block. As a consequence,\r | |
1763 | when it looked for the analysis_point it was processing the B, but\r | |
1764 | skipping over the C alternative altogether because it thought\r | |
1765 | it was looking at a guess block, not realizing there was a loop\r | |
1766 | block in front of the loopBegin.\r | |
1767 | \r | |
1768 | loopBegin loopBlk subBlk/guess A G EB G B EB EB EB ER\r | |
1769 | | | | ^ ^\r | |
1770 | | | | |\r | |
1771 | | +-> G C G ----------------------+ |\r | |
1772 | | |\r | |
1773 | +--- G G G -------------------------------------+\r | |
1774 | \r | |
1775 | Reported by Arpad Beszedes (beszedes@inf.u-szeged.hu).\r | |
1776 | \r | |
1777 | MR30 This is still more complicated. This fix caused ambiguity messages\r | |
1778 | to be reported for "( (A B)? )* A B" but not for "( (A B)? )+". Why is\r | |
1779 | there a difference when these are outwardly identical ? It is because the\r | |
1780 | start of a (...)* block is represented by two nodes: a loopBegin block\r | |
1781 | followed by a loopBlock whereas the start of a (...)+ block is\r | |
1782 | represented as a single node: a plusBlock. So if first_item_is_guess_block\r | |
1783 | is called when the current node is a loopBegin it starts with the\r | |
1784 | loop block rather than the sub block which follows the loop block.\r | |
1785 | However, we can't just skip past the loop block because some routines\r | |
1786 | depend on the old implementation. So, we provide a new implementation\r | |
1787 | which does skip the loopBlock. However, which should be called when ?\r | |
1788 | I'm not sure, but my guess is that first_item_is_guess_block_extra (the\r | |
1789 | new one) should only be called for the ambiguity routines.\r | |
1790 | \r | |
1791 | */\r | |
1792 | \r | |
1793 | while ( q!=NULL &&\r | |
1794 | ( ( q->ntype==nAction ) ||\r | |
1795 | ( q->ntype==nJunction &&\r | |
1796 | (q->jtype==Generic /*** || q->jtype == aLoopBlk ***/ ) /*** MR30 Undo MR14 change ***/\r | |
1797 | )\r | |
1798 | )\r | |
1799 | )\r | |
1800 | {\r | |
1801 | if ( q->ntype==nJunction ) q = (Junction *)q->p1;\r | |
1802 | else q = (Junction *) ((ActionNode *)q)->next;\r | |
1803 | }\r | |
1804 | \r | |
1805 | if ( q==NULL ) return NULL;\r | |
1806 | if ( q->ntype!=nJunction ) return NULL;\r | |
1807 | if ( q->jtype!=aSubBlk ) return NULL;\r | |
1808 | if ( !q->guess ) return NULL;\r | |
1809 | \r | |
1810 | return q;\r | |
1811 | }\r | |
1812 | \r | |
1813 | /* MR1 */\r | |
1814 | /* MR1 10-Apr-97 MR1 Routine to stringize failed semantic predicates msgs */\r | |
1815 | /* MR1 */\r | |
1816 | \r | |
1817 | #define STRINGIZEBUFSIZE 1024\r | |
1818 | \r | |
1819 | static char stringizeBuf[STRINGIZEBUFSIZE];\r | |
1820 | char *\r | |
1821 | #ifdef __USE_PROTOS\r | |
1822 | stringize(char * s)\r | |
1823 | #else\r | |
1824 | stringize(s)\r | |
1825 | char *s;\r | |
1826 | #endif\r | |
1827 | \r | |
1828 | {\r | |
1829 | char *p;\r | |
1830 | char *stop;\r | |
1831 | \r | |
1832 | p=stringizeBuf;\r | |
1833 | stop=&stringizeBuf[1015];\r | |
1834 | \r | |
1835 | if (s != 0) {\r | |
1836 | while (*s != 0) {\r | |
1837 | if (p >= stop) {\r | |
1838 | goto stringizeStop;\r | |
1839 | } else if (*s == '\n') {\r | |
1840 | *p++='\\';\r | |
1841 | *p++='n';\r | |
1842 | *p++='\\';\r | |
1843 | *p++=*s++;\r | |
1844 | } else if (*s == '\\') {\r | |
1845 | *p++=*s;\r | |
1846 | *p++=*s++;\r | |
1847 | } else if (*s == '\"') {\r | |
1848 | *p++='\\';\r | |
1849 | *p++=*s++;\r | |
1850 | while (*s != 0) {\r | |
1851 | if (p >= stop) {\r | |
1852 | goto stringizeStop;\r | |
1853 | } else if (*s == '\n') {\r | |
1854 | *p++='\\';\r | |
1855 | *p++=*s++;\r | |
1856 | } else if (*s == '\\') {\r | |
1857 | *p++=*s++;\r | |
1858 | *p++=*s++;\r | |
1859 | } else if (*s == '\"') {\r | |
1860 | *p++='\\';\r | |
1861 | *p++=*s++;\r | |
1862 | break;\r | |
1863 | } else {\r | |
1864 | *p++=*s++;\r | |
1865 | };\r | |
1866 | };\r | |
1867 | } else if (*s == '\'') {\r | |
1868 | *p++=*s++;\r | |
1869 | while (*s != 0) {\r | |
1870 | if (p >= stop) {\r | |
1871 | goto stringizeStop;\r | |
1872 | } else if (*s == '\'') {\r | |
1873 | *p++=*s++;\r | |
1874 | break;\r | |
1875 | } else if (*s == '\\') {\r | |
1876 | *p++=*s++;\r | |
1877 | *p++=*s++;\r | |
1878 | } else if (*s == '\"') {\r | |
1879 | *p++='\\';\r | |
1880 | *p++=*s++;\r | |
1881 | break;\r | |
1882 | } else {\r | |
1883 | *p++=*s++;\r | |
1884 | };\r | |
1885 | };\r | |
1886 | } else {\r | |
1887 | *p++=*s++;\r | |
1888 | };\r | |
1889 | };\r | |
1890 | };\r | |
1891 | goto stringizeExit;\r | |
1892 | stringizeStop:\r | |
1893 | *p++='.'; \r | |
1894 | *p++='.'; \r | |
1895 | *p++='.'; \r | |
1896 | stringizeExit:\r | |
1897 | *p=0;\r | |
1898 | return stringizeBuf;\r | |
1899 | }\r | |
1900 | \r | |
1901 | #ifdef __USE_PROTOS\r | |
1902 | int isNullAction(char *s)\r | |
1903 | #else\r | |
1904 | int isNullAction(s)\r | |
1905 | char *s;\r | |
1906 | #endif\r | |
1907 | {\r | |
1908 | char *p;\r | |
1909 | for (p=s; *p != '\0' ; p++) {\r | |
1910 | if (*p != ';' && *p !=' ') return 0;\r | |
1911 | };\r | |
1912 | return 1;\r | |
1913 | }\r | |
1914 | /* MR1 */\r | |
1915 | /* MR1 End of Routine to stringize code for failed predicates msgs */\r | |
1916 | /* MR1 */\r | |
1917 | \r | |
1918 | /* Generate an action. Don't if action is NULL which means that it was already\r | |
1919 | * handled as an init action.\r | |
1920 | */\r | |
1921 | void\r | |
1922 | #ifdef __USE_PROTOS\r | |
1923 | genAction( ActionNode *p )\r | |
1924 | #else\r | |
1925 | genAction( p )\r | |
1926 | ActionNode *p;\r | |
1927 | #endif\r | |
1928 | {\r | |
1929 | require(p!=NULL, "genAction: invalid node and/or rule");\r | |
1930 | require(p->ntype==nAction, "genAction: not action");\r | |
1931 | \r | |
1932 | if ( !p->done ) /* MR10 */ /* MR11 */\r | |
1933 | {\r | |
1934 | if ( p->is_predicate)\r | |
1935 | {\r | |
1936 | if ( p->guardpred != NULL )\r | |
1937 | {\r | |
1938 | Predicate *guardDup=predicate_dup(p->guardpred); /* MR10 */\r | |
1939 | gen("if (!");\r | |
1940 | guardDup=genPredTreeMain(guardDup, (Node *)p);\r | |
1941 | predicate_free(guardDup);\r | |
1942 | }\r | |
1943 | /* MR10 */ else if (p->ampersandPred != NULL) {\r | |
1944 | /* MR10 */ gen("if (!");\r | |
1945 | /* MR10 */ p->ampersandPred=genPredTreeMain(p->ampersandPred, (Node *)p);\r | |
1946 | /* MR10 */ }\r | |
1947 | else\r | |
1948 | {\r | |
1949 | gen("if (!(");\r | |
1950 | /* make sure that '#line n' is on front of line */\r | |
1951 | if ( GenLineInfo && p->file != -1 ) _gen("\n");\r | |
1952 | dumpPredAction(p,p->action, output, 0, p->file, p->line, 0);\r | |
1953 | _gen(")");\r | |
1954 | }\r | |
1955 | \r | |
1956 | /* MR23 Change failed predicate macro to have three arguments:\r | |
1957 | \r | |
1958 | macro arg 1: The stringized predicate itself\r | |
1959 | macro arg 2: 0 => no user-defined error action\r | |
1960 | 1 => user-defined error action\r | |
1961 | macro arg 3: The user-defined error action\r | |
1962 | \r | |
1963 | This gives the user more control of the error action.\r | |
1964 | */\r | |
1965 | tabs++;\r | |
1966 | gen3(") {zzfailed_pred(\"%s\",%s, { %s } );}\n", /* MR23 */\r | |
1967 | stringize(p->action), /* MR23 */\r | |
1968 | (p->pred_fail == NULL ? /* MR23/MR27 */\r | |
1969 | "0 /* report */" : "1 /* user action */"), /* MR23/MR27 */\r | |
1970 | (p->pred_fail == NULL ? /* MR23 */\r | |
1971 | "; /* no user action */" : p->pred_fail)); /* MR23 */\r | |
1972 | tabs--;\r | |
1973 | }\r | |
1974 | else /* not a predicate */\r | |
1975 | {\r | |
1976 | if (! isNullAction(p->action) && !p->noHoist) {\r | |
1977 | if ( FoundGuessBlk ) {\r | |
1978 | if ( GenCC ) {\r | |
1979 | gen("if ( !guessing ) {\n");\r | |
1980 | } else {\r | |
1981 | gen("zzNON_GUESS_MODE {\n");\r | |
1982 | };\r | |
1983 | };\r | |
1984 | dumpActionPlus(p, p->action, output, tabs, p->file, p->line, 1); /* MR21 */\r | |
1985 | if ( FoundGuessBlk ) gen("}\n");\r | |
1986 | };\r | |
1987 | }\r | |
1988 | }\r | |
1989 | TRANS(p->next)\r | |
1990 | }\r | |
1991 | \r | |
1992 | /*\r | |
1993 | * if invoking rule has !noAST pass zzSTR to rule ref and zzlink it in\r | |
1994 | * else pass addr of temp root ptr (&_ast) (don't zzlink it in).\r | |
1995 | *\r | |
1996 | * if ! modifies rule-ref, then never link it in and never pass zzSTR.\r | |
1997 | * Always pass address of temp root ptr.\r | |
1998 | */\r | |
1999 | void\r | |
2000 | #ifdef __USE_PROTOS\r | |
2001 | genRuleRef( RuleRefNode *p )\r | |
2002 | #else\r | |
2003 | genRuleRef( p )\r | |
2004 | RuleRefNode *p;\r | |
2005 | #endif\r | |
2006 | {\r | |
2007 | Junction *q;\r | |
2008 | char *handler_id = "";\r | |
2009 | RuleEntry *r, *r2;\r | |
2010 | char *parm = "", *exsig = "";\r | |
2011 | \r | |
2012 | int genRuleRef_emittedGuessGuard=0; /* MR10 */\r | |
2013 | \r | |
2014 | require(p!=NULL, "genRuleRef: invalid node and/or rule");\r | |
2015 | require(p->ntype==nRuleRef, "genRuleRef: not rule reference");\r | |
2016 | \r | |
2017 | if ( p->altstart!=NULL && p->altstart->exception_label!=NULL )\r | |
2018 | handler_id = p->altstart->exception_label;\r | |
2019 | \r | |
2020 | r = (RuleEntry *) hash_get(Rname, p->text);\r | |
2021 | if ( r == NULL )\r | |
2022 | {\r | |
2023 | warnFL( eMsg1("rule %s not defined",\r | |
2024 | p->text), FileStr[p->file], p->line );\r | |
2025 | return;\r | |
2026 | }\r | |
2027 | \r | |
2028 | /* MR8 5-Aug-97 Reported by S.Bochnak@microtool.com.pl */\r | |
2029 | /* Don't do assign when no return values declared */\r | |
2030 | /* Move definition of q up and use it to guard p->assign */\r | |
2031 | \r | |
2032 | q = RulePtr[r->rulenum]; /* find definition of ref'd rule */ /* MR8 */\r | |
2033 | \r | |
2034 | r2 = (RuleEntry *) hash_get(Rname, p->rname);\r | |
2035 | if ( r2 == NULL ) {warnNoFL("Rule hash table is screwed up beyond belief"); return;}\r | |
2036 | \r | |
2037 | OutLineInfo(output,p->line,FileStr[p->file]);\r | |
2038 | \r | |
2039 | if ( GenCC && GenAST ) {\r | |
2040 | gen("_ast = NULL;\n");\r | |
2041 | }\r | |
2042 | \r | |
2043 | if ( FoundGuessBlk && p->assign!=NULL && q->ret != NULL ) { /* MR8 */\r | |
2044 | if ( GenCC ) {\r | |
2045 | gen("if ( !guessing ) {\n");\r | |
2046 | } else {\r | |
2047 | gen("zzNON_GUESS_MODE {\n");\r | |
2048 | };\r | |
2049 | tabs++; /* MR11 */\r | |
2050 | genRuleRef_emittedGuessGuard=1; /* MR11 */\r | |
2051 | };\r | |
2052 | \r | |
2053 | if ( FoundException ) exsig = "&_signal";\r | |
2054 | \r | |
2055 | tab();\r | |
2056 | if ( GenAST )\r | |
2057 | {\r | |
2058 | if ( GenCC ) {\r | |
2059 | /**** if ( r2->noAST || p->astnode==ASTexclude )\r | |
2060 | ****/\r | |
2061 | {\r | |
2062 | /**** _gen("_ast = NULL;\n");\r | |
2063 | ****/\r | |
2064 | parm = "&_ast";\r | |
2065 | }\r | |
2066 | /*** we always want to set just a pointer now, then set correct\r | |
2067 | pointer after\r | |
2068 | \r | |
2069 | else {\r | |
2070 | _gen("_astp =\r | |
2071 | (_tail==NULL)?(&_sibling):(&(_tail->_right));\n");\r | |
2072 | parm = "_astp";\r | |
2073 | }\r | |
2074 | ****/\r | |
2075 | }\r | |
2076 | else {\r | |
2077 | if ( r2->noAST || p->astnode==ASTexclude )\r | |
2078 | {\r | |
2079 | _gen("_ast = NULL; ");\r | |
2080 | parm = "&_ast";\r | |
2081 | }\r | |
2082 | else parm = "zzSTR";\r | |
2083 | }\r | |
2084 | if ( p->assign!=NULL && q->ret!=NULL ) /* MR8 */\r | |
2085 | {\r | |
2086 | if ( !hasMultipleOperands(p->assign) ) {_gen1("%s = ",p->assign);} /* MR23 */\r | |
2087 | else _gen1("{ struct _rv%d _trv; _trv = ", r->rulenum);\r | |
2088 | }\r | |
2089 | if ( FoundException ) {\r | |
2090 | _gen5("%s%s(%s,&_signal%s%s); ",\r | |
2091 | RulePrefix,\r | |
2092 | p->text,\r | |
2093 | parm,\r | |
2094 | (p->parms!=NULL)?",":"",\r | |
2095 | (p->parms!=NULL)?p->parms:"");\r | |
2096 | if ( p->ex_group!=NULL ) {\r | |
2097 | _gen("\n");\r | |
2098 | gen("if (_signal) {\n");\r | |
2099 | tabs++;\r | |
2100 | dumpException(p->ex_group, 0);\r | |
2101 | tabs--;\r | |
2102 | gen("}");\r | |
2103 | }\r | |
2104 | else {\r | |
2105 | _gen1("if (_signal) goto %s_handler;", handler_id);\r | |
2106 | }\r | |
2107 | }\r | |
2108 | else {\r | |
2109 | _gen5("%s%s(%s%s%s);",\r | |
2110 | RulePrefix,\r | |
2111 | p->text,\r | |
2112 | parm,\r | |
2113 | (p->parms!=NULL)?",":"",\r | |
2114 | (p->parms!=NULL)?p->parms:"");\r | |
2115 | }\r | |
2116 | if ( GenCC && (r2->noAST || p->astnode==ASTexclude) )\r | |
2117 | {\r | |
2118 | /* rule has a ! or element does */\r | |
2119 | /* still need to assign to #i so we can play with it */\r | |
2120 | _gen("\n");\r | |
2121 | gen2("_ast%d%d = (AST *)_ast;", BlkLevel-1, p->elnum);\r | |
2122 | }\r | |
2123 | else if ( !r2->noAST && p->astnode == ASTinclude )\r | |
2124 | {\r | |
2125 | /* rule doesn't have a ! and neither does element */\r | |
2126 | /* MR10 */ if (FoundGuessBlk && !genRuleRef_emittedGuessGuard) {\r | |
2127 | /* MR10 */ _gen("\n");\r | |
2128 | /* MR10 */ if (GenCC) gen ("if (!guessing) { /* MR10 */")\r | |
2129 | /* MR10 */ else gen ("if (!zzguessing) { /* MR10 */\n");\r | |
2130 | /* MR10 */ tabs++;\r | |
2131 | /* MR10 */ };\r | |
2132 | if ( GenCC ) {\r | |
2133 | _gen("\n");\r | |
2134 | gen("if ( _tail==NULL ) _sibling = _ast; else _tail->setRight(_ast);\n");\r | |
2135 | gen2("_ast%d%d = (AST *)_ast;\n", BlkLevel-1, p->elnum);\r | |
2136 | tab();\r | |
2137 | }\r | |
2138 | else _gen(" ");\r | |
2139 | if ( GenCC ) {\r | |
2140 | _gen("ASTBase::"); }\r | |
2141 | else _gen("zz");\r | |
2142 | _gen("link(_root, &_sibling, &_tail);");\r | |
2143 | \r | |
2144 | /* MR10 */ if (FoundGuessBlk && !genRuleRef_emittedGuessGuard) { /* MR10 */\r | |
2145 | /* MR10 */ _gen("\n");\r | |
2146 | /* MR10 */ tabs--;\r | |
2147 | /* MR10 */ if (GenCC) gen ("}; /* MR10 */")\r | |
2148 | /* MR10 */ else gen ("}; /* MR10 */");\r | |
2149 | /* MR10 */ };\r | |
2150 | }\r | |
2151 | }\r | |
2152 | else\r | |
2153 | {\r | |
2154 | if ( p->assign!=NULL && q->ret!=NULL ) /* MR8 */\r | |
2155 | {\r | |
2156 | if ( !hasMultipleOperands(p->assign) ) {_gen1("%s = ",p->assign);} /* MR23 */\r | |
2157 | else _gen1("{ struct _rv%d _trv; _trv = ", r->rulenum);\r | |
2158 | }\r | |
2159 | if ( FoundException ) {\r | |
2160 | _gen4("%s%s(&_signal%s%s); ",\r | |
2161 | RulePrefix,\r | |
2162 | p->text,\r | |
2163 | (p->parms!=NULL)?",":"",\r | |
2164 | (p->parms!=NULL)?p->parms:"");\r | |
2165 | if ( p->ex_group!=NULL ) {\r | |
2166 | _gen("\n");\r | |
2167 | gen("if (_signal) {\n");\r | |
2168 | tabs++;\r | |
2169 | dumpException(p->ex_group, 0);\r | |
2170 | tabs--;\r | |
2171 | gen("}");\r | |
2172 | }\r | |
2173 | else {\r | |
2174 | _gen1("if (_signal) goto %s_handler;", handler_id);\r | |
2175 | }\r | |
2176 | }\r | |
2177 | else {\r | |
2178 | _gen3("%s%s(%s);",\r | |
2179 | RulePrefix,\r | |
2180 | p->text,\r | |
2181 | (p->parms!=NULL)?p->parms:"");\r | |
2182 | }\r | |
2183 | if ( p->assign!=NULL && q->ret!=NULL ) _gen("\n"); /* MR8 */\r | |
2184 | }\r | |
2185 | \r | |
2186 | if ( p->assign!=NULL && q->ret!=NULL) { /* MR8 */\r | |
2187 | if ( hasMultipleOperands(p->assign) ) /* MR23 */\r | |
2188 | {\r | |
2189 | _gen("\n");\r | |
2190 | dumpRetValAssign(p->assign, q->ret, p); /* MR30 */\r | |
2191 | _gen("}");\r | |
2192 | }\r | |
2193 | }\r | |
2194 | _gen("\n");\r | |
2195 | \r | |
2196 | /* Handle element labels now */\r | |
2197 | if ( p->el_label!=NULL )\r | |
2198 | {\r | |
2199 | if ( GenAST )\r | |
2200 | {\r | |
2201 | if ( GenCC ) {\r | |
2202 | gen3("%s_ast = _ast%d%d;\n", p->el_label, BlkLevel-1, p->elnum);\r | |
2203 | }\r | |
2204 | else {gen1("%s_ast = zzastCur;\n", p->el_label);}\r | |
2205 | }\r | |
2206 | else if (!GenCC ) {\r | |
2207 | gen1("%s = zzaCur;\n", p->el_label);\r | |
2208 | }\r | |
2209 | }\r | |
2210 | \r | |
2211 | if ( FoundGuessBlk && p->assign!=NULL && q->ret!=NULL ) { /* MR8 */\r | |
2212 | /* in guessing mode, don't branch to handler upon error */\r | |
2213 | tabs--; /* MR11 */\r | |
2214 | gen("} else {\n");\r | |
2215 | tabs++; /* MR11 */\r | |
2216 | if ( FoundException ) {\r | |
2217 | gen6("%s%s(%s%s&_signal%s%s);\n",\r | |
2218 | RulePrefix,\r | |
2219 | p->text,\r | |
2220 | parm,\r | |
2221 | (*parm!='\0')?",":"",\r | |
2222 | (p->parms!=NULL)?",":"",\r | |
2223 | (p->parms!=NULL)?p->parms:"");\r | |
2224 | }\r | |
2225 | else {\r | |
2226 | gen5("%s%s(%s%s%s);\n",\r | |
2227 | RulePrefix,\r | |
2228 | p->text,\r | |
2229 | parm,\r | |
2230 | (p->parms!=NULL && *parm!='\0')?",":"",\r | |
2231 | (p->parms!=NULL)?p->parms:"");\r | |
2232 | }\r | |
2233 | tabs--; /* MR11 */\r | |
2234 | gen("}\n");\r | |
2235 | }\r | |
2236 | TRANS(p->next)\r | |
2237 | }\r | |
2238 | \r | |
2239 | /*\r | |
2240 | * Generate code to match a token.\r | |
2241 | *\r | |
2242 | * Getting the next token is tricky. We want to ensure that any action\r | |
2243 | * following a token is executed before the next GetToken();\r | |
2244 | */\r | |
2245 | void\r | |
2246 | #ifdef __USE_PROTOS\r | |
2247 | genToken( TokNode *p )\r | |
2248 | #else\r | |
2249 | genToken( p )\r | |
2250 | TokNode *p;\r | |
2251 | #endif\r | |
2252 | {\r | |
2253 | RuleEntry *r;\r | |
2254 | char *handler_id = "";\r | |
2255 | ActionNode *a;\r | |
2256 | char *set_name;\r | |
2257 | char *set_nameErrSet;\r | |
2258 | int complement;\r | |
2259 | int ast_label_in_action = 0; /* MR27 */\r | |
2260 | int pushedCmodeAST = 0; /* MR27 */\r | |
2261 | \r | |
2262 | require(p!=NULL, "genToken: invalid node and/or rule");\r | |
2263 | require(p->ntype==nToken, "genToken: not token");\r | |
2264 | if ( p->altstart!=NULL && p->altstart->exception_label!=NULL )\r | |
2265 | handler_id = p->altstart->exception_label;\r | |
2266 | \r | |
2267 | r = (RuleEntry *) hash_get(Rname, p->rname);\r | |
2268 | if ( r == NULL ) {warnNoFL("Rule hash table is screwed up beyond belief"); return;}\r | |
2269 | \r | |
2270 | /*\r | |
2271 | * MR27 Has the element label been referenced as an AST (with the # operator) ?\r | |
2272 | * If so, then we'll want to build the AST even though the user has used\r | |
2273 | * the ! operator.\r | |
2274 | */\r | |
2275 | /* MR27 */ if (GenAST && p->el_label != NULL) {\r | |
2276 | /* MR27 */ ast_label_in_action = list_search_cstring(r->ast_labels_in_actions,\r | |
2277 | /* MR27 */ p->el_label);\r | |
2278 | /* MR27 */ }\r | |
2279 | \r | |
2280 | OutLineInfo(output,p->line,FileStr[p->file]);\r | |
2281 | \r | |
2282 | if ( !set_nil(p->tset) ) /* implies '.', ~Tok, or tokenclass */\r | |
2283 | {\r | |
2284 | unsigned e;\r | |
2285 | unsigned eErrSet = 0;\r | |
2286 | set b;\r | |
2287 | set bErrSet; /* MR23 */\r | |
2288 | b = set_dup(p->tset);\r | |
2289 | bErrSet = set_dup(p->tset); /* MR23 */\r | |
2290 | complement = p->complement; /* MR23 */\r | |
2291 | if ( p->tclass!=NULL && complement == 0 /* MR23 */) { /* token class not complemented*/\r | |
2292 | static char buf[MaxRuleName+20]; /* MR23 */\r | |
2293 | static char bufErrSet[MaxRuleName+20]; /* MR23 */\r | |
2294 | if ( p->tclass->dumped ) {\r | |
2295 | e = p->tclass->setnum;\r | |
2296 | eErrSet = p->tclass->setnumErrSet;\r | |
2297 | }\r | |
2298 | else {\r | |
2299 | e = DefErrSet(&b, 0, TokenString(p->token));\r | |
2300 | eErrSet = DefErrSetWithSuffix(0, &bErrSet, 1, TokenString(p->token), "_errset");\r | |
2301 | p->tclass->dumped = 1; /* indicate set has been created */\r | |
2302 | p->tclass->setnum = e;\r | |
2303 | p->tclass->setnumErrSet = eErrSet; /* MR23 */\r | |
2304 | }\r | |
2305 | sprintf(buf, "%s_set", TokenString(p->token));\r | |
2306 | sprintf(bufErrSet, "%s_errset", TokenString(p->token)); /* MR23 */\r | |
2307 | set_name = buf;\r | |
2308 | set_nameErrSet = bufErrSet; /* MR23 */\r | |
2309 | }\r | |
2310 | \r | |
2311 | /* MR23 - Forgot about the case of ~TOKCLASS. */\r | |
2312 | \r | |
2313 | else if ( p->tclass!=NULL && complement != 0 /* MR23 */)\r | |
2314 | {\r | |
2315 | static char buf[MaxRuleName+20]; /* MR23 */\r | |
2316 | static char bufErrSet[MaxRuleName+20]; /* MR23 */\r | |
2317 | if ( p->tclass->dumpedComplement ) {\r | |
2318 | e = p->tclass->setnumComplement;\r | |
2319 | eErrSet = p->tclass->setnumErrSetComplement;\r | |
2320 | }\r | |
2321 | else {\r | |
2322 | e = DefErrSetWithSuffix(0, &b, 0, TokenString(p->token), "_setbar");\r | |
2323 | eErrSet = DefErrSetWithSuffix(0, &bErrSet, 1, TokenString(p->token), "_errsetbar");\r | |
2324 | p->tclass->dumpedComplement = 1; /* indicate set has been created */\r | |
2325 | p->tclass->setnumComplement = e;\r | |
2326 | p->tclass->setnumErrSetComplement = eErrSet; /* MR23 */\r | |
2327 | }\r | |
2328 | sprintf(buf, "%s_setbar", TokenString(p->token));\r | |
2329 | sprintf(bufErrSet, "%s_errsetbar", TokenString(p->token)); /* MR23 */\r | |
2330 | set_name = buf;\r | |
2331 | set_nameErrSet = bufErrSet; /* MR23 */\r | |
2332 | }\r | |
2333 | else { /* wild card */\r | |
2334 | static char buf[sizeof("zzerr")+10];\r | |
2335 | static char bufErrSet[sizeof("zzerr")+10];\r | |
2336 | int n = DefErrSet( &b, 0, NULL );\r | |
2337 | int nErrSet = DefErrSetWithSuffix(0, &bErrSet, 1, NULL, "_set");\r | |
2338 | if ( GenCC ) sprintf(buf, "err%d", n);\r | |
2339 | else sprintf(buf, "zzerr%d", n);\r | |
2340 | if ( GenCC ) sprintf(bufErrSet, "err%d", nErrSet);\r | |
2341 | else sprintf(bufErrSet, "zzerr%d", nErrSet);\r | |
2342 | set_name = buf;\r | |
2343 | set_nameErrSet = bufErrSet;\r | |
2344 | }\r | |
2345 | \r | |
2346 | if ( !FoundException ) {\r | |
2347 | /* MR23 */ gen2("zzsetmatch(%s, %s);", set_name, set_nameErrSet);\r | |
2348 | }\r | |
2349 | else if ( p->ex_group==NULL ) {\r | |
2350 | if ( p->use_def_MT_handler )\r | |
2351 | gen3("zzsetmatch_wdfltsig(%s,(ANTLRTokenType)%d,%s);",\r | |
2352 | set_name,\r | |
2353 | p->token,\r | |
2354 | tokenFollowSet(p))\r | |
2355 | else\r | |
2356 | gen2("zzsetmatch_wsig(%s, %s_handler);",\r | |
2357 | set_name,\r | |
2358 | handler_id);\r | |
2359 | }\r | |
2360 | else\r | |
2361 | {\r | |
2362 | gen1("if ( !_setmatch_wsig(%s) ) {\n", set_name);\r | |
2363 | tabs++;\r | |
2364 | /* MR6 */ if (FoundGuessBlk) {\r | |
2365 | /* MR6 */ if ( GenCC ) {gen("if ( guessing ) goto fail;\n");}\r | |
2366 | /* MR6 */ else gen("if ( zzguessing ) goto fail;\n");\r | |
2367 | /* MR6 */ };\r | |
2368 | gen("_signal=MismatchedToken;\n");\r | |
2369 | dumpException(p->ex_group, 0);\r | |
2370 | tabs--;\r | |
2371 | gen("}\n");\r | |
2372 | }\r | |
2373 | set_free(b);\r | |
2374 | set_free(bErrSet);\r | |
2375 | }\r | |
2376 | else if ( TokenString(p->token)!=NULL )\r | |
2377 | {\r | |
2378 | if ( FoundException ) {\r | |
2379 | if ( p->use_def_MT_handler )\r | |
2380 | gen2("zzmatch_wdfltsig(%s,%s);",TokenString(p->token),tokenFollowSet(p))\r | |
2381 | else if ( p->ex_group==NULL )\r | |
2382 | {\r | |
2383 | gen2("zzmatch_wsig(%s, %s_handler);",\r | |
2384 | TokenString(p->token),\r | |
2385 | handler_id);\r | |
2386 | }\r | |
2387 | else\r | |
2388 | {\r | |
2389 | /* MR6 */ if (GenCC) {\r | |
2390 | /* MR6 */ gen1("if ( !_match_wsig(%s) ) {\n", TokenString(p->token));\r | |
2391 | /* MR6 */ } else {\r | |
2392 | /* MR6 */ gen1("if ( !_zzmatch_wsig(%s) ) {\n", TokenString(p->token));\r | |
2393 | /* MR6 */ };\r | |
2394 | tabs++;\r | |
2395 | /* MR6 */ if (FoundGuessBlk) {\r | |
2396 | /* MR6 */ if ( GenCC ) {gen("if ( guessing ) goto fail;\n");}\r | |
2397 | /* MR6 */ else gen("if ( zzguessing ) goto fail;\n");\r | |
2398 | /* MR6 */ };\r | |
2399 | gen("_signal=MismatchedToken;\n");\r | |
2400 | dumpException(p->ex_group, 0);\r | |
2401 | tabs--;\r | |
2402 | gen("}\n");\r | |
2403 | }\r | |
2404 | }\r | |
2405 | else gen1("zzmatch(%s);", TokenString(p->token));\r | |
2406 | }\r | |
2407 | else {\r | |
2408 | if ( FoundException ) {\r | |
2409 | if ( p->use_def_MT_handler )\r | |
2410 | gen2("zzmatch_wdfltsig((ANTLRTokenType)%d,%s);",\r | |
2411 | p->token,tokenFollowSet(p))\r | |
2412 | else\r | |
2413 | gen2("zzmatch_wsig(%d,%s_handler);",p->token,handler_id);\r | |
2414 | }\r | |
2415 | else {gen1("zzmatch(%d);", p->token);}\r | |
2416 | }\r | |
2417 | \r | |
2418 | a = findImmedAction( p->next );\r | |
2419 | /* generate the token labels */\r | |
2420 | if ( GenCC && p->elnum>0 )\r | |
2421 | {\r | |
2422 | /* If building trees in C++, always gen the LT() assigns */\r | |
2423 | if ( set_el(p->elnum, tokensRefdInBlock) || GenAST )\r | |
2424 | {\r | |
2425 | /* MR10 */ if ( FoundGuessBlk ) {\r | |
2426 | /* MR10 */ gen("\n");\r | |
2427 | /* MR10 */ if (p->label_used_in_semantic_pred) {\r | |
2428 | /* MR10 */ gen2(" _t%d%d = (ANTLRTokenPtr)LT(1); /* MR10 */\n", BlkLevel-1, p->elnum);\r | |
2429 | /* MR10 */ } else {\r | |
2430 | /* MR10 */ gen("if ( !guessing ) {\n"); tab();\r | |
2431 | /* MR10 */ _gen2(" _t%d%d = (ANTLRTokenPtr)LT(1);\n", BlkLevel-1, p->elnum);\r | |
2432 | /* MR10 */ gen("}\n");\r | |
2433 | /* MR10 */ };\r | |
2434 | /* MR10 */ } else {\r | |
2435 | /* MR10 */ _gen2(" _t%d%d = (ANTLRTokenPtr)LT(1);", BlkLevel-1, p->elnum);\r | |
2436 | /* MR10 */ };\r | |
2437 | /* MR10 */\r | |
2438 | }\r | |
2439 | \r | |
2440 | /*\r | |
2441 | * MR23 labase is never used in the C++ runtime library.\r | |
2442 | * and this code is generated only in C++ mode\r | |
2443 | */\r | |
2444 | \r | |
2445 | /*** if ( LL_k>1 ) / * MR23 disabled */\r | |
2446 | /*** if ( !DemandLookahead ) _gen(" labase++;"); / * MR23 disabled */\r | |
2447 | /*** _gen("\n"); / * MR23 disabled */\r | |
2448 | /*** tab(); / * MR23 disabled */\r | |
2449 | }\r | |
2450 | if ( GenAST )\r | |
2451 | {\r | |
2452 | if ( FoundGuessBlk &&\r | |
2453 | (ast_label_in_action || !(p->astnode == ASTexclude || r->noAST)) )\r | |
2454 | {\r | |
2455 | if ( GenCC ) {_gen("if ( !guessing ) {\n"); tab();}\r | |
2456 | else {_gen("zzNON_GUESS_MODE {\n"); tab();}\r | |
2457 | }\r | |
2458 | \r | |
2459 | /* MR27 addition when labels referenced when operator ! used */\r | |
2460 | \r | |
2461 | pushedCmodeAST = 0; /* MR27 */\r | |
2462 | if (ast_label_in_action && (p->astnode == ASTexclude || r->noAST)) {\r | |
2463 | _gen("\n");\r | |
2464 | if (GenCC) {\r | |
2465 | /* MR13 */ if (NewAST) {\r | |
2466 | /* MR13 */ gen4("_ast%d%d = newAST(_t%d%d); /* MR27 */\n", BlkLevel-1, p->elnum, BlkLevel-1, p->elnum);\r | |
2467 | /* MR13 */ } else {\r | |
2468 | /* MR13 */ gen4("_ast%d%d = new AST(_t%d%d); /* MR27 */\n", BlkLevel-1, p->elnum, BlkLevel-1, p->elnum);\r | |
2469 | /* MR13 */ }\r | |
2470 | }\r | |
2471 | else {\r | |
2472 | pushedCmodeAST = 1;\r | |
2473 | gen("zzastPush(zzmk_ast(zzastnew(),zzaCur)); /* MR27 */");\r | |
2474 | }\r | |
2475 | }\r | |
2476 | \r | |
2477 | /* end MR27 addition for labels referenced when operator ! used */\r | |
2478 | \r | |
2479 | if (!r->noAST )\r | |
2480 | {\r | |
2481 | if (GenCC && !(p->astnode == ASTexclude) ) {\r | |
2482 | _gen("\n");\r | |
2483 | /* MR13 */ if (NewAST) {\r | |
2484 | /* MR13 */ gen4("_ast%d%d = newAST(_t%d%d);\n", BlkLevel-1, p->elnum, BlkLevel-1, p->elnum);\r | |
2485 | /* MR13 */ } else {\r | |
2486 | /* MR13 */ gen4("_ast%d%d = new AST(_t%d%d);\n", BlkLevel-1, p->elnum, BlkLevel-1, p->elnum);\r | |
2487 | /* MR13 */ }\r | |
2488 | tab();\r | |
2489 | }\r | |
2490 | if ( GenCC && !(p->astnode == ASTexclude) )\r | |
2491 | {_gen2("_ast%d%d->", BlkLevel-1, p->elnum);}\r | |
2492 | else _gen(" ");\r | |
2493 | if ( p->astnode==ASTchild ) {\r | |
2494 | if ( !GenCC ) _gen("zz");\r | |
2495 | _gen("subchild(_root, &_sibling, &_tail);");\r | |
2496 | }\r | |
2497 | else if ( p->astnode==ASTroot ) {\r | |
2498 | if ( !GenCC ) _gen("zz");\r | |
2499 | _gen("subroot(_root, &_sibling, &_tail);");\r | |
2500 | }\r | |
2501 | if ( GenCC && !(p->astnode == ASTexclude) ) {\r | |
2502 | _gen("\n");\r | |
2503 | tab();\r | |
2504 | }\r | |
2505 | }\r | |
2506 | else if ( !GenCC ) {\r | |
2507 | if (! pushedCmodeAST) _gen(" zzastDPush;");\r | |
2508 | }\r | |
2509 | if ( FoundGuessBlk &&\r | |
2510 | (ast_label_in_action || !(p->astnode == ASTexclude || r->noAST)) )\r | |
2511 | {gen("}\n"); tab();}\r | |
2512 | }\r | |
2513 | \r | |
2514 | /* Handle element labels now */\r | |
2515 | if ( p->el_label!=NULL )\r | |
2516 | {\r | |
2517 | int done_NON_GUESSMODE=0;\r | |
2518 | \r | |
2519 | _gen("\n");\r | |
2520 | \r | |
2521 | /* MR10 */ /* do Attrib / Token ptr for token label used in semantic pred */\r | |
2522 | /* MR10 */ /* for these cases do assign even in guess mode */\r | |
2523 | /* MR10 */\r | |
2524 | /* MR10 */ if (p->label_used_in_semantic_pred) {\r | |
2525 | /* MR10 */ if ( GenCC ) {\r | |
2526 | /* MR10 */ if ( set_el(p->elnum, tokensRefdInBlock) || GenAST ) {\r | |
2527 | /* MR10 */ gen3("%s = _t%d%d;", p->el_label, BlkLevel-1, p->elnum);\r | |
2528 | /* MR10 */ } else {\r | |
2529 | /* MR10 */ gen1("%s = (ANTLRTokenPtr)LT(1);\n", p->el_label);\r | |
2530 | /* MR10 */ };\r | |
2531 | /* MR10 */ } else {\r | |
2532 | /* MR10 */ gen1("%s = zzaCur;", p->el_label);\r | |
2533 | /* MR10 */ };\r | |
2534 | /* MR10 */ if (FoundGuessBlk) _gen(" /* MR10 */");\r | |
2535 | /* MR10 */ _gen("\n");\r | |
2536 | /* MR10 */ };\r | |
2537 | \r | |
2538 | /* Do Attrib / Token ptr */\r | |
2539 | \r | |
2540 | /* MR10 */ if (! p->label_used_in_semantic_pred) {\r | |
2541 | /* MR10 */\r | |
2542 | /* MR10 */ if ( FoundGuessBlk ) {\r | |
2543 | /* MR10 */ if (! done_NON_GUESSMODE) {\r | |
2544 | /* MR10 */ done_NON_GUESSMODE=1;\r | |
2545 | /* MR10 */ if ( GenCC ) {gen("if ( !guessing ) {\n"); tab();}\r | |
2546 | /* MR10 */ else {gen("zzNON_GUESS_MODE {\n"); tab();}\r | |
2547 | /* MR10 */ };\r | |
2548 | /* MR10 */ };\r | |
2549 | /* MR10 */\r | |
2550 | /* MR10 */ if ( GenCC ) {\r | |
2551 | /* MR10 */ if ( set_el(p->elnum, tokensRefdInBlock) || GenAST ) {\r | |
2552 | /* MR10 */ gen3("%s = _t%d%d;\n", p->el_label, BlkLevel-1, p->elnum);\r | |
2553 | /* MR10 */ } else {\r | |
2554 | /* MR10 */ gen1("%s = (ANTLRTokenPtr)LT(1);\n", p->el_label);\r | |
2555 | /* MR10 */ };\r | |
2556 | /* MR10 */ } else {\r | |
2557 | /* MR10 */ gen1("%s = zzaCur;\n", p->el_label);\r | |
2558 | /* MR10 */ };\r | |
2559 | /* MR10 */ };\r | |
2560 | \r | |
2561 | /* Do AST ptr */\r | |
2562 | \r | |
2563 | if (GenAST && (ast_label_in_action || !(p->astnode == ASTexclude || r->noAST) )) /* MR27 */\r | |
2564 | {\r | |
2565 | \r | |
2566 | /* MR10 */ if ( FoundGuessBlk ) {\r | |
2567 | /* MR10 */ if (! done_NON_GUESSMODE) {\r | |
2568 | /* MR10 */ done_NON_GUESSMODE=1;\r | |
2569 | /* MR10 */ if ( GenCC ) {gen("if ( !guessing ) {\n"); tab();}\r | |
2570 | /* MR10 */ else {gen("zzNON_GUESS_MODE {\n"); tab();}\r | |
2571 | /* MR10 */ };\r | |
2572 | /* MR10 */ };\r | |
2573 | \r | |
2574 | if ( GenCC ) {\r | |
2575 | gen3("%s_ast = _ast%d%d;\n", p->el_label, BlkLevel-1, p->elnum);\r | |
2576 | }\r | |
2577 | else {gen1("%s_ast = zzastCur;\n", p->el_label);}\r | |
2578 | }\r | |
2579 | \r | |
2580 | /* MR10 */ if (done_NON_GUESSMODE) {\r | |
2581 | /* MR10 */ gen("}\n"); tab();\r | |
2582 | /* MR10 */ };\r | |
2583 | \r | |
2584 | }\r | |
2585 | \r | |
2586 | /* Handle any actions immediately following action */\r | |
2587 | if ( a != NULL ) /* MR10 */ /* MR11 */\r | |
2588 | {\r | |
2589 | /* delay next token fetch until after action */\r | |
2590 | _gen("\n");\r | |
2591 | if ( a->is_predicate)\r | |
2592 | {\r | |
2593 | #if 0\r | |
2594 | /* Disabled in MR30 ************************************************************\r | |
2595 | And moved into genAction\r | |
2596 | *****************************************************************************\r | |
2597 | */\r | |
2598 | \r | |
2599 | gen("if (!(");\r | |
2600 | \r | |
2601 | /* make sure that '#line n' is on front of line */ /* MR14 */\r | |
2602 | if ( GenLineInfo && p->file != -1 ) _gen("\n"); /* MR14 */\r | |
2603 | dumpPredAction(a,a->action, output, 0, a->file, a->line, 0);\r | |
2604 | \r | |
2605 | /* MR23 Change failed predicate macro to have three arguments:\r | |
2606 | \r | |
2607 | macro arg 1: The stringized predicate itself\r | |
2608 | macro arg 2: 0 => no user-defined error action\r | |
2609 | 1 => user-defined error action\r | |
2610 | macro arg 3: The user-defined error action\r | |
2611 | \r | |
2612 | This gives the user more control of the error action.\r | |
2613 | */\r | |
2614 | _gen(")) \n");\r | |
2615 | tabs++;\r | |
2616 | gen3(" {zzfailed_pred(\"%s\",%s,{ %s } );}\n", /* MR23 */\r | |
2617 | stringize(a->action), /* MR23 */\r | |
2618 | (a->pred_fail == NULL ? /* MR23/MR27 */\r | |
2619 | "0 /* report */" : "1 /* user action */"), /* MR23/MR27 */\r | |
2620 | (a->pred_fail == NULL ? /* MR23 */\r | |
2621 | "; /* no user action */" : a->pred_fail)); /* MR23 */\r | |
2622 | tabs--;\r | |
2623 | /* Disabled in MR30 ************************************************************\r | |
2624 | And moved into genAction\r | |
2625 | *****************************************************************************\r | |
2626 | */\r | |
2627 | #endif\r | |
2628 | }\r | |
2629 | else /* MR9 a regular action - not a predicate action */\r | |
2630 | {\r | |
2631 | \r | |
2632 | /* MR23: Search an action which is not a predicate for LT(i),\r | |
2633 | LA(i), or LATEXT(i) in order to warn novice users that\r | |
2634 | it refers to the previous matched token, not the next\r | |
2635 | one. This is different than the case for semantic\r | |
2636 | predicates.\r | |
2637 | */\r | |
2638 | \r | |
2639 | /* MR23 */ if (GenCC) {\r | |
2640 | /* MR23 */ if (strstr(a->action, "LT(") != NULL) LTinTokenAction = 1;\r | |
2641 | /* MR23 */ }\r | |
2642 | /* MR23 */ else {\r | |
2643 | /* MR23 */ if (strstr(a->action, "LA(") != NULL) LTinTokenAction = 1; \r | |
2644 | /* MR23 */ if (strstr(a->action, "LATEXT(") != NULL) LTinTokenAction = 1;\r | |
2645 | /* MR23 */ }\r | |
2646 | \r | |
2647 | if ( FoundGuessBlk ) {\r | |
2648 | if ( GenCC ) {gen("if ( !guessing ) {\n");}\r | |
2649 | else gen("zzNON_GUESS_MODE {\n");\r | |
2650 | }\r | |
2651 | dumpActionPlus(a, a->action, output, tabs, a->file, a->line, 1); /* MR21 */\r | |
2652 | if ( FoundGuessBlk ) gen("}\n");\r | |
2653 | a->done = 1; /* MR30 */\r | |
2654 | }\r | |
2655 | /*** a->done = 1; MR30 Moved up into then branch for true actions, but not predicates ***/\r | |
2656 | if ( !DemandLookahead ) {\r | |
2657 | if ( GenCC ) {\r | |
2658 | if ( FoundException && p->use_def_MT_handler ) gen("if (!_signal)");\r | |
2659 | _gen(" consume();")\r | |
2660 | if ( FoundException && p->use_def_MT_handler )\r | |
2661 | _gen(" _signal=NoSignal;");\r | |
2662 | _gen("\n");\r | |
2663 | }\r | |
2664 | else\r | |
2665 | {\r | |
2666 | if ( FoundException && p->use_def_MT_handler ) _gen("if (!_signal)");\r | |
2667 | _gen(" zzCONSUME;\n");\r | |
2668 | if ( FoundException && p->use_def_MT_handler ) _gen(" _signal=NoSignal;");\r | |
2669 | _gen("\n");\r | |
2670 | }\r | |
2671 | }\r | |
2672 | else gen("\n");\r | |
2673 | if (a->done) { /* MR30 */\r | |
2674 | TRANS( a->next ); /* MR30 */\r | |
2675 | } /* MR30 */\r | |
2676 | else { /* MR30 */\r | |
2677 | TRANS( p->next ); /* MR30 */\r | |
2678 | } /* MR30 */\r | |
2679 | }\r | |
2680 | else\r | |
2681 | {\r | |
2682 | if ( !DemandLookahead ) {\r | |
2683 | if ( GenCC ) {\r | |
2684 | if (FoundException && p->use_def_MT_handler) _gen("if (!_signal)");\r | |
2685 | _gen(" consume();")\r | |
2686 | if (FoundException&&p->use_def_MT_handler) _gen(" _signal=NoSignal;");\r | |
2687 | _gen("\n");\r | |
2688 | }\r | |
2689 | else {\r | |
2690 | if (FoundException && p->use_def_MT_handler) _gen("if (!_signal)");\r | |
2691 | _gen(" zzCONSUME;");\r | |
2692 | if ( FoundException && p->use_def_MT_handler ) _gen(" _signal=NoSignal;");\r | |
2693 | _gen("\n");\r | |
2694 | }\r | |
2695 | }\r | |
2696 | else _gen("\n");\r | |
2697 | TRANS(p->next);\r | |
2698 | }\r | |
2699 | }\r | |
2700 | \r | |
2701 | /* MR21\r | |
2702 | *\r | |
2703 | * There was a bug in the code generation for {...} which causes it\r | |
2704 | * to omit the optional tokens from the error messages. The easiest\r | |
2705 | * way to fix this was to make the opt block look like a sub block:\r | |
2706 | *\r | |
2707 | * { a | b | c }\r | |
2708 | *\r | |
2709 | * becomes (internally):\r | |
2710 | *\r | |
2711 | * ( a | b | c | )\r | |
2712 | *\r | |
2713 | * The code for genOptBlk is now identical to genSubBlk except for\r | |
2714 | * cosmetic changes.\r | |
2715 | */\r | |
2716 | \r | |
2717 | void\r | |
2718 | #ifdef __USE_PROTOS\r | |
2719 | genOptBlk( Junction *q )\r | |
2720 | #else\r | |
2721 | genOptBlk( q )\r | |
2722 | Junction *q;\r | |
2723 | #endif\r | |
2724 | {\r | |
2725 | int max_k;\r | |
2726 | set f;\r | |
2727 | int need_right_curly;\r | |
2728 | set savetkref;\r | |
2729 | int lastAltEmpty; /* MR23 */\r | |
2730 | savetkref = tokensRefdInBlock;\r | |
2731 | require(q->ntype == nJunction, "genOptBlk: not junction");\r | |
2732 | require(q->jtype == aOptBlk, "genOptBlk: not opt block");\r | |
2733 | \r | |
2734 | OutLineInfo(output,q->line,FileStr[q->file]);\r | |
2735 | BLOCK_Preamble(q);\r | |
2736 | BlkLevel++;\r | |
2737 | BlockPreambleOption(q,q->pFirstSetSymbol); /* MR21 */\r | |
2738 | f = genBlk(q, aOptBlk, &max_k, &need_right_curly, &lastAltEmpty /* MR23 */);\r | |
2739 | /* MR23\r | |
2740 | Bypass error clause generation when exceptions are used in {...} block \r | |
2741 | See multi-line note in genBlk near call to isEmptyAlt.\r | |
2742 | */\r | |
2743 | if (! FoundException) {\r | |
2744 | if ( q->p2 != NULL ) {tab(); makeErrorClause(q,f,max_k,0 /* use plus block bypass ? */ );}\r | |
2745 | }\r | |
2746 | else {\r | |
2747 | gen("/* MR23 skip error clause for {...} when exceptions in use */\n");\r | |
2748 | }\r | |
2749 | { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }\r | |
2750 | freeBlkFsets(q);\r | |
2751 | --BlkLevel;\r | |
2752 | BLOCK_Tail();\r | |
2753 | \r | |
2754 | if ( q->guess )\r | |
2755 | {\r | |
2756 | gen("zzGUESS_DONE\n");\r | |
2757 | }\r | |
2758 | \r | |
2759 | /* must duplicate if (alpha)?; one guesses (validates), the\r | |
2760 | * second pass matches */\r | |
2761 | if ( q->guess && analysis_point(q)==q )\r | |
2762 | {\r | |
2763 | OutLineInfo(output,q->line,FileStr[q->file]);\r | |
2764 | BLOCK_Preamble(q);\r | |
2765 | BlkLevel++;\r | |
2766 | f = genBlk(q, aSubBlk, &max_k, &need_right_curly, &lastAltEmpty /* MR23 */);\r | |
2767 | if ( q->p2 != NULL ) {tab(); makeErrorClause(q,f,max_k,0 /* use plus block bypass ? */ );}\r | |
2768 | { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }\r | |
2769 | freeBlkFsets(q);\r | |
2770 | --BlkLevel;\r | |
2771 | BLOCK_Tail();\r | |
2772 | }\r | |
2773 | \r | |
2774 | tokensRefdInBlock = savetkref;\r | |
2775 | if (q->end->p1 != NULL) TRANS(q->end->p1);\r | |
2776 | }\r | |
2777 | \r | |
2778 | /*\r | |
2779 | * Generate code for a loop blk of form:\r | |
2780 | *\r | |
2781 | * |---|\r | |
2782 | * v |\r | |
2783 | * --o-G-o-->o--\r | |
2784 | */\r | |
2785 | void\r | |
2786 | #ifdef __USE_PROTOS\r | |
2787 | genLoopBlk( Junction *begin, Junction *q, Junction *start, int max_k )\r | |
2788 | #else\r | |
2789 | genLoopBlk( begin, q, start, max_k )\r | |
2790 | Junction *begin;\r | |
2791 | Junction *q;\r | |
2792 | Junction *start; /* where to start generating code from */\r | |
2793 | int max_k;\r | |
2794 | #endif\r | |
2795 | {\r | |
2796 | set f;\r | |
2797 | int need_right_curly;\r | |
2798 | set savetkref;\r | |
2799 | Junction *guessBlock; /* MR10 */\r | |
2800 | int singleAlt; /* MR10 */\r | |
2801 | int lastAltEmpty; /* MR23 */\r | |
2802 | \r | |
2803 | savetkref = tokensRefdInBlock;\r | |
2804 | require(q->ntype == nJunction, "genLoopBlk: not junction");\r | |
2805 | require(q->jtype == aLoopBlk, "genLoopBlk: not loop block");\r | |
2806 | \r | |
2807 | if ( q->visited ) return;\r | |
2808 | q->visited = TRUE;\r | |
2809 | \r | |
2810 | /* first_item_is_guess_block doesn't care what kind of node it is */\r | |
2811 | \r | |
2812 | guessBlock=first_item_is_guess_block( (Junction *) q->p1); /* MR10 */\r | |
2813 | singleAlt=q->p2==NULL; /* MR10 */\r | |
2814 | \r | |
2815 | if (singleAlt && !guessBlock) /* MR10 */ /* only one alternative? */\r | |
2816 | {\r | |
2817 | if ( DemandLookahead ) {\r | |
2818 | if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}\r | |
2819 | else gen1("look(%d);\n", max_k);\r | |
2820 | }\r | |
2821 | gen("while ( ");\r | |
2822 | if ( begin!=NULL ) genExpr(begin);\r | |
2823 | else genExpr(q);\r | |
2824 | /* if no predicates have been hoisted for this single alt (..)*\r | |
2825 | * do so now\r | |
2826 | */\r | |
2827 | require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");\r | |
2828 | if ( ParseWithPredicates && begin->predicate==NULL )\r | |
2829 | {\r | |
2830 | Predicate *a = MR_find_predicates_and_supp((Node *)q->p1);\r | |
2831 | require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");\r | |
2832 | \r | |
2833 | if ( a!=NULL )\r | |
2834 | {\r | |
2835 | _gen("&&");\r | |
2836 | a=genPredTreeMain(a, (Node *)q); /* MR10 */\r | |
2837 | }\r | |
2838 | /* MR10 */ if (MRhoisting) {\r | |
2839 | /* MR10 */ predicate_free(a);\r | |
2840 | /* MR10 */ };\r | |
2841 | }\r | |
2842 | _gen(" ) {\n");\r | |
2843 | tabs++;\r | |
2844 | TRANS(q->p1);\r | |
2845 | if ( !GenCC ) gen1("zzLOOP(zztasp%d);\n", BlkLevel-1);\r | |
2846 | if ( DemandLookahead ) {\r | |
2847 | if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}\r | |
2848 | else gen1("look(%d);\n", max_k);\r | |
2849 | }\r | |
2850 | --tabs;\r | |
2851 | gen("}\n");\r | |
2852 | freeBlkFsets(q);\r | |
2853 | q->visited = FALSE;\r | |
2854 | tokensRefdInBlock = savetkref;\r | |
2855 | return;\r | |
2856 | }\r | |
2857 | gen("for (;;) {\n"); /* MR20 G. Hobbelt */\r | |
2858 | tabs++;\r | |
2859 | /* MR6 */\r | |
2860 | /* MR6 "begin" can never be null when called from genLoopBegin */\r | |
2861 | /* MR6 because q==(Junction *)begin->p1 and we know q is valid */\r | |
2862 | /* MR6 */\r | |
2863 | /* MR6 from genLoopBegin: */\r | |
2864 | /* MR6 */\r | |
2865 | /* MR6 if ( LL_k>1 && !set_nil(q->fset[2]) ) */\r | |
2866 | /* MR6 genLoopBlk( q, (Junction *)q->p1, q, max_k ); */\r | |
2867 | /* MR6 else genLoopBlk( q, (Junction *)q->p1, NULL, max_k ); */\r | |
2868 | /* MR6 */\r | |
2869 | if ( begin!=NULL )\r | |
2870 | {\r | |
2871 | if ( DemandLookahead )\r | |
2872 | {\r | |
2873 | if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}\r | |
2874 | else gen1("look(%d);\n", max_k);\r | |
2875 | }\r | |
2876 | /* The bypass arc of the (...)* predicts what to do when you fail, but\r | |
2877 | * ONLY after having tested the loop start expression. To avoid this,\r | |
2878 | * we simply break out of the (...)* loop when we find something that\r | |
2879 | * is not in the prediction of the loop (all alts thereof).\r | |
2880 | */\r | |
2881 | gen("if ( !(");\r | |
2882 | \r | |
2883 | /*** TJP says: It used to use the prediction expression for the bypass arc\r | |
2884 | of the (...)*. HOWEVER, if a non LL^1(k) decision was found, this\r | |
2885 | thing would miss the ftree stored in the aLoopBegin node and generate\r | |
2886 | an LL^1(k) decision anyway.\r | |
2887 | \r | |
2888 | *** genExpr((Junction *)begin->p2);\r | |
2889 | ***/\r | |
2890 | \r | |
2891 | genExpr((Junction *)begin);\r | |
2892 | _gen(")) break;\n");\r | |
2893 | \r | |
2894 | }\r | |
2895 | \r | |
2896 | /* generate code for terminating loop (this is optional branch) */\r | |
2897 | \r | |
2898 | f = genBlk(q, aLoopBlk, &max_k, &need_right_curly, &lastAltEmpty /* MR23 */);\r | |
2899 | set_free(f);\r | |
2900 | freeBlkFsets(q);\r | |
2901 | \r | |
2902 | /* generate code for terminating loop (this is optional branch) */\r | |
2903 | \r | |
2904 | /* MR6 */\r | |
2905 | /* MR6 30-May-97 Bug reported by Manuel Ornato */\r | |
2906 | /* MR6 A definite bug involving the exit from a loop block */\r | |
2907 | /* MR6 In 1.23 and later versions (including 1.33) Instead */\r | |
2908 | /* MR6 exiting the block and reporting a syntax error the */\r | |
2909 | /* MR6 code loops forever. */\r | |
2910 | /* MR6 Looking at 1.20 which generates proper code it is not */\r | |
2911 | /* MR6 clear which of two changes should be undone. */\r | |
2912 | /* MR6 This is my best guess. */\r | |
2913 | /* MR6 From earlier MR6 note we know that begin can never be */\r | |
2914 | /* MR6 null when genLoopBlk called from genLoopBegin */\r | |
2915 | /* MR6 */\r | |
2916 | /* MR6 */ if ( begin==NULL) {\r | |
2917 | /* MR6 */ /* code for exiting loop "for sure" */\r | |
2918 | /* MR6 */ gen("/* Suppressed by MR6 */ /*** else break; ***/\n");\r | |
2919 | /* MR6 */ };\r | |
2920 | \r | |
2921 | /* MR10 */if (singleAlt && guessBlock) {\r | |
2922 | /* MR10 */ tabs--;\r | |
2923 | /* MR6 */ gen("} else break; /* MR6 code for exiting loop \"for sure\" */\n");\r | |
2924 | /* MR10 */ need_right_curly--;\r | |
2925 | /* MR10 */ } else {\r | |
2926 | /* MR6 */ gen("else break; /* MR6 code for exiting loop \"for sure\" */\n");\r | |
2927 | /* MR10 */ };\r | |
2928 | \r | |
2929 | { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }\r | |
2930 | if ( !GenCC ) gen1("zzLOOP(zztasp%d);\n", BlkLevel-1);\r | |
2931 | --tabs;\r | |
2932 | gen("}\n");\r | |
2933 | q->visited = FALSE;\r | |
2934 | tokensRefdInBlock = savetkref;\r | |
2935 | }\r | |
2936 | \r | |
2937 | /*\r | |
2938 | * Generate code for a loop blk of form:\r | |
2939 | *\r | |
2940 | * |---|\r | |
2941 | * v |\r | |
2942 | * --o-->o-->o-G-o-->o--\r | |
2943 | * | ^\r | |
2944 | * v |\r | |
2945 | * o-----------o\r | |
2946 | *\r | |
2947 | * q->end points to the last node (far right) in the blk.\r | |
2948 | *\r | |
2949 | * Note that q->end->jtype must be 'EndBlk'.\r | |
2950 | *\r | |
2951 | * Generate code roughly of the following form:\r | |
2952 | *\r | |
2953 | * do {\r | |
2954 | * ... code for alternatives ...\r | |
2955 | * } while ( First Set of aLoopBlk );\r | |
2956 | *\r | |
2957 | * OR if > 1 alternative\r | |
2958 | *\r | |
2959 | * do {\r | |
2960 | * ... code for alternatives ...\r | |
2961 | * else break;\r | |
2962 | * } while ( 1 );\r | |
2963 | */\r | |
2964 | void\r | |
2965 | #ifdef __USE_PROTOS\r | |
2966 | genLoopBegin( Junction *q )\r | |
2967 | #else\r | |
2968 | genLoopBegin( q )\r | |
2969 | Junction *q;\r | |
2970 | #endif\r | |
2971 | {\r | |
2972 | set f;\r | |
2973 | int i;\r | |
2974 | int max_k;\r | |
2975 | set savetkref;\r | |
2976 | savetkref = tokensRefdInBlock;\r | |
2977 | require(q!=NULL, "genLoopBegin: invalid node and/or rule");\r | |
2978 | require(q->ntype == nJunction, "genLoopBegin: not junction");\r | |
2979 | require(q->jtype == aLoopBegin, "genLoopBegin: not loop block");\r | |
2980 | require(q->p2!=NULL, "genLoopBegin: invalid Loop Graph");\r | |
2981 | \r | |
2982 | OutLineInfo(output,q->line,FileStr[q->file]);\r | |
2983 | \r | |
2984 | BLOCK_Preamble(q);\r | |
2985 | BlkLevel++;\r | |
2986 | BlockPreambleOption(q,q->pFirstSetSymbol); /* MR21 */\r | |
2987 | f = First(q, 1, aLoopBegin, &max_k);\r | |
2988 | /* If not simple LL(1), must specify to start at LoopBegin, not LoopBlk */\r | |
2989 | if ( LL_k>1 && !set_nil(q->fset[2]) )\r | |
2990 | genLoopBlk( q, (Junction *)q->p1, q, max_k );\r | |
2991 | else genLoopBlk( q, (Junction *)q->p1, NULL, max_k );\r | |
2992 | \r | |
2993 | for (i=1; i<=CLL_k; i++) set_free(q->fset[i]);\r | |
2994 | for (i=1; i<=CLL_k; i++) set_free(((Junction *)q->p2)->fset[i]);\r | |
2995 | --BlkLevel;\r | |
2996 | BLOCK_Tail();\r | |
2997 | set_free(f);\r | |
2998 | tokensRefdInBlock = savetkref;\r | |
2999 | /* MR21 */ if (MR_BlkErr) {\r | |
3000 | /* MR21 */ set f, fArray[2];\r | |
3001 | /* MR21 */ f = ComputeErrorSet(q,1,0 /* use plus block bypass ? */ );\r | |
3002 | /* MR21 */ fArray[0]= empty;\r | |
3003 | /* MR21 */ fArray[1]= set_dup(f);\r | |
3004 | /* MR21 */ gen("if (");\r | |
3005 | /* MR21 */ genExprSets(fArray,1); /* note: destroys set arguments */\r | |
3006 | /* MR21 */ _gen(") { /* MR21 option -mrblksynerr */\n");\r | |
3007 | /* MR21 */ tabs++;\r | |
3008 | /* MR21 */ tab();\r | |
3009 | /* MR21 */ _gen("/* nothing */ }\n");\r | |
3010 | /* MR21 */ tab();\r | |
3011 | /* MR21 */ makeErrorClause(q,f,1,0 /* use plus block bypass ? */ ); /* frees set */\r | |
3012 | /* MR21 */ tabs--;\r | |
3013 | /* MR21 */ };\r | |
3014 | if (q->end->p1 != NULL) TRANS(q->end->p1);\r | |
3015 | }\r | |
3016 | \r | |
3017 | /*\r | |
3018 | * Generate code for a loop blk of form:\r | |
3019 | *\r | |
3020 | * |---|\r | |
3021 | * v |\r | |
3022 | * --o-G-o-->o--\r | |
3023 | *\r | |
3024 | * q->end points to the last node (far right) in the blk.\r | |
3025 | * Note that q->end->jtype must be 'EndBlk'.\r | |
3026 | *\r | |
3027 | * Generate code roughly of the following form:\r | |
3028 | *\r | |
3029 | * do {\r | |
3030 | * ... code for alternatives ...\r | |
3031 | * } while ( First Set of aPlusBlk );\r | |
3032 | *\r | |
3033 | * OR if > 1 alternative\r | |
3034 | *\r | |
3035 | * do {\r | |
3036 | * ... code for alternatives ...\r | |
3037 | * else if not 1st time through, break;\r | |
3038 | * } while ( 1 );\r | |
3039 | */\r | |
3040 | void\r | |
3041 | #ifdef __USE_PROTOS\r | |
3042 | genPlusBlk( Junction *q )\r | |
3043 | #else\r | |
3044 | genPlusBlk( q )\r | |
3045 | Junction *q;\r | |
3046 | #endif\r | |
3047 | {\r | |
3048 | int max_k;\r | |
3049 | set f;\r | |
3050 | int need_right_curly;\r | |
3051 | int lastAltEmpty; /* MR23 */\r | |
3052 | set savetkref;\r | |
3053 | Junction *guessBlock; /* MR10 */\r | |
3054 | int singleAlt; /* MR10 */\r | |
3055 | \r | |
3056 | savetkref = tokensRefdInBlock;\r | |
3057 | require(q!=NULL, "genPlusBlk: invalid node and/or rule");\r | |
3058 | require(q->ntype == nJunction, "genPlusBlk: not junction");\r | |
3059 | require(q->jtype == aPlusBlk, "genPlusBlk: not Plus block");\r | |
3060 | require(q->p2 != NULL, "genPlusBlk: not a valid Plus block");\r | |
3061 | \r | |
3062 | if ( q->visited ) return;\r | |
3063 | q->visited = TRUE;\r | |
3064 | OutLineInfo(output,q->line,FileStr[q->file]);\r | |
3065 | BLOCK_Preamble(q);\r | |
3066 | BlkLevel++;\r | |
3067 | \r | |
3068 | BlockPreambleOption((Junction *)q, q->pFirstSetSymbol); /* MR21 */\r | |
3069 | \r | |
3070 | /* first_item_is_guess_block doesn't care what kind of node it is */\r | |
3071 | \r | |
3072 | guessBlock=first_item_is_guess_block( (Junction *)q->p1); /* MR10 */\r | |
3073 | \r | |
3074 | /* if the ignore flag is set on the 2nd alt and that alt is empty,\r | |
3075 | * then it is the implied optional alternative that we added for (...)+\r | |
3076 | * and, hence, only 1 alt.\r | |
3077 | */\r | |
3078 | \r | |
3079 | /* MR10 Reported by Pulkkinen Esa (esap@cs.tut.fi)\r | |
3080 | * Outer code for guess blocks ignored when there is only one alt\r | |
3081 | * for a (...)+ block.\r | |
3082 | * Force use of regular code rather than "optimized" code for that case\r | |
3083 | */\r | |
3084 | \r | |
3085 | singleAlt=( ( (Junction *) q->p2)->p2 == NULL) &&\r | |
3086 | ( ( (Junction *) q->p2)->ignore ); /* only one alternative? */\r | |
3087 | \r | |
3088 | if (singleAlt && !guessBlock) /* MR10 */\r | |
3089 | {\r | |
3090 | \r | |
3091 | Predicate *a=NULL;\r | |
3092 | /* if the only alt has a semantic predicate, hoist it; must test before\r | |
3093 | * entering loop.\r | |
3094 | */\r | |
3095 | if ( ParseWithPredicates )\r | |
3096 | {\r | |
3097 | require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");\r | |
3098 | a = MR_find_predicates_and_supp((Node *)q);\r | |
3099 | require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");\r | |
3100 | \r | |
3101 | if ( a!=NULL ) {\r | |
3102 | gen("if (");\r | |
3103 | a=genPredTreeMain(a, (Node *)q); /* MR10 */\r | |
3104 | _gen(") {\n");\r | |
3105 | }\r | |
3106 | }\r | |
3107 | gen("do {\n");\r | |
3108 | tabs++;\r | |
3109 | TRANS(q->p1);\r | |
3110 | if ( !GenCC ) gen1("zzLOOP(zztasp%d);\n", BlkLevel-1);\r | |
3111 | f = First(q, 1, aPlusBlk, &max_k);\r | |
3112 | if ( DemandLookahead ) {\r | |
3113 | if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}\r | |
3114 | else gen1("look(%d);\n", max_k);\r | |
3115 | }\r | |
3116 | --tabs;\r | |
3117 | gen("} while ( ");\r | |
3118 | if ( q->parm!=NULL && q->predparm ) _gen1("(%s) && ", q->parm);\r | |
3119 | genExpr(q);\r | |
3120 | if ( ParseWithPredicates && a!=NULL )\r | |
3121 | {\r | |
3122 | if (! MR_comparePredicates(q->predicate,a)) {\r | |
3123 | _gen("&&");\r | |
3124 | a=genPredTreeMain(a, (Node *)q); /* MR10 */\r | |
3125 | };\r | |
3126 | }\r | |
3127 | _gen(" );\n");\r | |
3128 | if ( ParseWithPredicates && a!=NULL ) gen("}\n");\r | |
3129 | --BlkLevel;\r | |
3130 | BLOCK_Tail();\r | |
3131 | q->visited = FALSE;\r | |
3132 | freeBlkFsets(q);\r | |
3133 | set_free(f);\r | |
3134 | tokensRefdInBlock = savetkref;\r | |
3135 | /* MR21 */ if (MR_BlkErr) {\r | |
3136 | /* MR21 */ set f, fArray[2];\r | |
3137 | /* MR21 */ f = ComputeErrorSet(q,1,1 /* use plus block bypass ? */ );\r | |
3138 | /* MR21 */ fArray[0]= empty;\r | |
3139 | /* MR21 */ fArray[1]= set_dup(f);\r | |
3140 | /* MR21 */ gen("if (");\r | |
3141 | /* MR21 */ genExprSets(fArray,1); /* note: destroys set arguments */\r | |
3142 | /* MR21 */ _gen(") { /* MR21 option -mrblksynerr */\n");\r | |
3143 | /* MR21 */ tabs++;\r | |
3144 | /* MR21 */ tab();\r | |
3145 | /* MR21 */ _gen("/* nothing */ }\n");\r | |
3146 | /* MR21 */ tab();\r | |
3147 | /* MR21 */ makeErrorClause(q,f,1,1 /* use plus block bypass ? */ ); /* frees set */\r | |
3148 | /* MR21 */ tabs--;\r | |
3149 | /* MR21 */ };\r | |
3150 | if (q->end->p1 != NULL) TRANS(q->end->p1);\r | |
3151 | /* MR10 */ if (MRhoisting) {\r | |
3152 | /* MR10 */ predicate_free(a);\r | |
3153 | /* MR10 */ };\r | |
3154 | return;\r | |
3155 | }\r | |
3156 | gen("do {\n");\r | |
3157 | tabs++;\r | |
3158 | f = genBlk(q, aPlusBlk, &max_k, &need_right_curly, &lastAltEmpty /* MR23 */);\r | |
3159 | /* MR6 */\r | |
3160 | /* MR6 Sinan Karasu (sinan@tardis.ds.boeing.com) */\r | |
3161 | /* MR6 Failed to turn off guess mode when leaving block */\r | |
3162 | /* MR6 */\r | |
3163 | /* MR6 */ if ( has_guess_block_as_last_item(q) ) {\r | |
3164 | /* MR10 */ gen("/* MR10 ()+ */ else {\n");\r | |
3165 | /* MR10 */ tabs++;\r | |
3166 | /* MR10 */ need_right_curly++;\r | |
3167 | /* MR10 */ gen("/* MR10 ()+ */ if ( !zzrv ) zzGUESS_DONE;\n");\r | |
3168 | /* MR6 */ gen("/* MR10 ()+ */ if ( zzcnt > 1 ) break;\n");\r | |
3169 | /* MR10 */ } else {\r | |
3170 | /* MR10 */ gen("/* MR10 ()+ */ else {\n");\r | |
3171 | /* MR10 */ tabs++;\r | |
3172 | /* MR10 */ need_right_curly++;\r | |
3173 | /* MR10 */ gen("if ( zzcnt > 1 ) break;\n");\r | |
3174 | /* MR10 */ };\r | |
3175 | \r | |
3176 | /* MR21 */ if (MR_BlkErr && 1 >= max_k) {\r | |
3177 | /* MR21 */ set f;\r | |
3178 | /* MR21 */ f = ComputeErrorSet(q,1,0 /* use plus block bypass ? */ );\r | |
3179 | /* MR21 */ tabs++;\r | |
3180 | /* MR21 */ tab();\r | |
3181 | /* MR21 */ makeErrorClause(q,f,1,0 /* use plus block bypass ? */ ); /* frees set */\r | |
3182 | /* MR21 */ tabs--;\r | |
3183 | /* MR21 */ }\r | |
3184 | /* MR21 */ else {\r | |
3185 | tab();\r | |
3186 | makeErrorClause(q,f,max_k,1 /* use plus block bypass ? */);\r | |
3187 | /* MR21 I think this generates the wrong set ? */\r | |
3188 | /* MR21 because it includes the plus block bypass ? */\r | |
3189 | /* MR21 but I'm afraid to change it without additional checking */\r | |
3190 | }\r | |
3191 | \r | |
3192 | { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }\r | |
3193 | freeBlkFsets(q);\r | |
3194 | gen("zzcnt++;");\r | |
3195 | if ( !GenCC ) _gen1(" zzLOOP(zztasp%d);", BlkLevel-1);\r | |
3196 | _gen("\n");\r | |
3197 | if ( DemandLookahead ) {\r | |
3198 | if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}\r | |
3199 | else gen1("look(%d);\n", max_k);\r | |
3200 | }\r | |
3201 | --tabs;\r | |
3202 | if ( q->parm!=NULL && q->predparm ) {gen1("} while (%s);\n", q->parm);}\r | |
3203 | else gen("} while ( 1 );\n");\r | |
3204 | --BlkLevel;\r | |
3205 | BLOCK_Tail();\r | |
3206 | q->visited = FALSE;\r | |
3207 | tokensRefdInBlock = savetkref;\r | |
3208 | /* MR21 */ if (MR_BlkErr) {\r | |
3209 | /* MR21 */ set f, fArray[2];\r | |
3210 | /* MR21 */ f = ComputeErrorSet(q,1,1 /* use plus block bypass ? */ );\r | |
3211 | /* MR21 */ fArray[0]= empty;\r | |
3212 | /* MR21 */ fArray[1]= set_dup(f);\r | |
3213 | /* MR21 */ gen("if (");\r | |
3214 | /* MR21 */ genExprSets(fArray,1); /* note: destroys set arguments */\r | |
3215 | /* MR21 */ _gen(") { /* MR21 option -mrblksynerr */\n");\r | |
3216 | /* MR21 */ tabs++;\r | |
3217 | /* MR21 */ tab();\r | |
3218 | /* MR21 */ _gen("/* nothing */ }\n");\r | |
3219 | /* MR21 */ tab();\r | |
3220 | /* MR21 */ makeErrorClause(q,f,1,1 /* use plus block bypass ? */ ); /* frees set */\r | |
3221 | /* MR21 */ tabs--;\r | |
3222 | /* MR21 */ };\r | |
3223 | if (q->end->p1 != NULL) TRANS(q->end->p1);\r | |
3224 | }\r | |
3225 | \r | |
3226 | /*\r | |
3227 | * Generate code for a sub blk of alternatives of form:\r | |
3228 | *\r | |
3229 | * --o-G1--o--\r | |
3230 | * | ^\r | |
3231 | * v /|\r | |
3232 | * o-G2-o|\r | |
3233 | * | ^\r | |
3234 | * v |\r | |
3235 | * ..........\r | |
3236 | * | ^\r | |
3237 | * v /\r | |
3238 | * o-Gn-o\r | |
3239 | *\r | |
3240 | * q points to the 1st junction of blk (upper-left).\r | |
3241 | * q->end points to the last node (far right) in the blk.\r | |
3242 | * Note that q->end->jtype must be 'EndBlk'.\r | |
3243 | * The last node in every alt points to q->end.\r | |
3244 | *\r | |
3245 | * Generate code of the following form:\r | |
3246 | * if ( First(G1) ) {\r | |
3247 | * ...code for G1...\r | |
3248 | * }\r | |
3249 | * else if ( First(G2) ) {\r | |
3250 | * ...code for G2...\r | |
3251 | * }\r | |
3252 | * ...\r | |
3253 | * else {\r | |
3254 | * ...code for Gn...\r | |
3255 | * }\r | |
3256 | */\r | |
3257 | \r | |
3258 | void\r | |
3259 | #ifdef __USE_PROTOS\r | |
3260 | genSubBlk( Junction *q )\r | |
3261 | #else\r | |
3262 | genSubBlk( q )\r | |
3263 | Junction *q;\r | |
3264 | #endif\r | |
3265 | {\r | |
3266 | int max_k;\r | |
3267 | set f;\r | |
3268 | int need_right_curly;\r | |
3269 | int lastAltEmpty; /* MR23 */\r | |
3270 | set savetkref;\r | |
3271 | savetkref = tokensRefdInBlock;\r | |
3272 | require(q->ntype == nJunction, "genSubBlk: not junction");\r | |
3273 | require(q->jtype == aSubBlk, "genSubBlk: not subblock");\r | |
3274 | \r | |
3275 | OutLineInfo(output,q->line,FileStr[q->file]);\r | |
3276 | BLOCK_Preamble(q);\r | |
3277 | BlkLevel++;\r | |
3278 | BlockPreambleOption(q,q->pFirstSetSymbol); /* MR21 */\r | |
3279 | f = genBlk(q, aSubBlk, &max_k, &need_right_curly, &lastAltEmpty /* MR23 */);\r | |
3280 | \r | |
3281 | /* MR23\r | |
3282 | Bypass error clause generation when exceptions are used in a sub block\r | |
3283 | in which the last alternative is epsilon. Example: "(A | B | )". \r | |
3284 | See multi-line note in genBlk near call to isEmptyAlt.\r | |
3285 | */\r | |
3286 | if (FoundException && lastAltEmpty) {\r | |
3287 | gen("/* MR23 skip error clause for (...| epsilon) when exceptions in use */\n");\r | |
3288 | }\r | |
3289 | else {\r | |
3290 | if ( q->p2 != NULL ) {tab(); makeErrorClause(q,f,max_k,0 /* use plus block bypass ? */ );}\r | |
3291 | }\r | |
3292 | \r | |
3293 | { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }\r | |
3294 | freeBlkFsets(q);\r | |
3295 | --BlkLevel;\r | |
3296 | BLOCK_Tail();\r | |
3297 | \r | |
3298 | if ( q->guess )\r | |
3299 | {\r | |
3300 | gen("zzGUESS_DONE\n");\r | |
3301 | }\r | |
3302 | \r | |
3303 | /* must duplicate if (alpha)?; one guesses (validates), the\r | |
3304 | * second pass matches */\r | |
3305 | if ( q->guess && analysis_point(q)==q )\r | |
3306 | {\r | |
3307 | OutLineInfo(output,q->line,FileStr[q->file]);\r | |
3308 | BLOCK_Preamble(q);\r | |
3309 | BlkLevel++;\r | |
3310 | f = genBlk(q, aSubBlk, &max_k, &need_right_curly, &lastAltEmpty /* MR23 */);\r | |
3311 | if ( q->p2 != NULL ) {tab(); makeErrorClause(q,f,max_k,0 /* use plus block bypass ? */);}\r | |
3312 | { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }\r | |
3313 | freeBlkFsets(q);\r | |
3314 | --BlkLevel;\r | |
3315 | BLOCK_Tail();\r | |
3316 | }\r | |
3317 | \r | |
3318 | tokensRefdInBlock = savetkref;\r | |
3319 | if (q->end->p1 != NULL) TRANS(q->end->p1);\r | |
3320 | }\r | |
3321 | \r | |
3322 | static int TnodesAllocatedPrevRule=0;\r | |
3323 | \r | |
3324 | /*\r | |
3325 | * Generate code for a rule.\r | |
3326 | *\r | |
3327 | * rule--> o-->o-Alternatives-o-->o\r | |
3328 | * Or,\r | |
3329 | * rule--> o-->o-Alternative-o-->o\r | |
3330 | *\r | |
3331 | * The 1st junction is a RuleBlk. The second can be a SubBlk or just a junction\r | |
3332 | * (one alternative--no block), the last is EndRule.\r | |
3333 | * The second to last is EndBlk if more than one alternative exists in the rule.\r | |
3334 | *\r | |
3335 | * To get to the init-action for a rule, we must bypass the RuleBlk,\r | |
3336 | * and possible SubBlk.\r | |
3337 | * Mark any init-action as generated so genBlk() does not regenerate it.\r | |
3338 | */\r | |
3339 | void\r | |
3340 | #ifdef __USE_PROTOS\r | |
3341 | genRule( Junction *q )\r | |
3342 | #else\r | |
3343 | genRule( q )\r | |
3344 | Junction *q;\r | |
3345 | #endif\r | |
3346 | {\r | |
3347 | \r | |
3348 | const char * returnValueInitializer;\r | |
3349 | \r | |
3350 | do { /* MR10 Change recursion into iteration */\r | |
3351 | \r | |
3352 | int max_k;\r | |
3353 | set follow, rk, f;\r | |
3354 | ActionNode *a;\r | |
3355 | RuleEntry *r;\r | |
3356 | int lastAltEmpty; /* MR23 */\r | |
3357 | static int file = -1;\r | |
3358 | int need_right_curly;\r | |
3359 | require(q->ntype == nJunction, "genRule: not junction");\r | |
3360 | require(q->jtype == RuleBlk, "genRule: not rule");\r | |
3361 | \r | |
3362 | /* MR14 */ require (MR_BackTraceStack.count == 0,"-alpha MR_BackTraceStack.count != 0");\r | |
3363 | /* MR14 */ MR_pointerStackReset(&MR_BackTraceStack);\r | |
3364 | /* MR14 */ if (AlphaBetaTrace) MR_MaintainBackTrace=1;\r | |
3365 | \r | |
3366 | CurRule=q->rname; /* MR11 */\r | |
3367 | \r | |
3368 | r = (RuleEntry *) hash_get(Rname, q->rname);\r | |
3369 | if ( r == NULL ) warnNoFL("Rule hash table is screwed up beyond belief");\r | |
3370 | if ( q->file != file ) /* open new output file if need to */\r | |
3371 | {\r | |
3372 | /* MR6 */\r | |
3373 | /* MR6 Simpler to debug when output goes to stdout rather than a file */\r | |
3374 | /* MR6 */\r | |
3375 | /* MR6 */ if (UseStdout) {\r | |
3376 | /* MR6 */ output = stdout;\r | |
3377 | /* MR6 */ } else {\r | |
3378 | /* MR6 */ if ( output != NULL) fclose( output );\r | |
3379 | /* MR6 */ output = fopen(OutMetaName(outname(FileStr[q->file])), "w");\r | |
3380 | /* MR6 */ };\r | |
3381 | require(output != NULL, "genRule: can't open output file");\r | |
3382 | \r | |
3383 | #ifdef SPECIAL_FOPEN\r | |
3384 | special_fopen_actions(OutMetaName(outname(FileStr[q->file]))); /* MR1 */\r | |
3385 | #endif\r | |
3386 | if ( file == -1 ) genHdr1(q->file);\r | |
3387 | else genHdr(q->file);\r | |
3388 | file = q->file;\r | |
3389 | }\r | |
3390 | \r | |
3391 | if (InfoM) {\r | |
3392 | fprintf(stderr," rule %s\n",q->rname);\r | |
3393 | fflush(output);\r | |
3394 | };\r | |
3395 | \r | |
3396 | #if 0\r | |
3397 | if (strcmp(q->rname,"***debug***") == 0) {\r | |
3398 | fprintf(stderr,"***debug*** %s reached\n",q->rname);\r | |
3399 | MR_break();\r | |
3400 | };\r | |
3401 | #endif\r | |
3402 | \r | |
3403 | DumpFuncHeader(q,r);\r | |
3404 | tabs++;\r | |
3405 | \r | |
3406 | /* MR23 \r | |
3407 | \r | |
3408 | If there is a single return value then it can be initialized in \r | |
3409 | the declaration using assignment syntax. If there are multiple\r | |
3410 | return values then antlr creates a struct and initialization takes\r | |
3411 | place element by element for each element of the struct. For\r | |
3412 | multiple elements the initialization is by assignment so we have\r | |
3413 | to wait until all declarations are done before emitting that code -\r | |
3414 | because of restrictions in C which don't exist in C++.\r | |
3415 | \r | |
3416 | In the past (before MR23) the only kind of initialization was\r | |
3417 | the PURIFY macro which was just a memset() of 0. Now we allow\r | |
3418 | the user to specify an initial value. PURIFY is still used in C\r | |
3419 | mode because C does not have constructors. However, PURIFY is\r | |
3420 | not used in C++ mode because it might overwrite information created\r | |
3421 | by elements which have their own ctor.\r | |
3422 | \r | |
3423 | */\r | |
3424 | \r | |
3425 | if ( q->ret!=NULL )\r | |
3426 | {\r | |
3427 | if ( hasMultipleOperands(q->ret) ) /* MR23 */\r | |
3428 | {\r | |
3429 | \r | |
3430 | /* Emit initialization code later. */\r | |
3431 | \r | |
3432 | gen1("struct _rv%d _retv;\n",r->rulenum);\r | |
3433 | }\r | |
3434 | else\r | |
3435 | {\r | |
3436 | /* Emit initialization code now. */\r | |
3437 | \r | |
3438 | tab();\r | |
3439 | DumpType(q->ret, output);\r | |
3440 | returnValueInitializer = getInitializer(q->ret);\r | |
3441 | if (returnValueInitializer == NULL) { /* MR23 */\r | |
3442 | gen(" _retv;\n"); /* MR1 MR3 */\r | |
3443 | } /* MR23 */\r | |
3444 | else { /* MR23 */\r | |
3445 | gen1(" _retv = %s;\n", returnValueInitializer); /* MR23 */\r | |
3446 | } /* MR23 */\r | |
3447 | }\r | |
3448 | }\r | |
3449 | \r | |
3450 | OutLineInfo(output,q->line,FileStr[q->file]);\r | |
3451 | \r | |
3452 | if (InfoM) {\r | |
3453 | fflush(output);\r | |
3454 | };\r | |
3455 | \r | |
3456 | gen("zzRULE;\n");\r | |
3457 | if ( FoundException )\r | |
3458 | {\r | |
3459 | gen("int _sva=1;\n");\r | |
3460 | }\r | |
3461 | if ( GenCC && GenAST )\r | |
3462 | gen("ASTBase *_ast = NULL, *_sibling = NULL, *_tail = NULL;\n");\r | |
3463 | if ( GenCC ) genTokenPointers(q);\r | |
3464 | if ( GenCC&&GenAST ) genASTPointers(q);\r | |
3465 | if ( q->el_labels!=NULL ) genElementLabels(q->el_labels);\r | |
3466 | if ( FoundException ) gen("int _signal=NoSignal;\n");\r | |
3467 | \r | |
3468 | if ( !GenCC ) gen1("zzBLOCK(zztasp%d);\n", BlkLevel);\r | |
3469 | \r | |
3470 | /* MR10 */ /* move zzTRACEIN to before init action */\r | |
3471 | \r | |
3472 | /* MR10 */ if ( TraceGen ) {\r | |
3473 | /* MR10 */ if ( GenCC ) {gen1("zzTRACEIN(\"%s\");\n", q->rname);}\r | |
3474 | /* MR10 */ else gen1("zzTRACEIN((ANTLRChar *)\"%s\");\n", q->rname);\r | |
3475 | /* MR10 */ }\r | |
3476 | \r | |
3477 | /* MR7 Moved PURIFY() to after all local variables have been declared */\r | |
3478 | /* MR7 so that the generated code is valid C as well as C++ */\r | |
3479 | /* MR7 Jan Mikkelsen 10-June-1997 */\r | |
3480 | \r | |
3481 | \r | |
3482 | /*\r | |
3483 | MR23 Do the PURIFY macro only for C mode.\r | |
3484 | C++ users should use constructors or initialization expressions.\r | |
3485 | */\r | |
3486 | \r | |
3487 | if ( q->ret != NULL ) /* MR7 */\r | |
3488 | { /* MR7 */\r | |
3489 | if (hasMultipleOperands(q->ret)) { /* MR23 */\r | |
3490 | if (PURIFY == TRUE) {\r | |
3491 | gen1("PCCTS_PURIFY(_retv,sizeof(struct _rv%d))\n",r->rulenum); /* MR23 */\r | |
3492 | }\r | |
3493 | } /* MR7 */\r | |
3494 | else { /* MR7 */\r | |
3495 | \r | |
3496 | /* MR23\r | |
3497 | If there were only one return value operand and\r | |
3498 | it had an initializer then it would have been\r | |
3499 | initialized in the declaration.\r | |
3500 | */\r | |
3501 | \r | |
3502 | returnValueInitializer = getInitializer(q->ret); /* MR23 */\r | |
3503 | if (returnValueInitializer == NULL) { /* MR23 */\r | |
3504 | if (PURIFY == TRUE) {\r | |
3505 | gen("PCCTS_PURIFY(_retv,sizeof("); /* MR23 */\r | |
3506 | DumpType(q->ret, output); /* MR7 */\r | |
3507 | gen("))\n"); /* MR7 */\r | |
3508 | }\r | |
3509 | } /* MR23 */\r | |
3510 | } /* MR7 */\r | |
3511 | \r | |
3512 | if (hasMultipleOperands(q->ret)) { /* MR23 */\r | |
3513 | DumpInitializers(output, r, q->ret); /* MR23 */\r | |
3514 | }\r | |
3515 | \r | |
3516 | }\r | |
3517 | if ( !GenCC ) gen("zzMake0;\n");\r | |
3518 | if ( FoundException ) gen("*_retsignal = NoSignal;\n");\r | |
3519 | \r | |
3520 | if ( !GenCC ) gen("{\n");\r | |
3521 | \r | |
3522 | if ( has_guess_block_as_first_item((Junction *)q->p1) )\r | |
3523 | {\r | |
3524 | gen("zzGUESS_BLOCK\n");\r | |
3525 | }\r | |
3526 | \r | |
3527 | /* L o o k F o r I n i t A c t i o n */\r | |
3528 | if ( ((Junction *)q->p1)->jtype == aSubBlk )\r | |
3529 | a = findImmedAction( ((Junction *)q->p1)->p1 );\r | |
3530 | else\r | |
3531 | a = findImmedAction( q->p1 ); /* only one alternative in rule */\r | |
3532 | if ( a!=NULL && !a->is_predicate)\r | |
3533 | {\r | |
3534 | /* MR21 */ if (!a->noHoist) dumpActionPlus(a, a->action, output, tabs, a->file, a->line, 1);\r | |
3535 | a->done = 1; /* ignore action. We have already handled it */\r | |
3536 | }\r | |
3537 | \r | |
3538 | BlkLevel++;\r | |
3539 | q->visited = TRUE; /* mark RULE as visited for FIRST/FOLLOW */\r | |
3540 | BlockPreambleOption((Junction *)q->p1, NULL); /* MR21 */\r | |
3541 | f = genBlk((Junction *)q->p1, RuleBlk, &max_k, &need_right_curly, &lastAltEmpty /* MR23 */);\r | |
3542 | if ( q->p1 != NULL )\r | |
3543 | if ( ((Junction *)q->p1)->p2 != NULL )\r | |
3544 | {tab(); makeErrorClause((Junction *)q->p1,f,max_k,0 /* use plus block bypass ? */);}\r | |
3545 | { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }\r | |
3546 | freeBlkFsets((Junction *)q->p1);\r | |
3547 | q->visited = FALSE;\r | |
3548 | --BlkLevel;\r | |
3549 | if ( !GenCC ) gen1("zzEXIT(zztasp%d);\n", BlkLevel);\r | |
3550 | \r | |
3551 | genTraceOut(q);\r | |
3552 | \r | |
3553 | if ( q->ret!=NULL ) gen("return _retv;\n") else gen("return;\n");\r | |
3554 | /* E r r o r R e c o v e r y */\r | |
3555 | NewSet();\r | |
3556 | rk = empty;\r | |
3557 | \r | |
3558 | /* MR14 */ if (r->dontComputeErrorSet) {\r | |
3559 | /* MR14 */ follow=empty;\r | |
3560 | } else {\r | |
3561 | MR_pointerStackReset(&MR_BackTraceStack); /* MR14 */\r | |
3562 | MR_ErrorSetComputationActive=1;\r | |
3563 | REACH(q->end, 1, &rk, follow);\r | |
3564 | MR_ErrorSetComputationActive=0;\r | |
3565 | require (MR_BackTraceStack.count == 0,"K: MR_BackTraceStack.count != 0");\r | |
3566 | }\r | |
3567 | \r | |
3568 | FillSet( follow );\r | |
3569 | set_free( follow );\r | |
3570 | \r | |
3571 | /* MR20 G. Hobbelt \r | |
3572 | Isn't it so that "fail:" is ONLY referenced when:\r | |
3573 | \r | |
3574 | !FoundException || FoundGuessBlk ?\r | |
3575 | \r | |
3576 | Therefore add the "if" around this piece of code generation...\r | |
3577 | \r | |
3578 | Should guessing mode also use _handler label instead of "fail"\r | |
3579 | when exception handling is active? gen can automatically put \r | |
3580 | "if (guessing)" there so as to skip all kinds of user code.\r | |
3581 | \r | |
3582 | */\r | |
3583 | \r | |
3584 | if ( !FoundException || FoundGuessBlk ) /* MR20 G. Hobbelt */\r | |
3585 | { /* MR20 G. Hobbelt */\r | |
3586 | _gen("fail:\n");\r | |
3587 | if ( !GenCC ) gen("zzEXIT(zztasp1);\n");\r | |
3588 | if ( FoundGuessBlk ) {\r | |
3589 | if ( !GenCC ) {gen("if ( zzguessing ) zzGUESS_FAIL;\n");}\r | |
3590 | else gen("if ( guessing ) zzGUESS_FAIL;\n");\r | |
3591 | }\r | |
3592 | if ( q->erraction!=NULL )\r | |
3593 | dumpAction(q->erraction, output, tabs, q->file, q->line, 1);\r | |
3594 | if ( GenCC )\r | |
3595 | {\r | |
3596 | gen1("syn(zzBadTok, %s, zzMissSet, zzMissTok, zzErrk);\n",\r | |
3597 | r->egroup==NULL?"(ANTLRChar *)\"\"":r->egroup);\r | |
3598 | }\r | |
3599 | else\r | |
3600 | {\r | |
3601 | gen1("zzsyn(zzMissText, zzBadTok, %s, zzMissSet, zzMissTok, zzErrk, zzBadText);\n",\r | |
3602 | r->egroup==NULL?"(ANTLRChar *)\"\"":r->egroup);\r | |
3603 | }\r | |
3604 | gen3("%sresynch(setwd%d, 0x%x);\n", GenCC?"":"zz", wordnum, 1<<setnum);\r | |
3605 | \r | |
3606 | if ( q->ret!=NULL ) {\r | |
3607 | genTraceOut(q);\r | |
3608 | gen("return _retv;\n");\r | |
3609 | } else if ( q->exceptions!=NULL ) {\r | |
3610 | genTraceOut(q);\r | |
3611 | gen("return;\n");\r | |
3612 | } else if (!FoundException) { /* MR10 */\r | |
3613 | genTraceOut(q); /* MR10 */\r | |
3614 | };\r | |
3615 | \r | |
3616 | } /* MR20 G. Hobbelt */\r | |
3617 | \r | |
3618 | if ( !GenCC ) gen("}\n");\r | |
3619 | \r | |
3620 | /* Gen code for exception handlers */\r | |
3621 | /* make sure each path out contains genTraceOut() */\r | |
3622 | \r | |
3623 | if ( q->exceptions!=NULL )\r | |
3624 | {\r | |
3625 | \r | |
3626 | gen("/* exception handlers */\n");\r | |
3627 | \r | |
3628 | dumpExceptions(q->exceptions);\r | |
3629 | \r | |
3630 | if ( !r->has_rule_exception )\r | |
3631 | {\r | |
3632 | _gen("_handler:\n");\r | |
3633 | gen("zzdflthandlers(_signal,_retsignal);\n");\r | |
3634 | }\r | |
3635 | /* MR20 G. Gobbelt The label "adios" is never referenced */\r | |
3636 | \r | |
3637 | #if 0\r | |
3638 | _gen("_adios:\n");\r | |
3639 | #endif\r | |
3640 | if ( q->ret!=NULL ) {\r | |
3641 | genTraceOut(q);\r | |
3642 | gen("return _retv;\n");\r | |
3643 | }\r | |
3644 | else {\r | |
3645 | genTraceOut(q);\r | |
3646 | gen("return;\n");\r | |
3647 | }\r | |
3648 | }\r | |
3649 | else if ( FoundException )\r | |
3650 | {\r | |
3651 | _gen("_handler:\n");\r | |
3652 | gen("zzdflthandlers(_signal,_retsignal);\n");\r | |
3653 | \r | |
3654 | /* MR1 */\r | |
3655 | /* MR1 7-Apr-97 Fix suggested by: John Bair (jbair@iftime.com) */\r | |
3656 | /* MR1 */\r | |
3657 | \r | |
3658 | if ( q->ret != NULL) { /* MR1 */\r | |
3659 | genTraceOut(q); /* MR10 */\r | |
3660 | gen("return _retv;\n"); /* MR1 */\r | |
3661 | } else { /* MR1 */\r | |
3662 | genTraceOut(q); /* MR10 */\r | |
3663 | gen("return;\n") ; /* MR1 */\r | |
3664 | }; /* MR1 */\r | |
3665 | }\r | |
3666 | \r | |
3667 | tabs--;\r | |
3668 | gen("}\n");\r | |
3669 | \r | |
3670 | /* MR10 Tired of looking at stacks that are as deep as the number of */\r | |
3671 | /* MR10 rules. Changes recursion to iteration. */\r | |
3672 | \r | |
3673 | MR_releaseResourcesUsedInRule( (Node *) q ); /* MR10 */\r | |
3674 | \r | |
3675 | if (InfoT) {\r | |
3676 | fprintf(output,"\n/* tnodes created for rule %s: %d */\n",\r | |
3677 | q->rname, (TnodesAllocated-TnodesAllocatedPrevRule) );\r | |
3678 | };\r | |
3679 | \r | |
3680 | TnodesAllocatedPrevRule=TnodesAllocated;\r | |
3681 | \r | |
3682 | if (q->p2 == NULL) dumpAfterActions( output );\r | |
3683 | q=(Junction *)q->p2;\r | |
3684 | require(q==NULL || q->jtype==RuleBlk,"RuleBlk p2 does not point to another RuleBlk");\r | |
3685 | \r | |
3686 | } while (q != NULL);\r | |
3687 | \r | |
3688 | /**** The old code ****/\r | |
3689 | /**** if ( q->p2 != NULL ) {TRANS(q->p2);} ****/ /* generate code for next rule too */\r | |
3690 | /**** else dumpAfterActions( output ); ****/\r | |
3691 | \r | |
3692 | }\r | |
3693 | \r | |
3694 | \r | |
3695 | /* This is for the function definition, not the declaration. */\r | |
3696 | \r | |
3697 | static void\r | |
3698 | #ifdef __USE_PROTOS\r | |
3699 | DumpFuncHeader( Junction *q, RuleEntry *r )\r | |
3700 | #else\r | |
3701 | DumpFuncHeader( q, r )\r | |
3702 | Junction *q;\r | |
3703 | RuleEntry *r;\r | |
3704 | #endif\r | |
3705 | {\r | |
3706 | /* */\r | |
3707 | /* MR1 10-Apr-97 MR1 Simplify insertion of commas in function header */\r | |
3708 | /* */\r | |
3709 | int needComma; /* MR1 */\r | |
3710 | \r | |
3711 | \r | |
3712 | /* A N S I */\r | |
3713 | _gen("\n");\r | |
3714 | if ( q->ret!=NULL )\r | |
3715 | {\r | |
3716 | if ( hasMultipleOperands(q->ret) ) /* MR23 */\r | |
3717 | {\r | |
3718 | if (GenCC) gen2("%s::_rv%d\n", CurrentClassName, r->rulenum)\r | |
3719 | else gen1("struct _rv%d\n",r->rulenum);\r | |
3720 | }\r | |
3721 | else\r | |
3722 | {\r | |
3723 | DumpType(q->ret, output);\r | |
3724 | gen("\n");\r | |
3725 | }\r | |
3726 | }\r | |
3727 | else\r | |
3728 | {\r | |
3729 | _gen("void\n");\r | |
3730 | }\r | |
3731 | /* MR1 */\r | |
3732 | /* MR1 10-Apr-97 133MR1 Replace __STDC__ with __USE_PROTOS */\r | |
3733 | /* MR1 */\r | |
3734 | if ( !GenCC ) _gen("#ifdef __USE_PROTOS\n"); /* MR1 */\r | |
3735 | if ( !GenCC ) gen2("%s%s(", RulePrefix, q->rname)\r | |
3736 | else gen3("%s::%s%s(", CurrentClassName, RulePrefix,q->rname);\r | |
3737 | \r | |
3738 | /* If we generate C++ method names, we must hide default arguments */\r | |
3739 | /* which can appear in the parameter declaration list. */\r | |
3740 | /* NOTICE: this is done only here, for the method definition, but */\r | |
3741 | /* not for the method declaration inside the class */\r | |
3742 | /* definition. This is exactly the behaviour defined in */\r | |
3743 | /* C++ standard for default parameters. */\r | |
3744 | \r | |
3745 | DumpANSIFunctionArgDef(output,q, 0 /* emit initializers ? */);\r | |
3746 | _gen("\n");\r | |
3747 | \r | |
3748 | if ( GenCC ) {\r | |
3749 | gen("{\n");\r | |
3750 | return;\r | |
3751 | }\r | |
3752 | \r | |
3753 | /* K & R */\r | |
3754 | gen("#else\n");\r | |
3755 | gen2("%s%s(", RulePrefix, q->rname);\r | |
3756 | needComma=0; /* MR1 */\r | |
3757 | if ( GenAST ) /* MR1 */\r | |
3758 | { /* MR1 */\r | |
3759 | _gen("_root"); /* MR1 */\r | |
3760 | needComma=1; /* MR1 */\r | |
3761 | } /* MR1 */\r | |
3762 | if ( FoundException ) /* MR1 */\r | |
3763 | { /* MR1 */\r | |
3764 | if (needComma) {_gen(",");needComma=0;}; /* MR1 */\r | |
3765 | _gen("_retsignal"); /* MR1 */\r | |
3766 | needComma=1; /* MR1 */\r | |
3767 | } /* MR1 */\r | |
3768 | /* MR5 Change below by Jan Mikkelsen (janm@zeta.org.au) 26-May-97 MR5 */\r | |
3769 | DumpListOfParmNames( q->pdecl, output, needComma ); /* MR5 */\r | |
3770 | gen(")\n");\r | |
3771 | if ( GenAST ) gen("AST **_root;\n");\r | |
3772 | if ( FoundException ) gen("int *_retsignal;\n");\r | |
3773 | DumpOldStyleParms( q->pdecl, output );\r | |
3774 | gen("#endif\n");\r | |
3775 | gen("{\n");\r | |
3776 | }\r | |
3777 | \r | |
3778 | void\r | |
3779 | #ifdef __USE_PROTOS\r | |
3780 | DumpANSIFunctionArgDef(FILE *f, Junction *q, int bInitializer)\r | |
3781 | #else\r | |
3782 | DumpANSIFunctionArgDef(f,q,bInitializer)\r | |
3783 | FILE *f;\r | |
3784 | Junction *q;\r | |
3785 | int bInitializer;\r | |
3786 | #endif\r | |
3787 | {\r | |
3788 | if ( GenAST )\r | |
3789 | {\r | |
3790 | if ( GenCC ) {fprintf(f,"ASTBase **_root");}\r | |
3791 | else fprintf(f,"AST**_root");\r | |
3792 | if ( !FoundException && q->pdecl!=NULL ) fprintf(f,",");\r | |
3793 | }\r | |
3794 | if ( FoundException )\r | |
3795 | {\r | |
3796 | if ( GenAST ) fprintf(f,",");\r | |
3797 | fprintf(f,"int *_retsignal");\r | |
3798 | if ( q->pdecl!=NULL ) {\r | |
3799 | fprintf(f,",");\r | |
3800 | }\r | |
3801 | }\r | |
3802 | if ( q->pdecl!=NULL ) {\r | |
3803 | DumpFormals(f, q->pdecl, bInitializer); /* MR23 */\r | |
3804 | }\r | |
3805 | else {\r | |
3806 | if ( !GenAST && !FoundException ) {\r | |
3807 | fprintf(f,"void");\r | |
3808 | }\r | |
3809 | }\r | |
3810 | fprintf(f,")");\r | |
3811 | }\r | |
3812 | \r | |
3813 | void\r | |
3814 | #ifdef __USE_PROTOS\r | |
3815 | genJunction( Junction *q )\r | |
3816 | #else\r | |
3817 | genJunction( q )\r | |
3818 | Junction *q;\r | |
3819 | #endif\r | |
3820 | {\r | |
3821 | require(q->ntype == nJunction, "genJunction: not junction");\r | |
3822 | require(q->jtype == Generic, "genJunction: not generic junction");\r | |
3823 | \r | |
3824 | if ( q->p1 != NULL ) TRANS(q->p1);\r | |
3825 | if ( q->p2 != NULL ) TRANS(q->p2);\r | |
3826 | }\r | |
3827 | \r | |
3828 | void\r | |
3829 | #ifdef __USE_PROTOS\r | |
3830 | genEndBlk( Junction *q )\r | |
3831 | #else\r | |
3832 | genEndBlk( q )\r | |
3833 | Junction *q;\r | |
3834 | #endif\r | |
3835 | {\r | |
3836 | }\r | |
3837 | \r | |
3838 | void\r | |
3839 | #ifdef __USE_PROTOS\r | |
3840 | genEndRule( Junction *q )\r | |
3841 | #else\r | |
3842 | genEndRule( q )\r | |
3843 | Junction *q;\r | |
3844 | #endif\r | |
3845 | {\r | |
3846 | }\r | |
3847 | \r | |
3848 | void\r | |
3849 | #ifdef __USE_PROTOS\r | |
3850 | genHdr( int file )\r | |
3851 | #else\r | |
3852 | genHdr( file )\r | |
3853 | int file;\r | |
3854 | #endif\r | |
3855 | {\r | |
3856 | int i;\r | |
3857 | \r | |
3858 | _gen("/*\n");\r | |
3859 | _gen(" * A n t l r T r a n s l a t i o n H e a d e r\n");\r | |
3860 | _gen(" *\n");\r | |
3861 | _gen(" * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001\n");\r | |
3862 | _gen(" * Purdue University Electrical Engineering\n");\r | |
3863 | _gen(" * With AHPCRC, University of Minnesota\n");\r | |
3864 | _gen1(" * ANTLR Version %s\n", Version);\r | |
3865 | _gen(" *\n");\r | |
3866 | /* MR10 */ _gen(" * ");\r | |
3867 | /* MR10 */ for (i=0 ; i < Save_argc ; i++) {\r | |
3868 | /* MR10 */ _gen(" ");\r | |
3869 | /* MR10 */ _gen1("%s", Save_argv[i]);\r | |
3870 | /* MR10 */ };\r | |
3871 | _gen("\n");\r | |
3872 | _gen(" *\n");\r | |
3873 | _gen(" */\n\n");\r | |
3874 | if (FirstAction != NULL ) dumpAction( FirstAction, output, 0, -1, 0, 1); /* MR11 MR15b */\r | |
3875 | _gen1("#define ANTLR_VERSION %s\n", VersionDef);\r | |
3876 | _gen("#include \"pcctscfg.h\"\n");\r | |
3877 | _gen("#include \"pccts_stdio.h\"\n");\r | |
3878 | if ( strcmp(ParserName, DefaultParserName)!=0 )\r | |
3879 | _gen2("#define %s %s\n", DefaultParserName, ParserName);\r | |
3880 | if ( strcmp(ParserName, DefaultParserName)!=0 )\r | |
3881 | {_gen1("#include \"%s\"\n", RemapFileName);}\r | |
3882 | OutLineInfo(output,1,FileStr[file]);\r | |
3883 | if ( GenCC ) {\r | |
3884 | if ( UserTokenDefsFile != NULL )\r | |
3885 | fprintf(output, "#include %s\n", UserTokenDefsFile);\r | |
3886 | else\r | |
3887 | fprintf(output, "#include \"%s\"\n", DefFileName);\r | |
3888 | }\r | |
3889 | \r | |
3890 | if ( HdrAction != NULL ) dumpAction( HdrAction, output, 0, -1, 0, 1);\r | |
3891 | if ( !GenCC && FoundGuessBlk )\r | |
3892 | {\r | |
3893 | _gen("#define ZZCAN_GUESS\n");\r | |
3894 | _gen("#include \"pccts_setjmp.h\"\n"); /* MR15 K.J. Cummings (cummings@peritus.com) */\r | |
3895 | }\r | |
3896 | if ( FoundException )\r | |
3897 | {\r | |
3898 | _gen("#define EXCEPTION_HANDLING\n");\r | |
3899 | _gen1("#define NUM_SIGNALS %d\n", NumSignals);\r | |
3900 | }\r | |
3901 | if ( !GenCC && OutputLL_k > 1 ) _gen1("#define LL_K %d\n", OutputLL_k);\r | |
3902 | if ( GenAST&&!GenCC ) _gen("#define GENAST\n\n");\r | |
3903 | if ( GenAST ) {\r | |
3904 | if ( GenCC ) {_gen1("#include \"%s\"\n\n", ASTBASE_H);}\r | |
3905 | else _gen("#include \"ast.h\"\n\n");\r | |
3906 | }\r | |
3907 | if ( !GenCC && DemandLookahead ) _gen("#define DEMAND_LOOK\n\n");\r | |
3908 | #ifdef DUM\r | |
3909 | if ( !GenCC && LexGen ) {\r | |
3910 | _gen1("#define zzEOF_TOKEN %d\n", (TokenInd!=NULL?TokenInd[EofToken]:EofToken));\r | |
3911 | }\r | |
3912 | #endif\r | |
3913 | /* ###WARNING: This will have to change when SetWordSize changes */\r | |
3914 | if ( !GenCC ) _gen1("#define zzSET_SIZE %lu\n", NumWords(TokenNum-1)*sizeof(unsigned));\r | |
3915 | if (TraceGen) {\r | |
3916 | _gen("#ifndef zzTRACE_RULES\n"); /* MR20 */\r | |
3917 | _gen("#define zzTRACE_RULES\n"); /* MR20 */\r | |
3918 | _gen("#endif\n"); /* MR22 */\r | |
3919 | };\r | |
3920 | if ( !GenCC ) {_gen("#include \"antlr.h\"\n");}\r | |
3921 | else {\r | |
3922 | _gen1("#include \"%s\"\n", APARSER_H);\r | |
3923 | _gen1("#include \"%s.h\"\n", CurrentClassName);\r | |
3924 | }\r | |
3925 | if ( !GenCC ) {\r | |
3926 | if ( UserDefdTokens )\r | |
3927 | {_gen1("#include %s\n", UserTokenDefsFile);}\r | |
3928 | /* still need this one as it has the func prototypes */\r | |
3929 | _gen1("#include \"%s\"\n", DefFileName);\r | |
3930 | }\r | |
3931 | /* still need this one as it defines the DLG interface */\r | |
3932 | if ( !GenCC ) _gen("#include \"dlgdef.h\"\n");\r | |
3933 | if ( LexGen && GenCC ) _gen1("#include \"%s\"\n", DLEXERBASE_H);\r | |
3934 | if ( GenCC ) _gen1("#include \"%s\"\n", ATOKPTR_H);\r | |
3935 | if ( !GenCC && LexGen ) _gen1("#include \"%s\"\n", ModeFileName);\r | |
3936 | \r | |
3937 | /* MR10 Ofer Ben-Ami (gremlin@cs.huji.ac.il) */\r | |
3938 | /* MR10 Finally, a definition of the Purify macro */\r | |
3939 | \r | |
3940 | if (PURIFY == TRUE) { /* MR23 */\r | |
3941 | _gen("\n/* MR23 In order to remove calls to PURIFY use the antlr"); /* MR23 */\r | |
3942 | _gen(" -nopurify option */\n\n"); /* MR23 */\r | |
3943 | _gen("#ifndef PCCTS_PURIFY\n");\r | |
3944 | _gen("#define PCCTS_PURIFY(r,s) memset((char *) &(r),'\\0',(s));\n");\r | |
3945 | _gen("#endif\n\n");\r | |
3946 | } /* MR23 */\r | |
3947 | }\r | |
3948 | \r | |
3949 | void\r | |
3950 | #ifdef __USE_PROTOS\r | |
3951 | genHdr1( int file )\r | |
3952 | #else\r | |
3953 | genHdr1( file )\r | |
3954 | int file;\r | |
3955 | #endif\r | |
3956 | {\r | |
3957 | ListNode *p;\r | |
3958 | \r | |
3959 | genHdr(file);\r | |
3960 | if ( GenAST )\r | |
3961 | {\r | |
3962 | if ( !GenCC ) {\r | |
3963 | _gen("#include \"ast.c\"\n");\r | |
3964 | _gen("zzASTgvars\n\n");\r | |
3965 | }\r | |
3966 | }\r | |
3967 | if ( !GenCC ) _gen("ANTLR_INFO\n");\r | |
3968 | if ( BeforeActions != NULL )\r | |
3969 | {\r | |
3970 | for (p = BeforeActions->next; p!=NULL; p=p->next)\r | |
3971 | {\r | |
3972 | UserAction *ua = (UserAction *)p->elem;\r | |
3973 | dumpAction( ua->action, output, 0, ua->file, ua->line, 1);\r | |
3974 | }\r | |
3975 | }\r | |
3976 | \r | |
3977 | if ( !FoundException ) return;\r | |
3978 | \r | |
3979 | if ( GenCC )\r | |
3980 | {\r | |
3981 | _gen1("\nvoid %s::\n", CurrentClassName);\r | |
3982 | _gen("zzdflthandlers( int _signal, int *_retsignal )\n");\r | |
3983 | _gen("{\n");\r | |
3984 | }\r | |
3985 | else\r | |
3986 | {\r | |
3987 | _gen("\nvoid\n");\r | |
3988 | /* MR1 */\r | |
3989 | /* MR1 10-Apr-97 133MR1 Replace __STDC__ with __USE_PROTOS */\r | |
3990 | /* MR1 */\r | |
3991 | _gen("#ifdef __USE_PROTOS\n"); /* MR1 */\r | |
3992 | _gen("zzdflthandlers( int _signal, int *_retsignal )\n");\r | |
3993 | _gen("#else\n");\r | |
3994 | _gen("zzdflthandlers( _signal, _retsignal )\n");\r | |
3995 | _gen("int _signal;\n");\r | |
3996 | _gen("int *_retsignal;\n");\r | |
3997 | _gen("#endif\n");\r | |
3998 | _gen("{\n");\r | |
3999 | }\r | |
4000 | tabs++;\r | |
4001 | if ( DefaultExGroup!=NULL )\r | |
4002 | {\r | |
4003 | dumpException(DefaultExGroup, 1);\r | |
4004 | if ( !hasDefaultException(DefaultExGroup) )\r | |
4005 | {\r | |
4006 | gen("default :\n");\r | |
4007 | tabs++;\r | |
4008 | gen("*_retsignal = _signal;\n");\r | |
4009 | tabs--;\r | |
4010 | gen("}\n");\r | |
4011 | }\r | |
4012 | }\r | |
4013 | else {\r | |
4014 | gen("*_retsignal = _signal;\n");\r | |
4015 | }\r | |
4016 | \r | |
4017 | tabs--;\r | |
4018 | _gen("}\n\n");\r | |
4019 | }\r | |
4020 | \r | |
4021 | void\r | |
4022 | #ifdef __USE_PROTOS\r | |
4023 | genStdPCCTSIncludeFile( FILE *f,char *gate ) /* MR10 */\r | |
4024 | #else\r | |
4025 | genStdPCCTSIncludeFile( f , gate) /* MR10 */\r | |
4026 | FILE *f;\r | |
4027 | char * gate; /* MR10 */\r | |
4028 | #endif\r | |
4029 | {\r | |
4030 | /* MR10 Ramanathan Santhanam (ps@kumaran.com) */\r | |
4031 | /* MR10 Same preprocessor symbol use to gate stdpccts.h */\r | |
4032 | /* MR10 even when two grammars are in use. */\r | |
4033 | /* MR10 Derive gate symbol from -fh filename */\r | |
4034 | \r | |
4035 | if (gate == NULL) {\r | |
4036 | fprintf(f,"#ifndef STDPCCTS_H\n"); /* MR10 */\r | |
4037 | fprintf(f,"#define STDPCCTS_H\n"); /* MR10 */\r | |
4038 | } else {\r | |
4039 | fprintf(f,"#ifndef STDPCCTS_%s_H\n",gate); /* MR10 */\r | |
4040 | fprintf(f,"#define STDPCCTS_%s_H\n",gate); /* MR10 */\r | |
4041 | };\r | |
4042 | fprintf(f,"/*\n");\r | |
4043 | if (gate == NULL) {\r | |
4044 | fprintf(f," * %s -- P C C T S I n c l u d e\n", stdpccts);\r | |
4045 | } else {\r | |
4046 | fprintf(f," * Standard PCCTS include file with -fh %s -- P C C T S I n c l u d e\n", stdpccts);\r | |
4047 | }\r | |
4048 | fprintf(f," *\n");\r | |
4049 | fprintf(f," * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001\n");\r | |
4050 | fprintf(f," * Purdue University Electrical Engineering\n");\r | |
4051 | fprintf(f," * With AHPCRC, University of Minnesota\n");\r | |
4052 | fprintf(f," * ANTLR Version %s\n", Version);\r | |
4053 | fprintf(f," */\n\n");\r | |
4054 | \r | |
4055 | fprintf(f,"#ifndef ANTLR_VERSION\n");\r | |
4056 | fprintf(f,"#define ANTLR_VERSION %s\n", VersionDef);\r | |
4057 | fprintf(f,"#endif\n\n");\r | |
4058 | \r | |
4059 | if (FirstAction != NULL ) dumpAction(FirstAction, f, 0, -1, 0, 1); /* MR11 */\r | |
4060 | \r | |
4061 | fprintf(f,"#include \"pcctscfg.h\"\n");\r | |
4062 | fprintf(f,"#include \"pccts_stdio.h\"\n");\r | |
4063 | if ( GenCC )\r | |
4064 | {\r | |
4065 | if ( UserDefdTokens )\r | |
4066 | fprintf(f, "#include %s\n", UserTokenDefsFile);\r | |
4067 | else {\r | |
4068 | fprintf(f, "#include \"%s\"\n", DefFileName);\r | |
4069 | }\r | |
4070 | \r | |
4071 | fprintf(f, "#include \"%s\"\n", ATOKEN_H);\r | |
4072 | \r | |
4073 | if ( HdrAction != NULL ) dumpAction( HdrAction, f, 0, -1, 0, 1);\r | |
4074 | \r | |
4075 | fprintf(f, "#include \"%s\"\n", ATOKENBUFFER_H);\r | |
4076 | \r | |
4077 | if ( OutputLL_k > 1 ) fprintf(f,"static const unsigned LL_K=%d;\n", OutputLL_k);\r | |
4078 | if ( GenAST ) {\r | |
4079 | fprintf(f, "#include \"%s\"\n", ASTBASE_H);\r | |
4080 | }\r | |
4081 | \r | |
4082 | if (TraceGen) {\r | |
4083 | fprintf(f,"#ifndef zzTRACE_RULES\n"); /* MR20 */\r | |
4084 | fprintf(f,"#define zzTRACE_RULES\n"); /* MR20 */\r | |
4085 | fprintf(f,"#endif\n"); /* MR22 */\r | |
4086 | };\r | |
4087 | \r | |
4088 | fprintf(f,"#include \"%s\"\n", APARSER_H);\r | |
4089 | fprintf(f,"#include \"%s.h\"\n", CurrentClassName);\r | |
4090 | if ( LexGen ) fprintf(f,"#include \"%s\"\n", DLEXERBASE_H);\r | |
4091 | fprintf(f, "#endif\n");\r | |
4092 | return;\r | |
4093 | }\r | |
4094 | \r | |
4095 | if ( strcmp(ParserName, DefaultParserName)!=0 )\r | |
4096 | fprintf(f, "#define %s %s\n", DefaultParserName, ParserName);\r | |
4097 | if ( strcmp(ParserName, DefaultParserName)!=0 )\r | |
4098 | fprintf(f, "#include \"%s\"\n", RemapFileName);\r | |
4099 | if ( UserTokenDefsFile != NULL )\r | |
4100 | fprintf(f, "#include %s\n", UserTokenDefsFile);\r | |
4101 | if ( HdrAction != NULL ) dumpAction( HdrAction, f, 0, -1, 0, 1);\r | |
4102 | if ( FoundGuessBlk )\r | |
4103 | {\r | |
4104 | fprintf(f,"#define ZZCAN_GUESS\n");\r | |
4105 | fprintf(f,"#include \"pccts_setjmp.h\"\n");\r | |
4106 | }\r | |
4107 | if (TraceGen) {\r | |
4108 | fprintf(f,"#ifndef zzTRACE_RULES\n"); /* MR20 */\r | |
4109 | fprintf(f,"#define zzTRACE_RULES\n"); /* MR20 */\r | |
4110 | fprintf(f,"#endif\n"); /* MR22 */\r | |
4111 | };\r | |
4112 | if ( OutputLL_k > 1 ) fprintf(f,"#define LL_K %d\n", OutputLL_k);\r | |
4113 | if ( GenAST ) fprintf(f,"#define GENAST\n");\r | |
4114 | if ( FoundException )\r | |
4115 | {\r | |
4116 | /* MR1 7-Apr-97 1.33MR1 */\r | |
4117 | /* MR1 Fix suggested by: */\r | |
4118 | /* MR1 Francois-Xavier Fontaine (fontaine_f@istvax.ist.lu) */\r | |
4119 | \r | |
4120 | fprintf(f,"#define EXCEPTION_HANDLING\n"); /* MR1 */\r | |
4121 | fprintf(f,"#define NUM_SIGNALS %d\n", NumSignals); /* MR1 */\r | |
4122 | }\r | |
4123 | if ( DemandLookahead ) fprintf(f,"#define DEMAND_LOOK\n");\r | |
4124 | #ifdef DUM\r | |
4125 | if ( LexGen ) fprintf(f, "#define zzEOF_TOKEN %d\n", (TokenInd!=NULL?TokenInd[EofToken]:EofToken));\r | |
4126 | #endif\r | |
4127 | /* ###WARNING: This will have to change when SetWordSize changes */\r | |
4128 | fprintf(f, "#define zzSET_SIZE %lu\n", NumWords(TokenNum-1)*sizeof(unsigned));\r | |
4129 | if (TraceGen) {\r | |
4130 | fprintf(f,"#ifndef zzTRACE_RULES\n"); /* MR20 */\r | |
4131 | fprintf(f,"#define zzTRACE_RULES\n"); /* MR20 */\r | |
4132 | fprintf(f,"#endif\n"); /* MR22 */\r | |
4133 | };\r | |
4134 | fprintf(f,"#include \"antlr.h\"\n");\r | |
4135 | if ( GenAST ) fprintf(f,"#include \"ast.h\"\n");\r | |
4136 | if ( UserDefdTokens )\r | |
4137 | fprintf(f, "#include %s\n", UserTokenDefsFile);\r | |
4138 | /* still need this one as it has the func prototypes */\r | |
4139 | fprintf(f, "#include \"%s\"\n", DefFileName);\r | |
4140 | /* still need this one as it defines the DLG interface */\r | |
4141 | fprintf(f,"#include \"dlgdef.h\"\n");\r | |
4142 | /* don't need this one unless DLG is used */\r | |
4143 | if ( LexGen ) fprintf(f,"#include \"%s\"\n", ModeFileName);\r | |
4144 | fprintf(f,"#endif\n");\r | |
4145 | }\r | |
4146 | \r | |
4147 | /* dump action 's' to file 'output' starting at "local" tab 'tabs'\r | |
4148 | Dump line information in front of action if GenLineInfo is set\r | |
4149 | If file == -1 then GenLineInfo is ignored.\r | |
4150 | The user may redefine the LineInfoFormatStr to his/her liking\r | |
4151 | most compilers will like the default, however.\r | |
4152 | \r | |
4153 | June '93; changed so that empty lines are left alone so that\r | |
4154 | line information is correct for the compiler/debuggers.\r | |
4155 | */\r | |
4156 | void\r | |
4157 | #ifdef __USE_PROTOS\r | |
4158 | dumpAction( char *s, FILE *output, int tabs, int file, int line,\r | |
4159 | int final_newline )\r | |
4160 | #else\r | |
4161 | dumpAction( s, output, tabs, file, line, final_newline )\r | |
4162 | char *s;\r | |
4163 | FILE *output;\r | |
4164 | int tabs;\r | |
4165 | int file;\r | |
4166 | int line;\r | |
4167 | int final_newline;\r | |
4168 | #endif\r | |
4169 | {\r | |
4170 | int inDQuote, inSQuote;\r | |
4171 | require(s!=NULL, "dumpAction: NULL action");\r | |
4172 | require(output!=NULL, eMsg1("dumpAction: output FILE is NULL for %s",s));\r | |
4173 | \r | |
4174 | if ( GenLineInfo && file != -1 )\r | |
4175 | {\r | |
4176 | OutLineInfo(output,line,FileStr[file]);\r | |
4177 | }\r | |
4178 | PastWhiteSpace( s );\r | |
4179 | /* don't print a tab if first non-white char is a # (preprocessor command) */\r | |
4180 | if ( *s!='#' ) {TAB;}\r | |
4181 | inDQuote = inSQuote = FALSE;\r | |
4182 | while ( *s != '\0' )\r | |
4183 | {\r | |
4184 | if ( *s == '\\' )\r | |
4185 | {\r | |
4186 | fputc( *s++, output ); /* Avoid '"' Case */\r | |
4187 | if ( *s == '\0' ) return;\r | |
4188 | if ( *s == '\'' ) fputc( *s++, output );\r | |
4189 | if ( *s == '\"' ) fputc( *s++, output );\r | |
4190 | }\r | |
4191 | if ( *s == '\'' )\r | |
4192 | {\r | |
4193 | if ( !inDQuote ) inSQuote = !inSQuote;\r | |
4194 | }\r | |
4195 | if ( *s == '"' )\r | |
4196 | {\r | |
4197 | if ( !inSQuote ) inDQuote = !inDQuote;\r | |
4198 | }\r | |
4199 | if ( *s == '\n' )\r | |
4200 | {\r | |
4201 | fputc('\n', output);\r | |
4202 | s++;\r | |
4203 | PastWhiteSpace( s );\r | |
4204 | if ( *s == '}' )\r | |
4205 | {\r | |
4206 | --tabs;\r | |
4207 | TAB;\r | |
4208 | fputc( *s++, output );\r | |
4209 | continue;\r | |
4210 | }\r | |
4211 | if ( *s == '\0' ) return;\r | |
4212 | if ( *s != '#' ) /* #define, #endif etc.. start at col 1 */\r | |
4213 | {\r | |
4214 | TAB;\r | |
4215 | }\r | |
4216 | }\r | |
4217 | if ( *s == '}' && !(inSQuote || inDQuote) )\r | |
4218 | {\r | |
4219 | --tabs; /* Indent one fewer */\r | |
4220 | }\r | |
4221 | if ( *s == '{' && !(inSQuote || inDQuote) )\r | |
4222 | {\r | |
4223 | tabs++; /* Indent one more */\r | |
4224 | }\r | |
4225 | fputc( *s, output );\r | |
4226 | s++;\r | |
4227 | }\r | |
4228 | if ( final_newline ) fputc('\n', output);\r | |
4229 | }\r | |
4230 | \r | |
4231 | static void\r | |
4232 | #ifdef __USE_PROTOS\r | |
4233 | dumpAfterActions( FILE *output )\r | |
4234 | #else\r | |
4235 | dumpAfterActions( output )\r | |
4236 | FILE *output;\r | |
4237 | #endif\r | |
4238 | {\r | |
4239 | ListNode *p;\r | |
4240 | require(output!=NULL, "dumpAfterActions: output file was NULL for some reason");\r | |
4241 | if ( AfterActions != NULL )\r | |
4242 | {\r | |
4243 | for (p = AfterActions->next; p!=NULL; p=p->next)\r | |
4244 | {\r | |
4245 | UserAction *ua = (UserAction *)p->elem;\r | |
4246 | dumpAction( ua->action, output, 0, ua->file, ua->line, 1);\r | |
4247 | }\r | |
4248 | }\r | |
4249 | fclose( output );\r | |
4250 | }\r | |
4251 | \r | |
4252 | /*\r | |
4253 | * Find the next action in the stream of execution. Do not pass\r | |
4254 | * junctions with more than one path leaving them.\r | |
4255 | * Only pass generic junctions.\r | |
4256 | *\r | |
4257 | * Scan forward while (generic junction with p2==NULL)\r | |
4258 | * If we stop on an action, return ptr to the action\r | |
4259 | * else return NULL;\r | |
4260 | */\r | |
4261 | static ActionNode *\r | |
4262 | #ifdef __USE_PROTOS\r | |
4263 | findImmedAction( Node *q )\r | |
4264 | #else\r | |
4265 | findImmedAction( q )\r | |
4266 | Node *q;\r | |
4267 | #endif\r | |
4268 | {\r | |
4269 | Junction *j;\r | |
4270 | require(q!=NULL, "findImmedAction: NULL node");\r | |
4271 | require(q->ntype>=1 && q->ntype<=NumNodeTypes, "findImmedAction: invalid node");\r | |
4272 | \r | |
4273 | while ( q->ntype == nJunction )\r | |
4274 | {\r | |
4275 | j = (Junction *)q;\r | |
4276 | if ( j->jtype != Generic || j->p2 != NULL ) return NULL;\r | |
4277 | q = j->p1;\r | |
4278 | if ( q == NULL ) return NULL;\r | |
4279 | }\r | |
4280 | if ( q->ntype == nAction ) return (ActionNode *)q;\r | |
4281 | return NULL;\r | |
4282 | }\r | |
4283 | \r | |
4284 | static void\r | |
4285 | #ifdef __USE_PROTOS\r | |
4286 | dumpRetValAssign( char *retval, char *ret_def, RuleRefNode * ruleRef /* MR30 */)\r | |
4287 | #else\r | |
4288 | dumpRetValAssign( retval, ret_def, ruleRef /* MR30 */)\r | |
4289 | char *retval;\r | |
4290 | char *ret_def;\r | |
4291 | RuleRefNode *ruleRefNode;\r | |
4292 | #endif\r | |
4293 | {\r | |
4294 | char *q = ret_def;\r | |
4295 | \r | |
4296 | tab();\r | |
4297 | while ( *retval != '\0' && *q != '\0')\r | |
4298 | {\r | |
4299 | while ( isspace((*retval)) ) retval++;\r | |
4300 | while ( *retval!=',' && *retval!='\0' ) fputc(*retval++, output);\r | |
4301 | fprintf(output, " = _trv.");\r | |
4302 | \r | |
4303 | DumpNextNameInDef(&q, output);\r | |
4304 | while ( isspace(*q) ) q++;\r | |
4305 | fputc(';', output); fputc(' ', output);\r | |
4306 | if ( *retval == ',' ) retval++;\r | |
4307 | }\r | |
4308 | if (*retval == '\0' && *q != '\0') {\r | |
4309 | /* MR30 */ errFL("Fewer output values than output formals for rule reference",\r | |
4310 | /* MR30 */ FileStr[ruleRef->file],ruleRef->line);\r | |
4311 | }\r | |
4312 | if (*retval != '\0' && *q == '\0') {\r | |
4313 | /* MR30 */ errFL("More output actuals than output formals for rule reference",\r | |
4314 | /* MR30 */ FileStr[ruleRef->file],ruleRef->line);\r | |
4315 | }\r | |
4316 | }\r | |
4317 | \r | |
4318 | /* This function computes the set of tokens that can possibly be seen k\r | |
4319 | * tokens in the future from point j\r | |
4320 | */\r | |
4321 | \r | |
4322 | static set\r | |
4323 | #ifdef __USE_PROTOS\r | |
4324 | ComputeErrorSet( Junction *j, int k, int usePlusBlockBypass)\r | |
4325 | #else\r | |
4326 | ComputeErrorSet( j, k, usePlusBlockBypass )\r | |
4327 | Junction *j;\r | |
4328 | int k;\r | |
4329 | int usePlusBlockBypass;\r | |
4330 | #endif\r | |
4331 | {\r | |
4332 | Junction *alt1;\r | |
4333 | set a, rk, f;\r | |
4334 | require(j->ntype==nJunction, "ComputeErrorSet: non junction passed");\r | |
4335 | \r | |
4336 | f = rk = empty;\r | |
4337 | for (alt1=j; alt1!=NULL; alt1 = (Junction *)alt1->p2)\r | |
4338 | {\r | |
4339 | if (alt1->ignore && ! usePlusBlockBypass) continue; /* MR21 - Ignore aPlusBlk forward p2 */\r | |
4340 | REACH(alt1->p1, k, &rk, a);\r | |
4341 | require(set_nil(rk), "ComputeErrorSet: rk != nil");\r | |
4342 | set_free(rk);\r | |
4343 | set_orin(&f, a);\r | |
4344 | set_free(a);\r | |
4345 | }\r | |
4346 | return f;\r | |
4347 | }\r | |
4348 | \r | |
4349 | static char *\r | |
4350 | #ifdef __USE_PROTOS\r | |
4351 | tokenFollowSet(TokNode *p)\r | |
4352 | #else\r | |
4353 | tokenFollowSet(p)\r | |
4354 | TokNode *p;\r | |
4355 | #endif\r | |
4356 | {\r | |
4357 | static char buf[100];\r | |
4358 | set rk, a;\r | |
4359 | int n;\r | |
4360 | rk = empty;\r | |
4361 | \r | |
4362 | REACH(p->next, 1, &rk, a);\r | |
4363 | require(set_nil(rk), "rk != nil");\r | |
4364 | set_free(rk);\r | |
4365 | n = DefErrSet( &a, 0, NULL );\r | |
4366 | set_free(a);\r | |
4367 | if ( GenCC )\r | |
4368 | sprintf(buf, "err%d", n);\r | |
4369 | else\r | |
4370 | sprintf(buf, "zzerr%d", n);\r | |
4371 | return buf;\r | |
4372 | }\r | |
4373 | \r | |
4374 | static void\r | |
4375 | #ifdef __USE_PROTOS\r | |
4376 | makeErrorClause( Junction *q, set f, int max_k, int usePlusBlockBypass )\r | |
4377 | #else\r | |
4378 | makeErrorClause( q, f, max_k, usePlusBlockBypass )\r | |
4379 | Junction *q;\r | |
4380 | set f;\r | |
4381 | int max_k;\r | |
4382 | int usePlusBlockBypass;\r | |
4383 | #endif\r | |
4384 | {\r | |
4385 | char * handler_id=""; /* MR7 */\r | |
4386 | int nilf=0; /* MR13 */\r | |
4387 | RuleEntry *ruleEntry; /* MR14 */\r | |
4388 | \r | |
4389 | if ( FoundException )\r | |
4390 | {\r | |
4391 | _gen("else {\n");\r | |
4392 | tabs++;\r | |
4393 | if ( FoundGuessBlk )\r | |
4394 | {\r | |
4395 | if ( GenCC ) {gen("if ( guessing ) goto fail;\n");}\r | |
4396 | else gen("if ( zzguessing ) goto fail;\n");\r | |
4397 | }\r | |
4398 | gen("if (_sva) _signal=NoViableAlt;\n");\r | |
4399 | gen("else _signal=NoSemViableAlt;\n");\r | |
4400 | if (q->outerEG != NULL) {\r | |
4401 | handler_id=q->outerEG->altID;\r | |
4402 | #if 0\r | |
4403 | } else {\r | |
4404 | printf("q->curAltNum=%d q->exception_label=%s\n",q->curAltNum,q->exception_label);\r | |
4405 | gen("*** DEBUG *** outerEG==NULL\n");\r | |
4406 | #endif\r | |
4407 | };\r | |
4408 | gen1("goto %s_handler; /* MR7 */\n",handler_id); /* MR7 */\r | |
4409 | tabs--;\r | |
4410 | gen("}\n");\r | |
4411 | return;\r | |
4412 | }\r | |
4413 | \r | |
4414 | if ( max_k == 1 )\r | |
4415 | {\r | |
4416 | /* MR13 */ nilf=set_nil(f);\r | |
4417 | if ( GenCC ) {\r | |
4418 | _gen1("else {FAIL(1,err%d", DefErrSet1(1,&f,1,NULL));\r | |
4419 | } else {\r | |
4420 | _gen1("else {zzFAIL(1,zzerr%d", DefErrSet1(1,&f,1,NULL));\r | |
4421 | };\r | |
4422 | set_free(f);\r | |
4423 | }\r | |
4424 | else\r | |
4425 | {\r | |
4426 | int i;\r | |
4427 | set_free(f);\r | |
4428 | if ( GenCC ) {_gen1("else {FAIL(%d", max_k);}\r | |
4429 | else _gen1("else {zzFAIL(%d", max_k);\r | |
4430 | \r | |
4431 | ruleEntry = (RuleEntry *) hash_get(Rname,q->rname);\r | |
4432 | \r | |
4433 | for (i=1; i<=max_k; i++)\r | |
4434 | {\r | |
4435 | /* MR14 */ if (ruleEntry->dontComputeErrorSet) {\r | |
4436 | /* MR14 */ f=empty;\r | |
4437 | } else {\r | |
4438 | f = ComputeErrorSet(q, i, usePlusBlockBypass /* use plus block bypass ? */ );\r | |
4439 | }\r | |
4440 | \r | |
4441 | if ( GenCC ) {_gen1(",err%d", DefErrSet( &f, 1, NULL ));}\r | |
4442 | else _gen1(",zzerr%d", DefErrSet( &f, 1, NULL ));\r | |
4443 | \r | |
4444 | set_free(f);\r | |
4445 | }\r | |
4446 | }\r | |
4447 | _gen(",&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}\n");\r | |
4448 | /* MR13 */ if (nilf) {\r | |
4449 | /* MR13 */ errFL("empty error set for alt - probably because of undefined rule or infinite left recursion",\r | |
4450 | /* MR13 */ FileStr[q->file],q->line);\r | |
4451 | /* MR13 */ gen(" /* MR13 empty error set for this alt - undef rule ? infinite left recursion ? */");\r | |
4452 | /* MR13 */ };\r | |
4453 | }\r | |
4454 | \r | |
4455 | static /* MR7 */\r | |
4456 | #ifdef __USE_PROTOS\r | |
4457 | char * findOuterHandlerLabel(ExceptionGroup *eg) /* MR7 */\r | |
4458 | #else\r | |
4459 | char * findOuterHandlerLabel(eg) /* MR7 */\r | |
4460 | ExceptionGroup *eg; /* MR7 */\r | |
4461 | #endif\r | |
4462 | {\r | |
4463 | char *label=NULL; /* MR7 */\r | |
4464 | ExceptionGroup *outerEG; /* MR7 */\r | |
4465 | \r | |
4466 | if (eg->forRule == 0) { /* MR7 */\r | |
4467 | if (eg->labelEntry != NULL) { /* MR7 */\r | |
4468 | outerEG=eg->labelEntry->outerEG; /* MR7 */\r | |
4469 | if (outerEG != NULL) { /* MR7 */\r | |
4470 | label=outerEG->altID; /* MR7 */\r | |
4471 | outerEG->used=1; /* MR7 */\r | |
4472 | }; /* MR7 */\r | |
4473 | } else if (eg->outerEG != NULL) { /* MR7 */\r | |
4474 | outerEG=eg->outerEG; /* MR7 */\r | |
4475 | label=outerEG->altID; /* MR7 */\r | |
4476 | outerEG->used=1; /* MR7 */\r | |
4477 | }; /* MR7 */\r | |
4478 | }; /* MR7 */\r | |
4479 | return (label==NULL ? "" : label); /* MR7 */\r | |
4480 | } /* MR7 */\r | |
4481 | \r | |
4482 | /*** debug ***/\r | |
4483 | #if 0\r | |
4484 | ** static /* MR7 */\r | |
4485 | ** #ifdef __USE_PROTOS\r | |
4486 | ** char * findOuterAltHandlerLabel(Junction *startJ) /* MR7 */\r | |
4487 | ** #else\r | |
4488 | ** char * findOuterAltHandlerLabel(startJ) /* MR7 */\r | |
4489 | ** Junction *startJ; /* MR7 */\r | |
4490 | ** #endif\r | |
4491 | ** { /* MR7 */\r | |
4492 | ** char *label=NULL; /* MR7 */\r | |
4493 | ** Junction *alt; /* MR7 */\r | |
4494 | ** /* MR7 */\r | |
4495 | ** for (alt=startJ; alt != NULL; alt=alt->outerAltstart) { /* MR7 */\r | |
4496 | ** label=alt->exception_label; /* MR7 */\r | |
4497 | ** if (label != NULL) break; /* MR7 */\r | |
4498 | ** }; /* MR7 */\r | |
4499 | ** return (label==NULL ? "" : label); /* MR7 */\r | |
4500 | ** } /* MR7 */\r | |
4501 | #endif\r | |
4502 | \r | |
4503 | #ifdef __USE_PROTOS\r | |
4504 | static void OutLineInfo(FILE *file,int line,char *fileName)\r | |
4505 | #else\r | |
4506 | static void OutLineInfo(file,line,fileName)\r | |
4507 | FILE * file;\r | |
4508 | int line;\r | |
4509 | char * fileName;\r | |
4510 | #endif\r | |
4511 | {\r | |
4512 | static char * prevFileName=NULL;\r | |
4513 | static char * prevFileNameMS=NULL;\r | |
4514 | \r | |
4515 | char * p;\r | |
4516 | char * q;\r | |
4517 | \r | |
4518 | if (! GenLineInfo) return;\r | |
4519 | \r | |
4520 | if (!GenLineInfoMS) {\r | |
4521 | fprintf(file, LineInfoFormatStr,line,fileName);\r | |
4522 | } else {\r | |
4523 | if (fileName == prevFileName) {\r | |
4524 | fprintf(file, LineInfoFormatStr,line,prevFileNameMS);\r | |
4525 | } else {\r | |
4526 | if (prevFileNameMS != NULL) free (prevFileNameMS);\r | |
4527 | prevFileNameMS=(char *)calloc(1,strlen(fileName)+1);\r | |
4528 | require(prevFileNameMS != NULL,"why not do this in calloc wrapper");\r | |
4529 | q=prevFileNameMS;\r | |
4530 | for (p=fileName; *p != 0; p++) {\r | |
4531 | *q=*p;\r | |
4532 | if (*q == '\\') *q='/';\r | |
4533 | q++;\r | |
4534 | }\r | |
4535 | }\r | |
4536 | prevFileName=fileName;\r | |
4537 | };\r | |
4538 | }\r | |
4539 | \r | |
4540 | #if 0\r | |
4541 | \r | |
4542 | /* MR21 */\r | |
4543 | \r | |
4544 | #ifdef __USE_PROTOS\r | |
4545 | void OutFirstSetSymbol(Junction *q, char * pSymbol)\r | |
4546 | #else\r | |
4547 | void OutFirstSetSymbol(q, pSymbol)\r | |
4548 | Junction* q;\r | |
4549 | char * pSymbol\r | |
4550 | #endif\r | |
4551 | {\r | |
4552 | \r | |
4553 | set f;\r | |
4554 | if (pSymbol == NULL) return;\r | |
4555 | gen1("/** #FirstSetSymbol(%s) **/\n",pSymbol);\r | |
4556 | f = ComputeErrorSet(q, 1, 0 /* use plus block bypass ? */);\r | |
4557 | DefErrSetWithSuffix (0 /* nil ok */, &f,0 /* no substitute */, pSymbol, "");\r | |
4558 | set_free(f);\r | |
4559 | }\r | |
4560 | #endif\r | |
4561 | \r | |
4562 | /* MR21 */\r | |
4563 | \r | |
4564 | #ifdef __USE_PROTOS\r | |
4565 | void BlockPreambleOption(Junction *q, char * pSymbol)\r | |
4566 | #else\r | |
4567 | void BlockPreambleOption(q, pSymbol)\r | |
4568 | Junction* q;\r | |
4569 | char * pSymbol;\r | |
4570 | #endif\r | |
4571 | {\r | |
4572 | set f = empty;\r | |
4573 | if (pSymbol != NULL) {\r | |
4574 | f = ComputeErrorSet(q, 1, 0 /* use plus block bypass ? */);\r | |
4575 | gen1("/** #FirstSetSymbol(%s) **/\n",pSymbol);\r | |
4576 | DefErrSetWithSuffix (0 /* nil ok */, &f,0 /* no substitute */, pSymbol, "");\r | |
4577 | }\r | |
4578 | set_free(f);\r | |
4579 | }\r | |
4580 | \r | |
4581 | /* MR21 */\r | |
4582 | \r | |
4583 | void\r | |
4584 | #ifdef __USE_PROTOS\r | |
4585 | dumpActionPlus(ActionNode *a, char *s, FILE *output, int tabs, int file, int line,\r | |
4586 | int final_newline )\r | |
4587 | #else\r | |
4588 | dumpActionPlus(a, s, output, tabs, file, line, final_newline )\r | |
4589 | ActionNode *a;\r | |
4590 | char *s;\r | |
4591 | FILE *output;\r | |
4592 | int tabs;\r | |
4593 | int file;\r | |
4594 | int line;\r | |
4595 | int final_newline;\r | |
4596 | #endif\r | |
4597 | {\r | |
4598 | dumpAction(s,output,tabs,file,line,final_newline);\r | |
4599 | }\r | |
4600 | \r | |
4601 | \r | |
4602 | #if 0\r | |
4603 | ** #ifdef __USE_PROTOS\r | |
4604 | ** void MR_ErrorSets(Junction *q, int max_k, int usePlusBlockBypass)\r | |
4605 | ** #else\r | |
4606 | ** void MR_ErrorSets(q, max_k, usePlusBlockBypass)\r | |
4607 | ** Junction *q;\r | |
4608 | ** int max_k;\r | |
4609 | ** int usePlusBlockBypass;\r | |
4610 | ** #endif\r | |
4611 | ** {\r | |
4612 | ** int k;\r | |
4613 | ** set setResult;\r | |
4614 | ** Junction* alt1;\r | |
4615 | ** Junction* p;\r | |
4616 | ** set rk;\r | |
4617 | ** \r | |
4618 | ** require (max_k <= CLL_k, "k > CLL_k");\r | |
4619 | ** \r | |
4620 | ** \r | |
4621 | ** for (k = 1; k <= CLL_k; k++) {set_clr(q->fset[k]); }\r | |
4622 | ** \r | |
4623 | ** for (k = 1; k <= max_k; k++) {\r | |
4624 | ** for (alt1=q; alt1 != NULL; alt1 = (Junction *)alt1->p2)\r | |
4625 | ** {\r | |
4626 | ** if (alt1->ignore && ! usePlusBlockBypass) continue;\r | |
4627 | ** p = analysis_point((Junction *)alt1->p1);\r | |
4628 | ** REACH(p, k, &rk, setResult);\r | |
4629 | ** require(set_nil(rk), "rk != nil");\r | |
4630 | ** set_orin(&q->fset[k], setResult);\r | |
4631 | ** }\r | |
4632 | ** }\r | |
4633 | ** }\r | |
4634 | #endif\r | |
4635 | \r | |
4636 | \r | |
4637 | #ifdef __USE_PROTOS\r | |
4638 | void DumpInitializers(FILE* output, RuleEntry *r, char * pReturn)\r | |
4639 | #else\r | |
4640 | void DumpInitializers(output, r, pReturn)\r | |
4641 | FILE* output;\r | |
4642 | RuleEntry *r;\r | |
4643 | char * pReturn;\r | |
4644 | #endif\r | |
4645 | {\r | |
4646 | char *p = pReturn;\r | |
4647 | char *pDataType;\r | |
4648 | char *pSymbol;\r | |
4649 | char *pEqualSign;\r | |
4650 | char *pValue;\r | |
4651 | char *pSeparator;\r | |
4652 | int nest = 0;\r | |
4653 | char *q;\r | |
4654 | \r | |
4655 | require(pReturn!=NULL, "DumpInitializer: invalid string"); \r | |
4656 | \r | |
4657 | while (*p != 0) {\r | |
4658 | p = endFormal(p,\r | |
4659 | &pDataType,\r | |
4660 | &pSymbol,\r | |
4661 | &pEqualSign,\r | |
4662 | &pValue,\r | |
4663 | &pSeparator,\r | |
4664 | &nest);\r | |
4665 | if (nest != 0) return;\r | |
4666 | if (pValue != NULL) {\r | |
4667 | tab();\r | |
4668 | q = strBetween(pSymbol, pEqualSign, pSeparator);\r | |
4669 | fprintf(output, "_retv.%s", q);\r | |
4670 | q = strBetween(pValue, NULL, pSeparator);\r | |
4671 | fprintf(output, " = %s;\n", q);\r | |
4672 | }\r | |
4673 | }\r | |
4674 | }\r | |
4675 | \r | |
4676 | #ifdef __USE_PROTOS\r | |
4677 | void DumpFormals(FILE* output, char * pReturn, int bInitializer)\r | |
4678 | #else\r | |
4679 | void DumpFormals(output, pReturn, bInitializer)\r | |
4680 | FILE* output;\r | |
4681 | char * pReturn;\r | |
4682 | int bInitializer;\r | |
4683 | #endif\r | |
4684 | {\r | |
4685 | char *p = pReturn;\r | |
4686 | char *pDataType;\r | |
4687 | char *pSymbol;\r | |
4688 | char *pEqualSign;\r | |
4689 | char *pValue;\r | |
4690 | char *pSeparator;\r | |
4691 | int nest = 0;\r | |
4692 | char *q;\r | |
4693 | int count = 0;\r | |
4694 | \r | |
4695 | require(pReturn!=NULL, "DumpFormals: invalid string"); \r | |
4696 | \r | |
4697 | while (*p != 0) {\r | |
4698 | p = endFormal(p,\r | |
4699 | &pDataType,\r | |
4700 | &pSymbol,\r | |
4701 | &pEqualSign,\r | |
4702 | &pValue,\r | |
4703 | &pSeparator,\r | |
4704 | &nest);\r | |
4705 | if (nest != 0) return;\r | |
4706 | if (count > 0) fprintf(output,",");\r | |
4707 | if (pDataType != NULL && pSymbol != NULL) {\r | |
4708 | q = strBetween(pDataType, pSymbol, pSeparator);\r | |
4709 | fprintf(output, "%s", q);\r | |
4710 | q = strBetween(pSymbol, pEqualSign, pSeparator);\r | |
4711 | fprintf(output," %s",q);\r | |
4712 | if (pValue != NULL) {\r | |
4713 | q = strBetween(pValue, NULL, pSeparator);\r | |
4714 | if (bInitializer != 0) {\r | |
4715 | fprintf(output, " = %s", q);\r | |
4716 | }\r | |
4717 | }\r | |
4718 | }\r | |
4719 | count++;\r | |
4720 | }\r | |
4721 | }\r | |
4722 | \r | |
4723 | /* MR23 Check for empty alt in a more intelligent way.\r | |
4724 | Previously, an empty alt for genBlk had to point directly\r | |
4725 | to the endBlock. This did not work once I changed {...}\r | |
4726 | blocks to look like (...|...| epsilon) since there were\r | |
4727 | intervening generics. This fixes the problem for this\r | |
4728 | particular case. Things like actions or empty blocks of\r | |
4729 | various kinds will still cause problems, but I wasn't\r | |
4730 | prepared to handle pathological cases like (A|()*). It\r | |
4731 | does handle (A | ()), which is a recommended idiom for\r | |
4732 | epsilon.\r | |
4733 | \r | |
4734 | Actually, this isn't quite correct since it doesn't handle\r | |
4735 | the case of the ignore bit in the plus block bypass, but\r | |
4736 | I'm too tired to figure out the correct fix, and will just\r | |
4737 | work around it.\r | |
4738 | */\r | |
4739 | \r | |
4740 | #ifdef __USE_PROTOS\r | |
4741 | int isEmptyAlt(Node * alt, Node * endBlock)\r | |
4742 | #else\r | |
4743 | int isEmptyAlt(alt, endBlock)\r | |
4744 | Node * alt;\r | |
4745 | Node * endBlock;\r | |
4746 | #endif\r | |
4747 | {\r | |
4748 | Node * n = alt;\r | |
4749 | Junction * j;\r | |
4750 | while (n != endBlock) {\r | |
4751 | switch (n->ntype) {\r | |
4752 | \r | |
4753 | case nRuleRef:\r | |
4754 | return 0;\r | |
4755 | \r | |
4756 | case nToken:\r | |
4757 | return 0;\r | |
4758 | \r | |
4759 | case nAction:\r | |
4760 | return 0;\r | |
4761 | \r | |
4762 | case nJunction:\r | |
4763 | goto JUNCTION;\r | |
4764 | \r | |
4765 | default:\r | |
4766 | fatal_internal("Invalid node type");\r | |
4767 | return 0;\r | |
4768 | }\r | |
4769 | JUNCTION:\r | |
4770 | j = (Junction *) n;\r | |
4771 | \r | |
4772 | switch (j->jtype) {\r | |
4773 | case Generic:\r | |
4774 | {\r | |
4775 | n = j->p1;\r | |
4776 | goto NEXT;\r | |
4777 | }\r | |
4778 | \r | |
4779 | case aSubBlk:\r | |
4780 | {\r | |
4781 | n = j->p1; /* MR26 */\r | |
4782 | goto NEXT; /* MR26 */\r | |
4783 | }\r | |
4784 | \r | |
4785 | case EndBlk:\r | |
4786 | return 0;\r | |
4787 | \r | |
4788 | case EndRule:\r | |
4789 | return 1;\r | |
4790 | \r | |
4791 | default:\r | |
4792 | return 0;\r | |
4793 | }\r | |
4794 | NEXT: continue;\r | |
4795 | }\r | |
4796 | return 1;\r | |
4797 | }\r |