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