home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / pccts.zip / pccts / antlr / gen.c < prev    next >
C/C++ Source or Header  |  1994-03-31  |  49KB  |  2,003 lines

  1. /*
  2.  * gen.c
  3.  *
  4.  * $Id: gen.c,v 1.7 1994/03/25 19:40:05 parrt Exp parrt $
  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.20
  30.  * Terence Parr
  31.  * Purdue University
  32.  * With AHPCRC, University of Minnesota
  33.  * 1989-1994
  34.  */
  35. #include <stdio.h>
  36. #ifdef __cplusplus
  37. #ifndef __STDC__
  38. #define __STDC__
  39. #endif
  40. #endif
  41. #include <ctype.h>
  42. #include "set.h"
  43. #include "syn.h"
  44. #include "hash.h"
  45. #include "generic.h"
  46. #include "dlgdef.h"
  47.  
  48. #define NumExprPerLine    4
  49. static     int on1line=0;
  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.  Junctions have many types */
  58.     (void (*)(...)) genRuleRef,
  59.     (void (*)(...)) genToken,
  60.     (void (*)(...)) genAction
  61. };
  62. #else
  63. void (*C_Trans[NumNodeTypes+1])() = {
  64.     NULL,
  65.     NULL,                    /* See next table.  Junctions have many types */
  66.     genRuleRef,
  67.     genToken,
  68.     genAction
  69. };
  70. #endif
  71.  
  72. /* C_JTrans[Junction type] == pointer to function that knows how to translate that
  73.  * kind of junction node.
  74.  */
  75. #ifdef __cplusplus
  76. void (*C_JTrans[NumJuncTypes+1])(...) = {
  77.     NULL,
  78.     (void (*)(...)) genSubBlk,
  79.     (void (*)(...)) genOptBlk,
  80.     (void (*)(...)) genLoopBlk,
  81.     (void (*)(...)) genEndBlk,
  82.     (void (*)(...)) genRule,
  83.     (void (*)(...)) genJunction,
  84.     (void (*)(...)) genEndRule,
  85.     (void (*)(...)) genPlusBlk,
  86.     (void (*)(...)) genLoopBegin
  87. };
  88. #else
  89. void (*C_JTrans[NumJuncTypes+1])() = {
  90.     NULL,
  91.     genSubBlk,
  92.     genOptBlk,
  93.     genLoopBlk,
  94.     genEndBlk,
  95.     genRule,
  96.     genJunction,
  97.     genEndRule,
  98.     genPlusBlk,
  99.     genLoopBegin
  100. };
  101. #endif
  102.  
  103. #define PastWhiteSpace(s)    while (*(s) == ' ' || *(s) == '\t') {s++;}
  104.  
  105. static int tabs = 0;
  106. #define TAB { int i; for (i=0; i<tabs; i++) putc('\t', output); }
  107. static void
  108. #ifdef __STDC__
  109. tab( void )
  110. #else
  111. tab( )
  112. #endif
  113. TAB
  114.  
  115. #ifdef __STDC__
  116. static ActionNode *findImmedAction( Node * );
  117. static void dumpRetValAssign(char *, char *);
  118. static void dumpAfterActions(FILE *output);
  119. static set ComputeErrorSet(Junction *, int);
  120. static void makeErrorClause(Junction *, set, int);
  121. static void DumpFuncHeader( Junction *, RuleEntry * );
  122. static int has_guess_block_as_first_item(Junction *);
  123. static int genExprSets(set *, int);
  124. static void genExprTree( Tree *t, int k );
  125. #else
  126. static ActionNode *findImmedAction();
  127. static void dumpRetValAssign();
  128. static void dumpAfterActions();
  129. static set ComputeErrorSet();
  130. static void makeErrorClause();
  131. static void DumpFuncHeader();
  132. static int has_guess_block_as_first_item();
  133. static int genExprSets();
  134. static void genExprTree();
  135. #endif
  136.  
  137. #define gen(s)            {tab(); fprintf(output, s);}
  138. #define gen1(s,a)        {tab(); fprintf(output, s,a);}
  139. #define gen2(s,a,b)        {tab(); fprintf(output, s,a,b);}
  140. #define gen3(s,a,b,c)    {tab(); fprintf(output, s,a,b,c);}
  141. #define gen4(s,a,b,c,d)    {tab(); fprintf(output, s,a,b,c,d);}
  142. #define gen5(s,a,b,c,d,e)    {tab(); fprintf(output, s,a,b,c,d,e);}
  143. #define gen6(s,a,b,c,d,e,f)    {tab(); fprintf(output, s,a,b,c,d,e,f);}
  144.  
  145. #define _gen(s)            {fprintf(output, s);}
  146. #define _gen1(s,a)        {fprintf(output, s,a);}
  147. #define _gen2(s,a,b)    {fprintf(output, s,a,b);}
  148. #define _gen3(s,a,b,c)    {fprintf(output, s,a,b,c);}
  149. #define _gen4(s,a,b,c,d){fprintf(output, s,a,b,c,d);}
  150. #define _gen5(s,a,b,c,d,e){fprintf(output, s,a,b,c,d,e);}
  151. #define _gen6(s,a,b,c,d,e,f){fprintf(output, s,a,b,c,d,e,f);}
  152.  
  153. static void
  154. #ifdef __STDC__
  155. warn_about_using_gk_option(void)
  156. #else
  157. warn_about_using_gk_option()
  158. #endif
  159. {
  160.     static int warned_already=0;
  161.  
  162.     if ( !DemandLookahead || warned_already ) return;
  163.     warned_already = 1;
  164.     warnNoFL("-gk option could cause trouble for <<...>>? predicates");
  165. }
  166.  
  167. void
  168. #ifdef __STDC__
  169. freeBlkFsets( Junction *q )
  170. #else
  171. freeBlkFsets( q )
  172. Junction *q;
  173. #endif
  174. {
  175.     int i;
  176.     Junction *alt;
  177.     require(q!=NULL, "freeBlkFsets: invalid node");
  178.  
  179.     for (alt=q; alt != NULL; alt= (Junction *) alt->p2 )
  180.     {
  181.         for (i=1; i<=CLL_k; i++) set_free(alt->fset[i]);
  182.     }
  183. }
  184.  
  185. /*
  186.  * Generate a local variable allocation for each token references
  187.  * in this block.
  188.  */
  189. static void
  190. #ifdef __STDC__
  191. genTokenPointers( Junction *q )
  192. #else
  193. genTokenPointers( q )
  194. Junction *q;
  195. #endif
  196. {
  197.     /* Rule refs are counted and can be referenced, but their
  198.      * value is not set to anything useful ever.
  199.      *
  200.      * The ptrs are to be named _tij where i is the current level
  201.      * and j is the element number within an alternative.
  202.      */
  203.     int first=1, t;
  204.     set a;
  205.  
  206.     if ( set_deg(q->tokrefs) == 0 ) return;
  207.     a = set_dup(q->tokrefs);
  208.     gen("ANTLRToken ");
  209.     for (; !set_nil(a); set_rm(t, a))
  210.     {
  211.         t = set_int(a);
  212.         if ( first ) first = 0;
  213.         else _gen(",");
  214.         if ( !DontCopyTokens ) _gen2("_tv%d%d,", BlkLevel, t);
  215.         _gen2("*_t%d%d", BlkLevel, t);
  216.         if ( !DontCopyTokens ) {_gen2("= &_tv%d%d", BlkLevel, t);}
  217.         else _gen("=NULL");
  218.     }
  219.     _gen(";\n");
  220.     set_free(a);
  221. }
  222.  
  223. /*
  224.  * Generate a local variable allocation for each token or rule reference
  225.  * in this block.
  226.  */
  227. static void
  228. #ifdef __STDC__
  229. genASTPointers( Junction *q )
  230. #else
  231. genASTPointers( q )
  232. Junction *q;
  233. #endif
  234. {
  235.     int first=1, t;
  236.     set a;
  237.  
  238.     gen("AST ");
  239.     if ( set_deg(q->tokrefs) > 0 )
  240.     {
  241.         a = set_dup(q->tokrefs);
  242.         for (; !set_nil(a); set_rm(t, a))
  243.         {
  244.             t = set_int(a);
  245.             if ( first ) first = 0;
  246.             else _gen(",");
  247.             _gen2("*_ast%d%d=NULL", BlkLevel, t);
  248.         }
  249.         set_free(a);
  250.     }
  251.     if ( set_deg(q->rulerefs) > 0 )
  252.     {
  253.         a = set_dup(q->rulerefs);
  254.         for (; !set_nil(a); set_rm(t, a))
  255.         {
  256.             t = set_int(a);
  257.             if ( first ) first = 0;
  258.             else _gen(",");
  259.             _gen2("*_ast%d%d=NULL", BlkLevel, t);
  260.         }
  261.         set_free(a);
  262.     }
  263.     _gen(";\n");
  264. }
  265.  
  266. static void
  267. #ifdef __STDC__
  268. BLOCK_Head( void )
  269. #else
  270. BLOCK_Head( )
  271. #endif
  272. {
  273.     gen("{\n");
  274.     tabs++;
  275.     if ( !GenCC ) gen1("zzBLOCK(zztasp%d);\n", BlkLevel);
  276. }
  277.  
  278. static void
  279. #ifdef __STDC__
  280. BLOCK_Tail( void )
  281. #else
  282. BLOCK_Tail( )
  283. #endif
  284. {
  285.     if ( !GenCC ) gen1("zzEXIT(zztasp%d);\n", BlkLevel);
  286.     if ( !GenCC ) gen("}\n");
  287.     tabs--;
  288.     gen("}\n");
  289. }
  290.  
  291. static void
  292. #ifdef __STDC__
  293. BLOCK_Preamble( Junction *q )
  294. #else
  295. BLOCK_Preamble( q )
  296. Junction *q;
  297. #endif
  298. {
  299.     ActionNode *a;
  300.     Junction *begin;
  301.  
  302.     BLOCK_Head();
  303.     if ( GenCC ) genTokenPointers(q);
  304.     if ( GenCC&&GenAST ) genASTPointers(q);
  305.     if ( q->jtype == aPlusBlk ) gen("int zzcnt=1;\n");
  306.     if ( q->parm != NULL && !q->predparm ) gen1("zzaPush(%s);\n", q->parm)
  307.     else if ( !GenCC ) gen("zzMake0;\n");
  308.     if ( !GenCC ) gen("{\n");
  309.     if ( q->jtype == aLoopBegin ) begin = (Junction *) ((Junction *)q->p1);
  310.     else begin = q;
  311.     if ( has_guess_block_as_first_item(begin) )
  312.     {
  313.         gen("zzGUESS_BLOCK\n");
  314.     }
  315.     if ( q->jtype == aLoopBegin )
  316.         a = findImmedAction( ((Junction *)q->p1)->p1 );    /* look at aLoopBlk */
  317.     else
  318.         a = findImmedAction( q->p1 );
  319.     if ( a!=NULL && !a->is_predicate ) {
  320.         dumpAction(a->action, output, tabs, a->file, a->line, 1);
  321.         a->done = 1;    /* remove action. We have already handled it */
  322.     }
  323. }
  324.  
  325. /* If predicates are allowed in parsing expressions:
  326.  *
  327.  * (    production 1
  328.  * |    production 2
  329.  * ...
  330.  * |    production n
  331.  * )
  332.  *
  333.  * where production 1 yields visible predicates: <<pred>>? <<pred2>>?
  334.  *
  335.  * generates:
  336.  *
  337.  * if ( (context_of_pred && pred) &&
  338.  *        (context_of_pred2 && pred2) &&
  339.  *        (production 1 prediction) ) {
  340.  *         ...
  341.  * }
  342.  * else if ( production 2 prediction ) {
  343.  *         ...
  344.  * }
  345.  * ...
  346.  *
  347.  *        p1
  348.  *        |
  349.  *        p2--p3
  350.  *
  351.  * results in
  352.  *
  353.  * if ( (production 1 prediction) &&
  354.  *        (context_of_p1 && p1) &&
  355.  *        ((context_of_p2 && p2)||
  356.  *        (context_of_p3 && p3)) &&
  357.  *        ) {
  358.  *         ...
  359.  * }
  360.  *
  361.  * If no context, then just test expression.
  362.  */
  363. void
  364. #ifdef __STDC__
  365. genPredTree( Predicate *p, Junction *j )
  366. #else
  367. genPredTree( p, j )
  368. Predicate *p;
  369. Junction *j;
  370. #endif
  371. {
  372.     int context_was_present = 0;
  373.  
  374.     _gen("(");
  375.     for (; p!=NULL; p=p->right)
  376.     {
  377.         if ( HoistPredicateContext )
  378.         {
  379.             context_was_present = 0;
  380.             if ( LL_k>1 && p->tcontext!=NULL )
  381.             {
  382.                 context_was_present = 1;
  383.                 _gen("((");
  384.                 genExprTree(p->tcontext, 1);
  385.                 _gen(") ? ");
  386.             }
  387.             else if ( LL_k==1 && set_deg(p->scontext[1])>0 )
  388.             {
  389.                 context_was_present = 1;
  390.                 _gen("((");
  391.                 genExprSets(&(p->scontext[0]), CLL_k);
  392.                 _gen(") ? ");
  393.             }
  394.         }
  395.  
  396.         _gen("(");
  397.         dumpAction(p->expr, output, 0, j->file, j->line, 0);
  398.         _gen(")");
  399.  
  400.         if ( HoistPredicateContext && context_was_present ) _gen(" : 1)");
  401.  
  402.         if ( p->down!=NULL )
  403.         {
  404.             _gen("&&");
  405.             genPredTree(p->down, j);
  406.         }
  407.  
  408.         if ( p->right!=NULL ) _gen("||");
  409.     }
  410.     _gen(")");
  411. }
  412.  
  413. static void
  414. #ifdef __STDC__
  415. genExprTree( Tree *t, int k )
  416. #else
  417. genExprTree( t, k )
  418. Tree *t;
  419. int k;
  420. #endif
  421. {
  422.     require(t!=NULL, "genExprTree: NULL tree");
  423.     
  424.     if ( t->token == ALT )
  425.     {
  426.         _gen("("); genExprTree(t->down, k); _gen(")");
  427.         if ( t->right!=NULL )
  428.         {
  429.             _gen("||");
  430.             on1line++;
  431.             if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
  432.             _gen("("); genExprTree(t->right, k); _gen(")");
  433.         }
  434.         return;
  435.     }
  436.     if ( t->down!=NULL ) _gen("(");
  437.     _gen1("LA(%d)==",k);
  438.     if ( TokenString(t->token) == NULL ) _gen1("%d", t->token)
  439.     else _gen1("%s", TokenString(t->token));
  440.     if ( t->down!=NULL )
  441.     {
  442.         _gen("&&");
  443.         on1line++;
  444.         if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
  445.         _gen("("); genExprTree(t->down, k+1); _gen(")");
  446.     }
  447.     if ( t->down!=NULL ) _gen(")");
  448.     if ( t->right!=NULL )
  449.     {
  450.         _gen("||");
  451.         on1line++;
  452.         if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
  453.         _gen("("); genExprTree(t->right, k); _gen(")");
  454.     }
  455. }
  456.  
  457. /*
  458.  * Generate LL(k) type expressions of the form:
  459.  *
  460.  *         (LA(1) == T1 || LA(1) == T2 || ... || LA(1) == Tn) &&
  461.  *         (LA(2) == T1 || LA(2) == T2 || ... || LA(2) == Tn) &&
  462.  *            .....
  463.  *         (LA(k) == T1 || LA(k) == T2 || ... || LA(k) == Tn)
  464.  *
  465.  * If GenExprSets generate:
  466.  *
  467.  *        (setwdi[LA(1)]&(1<<j)) && (setwdi[LA(2)]&(1<<j)) ...
  468.  *
  469.  * where n is set_deg(expr) and Ti is some random token and k is the last nonempty
  470.  * set in fset <=CLL_k.
  471.  * k=1..CLL_k where CLL_k >= 1.
  472.  *
  473.  * This routine is visible only to this file and cannot answer a TRANS message.
  474.  *
  475.  */
  476. static int
  477. #ifdef __STDC__
  478. genExpr( Junction *j )
  479. #else
  480. genExpr( j )
  481. Junction *j;
  482. #endif
  483. {
  484.     int max_k;
  485.  
  486.     /* if full LL(k) is sufficient, then don't use approximate (-ck) lookahead
  487.      * from CLL_k..LL_k
  488.      */
  489.     {
  490.         int limit;
  491.         if ( j->ftree!=NULL ) limit = LL_k;
  492.         else limit = CLL_k;
  493.         max_k = genExprSets(j->fset, limit);
  494.     }
  495.  
  496.     /* Do tests for real tuples from other productions that conflict with
  497.      * artificial tuples generated by compression (using sets of tokens
  498.      * rather than k-trees).
  499.      */
  500.     if ( j->ftree != NULL )
  501.     {
  502.         _gen(" && !("); genExprTree(j->ftree, 1); _gen(")");
  503.     }
  504.  
  505.     if ( ParseWithPredicates && j->predicate!=NULL )
  506.     {
  507.         Predicate *p = j->predicate;
  508.         warn_about_using_gk_option();
  509.         _gen("&&");
  510.         genPredTree(p, j);
  511.     }
  512.  
  513.     return max_k;
  514. }
  515.  
  516. static int
  517. #ifdef __STDC__
  518. genExprSets( set *fset, int limit )
  519. #else
  520. genExprSets( fset, limit )
  521. set *fset;
  522. int limit;
  523. #endif
  524. {
  525.     int k = 1;
  526.     int max_k = 0;
  527.     unsigned *e, *g, firstTime=1;
  528.  
  529.     if ( GenExprSets )
  530.     {
  531.         while ( !set_nil(fset[k]) && k<=limit )
  532.         {
  533.             if ( set_deg(fset[k])==1 )    /* too simple for a set? */
  534.             {
  535.                 int e;
  536.                 _gen1("(LA(%d)==",k);
  537.                 e = set_int(fset[k]);
  538.                 if ( TokenString(e) == NULL ) _gen1("%d)", e)
  539.                 else _gen1("%s)", TokenString(e));
  540.             }
  541.             else
  542.             {
  543.                 NewSet();
  544.                 FillSet( fset[k] );
  545.                 _gen3("(setwd%d[LA(%d)]&0x%x)", wordnum, k, 1<<setnum);
  546.             }
  547.             if ( k>max_k ) max_k = k;
  548.             if ( k == CLL_k ) break;
  549.             k++;
  550.             if ( !set_nil(fset[k]) && k<=limit ) _gen(" && ");
  551.             on1line++;
  552.             if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
  553.         }
  554.         return max_k;
  555.     }
  556.  
  557.     while ( !set_nil(fset[k]) && k<=limit )
  558.     {
  559.         if ( (e=g=set_pdq(fset[k])) == NULL ) fatal("genExpr: cannot allocate IF expr pdq set");
  560.         for (; *e!=nil; e++)
  561.         {
  562.             if ( !firstTime ) _gen(" || ") else { _gen("("); firstTime = 0; }
  563.             on1line++;
  564.             if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
  565.             _gen1("LA(%d)==",k);
  566.             if ( TokenString(*e) == NULL ) _gen1("%d", *e)
  567.             else _gen1("%s", TokenString(*e));
  568.         }
  569.         free( g );
  570.         _gen(")");
  571.         if ( k>max_k ) max_k = k;
  572.         if ( k == CLL_k ) break;
  573.         k++;
  574.         if ( !set_nil(fset[k]) && k<=limit ) { firstTime=1; _gen(" && "); }
  575.         on1line++;
  576.         if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
  577.     }
  578.     return max_k;
  579. }
  580.  
  581. /*
  582.  * Generate code for any type of block.  If the last alternative in the block is
  583.  * empty (not even an action) don't bother doing it.  This permits us to handle
  584.  * optional and loop blocks as well.
  585.  *
  586.  * Only do this block, return after completing the block.
  587.  * This routine is visible only to this file and cannot answer a TRANS message.
  588.  */
  589. static set
  590. #ifdef __STDC__
  591. genBlk( Junction *q, int jtype, int *max_k, int *need_right_curly )
  592. #else
  593. genBlk( q, jtype, max_k, need_right_curly )
  594. Junction *q;
  595. int jtype;
  596. int *max_k;
  597. int *need_right_curly;
  598. #endif
  599. {
  600.     set f;
  601.     Junction *alt;
  602.     int a_guess_in_block = 0;
  603.     require(q!=NULL,                "genBlk: invalid node");
  604.     require(q->ntype == nJunction,    "genBlk: not junction");
  605.  
  606.     *need_right_curly=0;
  607.     if ( q->p2 == NULL )    /* only one alternative?  Then don't need if */
  608.     {    
  609.         if ( first_item_is_guess_block((Junction *)q->p1)!=NULL )
  610.         {
  611.             warnFL("(...)? as only alternative of block is unnecessary", FileStr[q->file], q->line);
  612.             gen("zzGUESS\n");    /* guess anyway to make output code consistent */
  613.             gen("if ( !zzrv )\n");
  614.         }
  615.         TRANS(q->p1);
  616.         return empty;        /* no decision to be made-->no error set */
  617.     }
  618.  
  619.     f = First(q, 1, jtype, max_k);
  620.     for (alt=q; alt != NULL; alt= (Junction *) alt->p2 )
  621.     {
  622.         if ( alt->p2 == NULL )                    /* chk for empty alt */
  623.         {    
  624.             Node *p = alt->p1;
  625.             if ( p->ntype == nJunction )
  626.             {
  627.                 /* we have empty alt */
  628.                 if ( ((Junction *)p)->p1 == (Node *)q->end )
  629.                 {
  630.                     break;                        /* don't do this one, quit */
  631.                 }
  632.             }
  633.         }
  634.         if ( alt != q ) gen("else ")
  635.         else
  636.         {
  637.             if ( DemandLookahead )
  638.                 if ( !GenCC ) {gen1("LOOK(%d);\n", *max_k);}
  639.                 else gen1("look(%d);\n", *max_k);
  640.         }
  641.         if ( alt!=q )
  642.         {
  643.             _gen("{\n");
  644.             tabs++;
  645.             (*need_right_curly)++;
  646.             /* code to restore state if a prev alt didn't follow guess */
  647.             if ( a_guess_in_block )
  648.                    if ( !GenCC ) {gen("if ( zzguessing ) zzGUESS_DONE;\n");}
  649.                 else gen("if ( guessing ) zzGUESS_DONE;\n");
  650.         }
  651.         if ( first_item_is_guess_block((Junction *)alt->p1)!=NULL )
  652.         {
  653.             a_guess_in_block = 1;
  654.             gen("zzGUESS\n");
  655.         }
  656.         gen("if ( ");
  657.         if ( first_item_is_guess_block((Junction *)alt->p1)!=NULL ) _gen("!zzrv && ");
  658.         genExpr(alt);
  659.         _gen(" ) ");
  660.         _gen("{\n");
  661.         tabs++;
  662.         TRANS(alt->p1);
  663.         --tabs;
  664.         gen("}\n");
  665.     }
  666.     return f;
  667. }
  668.  
  669. static int
  670. #ifdef __STDC__
  671. has_guess_block_as_first_item( Junction *q )
  672. #else
  673. has_guess_block_as_first_item( q )
  674. Junction *q;
  675. #endif
  676. {
  677.     Junction *alt;
  678.  
  679.     for (alt=q; alt != NULL; alt= (Junction *) alt->p2 )
  680.     {
  681.         if ( first_item_is_guess_block((Junction *)alt->p1)!=NULL ) return 1;
  682.     }
  683.     return 0;
  684. }
  685.  
  686. /* return NULL if 1st item of alt is (...)? block; else return ptr to aSubBlk node
  687.  * of (...)?;  This function ignores actions and predicates.
  688.  */
  689. Junction *
  690. #ifdef __STDC__
  691. first_item_is_guess_block( Junction *q )
  692. #else
  693. first_item_is_guess_block( q )
  694. Junction *q;
  695. #endif
  696. {
  697.     while ( q!=NULL && ((q->ntype==nJunction && q->jtype==Generic) || q->ntype==nAction) )
  698.     {
  699.         if ( q->ntype==nJunction ) q = (Junction *)q->p1;
  700.         else q = (Junction *) ((ActionNode *)q)->next;
  701.     }
  702.  
  703.     if ( q==NULL ) return NULL;
  704.     if ( q->ntype!=nJunction ) return NULL;
  705.     if ( q->jtype!=aSubBlk ) return NULL;
  706.     if ( !q->guess ) return NULL;
  707.     return q;
  708. }
  709.  
  710. /* Generate an action.  Don't if action is NULL which means that it was already
  711.  * handled as an init action.
  712.  */
  713. void
  714. #ifdef __STDC__
  715. genAction( ActionNode *p )
  716. #else
  717. genAction( p )
  718. ActionNode *p;
  719. #endif
  720. {
  721.     require(p!=NULL,            "genAction: invalid node and/or rule");
  722.     require(p->ntype==nAction,    "genAction: not action");
  723.     
  724.     if ( !p->done )
  725.     {
  726.         if ( p->is_predicate )
  727.         {
  728.             gen("if (!(");
  729.             /* make sure that '#line n' is on front of line */
  730.             if ( GenLineInfo && p->file != -1 ) _gen("\n");
  731.             dumpAction(p->action, output, 0, p->file, p->line, 0);
  732.             if ( p->pred_fail != NULL )
  733.             {
  734.                 _gen("))\n");
  735. /*                if ( FoundGuessBlk ) gen("zzNON_GUESS_MODE {\n");*/
  736.                 tabs++;
  737.                 gen1("%s;\n", p->pred_fail);
  738.                 tabs--;
  739. /*                if ( FoundGuessBlk ) gen("}\n");*/
  740.             }
  741.             else _gen1(")) {zzfailed_pred((ANTLRChar *)\"%s\");}\n",p->action);
  742.         }
  743.         else
  744.         {
  745.             if ( FoundGuessBlk )
  746.                 if ( GenCC ) {gen("if ( !guessing ) {\n");}
  747.                 else gen("zzNON_GUESS_MODE {\n");
  748.             dumpAction(p->action, output, tabs, p->file, p->line, 1);
  749.             if ( FoundGuessBlk ) gen("}\n");
  750.         }
  751.     }
  752.     TRANS(p->next)
  753. }
  754.  
  755. /*
  756.  *        if invoking rule has !noAST pass zzSTR to rule ref and zzlink it in
  757.  *        else pass addr of temp root ptr (&_ast) (don't zzlink it in).
  758.  *
  759.  *        if ! modifies rule-ref, then never link it in and never pass zzSTR.
  760.  *        Always pass address of temp root ptr.
  761.  */
  762. void
  763. #ifdef __STDC__
  764. genRuleRef( RuleRefNode *p )
  765. #else
  766. genRuleRef( p )
  767. RuleRefNode *p;
  768. #endif
  769. {
  770.     Junction *q;
  771.     RuleEntry *r, *r2;
  772.     char *parm = "";
  773.     require(p!=NULL,            "genRuleRef: invalid node and/or rule");
  774.     require(p->ntype==nRuleRef, "genRuleRef: not rule reference");
  775.     
  776.     r = (RuleEntry *) hash_get(Rname, p->text);
  777.     if ( r == NULL ) {warnFL( eMsg1("rule %s not defined", p->text), FileStr[p->file], p->line ); return;}
  778.     r2 = (RuleEntry *) hash_get(Rname, p->rname);
  779.     if ( r2 == NULL ) {warnNoFL("Rule hash table is screwed up beyond belief"); return;}
  780.  
  781.     if ( FoundGuessBlk )
  782.         if ( GenCC ) {gen("if ( !guessing ) {\n");}
  783.         else gen("zzNON_GUESS_MODE {\n");
  784.  
  785.     tab();
  786.     if ( GenAST )
  787.     {
  788.         if ( GenCC ) {
  789.             if ( r2->noAST || p->astnode==ASTexclude )
  790.             {
  791.                 _gen("_ast = NULL;\n"); tab();
  792.                 parm = "&_ast";
  793.             }
  794.             else {
  795.                 _gen("_astp = (_tail==NULL)?(&_sibling):(&(_tail->_right));\n");
  796.                 parm = "_astp";
  797.             }
  798.             tab();
  799.         }
  800.         else {
  801.             if ( r2->noAST || p->astnode==ASTexclude )
  802.             {
  803.                 _gen("_ast = NULL; ");
  804.                 parm = "&_ast";
  805.             }
  806.             else parm = "zzSTR";
  807.         }
  808.         if ( p->assign!=NULL )
  809.         {
  810.             if ( !HasComma(p->assign) ) {_gen1("%s = ",p->assign);}
  811.             else _gen1("{ struct _rv%d _trv; _trv = ", r->rulenum);
  812.         }
  813.         _gen5("%s%s(%s%s%s);", RulePrefix,
  814.                                p->text,
  815.                                parm,
  816.                                (p->parms!=NULL)?",":"",
  817.                                (p->parms!=NULL)?p->parms:"");
  818.         if ( !r2->noAST && p->astnode == ASTinclude )
  819.         {
  820.             if ( GenCC ) {
  821.                 _gen("\n");
  822.                 if ( r2->noAST || p->astnode==ASTexclude )
  823.                     {gen2("_ast%d%d = _ast\n", BlkLevel-1, p->elnum);}
  824.                 else
  825.                     {gen2("_ast%d%d = *((AST **)_astp);\n", BlkLevel-1, p->elnum);}
  826.                 tab();
  827.             }
  828.             else _gen(" ");
  829.             if ( GenCC ) {_gen("ASTBase::");} else _gen("zz");
  830.             _gen("link(_root, &_sibling, &_tail);");
  831.         }
  832.     }
  833.     else
  834.     {
  835.         if ( p->assign!=NULL )
  836.         {
  837.             if ( !HasComma(p->assign) ) {_gen1("%s = ",p->assign);}
  838.             else _gen1("{ struct _rv%d _trv; _trv = ", r->rulenum);
  839.         }
  840.         _gen3("%s%s(%s);", RulePrefix, p->text, (p->parms!=NULL)?p->parms:"");
  841.         if ( p->assign!=NULL ) _gen("\n");
  842.     }
  843.     q = RulePtr[r->rulenum];    /* find definition of ref'd rule */
  844.     if ( p->assign!=NULL ) {
  845.         if ( HasComma(p->assign) )
  846.         {
  847.             _gen("\n");
  848.             dumpRetValAssign(p->assign, q->ret);
  849.             _gen("}");
  850.         }
  851.     }
  852.     _gen("\n");
  853.     if ( FoundGuessBlk ) {
  854.         gen("} else {\n");
  855.         gen5("%s%s(%s%s%s);\n", RulePrefix,
  856.                                p->text,
  857.                                parm,
  858.                                (p->parms!=NULL && *parm!='\0')?",":"",
  859.                                (p->parms!=NULL)?p->parms:"");
  860.         gen("}\n");
  861.     }
  862.     TRANS(p->next)
  863. }
  864.  
  865. /*
  866.  * Generate code to match a token.
  867.  *
  868.  * Getting the next token is tricky.  We want to ensure that any action
  869.  * following a token is executed before the next GetToken();
  870.  */ 
  871. void
  872. #ifdef __STDC__
  873. genToken( TokNode *p )
  874. #else
  875. genToken( p )
  876. TokNode *p;
  877. #endif
  878. {
  879.     RuleEntry *r;
  880.     ActionNode *a;
  881.     require(p!=NULL,            "genToken: invalid node and/or rule");
  882.     require(p->ntype==nToken,    "genToken: not token");
  883.     
  884.     r = (RuleEntry *) hash_get(Rname, p->rname);
  885.     if ( r == NULL ) {warnNoFL("Rule hash table is screwed up beyond belief"); return;}
  886.     if ( !set_nil(p->tset) )
  887.     {
  888.         unsigned e;
  889.         set b;
  890.         b = set_dup(p->tset);
  891.         e = DefErrSet(&b, 0);
  892.         if ( GenCC ) {gen1("setmatch(err%d);", e);}
  893.         else gen1("zzsetmatch(zzerr%d);", e);
  894.         set_free(b);
  895.     }
  896.     else if ( TokenString(p->token)!=NULL )
  897.         gen1("zzmatch(%s);", TokenString(p->token))
  898.     else
  899.         gen1("zzmatch(%d);", p->token);
  900.  
  901.     a = findImmedAction( p->next );
  902.     /* generate the token copies */
  903.     if ( GenCC && p->elnum>0 )
  904.     {
  905.         if ( !DontCopyTokens ) {_gen2(" *_t%d%d = *((ANTLRToken *)LT(1));", BlkLevel-1, p->elnum);}
  906.         else _gen2(" _t%d%d = (ANTLRToken *)LT(1);", BlkLevel-1, p->elnum);
  907.         if ( LL_k>1 ) _gen(" labase++;");
  908.         _gen("\n");
  909.         tab();
  910.     }
  911.     if ( GenAST )
  912.     {
  913.         if ( FoundGuessBlk && p->astnode != ASTexclude )
  914.         {
  915.             if ( GenCC ) {_gen("if ( !guessing ) {\n"); tab();}
  916.             else {_gen("zzNON_GUESS_MODE {\n"); tab();}
  917.         }
  918.         if ( !r->noAST )
  919.         {
  920.             if ( GenCC && p->astnode != ASTexclude ) {
  921.                 _gen("\n");
  922.                 gen4("_ast%d%d = new AST(_t%d%d);\n", BlkLevel-1, p->elnum, BlkLevel-1, p->elnum);
  923.                 tab();
  924.             }
  925.             if ( GenCC && p->astnode != ASTexclude ) {_gen2("_ast%d%d->", BlkLevel-1, p->elnum);}
  926.             else _gen(" ");
  927.             if ( p->astnode==ASTchild ) {
  928.                 if ( !GenCC ) _gen("zz");
  929.                 _gen("subchild(_root, &_sibling, &_tail);");
  930.             }
  931.             else if ( p->astnode==ASTroot ) {
  932.                 if ( !GenCC ) _gen("zz");
  933.                 _gen("subroot(_root, &_sibling, &_tail);");
  934.             }
  935.             if ( GenCC && p->astnode != ASTexclude ) {
  936.                 _gen("\n");
  937.                 tab();
  938.             }
  939.         }
  940.         else if ( !GenCC ) _gen(" zzastDPush;");
  941.         if ( FoundGuessBlk && p->astnode != ASTexclude )
  942.             {_gen("}\n"); tab();}
  943.     }
  944.     if ( a != NULL )
  945.     {
  946.         /* delay next token fetch until after action */
  947.         _gen("\n");
  948.         if ( a->is_predicate )
  949.         {
  950.             gen("if (!(");
  951.             dumpAction(a->action, output, 0, a->file, a->line, 0);
  952.             if ( a->pred_fail != NULL )
  953.             {
  954.                 _gen("))\n");
  955. /*                if ( FoundGuessBlk ) gen("zzNON_GUESS_MODE {\n");*/
  956.                 tabs++;
  957.                 gen1("%s;\n", a->pred_fail);
  958.                 tabs--;
  959. /*                if ( FoundGuessBlk ) gen("}\n");*/
  960.             }
  961.             else _gen1(")) {zzfailed_pred((ANTLRChar *)\"%s\");}\n",a->action);
  962.         }
  963.         else
  964.         {
  965.             if ( FoundGuessBlk )
  966.                 if ( GenCC ) {gen("if ( !guessing ) {\n");}
  967.                 else gen("zzNON_GUESS_MODE {\n");
  968.             dumpAction(a->action, output, tabs, a->file, a->line, 1);
  969.             if ( FoundGuessBlk ) gen("}\n");
  970.         }
  971.         a->done = 1;
  972.         if ( !DemandLookahead ) {
  973.             if ( GenCC ) gen(" consume();\n")
  974.             else _gen(" zzCONSUME;\n");
  975.         }
  976.         else gen("\n");
  977.         TRANS( a->next );
  978.     }
  979.     else
  980.     {
  981.         if ( !DemandLookahead ) {
  982.             if ( GenCC ) _gen(" consume();\n")
  983.             else _gen(" zzCONSUME;\n");
  984.         }
  985.         else _gen("\n");
  986.         TRANS(p->next);
  987.     }
  988. }
  989.  
  990. void
  991. #ifdef __STDC__
  992. genOptBlk( Junction *q )
  993. #else
  994. genOptBlk( q )
  995. Junction *q;
  996. #endif
  997. {
  998.     int max_k;
  999.     set f;
  1000.     int need_right_curly;
  1001.     require(q!=NULL,                "genOptBlk: invalid node and/or rule");
  1002.     require(q->ntype == nJunction,    "genOptBlk: not junction");
  1003.     require(q->jtype == aOptBlk,    "genOptBlk: not optional block");
  1004.  
  1005.     BLOCK_Preamble(q);
  1006.     BlkLevel++;
  1007.     f = genBlk(q, aOptBlk, &max_k, &need_right_curly);
  1008.     set_free(f);
  1009.     freeBlkFsets(q);
  1010.     BlkLevel--;
  1011.     if ( first_item_is_guess_block((Junction *)q->p1)!=NULL )
  1012.     {
  1013.         if ( !GenCC ) {gen("else if ( zzguessing ) zzGUESS_DONE;\n");}
  1014.         else gen("else if ( guessing ) zzGUESS_DONE;\n");
  1015.     }
  1016.     { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
  1017.     BLOCK_Tail();
  1018.     if (q->end->p1 != NULL) TRANS(q->end->p1);
  1019. }
  1020.  
  1021. /*
  1022.  * Generate code for a loop blk of form:
  1023.  *
  1024.  *                 |---|
  1025.  *                 v   |
  1026.  *               --o-G-o-->o--
  1027.  */
  1028. void
  1029. #ifdef __STDC__
  1030. genLoopBlk( Junction *begin, Junction *q, Junction *start, int max_k )
  1031. #else
  1032. genLoopBlk( begin, q, start, max_k )
  1033. Junction *begin;
  1034. Junction *q;
  1035. Junction *start;    /* where to start generating code from */
  1036. int max_k;
  1037. #endif
  1038. {
  1039.     set f;
  1040.     int need_right_curly;
  1041.     require(q->ntype == nJunction,    "genLoopBlk: not junction");
  1042.     require(q->jtype == aLoopBlk,    "genLoopBlk: not loop block");
  1043.  
  1044.     if ( q->visited ) return;
  1045.     q->visited = TRUE;
  1046.     if ( q->p2 == NULL )    /* only one alternative? */
  1047.     {
  1048. #ifdef DUM
  1049.         int dum_k;
  1050. /* haven't we already done this?  I took it out as redundant TJP March 1994 */
  1051.         f = First(q, 1, aLoopBlk, &dum_k);
  1052. #endif
  1053.         if ( DemandLookahead )
  1054.             if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}
  1055.             else gen1("look(%d);\n", max_k);
  1056.         gen("while ( ");
  1057.         if ( begin->parm!=NULL && begin->predparm ) _gen1("(%s) && ", begin->parm);
  1058.         genExpr(begin);
  1059. /* WAS:
  1060.         if ( start!=NULL )
  1061.         {
  1062.             genExpr(start);
  1063.         }
  1064.         else genExpr(q);
  1065. */
  1066.         /* if no predicates have been hoisted for this single alt (..)*
  1067.          * do so now
  1068.          */
  1069.         if ( ParseWithPredicates && begin->predicate==NULL )
  1070.         {
  1071.             Predicate *a = find_predicates((Node *)q->p1);
  1072.             if ( a!=NULL )
  1073.             {
  1074.                 _gen("&&");
  1075.                 genPredTree(a, q);
  1076.             }
  1077.         }
  1078.         _gen(" ) {\n");
  1079.         tabs++;
  1080.         TRANS(q->p1);
  1081.         if ( !GenCC ) gen1("zzLOOP(zztasp%d);\n", BlkLevel-1);
  1082.         if ( DemandLookahead )
  1083.             if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}
  1084.             else gen1("look(%d);\n", max_k);
  1085.         --tabs;
  1086.         gen("}\n");
  1087.         freeBlkFsets(q);
  1088. #ifdef DUM
  1089.          set_free(f);
  1090. #endif
  1091.         q->visited = FALSE;
  1092.         return;
  1093.     }
  1094.     if (begin->parm!=NULL && begin->predparm) {_gen1("while (%s) {", begin->parm);}
  1095.     else gen("while ( 1 ) {\n");
  1096.     tabs++;
  1097. #ifdef DUM
  1098. Was:
  1099.     if ( start!=NULL )
  1100.     {
  1101.         if ( DemandLookahead )
  1102.             if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}
  1103.             else gen1("look(%d);\n", max_k);
  1104.         gen("if ( ");
  1105.         genExpr((Junction *)start->p2);
  1106.         _gen(" ) break;\n");
  1107.     }
  1108. #endif
  1109.     f = genBlk(q, aLoopBlk, &max_k, &need_right_curly);
  1110.     set_free(f);
  1111.     freeBlkFsets(q);
  1112.  
  1113. /* DON'T NEED?
  1114.     if ( start==NULL ) gen("else break;\n");        /* code for exiting loop */
  1115.  
  1116.     /* generate code for terminating loop (this is optional branch) */
  1117. /*  DON"T REALLY NEED; can let just fall out of loop.
  1118.     if ( DemandLookahead )
  1119.         if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}
  1120.         else gen1("look(%d);\n", max_k);
  1121.     gen("else if ( ");
  1122.     genExpr((Junction *)start->p2);
  1123.     _gen(" ) break;\n");
  1124. */
  1125.     gen("else break;\n");        /* code for exiting loop "for sure" */
  1126.  
  1127.     { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
  1128.     if ( !GenCC ) gen1("zzLOOP(zztasp%d);\n", BlkLevel-1);
  1129.     --tabs;
  1130.     gen("}\n");
  1131.     q->visited = FALSE;
  1132. }
  1133.  
  1134. /*
  1135.  * Generate code for a loop blk of form:
  1136.  *
  1137.  *                          |---|
  1138.  *                         v   |
  1139.  *               --o-->o-->o-G-o-->o--
  1140.  *                   |           ^
  1141.  *                   v           |
  1142.  *                     o-----------o
  1143.  *
  1144.  * q->end points to the last node (far right) in the blk.  Note that q->end->jtype
  1145.  * must be 'EndBlk'.
  1146.  *
  1147.  * Generate code roughly of the following form:
  1148.  *
  1149.  *    do {
  1150.  *        ... code for alternatives ...
  1151.  *  } while ( First Set of aLoopBlk );
  1152.  *
  1153.  *    OR if > 1 alternative
  1154.  *
  1155.  *    do {
  1156.  *        ... code for alternatives ...
  1157.  *        else break;
  1158.  *  } while ( 1 );
  1159.  */
  1160. void
  1161. #ifdef __STDC__
  1162. genLoopBegin( Junction *q )
  1163. #else
  1164. genLoopBegin( q )
  1165. Junction *q;
  1166. #endif
  1167. {
  1168.     set f;
  1169.     int i;
  1170.     int max_k;
  1171.     require(q!=NULL,                "genLoopBegin: invalid node and/or rule");
  1172.     require(q->ntype == nJunction,    "genLoopBegin: not junction");
  1173.     require(q->jtype == aLoopBegin,    "genLoopBegin: not loop block");
  1174.     require(q->p2!=NULL,            "genLoopBegin: invalid Loop Graph");
  1175.  
  1176.     BLOCK_Preamble(q);
  1177.     BlkLevel++;
  1178.     f = First(q, 1, aLoopBegin, &max_k);
  1179.     genLoopBlk( q, (Junction *)q->p1, q, max_k );
  1180. #ifdef DUM
  1181. WAS:
  1182.     if ( LL_k>1 && !set_nil(q->fset[2]) )
  1183.         genLoopBlk( q, (Junction *)q->p1, q, max_k );
  1184.     else genLoopBlk( q, (Junction *)q->p1, NULL, max_k );
  1185. #endif
  1186.     for (i=1; i<=CLL_k; i++) set_free(q->fset[i]);
  1187.     for (i=1; i<=CLL_k; i++) set_free(((Junction *)q->p2)->fset[i]);
  1188.     --BlkLevel;
  1189.     BLOCK_Tail();
  1190.     set_free(f);
  1191.     if (q->end->p1 != NULL) TRANS(q->end->p1);
  1192. }
  1193.  
  1194. /*
  1195.  * Generate code for a loop blk of form:
  1196.  *
  1197.  *                      |---|
  1198.  *                     v   |
  1199.  *                   --o-G-o-->o--
  1200.  *
  1201.  * q->end points to the last node (far right) in the blk.  Note that q->end->jtype
  1202.  * must be 'EndBlk'.
  1203.  *
  1204.  * Generate code roughly of the following form:
  1205.  *
  1206.  *    do {
  1207.  *        ... code for alternatives ...
  1208.  *  } while ( First Set of aPlusBlk );
  1209.  *
  1210.  *    OR if > 1 alternative
  1211.  *
  1212.  *    do {
  1213.  *        ... code for alternatives ...
  1214.  *        else if not 1st time through, break;
  1215.  *  } while ( 1 );
  1216.  */
  1217. void
  1218. #ifdef __STDC__
  1219. genPlusBlk( Junction *q )
  1220. #else
  1221. genPlusBlk( q )
  1222. Junction *q;
  1223. #endif
  1224. {
  1225.     int max_k;
  1226.     set f;
  1227.     int need_right_curly;
  1228.     require(q!=NULL,                "genPlusBlk: invalid node and/or rule");
  1229.     require(q->ntype == nJunction,    "genPlusBlk: not junction");
  1230.     require(q->jtype == aPlusBlk,    "genPlusBlk: not Plus block");
  1231.     require(q->p2 != NULL,            "genPlusBlk: not a valid Plus block");
  1232.  
  1233.     if ( q->visited ) return;
  1234.     q->visited = TRUE;
  1235.     BLOCK_Preamble(q);
  1236.     BlkLevel++;
  1237.     /* if the ignore flag is set on the 2nd alt and that alt is empty,
  1238.      * then it is the implied optional alternative that we added for (...)+
  1239.      * and, hence, only 1 alt.
  1240.      */
  1241.     if ( ((Junction *)q->p2)->p2 == NULL &&
  1242.          ((Junction *)q->p2)->ignore )            /* only one alternative? */
  1243.     {
  1244.         Predicate *a=NULL;
  1245.         /* if the only alt has a semantic predicate, hoist it; must test before
  1246.          * entering loop.
  1247.          */
  1248.         if ( ParseWithPredicates )
  1249.         {
  1250.             a = find_predicates((Node *)q);
  1251.             if ( a!=NULL ) {
  1252.                 gen("if (");
  1253.                 genPredTree(a, q);
  1254.                 _gen(") {\n");
  1255.             }
  1256.         }
  1257.         gen("do {\n");
  1258.         tabs++;
  1259.         TRANS(q->p1);
  1260.         if ( !GenCC ) gen1("zzLOOP(zztasp%d);\n", BlkLevel-1);
  1261.         f = First(q, 1, aPlusBlk, &max_k);
  1262.         if ( DemandLookahead )
  1263.             if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}
  1264.             else gen1("look(%d);\n", max_k);
  1265.         --tabs;
  1266.         gen("} while ( ");
  1267.         if ( q->parm!=NULL && q->predparm ) _gen1("(%s) && ", q->parm);
  1268.         genExpr(q);
  1269. /*        if ( ParseWithPredicates && a!=NULL )
  1270.         {
  1271.             _gen("&&");
  1272.             genPredTree(a, q);
  1273.         }*/
  1274.         _gen(" );\n");
  1275.         if ( ParseWithPredicates && a!=NULL ) gen("}\n");
  1276.         --BlkLevel;
  1277.         BLOCK_Tail();
  1278.         q->visited = FALSE;
  1279.         freeBlkFsets(q);
  1280.         set_free(f);
  1281.         if (q->end->p1 != NULL) TRANS(q->end->p1);
  1282.         return;
  1283.     }
  1284.     gen("do {\n");
  1285.     tabs++;
  1286.     f = genBlk(q, aPlusBlk, &max_k, &need_right_curly);
  1287.     gen("else if ( zzcnt>1 ) break; /* implied exit branch */\n");/* code for exiting loop */
  1288.     tab();
  1289.     makeErrorClause(q,f,max_k);
  1290.     { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
  1291.     freeBlkFsets(q);
  1292.     gen("zzcnt++;");
  1293.     if ( !GenCC ) _gen1(" zzLOOP(zztasp%d);", BlkLevel-1);
  1294.     _gen("\n");
  1295.     if ( DemandLookahead )
  1296.         if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}
  1297.         else gen1("look(%d);\n", max_k);
  1298.     --tabs;
  1299.     if ( q->parm!=NULL && q->predparm ) {gen1("} while (%s);\n", q->parm);}
  1300.     else gen("} while ( 1 );\n");
  1301.     --BlkLevel;
  1302.     BLOCK_Tail();
  1303.     q->visited = FALSE;
  1304.     if (q->end->p1 != NULL) TRANS(q->end->p1);
  1305. }
  1306.  
  1307. /*
  1308.  * Generate code for a sub blk of alternatives of form:
  1309.  *
  1310.  *                   --o-G1--o--
  1311.  *                     |     ^
  1312.  *                     v    /|
  1313.  *                     o-G2-o|
  1314.  *                     |     ^
  1315.  *                     v     |
  1316.  *                   ..........
  1317.  *                     |     ^
  1318.  *                     v    /
  1319.  *                     o-Gn-o
  1320.  *
  1321.  * q points to the 1st junction of blk (upper-left).
  1322.  * q->end points to the last node (far right) in the blk.  Note that q->end->jtype
  1323.  * must be 'EndBlk'.
  1324.  * The last node in every alt points to q->end.
  1325.  *
  1326.  * Generate code of the following form:
  1327.  *    if ( First(G1) ) {
  1328.  *        ...code for G1...
  1329.  *    }
  1330.  *    else if ( First(G2) ) {
  1331.  *        ...code for G2...
  1332.  *    }
  1333.  *    ...
  1334.  *    else {
  1335.  *        ...code for Gn...
  1336.  *    }
  1337.  */
  1338. void
  1339. #ifdef __STDC__
  1340. genSubBlk( Junction *q )
  1341. #else
  1342. genSubBlk( q )
  1343. Junction *q;
  1344. #endif
  1345. {
  1346.     int max_k;
  1347.     set f;
  1348.     int need_right_curly;
  1349.     require(q->ntype == nJunction,    "genSubBlk: not junction");
  1350.     require(q->jtype == aSubBlk,    "genSubBlk: not subblock");
  1351.  
  1352.     BLOCK_Preamble(q);
  1353.     BlkLevel++;
  1354.     f = genBlk(q, aSubBlk, &max_k, &need_right_curly);
  1355.     if ( q->p2 != NULL ) {tab(); makeErrorClause(q,f,max_k);}
  1356.     { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
  1357.     freeBlkFsets(q);
  1358.     --BlkLevel;
  1359.     BLOCK_Tail();
  1360.  
  1361.     if ( q->guess )
  1362.     {
  1363.         gen("zzGUESS_DONE\n");
  1364.     }
  1365.  
  1366.     /* must duplicate if (alpha)?; one guesses (validates), the second pass matches */
  1367.     if ( q->guess && analysis_point(q)==q )
  1368.     {
  1369.         BLOCK_Preamble(q);
  1370.         BlkLevel++;
  1371.         f = genBlk(q, aSubBlk, &max_k, &need_right_curly);
  1372.         if ( q->p2 != NULL ) {tab(); makeErrorClause(q,f,max_k);}
  1373.         { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
  1374.         freeBlkFsets(q);
  1375.         --BlkLevel;
  1376.         BLOCK_Tail();
  1377.     }
  1378.  
  1379.     if (q->end->p1 != NULL) TRANS(q->end->p1);
  1380. }
  1381.  
  1382. /*
  1383.  * Generate code for a rule.
  1384.  *
  1385.  *        rule--> o-->o-Alternatives-o-->o
  1386.  * Or,
  1387.  *        rule--> o-->o-Alternative-o-->o
  1388.  *
  1389.  * The 1st junction is a RuleBlk.  The second can be a SubBlk or just a junction
  1390.  * (one alternative--no block), the last is EndRule.
  1391.  * The second to last is EndBlk if more than one alternative exists in the rule.
  1392.  *
  1393.  * To get to the init-action for a rule, we must bypass the RuleBlk,
  1394.  * and possible SubBlk.
  1395.  * Mark any init-action as generated so genBlk() does not regenerate it.
  1396.  */
  1397. void
  1398. #ifdef __STDC__
  1399. genRule( Junction *q )
  1400. #else
  1401. genRule( q )
  1402. Junction *q;
  1403. #endif
  1404. {
  1405.     int max_k;
  1406.     set follow, rk, f;
  1407.     ActionNode *a;
  1408.     RuleEntry *r;
  1409.     static int file = -1;
  1410.     int need_right_curly;
  1411.     require(q->ntype == nJunction,    "genRule: not junction");
  1412.     require(q->jtype == RuleBlk,    "genRule: not rule");
  1413.  
  1414.     r = (RuleEntry *) hash_get(Rname, q->rname);
  1415.     if ( r == NULL ) warnNoFL("Rule hash table is screwed up beyond belief");
  1416.     if ( q->file != file )        /* open new output file if need to */
  1417.     {
  1418.         if ( output != NULL ) fclose( output );
  1419.         output = fopen(OutMetaName(outname(FileStr[q->file])), "w");
  1420.         require(output != NULL, "genRule: can't open output file");
  1421.         if ( file == -1 ) genHdr1(q->file);
  1422.         else genHdr(q->file);
  1423.         file = q->file;
  1424.     }
  1425.     DumpFuncHeader(q,r);
  1426.     tabs++;
  1427.     if ( q->ret!=NULL )
  1428.     {
  1429.         if ( HasComma(q->ret) ) {gen1("struct _rv%d _retv;\n",r->rulenum);}
  1430.         else
  1431.         {
  1432.             tab();
  1433.             DumpType(q->ret, output);
  1434.             gen(" _retv;\n");
  1435.         }
  1436.     }
  1437.     gen("zzRULE;\n");
  1438.     if ( GenCC && GenAST )
  1439.         gen("ASTBase **_astp, *_ast = NULL, *_sibling = NULL, *_tail = NULL;\n");
  1440.     if ( GenCC ) genTokenPointers(q);
  1441.     if ( GenCC&&GenAST ) genASTPointers(q);
  1442.     if ( !GenCC ) gen1("zzBLOCK(zztasp%d);\n", BlkLevel);
  1443.     if ( !GenCC ) gen("zzMake0;\n");
  1444.     if ( !GenCC ) gen("{\n");
  1445.  
  1446.     if ( has_guess_block_as_first_item((Junction *)q->p1) )
  1447.     {
  1448.         gen("zzGUESS_BLOCK\n");
  1449.     }
  1450.  
  1451.     /* L o o k  F o r  I n i t  A c t i o n */
  1452.     if ( ((Junction *)q->p1)->jtype == aSubBlk )
  1453.         a = findImmedAction( ((Junction *)q->p1)->p1 );
  1454.     else
  1455.         a = findImmedAction( q->p1 );    /* only one alternative in rule */
  1456.     if ( a!=NULL && !a->is_predicate )
  1457.     {
  1458.         dumpAction(a->action, output, tabs, a->file, a->line, 1);
  1459.         a->done = 1;    /* ignore action. We have already handled it */
  1460.     }
  1461.     if ( TraceGen )
  1462.         if ( GenCC ) {gen1("tracein((ANTLRChar *)\"%s\");\n", q->rname);}
  1463.         else gen1("zzTRACEIN((ANTLRChar *)\"%s\");\n", q->rname);
  1464.  
  1465.     BlkLevel++;
  1466.     q->visited = TRUE;                /* mark RULE as visited for FIRST/FOLLOW */
  1467.     f = genBlk((Junction *)q->p1, RuleBlk, &max_k, &need_right_curly);
  1468.     if ( q->p1 != NULL )
  1469.         if ( ((Junction *)q->p1)->p2 != NULL )
  1470.             {tab(); makeErrorClause((Junction *)q->p1,f,max_k);}
  1471.     { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
  1472.     freeBlkFsets((Junction *)q->p1);
  1473.     q->visited = FALSE;
  1474.     --BlkLevel;
  1475.     if ( !GenCC ) gen1("zzEXIT(zztasp%d);\n", BlkLevel);
  1476.  
  1477.     if ( TraceGen )
  1478.         if ( GenCC ) {gen1("traceout((ANTLRChar *)\"%s\");\n", q->rname);}
  1479.         else gen1("zzTRACEOUT((ANTLRChar *)\"%s\");\n", q->rname);
  1480.  
  1481.     if ( q->ret!=NULL ) gen("return _retv;\n") else gen("return;\n");
  1482.     /* E r r o r  R e c o v e r y */
  1483.     NewSet();
  1484.     rk = empty;
  1485.     REACH(q->end, 1, &rk, follow);
  1486.     FillSet( follow );
  1487.     set_free( follow );
  1488.     _gen("fail:\n");
  1489.     if ( !GenCC ) gen("zzEXIT(zztasp1);\n");
  1490.     if ( FoundGuessBlk )
  1491.            if ( !GenCC ) {gen("if ( zzguessing ) zzGUESS_FAIL;\n");}
  1492.         else gen("if ( guessing ) zzGUESS_FAIL;\n");
  1493.     if ( q->erraction!=NULL )
  1494.         dumpAction(q->erraction, output, tabs, q->file, q->line, 1);
  1495.     if ( GenCC )
  1496.     {
  1497.         gen1("syn(zzBadTok, %s, zzMissSet, zzMissTok, zzErrk);\n",
  1498.              r->egroup==NULL?"(ANTLRChar *)\"\"":r->egroup);
  1499.     }
  1500.     else
  1501.     {
  1502.         gen1("zzsyn(zzMissText, zzBadTok, %s, zzMissSet, zzMissTok, zzErrk, zzBadText);\n",
  1503.              r->egroup==NULL?"(ANTLRChar *)\"\"":r->egroup);
  1504.     }
  1505.     gen3("%sresynch(setwd%d, 0x%x);\n", GenCC?"":"zz", wordnum, 1<<setnum);
  1506.  
  1507.     if ( TraceGen )
  1508.         if ( GenCC ) {gen1("traceout((ANTLRChar *)\"%s\");\n", q->rname);}
  1509.         else gen1("zzTRACEOUT((ANTLRChar *)\"%s\");\n", q->rname);
  1510.  
  1511.     if ( q->ret!=NULL ) gen("return _retv;\n");
  1512.     if ( !GenCC ) gen("}\n");
  1513.     tabs--;
  1514.     gen("}\n");
  1515.     if ( q->p2 != NULL ) {TRANS(q->p2);} /* generate code for next rule too */
  1516.     else dumpAfterActions( output );
  1517. }
  1518.  
  1519. static void
  1520. #ifdef __STDC__
  1521. DumpFuncHeader( Junction *q, RuleEntry *r )
  1522. #else
  1523. DumpFuncHeader( q, r )
  1524. Junction *q;
  1525. RuleEntry *r;
  1526. #endif
  1527. {
  1528.     /* A N S I */
  1529.     _gen("\n");
  1530.     if ( q->ret!=NULL )
  1531.     {
  1532.         if ( HasComma(q->ret) ) {gen1("struct _rv%d\n",r->rulenum);}
  1533.         else
  1534.         {
  1535.             DumpType(q->ret, output);
  1536.             gen("\n");
  1537.         }
  1538.     }
  1539.     else
  1540.     {
  1541.         _gen("void\n");
  1542.     }
  1543.     if ( !GenCC ) _gen("#ifdef __STDC__\n");
  1544.     if ( !GenCC ) gen2("%s%s(", RulePrefix, q->rname)
  1545.     else gen2("%s::%s(", CurrentClassName, q->rname);
  1546.     if ( GenAST )
  1547.     {
  1548.         if ( GenCC ) {_gen("ASTBase **_root");}
  1549.         else _gen("AST **_root");
  1550.         if ( q->pdecl!=NULL ) _gen(",");
  1551.     }
  1552.     if ( q->pdecl!=NULL ) {_gen1("%s", q->pdecl);}
  1553.     else if ( !GenAST ) _gen("void");
  1554.     _gen(")\n");
  1555.  
  1556.     if ( GenCC ) {gen("{\n"); return;}
  1557.  
  1558.     /* K & R */
  1559.     gen("#else\n");
  1560.     if ( q->ret!=NULL )
  1561.     {
  1562.         if ( HasComma(q->ret) ) {gen1("struct _rv%d\n",r->rulenum);}
  1563.         else
  1564.         {
  1565.             DumpType(q->ret, output);
  1566.             gen("\n");
  1567.         }
  1568.     }
  1569.     gen2("%s%s(", RulePrefix, q->rname);
  1570.     if ( GenAST )
  1571.     {
  1572.         _gen("_root");
  1573.         if ( q->pdecl!=NULL ) _gen(",");
  1574.     }
  1575.  
  1576.     DumpListOfParmNames( q->pdecl, output );
  1577.     gen(")\n");
  1578.     if ( GenAST ) gen("AST **_root;\n");
  1579.     DumpOldStyleParms( q->pdecl, output );
  1580.     gen("#endif\n");
  1581.     gen("{\n");
  1582. }
  1583.  
  1584. void
  1585. #ifdef __STDC__
  1586. genJunction( Junction *q )
  1587. #else
  1588. genJunction( q )
  1589. Junction *q;
  1590. #endif
  1591. {
  1592.     require(q->ntype == nJunction,    "genJunction: not junction");
  1593.     require(q->jtype == Generic,    "genJunction: not generic junction");
  1594.  
  1595.     if ( q->p1 != NULL ) TRANS(q->p1);
  1596.     if ( q->p2 != NULL ) TRANS(q->p2);
  1597. }
  1598.  
  1599. void
  1600. #ifdef __STDC__
  1601. genEndBlk( Junction *q )
  1602. #else
  1603. genEndBlk( q )
  1604. Junction *q;
  1605. #endif
  1606. {
  1607. }
  1608.  
  1609. void
  1610. #ifdef __STDC__
  1611. genEndRule( Junction *q )
  1612. #else
  1613. genEndRule( q )
  1614. Junction *q;
  1615. #endif
  1616. {
  1617. }
  1618.  
  1619. void
  1620. #ifdef __STDC__
  1621. genHdr( int file )
  1622. #else
  1623. genHdr( file )
  1624. int file;
  1625. #endif
  1626. {
  1627.     _gen("/*\n");
  1628.     _gen(" * A n t l r  T r a n s l a t i o n  H e a d e r\n");
  1629.     _gen(" *\n");
  1630.     _gen(" * Terence Parr, Will Cohen, and Hank Dietz: 1989-1994\n");
  1631.     _gen(" * Purdue University Electrical Engineering\n");
  1632.     _gen(" * With AHPCRC, University of Minnesota\n");
  1633.     _gen1(" * ANTLR Version %s\n", Version);
  1634.     _gen(" */\n");
  1635.     _gen("#include <stdio.h>\n");
  1636.     _gen1("#define ANTLR_VERSION    %s\n", VersionDef);
  1637.     if ( strcmp(ParserName, DefaultParserName)!=0 )
  1638.         _gen2("#define %s %s\n", DefaultParserName, ParserName);
  1639.        if ( strcmp(ParserName, DefaultParserName)!=0 )
  1640.         {_gen1("#include \"%s\"\n", RemapFileName);}
  1641.     if ( GenLineInfo ) _gen2(LineInfoFormatStr, 1, FileStr[file]);
  1642.     if ( GenCC ) {
  1643.         if ( UserTokenDefsFile != NULL )
  1644.             fprintf(output, "#include %s\n", UserTokenDefsFile);
  1645.         else
  1646.             fprintf(output, "#include \"%s\"\n", DefFileName);
  1647.     }
  1648.  
  1649.     if ( HdrAction != NULL ) dumpAction( HdrAction, output, 0, -1, 0, 1);
  1650.     if ( !GenCC && FoundGuessBlk )
  1651.     {
  1652.         _gen("#define ZZCAN_GUESS\n");
  1653.         _gen("#include <setjmp.h>\n");
  1654.     }
  1655.     if ( !GenCC && OutputLL_k > 1 ) _gen1("#define LL_K %d\n", OutputLL_k);
  1656.     if ( GenAST&&!GenCC ) _gen("#define GENAST\n\n");
  1657.     if ( GenAST ) {
  1658.         if ( GenCC ) {_gen("#include \"astx.h\"\n\n");}
  1659.         else _gen("#include \"ast.h\"\n\n");
  1660.     }
  1661.     if ( !GenCC && DemandLookahead ) _gen("#define DEMAND_LOOK\n\n");
  1662.     if ( !GenCC && LexGen ) {
  1663.         _gen1("#define zzEOF_TOKEN %d\n", (TokenInd!=NULL?TokenInd[EofToken]:EofToken));
  1664.     }
  1665.     /* ###WARNING: This will have to change when SetWordSize changes */
  1666.     if ( !GenCC ) _gen1("#define zzSET_SIZE %d\n", NumWords(TokenNum-1)*sizeof(unsigned));
  1667.     if ( !GenCC ) {_gen("#include \"antlr.h\"\n");}
  1668.     else {
  1669.         _gen("#include \"antlrx.h\"\n");
  1670.         _gen1("#include \"%s.h\"\n", CurrentClassName);
  1671.     }
  1672.     if ( !GenCC ) {
  1673.         if ( UserDefdTokens )
  1674.             {_gen1("#include %s\n", UserTokenDefsFile);}
  1675.         /* still need this one as it has the func prototypes */
  1676.         _gen1("#include \"%s\"\n", DefFileName);
  1677.     }
  1678.     /* still need this one as it defines the DLG interface */
  1679.     if ( !GenCC ) _gen("#include \"dlgdef.h\"\n");
  1680.     if ( LexGen && GenCC ) _gen("#include \"dlgx.h\"\n");
  1681.     if ( !GenCC && LexGen ) _gen1("#include \"%s\"\n", ModeFileName);
  1682. }
  1683.  
  1684. void
  1685. #ifdef __STDC__
  1686. genHdr1( int file )
  1687. #else
  1688. genHdr1( file )
  1689. int file;
  1690. #endif
  1691. {
  1692.     ListNode *p;
  1693.  
  1694.     genHdr(file);
  1695.     if ( GenAST )
  1696.     {
  1697.         if ( !GenCC ) {
  1698.             _gen("#include \"ast.c\"\n");
  1699.             _gen("zzASTgvars\n\n");
  1700.         }
  1701.     }
  1702.     if ( !GenCC ) _gen("ANTLR_INFO\n");
  1703.     if ( BeforeActions != NULL )
  1704.     {
  1705.         for (p = BeforeActions->next; p!=NULL; p=p->next)
  1706.             dumpAction( (char *)p->elem, output, 0, -1, 0, 1);
  1707.     }
  1708. }
  1709.  
  1710. void
  1711. #ifdef __STDC__
  1712. genStdPCCTSIncludeFile( FILE *f )
  1713. #else
  1714. genStdPCCTSIncludeFile( f )
  1715. FILE *f;
  1716. #endif
  1717. {
  1718.     fprintf(f,"#ifndef STDPCCTS_H\n");
  1719.     fprintf(f,"#define STDPCCTS_H\n");
  1720.     fprintf(f,"/*\n");
  1721.     fprintf(f," * %s -- P C C T S  I n c l u d e\n", stdpccts);
  1722.     fprintf(f," *\n");
  1723.     fprintf(f," * Terence Parr, Will Cohen, and Hank Dietz: 1989-1994\n");
  1724.     fprintf(f," * Purdue University Electrical Engineering\n");
  1725.     fprintf(f," * With AHPCRC, University of Minnesota\n");
  1726.     fprintf(f," * ANTLR Version %s\n", Version);
  1727.     fprintf(f," */\n");
  1728.     fprintf(f,"#include <stdio.h>\n");
  1729.     fprintf(f,"#define ANTLR_VERSION    %s\n", VersionDef);
  1730.     if ( GenCC )
  1731.     {
  1732.         if ( UserDefdTokens )
  1733.             fprintf(f, "#include %s\n", UserTokenDefsFile);
  1734.         else {
  1735.             fprintf(f, "#include \"%s\"\n", DefFileName);
  1736.         }
  1737.  
  1738.         fprintf(f, "#include \"AToken.h\"\n");
  1739.  
  1740.         if ( HdrAction != NULL ) dumpAction( HdrAction, f, 0, -1, 0, 1);
  1741.  
  1742.         fprintf(f, "#include \"ATokenStream.h\"\n");
  1743.  
  1744.         if ( OutputLL_k > 1 ) fprintf(f,"static const unsigned LL_K=%d;\n", OutputLL_k);
  1745.         if ( GenAST ) {
  1746.             fprintf(f, "#include \"astx.h\"\n");
  1747.         }
  1748.         fprintf(f,"#include \"antlrx.h\"\n");
  1749.         fprintf(f,"#include \"%s.h\"\n", CurrentClassName);
  1750.         if ( LexGen ) fprintf(f,"#include \"dlgx.h\"\n");
  1751.         return;
  1752.     }
  1753.  
  1754.     if ( strcmp(ParserName, DefaultParserName)!=0 )
  1755.         fprintf(f, "#define %s %s\n", DefaultParserName, ParserName);
  1756.     if ( strcmp(ParserName, DefaultParserName)!=0 )
  1757.         fprintf(f, "#include \"%s\"\n", RemapFileName);
  1758.     if ( UserTokenDefsFile != NULL )
  1759.        fprintf(f, "#include %s\n", UserTokenDefsFile);
  1760.     if ( HdrAction != NULL ) dumpAction( HdrAction, f, 0, -1, 0, 1);
  1761.     if ( FoundGuessBlk )
  1762.     {
  1763.         fprintf(f,"#define ZZCAN_GUESS\n");
  1764.         fprintf(f,"#include <setjmp.h>\n");
  1765.     }
  1766.     if ( OutputLL_k > 1 ) fprintf(f,"#define LL_K %d\n", OutputLL_k);
  1767.     if ( GenAST ) fprintf(f,"#define GENAST\n");
  1768.     if ( DemandLookahead ) fprintf(f,"#define DEMAND_LOOK\n");
  1769.     if ( LexGen ) fprintf(f, "#define zzEOF_TOKEN %d\n", (TokenInd!=NULL?TokenInd[EofToken]:EofToken));
  1770.     /* ###WARNING: This will have to change when SetWordSize changes */
  1771.     fprintf(f, "#define zzSET_SIZE %d\n", NumWords(TokenNum-1)*sizeof(unsigned));
  1772.     fprintf(f,"#include \"antlr.h\"\n");
  1773.     if ( GenAST ) fprintf(f,"#include \"ast.h\"\n");
  1774.     if ( UserDefdTokens )
  1775.         fprintf(f, "#include %s\n", UserTokenDefsFile);
  1776.     /* still need this one as it has the func prototypes */
  1777.     fprintf(f, "#include \"%s\"\n", DefFileName);
  1778.     /* still need this one as it defines the DLG interface */
  1779.     fprintf(f,"#include \"dlgdef.h\"\n");
  1780.     /* don't need this one unless DLG is used */
  1781.     if ( LexGen ) fprintf(f,"#include \"%s\"\n", ModeFileName);
  1782.     fprintf(f,"#endif\n");
  1783. }
  1784.  
  1785. /* dump action 's' to file 'output' starting at "local" tab 'tabs'
  1786.    Dump line information in front of action if GenLineInfo is set
  1787.    If file == -1 then GenLineInfo is ignored.
  1788.    The user may redefine the LineInfoFormatStr to his/her liking
  1789.    most compilers will like the default, however.
  1790.  
  1791.    June '93; changed so that empty lines are left alone so that
  1792.    line information is correct for the compiler/debuggers.
  1793. */
  1794. void
  1795. #ifdef __STDC__
  1796. dumpAction( char *s, FILE *output, int tabs, int file, int line, int final_newline )
  1797. #else
  1798. dumpAction( s, output, tabs, file, line, final_newline )
  1799. char *s;
  1800. FILE *output;
  1801. int tabs;
  1802. int file;
  1803. int line;
  1804. int final_newline;
  1805. #endif
  1806. {
  1807.     int inDQuote, inSQuote;
  1808.     require(s!=NULL,         "dumpAction: NULL action");
  1809.     require(output!=NULL,    eMsg1("dumpAction: output FILE is NULL for %s",s));
  1810.  
  1811.     if ( GenLineInfo && file != -1 )
  1812.     {
  1813.         fprintf(output, LineInfoFormatStr, line, FileStr[file]);
  1814.     }
  1815.     PastWhiteSpace( s );
  1816.     /* don't print a tab if first non-white char is a # (preprocessor command) */
  1817.     if ( *s!='#' ) {TAB;}
  1818.     inDQuote = inSQuote = FALSE;
  1819.     while ( *s != '\0' )
  1820.     {
  1821.         if ( *s == '\\' )
  1822.         {
  1823.             putc( *s++, output ); /* Avoid '"' Case */
  1824.             if ( *s == '\0' ) return;
  1825.             if ( *s == '\'' ) putc( *s++, output );
  1826.             if ( *s == '\"' ) putc( *s++, output );
  1827.         }
  1828.         if ( *s == '\'' )
  1829.         {
  1830.             if ( !inDQuote ) inSQuote = !inSQuote;
  1831.         }
  1832.         if ( *s == '"' )
  1833.         {
  1834.             if ( !inSQuote ) inDQuote = !inDQuote;
  1835.         }
  1836.         if ( *s == '\n' )
  1837.         {
  1838.             putc('\n', output);
  1839.             s++;
  1840.             PastWhiteSpace( s );
  1841.             if ( *s == '}' )
  1842.             {
  1843.                 --tabs;
  1844.                 TAB;
  1845.                 putc( *s++, output );
  1846.                 continue;
  1847.             }
  1848.             if ( *s == '\0' ) return;
  1849.             if ( *s != '#' )    /* #define, #endif etc.. start at col 1 */
  1850.             {
  1851.                 TAB;
  1852.             }
  1853.         }
  1854.         if ( *s == '}' && !(inSQuote || inDQuote) )
  1855.         {
  1856.             --tabs;            /* Indent one fewer */
  1857.         }
  1858.         if ( *s == '{' && !(inSQuote || inDQuote) )
  1859.         {
  1860.             tabs++;            /* Indent one more */
  1861.         }
  1862.         putc( *s, output );
  1863.         s++;
  1864.     }
  1865.     if ( final_newline ) putc('\n', output);
  1866. }
  1867.  
  1868. static void
  1869. #ifdef __STDC__
  1870. dumpAfterActions( FILE *output )
  1871. #else
  1872. dumpAfterActions( output )
  1873. FILE *output;
  1874. #endif
  1875. {
  1876.     ListNode *p;
  1877.     require(output!=NULL, "dumpAfterActions: output file was NULL for some reason");
  1878.     if ( AfterActions != NULL )
  1879.     {
  1880.         for (p = AfterActions->next; p!=NULL; p=p->next)
  1881.             dumpAction( (char *)p->elem, output, 0, -1, 0, 1 );
  1882.     }
  1883.     fclose( output );
  1884. }
  1885.  
  1886. /*
  1887.  * Find the next action in the stream of execution.  Do not pass
  1888.  * junctions with more than one path leaving them.
  1889.  * Only pass generic junctions.
  1890.  *
  1891.  *    Scan forward while (generic junction with p2==NULL)
  1892.  *    If we stop on an action, return ptr to the action
  1893.  *    else return NULL;
  1894.  */
  1895. static ActionNode *
  1896. #ifdef __STDC__
  1897. findImmedAction( Node *q )
  1898. #else
  1899. findImmedAction( q )
  1900. Node *q;
  1901. #endif
  1902. {
  1903.     Junction *j;
  1904.     require(q!=NULL, "findImmedAction: NULL node");
  1905.     require(q->ntype>=1 && q->ntype<=NumNodeTypes, "findImmedAction: invalid node");
  1906.     
  1907.     while ( q->ntype == nJunction )
  1908.     {
  1909.         j = (Junction *)q;
  1910.         if ( j->jtype != Generic || j->p2 != NULL ) return NULL;
  1911.         q = j->p1;
  1912.         if ( q == NULL ) return NULL;
  1913.     }
  1914.     if ( q->ntype == nAction ) return (ActionNode *)q;
  1915.     return NULL;
  1916. }
  1917.  
  1918. static void
  1919. #ifdef __STDC__
  1920. dumpRetValAssign( char *retval, char *ret_def )
  1921. #else
  1922. dumpRetValAssign( retval, ret_def )
  1923. char *retval;
  1924. char *ret_def;
  1925. #endif
  1926. {
  1927.     char *q = ret_def;
  1928.     
  1929.     tab();
  1930.     while ( *retval != '\0' )
  1931.     {
  1932.         while ( isspace((*retval)) ) retval++;
  1933.         while ( *retval!=',' && *retval!='\0' ) putc(*retval++, output);
  1934.         fprintf(output, " = _trv.");
  1935.         
  1936.         DumpNextNameInDef(&q, output);
  1937.         putc(';', output); putc(' ', output);
  1938.         if ( *retval == ',' ) retval++;
  1939.     }
  1940. }
  1941.  
  1942. /* This function computes the set of tokens that can possibly be seen k
  1943.  * tokens in the future from point j
  1944.  */
  1945. static set
  1946. #ifdef __STDC__
  1947. ComputeErrorSet( Junction *j, int k )
  1948. #else
  1949. ComputeErrorSet( j, k )
  1950. Junction *j;
  1951. int k;
  1952. #endif
  1953. {
  1954.     Junction *alt1;
  1955.     set a, rk, f;
  1956.     require(j->ntype==nJunction, "ComputeErrorSet: non junction passed");
  1957.  
  1958.     f = rk = empty;
  1959.     for (alt1=j; alt1!=NULL; alt1 = (Junction *)alt1->p2)
  1960.     {
  1961.         REACH(alt1->p1, k, &rk, a);
  1962.         require(set_nil(rk), "ComputeErrorSet: rk != nil");
  1963.         set_free(rk);
  1964.         set_orin(&f, a);
  1965.         set_free(a);
  1966.     }
  1967.     return f;
  1968. }
  1969.  
  1970. static void
  1971. #ifdef __STDC__
  1972. makeErrorClause( Junction *q, set f, int max_k )
  1973. #else
  1974. makeErrorClause( q, f, max_k )
  1975. Junction *q;
  1976. set f;
  1977. int max_k;
  1978. #endif
  1979. {
  1980.     if ( max_k == 1 )
  1981.     {
  1982.         if ( GenCC ) {_gen1("else {FAIL(1,err%d", DefErrSet(&f,1));}
  1983.         else _gen1("else {zzFAIL(1,zzerr%d", DefErrSet(&f,1))
  1984.         set_free(f);
  1985.     }
  1986.     else
  1987.     {
  1988.         int i;
  1989.         set_free(f);
  1990.         if ( GenCC ) {_gen1("else {FAIL(%d", max_k);}
  1991.         else _gen1("else {zzFAIL(%d", max_k);
  1992.         for (i=1; i<=max_k; i++)
  1993.         {
  1994.             f = ComputeErrorSet(q, i);
  1995.             if ( GenCC ) {_gen1(",err%d", DefErrSet( &f, 1 ));}
  1996.             else _gen1(",zzerr%d", DefErrSet( &f, 1 ));
  1997.             
  1998.             set_free(f);
  1999.         }
  2000.     }
  2001.     _gen(",&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}\n");
  2002. }
  2003.