4 * $Id: gen.c,v 1.7 95/09/26 12:58:40 parrt Exp $
7 * Generate C code (ANSI, K&R, C++)
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.
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
31 * Parr Research Corporation
32 * with Purdue University and AHPCRC, University of Minnesota
43 #define NumExprPerLine 4
45 static set tokensRefdInBlock;
47 extern char *PRED_AND_LIST;
48 extern char *PRED_OR_LIST;
51 /* T r a n s l a t i o n T a b l e s */
53 /* C_Trans[node type] == pointer to function that knows how to translate that node. */
55 void (*C_Trans[NumNodeTypes+1])(...) = {
57 NULL, /* See next table.
58 Junctions have many types */
59 (void (*)(...)) genRuleRef,
60 (void (*)(...)) genToken,
61 (void (*)(...)) genAction
64 void (*C_Trans[NumNodeTypes+1])() = {
66 NULL, /* See next table.
67 Junctions have many types */
74 /* C_JTrans[Junction type] == pointer to function that knows how to translate that
75 * kind of junction node.
78 void (*C_JTrans[NumJuncTypes+1])(...) = {
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
91 void (*C_JTrans[NumJuncTypes+1])() = {
105 #define PastWhiteSpace(s) while (*(s) == ' ' || *(s) == '\t') {s++;}
108 #define TAB { int i; for (i=0; i<tabs; i++) fputc('\t', output); }
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 );
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();
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);}
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);}
161 warn_about_using_gk_option(void)
163 warn_about_using_gk_option()
166 static int warned_already=0;
168 if ( !DemandLookahead || warned_already ) return;
170 warnNoFL("-gk option could cause trouble for <<...>>? predicates");
175 freeBlkFsets( Junction *q )
183 require(q!=NULL, "freeBlkFsets: invalid node");
185 for (alt=q; alt != NULL; alt= (Junction *) alt->p2 )
187 for (i=1; i<=CLL_k; i++) set_free(alt->fset[i]);
192 * Generate a local variable allocation for each token references
197 genTokenPointers( Junction *q )
199 genTokenPointers( q )
203 /* Rule refs are counted and can be referenced, but their
204 * value is not set to anything useful ever.
206 * The ptrs are to be named _tij where i is the current level
207 * and j is the element number within an alternative.
211 tokensRefdInBlock = q->tokrefs;
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))
219 if ( first ) first = 0;
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);}
232 hasDefaultException(ExceptionGroup *eg)
234 hasDefaultException(eg)
240 for (q = eg->handlers->next; q!=NULL; q=q->next)
242 ExceptionHandler *eh = (ExceptionHandler *)q->elem;
243 if ( strcmp("default", eh->signalname)==0 ) {
252 dumpException(ExceptionGroup *eg, int no_default_case)
254 dumpException(eg, no_default_case)
259 gen1("switch ( _signal ) {\n", eg->label==NULL?"":eg->label);
262 for (q = eg->handlers->next; q!=NULL; q=q->next)
264 ExceptionHandler *eh = (ExceptionHandler *)q->elem;
265 if ( strcmp("default", eh->signalname)==0 ) {
268 dumpAction(eh->action, output, tabs, -1, 1, 1);
269 gen("_signal = NoSignal;\n");
274 gen1("case %s :\n", eh->signalname);
276 if ( eh->action != NULL )
278 dumpAction(eh->action, output, tabs, -1, 1, 1);
279 gen("_signal = NoSignal;\n");
285 if ( no_default_case ) return;
289 /* gen("*_retsignal = _signal;\n");*/
290 gen("goto _handler;\n");
297 dumpExceptions(ListNode *list)
305 for (p = list->next; p!=NULL; p=p->next)
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);
313 /* This must be the rule exception handler */
314 dumpException(eg, 1);
315 if ( !hasDefaultException(eg) )
319 gen("zzdflthandlers(_signal,_retsignal);\n");
327 /* For each element label that is found in a rule, generate a unique
328 * Attribute (and AST pointer if GenAST) variable.
332 genElementLabels(ListNode *list)
334 genElementLabels(list)
341 if ( GenCC ) {gen("ANTLRTokenPtr");}
342 else {gen("Attrib");}
343 for (p = list->next; p!=NULL; p=p->next)
345 char *ep = (char *)p->elem;
346 if ( first ) first = 0;
348 if ( GenCC ) {_gen1(" %s=NULL",ep);}
349 else {_gen1(" %s",ep);}
353 if ( !GenAST ) return;
357 for (p = list->next; p!=NULL; p=p->next)
359 char *ep = (char *)p->elem;
360 if ( first ) first = 0;
362 _gen1(" *%s_ast=NULL",ep);
368 * Generate a local variable allocation for each token or rule reference
373 genASTPointers( Junction *q )
382 a = set_or(q->tokrefs, q->rulerefs);
383 if ( set_deg(a) > 0 )
386 for (; !set_nil(a); set_rm(t, a))
389 if ( first ) first = 0;
391 _gen2("*_ast%d%d=NULL", BlkLevel, t);
407 if ( !GenCC ) gen1("zzBLOCK(zztasp%d);\n", BlkLevel);
417 if ( !GenCC ) gen1("zzEXIT(zztasp%d);\n", BlkLevel);
418 if ( !GenCC ) gen("}\n");
425 BLOCK_Preamble( Junction *q )
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);
443 if ( has_guess_block_as_first_item(begin) )
445 gen("zzGUESS_BLOCK\n");
447 if ( q->jtype == aLoopBegin )
448 a = findImmedAction( ((Junction *)q->p1)->p1 ); /* look at aLoopBlk */
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 */
459 genCombinedPredTreeContext( Predicate *p )
461 genCombinedPredTreeContext( p )
465 static set *ctx=NULL; /* genExprSets() is destructive, make copy*/
466 require(p!=NULL, "can't make context tree for NULL pred tree");
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");
473 if ( p->down == NULL )
475 /* if ( p->k>1 && p->tcontext!=NULL ) */
476 if ( p->tcontext!=NULL )
479 genExprTree(p->tcontext, 1);
482 /* else if ( p->k==1 && set_deg(p->scontext[1])>0 )*/
483 else if ( set_deg(p->scontext[1])>0 )
485 if ( ctx==NULL ) ctx = (set *)calloc(CLL_k+1, sizeof(set));
486 require(ctx!=NULL, "ctx cannot allocate");
488 ctx[1]=set_dup(p->scontext[1]);
490 genExprSets(&(ctx[0]), p->k);
494 else if ( p->expr==PRED_AND_LIST || p->expr==PRED_OR_LIST ) {
495 fatal_internal("pred tree is orphan OR or AND list");
498 fatal_internal("pred tree context is empty");
503 if ( p->expr == PRED_AND_LIST )
505 require(p->down!=NULL && p->down->right!=NULL, "pred tree is wacked");
506 genCombinedPredTreeContext(p->down);
508 genCombinedPredTreeContext(p->down->right);
512 if ( p->expr == PRED_OR_LIST )
514 Predicate *list = p->down;
515 for (; list!=NULL; list=list->right)
517 genCombinedPredTreeContext(list);
518 if ( list->right!=NULL ) _gen("||");
523 fatal("pred tree is really wacked");
528 genPredTreeGate( Predicate *p, int in_and_expr )
530 genPredTreeGate( p, in_and_expr )
538 genCombinedPredTreeContext(p);
540 if ( p->down!=NULL ) _gen("\n");
545 genCombinedPredTreeContext(p);
547 if ( p->down!=NULL ) _gen("\n");
553 genPred(Predicate *p, Node *j)
560 if ( FoundException ) {_gen("(_sva=(");}
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("))");}
570 genPredTree( Predicate *p, Node *j, int in_and_expr )
572 genPredTree( p, j, in_and_expr )
578 if ( HoistPredicateContext )
581 genPredTreeGate(p, in_and_expr);
584 /* if leaf node, just gen predicate */
588 if ( HoistPredicateContext ) _gen(")");
592 /* if AND list, do both preds (only two possible) */
593 if ( p->expr == PRED_AND_LIST )
596 genPredTree(p->down, j, 1);
598 genPredTree(p->down->right, j, 1);
600 if ( HoistPredicateContext ) _gen(")");
604 if ( p->expr == PRED_OR_LIST )
609 for (; list!=NULL; list=list->right)
611 genPredTree(list, j, 0);
612 if ( list->right!=NULL ) _gen("||");
615 if ( HoistPredicateContext ) _gen(")");
619 fatal_internal("predicate tree is wacked");
624 genPredTreeMain( Predicate *p, Node *j )
626 genPredTreeMain( p, j )
636 genExprTree( Tree *t, int k )
643 require(t!=NULL, "genExprTree: NULL tree");
645 if ( t->token == ALT )
647 _gen("("); genExprTree(t->down, k); _gen(")");
648 if ( t->right!=NULL )
652 if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
653 _gen("("); genExprTree(t->right, k); _gen(")");
657 if ( t->down!=NULL ) _gen("(");
659 if ( TokenString(t->token) == NULL ) _gen1("%d", t->token)
660 else _gen1("%s", TokenString(t->token));
665 if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
666 _gen("("); genExprTree(t->down, k+1); _gen(")");
668 if ( t->down!=NULL ) _gen(")");
669 if ( t->right!=NULL )
673 if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
674 _gen("("); genExprTree(t->right, k); _gen(")");
679 * Generate LL(k) type expressions of the form:
681 * (LA(1) == T1 || LA(1) == T2 || ... || LA(1) == Tn) &&
682 * (LA(2) == T1 || LA(2) == T2 || ... || LA(2) == Tn) &&
684 * (LA(k) == T1 || LA(k) == T2 || ... || LA(k) == Tn)
686 * If GenExprSets generate:
688 * (setwdi[LA(1)]&(1<<j)) && (setwdi[LA(2)]&(1<<j)) ...
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.
694 * This routine is visible only to this file and cannot answer a TRANS message.
699 genExpr( Junction *j )
707 /* if full LL(k) is sufficient, then don't use approximate (-ck) lookahead
712 if ( j->ftree!=NULL ) limit = LL_k;
714 max_k = genExprSets(j->fset, limit);
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).
721 if ( j->ftree != NULL )
723 _gen(" && !("); genExprTree(j->ftree, 1); _gen(")");
726 if ( ParseWithPredicates && j->predicate!=NULL )
728 Predicate *p = j->predicate;
729 warn_about_using_gk_option();
731 genPredTreeMain(p, (Node *)j);
739 genExprSets( set *fset, int limit )
741 genExprSets( fset, limit )
748 unsigned *e, *g, firstTime=1;
752 while ( !set_nil(fset[k]) && k<=limit )
754 if ( set_deg(fset[k])==1 ) /* too simple for a set? */
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));
766 _gen3("(setwd%d[LA(%d)]&0x%x)", wordnum, k, 1<<setnum);
768 if ( k>max_k ) max_k = k;
769 if ( k == CLL_k ) break;
771 if ( !set_nil(fset[k]) && k<=limit ) _gen(" && ");
773 if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
778 while ( !set_nil(fset[k]) && k<=limit )
780 if ( (e=g=set_pdq(fset[k])) == NULL ) fatal_internal("genExpr: cannot allocate IF expr pdq set");
783 if ( !firstTime ) _gen(" || ") else { _gen("("); firstTime = 0; }
785 if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
787 if ( TokenString(*e) == NULL ) _gen1("%d", *e)
788 else _gen1("%s", TokenString(*e));
792 if ( k>max_k ) max_k = k;
793 if ( k == CLL_k ) break;
795 if ( !set_nil(fset[k]) && k<=limit ) { firstTime=1; _gen(" && "); }
797 if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
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.
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.
812 genBlk( Junction *q, int jtype, int *max_k, int *need_right_curly )
814 genBlk( q, jtype, max_k, need_right_curly )
818 int *need_right_curly;
823 int a_guess_in_block = 0;
824 require(q!=NULL, "genBlk: invalid node");
825 require(q->ntype == nJunction, "genBlk: not junction");
828 if ( q->p2 == NULL ) /* only one alternative? Then don't need if */
830 if ( first_item_is_guess_block((Junction *)q->p1)!=NULL )
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");
837 return empty; /* no decision to be made-->no error set */
840 f = First(q, 1, jtype, max_k);
841 for (alt=q; alt != NULL; alt= (Junction *) alt->p2 )
843 if ( alt->p2 == NULL ) /* chk for empty alt */
846 if ( p->ntype == nJunction )
848 /* we have empty alt */
849 if ( ((Junction *)p)->p1 == (Node *)q->end )
851 break; /* don't do this one, quit */
855 if ( alt != q ) gen("else ")
858 if ( DemandLookahead )
859 if ( !GenCC ) {gen1("LOOK(%d);\n", *max_k);}
860 else gen1("look(%d);\n", *max_k);
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");
872 if ( first_item_is_guess_block((Junction *)alt->p1)!=NULL )
874 a_guess_in_block = 1;
878 if ( first_item_is_guess_block((Junction *)alt->p1)!=NULL ) _gen("!zzrv && ");
892 has_guess_block_as_first_item( Junction *q )
894 has_guess_block_as_first_item( q )
900 for (alt=q; alt != NULL; alt= (Junction *) alt->p2 )
902 if ( first_item_is_guess_block((Junction *)alt->p1)!=NULL ) return 1;
907 /* return NULL if 1st item of alt is (...)? block; else return ptr
909 * of (...)?; This function ignores actions and predicates.
913 first_item_is_guess_block( Junction *q )
915 first_item_is_guess_block( q )
919 while ( q!=NULL && ((q->ntype==nJunction && q->jtype==Generic) || q->ntype==nAction) )
921 if ( q->ntype==nJunction ) q = (Junction *)q->p1;
922 else q = (Junction *) ((ActionNode *)q)->next;
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;
932 /* Generate an action. Don't if action is NULL which means that it was already
933 * handled as an init action.
937 genAction( ActionNode *p )
943 require(p!=NULL, "genAction: invalid node and/or rule");
944 require(p->ntype==nAction, "genAction: not action");
948 if ( p->is_predicate )
950 if ( p->guardpred!=NULL )
953 genPredTreeMain(p->guardpred, (Node *)p);
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);
963 if ( p->pred_fail != NULL )
967 gen1("%s;\n", p->pred_fail);
970 else _gen1(") {zzfailed_pred(\"%s\");}\n",p->action);
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");
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).
988 * if ! modifies rule-ref, then never link it in and never pass zzSTR.
989 * Always pass address of temp root ptr.
993 genRuleRef( RuleRefNode *p )
1000 char *handler_id = "";
1002 char *parm = "", *exsig = "";
1003 require(p!=NULL, "genRuleRef: invalid node and/or rule");
1004 require(p->ntype==nRuleRef, "genRuleRef: not rule reference");
1006 if ( p->altstart!=NULL && p->altstart->exception_label!=NULL )
1007 handler_id = p->altstart->exception_label;
1009 r = (RuleEntry *) hash_get(Rname, p->text);
1012 warnFL( eMsg1("rule %s not defined",
1013 p->text), FileStr[p->file], p->line );
1016 r2 = (RuleEntry *) hash_get(Rname, p->rname);
1017 if ( r2 == NULL ) {warnNoFL("Rule hash table is screwed up beyond belief"); return;}
1019 if ( GenLineInfo ) fprintf(output, LineInfoFormatStr, p->line, FileStr[p->file]);
1021 if ( GenCC && GenAST ) {
1022 gen("_ast = NULL;\n");
1025 if ( FoundGuessBlk && p->assign!=NULL )
1026 if ( GenCC ) {gen("if ( !guessing ) {\n");}
1027 else gen("zzNON_GUESS_MODE {\n");
1029 if ( FoundException ) exsig = "&_signal";
1035 /* if ( r2->noAST || p->astnode==ASTexclude )
1038 /* _gen("_ast = NULL;\n");*/
1041 /* we always want to set just a pointer now, then set correct
1046 (_tail==NULL)?(&_sibling):(&(_tail->_right));\n");
1052 if ( r2->noAST || p->astnode==ASTexclude )
1054 _gen("_ast = NULL; ");
1057 else parm = "zzSTR";
1059 if ( p->assign!=NULL )
1061 if ( !HasComma(p->assign) ) {_gen1("%s = ",p->assign);}
1062 else _gen1("{ struct _rv%d _trv; _trv = ", r->rulenum);
1064 if ( FoundException ) {
1065 _gen5("%s%s(%s,&_signal%s%s); ",
1069 (p->parms!=NULL)?",":"",
1070 (p->parms!=NULL)?p->parms:"");
1071 if ( p->ex_group!=NULL ) {
1073 gen("if (_signal) {\n");
1075 dumpException(p->ex_group, 0);
1080 _gen1("if (_signal) goto %s_handler;", handler_id);
1084 _gen5("%s%s(%s%s%s);",
1088 (p->parms!=NULL)?",":"",
1089 (p->parms!=NULL)?p->parms:"");
1091 if ( GenCC && (r2->noAST || p->astnode==ASTexclude) )
1093 /* rule has a ! or element does */
1094 /* still need to assign to #i so we can play with it */
1096 gen2("_ast%d%d = (AST *)_ast;", BlkLevel-1, p->elnum);
1098 else if ( !r2->noAST && p->astnode == ASTinclude )
1100 /* rule doesn't have a ! and neither does element */
1103 gen("if ( _tail==NULL ) _sibling = _ast; else _tail->setRight(_ast);\n");
1104 gen2("_ast%d%d = (AST *)_ast;\n", BlkLevel-1, p->elnum);
1108 if ( GenCC ) {_gen("ASTBase::");} else _gen("zz");
1109 _gen("link(_root, &_sibling, &_tail);");
1114 if ( p->assign!=NULL )
1116 if ( !HasComma(p->assign) ) {_gen1("%s = ",p->assign);}
1117 else _gen1("{ struct _rv%d _trv; _trv = ", r->rulenum);
1119 if ( FoundException ) {
1120 _gen4("%s%s(&_signal%s%s); ",
1123 (p->parms!=NULL)?",":"",
1124 (p->parms!=NULL)?p->parms:"");
1125 if ( p->ex_group!=NULL ) {
1127 gen("if (_signal) {\n");
1129 dumpException(p->ex_group, 0);
1134 _gen1("if (_signal) goto %s_handler;", handler_id);
1141 (p->parms!=NULL)?p->parms:"");
1143 if ( p->assign!=NULL ) _gen("\n");
1145 q = RulePtr[r->rulenum]; /* find definition of ref'd rule */
1146 if ( p->assign!=NULL ) {
1147 if ( HasComma(p->assign) )
1150 dumpRetValAssign(p->assign, q->ret);
1156 /* Handle element labels now */
1157 if ( p->el_label!=NULL )
1162 gen3("%s_ast = _ast%d%d;\n", p->el_label, BlkLevel-1, p->elnum);
1164 else {gen1("%s_ast = zzastCur;\n", p->el_label);}
1167 gen1("%s = zzaCur;\n", p->el_label);
1171 if ( FoundGuessBlk && p->assign!=NULL ) {
1172 /* in guessing mode, don't branch to handler upon error */
1174 if ( FoundException ) {
1175 gen6("%s%s(%s%s&_signal%s%s);\n",
1179 (*parm!='\0')?",":"",
1180 (p->parms!=NULL)?",":"",
1181 (p->parms!=NULL)?p->parms:"");
1184 gen5("%s%s(%s%s%s);\n",
1188 (p->parms!=NULL && *parm!='\0')?",":"",
1189 (p->parms!=NULL)?p->parms:"");
1197 * Generate code to match a token.
1199 * Getting the next token is tricky. We want to ensure that any action
1200 * following a token is executed before the next GetToken();
1204 genToken( TokNode *p )
1211 char *handler_id = "";
1214 require(p!=NULL, "genToken: invalid node and/or rule");
1215 require(p->ntype==nToken, "genToken: not token");
1217 if ( p->altstart!=NULL && p->altstart->exception_label!=NULL )
1218 handler_id = p->altstart->exception_label;
1220 r = (RuleEntry *) hash_get(Rname, p->rname);
1221 if ( r == NULL ) {warnNoFL("Rule hash table is screwed up beyond belief"); return;}
1223 if ( GenLineInfo ) fprintf(output, LineInfoFormatStr, p->line, FileStr[p->file]);
1225 if ( !set_nil(p->tset) ) /* implies '.', ~Tok, or tokenclass */
1229 b = set_dup(p->tset);
1230 if ( p->tclass!=NULL ) /* token class? */
1232 static char buf[MaxRuleName+1];
1233 if ( p->tclass->dumped )
1234 e = p->tclass->setnum;
1236 e = DefErrSet(&b, 0, TokenString(p->token));
1237 p->tclass->dumped = 1; /* indicate set has been created */
1238 p->tclass->setnum = e;
1240 sprintf(buf, "%s_set", TokenString(p->token));
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);
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);",
1260 gen2("zzsetmatch_wsig(%s, %s_handler);",
1266 gen1("if ( !_setmatch_wsig(%s) ) {\n", set_name);
1268 gen("if ( guessing ) goto fail;\n");
1269 gen("_signal=MismatchedToken;\n");
1270 dumpException(p->ex_group, 0);
1276 else if ( TokenString(p->token)!=NULL )
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 )
1283 gen2("zzmatch_wsig(%s, %s_handler);",
1284 TokenString(p->token),
1289 gen1("if ( !_match_wsig(%s) ) {\n", TokenString(p->token));
1291 gen("if ( guessing ) goto fail;\n");
1292 gen("_signal=MismatchedToken;\n");
1293 dumpException(p->ex_group, 0);
1298 else gen1("zzmatch(%s);", TokenString(p->token));
1301 if ( FoundException ) {
1302 if ( p->use_def_MT_handler )
1303 gen2("zzmatch_wdfltsig((ANTLRTokenType)%d,%s);",
1304 p->token,tokenFollowSet(p))
1306 gen2("zzmatch_wsig(%d,%s_handler);",p->token,handler_id);
1308 else {gen1("zzmatch(%d);", p->token);}
1311 a = findImmedAction( p->next );
1312 /* generate the token labels */
1313 if ( GenCC && p->elnum>0 )
1315 /* If building trees in C++, always gen the LT() assigns */
1316 if ( set_el(p->elnum, tokensRefdInBlock) || GenAST )
1318 if ( FoundGuessBlk )
1321 if ( GenCC ) {gen("if ( !guessing ) {\n"); tab();}
1322 else {gen("zzNON_GUESS_MODE {\n"); tab();}
1324 _gen2(" _t%d%d = (ANTLRTokenPtr)LT(1);\n", BlkLevel-1, p->elnum);
1325 if ( FoundGuessBlk ) {gen("}\n");}
1328 if ( !DemandLookahead ) _gen(" labase++;");
1334 if ( FoundGuessBlk && !(p->astnode == ASTexclude || r->noAST) )
1336 if ( GenCC ) {_gen("if ( !guessing ) {\n"); tab();}
1337 else {_gen("zzNON_GUESS_MODE {\n"); tab();}
1341 if ( GenCC && !(p->astnode == ASTexclude || r->noAST) ) {
1343 gen4("_ast%d%d = new AST(_t%d%d);\n", BlkLevel-1, p->elnum, BlkLevel-1, p->elnum);
1346 if ( GenCC && !(p->astnode == ASTexclude || r->noAST) )
1347 {_gen2("_ast%d%d->", BlkLevel-1, p->elnum);}
1349 if ( p->astnode==ASTchild ) {
1350 if ( !GenCC ) _gen("zz");
1351 _gen("subchild(_root, &_sibling, &_tail);");
1353 else if ( p->astnode==ASTroot ) {
1354 if ( !GenCC ) _gen("zz");
1355 _gen("subroot(_root, &_sibling, &_tail);");
1357 if ( GenCC && !(p->astnode == ASTexclude || r->noAST) ) {
1362 else if ( !GenCC ) _gen(" zzastDPush;");
1363 if ( FoundGuessBlk && !(p->astnode == ASTexclude || r->noAST) )
1364 {_gen("}\n"); tab();}
1367 /* Handle element labels now */
1368 if ( p->el_label!=NULL )
1371 if ( FoundGuessBlk )
1373 if ( GenCC ) {gen("if ( !guessing ) {\n"); tab();}
1374 else {gen("zzNON_GUESS_MODE {\n"); tab();}
1376 /* Do Attrib / Token ptr */
1378 if ( set_el(p->elnum, tokensRefdInBlock) || GenAST )
1379 {gen3("%s = _t%d%d;\n", p->el_label, BlkLevel-1, p->elnum);}
1382 gen1("%s = (ANTLRTokenPtr)LT(1);\n", p->el_label);
1385 else {gen1("%s = zzaCur;\n", p->el_label);}
1387 if ( GenAST && !(p->astnode == ASTexclude || r->noAST) )
1390 gen3("%s_ast = _ast%d%d;\n", p->el_label, BlkLevel-1, p->elnum);
1392 else {gen1("%s_ast = zzastCur;\n", p->el_label);}
1395 if ( FoundGuessBlk ) {_gen("}\n"); tab();}
1398 /* Handle any actions immediately following action */
1401 /* delay next token fetch until after action */
1403 if ( a->is_predicate )
1406 dumpAction(a->action, output, 0, a->file, a->line, 0);
1407 if ( a->pred_fail != NULL )
1410 /* if ( FoundGuessBlk )
1411 gen("zzNON_GUESS_MODE {\n");*/
1413 gen1("%s;\n", a->pred_fail);
1416 /* if ( FoundGuessBlk ) gen("}\n");*/
1418 else _gen1(")) {zzfailed_pred(\"%s\");}\n",a->action);
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");
1429 if ( !DemandLookahead ) {
1431 if ( FoundException && p->use_def_MT_handler ) gen("if (!_signal)");
1433 if ( FoundException && p->use_def_MT_handler )
1434 _gen(" _signal=NoSignal;");
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;");
1449 if ( !DemandLookahead ) {
1451 if (FoundException && p->use_def_MT_handler) _gen("if (!_signal)");
1453 if (FoundException&&p->use_def_MT_handler) _gen(" _signal=NoSignal;");
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;");
1470 genOptBlk( Junction *q )
1478 int need_right_curly;
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");
1485 if ( GenLineInfo ) fprintf(output, LineInfoFormatStr, q->line, FileStr[q->file]);
1488 f = genBlk(q, aOptBlk, &max_k, &need_right_curly);
1492 if ( first_item_is_guess_block((Junction *)q->p1)!=NULL )
1494 if ( !GenCC ) {gen("else if ( zzguessing ) zzGUESS_DONE;\n");}
1495 else gen("else if ( !zzrv ) zzGUESS_DONE;\n");
1497 { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
1499 tokensRefdInBlock = savetkref;
1500 if (q->end->p1 != NULL) TRANS(q->end->p1);
1504 * Generate code for a loop blk of form:
1512 genLoopBlk( Junction *begin, Junction *q, Junction *start, int max_k )
1514 genLoopBlk( begin, q, start, max_k )
1517 Junction *start; /* where to start generating code from */
1522 int need_right_curly;
1524 savetkref = tokensRefdInBlock;
1525 require(q->ntype == nJunction, "genLoopBlk: not junction");
1526 require(q->jtype == aLoopBlk, "genLoopBlk: not loop block");
1528 if ( q->visited ) return;
1530 if ( q->p2 == NULL ) /* only one alternative? */
1532 if ( DemandLookahead )
1533 if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}
1534 else gen1("look(%d);\n", max_k);
1536 if ( begin!=NULL ) genExpr(begin);
1538 /* if no predicates have been hoisted for this single alt (..)*
1541 if ( ParseWithPredicates && begin->predicate==NULL )
1543 Predicate *a = find_predicates((Node *)q->p1);
1547 genPredTreeMain(a, (Node *)q);
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);
1561 tokensRefdInBlock = savetkref;
1564 gen("while ( 1 ) {\n");
1568 if ( DemandLookahead )
1570 if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}
1571 else gen1("look(%d);\n", max_k);
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).
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.
1585 genExpr((Junction *)begin->p2);
1588 genExpr((Junction *)begin);
1589 _gen(")) break;\n");
1591 f = genBlk(q, aLoopBlk, &max_k, &need_right_curly);
1595 /* generate code for terminating loop (this is optional branch) */
1596 if ( begin==NULL ) gen("else break;\n"); /* code for exiting loop "for sure" */
1598 { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
1599 if ( !GenCC ) gen1("zzLOOP(zztasp%d);\n", BlkLevel-1);
1603 tokensRefdInBlock = savetkref;
1607 * Generate code for a loop blk of form:
1611 * --o-->o-->o-G-o-->o--
1616 * q->end points to the last node (far right) in the blk. Note
1620 * Generate code roughly of the following form:
1623 * ... code for alternatives ...
1624 * } while ( First Set of aLoopBlk );
1626 * OR if > 1 alternative
1629 * ... code for alternatives ...
1635 genLoopBegin( Junction *q )
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");
1651 if ( GenLineInfo ) fprintf(output, LineInfoFormatStr, q->line, FileStr[q->file]);
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 );
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]);
1666 tokensRefdInBlock = savetkref;
1667 if (q->end->p1 != NULL) TRANS(q->end->p1);
1671 * Generate code for a loop blk of form:
1677 * q->end points to the last node (far right) in the blk.
1678 * Note that q->end->jtype must be 'EndBlk'.
1680 * Generate code roughly of the following form:
1683 * ... code for alternatives ...
1684 * } while ( First Set of aPlusBlk );
1686 * OR if > 1 alternative
1689 * ... code for alternatives ...
1690 * else if not 1st time through, break;
1695 genPlusBlk( Junction *q )
1703 int need_right_curly;
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");
1711 if ( q->visited ) return;
1713 if ( GenLineInfo ) fprintf(output, LineInfoFormatStr, q->line, FileStr[q->file]);
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.
1720 if ( ((Junction *)q->p2)->p2 == NULL &&
1721 ((Junction *)q->p2)->ignore ) /* only one alternative? */
1724 /* if the only alt has a semantic predicate, hoist it; must test before
1727 if ( ParseWithPredicates )
1729 a = find_predicates((Node *)q);
1732 genPredTreeMain(a, (Node *)q);
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);
1746 if ( q->parm!=NULL && q->predparm ) _gen1("(%s) && ", q->parm);
1748 if ( ParseWithPredicates && a!=NULL )
1751 genPredTreeMain(a, (Node *)q);
1754 if ( ParseWithPredicates && a!=NULL ) gen("}\n");
1760 tokensRefdInBlock = savetkref;
1761 if (q->end->p1 != NULL) TRANS(q->end->p1);
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 */
1769 makeErrorClause(q,f,max_k);
1770 { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
1773 if ( !GenCC ) _gen1(" zzLOOP(zztasp%d);", BlkLevel-1);
1775 if ( DemandLookahead )
1776 if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}
1777 else gen1("look(%d);\n", max_k);
1779 if ( q->parm!=NULL && q->predparm ) {gen1("} while (%s);\n", q->parm);}
1780 else gen("} while ( 1 );\n");
1784 tokensRefdInBlock = savetkref;
1785 if (q->end->p1 != NULL) TRANS(q->end->p1);
1789 * Generate code for a sub blk of alternatives of form:
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.
1807 * Generate code of the following form:
1808 * if ( First(G1) ) {
1811 * else if ( First(G2) ) {
1821 genSubBlk( Junction *q )
1829 int need_right_curly;
1831 savetkref = tokensRefdInBlock;
1832 require(q->ntype == nJunction, "genSubBlk: not junction");
1833 require(q->jtype == aSubBlk, "genSubBlk: not subblock");
1835 if ( GenLineInfo ) fprintf(output, LineInfoFormatStr, q->line, FileStr[q->file]);
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");} }
1847 gen("zzGUESS_DONE\n");
1850 /* must duplicate if (alpha)?; one guesses (validates), the
1851 * second pass matches */
1852 if ( q->guess && analysis_point(q)==q )
1854 if ( GenLineInfo ) fprintf(output, LineInfoFormatStr, q->line, FileStr[q->file]);
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");} }
1865 tokensRefdInBlock = savetkref;
1866 if (q->end->p1 != NULL) TRANS(q->end->p1);
1870 * Generate code for a rule.
1872 * rule--> o-->o-Alternatives-o-->o
1874 * rule--> o-->o-Alternative-o-->o
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.
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.
1886 genRule( Junction *q )
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");
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 */
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");
1909 special_fopen_actions(OutMetaName(outname(FileStr[q->file])));
1911 if ( file == -1 ) genHdr1(q->file);
1912 else genHdr(q->file);
1915 DumpFuncHeader(q,r);
1919 /* Declare the return value - and PURIFY it -ATG 6/5/95 */
1920 if ( HasComma(q->ret) )
1922 gen1("struct _rv%d _retv;\n",r->rulenum);
1923 gen1("PURIFY(_retv,sizeof(struct _rv%d))\n",r->rulenum);
1928 DumpType(q->ret, output);
1930 gen("PURIFY(_retv,sizeof(");
1931 DumpType(q->ret, output);
1938 fprintf(output, LineInfoFormatStr, q->line, FileStr[q->file]);
1942 if ( FoundException )
1944 gen("int _sva=1;\n");
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");
1957 if ( has_guess_block_as_first_item((Junction *)q->p1) )
1959 gen("zzGUESS_BLOCK\n");
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 );
1966 a = findImmedAction( q->p1 ); /* only one alternative in rule */
1967 if ( a!=NULL && !a->is_predicate )
1969 dumpAction(a->action, output, tabs, a->file, a->line, 1);
1970 a->done = 1; /* ignore action. We have already handled it */
1973 if ( GenCC ) {gen1("tracein(\"%s\");\n", q->rname);}
1974 else gen1("zzTRACEIN((ANTLRChar *)\"%s\");\n", q->rname);
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);
1986 if ( !GenCC ) gen1("zzEXIT(zztasp%d);\n", BlkLevel);
1989 if ( GenCC ) {gen1("traceout(\"%s\");\n", q->rname);}
1990 else gen1("zzTRACEOUT((ANTLRChar *)\"%s\");\n", q->rname);
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 */
1996 REACH(q->end, 1, &rk, follow);
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);
2009 gen1("syn(zzBadTok, %s, zzMissSet, zzMissTok, zzErrk);\n",
2010 r->egroup==NULL?"(ANTLRChar *)\"\"":r->egroup);
2014 gen1("zzsyn(zzMissText, zzBadTok, %s, zzMissSet, zzMissTok, zzErrk, zzBadText);\n",
2015 r->egroup==NULL?"(ANTLRChar *)\"\"":r->egroup);
2017 gen3("%sresynch(setwd%d, 0x%x);\n", GenCC?"":"zz", wordnum, 1<<setnum);
2020 if ( GenCC ) {gen1("traceout(\"%s\");\n", q->rname);}
2021 else gen1("zzTRACEOUT((ANTLRChar *)\"%s\");\n", q->rname);
2023 if ( q->ret!=NULL ) {gen("return _retv;\n");}
2024 else if ( q->exceptions!=NULL ) gen("return;\n");
2025 if ( !GenCC ) gen("}\n");
2027 /* Gen code for exception handlers */
2028 if ( q->exceptions!=NULL )
2030 gen("/* exception handlers */\n");
2031 dumpExceptions(q->exceptions);
2032 if ( !r->has_rule_exception )
2034 _gen("_handler:\n");
2035 gen("zzdflthandlers(_signal,_retsignal);\n");
2038 if ( q->ret!=NULL ) {gen("return _retv;\n");}
2039 else {gen("return;\n");}
2041 else if ( FoundException )
2043 _gen("_handler:\n");
2044 gen("zzdflthandlers(_signal,_retsignal);\n");
2050 if ( q->p2 != NULL ) {TRANS(q->p2);} /* generate code for next rule too */
2051 else dumpAfterActions( output );
2056 DumpFuncHeader( Junction *q, RuleEntry *r )
2058 DumpFuncHeader( q, r )
2067 if ( HasComma(q->ret) )
2069 if (GenCC) gen2("%s::_rv%d\n", CurrentClassName, r->rulenum)
2070 else gen1("struct _rv%d\n",r->rulenum);
2074 DumpType(q->ret, output);
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);
2088 if ( GenCC ) {gen("{\n"); return;}
2092 gen2("%s%s(", RulePrefix, q->rname);
2096 if ( q->pdecl!=NULL ) _gen(",");
2098 if ( FoundException )
2100 if ( GenAST ) _gen(",");
2102 if ( q->pdecl!=NULL ) _gen(",");
2105 DumpListOfParmNames( q->pdecl, output );
2107 if ( GenAST ) gen("AST **_root;\n");
2108 if ( FoundException ) gen("int *_retsignal;\n");
2109 DumpOldStyleParms( q->pdecl, output );
2116 DumpANSIFunctionArgDef(FILE *f, Junction *q)
2118 DumpANSIFunctionArgDef(f,q)
2125 if ( GenCC ) {fprintf(f,"ASTBase **_root");}
2126 else fprintf(f,"AST**_root");
2127 if ( !FoundException && q->pdecl!=NULL ) fprintf(f,",");
2129 if ( FoundException )
2131 if ( GenAST ) fprintf(f,",");
2132 fprintf(f,"int *_retsignal");
2133 if ( q->pdecl!=NULL ) fprintf(f,",");
2135 if ( q->pdecl!=NULL ) {fprintf(f,"%s", q->pdecl);}
2136 else if ( !GenAST && !FoundException ) fprintf(f,"void");
2142 genJunction( Junction *q )
2148 require(q->ntype == nJunction, "genJunction: not junction");
2149 require(q->jtype == Generic, "genJunction: not generic junction");
2151 if ( q->p1 != NULL ) TRANS(q->p1);
2152 if ( q->p2 != NULL ) TRANS(q->p2);
2157 genEndBlk( Junction *q )
2167 genEndRule( Junction *q )
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");
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);
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]);
2199 if ( UserTokenDefsFile != NULL )
2200 fprintf(output, "#include %s\n", UserTokenDefsFile);
2202 fprintf(output, "#include \"%s\"\n", DefFileName);
2205 if ( HdrAction != NULL ) dumpAction( HdrAction, output, 0, -1, 0, 1);
2206 if ( !GenCC && FoundGuessBlk )
2208 _gen("#define ZZCAN_GUESS\n");
2209 _gen("#include <setjmp.h>\n");
2211 if ( FoundException )
2213 _gen("#define EXCEPTION_HANDLING\n");
2214 _gen1("#define NUM_SIGNALS %d\n", NumSignals);
2216 if ( !GenCC && OutputLL_k > 1 ) _gen1("#define LL_K %d\n", OutputLL_k);
2217 if ( GenAST&&!GenCC ) _gen("#define GENAST\n\n");
2219 if ( GenCC ) {_gen1("#include \"%s\"\n\n", ASTBASE_H);}
2220 else _gen("#include \"ast.h\"\n\n");
2222 if ( !GenCC && DemandLookahead ) _gen("#define DEMAND_LOOK\n\n");
2224 if ( !GenCC && LexGen ) {
2225 _gen1("#define zzEOF_TOKEN %d\n", (TokenInd!=NULL?TokenInd[EofToken]:EofToken));
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");}
2232 _gen1("#include \"%s\"\n", APARSER_H);
2233 _gen1("#include \"%s.h\"\n", CurrentClassName);
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);
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");
2263 _gen("#include \"ast.c\"\n");
2264 _gen("zzASTgvars\n\n");
2267 if ( !GenCC ) _gen("ANTLR_INFO\n");
2268 if ( BeforeActions != NULL )
2270 for (p = BeforeActions->next; p!=NULL; p=p->next)
2272 UserAction *ua = (UserAction *)p->elem;
2273 dumpAction( ua->action, output, 0, ua->file, ua->line, 1);
2277 if ( !FoundException ) return;
2281 _gen1("\nvoid %s::\n", CurrentClassName);
2282 _gen("zzdflthandlers( int _signal, int *_retsignal )\n");
2288 _gen("#ifdef __STDC__\n");
2289 _gen("zzdflthandlers( int _signal, int *_retsignal )\n");
2291 _gen("zzdflthandlers( _signal, _retsignal )\n");
2292 _gen("int _signal;\n");
2293 _gen("int *_retsignal;\n");
2298 if ( DefaultExGroup!=NULL )
2300 dumpException(DefaultExGroup, 1);
2301 if ( !hasDefaultException(DefaultExGroup) )
2305 gen("*_retsignal = _signal;\n");
2311 gen("*_retsignal = _signal;\n");
2320 genStdPCCTSIncludeFile( FILE *f )
2322 genStdPCCTSIncludeFile( f )
2326 fprintf(f,"#ifndef STDPCCTS_H\n");
2327 fprintf(f,"#define STDPCCTS_H\n");
2329 fprintf(f," * %s -- P C C T S I n c l u d e\n", stdpccts);
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);
2336 fprintf(f,"#include <stdio.h>\n");
2337 fprintf(f,"#define ANTLR_VERSION %s\n", VersionDef);
2340 if ( UserDefdTokens )
2341 fprintf(f, "#include %s\n", UserTokenDefsFile);
2343 fprintf(f, "#include \"%s\"\n", DefFileName);
2346 fprintf(f, "#include \"%s\"\n", ATOKEN_H);
2348 if ( HdrAction != NULL ) dumpAction( HdrAction, f, 0, -1, 0, 1);
2350 fprintf(f, "#include \"%s\"\n", ATOKENBUFFER_H);
2352 if ( OutputLL_k > 1 ) fprintf(f,"static const unsigned LL_K=%d;\n", OutputLL_k);
2354 fprintf(f, "#include \"%s\"\n", ASTBASE_H);
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");
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 )
2372 fprintf(f,"#define ZZCAN_GUESS\n");
2373 fprintf(f,"#include <setjmp.h>\n");
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 )
2379 _gen("#define EXCEPTION_HANDLING\n");
2380 _gen1("#define NUM_SIGNALS %d\n", NumSignals);
2382 if ( DemandLookahead ) fprintf(f,"#define DEMAND_LOOK\n");
2384 if ( LexGen ) fprintf(f, "#define zzEOF_TOKEN %d\n", (TokenInd!=NULL?TokenInd[EofToken]:EofToken));
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");
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.
2407 June '93; changed so that empty lines are left alone so that
2408 line information is correct for the compiler/debuggers.
2412 dumpAction( char *s, FILE *output, int tabs, int file, int line,
2415 dumpAction( s, output, tabs, file, line, final_newline )
2424 int inDQuote, inSQuote;
2425 require(s!=NULL, "dumpAction: NULL action");
2426 require(output!=NULL, eMsg1("dumpAction: output FILE is NULL for %s",s));
2428 if ( GenLineInfo && file != -1 )
2430 fprintf(output, LineInfoFormatStr, line, FileStr[file]);
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' )
2440 fputc( *s++, output ); /* Avoid '"' Case */
2441 if ( *s == '\0' ) return;
2442 if ( *s == '\'' ) fputc( *s++, output );
2443 if ( *s == '\"' ) fputc( *s++, output );
2447 if ( !inDQuote ) inSQuote = !inSQuote;
2451 if ( !inSQuote ) inDQuote = !inDQuote;
2455 fputc('\n', output);
2457 PastWhiteSpace( s );
2462 fputc( *s++, output );
2465 if ( *s == '\0' ) return;
2466 if ( *s != '#' ) /* #define, #endif etc.. start at col 1 */
2471 if ( *s == '}' && !(inSQuote || inDQuote) )
2473 --tabs; /* Indent one fewer */
2475 if ( *s == '{' && !(inSQuote || inDQuote) )
2477 tabs++; /* Indent one more */
2479 fputc( *s, output );
2482 if ( final_newline ) fputc('\n', output);
2487 dumpAfterActions( FILE *output )
2489 dumpAfterActions( output )
2494 require(output!=NULL, "dumpAfterActions: output file was NULL for some reason");
2495 if ( AfterActions != NULL )
2497 for (p = AfterActions->next; p!=NULL; p=p->next)
2499 UserAction *ua = (UserAction *)p->elem;
2500 dumpAction( ua->action, output, 0, ua->file, ua->line, 1);
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.
2511 * Scan forward while (generic junction with p2==NULL)
2512 * If we stop on an action, return ptr to the action
2517 findImmedAction( Node *q )
2519 findImmedAction( q )
2524 require(q!=NULL, "findImmedAction: NULL node");
2525 require(q->ntype>=1 && q->ntype<=NumNodeTypes, "findImmedAction: invalid node");
2527 while ( q->ntype == nJunction )
2530 if ( j->jtype != Generic || j->p2 != NULL ) return NULL;
2532 if ( q == NULL ) return NULL;
2534 if ( q->ntype == nAction ) return (ActionNode *)q;
2540 dumpRetValAssign( char *retval, char *ret_def )
2542 dumpRetValAssign( retval, ret_def )
2550 while ( *retval != '\0' )
2552 while ( isspace((*retval)) ) retval++;
2553 while ( *retval!=',' && *retval!='\0' ) fputc(*retval++, output);
2554 fprintf(output, " = _trv.");
2556 DumpNextNameInDef(&q, output);
2557 fputc(';', output); fputc(' ', output);
2558 if ( *retval == ',' ) retval++;
2562 /* This function computes the set of tokens that can possibly be seen k
2563 * tokens in the future from point j
2567 ComputeErrorSet( Junction *j, int k )
2569 ComputeErrorSet( j, k )
2576 require(j->ntype==nJunction, "ComputeErrorSet: non junction passed");
2579 for (alt1=j; alt1!=NULL; alt1 = (Junction *)alt1->p2)
2581 REACH(alt1->p1, k, &rk, a);
2582 require(set_nil(rk), "ComputeErrorSet: rk != nil");
2592 tokenFollowSet(TokNode *p)
2598 static char buf[100];
2603 REACH(p->next, 1, &rk, a);
2604 require(set_nil(rk), "rk != nil");
2606 n = DefErrSet( &a, 0, NULL );
2609 sprintf(buf, "err%d", n);
2611 sprintf(buf, "zzerr%d", n);
2617 makeErrorClause( Junction *q, set f, int max_k )
2619 makeErrorClause( q, f, max_k )
2625 if ( FoundException )
2629 if ( FoundGuessBlk )
2631 if ( GenCC ) {gen("if ( guessing ) goto fail;\n");}
2632 else gen("if ( zzguessing ) goto fail;\n");
2634 gen("if (_sva) _signal=NoViableAlt;\n");
2635 gen("else _signal=NoSemViableAlt;\n");
2636 gen("goto _handler;\n");
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))
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++)
2656 f = ComputeErrorSet(q, i);
2657 if ( GenCC ) {_gen1(",err%d", DefErrSet( &f, 1, NULL ));}
2658 else _gen1(",zzerr%d", DefErrSet( &f, 1, NULL ));
2663 _gen(",&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}\n");
2670 /* If predicates are allowed in parsing expressions:
2678 * where production 1 yields visible predicates: <<pred>>? <<pred2>>?
2680 * generates (if -prc on):
2682 * if ( (production 1 prediction) &&
2683 * (((context_of_pred ? pred : 1) &&
2684 * (context_of_pred2 ? pred2 : 1))||!(ctx_pred||ctx_pred2))) ) {
2687 * else if ( production 2 prediction ) {
2692 * A predicate tree of
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))
2708 * If no context, then just test predicate expression.
2713 genPredTree( Predicate *p, Junction *j )
2720 int context_was_present = 0;
2721 Predicate *start_of_OR_list = NULL;
2724 start_of_OR_list = p;
2725 if ( HoistPredicateContext ) _gen("(");
2727 for (; p!=NULL; p=p->right)
2729 if ( HoistPredicateContext )
2731 context_was_present = 0;
2732 if ( LL_k>1 && p->tcontext!=NULL )
2734 context_was_present = 1;
2736 genExprTree(p->tcontext, 1);
2739 else if ( LL_k==1 && set_deg(p->scontext[1])>0 )
2741 context_was_present = 1;
2743 genExprSets(&(p->scontext[0]), CLL_k);
2746 /* &&'s must use ?: still; only leaves with no parent can avoid ?: */
2747 if ( p->down!=NULL || p->up!=NULL ) {_gen(" ? ");}
2748 else {_gen(" && ");}
2751 if ( FoundException ) {_gen("(_sva=(");}
2753 dumpAction(p->expr, output, 0, -1 /*indicates no line info*/, j->line, 0);
2754 if ( FoundException ) {_gen("))");}
2757 if ( HoistPredicateContext && context_was_present )
2759 if ( p->down!=NULL || p->up!=NULL ) { /* &&'s must use ?: still */
2761 genPredTermEliminator(p);
2766 if ( p->down!=NULL )
2769 if ( HoistPredicateContext && context_was_present ) _gen("(");
2770 genPredTree(p->down, j);
2771 if ( HoistPredicateContext && context_was_present && )
2774 genCombinedPredTreeContext(start_of_OR_list);
2779 if ( p->right!=NULL ) _gen("||");
2782 if ( HoistPredicateContext )
2785 genCombinedPredTreeContext(start_of_OR_list);