home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / compcomp / yacc / y1.c < prev    next >
Encoding:
Text File  |  1991-11-17  |  46.3 KB  |  1,379 lines

  1. /************************************************************************/
  2. /*                              y1.c                                    */  
  3. /*  YACC source file #1 (of 4).                                         */  
  4. /************************************************************************/  
  5.    
  6. /************************************************************************/  
  7. /*                              contents                                */  
  8. /*                                                                      */  
  9. /*    y1ArrayFill    Set elements 0 through n-1 to c.        */
  10. /*  * y1CharCopy        Copy str q into p, returning next free char ptr.*/
  11. /*  * y1CheckEmpty    Mark nonterminals which derive the empty string.*/
  12. /*    y1Closure     Generate the closure of state i.        */
  13. /*    y1Error           Write out fatal error comment.                  */
  14. /*  * y1First        Compute an array with the FIRSTS of nonterminals*/
  15. /*    y1GetChar     Get one input char.                */
  16. /*  * y1Lookahead       Return lookahead set.                           */
  17. /*  * y1MakeStates      Generate the states.                            */
  18. /*    main                                */
  19. /*  * y1PrintLookahead    Print lookahead.                */
  20. /*    y1PutItem                             */
  21. /*  * y1PutRest     Put out other arrays, copy the parsers.     */
  22. /*  * y1SetUnion    A gets union of A and B.            */
  23. /*    y1State        Sort last state, check it, return state #.    */
  24. /*  * y1Summary     Write the summary on the terminal.        */
  25. /*    y1SymbolName    Return a pointer to the name of symbol i.    */
  26. /*    y1UngetChar    Unget one char.                 */
  27. /*    y1WriteItem    Creates output string for item pointed to by pp.*/
  28. /*  * y1Yield           List productions YIELDING each nonterminal.     */
  29. /*                                    */
  30. /* * Local to this file.                                                */
  31. /*                                    */
  32. /************************************************************************/
  33.    
  34. /************************************************************************/  
  35. /*                              history                                 */  
  36. /*                                                                      */  
  37. /* 85Nov14 CrT  Global variable names decrypted.                        */
  38. /* 85Nov13 CrT    Give plaintiff routine in error messages.        */
  39. /* 85Nov11 CrT  Function names decrypted. Still unique in first 6 chars.*/
  40. /* 85Nov10 CrT    y1.c reconstructed from 18 (!) subfiles.  Cosmetics.    */
  41. /* 83Dec25 SG    Questions and suggestions on the IBM PC version of YACC */
  42. /*              can be directed to Scott Guthery, 11100 Leafwood Lane,  */ 
  43. /*              Austin, Texas,  78750.  Telephone: 512 258-1342.        */ 
  44. /*                                                                      */ 
  45. /* 83Dec25 SG   Added #ifdef UNION entries in yypars.c so that YACC     */ 
  46. /*              can be used with C compilers that do not support the    */ 
  47. /*              assignment of unions and structures.  If you use        */ 
  48. /*              the %union construct (see LANDY.Y for example) and your */ 
  49. /*              C compiler doesn't support union assignment, then       */ 
  50. /*              you have to write a routine                             */ 
  51. /*                           yyunion(to, from)                          */ 
  52. /*                           YYSTYPE *to, *from;                        */ 
  53. /*              which achieves the assignment of the %union.  If your   */ 
  54. /*              C compiler does support structure and union assignment  */ 
  55. /*              then undefine UNION in yypars.c.                        */ 
  56. /*                                                                      */ 
  57. /* 83Dec25 SG   Adapted YACC for IBM PC using the DeSmet C compiler.    */ 
  58. /*                                                                      */ 
  59. /* 83Apr12 RBD  Add symbolic exit status.                               */  
  60. /* 83Apr12 RBD    Additions and minor changes for running YACC under    */
  61. /*              VAX-11 C.  The newer versions of the files in this      */ 
  62. /*              UIC are the proper ones, and should run OK under        */ 
  63. /*              RSX & RT.  I have not purged the old ones because       */ 
  64. /*              I have not tested the new ones.                         */ 
  65. /*                                                                      */ 
  66. /* 82Mar22 RBD  Minor changes to accommodate the new DECUS library and  */ 
  67. /*              compiler. Command file changed to take advantage of the */ 
  68. /*              '-m' switch to disable the preprocessor phase of the    */ 
  69. /*              compiler, since MP is used.  'iovtoa()' changed to      */ 
  70. /*              'fgetname()'.  ODL slightly changed.  Added header to   */ 
  71. /*              output file to tell the name of the input file and the  */ 
  72. /*              date and time of generation.                            */ 
  73. /*                                                                      */ 
  74. /* 81Aug28 RBD  Changed to make debug code conditionally compile.       */
  75. /*                                                                      */ 
  76. /* 81Aug28 RBD    All of the debug stuff has been turned off. This makes    */
  77. /*              for a much easier to read YACC.OUT file.                */ 
  78. /*                                                                      */ 
  79. /* 81Aug28 RBD    The options accepted by Yacc have been changed. The    */
  80. /*              changes were all in YSETUP.2C. See the docs.            */ 
  81. /*                                                                      */ 
  82. /* 81Aug28 RBD  In using YACC with Forsythe's LEX, the variable         */ 
  83. /*              "yylval" was found to be declared in both YACC's        */ 
  84. /*              output c source (yypars()) and in LEX. Apparently, the  */ 
  85. /*              UNIX LEX assumes that yylval is in YACC. Because LEX    */ 
  86. /*              sees so much use with other than YACC, we chose to      */ 
  87. /*              leave yylval declared in LEX. So the YACC module        */ 
  88. /*              YSETUP.2C was modified to emit "extern YYSTYPE yylval"  */ 
  89. /*              when compiled by the Decus compiler or MP processor.    */ 
  90. /*                                                                      */ 
  91. /* 81Aug28 RBD  Much has happened since the last entry. Yacc has been   */ 
  92. /*              brought up on RSX-11M, along with changes in the        */ 
  93. /*              command string outlined below.                          */ 
  94. /*                                                                      */ 
  95. /* 80Dec18 RBD    Add conditional code for Decus for tempfile deletion.    */
  96. /* 80Dec06 RBD  Original code broken out of y1.c.                       */ 
  97. /* 80Dec05 RBD    MP has been fixed. Note the 'beauty' prettyprinter    */
  98. /*              was distributed in this UIC, but it's been deleted.     */ 
  99. /*                                                                      */ 
  100. /* 80Dec04 RBD  Include files and their names need looking at.          */ 
  101. /* 80Dec04 RBD  MP preprocessor inserts a ' ' at the beginning of       */ 
  102. /*              a text substitution. Otherwise, it looks like it        */ 
  103. /*              does the right stuff!                                   */ 
  104. /* 80Dec04 RBD  Variable declarations inside statements exist.          */ 
  105. /*                                                                      */ 
  106. /* 7?????? SCJ    Created.                        */
  107. /*                                                                      */  
  108. /*                                                                      */  
  109. /*                              credits                                 */
  110. /*      CrT=CrT                                                         */
  111. /*      RBD=Bob Denny                                                   */ 
  112. /*      SCJ=Steven C Johnson.                                           */ 
  113. /*      SG =Scott Guthery                                               */ 
  114. /*                                    */
  115. /************************************************************************/
  116.  
  117.  
  118.  
  119. #include <stdio.h>
  120. #include "system.h"
  121. #include "dtxtrn.h"
  122.                           
  123.  
  124.  
  125. # define EMPTY      1
  126. # define WHOKNOWS 0
  127. # define OK      1
  128.  
  129.  
  130. /* The default actions of states. */
  131. extern int   y3DefaultAction[ MAXsTATES ];
  132.  
  133. /* Character stack shared by y1GetChar and y1UngetChar: */
  134. static char   y1GetStack[ 30 ],   *y1TopStack = y1GetStack;
  135.  
  136.  
  137.  
  138.  
  139. /* Lookahead computations: */
  140.                                                    
  141. /********************************************************/
  142. /* Size of lookahead sets in words. Lookahead sets are    */
  143. /* represented by bit vectors with one bit for each    */
  144. /* terminal in the grammar -- this makes set unions a    */
  145. /* simple matter of ORing two bit vectors together. On    */
  146. /* large grammars, YACC spends most of its time doing    */
  147. /* set unions.                        */
  148. /********************************************************/
  149. int y1MaxLookaheadSet;
  150.  
  151. struct looksets y1LookaheadSet [ MAXy1lOOKAHEADsETS ];
  152.  
  153. /* Next lookahead set to allocate: */
  154. static int y1NextLookaheadSet  = 0;
  155.  
  156. /* Flag to suppress lookahead computations: */
  157. int y1NoLookahead = FALSE;
  158.  
  159. /* Temporary storage for lookahead computations: */
  160. static struct looksets y1ClosureSet;
  161.  
  162.  
  163.  
  164. /* Working set computations: */
  165.                                                    
  166. struct wset y1WorkingSet[ MAXy1wORKINGsET];
  167. struct wset *y1ThisWorkingSet;
  168.                                                    
  169.  
  170.  
  171. /* State information: */
  172.                                                    
  173. /* Number of states so far: */
  174. int y1NextState = 0;
  175.  
  176. /* States generated by terminal gotos: */
  177. int y1TerminalState[    MAXtERMINALsTATES    ];
  178.  
  179. /* States generated by nonterminal gotos: */
  180. int y1NonterminalState[ MAXnONTERMINALsTATES ];
  181.  
  182. /* Type information about the states: */
  183. int y1StateType[   MAXsTATES ];
  184.  
  185. /* Index to the stored goto table: */
  186. int y1GotoIndex[   MAXsTATES ];
  187.  
  188. /* [Non/]term generation lists overflow chain:    */
  189. static int y1Link[ MAXsTATES ];
  190.  
  191. /* State-description pointers: */
  192. struct item *y1StateItem[ MAXsTATES +2 ];
  193.  
  194.  
  195.  
  196. /* Storage for the actions in the parser: */
  197.                                                    
  198. /* Action table storage: */
  199. int y1Action[ MAXaCTIONS ];
  200.  
  201. /* Next free action table position: */
  202. int *y1NextAction = y1Action;
  203.  
  204.  
  205.  
  206. /* Other storage areas: */
  207.                                                    
  208. /* Scratch area andexed variously by terms+y2NextTerminal or states: */
  209. int y1Temp[ MAXy1TEMP ];
  210.  
  211. /* Current input line number: */
  212. int y1LineNumber = 1;
  213.  
  214. /* Signal to y1Error(): If y1ErrorsFatal, errors are fatal: */
  215. static int y1ErrorsFatal = TRUE;
  216.  
  217. /* Number of errors: */
  218. int y1Errors = 0;
  219.  
  220.  
  221.                                                    
  222. /* Storage for information about the nonterminals: */
  223.                                                    
  224. /* Productions yielding each nonterminal (Ptrs):*/
  225. static int **y1YieldedBy[       MAXnONTERMINALsTATES +2 ];
  226.  
  227. /* FIRST sets for nonterminals: */
  228. static struct looksets *y1FirstOf[ MAXnONTERMINALsTATES +2 ];
  229.  
  230. /* Nonterminals nontrivially deriving <empty>: */
  231. static int y1YieldsEmpty[       MAXnONTERMINALsTATES +1 ];
  232.  
  233.  
  234.  
  235. /* Storage for statistics: */
  236.                                                    
  237. static struct wset * y1LastWorkingSet         = y1WorkingSet;
  238. int             y1GotoEntries         =          0;
  239. int             y1GotosSavedByDefault   =          0;
  240.  
  241. int             y1ShiftEntries         =          0;
  242. int             y1Exceptions         =          0;
  243. static int         y1ClosuresDone         =          0;
  244.  
  245. int             y1ShiftReduceConflicts  =          0;
  246. int             y1ReduceReduceConflicts =          0;
  247. static        *         y1Nexty2PoolLoc         =         y2Pool;
  248.  
  249.  
  250.  
  251.  
  252.  
  253. /************************************************************************/
  254. /*    y1ArrayFill    Set elements 0 through n-1 to c         */
  255. /************************************************************************/
  256. y1ArrayFill( v, n, c )
  257. int *v,n,c;
  258. {
  259.     register int i;
  260.     for( i = n;   i--;    )   v[i] = c;
  261. }
  262.  
  263. /************************************************************************/
  264. /*    y1CharCopy    Copy string q into p, returning next free char ptr. */ 
  265. /************************************************************************/ 
  266. static char *y1CharCopy( p, q )
  267. char *p, *q; 
  268.     while (*p++ = *q++);
  269.   
  270.     return( --p ); 
  271.   
  272.   
  273. /************************************************************************/
  274. /*    y1CheckEmpty    Mark nonterminals which derive the empty string.*/
  275. /************************************************************************/
  276. static y1CheckEmpty() {
  277.  
  278.     /****************************************************************/
  279.     /* Mark nonterminals which derive the empty string.         */
  280.     /* Look for nonterminals which don't derive any token strings.  */
  281.     /****************************************************************/
  282.  
  283.     register i, *p;
  284.  
  285.  
  286.  
  287.     /************************************************************/
  288.     /* First, use the array y1YieldsEmpty to detect productions */
  289.     /* that can NEVER be reduced:                */
  290.     /************************************************************/
  291.  
  292.  
  293.  
  294.     y1ArrayFill( y1YieldsEmpty, y2LastNonterminal+1, WHOKNOWS );
  295.  
  296.     /* Now, look at productions, marking    */
  297.     /* nonterminals which derive something: */
  298.  
  299. more:
  300.     FORaLLpRODUCTIONS(0,i) {
  301.  
  302.         /***********************************************************/
  303.     /* Check nonterminal defined by this production.  If we    */
  304.     /* already know that nonterminal derives the empty string, */
  305.     /* skip to next production:                   */
  306.         /***********************************************************/
  307.     if( y1YieldsEmpty[ *y2Production[i] - FIRSTnONTERMINAL ] ) continue;
  308.  
  309.         /************************************************/
  310.     /* Scan RHSide of production. Stop if we reach    */
  311.     /* a nonterminal not known to derive something: */
  312.         /************************************************/
  313.     for (p = y2Production[i] +1;   *p >= 0;   ++p) {
  314.         if (
  315.         *p >= FIRSTnONTERMINAL
  316.         &&
  317.         y1YieldsEmpty[ *p-FIRSTnONTERMINAL ] == WHOKNOWS
  318.         ) {
  319.         break;
  320.         }
  321.         }
  322.  
  323.     /* See if we reached end of production: */
  324.     if (*p < 0)  {
  325.  
  326.          /*********************************************************/
  327.              /* Reached end of rule without finding any problematical */
  328.          /* entries, so production can be derived. Mark as safe:  */
  329.          /*********************************************************/
  330.              y1YieldsEmpty[ *y2Production[i]-FIRSTnONTERMINAL ] = OK;
  331.  
  332.          /* This may make something else safe, so start over: */
  333.              goto more;
  334.      }
  335.     }
  336.  
  337.     /********************************************************************/
  338.     /* We have now marked all nonterminals known to generate something. */
  339.     /* If any do NOT generate something, issue a warning message:    */
  340.     /********************************************************************/
  341.  
  342.     /* Make the useless-nonterminal errors nonfatal so we get all of them: */
  343.     y1ErrorsFatal = FALSE;
  344.  
  345.     FORaLLnONTERMINALS(i) {
  346.  
  347.     /* Ignore the %start nonterminal, which is special: */
  348.         if (!i)   continue;
  349.  
  350.     /* All the rest should derive something: */
  351.         if ( y1YieldsEmpty[ i ] != OK ) {
  352.  
  353.         y1Error(
  354.         "y1CheckEmpty: nonterminal %s never derives any token string",
  355.         y2NonterminalState[i].name
  356.         );
  357.     }
  358.     }
  359.     y1ErrorsFatal = TRUE;
  360.  
  361.     /* Quit if there are any useless nonterminals: */
  362.     if (y1Errors) {
  363.     y1Summary();
  364.     exit(EX_ERR);
  365.     }
  366.  
  367.  
  368.  
  369.     /******************************************************************/
  370.     /* Now figure out which nonterminals can derive the empty string: */
  371.     /******************************************************************/
  372.  
  373.  
  374.  
  375.     /* Set y1YieldsEmpty to WHOKNOWS: */
  376.     y1ArrayFill( y1YieldsEmpty, y2LastNonterminal+1, WHOKNOWS );
  377.  
  378.     /* Loop as long as we keep finding empty nonterminals: */
  379.  
  380. again:
  381.     FORaLLpRODUCTIONS(1,i) {
  382.  
  383.         if (y1YieldsEmpty[ *y2Production[i]-FIRSTnONTERMINAL ] == WHOKNOWS) {
  384.  
  385.             /*****************************************************/
  386.         /* Found a production not known to be empty.     */
  387.         /* See if all items on RHSide are known to be empty: */
  388.             /*****************************************************/
  389.  
  390.             for (p = y2Production[ i ] +1;  *p >= FIRSTnONTERMINAL;  ++p) {
  391.  
  392.                 if (y1YieldsEmpty[ *p - FIRSTnONTERMINAL ]  !=  EMPTY)   break;
  393.  
  394.             }
  395.  
  396.         if (*p < 0) {
  397.  
  398.                 /* We have a nontrivially empty nonterminal: */
  399.         y1YieldsEmpty[ *y2Production[ i ] - FIRSTnONTERMINAL ] = EMPTY;
  400.  
  401.         /* This rule may make another empty, so start over: */
  402.         goto again;
  403.         }
  404.     }
  405.     }
  406. }
  407.  
  408. /************************************************************************/
  409. /*    y1Closure     Generate the closure of state i         */
  410. /************************************************************************/
  411. y1Closure( i )    /* Called from y1StateGen and y3Output. */
  412. int i;
  413. {
  414.     /************************************************************************/
  415.     /* An "item" of a grammar G is a production of G with a dot at        */
  416.     /* some position of the right side.  The the production            */
  417.     /*                                        */
  418.     /*       a : x y z                                */
  419.     /*                                        */
  420.     /* generates the items                            */
  421.     /*                                        */
  422.     /*       a :.x y z                                */
  423.     /*       a : x.y z                                */
  424.     /*       a : x y.z                                */
  425.     /*       a : x y z.                                */
  426.     /*                                        */
  427.     /*    ...                                    */
  428.     /*                                        */
  429.     /* If i is a set of items for a grammar G, then the set of items        */
  430.     /* CLOSURE(i) is constructed from i by the rules                */
  431.     /* 1.  Every item in i is in CLOSURE(i)                    */
  432.     /* 2.  If "a : x.y z" is in CLOSURE(i) and "b : w" is a production,     */
  433.     /*       add "b : .w" to i.                            */
  434.     /*                                        */
  435.     /*    (Following Aho & Ullman PRIMCIPLES OF COMPILER DESIGN p205-206.) CrT*/
  436.     /************************************************************************/
  437.  
  438.     int                     c, ch, work, k;
  439.     register struct wset    *u, *v;
  440.     int             *pi;
  441.     int             **s, **t;
  442.     struct item         *q;
  443.     register struct item    *p;
  444.     int             num;
  445.  
  446.  
  447.     ++y1ClosuresDone;
  448.  
  449.     /* First, copy kernel of state i to y1WorkingSet: */
  450.  
  451.     y1ThisWorkingSet = y1WorkingSet;
  452.     FORaLLiTEMS(i,p,q) {
  453.  
  454.         y1ThisWorkingSet->pitem  = p->pitem;
  455.  
  456.     /* This item must get closed. */
  457.     y1ThisWorkingSet->flag     = TRUE;
  458.  
  459.     /* Copy the set over: */
  460.         FORaLLlOOKAHEADwORDS(k) {
  461.         y1ThisWorkingSet->ws.lset[k] = p->look->lset[k];
  462.     }
  463.  
  464.     NEXTwORKINGsET( y1ThisWorkingSet );
  465.     }
  466.  
  467.     /* Loop until no items remain to be closed: */
  468.     for (work = TRUE;    work; )  {
  469.  
  470.         work = FALSE;
  471.  
  472.     FORaLLwORKINGsETS( y1WorkingSet, u ) {
  473.  
  474.         /* Find an item with the close flag set: */
  475.             if (!u->flag) continue;
  476.  
  477.         /* Found one. Dot is before c: */
  478.         c = *(u->pitem);
  479.  
  480.         /* Only interesting case is where dot is before a nonterminal: */
  481.         if (c < FIRSTnONTERMINAL)  {
  482.  
  483.         /* Dot is before a terminal in this item: */
  484.                 u->flag = FALSE;
  485.         continue;
  486.         }
  487.  
  488.         /* Compute the lookahead: */
  489.  
  490.             y1ArrayFill( y1ClosureSet.lset, y1MaxLookaheadSet, 0 );
  491.  
  492.         /* Find items involving c: */
  493.         FORaLLwORKINGsETS(u,v)  {
  494.  
  495.         if (v->flag   &&   *(pi=v->pitem) == c) {
  496.             v->flag = FALSE;
  497.  
  498.                     if (y1NoLookahead)   continue;
  499.  
  500.             while ((ch = *++pi)  >  0)    {
  501.  
  502.                         if (ch < FIRSTnONTERMINAL) {
  503.                 /* Terminal symbol: */
  504.                 SETBIT( y1ClosureSet.lset, ch );
  505.                 break;
  506.              }
  507.  
  508.              /* Nonterminal symbol: */
  509.              num = ch-FIRSTnONTERMINAL;
  510.              y1SetUnion( y1ClosureSet.lset, y1FirstOf[num]->lset );
  511.              if (!y1YieldsEmpty[ num ])   break;
  512.             }
  513.             if (ch <= 0)   y1SetUnion( y1ClosureSet.lset, v->ws.lset );
  514.         }
  515.         }
  516.  
  517.         /* Now loop over productions derived from c: */
  518.  
  519.         c -= FIRSTnONTERMINAL;    /* c is now nonterminal number */
  520.  
  521.         t  = y1YieldedBy[ c+1 ];
  522.         for (s = y1YieldedBy[ c ];     s < t;   ++s) {
  523.  
  524.         /* Put these items into the closure: */
  525.         FORaLLwORKINGsETS(y1WorkingSet,v)  {
  526.  
  527.                     /* Is the item there? */
  528.             if (v->pitem == *s) {
  529.  
  530.                         /* Yes, it is there: */
  531.             if (y1NoLookahead)   goto nexts;
  532.             if (y1SetUnion( v->ws.lset, y1ClosureSet.lset )) {
  533.                 v->flag = work = TRUE;
  534.             }
  535.             goto nexts;
  536.             }
  537.         }
  538.  
  539.         /*  Not there; make a new entry: */
  540.         if (y1ThisWorkingSet-y1WorkingSet+1 >= MAXy1wORKINGsET)  {
  541.             y1Error( "y1Closure: Working set overflow" );
  542.         }
  543.         y1ThisWorkingSet->pitem  = *s;
  544.         y1ThisWorkingSet->flag     = TRUE;
  545.         if (!y1NoLookahead) {
  546.             work = TRUE;
  547.             FORaLLlOOKAHEADwORDS(k) {
  548.             y1ThisWorkingSet->ws.lset[k] = y1ClosureSet.lset[k];
  549.             }
  550.                 }
  551.         NEXTwORKINGsET( y1ThisWorkingSet );
  552. nexts:        ;
  553.         }
  554.  
  555.     }
  556.     }
  557.  
  558.     /* We have computed closure. Flags are reset. Return: */
  559.     if (y1LastWorkingSet < y1ThisWorkingSet)  {
  560.     y1LastWorkingSet = y1ThisWorkingSet;
  561.     }
  562.  
  563. #ifdef debug
  564.     if (y2OutputFD != NULL)  {
  565.     fprintf(
  566.         y2OutputFD,
  567.         "\nState %d, y1NoLookahead = %d\n",
  568.         i,
  569.         y1NoLookahead
  570.     );
  571.     FORaLLwORKINGsETS(y1WorkingSet,u) {
  572.         if (u->flag)   fprintf( y2OutputFD, "flag set!\n");
  573.         u->flag = FALSE;
  574.         fprintf( y2OutputFD, "\t%s", y1WriteItem(u->pitem));
  575.         y1PrintLookahead( &u->ws );
  576.         fprintf( y2OutputFD,  "\n" );
  577.     }
  578.     }
  579. #endif
  580. }
  581.  
  582.  
  583. /************************************************************************/
  584. /*    y1Error           Write out fatal error comment.                  */ 
  585. /************************************************************************/ 
  586. y1Error( s, a1 )        /* Called from everywhere. */ 
  587. char *s; 
  588.     ++y1Errors;
  589.     fprintf(   stderr,     "\nFATAL ERROR: "           );
  590.     fprintf(   stderr,     s, a1                   );
  591.     fprintf(   stderr,     ", line %d\n", y1LineNumber   );
  592.  
  593.     if (!y1ErrorsFatal)   return;
  594.  
  595.     y1Summary(); 
  596.  
  597.     exit(EX_ERR); 
  598.   
  599. /************************************************************************/
  600. /*    y1First           Compute an array with the FIRST of nonterminals */ 
  601. /************************************************************************/ 
  602. y1First() {     /* Called only from main. */ 
  603.  
  604.    register *p, **s, i, **t, ch, changes; 
  605.   
  606.    /**************************************************************/
  607.    /* For each nonterminal NT defined by the grammar, we want to */
  608.    /* figure out which terminals can occur first in a string     */
  609.    /* defined by NT.  This is a simple matter of enumerating     */
  610.    /* all terminals which occur at the start of a production     */
  611.    /* defining NT, and then adding in the recursively computed     */
  612.    /* FIRSTs of all nonterminals starting NT productions:     */
  613.    /**************************************************************/
  614.  
  615.    y1LastWorkingSet = &y1WorkingSet[ y2LastNonterminal ];
  616.  
  617.    /********************************************************************/
  618.    /* Do the first pass, finding for each nonterminal NT all terminals */
  619.    /* occurring at the start of a production defining NT:           */
  620.    /********************************************************************/
  621.  
  622.    FORaLLnONTERMINALS(i) {
  623.  
  624.     /* Allocate a set to hold FIRST of this nonterminal: */
  625.         y1ArrayFill( y1WorkingSet[i].ws.lset, y1MaxLookaheadSet, 0 );
  626.  
  627.     /* Iterate over the list of productions defining our nonterminal: */
  628.         t = y1YieldedBy[ i+1 ];
  629.     for (s = y1YieldedBy[i];   s < t;   ++s ) {
  630.   
  631.             /*************************************************************/
  632.         /* If this rule starts with a terminal, add it to our FIRST  */
  633.         /* set.  If the rule starts with a nonterminal that can     */
  634.         /* derive the empty string, then look at the next entry:     */
  635.             /*************************************************************/
  636.  
  637.             for (p = *s;   (ch = *p) > 0;   ++p) { 
  638.   
  639.         if (ch < FIRSTnONTERMINAL) {
  640.  
  641.                     /* Found a terminal, add it to FIRST set: */
  642.                     SETBIT( y1WorkingSet[i].ws.lset, ch );
  643.             break;
  644.  
  645.                 } else { 
  646.  
  647.                     /* Found a nonterminal.  Finished with this rule */
  648.             /* unless the nonterminal can derive <empty>:    */
  649.             if (!y1YieldsEmpty[ ch-FIRSTnONTERMINAL ])     break;
  650.                 } 
  651.             } 
  652.         } 
  653.     } 
  654.   
  655.     /****************************************************************/
  656.     /* Do the second pass, adding to FIRST(NT) FIRST(NT') for all   */
  657.     /* nonterminals NT' which occur first in a rule defining NT:    */
  658.     /****************************************************************/
  659.  
  660.     for (changes = TRUE;   changes;  ) {
  661.     changes = FALSE;
  662.  
  663.         FORaLLnONTERMINALS(i) {
  664.  
  665.         /* Iterate over the set of productions defining nonterminal i: */
  666.             t = y1YieldedBy[i+1];
  667.         for (s = y1YieldedBy[i];   s < t;    ++s) {
  668.  
  669.                 /************************************************************/
  670.         /* If this production starts with a nonterminal NT, collect */
  671.         /* its FIRST set.  As before, if NT can derive the empty    */
  672.         /* string then we have to collect FIRST of the following    */
  673.         /* item also:                            */
  674.                 /************************************************************/
  675.  
  676.                 for (p = *s;   (ch = (*p-FIRSTnONTERMINAL)) >= 0;   ++p) {
  677.             changes |= y1SetUnion(
  678.             y1WorkingSet[i].ws.lset,
  679.             y1WorkingSet[ch].ws.lset
  680.             );
  681.             if (!y1YieldsEmpty[ ch ])    break;
  682.                 } 
  683.             } 
  684.         } 
  685.     } 
  686.   
  687.     /********************************************************/
  688.     /* Finished! Now index the results for later reference, */
  689.     /* simultaneously merging identical lookahead sets:     */
  690.     /********************************************************/
  691.  
  692.     FORaLLnONTERMINALS(i) y1FirstOf[i] = y1Lookahead( &y1WorkingSet[i].ws );
  693. #ifdef debug 
  694.     if (y2OutputFD != NULL) {
  695.     FORaLLnONTERMINALS(i)  {
  696.         fprintf( y2OutputFD,  "\n%s: ", y2NonterminalState[i].name );
  697.         y1PrintLookahead( y1FirstOf[i] );
  698.         fprintf( y2OutputFD,  " %d\n", y1YieldsEmpty[i] );
  699.         } 
  700.     } 
  701. #endif 
  702.   
  703. /************************************************************************/
  704. /*    y1GetChar         Get one input char                              */ 
  705. /************************************************************************/ 
  706. y1GetChar( iop )                /* Called from everywhere */ 
  707. FILE *iop;
  708. {
  709.     if (y1TopStack == y1GetStack)   return  getc(iop)     ;
  710.     else                            return  *--y1TopStack;
  711. }
  712.  
  713. /************************************************************************/
  714. /*    y1Lookahead    Return lookahead set                */
  715. /************************************************************************/
  716. static struct looksets *y1Lookahead( p    )
  717. struct looksets *p;          /* Called from: y1First, y1PutItem, y1State */
  718. {
  719.     /* Decide if the lookahead set pointed to by p is known. */
  720.     /* Return pointer to a permanent location for the set.   */
  721.  
  722.     register struct looksets *q;
  723.     int              j,  *w;
  724.     register             *u, *v;
  725.  
  726.     /* Over all known lookahead sets q, see if q == p: */
  727.     for( q = &y1LookaheadSet[ y1NextLookaheadSet ];   q-- > y1LookaheadSet; ) {
  728.  
  729.         u = p->lset;
  730.     v = q->lset;
  731.  
  732.         w = &v[ y1MaxLookaheadSet ];
  733.  
  734.     /* Match all pair of corresponding words in p and q: */
  735.         while (v < w)   if (*u++ != *v++) goto more;
  736.  
  737.     /* P matches q -- return q */
  738.     return( q );
  739. more:    ;
  740.     }
  741.  
  742.     /* P is different from all known lookahead sets -- enter it: */
  743.     q = &y1LookaheadSet[ y1NextLookaheadSet++ ];
  744.  
  745.     /* Check for too many lookahead sets: */
  746.     if (y1NextLookaheadSet >= MAXy1lOOKAHEADsETS) {
  747.     y1Error("y1Lookahead: Too many lookahead sets");
  748.     }
  749.  
  750.     /* Copy p to permanent storage location: */
  751.     FORaLLlOOKAHEADwORDS(j) {
  752.     q->lset[j] = p->lset[j];
  753.     }
  754.     return( q );
  755. }
  756.  
  757. /************************************************************************/
  758. /*    y1MakeStates      Generate the states.                            */ 
  759. /************************************************************************/  
  760. static y1MakeStates() {      /* Called only from main. */
  761.     int i, j;  
  762.     register c;  
  763.     register struct wset *p, *q;  
  764.    
  765.     /********************************************************************/
  766.     /* Running your eye over a yacc grammar, you can imagine the parser */
  767.     /* proceeding methodically through the appropriate rules, looking    */
  768.     /* always for the next token in the current rule.  In fact, however,*/
  769.     /* one may have several rules which begin identically (say), so the */
  770.     /* parser must keep track of where it is in all the grammar rules    */
  771.     /* which >might< turn out to be the right one.  Thus, at any given    */
  772.     /* time, the parser is in effect in a set of states rather than a    */
  773.     /* single state.  In this routine we precompute all valid sets of    */
  774.     /* states which the parser might wind up in.  This is a simple    */
  775.     /* matter of starting at the root nonterminal of the grammar and    */
  776.     /* proceeding all possible directions simultaneously... :-)      CrT*/
  777.     /********************************************************************/
  778.  
  779.     /* Initialize */  
  780.    
  781.     y1NextState = 0;
  782.    /**************************************************************************/
  783.    /* This is funny from the standpoint of portability.              */
  784.    /* It represents the magic moment when the y2Pool array, which has         */
  785.    /* been holding the productions, starts to hold item pointers, of a         */
  786.    /* different type...                              */
  787.    /* Someday, alloc should be used to allocate all this stuff. For now, we  */
  788.    /* accept that if pointers don't fit in integers, there is a problem. SCJ.*/
  789.    /**************************************************************************/
  790.    
  791.    y1StateItem[ 0 ]  = y1StateItem[ 1 ] = (struct item *) y2FreePool;
  792.  
  793.    y1ArrayFill( y1ClosureSet.lset, y1MaxLookaheadSet, 0 );
  794.  
  795.    y1PutItem( y2Production[ 0 ]+1, &y1ClosureSet );
  796.  
  797.    /* Start state expansion at the root nonterminal: */
  798.    y1StateType[ 0 ]  = MUSTdOsTATE;
  799.    y1NextState         = 1;
  800.    y1StateItem[ 2 ]  = y1StateItem[ 1 ];
  801.    
  802.    y1ArrayFill( y1Action, MAXaCTIONS, 0 );
  803.    
  804.    /* Now, the main state generation loop: */  
  805.    
  806. more:  
  807.    FORaLLsTATES(i) {
  808.  
  809.     /* Find a state which needs expanding: */
  810.         if (y1StateType[i] != MUSTdOsTATE)   continue;
  811.  
  812.     /* Mark it as done: */
  813.         y1StateType[ i ] = DONEsTATE;
  814.  
  815.     /* Erase our scratchpad set: */
  816.         y1ArrayFill( y1Temp, y2LastNonterminal+1, 0 );
  817.    
  818.         /* Take state i, close it, and do gotos: */  
  819.     y1Closure(i);
  820.  
  821.         /*************************************************************/
  822.     /*"For item set i and grammar symbol x, GOTO(i,x) is defined */
  823.     /* to be the closure of the set of all items 'a : bx.c' such */
  824.     /* that 'a : b.xc' is in i..."                               */
  825.     /*    Aho & Ullman PRINCIPLES OF COMPILER DESIGN p207.  CrT*/
  826.         /*************************************************************/
  827.  
  828.         FORaLLwORKINGsETS(y1WorkingSet,p) {
  829.    
  830.             /* Generate goto's: */  
  831.             if (p->flag)   continue;  
  832.         p->flag = TRUE;
  833.             c       = *(p->pitem);  
  834.    
  835.             if (c <= 1) {  
  836.         if (y1StateItem[i+1]-y1StateItem[i] <= p-y1WorkingSet)    {
  837.             y1StateType[i] = MUSTlOOKaHEADsTATE;
  838.                 }  
  839.                 continue;  
  840.             }  
  841.    
  842.             /* Do a goto on c: */  
  843.         FORaLLwORKINGsETS(p,q) {
  844.                 if (c == *(q->pitem)) {  
  845.  
  846.                     /* This item contributes to the goto: */  
  847.                     y1PutItem( q->pitem + 1, &q->ws );  
  848.             q->flag = TRUE;
  849.                 }  
  850.             }  
  851.    
  852.         if (c < FIRSTnONTERMINAL) {
  853.                 y1State(c);  /* Register new state */  
  854.             } else {  
  855.         y1Temp[c-FIRSTnONTERMINAL] = y1State(c);
  856.             }  
  857.         }  
  858. #ifdef debug  
  859.     if (y2OutputFD != NULL) {
  860.         fprintf( y2OutputFD,  "%d: ", i );
  861.         FORaLLnONTERMINALS(j) {
  862.         if (y1Temp[j]) {
  863.             fprintf(
  864.             y2OutputFD,
  865.             "%s %d, ",
  866.             y2NonterminalState[j].name,
  867.             y1Temp[j]
  868.             );
  869.                 }  
  870.             }  
  871.         fprintf( y2OutputFD, "\n");
  872.         }  
  873. #endif  
  874.     y1GotoIndex[i] = y3PackState( &y1Temp[1], y2LastNonterminal-1 ) - 1;
  875.    
  876.         /* We have done one goto; Do some more: */  
  877.         goto more;  
  878.     }  
  879.     /* No more to do: Stop. */  
  880. }  
  881.    
  882.    
  883. /************************************************************************/
  884. /*    main                                */
  885. /************************************************************************/
  886. main( argc, argv )
  887. int argc;
  888. char *argv[];
  889. {
  890.     /* Initialize and read productions: */
  891.     puts("\ry2Initialize...      \r");
  892.     y2Initialize(argc,argv);
  893.  
  894.     /* Process input file, stashing results in appropriate the tables: */
  895.     puts("\ry2yyParse...         \r"); 
  896.     y2yyParse();
  897.  
  898.     /* Build yyActionIndex[] so parser can find user action chunks: */
  899.     puts("\ry3ActionIndex...     \r");
  900.     y3ActionIndex();
  901.  
  902.     /* Figure how many words a set of terminals requires, taking */
  903.     /* into account bits per word and number of terminals:     */
  904.     y1MaxLookaheadSet = NWORDS(y2NextTerminal);
  905.  
  906.     /* Find all productions defining each nonterminal: */
  907.     puts("\ry1Yield...           \r");
  908.     y1Yield();
  909.  
  910.     /* Figure out which nonterminals can match the empty string: */
  911.     puts("\ry1CheckEmpty...      \r");
  912.     y1CheckEmpty();
  913.  
  914.     /* Make a table of FIRSTs of nonterminals: */
  915.     puts("\ry1First...           \r");
  916.     y1First();
  917.  
  918.     /* Generate the states: */
  919.     puts("\ry1MakeStates...      \r");
  920.     y1MakeStates();
  921.  
  922.     /* Write the states and the tables: */
  923.     puts("\ry3PutStates...       \r");
  924.     y3PutStates();
  925.  
  926.     puts("\ry3Gotos...           \r");
  927.     y3Gotos();
  928.  
  929.     puts("\ry3HideProductions... \r");
  930.     y3HideProductions();
  931.  
  932.     puts("\ry1Summary...         \r");
  933.     y1Summary();
  934.  
  935.     puts("\ry4Optimize...        \r");
  936.     y4Optimize();
  937.  
  938.     puts("\ry1PutRest...         \r");
  939.     y1PutRest();
  940.  
  941.     puts("\rDone.                \r");
  942.     exit(EX_SUC);
  943. }
  944.  
  945.  
  946. /************************************************************************/
  947. /*    y1PutRest      Put out other arrays, copy the parsers.     */
  948. /************************************************************************/
  949. static y1PutRest() {         /* Called only from main. */
  950.     register c, i, j;
  951.  
  952.     y2InputFD = fopen( PARSER, "r" );
  953.     if (y2InputFD == NULL) {
  954.     y1Error( "y1PutRest: Cannot find parser file '%s'", PARSER );
  955.     }
  956.  
  957.     y3PutArray( "yyr1", y2ProductionProperties, y2ThisProduction );
  958.  
  959.     y1ArrayFill( y1Temp, y2ThisProduction, 0 );
  960.     FORaLLpRODUCTIONS( 1,i )   y1Temp[i] = y2Production[i+1]-y2Production[i]-2;
  961.     y3PutArray( "yyr2", y1Temp, y2ThisProduction );
  962.  
  963.     y1ArrayFill( y1Temp, y1NextState, -1000 );
  964.     FORaLLtERMINALS(i) {
  965.     for(j = y1TerminalState[i];   j != 0;    j = y1Link[j]) {
  966.         y1Temp[j] = y2Terminal[i].value;
  967.     }
  968.     }
  969.     FORaLLnONTERMINALS(i) {
  970.     for (j = y1NonterminalState[i];   j != 0;   j = y1Link[j]) {
  971.         y1Temp[j] = -i;
  972.     }
  973.     }
  974.     y3PutArray( "yychk", y1Temp, y1NextState );
  975.  
  976.     y3PutArray( "yydef", y3DefaultAction, y1NextState );
  977.  
  978.     /* Copy parser text: */
  979.     while ((c = y1GetChar(y2InputFD))    !=   EOF) {
  980.     if (c == '$') {
  981.         if ((c = y1GetChar(y2InputFD)) != 'A')   putc( '$', y2ytabcFD );
  982.         else {
  983.         /* Copy actions: */
  984.         y2ActionFD = fopen( ACTNAME, "r" );
  985.         if (y2ActionFD == NULL)   {
  986.             y1Error( "y1PutRest: Cannot reopen action tempfile" );
  987.         }
  988.         while( (c=y1GetChar(y2ActionFD) ) != EOF ) putc( c, y2ytabcFD );
  989.         fclose(y2ActionFD);
  990.         ZAPFILE(ACTNAME);
  991.         c = y1GetChar(y2InputFD);
  992.         }
  993.     }
  994.     putc( c, y2ytabcFD );
  995.     }
  996.     fclose( y2ytabcFD );
  997. }
  998.  
  999. /************************************************************************/
  1000. /*    y1PrintLookahead    Print lookahead.                */
  1001. /************************************************************************/
  1002. static y1PrintLookahead( p )        /* Called from y1Closure, y1First */
  1003. struct looksets *p;
  1004. {
  1005.     register j, *pp;
  1006.     pp = p->lset;
  1007.  
  1008.     if (pp == 0)   fprintf( y2OutputFD, "\tNULL" );
  1009.     else {
  1010.     fprintf( y2OutputFD, " { " );
  1011.     FORaLLtERMINALS(j) {
  1012.         if (GETBIT(pp,j))    fprintf( y2OutputFD,  "%s ", y1SymbolName(j) );
  1013.     }
  1014.     fprintf( y2OutputFD,  "}" );
  1015.     }
  1016. }
  1017.  
  1018. /************************************************************************/
  1019. /*    y1PutItem                             */
  1020. /************************************************************************/
  1021. y1PutItem( ptr, lptr )        /* Called from y1MakeStates, y3Output    */
  1022. int *ptr;
  1023. struct looksets *lptr;
  1024. {
  1025.     register struct item *j;
  1026.  
  1027. #ifdef debug
  1028.     if (y2OutputFD != NULL) {
  1029.     fprintf(
  1030.         y2OutputFD,
  1031.         "y1PutItem(%s), state %d\n",
  1032.         y1WriteItem(ptr),
  1033.         y1NextState
  1034.     );
  1035.     }
  1036. #endif
  1037.     j = y1StateItem[ y1NextState+1 ];
  1038.     j->pitem = ptr;
  1039.     if (!y1NoLookahead)   j->look = y1Lookahead( lptr );
  1040.     y1StateItem[ y1NextState+1 ]  = ++j;
  1041.  
  1042.     if (((int *)j)  >    y1Nexty2PoolLoc) {
  1043.     y1Nexty2PoolLoc = (int *)j;
  1044.     if( y1Nexty2PoolLoc >=    &y2Pool[MAXy2POOL] ) {
  1045.         y1Error( "y1PutItem: Out of state space" );
  1046.     }
  1047.     }
  1048. }
  1049.  
  1050.  
  1051. /************************************************************************/
  1052. /*    y1SetUnion    A gets union of A and B.            */
  1053. /************************************************************************/
  1054. static y1SetUnion( a, b )      /* Called by y1First, y1Closure, y1State. */
  1055. register *a, *b;
  1056. {
  1057.     /***************************************************/
  1058.     /* Set a to the union of a and b.               */
  1059.     /* Return 1 if b is not a subset of a, 0 otherwise.*/
  1060.     /***************************************************/
  1061.  
  1062.     register i, x, sub;
  1063.  
  1064.     sub = 0;
  1065.     FORaLLlOOKAHEADwORDS(i) {
  1066.     *a = (x = *a)|*b++;
  1067.     if (*a++ != x)     sub = 1;
  1068.     }
  1069.     return   sub;
  1070. }
  1071.  
  1072.  
  1073. /************************************************************************/
  1074. /*    y1State        Sort last state, check it, return state #.    */
  1075. /************************************************************************/
  1076. y1State( c )        /* Called in y3Output, y1MakeStates        */
  1077. int c;
  1078. {
  1079.     /* Sort last state, and see if it equals earlier ones. return state #: */
  1080.  
  1081.     int size1,size2;
  1082.     register i;
  1083.     int *s;                             /*01*/
  1084.     struct looksets *ss;                     /*01*/
  1085.     int s__;                             /*01*/
  1086.     struct item *p1, *p2, *k, *l, *q1, *q2;
  1087.  
  1088.     p1 = y1StateItem[y1NextState];
  1089.     p2 = y1StateItem[y1NextState+1];
  1090.  
  1091.     if (p1==p2)   return(0); /* Null state. */
  1092.  
  1093.     /* Sort the items: */
  1094.     for (k = p2-1;   k > p1;   k--) {
  1095.     /* Make k the biggest: */
  1096.     for (l = k-1;    l >= p1;   --l)   {
  1097.         if (l->pitem > k->pitem) {
  1098.         s = k->pitem;
  1099.         k->pitem = l->pitem;
  1100.         l->pitem = s;
  1101.         ss = k->look;
  1102.         k->look = l->look;
  1103.         l->look = ss;
  1104.         }
  1105.     }
  1106.     }
  1107.  
  1108.     /* Figure size of state: */
  1109.     size1 = p2 - p1;
  1110.  
  1111.     for (
  1112.     i =   (c >= FIRSTnONTERMINAL)    ?   y1NonterminalState[ c-FIRSTnONTERMINAL ]   :   y1TerminalState[ c ]
  1113.     ;
  1114.     i != 0
  1115.     ;
  1116.     i = y1Link[i]
  1117.     ) {
  1118.     /* Get ith state */
  1119.     q1    = y1StateItem[ i     ];
  1120.     q2    = y1StateItem[ i+1 ];
  1121.     size2 = q2 - q1;
  1122.  
  1123.     if (size1 != size2)   continue;
  1124.     k   = p1;
  1125.  
  1126.     for (l = q1;   l < q2;     l++) {
  1127.         if (l->pitem != k->pitem)    break;
  1128.         ++k;
  1129.     }
  1130.     if (l != q2)   continue;
  1131.  
  1132.     /* Found it: */
  1133.  
  1134.     /* Delete last state: */
  1135.     y1StateItem[y1NextState+1] = y1StateItem[y1NextState];
  1136.  
  1137.     /* Fix up lookaheads: */
  1138.     if (y1NoLookahead)   return(i);
  1139.     for (l = q1 , k = p1;    l < q2;   ++l, ++k) {
  1140.         FORaLLlOOKAHEADwORDS(s__) y1ClosureSet.lset[s__] = l->look->lset[s__];
  1141.  
  1142.         if (y1SetUnion( y1ClosureSet.lset, k->look->lset )) {
  1143.         y1StateType[i] = MUSTdOsTATE;
  1144.  
  1145.         /* Register the new set: */
  1146.         l->look = y1Lookahead( &y1ClosureSet );
  1147.         }
  1148.     }
  1149.     return     i;
  1150.     }
  1151.  
  1152.     /* State is new: */
  1153.     if (y1NoLookahead)         y1Error( "y1State: Yacc state/y1NoLookahead error" );
  1154.     y1StateItem[ y1NextState+2 ] = p2;
  1155.     if (y1NextState+1 >= MAXsTATES)   y1Error("y1State: Too many states" );
  1156.  
  1157.     if (c >= FIRSTnONTERMINAL) {
  1158.     y1Link[ y1NextState ]     = y1NonterminalState[ c-FIRSTnONTERMINAL ];
  1159.     y1NonterminalState[ c-FIRSTnONTERMINAL ] = y1NextState;
  1160.     } else {
  1161.     y1Link[ y1NextState ] = y1TerminalState[ c ];
  1162.     y1TerminalState[ c ] = y1NextState;
  1163.     }
  1164.     y1StateType[y1NextState]=MUSTdOsTATE;
  1165.     return  y1NextState++;
  1166. }
  1167.  
  1168.  
  1169. /************************************************************************/
  1170. /*    y1Summary         Write the summary on the terminal.              */ 
  1171. /************************************************************************/
  1172. static y1Summary() {    /* Called in y1CheckEmpty, y1Yield, y1Error, main */
  1173.  
  1174.  
  1175.     if (y2OutputFD != NULL) {
  1176.     fprintf(
  1177.         y2OutputFD,
  1178.         "\n%d/%d terminals, %d/%d nonterminals\n",
  1179.         y2NextTerminal,
  1180.         MAXtERMINALsTATES,
  1181.         y2LastNonterminal,
  1182.         MAXnONTERMINALsTATES
  1183.     );
  1184.     fprintf(
  1185.         y2OutputFD,
  1186.         "%d/%d grammar rules, %d/%d states\n",
  1187.         y2ThisProduction,
  1188.         MAXpRODUCTIONS,
  1189.         y1NextState,
  1190.         MAXsTATES
  1191.     );
  1192.     fprintf(
  1193.         y2OutputFD,
  1194.         "%d shift/reduce, %d reduce/reduce conflicts reported\n",
  1195.         y1ShiftReduceConflicts,
  1196.         y1ReduceReduceConflicts
  1197.     );
  1198.     fprintf(
  1199.         y2OutputFD,
  1200.         "%d/%d working sets used\n", y1LastWorkingSet-y1WorkingSet,
  1201.         MAXy1wORKINGsET
  1202.     );
  1203.     fprintf(
  1204.         y2OutputFD,
  1205.         "memory: states,etc. %d/%d, parser %d/%d\n",
  1206.         y1Nexty2PoolLoc-y2Pool,
  1207.         MAXy2POOL,
  1208.         y1NextAction-y1Action,
  1209.         MAXaCTIONS
  1210.     );
  1211.     fprintf(
  1212.         y2OutputFD,
  1213.         "%d/%d distinct lookahead sets\n",
  1214.         y1NextLookaheadSet,
  1215.         MAXy1lOOKAHEADsETS
  1216.     );
  1217.     fprintf( y2OutputFD, "%d extra closures\n", y1ClosuresDone - 2*y1NextState );
  1218.     fprintf(
  1219.         y2OutputFD,
  1220.         "%d shift entries, %d exceptions\n",
  1221.         y1ShiftEntries,
  1222.         y1Exceptions
  1223.     );
  1224.     fprintf( y2OutputFD, "%d goto entries\n", y1GotoEntries );
  1225.     fprintf( y2OutputFD, "%d entries saved by goto default\n", y1GotosSavedByDefault );
  1226.     }
  1227.     if (y1ShiftReduceConflicts || y1ReduceReduceConflicts) {
  1228.     fprintf( stdout,"\nconflicts: ");
  1229.     if (y1ShiftReduceConflicts)   fprintf( stdout, "%d shift/reduce" , y1ShiftReduceConflicts );
  1230.     if (y1ShiftReduceConflicts && y1ReduceReduceConflicts) fprintf( stdout, ", " );
  1231.     if (y1ReduceReduceConflicts)   fprintf( stdout, "%d reduce/reduce" , y1ReduceReduceConflicts );
  1232.     fprintf( stdout, "\n" );
  1233.     }
  1234.  
  1235.     fclose( y2TempFileFD );
  1236.     if (y2DefineFD != NULL)   fclose( y2DefineFD );
  1237. }
  1238.  
  1239.  
  1240. /************************************************************************/
  1241. /*    y1SymbolName    Return a pointer to the name of symbol i.    */
  1242. /************************************************************************/
  1243. char *y1SymbolName( i )     /* Called from all over */
  1244. int i;
  1245. {
  1246.     char *cp;
  1247.  
  1248.     cp    = (i>=FIRSTnONTERMINAL) ? y2NonterminalState[i-FIRSTnONTERMINAL].name : y2Terminal[i].name ;
  1249.  
  1250.     if (*cp == ' ')   ++cp;
  1251.  
  1252.     return   cp;
  1253. }
  1254.  
  1255. /************************************************************************/
  1256. /*    y1UngetChar    Unget one char.                 */
  1257. /************************************************************************/
  1258. y1UngetChar(c, iop)        /* Called from all over.        */
  1259. char c;
  1260. FILE iop; /* WARNING: iop ignored ... y1UngetChar's are multiplexed!!! */
  1261. {
  1262.     *y1TopStack++ = c;
  1263. }
  1264.  
  1265. /************************************************************************/
  1266. /*    y1WriteItem    Creates output string for item pointed to by pp.*/
  1267. /************************************************************************/
  1268. char *y1WriteItem(pp)    /* Called from: y1Closure, y1PutItem,        */
  1269. int *pp;        /*        y3HideProductions, y3WriteState */
  1270. {
  1271.     static char   sarr[ISIZE];
  1272.     char          *q;
  1273.     int       i;
  1274.     int       *p;
  1275.  
  1276.     for (p = pp;   *p > 0;   ++p);
  1277.     p = y2Production[-*p];
  1278.     q = y1CharCopy( sarr, y2NonterminalState[*p-FIRSTnONTERMINAL].name );
  1279.     q = y1CharCopy( q, " : " );
  1280.  
  1281.     loop {
  1282.     *q++ = ++p==pp ? '_' : ' ';
  1283.     *q = '\0';
  1284.     if ((i = *p)   <=   0)     break;
  1285.     q = y1CharCopy( q, y1SymbolName(i) );
  1286.     if (q > &sarr[ISIZE-30])   y1Error( "y1WriteItem: Item too big" );
  1287.     }
  1288.  
  1289.     if ((i = *pp)   <    0) {
  1290.     /* An item calling for a reduction: */
  1291.     q = y1CharCopy( q, "    (" );
  1292.     sprintf( q, "%d)", -i );
  1293.     }
  1294.     return( sarr );
  1295. }
  1296.  
  1297. /************************************************************************/
  1298. /*    y1Yield           List productions yielding each nonterminal.     */ 
  1299. /************************************************************************/ 
  1300. static y1Yield() {     /* Called only by main.                */
  1301.  
  1302.     /********************************************/ 
  1303.     /* First stage of grammar processing:    */
  1304.     /* For each nonterminal NT, find all the    */
  1305.     /* alternate rules defining NT.        */
  1306.     /* y1YieldedBy[] points to these lists.    */
  1307.     /* pyield[] has the lists: the        */
  1308.     /* total size is only MAXpRODUCTIONS+1    */
  1309.     /********************************************/ 
  1310.  
  1311.     static int *pyield[ MAXpRODUCTIONS ];
  1312.     register **pmem;
  1313.     register c, j, i; 
  1314.   
  1315.  
  1316.     pmem = pyield; 
  1317.   
  1318.     /*****************************************************/
  1319.     /* Want to identify all undefined nonterminals, not  */
  1320.     /* just first, so make errors nonfatal for now:     */
  1321.     /*****************************************************/
  1322.     y1ErrorsFatal = FALSE;
  1323.   
  1324.     /* Tackle all nonterminals sequentially: */
  1325.     FORaLLnONTERMINALS(i) {
  1326.  
  1327.     /* Figure internal name for this nonterminal: */
  1328.     c = i + FIRSTnONTERMINAL;
  1329.  
  1330.     y1YieldedBy[ i ]    = pmem;
  1331.  
  1332.     /* Check all productions in memory: */
  1333.     FORaLLpRODUCTIONS(0,j) {
  1334.  
  1335.             /********************************************************/
  1336.         /* The nonterminal defined by a rule is the first entry */
  1337.         /* in it.  Remember this rule if it defines our current */
  1338.         /* nonterminal:                        */
  1339.             /********************************************************/
  1340.         if (*y2Production[j] == c)     *pmem++ =  y2Production[j]+1;
  1341.         } 
  1342.  
  1343.     /* If we found no rules defining this nonterminal, complain: */
  1344.         if (y1YieldedBy[i] == pmem) {
  1345.         y1Error(
  1346.         "y1Yield:  Nonterminal %s not defined!",
  1347.         y2NonterminalState[ i ].name
  1348.         );
  1349.         } 
  1350.     } 
  1351.  
  1352.     /* Leave pointer to remaining free memory: */
  1353.     y1YieldedBy[i] = pmem;
  1354.  
  1355.     /* Errors are again fatal until further notice: */
  1356.     y1ErrorsFatal = TRUE;
  1357.  
  1358.     /* Quit if there were any undefined nonterminals: */
  1359.     if (y1Errors) {
  1360.         y1Summary(); 
  1361.         exit(EX_ERR); 
  1362.     } 
  1363.  
  1364.     /* Just for fun, check that we found exactly as many rules as expected: */
  1365.     if (pmem != &pyield[ y2ThisProduction ]) {
  1366.     y1Error(
  1367.         "y1Yield: Internal Yacc error: pyield %d",
  1368.         pmem-&pyield[y2ThisProduction]
  1369.     );
  1370.     } 
  1371.   
  1372.  
  1373.