]> pd.if.org Git - pccts/blob - antlr/gen.c
auto commit for import
[pccts] / antlr / gen.c
1 /*
2  * gen.c
3  *
4  * $Id: gen.c,v 1.7 95/09/26 12:58:40 parrt Exp $
5  * $Revision: 1.7 $
6  *
7  * Generate C code (ANSI, K&R, C++)
8  *
9  * SOFTWARE RIGHTS
10  *
11  * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
12  * Set (PCCTS) -- PCCTS is in the public domain.  An individual or
13  * company may do whatever they wish with source code distributed with
14  * PCCTS or the code generated by PCCTS, including the incorporation of
15  * PCCTS, or its output, into commerical software.
16  *
17  * We encourage users to develop software with PCCTS.  However, we do ask
18  * that credit is given to us for developing PCCTS.  By "credit",
19  * we mean that if you incorporate our source code into one of your
20  * programs (commercial product, research project, or otherwise) that you
21  * acknowledge this fact somewhere in the documentation, research report,
22  * etc...  If you like PCCTS and have developed a nice tool with the
23  * output, please mention that you developed it using PCCTS.  In
24  * addition, we ask that this header remain intact in our source code.
25  * As long as these guidelines are kept, we expect to continue enhancing
26  * this system and expect to make other tools available as they are
27  * completed.
28  *
29  * ANTLR 1.33
30  * Terence Parr
31  * Parr Research Corporation
32  * with Purdue University and AHPCRC, University of Minnesota
33  * 1989-1995
34  */
35 #include <stdio.h>
36 #include <ctype.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 extern char *PRED_AND_LIST;
48 extern char *PRED_OR_LIST;
49
50
51                                         /* T r a n s l a t i o n  T a b l e s */
52
53 /* C_Trans[node type] == pointer to function that knows how to translate that node. */
54 #ifdef __cplusplus
55 void (*C_Trans[NumNodeTypes+1])(...) = {
56         NULL,
57         NULL,                                   /* See next table.   
58 Junctions have many types */
59         (void (*)(...)) genRuleRef,
60         (void (*)(...)) genToken,
61         (void (*)(...)) genAction
62 };
63 #else
64 void (*C_Trans[NumNodeTypes+1])() = {
65         NULL,
66         NULL,                                   /* See next table.   
67 Junctions have many types */
68         genRuleRef,
69         genToken,
70         genAction
71 };
72 #endif
73
74 /* C_JTrans[Junction type] == pointer to function that knows how to translate that
75  * kind of junction node.
76  */
77 #ifdef __cplusplus
78 void (*C_JTrans[NumJuncTypes+1])(...) = {
79         NULL,
80         (void (*)(...)) genSubBlk,
81         (void (*)(...)) genOptBlk,
82         (void (*)(...)) genLoopBlk,
83         (void (*)(...)) genEndBlk,
84         (void (*)(...)) genRule,
85         (void (*)(...)) genJunction,
86         (void (*)(...)) genEndRule,
87         (void (*)(...)) genPlusBlk,
88         (void (*)(...)) genLoopBegin
89 };
90 #else
91 void (*C_JTrans[NumJuncTypes+1])() = {
92         NULL,
93         genSubBlk,
94         genOptBlk,
95         genLoopBlk,
96         genEndBlk,
97         genRule,
98         genJunction,
99         genEndRule,
100         genPlusBlk,
101         genLoopBegin
102 };
103 #endif
104
105 #define PastWhiteSpace(s)       while (*(s) == ' ' || *(s) == '\t') {s++;}
106
107 static int tabs = 0;
108 #define TAB { int i; for (i=0; i<tabs; i++) fputc('\t', output); }
109 static void
110 #ifdef __USE_PROTOS
111 tab( void )
112 #else
113 tab( )
114 #endif
115 TAB
116
117 #ifdef __USE_PROTOS
118 static char *tokenFollowSet(TokNode *);
119 static ActionNode *findImmedAction( Node * );
120 static void dumpRetValAssign(char *, char *);
121 static void dumpAfterActions(FILE *output);
122 static set ComputeErrorSet(Junction *, int);
123 static void makeErrorClause(Junction *, set, int);
124 static void DumpFuncHeader( Junction *, RuleEntry * );
125 static int has_guess_block_as_first_item(Junction *);
126 static int genExprSets(set *, int);
127 static void genExprTree( Tree *t, int k );
128 #else
129 static char *tokenFollowSet();
130 static ActionNode *findImmedAction();
131 static void dumpRetValAssign();
132 static void dumpAfterActions();
133 static set ComputeErrorSet();
134 static void makeErrorClause();
135 static void DumpFuncHeader();
136 static int has_guess_block_as_first_item();
137 static int genExprSets();
138 static void genExprTree();
139 #endif
140
141 #define gen(s)                  {tab(); fprintf(output, s);}
142 #define gen1(s,a)               {tab(); fprintf(output, s,a);}
143 #define gen2(s,a,b)             {tab(); fprintf(output, s,a,b);}
144 #define gen3(s,a,b,c)   {tab(); fprintf(output, s,a,b,c);}
145 #define gen4(s,a,b,c,d) {tab(); fprintf(output, s,a,b,c,d);}
146 #define gen5(s,a,b,c,d,e)       {tab(); fprintf(output, s,a,b,c,d,e);}
147 #define gen6(s,a,b,c,d,e,f)     {tab(); fprintf(output, s,a,b,c,d,e,f);}
148 #define gen7(s,a,b,c,d,e,f,g)   {tab(); fprintf(output, s,a,b,c,d,e,f,g);}
149
150 #define _gen(s)                 {fprintf(output, s);}
151 #define _gen1(s,a)              {fprintf(output, s,a);}
152 #define _gen2(s,a,b)    {fprintf(output, s,a,b);}
153 #define _gen3(s,a,b,c)  {fprintf(output, s,a,b,c);}
154 #define _gen4(s,a,b,c,d){fprintf(output, s,a,b,c,d);}
155 #define _gen5(s,a,b,c,d,e){fprintf(output, s,a,b,c,d,e);}
156 #define _gen6(s,a,b,c,d,e,f){fprintf(output, s,a,b,c,d,e,f);}
157 #define _gen7(s,a,b,c,d,e,f,g){fprintf(output, s,a,b,c,d,e,f,g);}
158
159 static void
160 #ifdef __USE_PROTOS
161 warn_about_using_gk_option(void)
162 #else
163 warn_about_using_gk_option()
164 #endif
165 {
166         static int warned_already=0;
167
168         if ( !DemandLookahead || warned_already ) return;
169         warned_already = 1;
170         warnNoFL("-gk option could cause trouble for <<...>>? predicates");
171 }
172
173 void
174 #ifdef __USE_PROTOS
175 freeBlkFsets( Junction *q )
176 #else
177 freeBlkFsets( q )
178 Junction *q;
179 #endif
180 {
181         int i;
182         Junction *alt;
183         require(q!=NULL, "freeBlkFsets: invalid node");
184
185         for (alt=q; alt != NULL; alt= (Junction *) alt->p2 )
186         {
187                 for (i=1; i<=CLL_k; i++) set_free(alt->fset[i]);
188         }
189 }
190
191 /*
192  * Generate a local variable allocation for each token references
193  * in this block.
194  */
195 static void
196 #ifdef __USE_PROTOS
197 genTokenPointers( Junction *q )
198 #else
199 genTokenPointers( q )
200 Junction *q;
201 #endif
202 {
203         /* Rule refs are counted and can be referenced, but their
204          * value is not set to anything useful ever.
205          *
206      * The ptrs are to be named _tij where i is the current level
207          * and j is the element number within an alternative.
208          */
209         int first=1, t=0;
210         set a;
211         tokensRefdInBlock = q->tokrefs;
212
213         if ( set_deg(q->tokrefs) == 0 ) return;
214         a = set_dup(q->tokrefs);
215         gen("ANTLRTokenPtr ");
216         for (; !set_nil(a); set_rm(t, a))
217         {
218                 t = set_int(a);
219                 if ( first ) first = 0;
220                 else _gen(",");
221                 if ( !DontCopyTokens ) _gen2("_tv%d%d,", BlkLevel, t);
222                 _gen2("_t%d%d", BlkLevel, t);
223                 if ( !DontCopyTokens ) {_gen2("= &_tv%d%d", BlkLevel, t);}
224                 else _gen("=NULL");
225         }
226         _gen(";\n");
227         set_free(a);
228 }
229
230 static int
231 #ifdef __USE_PROTOS
232 hasDefaultException(ExceptionGroup *eg)
233 #else
234 hasDefaultException(eg)
235 ExceptionGroup *eg;
236 #endif
237 {
238     ListNode *q;
239
240     for (q = eg->handlers->next; q!=NULL; q=q->next)
241     {
242         ExceptionHandler *eh = (ExceptionHandler *)q->elem;
243         if ( strcmp("default", eh->signalname)==0 ) {
244             return 1;
245         }
246     }
247     return 0;
248 }
249
250 static void
251 #ifdef __USE_PROTOS
252 dumpException(ExceptionGroup *eg, int no_default_case)
253 #else
254 dumpException(eg, no_default_case)
255 ExceptionGroup *eg;
256 int no_default_case;
257 #endif
258 {
259         gen1("switch ( _signal ) {\n", eg->label==NULL?"":eg->label);
260         {       
261                 ListNode *q;
262                 for (q = eg->handlers->next; q!=NULL; q=q->next)
263                 {
264                         ExceptionHandler *eh = (ExceptionHandler *)q->elem;
265                         if ( strcmp("default", eh->signalname)==0 ) {
266                                 gen("default :\n");
267                                 tabs++;
268                                 dumpAction(eh->action, output, tabs, -1, 1, 1);
269                 gen("_signal = NoSignal;\n");
270                                 tabs--;
271                                 gen("}\n");
272                                 return;
273                         }
274                         gen1("case %s :\n", eh->signalname);
275                         tabs++;
276                         if ( eh->action != NULL )
277                         {
278                                 dumpAction(eh->action, output, tabs, -1, 1, 1);
279                 gen("_signal = NoSignal;\n");
280                                 gen("break;\n");
281                         }
282                         tabs--;
283                 }
284         }
285         if ( no_default_case ) return;
286
287         gen("default :\n");
288         tabs++;
289 /*      gen("*_retsignal = _signal;\n");*/
290         gen("goto _handler;\n");
291         tabs--;
292         gen("}\n");
293 }
294
295 static void
296 #ifdef __USE_PROTOS
297 dumpExceptions(ListNode *list)
298 #else
299 dumpExceptions(list)
300 ListNode *list;
301 #endif
302 {
303         ListNode *p;
304
305         for (p = list->next; p!=NULL; p=p->next)
306         {
307                 ExceptionGroup *eg = (ExceptionGroup *) p->elem;
308                 _gen2("%s%s_handler:\n",
309                           eg->label==NULL?"":eg->label,
310                           eg->altID==NULL?"":eg->altID);
311                 if ( eg->altID!=NULL ) dumpException(eg, 0);
312                 else {
313                         /* This must be the rule exception handler */
314                         dumpException(eg, 1);
315                         if ( !hasDefaultException(eg) )
316             {
317                 gen("default :\n");
318                 tabs++;
319                 gen("zzdflthandlers(_signal,_retsignal);\n");
320                 tabs--;
321                 gen("}\n");
322             }
323                 }
324         }
325 }
326
327 /* For each element label that is found in a rule, generate a unique
328  * Attribute (and AST pointer if GenAST) variable.
329  */
330 void
331 #ifdef __USE_PROTOS
332 genElementLabels(ListNode *list)
333 #else
334 genElementLabels(list)
335 ListNode *list;
336 #endif
337 {
338         int first=1;
339         ListNode *p;
340
341         if ( GenCC ) {gen("ANTLRTokenPtr");}
342         else {gen("Attrib");}
343         for (p = list->next; p!=NULL; p=p->next)
344         {
345                 char *ep = (char *)p->elem;
346                 if ( first ) first = 0;
347                 else _gen(",");
348                 if ( GenCC ) {_gen1(" %s=NULL",ep);}
349                 else {_gen1(" %s",ep);}
350         }
351         _gen(";\n");
352
353         if ( !GenAST ) return;
354
355         first = 1;
356         gen("AST");
357         for (p = list->next; p!=NULL; p=p->next)
358         {
359                 char *ep = (char *)p->elem;
360                 if ( first ) first = 0;
361                 else _gen(",");
362                 _gen1(" *%s_ast=NULL",ep);
363         }
364         _gen(";\n");
365 }
366
367 /*
368  * Generate a local variable allocation for each token or rule reference
369  * in this block.
370  */
371 static void
372 #ifdef __USE_PROTOS
373 genASTPointers( Junction *q )
374 #else
375 genASTPointers( q )
376 Junction *q;
377 #endif
378 {
379         int first=1, t;
380         set a;
381
382         a = set_or(q->tokrefs, q->rulerefs);
383         if ( set_deg(a) > 0 )
384         {
385                 gen("AST ");
386                 for (; !set_nil(a); set_rm(t, a))
387                 {
388                         t = set_int(a);
389                         if ( first ) first = 0;
390                         else _gen(",");
391                         _gen2("*_ast%d%d=NULL", BlkLevel, t);
392                 }
393                 set_free(a);
394         }
395         _gen(";\n");
396 }
397
398 static void
399 #ifdef __USE_PROTOS
400 BLOCK_Head( void )
401 #else
402 BLOCK_Head( )
403 #endif
404 {
405         gen("{\n");
406         tabs++;
407         if ( !GenCC ) gen1("zzBLOCK(zztasp%d);\n", BlkLevel);
408 }
409
410 static void
411 #ifdef __USE_PROTOS
412 BLOCK_Tail( void )
413 #else
414 BLOCK_Tail( )
415 #endif
416 {
417         if ( !GenCC ) gen1("zzEXIT(zztasp%d);\n", BlkLevel);
418         if ( !GenCC ) gen("}\n");
419         tabs--;
420         gen("}\n");
421 }
422
423 static void
424 #ifdef __USE_PROTOS
425 BLOCK_Preamble( Junction *q )
426 #else
427 BLOCK_Preamble( q )
428 Junction *q;
429 #endif
430 {
431         ActionNode *a;
432         Junction *begin;
433
434         BLOCK_Head();
435         if ( GenCC ) genTokenPointers(q);
436         if ( GenCC&&GenAST ) genASTPointers(q);
437         if ( q->jtype == aPlusBlk ) gen("int zzcnt=1;\n");
438         if ( q->parm != NULL && !q->predparm ) gen1("zzaPush(%s);\n", q->parm)
439         else if ( !GenCC ) gen("zzMake0;\n");
440         if ( !GenCC ) gen("{\n");
441         if ( q->jtype == aLoopBegin ) begin = (Junction *) ((Junction *)q->p1);
442         else begin = q;
443         if ( has_guess_block_as_first_item(begin) )
444         {
445                 gen("zzGUESS_BLOCK\n");
446         }
447         if ( q->jtype == aLoopBegin )
448                 a = findImmedAction( ((Junction *)q->p1)->p1 ); /* look at aLoopBlk */
449         else
450                 a = findImmedAction( q->p1 );
451         if ( a!=NULL && !a->is_predicate ) {
452                 dumpAction(a->action, output, tabs, a->file, a->line, 1);
453                 a->done = 1;    /* remove action. We have already handled it */
454         }
455 }
456
457 void
458 #ifdef __USE_PROTOS
459 genCombinedPredTreeContext( Predicate *p )
460 #else
461 genCombinedPredTreeContext( p )
462 Predicate *p;
463 #endif
464 {
465         static set *ctx=NULL;           /* genExprSets() is destructive, make copy*/
466         require(p!=NULL, "can't make context tree for NULL pred tree");
467
468 #ifdef DBG_PRED
469         fprintf(stderr, "enter genCombinedPredTreeContext(%s,0x%x) with sets:\n", p->expr, p);
470         s_fprT(stderr, p->scontext[1]);
471         fprintf(stderr, "\n");
472 #endif
473         if ( p->down == NULL )
474         {
475 /*              if ( p->k>1 && p->tcontext!=NULL ) */
476                 if ( p->tcontext!=NULL )
477                 {
478                         _gen("(");
479                         genExprTree(p->tcontext, 1);
480                         _gen(")");
481                 }
482 /*              else if ( p->k==1 && set_deg(p->scontext[1])>0 )*/
483                 else if ( set_deg(p->scontext[1])>0 )
484                 {
485                         if ( ctx==NULL ) ctx = (set *)calloc(CLL_k+1, sizeof(set));
486                         require(ctx!=NULL, "ctx cannot allocate");
487                         ctx[0]=empty;
488                         ctx[1]=set_dup(p->scontext[1]);
489                         _gen("(");
490                         genExprSets(&(ctx[0]), p->k);
491                         _gen(")");
492                         set_free(ctx[1]);
493                 }
494                 else if ( p->expr==PRED_AND_LIST || p->expr==PRED_OR_LIST ) {
495                         fatal_internal("pred tree is orphan OR or AND list");
496                 }
497                 else {
498                         fatal_internal("pred tree context is empty");
499                 }
500                 return;
501         }
502
503         if ( p->expr == PRED_AND_LIST )
504         {
505                 require(p->down!=NULL && p->down->right!=NULL, "pred tree is wacked");
506                 genCombinedPredTreeContext(p->down);
507                 _gen("||");
508                 genCombinedPredTreeContext(p->down->right);
509                 return;
510         }
511
512         if ( p->expr == PRED_OR_LIST )
513         {
514                 Predicate *list = p->down;
515                 for (; list!=NULL; list=list->right)
516                 {
517                         genCombinedPredTreeContext(list);
518                         if ( list->right!=NULL ) _gen("||");
519                 }
520                 return;
521         }
522
523         fatal("pred tree is really wacked");
524 }
525
526 void
527 #ifdef __USE_PROTOS
528 genPredTreeGate( Predicate *p, int in_and_expr )
529 #else
530 genPredTreeGate( p, in_and_expr )
531 Predicate *p;
532 int in_and_expr;
533 #endif
534 {
535         if ( in_and_expr )
536         {
537                 _gen("!(");
538                 genCombinedPredTreeContext(p);
539                 _gen(")||");
540                 if ( p->down!=NULL ) _gen("\n");
541         }
542         else
543         {
544                 _gen("(");
545                 genCombinedPredTreeContext(p);
546                 _gen(")&&");
547                 if ( p->down!=NULL ) _gen("\n");
548         }
549 }
550
551 void
552 #ifdef __USE_PROTOS
553 genPred(Predicate *p, Node *j)
554 #else
555 genPred(p,j)
556 Predicate *p;
557 Node *j;
558 #endif
559 {
560         if ( FoundException ) {_gen("(_sva=(");}
561         else {_gen("(");}
562         if ( GenLineInfo && j->file != -1 ) _gen("\n");
563         dumpAction(p->expr, output, 0, -1 /*indicates no line info*/, j->line, 0);
564         if ( FoundException ) {_gen("))");}
565         else {_gen(")");}
566 }
567
568 void
569 #ifdef __USE_PROTOS
570 genPredTree( Predicate *p, Node *j, int in_and_expr )
571 #else
572 genPredTree( p, j, in_and_expr )
573 Predicate *p;
574 Node *j;
575 int in_and_expr;
576 #endif
577 {
578         if ( HoistPredicateContext )
579         {
580                 _gen("(");
581                 genPredTreeGate(p, in_and_expr);
582         }
583
584         /* if leaf node, just gen predicate */
585         if ( p->down==NULL )
586         {
587                 genPred(p,j);
588                 if ( HoistPredicateContext ) _gen(")");
589                 return;
590         }
591
592         /* if AND list, do both preds (only two possible) */
593         if ( p->expr == PRED_AND_LIST )
594         {
595                 _gen("(");
596                 genPredTree(p->down, j, 1);
597                 _gen("&&");
598                 genPredTree(p->down->right, j, 1);
599                 _gen(")");
600                 if ( HoistPredicateContext ) _gen(")");
601                 return;
602         }
603
604         if ( p->expr == PRED_OR_LIST )
605         {
606                 Predicate *list;
607                 _gen("(");
608                 list = p->down;
609                 for (; list!=NULL; list=list->right)
610                 {
611                         genPredTree(list, j, 0);
612                         if ( list->right!=NULL ) _gen("||");
613                 }
614                 _gen(")");
615                 if ( HoistPredicateContext ) _gen(")");
616                 return;
617         }
618
619         fatal_internal("predicate tree is wacked");
620 }
621
622 void
623 #ifdef __USE_PROTOS
624 genPredTreeMain( Predicate *p, Node *j )
625 #else
626 genPredTreeMain( p, j )
627 Predicate *p;
628 Node *j;
629 #endif
630 {
631         genPredTree(p,j,1);
632 }
633
634 static void
635 #ifdef __USE_PROTOS
636 genExprTree( Tree *t, int k )
637 #else
638 genExprTree( t, k )
639 Tree *t;
640 int k;
641 #endif
642 {
643         require(t!=NULL, "genExprTree: NULL tree");
644         
645         if ( t->token == ALT )
646         {
647                 _gen("("); genExprTree(t->down, k); _gen(")");
648                 if ( t->right!=NULL )
649                 {
650                         _gen("||");
651                         on1line++;
652                         if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
653                         _gen("("); genExprTree(t->right, k); _gen(")");
654                 }
655                 return;
656         }
657         if ( t->down!=NULL ) _gen("(");
658         _gen1("LA(%d)==",k);
659         if ( TokenString(t->token) == NULL ) _gen1("%d", t->token)
660         else _gen1("%s", TokenString(t->token));
661         if ( t->down!=NULL )
662         {
663                 _gen("&&");
664                 on1line++;
665                 if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
666                 _gen("("); genExprTree(t->down, k+1); _gen(")");
667         }
668         if ( t->down!=NULL ) _gen(")");
669         if ( t->right!=NULL )
670         {
671                 _gen("||");
672                 on1line++;
673                 if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
674                 _gen("("); genExprTree(t->right, k); _gen(")");
675         }
676 }
677
678 /*
679  * Generate LL(k) type expressions of the form:
680  *
681  *               (LA(1) == T1 || LA(1) == T2 || ... || LA(1) == Tn) &&
682  *               (LA(2) == T1 || LA(2) == T2 || ... || LA(2) == Tn) &&
683  *                      .....
684  *               (LA(k) == T1 || LA(k) == T2 || ... || LA(k) == Tn)
685  *
686  * If GenExprSets generate:
687  *
688  *              (setwdi[LA(1)]&(1<<j)) && (setwdi[LA(2)]&(1<<j)) ...
689  *
690  * where n is set_deg(expr) and Ti is some random token and k is the last nonempty
691  * set in fset <=CLL_k.
692  * k=1..CLL_k where CLL_k >= 1.
693  *
694  * This routine is visible only to this file and cannot answer a TRANS message.
695  *
696  */
697 static int
698 #ifdef __USE_PROTOS
699 genExpr( Junction *j )
700 #else
701 genExpr( j )
702 Junction *j;
703 #endif
704 {
705         int max_k;
706
707         /* if full LL(k) is sufficient, then don't use approximate (-ck) lookahead
708          * from CLL_k..LL_k
709          */
710         {
711                 int limit;
712                 if ( j->ftree!=NULL ) limit = LL_k;
713                 else limit = CLL_k;
714                 max_k = genExprSets(j->fset, limit);
715         }
716
717         /* Do tests for real tuples from other productions that conflict with
718          * artificial tuples generated by compression (using sets of tokens
719          * rather than k-trees).
720          */
721         if ( j->ftree != NULL )
722         {
723                 _gen(" && !("); genExprTree(j->ftree, 1); _gen(")");
724         }
725
726         if ( ParseWithPredicates && j->predicate!=NULL )
727         {
728                 Predicate *p = j->predicate;
729                 warn_about_using_gk_option();
730                 _gen("&&");
731                 genPredTreeMain(p, (Node *)j);
732         }
733
734         return max_k;
735 }
736
737 static int
738 #ifdef __USE_PROTOS
739 genExprSets( set *fset, int limit )
740 #else
741 genExprSets( fset, limit )
742 set *fset;
743 int limit;
744 #endif
745 {
746         int k = 1;
747         int max_k = 0;
748         unsigned *e, *g, firstTime=1;
749
750         if ( GenExprSets )
751         {
752                 while ( !set_nil(fset[k]) && k<=limit )
753                 {
754                         if ( set_deg(fset[k])==1 )      /* too simple for a set? */
755                         {
756                                 int e;
757                                 _gen1("(LA(%d)==",k);
758                                 e = set_int(fset[k]);
759                                 if ( TokenString(e) == NULL ) _gen1("%d)", e)
760                                 else _gen1("%s)", TokenString(e));
761                         }
762                         else
763                         {
764                                 NewSet();
765                                 FillSet( fset[k] );
766                                 _gen3("(setwd%d[LA(%d)]&0x%x)", wordnum, k, 1<<setnum);
767                         }
768                         if ( k>max_k ) max_k = k;
769                         if ( k == CLL_k ) break;
770                         k++;
771                         if ( !set_nil(fset[k]) && k<=limit ) _gen(" && ");
772                         on1line++;
773                         if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
774                 }
775                 return max_k;
776         }
777
778         while ( !set_nil(fset[k]) && k<=limit )
779         {
780                 if ( (e=g=set_pdq(fset[k])) == NULL ) fatal_internal("genExpr: cannot allocate IF expr pdq set");
781                 for (; *e!=nil; e++)
782                 {
783                         if ( !firstTime ) _gen(" || ") else { _gen("("); firstTime = 0; }
784                         on1line++;
785                         if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
786                         _gen1("LA(%d)==",k);
787                         if ( TokenString(*e) == NULL ) _gen1("%d", *e)
788                         else _gen1("%s", TokenString(*e));
789                 }
790                 free( (char *)g );
791                 _gen(")");
792                 if ( k>max_k ) max_k = k;
793                 if ( k == CLL_k ) break;
794                 k++;
795                 if ( !set_nil(fset[k]) && k<=limit ) { firstTime=1; _gen(" && "); }
796                 on1line++;
797                 if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
798         }
799         return max_k;
800 }
801
802 /*
803  * Generate code for any type of block.  If the last alternative in the block is
804  * empty (not even an action) don't bother doing it.  This permits us to handle
805  * optional and loop blocks as well.
806  *
807  * Only do this block, return after completing the block.
808  * This routine is visible only to this file and cannot answer a TRANS message.
809  */
810 static set
811 #ifdef __USE_PROTOS
812 genBlk( Junction *q, int jtype, int *max_k, int *need_right_curly )
813 #else
814 genBlk( q, jtype, max_k, need_right_curly )
815 Junction *q;
816 int jtype;
817 int *max_k;
818 int *need_right_curly;
819 #endif
820 {
821         set f;
822         Junction *alt;
823         int a_guess_in_block = 0;
824         require(q!=NULL,                                "genBlk: invalid node");
825         require(q->ntype == nJunction,  "genBlk: not junction");
826
827         *need_right_curly=0;
828         if ( q->p2 == NULL )    /* only one alternative?  Then don't need if */
829         {       
830                 if ( first_item_is_guess_block((Junction *)q->p1)!=NULL )
831                 {
832                         warnFL("(...)? as only alternative of block is unnecessary", FileStr[q->file], q->line);
833                         gen("zzGUESS\n");       /* guess anyway to make output code consistent */
834                         gen("if ( !zzrv )\n");
835                 }
836                 TRANS(q->p1);
837                 return empty;           /* no decision to be made-->no error set */
838         }
839
840         f = First(q, 1, jtype, max_k);
841         for (alt=q; alt != NULL; alt= (Junction *) alt->p2 )
842         {
843                 if ( alt->p2 == NULL )                                  /* chk for empty alt */
844                 {       
845                         Node *p = alt->p1;
846                         if ( p->ntype == nJunction )
847                         {
848                                 /* we have empty alt */
849                                 if ( ((Junction *)p)->p1 == (Node *)q->end )
850                                 {
851                                         break;                                          /* don't do this one, quit */
852                                 }
853                         }
854                 }
855                 if ( alt != q ) gen("else ")
856                 else
857                 {
858                         if ( DemandLookahead )
859                                 if ( !GenCC ) {gen1("LOOK(%d);\n", *max_k);}
860                                 else gen1("look(%d);\n", *max_k);
861                 }
862                 if ( alt!=q )
863                 {
864                         _gen("{\n");
865                         tabs++;
866                         (*need_right_curly)++;
867                         /* code to restore state if a prev alt didn't follow guess */
868                         if ( a_guess_in_block )
869                                 if ( !GenCC ) {gen("if ( zzguessing ) zzGUESS_DONE;\n");}
870                                 else gen("if ( !zzrv ) zzGUESS_DONE;\n");
871                 }
872                 if ( first_item_is_guess_block((Junction *)alt->p1)!=NULL )
873                 {
874                         a_guess_in_block = 1;
875                         gen("zzGUESS\n");
876                 }
877                 gen("if ( ");
878                 if ( first_item_is_guess_block((Junction *)alt->p1)!=NULL ) _gen("!zzrv && ");
879                 genExpr(alt);
880                 _gen(" ) ");
881                 _gen("{\n");
882                 tabs++;
883                 TRANS(alt->p1);
884                 --tabs;
885                 gen("}\n");
886         }
887         return f;
888 }
889
890 static int
891 #ifdef __USE_PROTOS
892 has_guess_block_as_first_item( Junction *q )
893 #else
894 has_guess_block_as_first_item( q )
895 Junction *q;
896 #endif
897 {
898         Junction *alt;
899
900         for (alt=q; alt != NULL; alt= (Junction *) alt->p2 )
901         {
902                 if ( first_item_is_guess_block((Junction *)alt->p1)!=NULL ) return 1;
903         }
904         return 0;
905 }
906
907 /* return NULL if 1st item of alt is (...)? block; else return ptr  
908 to aSubBlk node
909  * of (...)?;  This function ignores actions and predicates.
910  */
911 Junction *
912 #ifdef __USE_PROTOS
913 first_item_is_guess_block( Junction *q )
914 #else
915 first_item_is_guess_block( q )
916 Junction *q;
917 #endif
918 {
919         while ( q!=NULL && ((q->ntype==nJunction && q->jtype==Generic) || q->ntype==nAction) )
920         {
921                 if ( q->ntype==nJunction ) q = (Junction *)q->p1;
922                 else q = (Junction *) ((ActionNode *)q)->next;
923         }
924
925         if ( q==NULL ) return NULL;
926         if ( q->ntype!=nJunction ) return NULL;
927         if ( q->jtype!=aSubBlk ) return NULL;
928         if ( !q->guess ) return NULL;
929         return q;
930 }
931
932 /* Generate an action.  Don't if action is NULL which means that it was already
933  * handled as an init action.
934  */
935 void
936 #ifdef __USE_PROTOS
937 genAction( ActionNode *p )
938 #else
939 genAction( p )
940 ActionNode *p;
941 #endif
942 {
943         require(p!=NULL,                        "genAction: invalid node and/or rule");
944         require(p->ntype==nAction,      "genAction: not action");
945         
946         if ( !p->done )
947         {
948                 if ( p->is_predicate )
949                 {
950                         if ( p->guardpred!=NULL )
951                         {
952                                 gen("if (!");
953                                 genPredTreeMain(p->guardpred, (Node *)p);
954                         }
955                         else
956                         {
957                                 gen("if (!(");
958                                 /* make sure that '#line n' is on front of line */
959                                 if ( GenLineInfo && p->file != -1 ) _gen("\n");
960                                 dumpAction(p->action, output, 0, p->file, p->line, 0);
961                                 _gen(")");
962                         }
963                         if ( p->pred_fail != NULL )
964                         {
965                                 _gen(")\n");
966                                 tabs++;
967                                 gen1("%s;\n", p->pred_fail);
968                                 tabs--;
969                         }
970                         else _gen1(") {zzfailed_pred(\"%s\");}\n",p->action);
971                 }
972                 else
973                 {
974                         if ( FoundGuessBlk )
975                                 if ( GenCC ) {gen("if ( !guessing ) {\n");}
976                                 else gen("zzNON_GUESS_MODE {\n");
977                         dumpAction(p->action, output, tabs, p->file, p->line, 1);
978                         if ( FoundGuessBlk ) gen("}\n");
979                 }
980         }
981         TRANS(p->next)
982 }
983
984 /*
985  *              if invoking rule has !noAST pass zzSTR to rule ref and zzlink it in
986  *              else pass addr of temp root ptr (&_ast) (don't zzlink it in).
987  *
988  *              if ! modifies rule-ref, then never link it in and never pass zzSTR.
989  *              Always pass address of temp root ptr.
990  */
991 void
992 #ifdef __USE_PROTOS
993 genRuleRef( RuleRefNode *p )
994 #else
995 genRuleRef( p )
996 RuleRefNode *p;
997 #endif
998 {
999         Junction *q;
1000         char *handler_id = "";
1001         RuleEntry *r, *r2;
1002         char *parm = "", *exsig = "";
1003         require(p!=NULL,                        "genRuleRef: invalid node and/or rule");
1004         require(p->ntype==nRuleRef, "genRuleRef: not rule reference");
1005         
1006         if ( p->altstart!=NULL && p->altstart->exception_label!=NULL )
1007                 handler_id = p->altstart->exception_label;
1008
1009         r = (RuleEntry *) hash_get(Rname, p->text);
1010         if ( r == NULL )
1011         {
1012                 warnFL( eMsg1("rule %s not defined",
1013                                           p->text), FileStr[p->file], p->line );
1014                 return;
1015         }
1016         r2 = (RuleEntry *) hash_get(Rname, p->rname);
1017         if ( r2 == NULL ) {warnNoFL("Rule hash table is screwed up beyond belief"); return;}
1018
1019         if ( GenLineInfo ) fprintf(output, LineInfoFormatStr, p->line, FileStr[p->file]);
1020
1021         if ( GenCC && GenAST ) {
1022                 gen("_ast = NULL;\n");
1023         }
1024
1025         if ( FoundGuessBlk && p->assign!=NULL )
1026                 if ( GenCC ) {gen("if ( !guessing ) {\n");}
1027                 else gen("zzNON_GUESS_MODE {\n");
1028
1029         if ( FoundException ) exsig = "&_signal";
1030
1031         tab();
1032         if ( GenAST )
1033         {
1034                 if ( GenCC ) {
1035 /*                      if ( r2->noAST || p->astnode==ASTexclude )
1036 */
1037                         {
1038 /*                              _gen("_ast = NULL;\n");*/
1039                                 parm = "&_ast";
1040                         }
1041 /* we always want to set just a pointer now, then set correct  
1042 pointer after
1043
1044                         else {
1045                                 _gen("_astp =  
1046 (_tail==NULL)?(&_sibling):(&(_tail->_right));\n");
1047                                 parm = "_astp";
1048                         }
1049 */
1050                 }
1051                 else {
1052                         if ( r2->noAST || p->astnode==ASTexclude )
1053                         {
1054                                 _gen("_ast = NULL; ");
1055                                 parm = "&_ast";
1056                         }
1057                         else parm = "zzSTR";
1058                 }
1059                 if ( p->assign!=NULL )
1060                 {
1061                         if ( !HasComma(p->assign) ) {_gen1("%s = ",p->assign);}
1062                         else _gen1("{ struct _rv%d _trv; _trv = ", r->rulenum);
1063                 }
1064                 if ( FoundException ) {
1065                         _gen5("%s%s(%s,&_signal%s%s); ",
1066                                   RulePrefix,
1067                                   p->text,
1068                                   parm,
1069                                   (p->parms!=NULL)?",":"",
1070                                   (p->parms!=NULL)?p->parms:"");
1071                         if ( p->ex_group!=NULL ) {
1072                                 _gen("\n");
1073                                 gen("if (_signal) {\n");
1074                                 tabs++;
1075                                 dumpException(p->ex_group, 0);
1076                                 tabs--;
1077                                 gen("}");
1078                         }
1079                         else {
1080                                 _gen1("if (_signal) goto %s_handler;", handler_id);
1081                         }
1082                 }
1083                 else {
1084                         _gen5("%s%s(%s%s%s);",
1085                                   RulePrefix,
1086                                   p->text,
1087                                   parm,
1088                                   (p->parms!=NULL)?",":"",
1089                                   (p->parms!=NULL)?p->parms:"");
1090                 }
1091                 if ( GenCC && (r2->noAST || p->astnode==ASTexclude) )
1092                 {
1093                         /* rule has a ! or element does */
1094                         /* still need to assign to #i so we can play with it */
1095                         _gen("\n");
1096                         gen2("_ast%d%d = (AST *)_ast;", BlkLevel-1, p->elnum);
1097                 }
1098                 else if ( !r2->noAST && p->astnode == ASTinclude )
1099                 {
1100                         /* rule doesn't have a ! and neither does element */
1101                         if ( GenCC ) {
1102                                 _gen("\n");
1103                                 gen("if ( _tail==NULL ) _sibling = _ast; else _tail->setRight(_ast);\n");
1104                                 gen2("_ast%d%d = (AST *)_ast;\n", BlkLevel-1, p->elnum);
1105                                 tab();
1106                         }
1107                         else _gen(" ");
1108                         if ( GenCC ) {_gen("ASTBase::");} else _gen("zz");
1109                         _gen("link(_root, &_sibling, &_tail);");
1110                 }
1111         }
1112         else
1113         {
1114                 if ( p->assign!=NULL )
1115                 {
1116                         if ( !HasComma(p->assign) ) {_gen1("%s = ",p->assign);}
1117                         else _gen1("{ struct _rv%d _trv; _trv = ", r->rulenum);
1118                 }
1119                 if ( FoundException ) {
1120                         _gen4("%s%s(&_signal%s%s); ",
1121                                   RulePrefix,
1122                                   p->text,
1123                                   (p->parms!=NULL)?",":"",
1124                                   (p->parms!=NULL)?p->parms:"");
1125                         if ( p->ex_group!=NULL ) {
1126                                 _gen("\n");
1127                                 gen("if (_signal) {\n");
1128                                 tabs++;
1129                                 dumpException(p->ex_group, 0);
1130                                 tabs--;
1131                                 gen("}");
1132                         }
1133                         else {
1134                                 _gen1("if (_signal) goto %s_handler;", handler_id);
1135                         }
1136                 }
1137                 else {
1138                         _gen3("%s%s(%s);",
1139                                   RulePrefix,
1140                                   p->text,
1141                                   (p->parms!=NULL)?p->parms:"");
1142                 }
1143                 if ( p->assign!=NULL ) _gen("\n");
1144         }
1145         q = RulePtr[r->rulenum];        /* find definition of ref'd rule */
1146         if ( p->assign!=NULL ) {
1147                 if ( HasComma(p->assign) )
1148                 {
1149                         _gen("\n");
1150                         dumpRetValAssign(p->assign, q->ret);
1151                         _gen("}");
1152                 }
1153         }
1154         _gen("\n");
1155
1156         /* Handle element labels now */
1157         if ( p->el_label!=NULL )
1158         {
1159                 if ( GenAST )
1160                 {
1161                         if ( GenCC ) {
1162                                 gen3("%s_ast = _ast%d%d;\n", p->el_label, BlkLevel-1, p->elnum);
1163                         }
1164                         else {gen1("%s_ast = zzastCur;\n", p->el_label);}
1165                 }
1166         else if (!GenCC ) {
1167                         gen1("%s = zzaCur;\n", p->el_label);
1168         }
1169         }
1170
1171         if ( FoundGuessBlk && p->assign!=NULL ) {
1172                 /* in guessing mode, don't branch to handler upon error */
1173                 gen("} else {\n");
1174                 if ( FoundException ) {
1175                         gen6("%s%s(%s%s&_signal%s%s);\n",
1176                                  RulePrefix,
1177                                  p->text,
1178                                  parm,
1179                  (*parm!='\0')?",":"",
1180                  (p->parms!=NULL)?",":"",
1181                                  (p->parms!=NULL)?p->parms:"");
1182                 }
1183                 else {
1184                         gen5("%s%s(%s%s%s);\n",
1185                                  RulePrefix,
1186                                  p->text,
1187                                  parm,
1188                                  (p->parms!=NULL && *parm!='\0')?",":"",
1189                                  (p->parms!=NULL)?p->parms:"");
1190                 }
1191                 gen("}\n");
1192         }
1193         TRANS(p->next)
1194 }
1195
1196 /*
1197  * Generate code to match a token.
1198  *
1199  * Getting the next token is tricky.  We want to ensure that any action
1200  * following a token is executed before the next GetToken();
1201  */
1202 void
1203 #ifdef __USE_PROTOS
1204 genToken( TokNode *p )
1205 #else
1206 genToken( p )
1207 TokNode *p;
1208 #endif
1209 {
1210         RuleEntry *r;
1211         char *handler_id = "";
1212         ActionNode *a;
1213         char *set_name;
1214         require(p!=NULL,                        "genToken: invalid node and/or rule");
1215         require(p->ntype==nToken,       "genToken: not token");
1216         
1217         if ( p->altstart!=NULL && p->altstart->exception_label!=NULL )
1218                 handler_id = p->altstart->exception_label;
1219
1220         r = (RuleEntry *) hash_get(Rname, p->rname);
1221         if ( r == NULL ) {warnNoFL("Rule hash table is screwed up beyond belief"); return;}
1222
1223         if ( GenLineInfo ) fprintf(output, LineInfoFormatStr, p->line, FileStr[p->file]);
1224
1225         if ( !set_nil(p->tset) )        /* implies '.', ~Tok, or tokenclass */
1226         {
1227                 unsigned e;
1228                 set b;
1229                 b = set_dup(p->tset);
1230                 if ( p->tclass!=NULL )                  /* token class? */
1231                 {
1232                         static char buf[MaxRuleName+1];
1233                         if ( p->tclass->dumped )
1234                                 e = p->tclass->setnum;
1235                         else {
1236                                 e = DefErrSet(&b, 0, TokenString(p->token));
1237                                 p->tclass->dumped = 1;  /* indicate set has been created */
1238                                 p->tclass->setnum = e;
1239                         }
1240                         sprintf(buf, "%s_set", TokenString(p->token));
1241                         set_name = buf;
1242                 }
1243                 else {                                  /* wild card to ~ operator */
1244                         static char buf[sizeof("zzerr")+10];
1245                         int n = DefErrSet( &b, 0, NULL );
1246                         if ( GenCC ) sprintf(buf, "err%d", n);
1247                         else sprintf(buf, "zzerr%d", n);
1248                         set_name = buf;
1249                 }
1250
1251                 if ( !FoundException )
1252                         {gen1("zzsetmatch(%s);", set_name);}
1253                 else if ( p->ex_group==NULL ) {
1254             if ( p->use_def_MT_handler )
1255                 gen3("zzsetmatch_wdfltsig(%s,(ANTLRTokenType)%d,%s);",
1256                      set_name,
1257                      p->token,
1258                      tokenFollowSet(p))
1259             else
1260                 gen2("zzsetmatch_wsig(%s, %s_handler);",
1261                      set_name,
1262                      handler_id);
1263                 }
1264                 else
1265                 {
1266                         gen1("if ( !_setmatch_wsig(%s) ) {\n", set_name);
1267                         tabs++;
1268                         gen("if ( guessing ) goto fail;\n");
1269                         gen("_signal=MismatchedToken;\n");
1270                         dumpException(p->ex_group, 0);
1271                         tabs--;
1272                         gen("}\n");
1273                 }
1274                 set_free(b);
1275         }
1276         else if ( TokenString(p->token)!=NULL )
1277         {
1278                 if ( FoundException ) {
1279                         if ( p->use_def_MT_handler )
1280                                 gen2("zzmatch_wdfltsig(%s,%s);",TokenString(p->token),tokenFollowSet(p))
1281                         else if ( p->ex_group==NULL )
1282                         {
1283                                 gen2("zzmatch_wsig(%s, %s_handler);",
1284                                          TokenString(p->token),
1285                                          handler_id);
1286                         }
1287                         else
1288                         {
1289                                 gen1("if ( !_match_wsig(%s) ) {\n", TokenString(p->token));
1290                                 tabs++;
1291                                 gen("if ( guessing ) goto fail;\n");
1292                                 gen("_signal=MismatchedToken;\n");
1293                                 dumpException(p->ex_group, 0);
1294                                 tabs--;
1295                                 gen("}\n");
1296                         }
1297                 }
1298                 else gen1("zzmatch(%s);", TokenString(p->token));
1299         }
1300         else {
1301         if ( FoundException ) {
1302             if ( p->use_def_MT_handler )
1303                                 gen2("zzmatch_wdfltsig((ANTLRTokenType)%d,%s);",
1304                                          p->token,tokenFollowSet(p))
1305             else
1306                 gen2("zzmatch_wsig(%d,%s_handler);",p->token,handler_id);
1307         }
1308                 else {gen1("zzmatch(%d);", p->token);}
1309         }
1310
1311         a = findImmedAction( p->next );
1312         /* generate the token labels */
1313         if ( GenCC && p->elnum>0 )
1314         {
1315                 /* If building trees in C++, always gen the LT() assigns */
1316                 if ( set_el(p->elnum, tokensRefdInBlock) || GenAST )
1317                 {
1318                         if ( FoundGuessBlk )
1319                         {
1320                                 gen("\n");
1321                                 if ( GenCC ) {gen("if ( !guessing ) {\n"); tab();}
1322                                 else {gen("zzNON_GUESS_MODE {\n"); tab();}
1323                         }
1324                         _gen2(" _t%d%d = (ANTLRTokenPtr)LT(1);\n", BlkLevel-1, p->elnum);
1325                         if ( FoundGuessBlk ) {gen("}\n");}
1326                 }
1327                 if ( LL_k>1 )
1328                         if ( !DemandLookahead ) _gen(" labase++;");
1329                 _gen("\n");
1330                 tab();
1331         }
1332         if ( GenAST )
1333         {
1334                 if ( FoundGuessBlk && !(p->astnode == ASTexclude || r->noAST) )
1335                 {
1336                         if ( GenCC ) {_gen("if ( !guessing ) {\n"); tab();}
1337                         else {_gen("zzNON_GUESS_MODE {\n"); tab();}
1338                 }
1339                 if ( !r->noAST )
1340                 {
1341                         if ( GenCC && !(p->astnode == ASTexclude || r->noAST) ) {
1342                                 _gen("\n");
1343                                 gen4("_ast%d%d = new AST(_t%d%d);\n", BlkLevel-1, p->elnum, BlkLevel-1, p->elnum);
1344                                 tab();
1345                         }
1346                         if ( GenCC && !(p->astnode == ASTexclude || r->noAST) )
1347                                 {_gen2("_ast%d%d->", BlkLevel-1, p->elnum);}
1348                         else _gen(" ");
1349                         if ( p->astnode==ASTchild ) {
1350                                 if ( !GenCC ) _gen("zz");
1351                                 _gen("subchild(_root, &_sibling, &_tail);");
1352                         }
1353                         else if ( p->astnode==ASTroot ) {
1354                                 if ( !GenCC ) _gen("zz");
1355                                 _gen("subroot(_root, &_sibling, &_tail);");
1356                         }
1357                         if ( GenCC && !(p->astnode == ASTexclude || r->noAST) ) {
1358                                 _gen("\n");
1359                                 tab();
1360                         }
1361                 }
1362                 else if ( !GenCC ) _gen(" zzastDPush;");
1363                 if ( FoundGuessBlk && !(p->astnode == ASTexclude || r->noAST) )
1364                         {_gen("}\n"); tab();}
1365         }
1366
1367         /* Handle element labels now */
1368         if ( p->el_label!=NULL )
1369         {
1370                 _gen("\n");
1371                 if ( FoundGuessBlk )
1372                 {
1373                         if ( GenCC ) {gen("if ( !guessing ) {\n"); tab();}
1374                         else {gen("zzNON_GUESS_MODE {\n"); tab();}
1375                 }
1376                 /* Do Attrib / Token ptr */
1377                 if ( GenCC ) {
1378                         if ( set_el(p->elnum, tokensRefdInBlock) || GenAST )
1379                                 {gen3("%s = _t%d%d;\n", p->el_label, BlkLevel-1, p->elnum);}
1380                         else
1381                         {
1382                                 gen1("%s = (ANTLRTokenPtr)LT(1);\n", p->el_label);
1383                         }
1384                 }
1385                 else {gen1("%s = zzaCur;\n", p->el_label);}
1386                 /* Do AST ptr */
1387                 if ( GenAST && !(p->astnode == ASTexclude || r->noAST) )
1388                 {
1389                         if ( GenCC ) {
1390                                 gen3("%s_ast = _ast%d%d;\n", p->el_label, BlkLevel-1, p->elnum);
1391                         }
1392                         else {gen1("%s_ast = zzastCur;\n", p->el_label);}
1393                 }
1394
1395                 if ( FoundGuessBlk ) {_gen("}\n"); tab();}
1396         }
1397
1398         /* Handle any actions immediately following action */
1399         if ( a != NULL )
1400         {
1401                 /* delay next token fetch until after action */
1402                 _gen("\n");
1403                 if ( a->is_predicate )
1404                 {
1405                         gen("if (!(");
1406                         dumpAction(a->action, output, 0, a->file, a->line, 0);
1407                         if ( a->pred_fail != NULL )
1408                         {
1409                                 _gen(")) {\n");
1410 /*                              if ( FoundGuessBlk )  
1411 gen("zzNON_GUESS_MODE {\n");*/
1412                                 tabs++;
1413                                 gen1("%s;\n", a->pred_fail);
1414                                 tabs--;
1415                                 gen("}\n");
1416 /*                              if ( FoundGuessBlk ) gen("}\n");*/
1417                         }
1418                         else _gen1(")) {zzfailed_pred(\"%s\");}\n",a->action);
1419                 }
1420                 else
1421                 {
1422                         if ( FoundGuessBlk )
1423                                 if ( GenCC ) {gen("if ( !guessing ) {\n");}
1424                                 else gen("zzNON_GUESS_MODE {\n");
1425                         dumpAction(a->action, output, tabs, a->file, a->line, 1);
1426                         if ( FoundGuessBlk ) gen("}\n");
1427                 }
1428                 a->done = 1;
1429                 if ( !DemandLookahead ) {
1430                         if ( GenCC ) {
1431                                 if ( FoundException && p->use_def_MT_handler ) gen("if (!_signal)");
1432                                 _gen(" consume();")
1433                 if ( FoundException && p->use_def_MT_handler )
1434                     _gen(" _signal=NoSignal;");
1435                 _gen("\n");
1436                         }
1437             else {
1438                 if ( FoundException && p->use_def_MT_handler ) _gen("if (!_signal)");
1439                                         _gen(" zzCONSUME;\n");
1440                 if ( FoundException && p->use_def_MT_handler ) _gen(" _signal=NoSignal;");
1441                 _gen("\n");
1442             }
1443                 }
1444                 else gen("\n");
1445                 TRANS( a->next );
1446         }
1447         else
1448         {
1449         if ( !DemandLookahead ) {
1450                         if ( GenCC ) {
1451                                 if (FoundException && p->use_def_MT_handler) _gen("if (!_signal)");
1452                                 _gen(" consume();")
1453                                 if (FoundException&&p->use_def_MT_handler) _gen(" _signal=NoSignal;");
1454                                 _gen("\n");
1455                         }
1456                         else {
1457                                 if (FoundException && p->use_def_MT_handler) _gen("if (!_signal)");
1458                                 _gen(" zzCONSUME;");
1459                                 if ( FoundException && p->use_def_MT_handler ) _gen(" _signal=NoSignal;");
1460                                 _gen("\n");
1461                         }
1462                 }
1463                 else _gen("\n");
1464                 TRANS(p->next);
1465         }
1466 }
1467
1468 void
1469 #ifdef __USE_PROTOS
1470 genOptBlk( Junction *q )
1471 #else
1472 genOptBlk( q )
1473 Junction *q;
1474 #endif
1475 {
1476         int max_k;
1477         set f;
1478         int need_right_curly;
1479         set savetkref;
1480         savetkref = tokensRefdInBlock;
1481         require(q!=NULL,                                "genOptBlk: invalid node and/or rule");
1482         require(q->ntype == nJunction,  "genOptBlk: not junction");
1483         require(q->jtype == aOptBlk,    "genOptBlk: not optional block");
1484
1485         if ( GenLineInfo ) fprintf(output, LineInfoFormatStr, q->line, FileStr[q->file]);
1486         BLOCK_Preamble(q);
1487         BlkLevel++;
1488         f = genBlk(q, aOptBlk, &max_k, &need_right_curly);
1489         set_free(f);
1490         freeBlkFsets(q);
1491         BlkLevel--;
1492     if ( first_item_is_guess_block((Junction *)q->p1)!=NULL )
1493         {
1494                 if ( !GenCC ) {gen("else if ( zzguessing ) zzGUESS_DONE;\n");}
1495                 else gen("else if ( !zzrv ) zzGUESS_DONE;\n");
1496         }
1497         { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
1498         BLOCK_Tail();
1499         tokensRefdInBlock = savetkref;
1500         if (q->end->p1 != NULL) TRANS(q->end->p1);
1501 }
1502
1503 /*
1504  * Generate code for a loop blk of form:
1505  *
1506  *                               |---|
1507  *                               v   |
1508  *                         --o-G-o-->o--
1509  */
1510 void
1511 #ifdef __USE_PROTOS
1512 genLoopBlk( Junction *begin, Junction *q, Junction *start, int max_k )
1513 #else
1514 genLoopBlk( begin, q, start, max_k )
1515 Junction *begin;
1516 Junction *q;
1517 Junction *start;        /* where to start generating code from */
1518 int max_k;
1519 #endif
1520 {
1521         set f;
1522         int need_right_curly;
1523         set savetkref;
1524         savetkref = tokensRefdInBlock;
1525         require(q->ntype == nJunction,  "genLoopBlk: not junction");
1526         require(q->jtype == aLoopBlk,   "genLoopBlk: not loop block");
1527
1528         if ( q->visited ) return;
1529         q->visited = TRUE;
1530         if ( q->p2 == NULL )    /* only one alternative? */
1531         {
1532                 if ( DemandLookahead )
1533                         if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}
1534                         else gen1("look(%d);\n", max_k);
1535                 gen("while ( ");
1536                 if ( begin!=NULL ) genExpr(begin);
1537                 else genExpr(q);
1538                 /* if no predicates have been hoisted for this single alt (..)*
1539                  * do so now
1540                  */
1541                 if ( ParseWithPredicates && begin->predicate==NULL )
1542                 {
1543                         Predicate *a = find_predicates((Node *)q->p1);
1544                         if ( a!=NULL )
1545                         {
1546                                 _gen("&&");
1547                                 genPredTreeMain(a, (Node *)q);
1548                         }
1549                 }
1550                 _gen(" ) {\n");
1551                 tabs++;
1552                 TRANS(q->p1);
1553                 if ( !GenCC ) gen1("zzLOOP(zztasp%d);\n", BlkLevel-1);
1554                 if ( DemandLookahead )
1555                         if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}
1556                         else gen1("look(%d);\n", max_k);
1557                 --tabs;
1558                 gen("}\n");
1559                 freeBlkFsets(q);
1560                 q->visited = FALSE;
1561                 tokensRefdInBlock = savetkref;
1562                 return;
1563         }
1564         gen("while ( 1 ) {\n");
1565         tabs++;
1566         if ( begin!=NULL )
1567         {
1568                 if ( DemandLookahead )
1569                 {
1570                         if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}
1571                         else gen1("look(%d);\n", max_k);
1572                 }
1573                 /* The bypass arc of the (...)* predicts what to do when you fail, but
1574                  * ONLY after having tested the loop start expression.  To avoid this,
1575                  * we simply break out of the (...)* loop when we find something that
1576                  * is not in the prediction of the loop (all alts thereof).
1577                  */
1578                 gen("if ( !(");
1579
1580 /*      TJP says: It used to use the prediction expression for the bypass arc
1581         of the (...)*.  HOWEVER, if a non LL^1(k) decision was found, this
1582         thing would miss the ftree stored in the aLoopBegin node and generate
1583         an LL^1(k) decision anyway.
1584
1585                 genExpr((Junction *)begin->p2);
1586  */
1587
1588                 genExpr((Junction *)begin);
1589                 _gen(")) break;\n");
1590         }
1591         f = genBlk(q, aLoopBlk, &max_k, &need_right_curly);
1592         set_free(f);
1593         freeBlkFsets(q);
1594
1595         /* generate code for terminating loop (this is optional branch) */
1596         if ( begin==NULL ) gen("else break;\n"); /* code for exiting loop "for sure" */
1597
1598         { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
1599         if ( !GenCC ) gen1("zzLOOP(zztasp%d);\n", BlkLevel-1);
1600         --tabs;
1601         gen("}\n");
1602         q->visited = FALSE;
1603         tokensRefdInBlock = savetkref;
1604 }
1605
1606 /*
1607  * Generate code for a loop blk of form:
1608  *
1609  *                                       |---|
1610  *                                           v   |
1611  *                         --o-->o-->o-G-o-->o--
1612  *                   |           ^
1613  *                   v           |
1614  *                                       o-----------o
1615  *
1616  * q->end points to the last node (far right) in the blk.  Note  
1617 that q->end->jtype
1618  * must be 'EndBlk'.
1619  *
1620  * Generate code roughly of the following form:
1621  *
1622  *      do {
1623  *              ... code for alternatives ...
1624  *  } while ( First Set of aLoopBlk );
1625  *
1626  *      OR if > 1 alternative
1627  *
1628  *      do {
1629  *              ... code for alternatives ...
1630  *              else break;
1631  *  } while ( 1 );
1632  */
1633 void
1634 #ifdef __USE_PROTOS
1635 genLoopBegin( Junction *q )
1636 #else
1637 genLoopBegin( q )
1638 Junction *q;
1639 #endif
1640 {
1641         set f;
1642         int i;
1643         int max_k;
1644         set savetkref;
1645         savetkref = tokensRefdInBlock;
1646         require(q!=NULL,                                "genLoopBegin: invalid node and/or rule");
1647         require(q->ntype == nJunction,  "genLoopBegin: not junction");
1648         require(q->jtype == aLoopBegin, "genLoopBegin: not loop block");
1649         require(q->p2!=NULL,                    "genLoopBegin: invalid Loop Graph");
1650
1651         if ( GenLineInfo ) fprintf(output, LineInfoFormatStr, q->line, FileStr[q->file]);
1652
1653         BLOCK_Preamble(q);
1654         BlkLevel++;
1655         f = First(q, 1, aLoopBegin, &max_k);
1656         /* If not simple LL(1), must specify to start at LoopBegin, not LoopBlk */
1657         if ( LL_k>1 && !set_nil(q->fset[2]) )
1658                 genLoopBlk( q, (Junction *)q->p1, q, max_k );
1659         else genLoopBlk( q, (Junction *)q->p1, NULL, max_k );
1660
1661         for (i=1; i<=CLL_k; i++) set_free(q->fset[i]);
1662         for (i=1; i<=CLL_k; i++) set_free(((Junction *)q->p2)->fset[i]);
1663         --BlkLevel;
1664         BLOCK_Tail();
1665         set_free(f);
1666         tokensRefdInBlock = savetkref;
1667         if (q->end->p1 != NULL) TRANS(q->end->p1);
1668 }
1669
1670 /*
1671  * Generate code for a loop blk of form:
1672  *
1673  *                                       |---|
1674  *                                       v   |
1675  *                             --o-G-o-->o--
1676  *
1677  * q->end points to the last node (far right) in the blk.
1678  * Note that q->end->jtype must be 'EndBlk'.
1679  *
1680  * Generate code roughly of the following form:
1681  *
1682  *      do {
1683  *              ... code for alternatives ...
1684  *  } while ( First Set of aPlusBlk );
1685  *
1686  *      OR if > 1 alternative
1687  *
1688  *      do {
1689  *              ... code for alternatives ...
1690  *              else if not 1st time through, break;
1691  *  } while ( 1 );
1692  */
1693 void
1694 #ifdef __USE_PROTOS
1695 genPlusBlk( Junction *q )
1696 #else
1697 genPlusBlk( q )
1698 Junction *q;
1699 #endif
1700 {
1701         int max_k;
1702         set f;
1703         int need_right_curly;
1704         set savetkref;
1705         savetkref = tokensRefdInBlock;
1706         require(q!=NULL,                                "genPlusBlk: invalid node and/or rule");
1707         require(q->ntype == nJunction,  "genPlusBlk: not junction");
1708         require(q->jtype == aPlusBlk,   "genPlusBlk: not Plus block");
1709         require(q->p2 != NULL,                  "genPlusBlk: not a valid Plus block");
1710
1711         if ( q->visited ) return;
1712         q->visited = TRUE;
1713         if ( GenLineInfo ) fprintf(output, LineInfoFormatStr, q->line, FileStr[q->file]);
1714         BLOCK_Preamble(q);
1715         BlkLevel++;
1716         /* if the ignore flag is set on the 2nd alt and that alt is empty,
1717          * then it is the implied optional alternative that we added for (...)+
1718          * and, hence, only 1 alt.
1719          */
1720         if ( ((Junction *)q->p2)->p2 == NULL &&
1721                  ((Junction *)q->p2)->ignore )                  /* only one alternative? */
1722         {
1723                 Predicate *a=NULL;
1724                 /* if the only alt has a semantic predicate, hoist it; must test before
1725                  * entering loop.
1726                  */
1727                 if ( ParseWithPredicates )
1728                 {
1729                         a = find_predicates((Node *)q);
1730                         if ( a!=NULL ) {
1731                                 gen("if (");
1732                                 genPredTreeMain(a, (Node *)q);
1733                                 _gen(") {\n");
1734                         }
1735                 }
1736                 gen("do {\n");
1737                 tabs++;
1738                 TRANS(q->p1);
1739                 if ( !GenCC ) gen1("zzLOOP(zztasp%d);\n", BlkLevel-1);
1740                 f = First(q, 1, aPlusBlk, &max_k);
1741                 if ( DemandLookahead )
1742                         if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}
1743                         else gen1("look(%d);\n", max_k);
1744                 --tabs;
1745                 gen("} while ( ");
1746                 if ( q->parm!=NULL && q->predparm ) _gen1("(%s) && ", q->parm);
1747                 genExpr(q);
1748                 if ( ParseWithPredicates && a!=NULL )
1749                 {
1750                         _gen("&&");
1751                         genPredTreeMain(a, (Node *)q);
1752                 }
1753                 _gen(" );\n");
1754                 if ( ParseWithPredicates && a!=NULL ) gen("}\n");
1755                 --BlkLevel;
1756                 BLOCK_Tail();
1757                 q->visited = FALSE;
1758                 freeBlkFsets(q);
1759                 set_free(f);
1760                 tokensRefdInBlock = savetkref;
1761                 if (q->end->p1 != NULL) TRANS(q->end->p1);
1762                 return;
1763         }
1764         gen("do {\n");
1765         tabs++;
1766         f = genBlk(q, aPlusBlk, &max_k, &need_right_curly);
1767         gen("else if ( zzcnt>1 ) break; /* implied exit branch */\n");/* code for exiting loop */
1768         tab();
1769         makeErrorClause(q,f,max_k);
1770         { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
1771         freeBlkFsets(q);
1772         gen("zzcnt++;");
1773         if ( !GenCC ) _gen1(" zzLOOP(zztasp%d);", BlkLevel-1);
1774         _gen("\n");
1775         if ( DemandLookahead )
1776                 if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}
1777                 else gen1("look(%d);\n", max_k);
1778         --tabs;
1779         if ( q->parm!=NULL && q->predparm ) {gen1("} while (%s);\n", q->parm);}
1780         else gen("} while ( 1 );\n");
1781         --BlkLevel;
1782         BLOCK_Tail();
1783         q->visited = FALSE;
1784         tokensRefdInBlock = savetkref;
1785         if (q->end->p1 != NULL) TRANS(q->end->p1);
1786 }
1787
1788 /*
1789  * Generate code for a sub blk of alternatives of form:
1790  *
1791  *                             --o-G1--o--
1792  *                                       |     ^
1793  *                                       v    /|
1794  *                               o-G2-o|
1795  *                                       |     ^
1796  *                                       v     |
1797  *                                 ..........
1798  *                                       |     ^
1799  *                                       v    /
1800  *                               o-Gn-o
1801  *
1802  * q points to the 1st junction of blk (upper-left).
1803  * q->end points to the last node (far right) in the blk.
1804  * Note that q->end->jtype must be 'EndBlk'.
1805  * The last node in every alt points to q->end.
1806  *
1807  * Generate code of the following form:
1808  *      if ( First(G1) ) {
1809  *              ...code for G1...
1810  *      }
1811  *      else if ( First(G2) ) {
1812  *              ...code for G2...
1813  *      }
1814  *      ...
1815  *      else {
1816  *              ...code for Gn...
1817  *      }
1818  */
1819 void
1820 #ifdef __USE_PROTOS
1821 genSubBlk( Junction *q )
1822 #else
1823 genSubBlk( q )
1824 Junction *q;
1825 #endif
1826 {
1827         int max_k;
1828         set f;
1829         int need_right_curly;
1830         set savetkref;
1831         savetkref = tokensRefdInBlock;
1832         require(q->ntype == nJunction,  "genSubBlk: not junction");
1833         require(q->jtype == aSubBlk,    "genSubBlk: not subblock");
1834
1835         if ( GenLineInfo ) fprintf(output, LineInfoFormatStr, q->line, FileStr[q->file]);
1836         BLOCK_Preamble(q);
1837         BlkLevel++;
1838         f = genBlk(q, aSubBlk, &max_k, &need_right_curly);
1839         if ( q->p2 != NULL ) {tab(); makeErrorClause(q,f,max_k);}
1840         { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
1841         freeBlkFsets(q);
1842         --BlkLevel;
1843         BLOCK_Tail();
1844
1845         if ( q->guess )
1846         {
1847                 gen("zzGUESS_DONE\n");
1848         }
1849
1850         /* must duplicate if (alpha)?; one guesses (validates), the
1851          * second pass matches */
1852         if ( q->guess && analysis_point(q)==q )
1853         {
1854                 if ( GenLineInfo ) fprintf(output, LineInfoFormatStr, q->line, FileStr[q->file]);
1855                 BLOCK_Preamble(q);
1856                 BlkLevel++;
1857                 f = genBlk(q, aSubBlk, &max_k, &need_right_curly);
1858                 if ( q->p2 != NULL ) {tab(); makeErrorClause(q,f,max_k);}
1859                 { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
1860                 freeBlkFsets(q);
1861                 --BlkLevel;
1862                 BLOCK_Tail();
1863         }
1864
1865         tokensRefdInBlock = savetkref;
1866         if (q->end->p1 != NULL) TRANS(q->end->p1);
1867 }
1868
1869 /*
1870  * Generate code for a rule.
1871  *
1872  *              rule--> o-->o-Alternatives-o-->o
1873  * Or,
1874  *              rule--> o-->o-Alternative-o-->o
1875  *
1876  * The 1st junction is a RuleBlk.  The second can be a SubBlk or just a junction
1877  * (one alternative--no block), the last is EndRule.
1878  * The second to last is EndBlk if more than one alternative exists in the rule.
1879  *
1880  * To get to the init-action for a rule, we must bypass the RuleBlk,
1881  * and possible SubBlk.
1882  * Mark any init-action as generated so genBlk() does not regenerate it.
1883  */
1884 void
1885 #ifdef __USE_PROTOS
1886 genRule( Junction *q )
1887 #else
1888 genRule( q )
1889 Junction *q;
1890 #endif
1891 {
1892         int max_k;
1893         set follow, rk, f;
1894         ActionNode *a;
1895         RuleEntry *r;
1896         static int file = -1;
1897         int need_right_curly;
1898         require(q->ntype == nJunction,  "genRule: not junction");
1899         require(q->jtype == RuleBlk,    "genRule: not rule");
1900
1901         r = (RuleEntry *) hash_get(Rname, q->rname);
1902         if ( r == NULL ) warnNoFL("Rule hash table is screwed up beyond belief");
1903         if ( q->file != file )          /* open new output file if need to */
1904         {
1905                 if ( output != NULL ) fclose( output );
1906                 output = fopen(OutMetaName(outname(FileStr[q->file])), "w");
1907                 require(output != NULL, "genRule: can't open output file");
1908
1909                 special_fopen_actions(OutMetaName(outname(FileStr[q->file])));
1910
1911                 if ( file == -1 ) genHdr1(q->file);
1912                 else genHdr(q->file);
1913                 file = q->file;
1914         }
1915         DumpFuncHeader(q,r);
1916         tabs++;
1917         if ( q->ret!=NULL )
1918         {
1919                 /* Declare the return value - and PURIFY it -ATG 6/5/95 */
1920                 if ( HasComma(q->ret) )
1921                 {
1922                         gen1("struct _rv%d _retv;\n",r->rulenum);
1923                         gen1("PURIFY(_retv,sizeof(struct _rv%d))\n",r->rulenum);
1924                 }
1925                 else
1926                 {
1927                         tab();
1928                         DumpType(q->ret, output);
1929                         gen(" _retv;\n");
1930                         gen("PURIFY(_retv,sizeof(");
1931                         DumpType(q->ret, output);
1932                         gen("))\n");
1933                 }
1934         }
1935
1936         if ( GenLineInfo )
1937         {
1938                 fprintf(output, LineInfoFormatStr, q->line, FileStr[q->file]);
1939         }
1940
1941         gen("zzRULE;\n");
1942         if ( FoundException )
1943         {
1944                 gen("int _sva=1;\n");
1945         }
1946         if ( GenCC && GenAST )
1947                 gen("ASTBase **_astp, *_ast = NULL, *_sibling = NULL, *_tail = NULL;\n");
1948         if ( GenCC ) genTokenPointers(q);
1949         if ( GenCC&&GenAST ) genASTPointers(q);
1950         if ( q->el_labels!=NULL ) genElementLabels(q->el_labels);
1951         if ( FoundException ) gen("int _signal=NoSignal;\n");
1952         if ( !GenCC ) gen1("zzBLOCK(zztasp%d);\n", BlkLevel);
1953         if ( !GenCC ) gen("zzMake0;\n");
1954         if ( FoundException ) gen("*_retsignal = NoSignal;\n");
1955         if ( !GenCC ) gen("{\n");
1956
1957         if ( has_guess_block_as_first_item((Junction *)q->p1) )
1958         {
1959                 gen("zzGUESS_BLOCK\n");
1960         }
1961
1962         /* L o o k  F o r  I n i t  A c t i o n */
1963         if ( ((Junction *)q->p1)->jtype == aSubBlk )
1964                 a = findImmedAction( ((Junction *)q->p1)->p1 );
1965         else
1966                 a = findImmedAction( q->p1 );   /* only one alternative in rule */
1967         if ( a!=NULL && !a->is_predicate )
1968         {
1969                 dumpAction(a->action, output, tabs, a->file, a->line, 1);
1970                 a->done = 1;    /* ignore action. We have already handled it */
1971         }
1972         if ( TraceGen )
1973                 if ( GenCC ) {gen1("tracein(\"%s\");\n", q->rname);}
1974                 else gen1("zzTRACEIN((ANTLRChar *)\"%s\");\n", q->rname);
1975
1976         BlkLevel++;
1977         q->visited = TRUE;                              /* mark RULE as visited for FIRST/FOLLOW */
1978         f = genBlk((Junction *)q->p1, RuleBlk, &max_k, &need_right_curly);
1979         if ( q->p1 != NULL )
1980                 if ( ((Junction *)q->p1)->p2 != NULL )
1981                         {tab(); makeErrorClause((Junction *)q->p1,f,max_k);}
1982         { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
1983         freeBlkFsets((Junction *)q->p1);
1984         q->visited = FALSE;
1985         --BlkLevel;
1986         if ( !GenCC ) gen1("zzEXIT(zztasp%d);\n", BlkLevel);
1987
1988         if ( TraceGen )
1989                 if ( GenCC ) {gen1("traceout(\"%s\");\n", q->rname);}
1990                 else gen1("zzTRACEOUT((ANTLRChar *)\"%s\");\n", q->rname);
1991
1992         if ( q->ret!=NULL ) gen("return _retv;\n") else gen("return;\n");
1993         /* E r r o r  R e c o v e r y */
1994         NewSet();
1995         rk = empty;
1996         REACH(q->end, 1, &rk, follow);
1997         FillSet( follow );
1998         set_free( follow );
1999
2000         _gen("fail:\n");
2001         if ( !GenCC ) gen("zzEXIT(zztasp1);\n");
2002         if ( FoundGuessBlk )
2003                 if ( !GenCC ) {gen("if ( zzguessing ) zzGUESS_FAIL;\n");}
2004                 else gen("if ( guessing ) zzGUESS_FAIL;\n");
2005         if ( q->erraction!=NULL )
2006                 dumpAction(q->erraction, output, tabs, q->file, q->line, 1);
2007         if ( GenCC )
2008         {
2009                 gen1("syn(zzBadTok, %s, zzMissSet, zzMissTok, zzErrk);\n",
2010                          r->egroup==NULL?"(ANTLRChar *)\"\"":r->egroup);
2011         }
2012         else
2013         {
2014                 gen1("zzsyn(zzMissText, zzBadTok, %s, zzMissSet, zzMissTok, zzErrk, zzBadText);\n",
2015                          r->egroup==NULL?"(ANTLRChar *)\"\"":r->egroup);
2016         }
2017         gen3("%sresynch(setwd%d, 0x%x);\n", GenCC?"":"zz", wordnum, 1<<setnum);
2018
2019         if ( TraceGen )
2020                 if ( GenCC ) {gen1("traceout(\"%s\");\n", q->rname);}
2021                 else gen1("zzTRACEOUT((ANTLRChar *)\"%s\");\n", q->rname);
2022
2023         if ( q->ret!=NULL ) {gen("return _retv;\n");}
2024         else if ( q->exceptions!=NULL ) gen("return;\n");
2025         if ( !GenCC ) gen("}\n");
2026
2027         /* Gen code for exception handlers */
2028         if ( q->exceptions!=NULL )
2029         {
2030                 gen("/* exception handlers */\n");
2031                 dumpExceptions(q->exceptions);
2032         if ( !r->has_rule_exception )
2033         {
2034             _gen("_handler:\n");
2035             gen("zzdflthandlers(_signal,_retsignal);\n");
2036         }
2037                 _gen("_adios:\n");
2038                 if ( q->ret!=NULL ) {gen("return _retv;\n");}
2039                 else {gen("return;\n");}
2040         }
2041         else if ( FoundException )
2042         {
2043         _gen("_handler:\n");
2044         gen("zzdflthandlers(_signal,_retsignal);\n");
2045         }
2046
2047         tabs--;
2048         gen("}\n");
2049
2050         if ( q->p2 != NULL ) {TRANS(q->p2);} /* generate code for next rule too */
2051         else dumpAfterActions( output );
2052 }
2053
2054 static void
2055 #ifdef __USE_PROTOS
2056 DumpFuncHeader( Junction *q, RuleEntry *r )
2057 #else
2058 DumpFuncHeader( q, r )
2059 Junction *q;
2060 RuleEntry *r;
2061 #endif
2062 {
2063         /* A N S I */
2064         _gen("\n");
2065         if ( q->ret!=NULL )
2066         {
2067                 if ( HasComma(q->ret) )
2068                 {
2069                         if (GenCC) gen2("%s::_rv%d\n", CurrentClassName, r->rulenum)
2070                         else gen1("struct _rv%d\n",r->rulenum);
2071                 }
2072                 else
2073                 {
2074                         DumpType(q->ret, output);
2075                         gen("\n");
2076                 }
2077         }
2078         else
2079         {
2080                 _gen("void\n");
2081         }
2082         if ( !GenCC ) _gen("#ifdef __STDC__\n");
2083         if ( !GenCC ) gen2("%s%s(", RulePrefix, q->rname)
2084         else gen2("%s::%s(", CurrentClassName, q->rname);
2085         DumpANSIFunctionArgDef(output,q);
2086         _gen("\n");
2087
2088         if ( GenCC ) {gen("{\n"); return;}
2089
2090         /* K & R */
2091         gen("#else\n");
2092         gen2("%s%s(", RulePrefix, q->rname);
2093         if ( GenAST )
2094         {
2095                 _gen("_root");
2096                 if ( q->pdecl!=NULL ) _gen(",");
2097         }
2098         if ( FoundException )
2099         {
2100                 if ( GenAST ) _gen(",");
2101                 _gen("_retsignal");
2102                 if ( q->pdecl!=NULL ) _gen(",");
2103         }
2104
2105         DumpListOfParmNames( q->pdecl, output );
2106         gen(")\n");
2107         if ( GenAST ) gen("AST **_root;\n");
2108         if ( FoundException ) gen("int *_retsignal;\n");
2109         DumpOldStyleParms( q->pdecl, output );
2110         gen("#endif\n");
2111         gen("{\n");
2112 }
2113
2114 void
2115 #ifdef __USE_PROTOS
2116 DumpANSIFunctionArgDef(FILE *f, Junction *q)
2117 #else
2118 DumpANSIFunctionArgDef(f,q)
2119 FILE *f;
2120 Junction *q;
2121 #endif
2122 {
2123         if ( GenAST )
2124         {
2125                 if ( GenCC ) {fprintf(f,"ASTBase **_root");}
2126                 else fprintf(f,"AST**_root");
2127                 if ( !FoundException && q->pdecl!=NULL ) fprintf(f,",");
2128         }
2129         if ( FoundException )
2130         {
2131                 if ( GenAST ) fprintf(f,",");
2132                 fprintf(f,"int *_retsignal");
2133                 if ( q->pdecl!=NULL ) fprintf(f,",");
2134         }
2135         if ( q->pdecl!=NULL ) {fprintf(f,"%s", q->pdecl);}
2136         else if ( !GenAST && !FoundException ) fprintf(f,"void");
2137         fprintf(f,")");
2138 }
2139
2140 void
2141 #ifdef __USE_PROTOS
2142 genJunction( Junction *q )
2143 #else
2144 genJunction( q )
2145 Junction *q;
2146 #endif
2147 {
2148         require(q->ntype == nJunction,  "genJunction: not junction");
2149         require(q->jtype == Generic,    "genJunction: not generic junction");
2150
2151         if ( q->p1 != NULL ) TRANS(q->p1);
2152         if ( q->p2 != NULL ) TRANS(q->p2);
2153 }
2154
2155 void
2156 #ifdef __USE_PROTOS
2157 genEndBlk( Junction *q )
2158 #else
2159 genEndBlk( q )
2160 Junction *q;
2161 #endif
2162 {
2163 }
2164
2165 void
2166 #ifdef __USE_PROTOS
2167 genEndRule( Junction *q )
2168 #else
2169 genEndRule( q )
2170 Junction *q;
2171 #endif
2172 {
2173 }
2174
2175 void
2176 #ifdef __USE_PROTOS
2177 genHdr( int file )
2178 #else
2179 genHdr( file )
2180 int file;
2181 #endif
2182 {
2183         _gen("/*\n");
2184         _gen(" * A n t l r  T r a n s l a t i o n  H e a d e r\n");
2185         _gen(" *\n");
2186         _gen(" * Terence Parr, Will Cohen, and Hank Dietz: 1989-1994\n");
2187         _gen(" * Purdue University Electrical Engineering\n");
2188         _gen(" * With AHPCRC, University of Minnesota\n");
2189         _gen1(" * ANTLR Version %s\n", Version);
2190         _gen(" */\n");
2191         _gen("#include <stdio.h>\n");
2192         _gen1("#define ANTLR_VERSION    %s\n", VersionDef);
2193         if ( strcmp(ParserName, DefaultParserName)!=0 )
2194                 _gen2("#define %s %s\n", DefaultParserName, ParserName);
2195         if ( strcmp(ParserName, DefaultParserName)!=0 )
2196                 {_gen1("#include \"%s\"\n", RemapFileName);}
2197         if ( GenLineInfo ) _gen2(LineInfoFormatStr, 1, FileStr[file]);
2198         if ( GenCC ) {
2199                 if ( UserTokenDefsFile != NULL )
2200                         fprintf(output, "#include %s\n", UserTokenDefsFile);
2201                 else
2202                         fprintf(output, "#include \"%s\"\n", DefFileName);
2203         }
2204
2205         if ( HdrAction != NULL ) dumpAction( HdrAction, output, 0, -1, 0, 1);
2206         if ( !GenCC && FoundGuessBlk )
2207         {
2208                 _gen("#define ZZCAN_GUESS\n");
2209                 _gen("#include <setjmp.h>\n");
2210         }
2211         if ( FoundException )
2212         {
2213                 _gen("#define EXCEPTION_HANDLING\n");
2214                 _gen1("#define NUM_SIGNALS %d\n", NumSignals);
2215         }
2216         if ( !GenCC && OutputLL_k > 1 ) _gen1("#define LL_K %d\n", OutputLL_k);
2217         if ( GenAST&&!GenCC ) _gen("#define GENAST\n\n");
2218         if ( GenAST ) {
2219                 if ( GenCC ) {_gen1("#include \"%s\"\n\n", ASTBASE_H);}
2220                 else _gen("#include \"ast.h\"\n\n");
2221         }
2222         if ( !GenCC && DemandLookahead ) _gen("#define DEMAND_LOOK\n\n");
2223 #ifdef DUM
2224         if ( !GenCC && LexGen ) {
2225                 _gen1("#define zzEOF_TOKEN %d\n", (TokenInd!=NULL?TokenInd[EofToken]:EofToken));
2226         }
2227 #endif
2228         /* ###WARNING: This will have to change when SetWordSize changes */
2229         if ( !GenCC ) _gen1("#define zzSET_SIZE %d\n", NumWords(TokenNum-1)*sizeof(unsigned));
2230         if ( !GenCC ) {_gen("#include \"antlr.h\"\n");}
2231         else {
2232                 _gen1("#include \"%s\"\n", APARSER_H);
2233                 _gen1("#include \"%s.h\"\n", CurrentClassName);
2234         }
2235         if ( !GenCC ) {
2236                 if ( UserDefdTokens )
2237                         {_gen1("#include %s\n", UserTokenDefsFile);}
2238                 /* still need this one as it has the func prototypes */
2239                 _gen1("#include \"%s\"\n", DefFileName);
2240         }
2241         /* still need this one as it defines the DLG interface */
2242         if ( !GenCC ) _gen("#include \"dlgdef.h\"\n");
2243         if ( LexGen && GenCC ) _gen1("#include \"%s\"\n", DLEXERBASE_H);
2244         if ( GenCC ) _gen1("#include \"%s\"\n", ATOKPTR_H);
2245         if ( !GenCC && LexGen ) _gen1("#include \"%s\"\n", ModeFileName);
2246         _gen("#ifndef PURIFY\n#define PURIFY(r,s)\n#endif\n");
2247 }
2248
2249 void
2250 #ifdef __USE_PROTOS
2251 genHdr1( int file )
2252 #else
2253 genHdr1( file )
2254 int file;
2255 #endif
2256 {
2257         ListNode *p;
2258
2259         genHdr(file);
2260         if ( GenAST )
2261         {
2262                 if ( !GenCC ) {
2263                         _gen("#include \"ast.c\"\n");
2264                         _gen("zzASTgvars\n\n");
2265                 }
2266         }
2267         if ( !GenCC ) _gen("ANTLR_INFO\n");
2268         if ( BeforeActions != NULL )
2269         {
2270                 for (p = BeforeActions->next; p!=NULL; p=p->next)
2271                 {
2272                         UserAction *ua = (UserAction *)p->elem;
2273                         dumpAction( ua->action, output, 0, ua->file, ua->line, 1);
2274                 }
2275         }
2276
2277         if ( !FoundException ) return;
2278
2279         if ( GenCC )
2280         {
2281                 _gen1("\nvoid %s::\n", CurrentClassName);
2282                 _gen("zzdflthandlers( int _signal, int *_retsignal )\n");
2283                 _gen("{\n");
2284         }
2285         else
2286         {
2287                 _gen("\nvoid\n");
2288                 _gen("#ifdef __STDC__\n");
2289                 _gen("zzdflthandlers( int _signal, int *_retsignal )\n");
2290                 _gen("#else\n");
2291                 _gen("zzdflthandlers( _signal, _retsignal )\n");
2292                 _gen("int _signal;\n");
2293                 _gen("int *_retsignal;\n");
2294                 _gen("#endif\n");
2295                 _gen("{\n");
2296         }
2297         tabs++;
2298         if ( DefaultExGroup!=NULL )
2299         {
2300                 dumpException(DefaultExGroup, 1);
2301                 if ( !hasDefaultException(DefaultExGroup) )
2302                 {
2303                         gen("default :\n");
2304                         tabs++;
2305                         gen("*_retsignal = _signal;\n");
2306                         tabs--;
2307                         gen("}\n");
2308                 }
2309         }
2310         else {
2311                 gen("*_retsignal = _signal;\n");
2312         }
2313
2314         tabs--;
2315         _gen("}\n\n");
2316 }
2317
2318 void
2319 #ifdef __USE_PROTOS
2320 genStdPCCTSIncludeFile( FILE *f )
2321 #else
2322 genStdPCCTSIncludeFile( f )
2323 FILE *f;
2324 #endif
2325 {
2326         fprintf(f,"#ifndef STDPCCTS_H\n");
2327         fprintf(f,"#define STDPCCTS_H\n");
2328         fprintf(f,"/*\n");
2329         fprintf(f," * %s -- P C C T S  I n c l u d e\n", stdpccts);
2330         fprintf(f," *\n");
2331         fprintf(f," * Terence Parr, Will Cohen, and Hank Dietz: 1989-1994\n");
2332         fprintf(f," * Purdue University Electrical Engineering\n");
2333         fprintf(f," * With AHPCRC, University of Minnesota\n");
2334         fprintf(f," * ANTLR Version %s\n", Version);
2335         fprintf(f," */\n");
2336         fprintf(f,"#include <stdio.h>\n");
2337         fprintf(f,"#define ANTLR_VERSION        %s\n", VersionDef);
2338         if ( GenCC )
2339         {
2340                 if ( UserDefdTokens )
2341                         fprintf(f, "#include %s\n", UserTokenDefsFile);
2342                 else {
2343                         fprintf(f, "#include \"%s\"\n", DefFileName);
2344                 }
2345
2346                 fprintf(f, "#include \"%s\"\n", ATOKEN_H);
2347
2348                 if ( HdrAction != NULL ) dumpAction( HdrAction, f, 0, -1, 0, 1);
2349
2350                 fprintf(f, "#include \"%s\"\n", ATOKENBUFFER_H);
2351
2352                 if ( OutputLL_k > 1 ) fprintf(f,"static const unsigned LL_K=%d;\n", OutputLL_k);
2353                 if ( GenAST ) {
2354                         fprintf(f, "#include \"%s\"\n", ASTBASE_H);
2355                 }
2356                 fprintf(f,"#include \"%s\"\n", APARSER_H);
2357                 fprintf(f,"#include \"%s.h\"\n", CurrentClassName);
2358                 if ( LexGen ) fprintf(f,"#include \"%s\"\n", DLEXERBASE_H);
2359                 fprintf(f, "#endif\n");
2360                 return;
2361         }
2362
2363         if ( strcmp(ParserName, DefaultParserName)!=0 )
2364                 fprintf(f, "#define %s %s\n", DefaultParserName, ParserName);
2365         if ( strcmp(ParserName, DefaultParserName)!=0 )
2366                 fprintf(f, "#include \"%s\"\n", RemapFileName);
2367         if ( UserTokenDefsFile != NULL )
2368            fprintf(f, "#include %s\n", UserTokenDefsFile);
2369         if ( HdrAction != NULL ) dumpAction( HdrAction, f, 0, -1, 0, 1);
2370         if ( FoundGuessBlk )
2371         {
2372                 fprintf(f,"#define ZZCAN_GUESS\n");
2373                 fprintf(f,"#include <setjmp.h>\n");
2374         }
2375         if ( OutputLL_k > 1 ) fprintf(f,"#define LL_K %d\n", OutputLL_k);
2376         if ( GenAST ) fprintf(f,"#define GENAST\n");
2377         if ( FoundException )
2378         {
2379                 _gen("#define EXCEPTION_HANDLING\n");
2380                 _gen1("#define NUM_SIGNALS %d\n", NumSignals);
2381         }
2382         if ( DemandLookahead ) fprintf(f,"#define DEMAND_LOOK\n");
2383 #ifdef DUM
2384         if ( LexGen ) fprintf(f, "#define zzEOF_TOKEN %d\n", (TokenInd!=NULL?TokenInd[EofToken]:EofToken));
2385 #endif
2386         /* ###WARNING: This will have to change when SetWordSize changes */
2387         fprintf(f, "#define zzSET_SIZE %d\n", NumWords(TokenNum-1)*sizeof(unsigned));
2388         fprintf(f,"#include \"antlr.h\"\n");
2389         if ( GenAST ) fprintf(f,"#include \"ast.h\"\n");
2390         if ( UserDefdTokens )
2391                 fprintf(f, "#include %s\n", UserTokenDefsFile);
2392         /* still need this one as it has the func prototypes */
2393         fprintf(f, "#include \"%s\"\n", DefFileName);
2394         /* still need this one as it defines the DLG interface */
2395         fprintf(f,"#include \"dlgdef.h\"\n");
2396         /* don't need this one unless DLG is used */
2397         if ( LexGen ) fprintf(f,"#include \"%s\"\n", ModeFileName);
2398         fprintf(f,"#endif\n");
2399 }
2400
2401 /* dump action 's' to file 'output' starting at "local" tab 'tabs'
2402    Dump line information in front of action if GenLineInfo is set
2403    If file == -1 then GenLineInfo is ignored.
2404    The user may redefine the LineInfoFormatStr to his/her liking
2405    most compilers will like the default, however.
2406
2407    June '93; changed so that empty lines are left alone so that
2408    line information is correct for the compiler/debuggers.
2409 */
2410 void
2411 #ifdef __USE_PROTOS
2412 dumpAction( char *s, FILE *output, int tabs, int file, int line,  
2413 int final_newline )
2414 #else
2415 dumpAction( s, output, tabs, file, line, final_newline )
2416 char *s;
2417 FILE *output;
2418 int tabs;
2419 int file;
2420 int line;
2421 int final_newline;
2422 #endif
2423 {
2424     int inDQuote, inSQuote;
2425     require(s!=NULL,            "dumpAction: NULL action");
2426     require(output!=NULL,       eMsg1("dumpAction: output FILE is NULL for %s",s));
2427
2428         if ( GenLineInfo && file != -1 )
2429         {
2430                 fprintf(output, LineInfoFormatStr, line, FileStr[file]);
2431         }
2432     PastWhiteSpace( s );
2433         /* don't print a tab if first non-white char is a # (preprocessor command) */
2434         if ( *s!='#' ) {TAB;}
2435     inDQuote = inSQuote = FALSE;
2436     while ( *s != '\0' )
2437     {
2438         if ( *s == '\\' )
2439         {
2440             fputc( *s++, output ); /* Avoid '"' Case */
2441             if ( *s == '\0' ) return;
2442             if ( *s == '\'' ) fputc( *s++, output );
2443             if ( *s == '\"' ) fputc( *s++, output );
2444         }
2445         if ( *s == '\'' )
2446         {
2447             if ( !inDQuote ) inSQuote = !inSQuote;
2448         }
2449         if ( *s == '"' )
2450         {
2451             if ( !inSQuote ) inDQuote = !inDQuote;
2452         }
2453         if ( *s == '\n' )
2454         {
2455             fputc('\n', output);
2456                         s++;
2457             PastWhiteSpace( s );
2458             if ( *s == '}' )
2459             {
2460                 --tabs;
2461                                 TAB;
2462                 fputc( *s++, output );
2463                 continue;
2464             }
2465             if ( *s == '\0' ) return;
2466                         if ( *s != '#' )        /* #define, #endif etc.. start at col 1 */
2467             {
2468                                 TAB;
2469                         }
2470         }
2471         if ( *s == '}' && !(inSQuote || inDQuote) )
2472         {
2473             --tabs;            /* Indent one fewer */
2474         }
2475         if ( *s == '{' && !(inSQuote || inDQuote) )
2476         {
2477             tabs++;            /* Indent one more */
2478         }
2479         fputc( *s, output );
2480         s++;
2481     }
2482     if ( final_newline ) fputc('\n', output);
2483 }
2484
2485 static void
2486 #ifdef __USE_PROTOS
2487 dumpAfterActions( FILE *output )
2488 #else
2489 dumpAfterActions( output )
2490 FILE *output;
2491 #endif
2492 {
2493         ListNode *p;
2494         require(output!=NULL, "dumpAfterActions: output file was NULL for some reason");
2495         if ( AfterActions != NULL )
2496         {
2497                 for (p = AfterActions->next; p!=NULL; p=p->next)
2498                 {
2499                         UserAction *ua = (UserAction *)p->elem;
2500                         dumpAction( ua->action, output, 0, ua->file, ua->line, 1);
2501                 }
2502         }
2503         fclose( output );
2504 }
2505
2506 /*
2507  * Find the next action in the stream of execution.  Do not pass
2508  * junctions with more than one path leaving them.
2509  * Only pass generic junctions.
2510  *
2511  *      Scan forward while (generic junction with p2==NULL)
2512  *      If we stop on an action, return ptr to the action
2513  *      else return NULL;
2514  */
2515 static ActionNode *
2516 #ifdef __USE_PROTOS
2517 findImmedAction( Node *q )
2518 #else
2519 findImmedAction( q )
2520 Node *q;
2521 #endif
2522 {
2523         Junction *j;
2524         require(q!=NULL, "findImmedAction: NULL node");
2525         require(q->ntype>=1 && q->ntype<=NumNodeTypes, "findImmedAction: invalid node");
2526         
2527         while ( q->ntype == nJunction )
2528         {
2529                 j = (Junction *)q;
2530                 if ( j->jtype != Generic || j->p2 != NULL ) return NULL;
2531                 q = j->p1;
2532                 if ( q == NULL ) return NULL;
2533         }
2534         if ( q->ntype == nAction ) return (ActionNode *)q;
2535         return NULL;
2536 }
2537
2538 static void
2539 #ifdef __USE_PROTOS
2540 dumpRetValAssign( char *retval, char *ret_def )
2541 #else
2542 dumpRetValAssign( retval, ret_def )
2543 char *retval;
2544 char *ret_def;
2545 #endif
2546 {
2547         char *q = ret_def;
2548         
2549         tab();
2550         while ( *retval != '\0' )
2551         {
2552                 while ( isspace((*retval)) ) retval++;
2553                 while ( *retval!=',' && *retval!='\0' ) fputc(*retval++, output);
2554                 fprintf(output, " = _trv.");
2555                 
2556                 DumpNextNameInDef(&q, output);
2557                 fputc(';', output); fputc(' ', output);
2558                 if ( *retval == ',' ) retval++;
2559         }
2560 }
2561
2562 /* This function computes the set of tokens that can possibly be seen k
2563  * tokens in the future from point j
2564  */
2565 static set
2566 #ifdef __USE_PROTOS
2567 ComputeErrorSet( Junction *j, int k )
2568 #else
2569 ComputeErrorSet( j, k )
2570 Junction *j;
2571 int k;
2572 #endif
2573 {
2574         Junction *alt1;
2575         set a, rk, f;
2576         require(j->ntype==nJunction, "ComputeErrorSet: non junction passed");
2577
2578         f = rk = empty;
2579         for (alt1=j; alt1!=NULL; alt1 = (Junction *)alt1->p2)
2580         {
2581                 REACH(alt1->p1, k, &rk, a);
2582                 require(set_nil(rk), "ComputeErrorSet: rk != nil");
2583                 set_free(rk);
2584                 set_orin(&f, a);
2585                 set_free(a);
2586         }
2587         return f;
2588 }
2589
2590 static char *
2591 #ifdef __USE_PROTOS
2592 tokenFollowSet(TokNode *p)
2593 #else
2594 tokenFollowSet(p)
2595 TokNode *p;
2596 #endif
2597 {
2598     static char buf[100];
2599     set rk, a;
2600     int n;
2601     rk = empty;
2602
2603     REACH(p->next, 1, &rk, a);
2604     require(set_nil(rk), "rk != nil");
2605     set_free(rk);
2606     n = DefErrSet( &a, 0, NULL );
2607     set_free(a);
2608     if ( GenCC )
2609         sprintf(buf, "err%d", n);
2610     else
2611         sprintf(buf, "zzerr%d", n);
2612     return buf;
2613 }
2614
2615 static void
2616 #ifdef __USE_PROTOS
2617 makeErrorClause( Junction *q, set f, int max_k )
2618 #else
2619 makeErrorClause( q, f, max_k )
2620 Junction *q;
2621 set f;
2622 int max_k;
2623 #endif
2624 {
2625         if ( FoundException )
2626         {
2627                 _gen("else {\n");
2628                 tabs++;
2629                 if ( FoundGuessBlk )
2630                 {
2631                         if ( GenCC ) {gen("if ( guessing ) goto fail;\n");}
2632                         else gen("if ( zzguessing ) goto fail;\n");
2633                 }
2634                 gen("if (_sva) _signal=NoViableAlt;\n");
2635                 gen("else _signal=NoSemViableAlt;\n");
2636                 gen("goto _handler;\n");
2637                 tabs--;
2638                 gen("}\n");
2639                 return;
2640         }
2641
2642         if ( max_k == 1 )
2643         {
2644                 if ( GenCC ) {_gen1("else {FAIL(1,err%d", DefErrSet(&f,1,NULL));}
2645                 else _gen1("else {zzFAIL(1,zzerr%d", DefErrSet(&f,1,NULL))
2646                 set_free(f);
2647         }
2648         else
2649         {
2650                 int i;
2651                 set_free(f);
2652                 if ( GenCC ) {_gen1("else {FAIL(%d", max_k);}
2653                 else _gen1("else {zzFAIL(%d", max_k);
2654                 for (i=1; i<=max_k; i++)
2655                 {
2656                         f = ComputeErrorSet(q, i);
2657                         if ( GenCC ) {_gen1(",err%d", DefErrSet( &f, 1, NULL ));}
2658                         else _gen1(",zzerr%d", DefErrSet( &f, 1, NULL ));
2659                         
2660                         set_free(f);
2661                 }
2662         }
2663         _gen(",&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}\n");
2664 }
2665
2666
2667
2668
2669
2670 /* If predicates are allowed in parsing expressions:
2671  *
2672  * (    production 1
2673  * |    production 2
2674  * ...
2675  * |    production n
2676  * )
2677  *
2678  * where production 1 yields visible predicates: <<pred>>? <<pred2>>?
2679  *
2680  * generates (if -prc on):
2681  *
2682  * if ( (production 1 prediction) &&
2683  *              (((context_of_pred ? pred : 1) &&
2684  *              (context_of_pred2 ? pred2 : 1))||!(ctx_pred||ctx_pred2))) ) {
2685  *              ...
2686  * }
2687  * else if ( production 2 prediction ) {
2688  *              ...
2689  * }
2690  * ...
2691  *
2692  * A predicate tree of
2693  *
2694  *              p1
2695  *              |
2696  *              p2--p3
2697  *
2698  * results in
2699  *
2700  * if ( (production 1 prediction) &&
2701  *              (((context_of_p1 ? p1 : 1) &&
2702  *              ((context_of_p2 ? p2 : 0)||
2703  *              (context_of_p3 ? p3 : 0))) || !(ctx_p1||ctx_p2||ctx_p3))
2704  *              ) {
2705  *              ...
2706  * }
2707  *
2708  * If no context, then just test predicate expression.
2709  */
2710 #ifdef DUM
2711 void
2712 #ifdef __USE_PROTOS
2713 genPredTree( Predicate *p, Junction *j )
2714 #else
2715 genPredTree( p, j )
2716 Predicate *p;
2717 Junction *j;
2718 #endif
2719 {
2720         int context_was_present = 0;
2721         Predicate *start_of_OR_list = NULL;
2722
2723         _gen("(");
2724         start_of_OR_list = p;
2725         if ( HoistPredicateContext ) _gen("(");
2726
2727         for (; p!=NULL; p=p->right)
2728         {
2729                 if ( HoistPredicateContext )
2730                 {
2731                         context_was_present = 0;
2732                         if ( LL_k>1 && p->tcontext!=NULL )
2733                         {
2734                                 context_was_present = 1;
2735                                 _gen("((");
2736                                 genExprTree(p->tcontext, 1);
2737                                 _gen(")");
2738                         }
2739                         else if ( LL_k==1 && set_deg(p->scontext[1])>0 )
2740                         {
2741                                 context_was_present = 1;
2742                                 _gen("((");
2743                                 genExprSets(&(p->scontext[0]), CLL_k);
2744                                 _gen(")");
2745                         }
2746                         /* &&'s must use ?: still; only leaves with no parent can avoid ?: */
2747                         if ( p->down!=NULL || p->up!=NULL ) {_gen(" ? ");}
2748                         else {_gen(" && ");}
2749                 }
2750
2751                 if ( FoundException ) {_gen("(_sva=(");}
2752                 else {_gen("(");}
2753                 dumpAction(p->expr, output, 0, -1 /*indicates no line info*/, j->line, 0);
2754                 if ( FoundException ) {_gen("))");}
2755                 else {_gen(")");}
2756
2757                 if ( HoistPredicateContext && context_was_present )
2758                 {
2759                         if ( p->down!=NULL || p->up!=NULL ) {           /* &&'s must use ?: still */
2760                                 _gen(" : ");
2761                                 genPredTermEliminator(p);
2762                         }
2763                         _gen(")");
2764                 }
2765
2766                 if ( p->down!=NULL )
2767                 {
2768                         _gen("&&");
2769                         if ( HoistPredicateContext && context_was_present ) _gen("(");
2770                         genPredTree(p->down, j);
2771                         if ( HoistPredicateContext && context_was_present && )
2772                         {
2773                                 _gen(") || !(");
2774                                 genCombinedPredTreeContext(start_of_OR_list);
2775                                 _gen(")");
2776                         }
2777                 }
2778
2779                 if ( p->right!=NULL ) _gen("||");
2780         }
2781
2782         if ( HoistPredicateContext )
2783         {
2784                 _gen(")) || !(");
2785                 genCombinedPredTreeContext(start_of_OR_list);
2786                 _gen(")");
2787         }
2788         _gen(")");
2789 }
2790 #endif