home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 22 gnu / 22-gnu.zip / BYACC.ZIP / RCS / READER.C_V < prev    next >
Text File  |  1992-06-10  |  30KB  |  1,760 lines

  1. head    1.1;
  2. access;
  3. symbols;
  4. locks; strict;
  5. comment    @ * @;
  6.  
  7.  
  8. 1.1
  9. date    92.06.10.21.55.08;    author downey;    state Exp;
  10. branches;
  11. next    ;
  12.  
  13.  
  14. desc
  15. @@
  16.  
  17.  
  18. 1.1
  19. log
  20. @Initial revision
  21. @
  22. text
  23. @#include "defs.h"
  24.  
  25.  
  26. /*  The line size must be a positive integer.  One hundred was chosen    */
  27. /*  because few lines in Yacc input grammars exceed 100 characters.    */
  28. /*  Note that if a line exceeds LINESIZE characters, the line buffer    */
  29. /*  will be expanded to accomodate it.                    */
  30.  
  31. #define LINESIZE 100
  32.  
  33.  
  34. char *cache;
  35. int cinc, cache_size;
  36.  
  37. int ntags, tagmax;
  38. char **tag_table;
  39.  
  40. char saw_eof, unionized;
  41. char *cptr, *line;
  42. int linesize;
  43.  
  44. bucket *goal;
  45. int prec;
  46. int gensym;
  47. char last_was_action;
  48.  
  49. int maxitems;
  50. bucket **pitem;
  51.  
  52. int maxrules;
  53. bucket **plhs;
  54.  
  55. int name_pool_size;
  56. char *name_pool;
  57.  
  58. char line_format[] = "#line %d \"%s\"\n";
  59.  
  60.  
  61. cachec(c)
  62. int c;
  63. {
  64.     assert(cinc >= 0);
  65.     if (cinc >= cache_size)
  66.     {
  67.     cache_size += 256;
  68.     cache = REALLOC(cache, cache_size);
  69.     if (cache == 0) no_space();
  70.     }
  71.     cache[cinc] = c;
  72.     ++cinc;
  73. }
  74.  
  75.  
  76. get_line()
  77. {
  78.     register FILE *f = input_file;
  79.     register int c;
  80.     register int i;
  81.  
  82.     if (saw_eof || (c = getc(f)) == EOF)
  83.     {
  84.     if (line) { FREE(line); line = 0; }
  85.     cptr = 0;
  86.     saw_eof = 1;
  87.     return;
  88.     }
  89.  
  90.     if (line == 0 || linesize != (LINESIZE + 1))
  91.     {
  92.     if (line) FREE(line);
  93.     linesize = LINESIZE + 1;
  94.     line = MALLOC(linesize);
  95.     if (line == 0) no_space();
  96.     }
  97.  
  98.     i = 0;
  99.     ++lineno;
  100.     for (;;)
  101.     {
  102.     line[i]  =  c;
  103.     if (c == '\n') { cptr = line; return; }
  104.     if (++i >= linesize)
  105.     {
  106.         linesize += LINESIZE;
  107.         line = REALLOC(line, linesize);
  108.         if (line ==  0) no_space();
  109.     }
  110.     c = getc(f);
  111.     if (c ==  EOF)
  112.     {
  113.         line[i] = '\n';
  114.         saw_eof = 1;
  115.         cptr = line;
  116.         return;
  117.     }
  118.     }
  119. }
  120.  
  121.  
  122. char *
  123. dup_line()
  124. {
  125.     register char *p, *s, *t;
  126.  
  127.     if (line == 0) return (0);
  128.     s = line;
  129.     while (*s != '\n') ++s;
  130.     p = MALLOC(s - line + 1);
  131.     if (p == 0) no_space();
  132.  
  133.     s = line;
  134.     t = p;
  135.     while ((*t++ = *s++) != '\n') continue;
  136.     return (p);
  137. }
  138.  
  139.  
  140. skip_comment()
  141. {
  142.     register char *s;
  143.  
  144.     int st_lineno = lineno;
  145.     char *st_line = dup_line();
  146.     char *st_cptr = st_line + (cptr - line);
  147.  
  148.     s = cptr + 2;
  149.     for (;;)
  150.     {
  151.     if (*s == '*' && s[1] == '/')
  152.     {
  153.         cptr = s + 2;
  154.         FREE(st_line);
  155.         return;
  156.     }
  157.     if (*s == '\n')
  158.     {
  159.         get_line();
  160.         if (line == 0)
  161.         unterminated_comment(st_lineno, st_line, st_cptr);
  162.         s = cptr;
  163.     }
  164.     else
  165.         ++s;
  166.     }
  167. }
  168.  
  169.  
  170. int
  171. nextc()
  172. {
  173.     register char *s;
  174.  
  175.     if (line == 0)
  176.     {
  177.     get_line();
  178.     if (line == 0)
  179.         return (EOF);
  180.     }
  181.  
  182.     s = cptr;
  183.     for (;;)
  184.     {
  185.     switch (*s)
  186.     {
  187.     case '\n':
  188.         get_line();
  189.         if (line == 0) return (EOF);
  190.         s = cptr;
  191.         break;
  192.  
  193.     case ' ':
  194.     case '\t':
  195.     case '\f':
  196.     case '\r':
  197.     case '\v':
  198.     case ',':
  199.     case ';':
  200.         ++s;
  201.         break;
  202.  
  203.     case '\\':
  204.         cptr = s;
  205.         return ('%');
  206.  
  207.     case '/':
  208.         if (s[1] == '*')
  209.         {
  210.         cptr = s;
  211.         skip_comment();
  212.         s = cptr;
  213.         break;
  214.         }
  215.         else if (s[1] == '/')
  216.         {
  217.         get_line();
  218.         if (line == 0) return (EOF);
  219.         s = cptr;
  220.         break;
  221.         }
  222.         /* fall through */
  223.  
  224.     default:
  225.         cptr = s;
  226.         return (*s);
  227.     }
  228.     }
  229. }
  230.  
  231.  
  232. int
  233. keyword()
  234. {
  235.     register int c;
  236.     char *t_cptr = cptr;
  237.  
  238.     c = *++cptr;
  239.     if (isalpha(c))
  240.     {
  241.     cinc = 0;
  242.     for (;;)
  243.     {
  244.         if (isalpha(c))
  245.         {
  246.         if (isupper(c)) c = tolower(c);
  247.         cachec(c);
  248.         }
  249.         else if (isdigit(c) || c == '_' || c == '.' || c == '$')
  250.         cachec(c);
  251.         else
  252.         break;
  253.         c = *++cptr;
  254.     }
  255.     cachec(NUL);
  256.  
  257.     if (strcmp(cache, "token") == 0 || strcmp(cache, "term") == 0)
  258.         return (TOKEN);
  259.     if (strcmp(cache, "type") == 0)
  260.         return (TYPE);
  261.     if (strcmp(cache, "left") == 0)
  262.         return (LEFT);
  263.     if (strcmp(cache, "right") == 0)
  264.         return (RIGHT);
  265.     if (strcmp(cache, "nonassoc") == 0 || strcmp(cache, "binary") == 0)
  266.         return (NONASSOC);
  267.     if (strcmp(cache, "start") == 0)
  268.         return (START);
  269.     if (strcmp(cache, "union") == 0)
  270.         return (UNION);
  271.     if (strcmp(cache, "ident") == 0)
  272.         return (IDENT);
  273.     }
  274.     else
  275.     {
  276.     ++cptr;
  277.     if (c == '{')
  278.         return (TEXT);
  279.     if (c == '%' || c == '\\')
  280.         return (MARK);
  281.     if (c == '<')
  282.         return (LEFT);
  283.     if (c == '>')
  284.         return (RIGHT);
  285.     if (c == '0')
  286.         return (TOKEN);
  287.     if (c == '2')
  288.         return (NONASSOC);
  289.     }
  290.     syntax_error(lineno, line, t_cptr);
  291.     /*NOTREACHED*/
  292. }
  293.  
  294.  
  295. copy_ident()
  296. {
  297.     register int c;
  298.     register FILE *f = output_file;
  299.  
  300.     c = nextc();
  301.     if (c == EOF) unexpected_EOF();
  302.     if (c != '"') syntax_error(lineno, line, cptr);
  303.     ++outline;
  304.     fprintf(f, "#ident \"");
  305.     for (;;)
  306.     {
  307.     c = *++cptr;
  308.     if (c == '\n')
  309.     {
  310.         fprintf(f, "\"\n");
  311.         return;
  312.     }
  313.     putc(c, f);
  314.     if (c == '"')
  315.     {
  316.         putc('\n', f);
  317.         ++cptr;
  318.         return;
  319.     }
  320.     }
  321. }
  322.  
  323.  
  324. copy_text()
  325. {
  326.     register int c;
  327.     int quote;
  328.     register FILE *f = text_file;
  329.     int need_newline = 0;
  330.     int t_lineno = lineno;
  331.     char *t_line = dup_line();
  332.     char *t_cptr = t_line + (cptr - line - 2);
  333.  
  334.     if (*cptr == '\n')
  335.     {
  336.     get_line();
  337.     if (line == 0)
  338.         unterminated_text(t_lineno, t_line, t_cptr);
  339.     }
  340.     if (!lflag) fprintf(f, line_format, lineno, input_file_name);
  341.  
  342. loop:
  343.     c = *cptr++;
  344.     switch (c)
  345.     {
  346.     case '\n':
  347.     next_line:
  348.     putc('\n', f);
  349.     need_newline = 0;
  350.     get_line();
  351.     if (line) goto loop;
  352.     unterminated_text(t_lineno, t_line, t_cptr);
  353.  
  354.     case '\'':
  355.     case '"':
  356.     {
  357.         int s_lineno = lineno;
  358.         char *s_line = dup_line();
  359.         char *s_cptr = s_line + (cptr - line - 1);
  360.  
  361.         quote = c;
  362.         putc(c, f);
  363.         for (;;)
  364.         {
  365.         c = *cptr++;
  366.         putc(c, f);
  367.         if (c == quote)
  368.         {
  369.             need_newline = 1;
  370.             FREE(s_line);
  371.             goto loop;
  372.         }
  373.         if (c == '\n')
  374.             unterminated_string(s_lineno, s_line, s_cptr);
  375.         if (c == '\\')
  376.         {
  377.             c = *cptr++;
  378.             putc(c, f);
  379.             if (c == '\n')
  380.             {
  381.             get_line();
  382.             if (line == 0)
  383.                 unterminated_string(s_lineno, s_line, s_cptr);
  384.             }
  385.         }
  386.         }
  387.     }
  388.  
  389.     case '/':
  390.     putc(c, f);
  391.     need_newline = 1;
  392.     c = *cptr;
  393.     if (c == '/')
  394.     {
  395.         putc('*', f);
  396.         while ((c = *++cptr) != '\n') putc(c, f);
  397.         fprintf(f, "*/");
  398.         goto next_line;
  399.     }
  400.     if (c == '*')
  401.     {
  402.         int c_lineno = lineno;
  403.         char *c_line = dup_line();
  404.         char *c_cptr = c_line + (cptr - line - 1);
  405.  
  406.         putc('*', f);
  407.         ++cptr;
  408.         for (;;)
  409.         {
  410.         c = *cptr++;
  411.         putc(c, f);
  412.         if (c == '*' && *cptr == '/')
  413.         {
  414.             putc('/', f);
  415.             ++cptr;
  416.             FREE(c_line);
  417.             goto loop;
  418.         }
  419.         if (c == '\n')
  420.         {
  421.             get_line();
  422.             if (line == 0)
  423.             unterminated_comment(c_lineno, c_line, c_cptr);
  424.         }
  425.         }
  426.     }
  427.     putc('/', f);
  428.     need_newline = 1;
  429.     goto loop;
  430.  
  431.     case '%':
  432.     case '\\':
  433.     if (*cptr == '}')
  434.     {
  435.         if (need_newline) putc('\n', f);
  436.         ++cptr;
  437.         FREE(t_line);
  438.         return;
  439.     }
  440.     /* fall through */
  441.  
  442.     default:
  443.     putc(c, f);
  444.     need_newline = 1;
  445.     goto loop;
  446.     }
  447. }
  448.  
  449.  
  450. copy_union()
  451. {
  452.     register int c;
  453.     int quote;
  454.     int depth;
  455.     int u_lineno = lineno;
  456.     char *u_line = dup_line();
  457.     char *u_cptr = u_line + (cptr - line - 6);
  458.  
  459.     if (unionized) over_unionized(cptr - 6);
  460.     unionized = 1;
  461.  
  462.     if (!lflag)
  463.     fprintf(text_file, line_format, lineno, input_file_name);
  464.  
  465.     fprintf(text_file, "typedef union");
  466.     if (dflag) fprintf(union_file, "typedef union");
  467.  
  468.     depth = 0;
  469. loop:
  470.     c = *cptr++;
  471.     putc(c, text_file);
  472.     if (dflag) putc(c, union_file);
  473.     switch (c)
  474.     {
  475.     case '\n':
  476.     next_line:
  477.     get_line();
  478.     if (line == 0) unterminated_union(u_lineno, u_line, u_cptr);
  479.     goto loop;
  480.  
  481.     case '{':
  482.     ++depth;
  483.     goto loop;
  484.  
  485.     case '}':
  486.     if (--depth == 0)
  487.     {
  488.         fprintf(text_file, " YYSTYPE;\n");
  489.         if (dflag) fprintf(text_file, " YYSTYPE;\n");
  490.         FREE(u_line);
  491.         return;
  492.     }
  493.     goto loop;
  494.  
  495.     case '\'':
  496.     case '"':
  497.     {
  498.         int s_lineno = lineno;
  499.         char *s_line = dup_line();
  500.         char *s_cptr = s_line + (cptr - line - 1);
  501.  
  502.         quote = c;
  503.         for (;;)
  504.         {
  505.         c = *cptr++;
  506.         putc(c, text_file);
  507.         if (dflag) putc(c, union_file);
  508.         if (c == quote)
  509.         {
  510.             FREE(s_line);
  511.             goto loop;
  512.         }
  513.         if (c == '\n')
  514.             unterminated_string(s_lineno, s_line, s_cptr);
  515.         if (c == '\\')
  516.         {
  517.             c = *cptr++;
  518.             putc(c, text_file);
  519.             if (dflag) putc(c, union_file);
  520.             if (c == '\n')
  521.             {
  522.             get_line();
  523.             if (line == 0)
  524.                 unterminated_string(s_lineno, s_line, s_cptr);
  525.             }
  526.         }
  527.         }
  528.     }
  529.  
  530.     case '/':
  531.     c = *cptr;
  532.     if (c == '/')
  533.     {
  534.         putc('*', text_file);
  535.         if (dflag) putc('*', union_file);
  536.         while ((c = *++cptr) != '\n')
  537.         {
  538.         putc(c, text_file);
  539.         if (dflag) putc(c, union_file);
  540.         }
  541.         fprintf(text_file, "*/\n");
  542.         if (dflag) fprintf(union_file, "*/\n");
  543.         goto next_line;
  544.     }
  545.     if (c == '*')
  546.     {
  547.         int c_lineno = lineno;
  548.         char *c_line = dup_line();
  549.         char *c_cptr = c_line + (cptr - line - 1);
  550.  
  551.         putc('*', text_file);
  552.         if (dflag) putc('*', union_file);
  553.         for (;;)
  554.         {
  555.         c = *++cptr;
  556.         putc(c, text_file);
  557.         if (dflag) putc(c, union_file);
  558.         if (c == '*' && cptr[1] == '/')
  559.         {
  560.             putc('/', text_file);
  561.             if (dflag) putc('/', union_file);
  562.             cptr += 2;
  563.             FREE(c_line);
  564.             goto loop;
  565.         }
  566.         if (c == '\n')
  567.         {
  568.             get_line();
  569.             if (line == 0)
  570.             unterminated_comment(c_lineno, c_line, c_cptr);
  571.         }
  572.         }
  573.     }
  574.     goto loop;
  575.  
  576.     default:
  577.     goto loop;
  578.     }
  579. }
  580.  
  581.  
  582. int
  583. hexval(c)
  584. int c;
  585. {
  586.     if (c >= '0' && c <= '9')
  587.     return (c - '0');
  588.     if (c >= 'A' && c <= 'F')
  589.     return (c - 'A' + 10);
  590.     if (c >= 'a' && c <= 'f')
  591.     return (c - 'a' + 10);
  592.     return (-1);
  593. }
  594.  
  595.  
  596. bucket *
  597. get_literal()
  598. {
  599.     register int c, quote;
  600.     register int i;
  601.     register int n;
  602.     register char *s;
  603.     register bucket *bp;
  604.     int s_lineno = lineno;
  605.     char *s_line = dup_line();
  606.     char *s_cptr = s_line + (cptr - line);
  607.  
  608.     quote = *cptr++;
  609.     cinc = 0;
  610.     for (;;)
  611.     {
  612.     c = *cptr++;
  613.     if (c == quote) break;
  614.     if (c == '\n') unterminated_string(s_lineno, s_line, s_cptr);
  615.     if (c == '\\')
  616.     {
  617.         char *c_cptr = cptr - 1;
  618.  
  619.         c = *cptr++;
  620.         switch (c)
  621.         {
  622.         case '\n':
  623.         get_line();
  624.         if (line == 0) unterminated_string(s_lineno, s_line, s_cptr);
  625.         continue;
  626.  
  627.         case '0': case '1': case '2': case '3':
  628.         case '4': case '5': case '6': case '7':
  629.         n = c - '0';
  630.         c = *cptr++;
  631.         if (IS_OCTAL(c))
  632.         {
  633.             n = (n << 3) + (c - '0');
  634.             c = *cptr++;
  635.             if (IS_OCTAL(c))
  636.             {
  637.             n = (n << 3) + (c - '0');
  638.             ++cptr;
  639.             }
  640.         }
  641.         if (n > MAXCHAR) illegal_character(c_cptr);
  642.         c = n;
  643.             break;
  644.  
  645.         case 'x':
  646.         c = *cptr++;
  647.         n = hexval(c);
  648.         if (n < 0 || n >= 16)
  649.             illegal_character(c_cptr);
  650.         for (;;)
  651.         {
  652.             c = *cptr++;
  653.             i = hexval(c);
  654.             if (i < 0 || i >= 16) break;
  655.             n = (n << 4) + i;
  656.             if (n > MAXCHAR) illegal_character(c_cptr);
  657.         }
  658.         c = n;
  659.         break;
  660.  
  661.         case 'a': c = 7; break;
  662.         case 'b': c = '\b'; break;
  663.         case 'f': c = '\f'; break;
  664.         case 'n': c = '\n'; break;
  665.         case 'r': c = '\r'; break;
  666.         case 't': c = '\t'; break;
  667.         case 'v': c = '\v'; break;
  668.         }
  669.     }
  670.     cachec(c);
  671.     }
  672.     FREE(s_line);
  673.  
  674.     n = cinc;
  675.     s = MALLOC(n);
  676.     if (s == 0) no_space();
  677.     
  678.     for (i = 0; i < n; ++i)
  679.     s[i] = cache[i];
  680.  
  681.     cinc = 0;
  682.     if (n == 1)
  683.     cachec('\'');
  684.     else
  685.     cachec('"');
  686.  
  687.     for (i = 0; i < n; ++i)
  688.     {
  689.     c = ((unsigned char *)s)[i];
  690.     if (c == '\\' || c == cache[0])
  691.     {
  692.         cachec('\\');
  693.         cachec(c);
  694.     }
  695.     else if (isprint(c))
  696.         cachec(c);
  697.     else
  698.     {
  699.         cachec('\\');
  700.         switch (c)
  701.         {
  702.         case 7: cachec('a'); break;
  703.         case '\b': cachec('b'); break;
  704.         case '\f': cachec('f'); break;
  705.         case '\n': cachec('n'); break;
  706.         case '\r': cachec('r'); break;
  707.         case '\t': cachec('t'); break;
  708.         case '\v': cachec('v'); break;
  709.         default:
  710.         cachec(c >> 6);
  711.         cachec((c >> 3) & 7);
  712.         cachec(c & 7);
  713.         break;
  714.         }
  715.     }
  716.     }
  717.  
  718.     if (n == 1)
  719.     cachec('\'');
  720.     else
  721.     cachec('"');
  722.  
  723.     cachec(NUL);
  724.     bp = lookup(cache);
  725.     bp->class = TERM;
  726.     if (n == 1 && bp->value == UNDEFINED)
  727.     bp->value = *(unsigned char *)s;
  728.     FREE(s);
  729.  
  730.     return (bp);
  731. }
  732.  
  733.  
  734. int
  735. is_reserved(name)
  736. char *name;
  737. {
  738.     char *s;
  739.  
  740.     if (strcmp(name, ".") == 0 ||
  741.         strcmp(name, "$accept") == 0 ||
  742.         strcmp(name, "$end") == 0)
  743.     return (1);
  744.  
  745.     if (name[0] == '$' && name[1] == '$' && isdigit(name[2]))
  746.     {
  747.     s = name + 3;
  748.     while (isdigit(*s)) ++s;
  749.     if (*s == NUL) return (1);
  750.     }
  751.  
  752.     return (0);
  753. }
  754.  
  755.  
  756. bucket *
  757. get_name()
  758. {
  759.     register int c;
  760.  
  761.     cinc = 0;
  762.     for (c = *cptr; IS_IDENT(c); c = *++cptr)
  763.     cachec(c);
  764.     cachec(NUL);
  765.  
  766.     if (is_reserved(cache)) used_reserved(cache);
  767.  
  768.     return (lookup(cache));
  769. }
  770.  
  771.  
  772. int
  773. get_number()
  774. {
  775.     register int c;
  776.     register int n;
  777.  
  778.     n = 0;
  779.     for (c = *cptr; isdigit(c); c = *++cptr)
  780.     n = 10*n + (c - '0');
  781.  
  782.     return (n);
  783. }
  784.  
  785.  
  786. char *
  787. get_tag()
  788. {
  789.     register int c;
  790.     register int i;
  791.     register char *s;
  792.     int t_lineno = lineno;
  793.     char *t_line = dup_line();
  794.     char *t_cptr = t_line + (cptr - line);
  795.  
  796.     ++cptr;
  797.     c = nextc();
  798.     if (c == EOF) unexpected_EOF();
  799.     if (!isalpha(c) && c != '_' && c != '$')
  800.     illegal_tag(t_lineno, t_line, t_cptr);
  801.  
  802.     cinc = 0;
  803.     do { cachec(c); c = *++cptr; } while (IS_IDENT(c));
  804.     cachec(NUL);
  805.  
  806.     c = nextc();
  807.     if (c == EOF) unexpected_EOF();
  808.     if (c != '>')
  809.     illegal_tag(t_lineno, t_line, t_cptr);
  810.     ++cptr;
  811.  
  812.     for (i = 0; i < ntags; ++i)
  813.     {
  814.     if (strcmp(cache, tag_table[i]) == 0)
  815.         return (tag_table[i]);
  816.     }
  817.  
  818.     if (ntags >= tagmax)
  819.     {
  820.     tagmax += 16;
  821.     tag_table = (char **)
  822.             (tag_table ? REALLOC(tag_table, tagmax*sizeof(char *))
  823.                    : MALLOC(tagmax*sizeof(char *)));
  824.     if (tag_table == 0) no_space();
  825.     }
  826.  
  827.     s = MALLOC(cinc);
  828.     if  (s == 0) no_space();
  829.     strcpy(s, cache);
  830.     tag_table[ntags] = s;
  831.     ++ntags;
  832.     FREE(t_line);
  833.     return (s);
  834. }
  835.  
  836.  
  837. declare_tokens(assoc)
  838. int assoc;
  839. {
  840.     register int c;
  841.     register bucket *bp;
  842.     int value;
  843.     char *tag = 0;
  844.  
  845.     if (assoc != TOKEN) ++prec;
  846.  
  847.     c = nextc();
  848.     if (c == EOF) unexpected_EOF();
  849.     if (c == '<')
  850.     {
  851.     tag = get_tag();
  852.     c = nextc();
  853.     if (c == EOF) unexpected_EOF();
  854.     }
  855.  
  856.     for (;;)
  857.     {
  858.     if (isalpha(c) || c == '_' || c == '.' || c == '$')
  859.         bp = get_name();
  860.     else if (c == '\'' || c == '"')
  861.         bp = get_literal();
  862.     else
  863.         return;
  864.  
  865.     if (bp == goal) tokenized_start(bp->name);
  866.     bp->class = TERM;
  867.  
  868.     if (tag)
  869.     {
  870.         if (bp->tag && tag != bp->tag)
  871.         retyped_warning(bp->name);
  872.         bp->tag = tag;
  873.     }
  874.  
  875.     if (assoc != TOKEN)
  876.     {
  877.         if (bp->prec && prec != bp->prec)
  878.         reprec_warning(bp->name);
  879.         bp->assoc = assoc;
  880.         bp->prec = prec;
  881.     }
  882.  
  883.     c = nextc();
  884.     if (c == EOF) unexpected_EOF();
  885.     value = UNDEFINED;
  886.     if (isdigit(c))
  887.     {
  888.         value = get_number();
  889.         if (bp->value != UNDEFINED && value != bp->value)
  890.         revalued_warning(bp->name);
  891.         bp->value = value;
  892.         c = nextc();
  893.         if (c == EOF) unexpected_EOF();
  894.     }
  895.     }
  896. }
  897.  
  898.  
  899. declare_types()
  900. {
  901.     register int c;
  902.     register bucket *bp;
  903.     char *tag;
  904.  
  905.     c = nextc();
  906.     if (c == EOF) unexpected_EOF();
  907.     if (c != '<') syntax_error(lineno, line, cptr);
  908.     tag = get_tag();
  909.  
  910.     for (;;)
  911.     {
  912.     c = nextc();
  913.     if (isalpha(c) || c == '_' || c == '.' || c == '$')
  914.         bp = get_name();
  915.     else if (c == '\'' || c == '"')
  916.         bp = get_literal();
  917.     else
  918.         return;
  919.  
  920.     if (bp->tag && tag != bp->tag)
  921.         retyped_warning(bp->name);
  922.     bp->tag = tag;
  923.     }
  924. }
  925.  
  926.  
  927. declare_start()
  928. {
  929.     register int c;
  930.     register bucket *bp;
  931.  
  932.     c = nextc();
  933.     if (c == EOF) unexpected_EOF();
  934.     if (!isalpha(c) && c != '_' && c != '.' && c != '$')
  935.     syntax_error(lineno, line, cptr);
  936.     bp = get_name();
  937.     if (bp->class == TERM)
  938.     terminal_start(bp->name);
  939.     if (goal && goal != bp)
  940.     restarted_warning();
  941.     goal = bp;
  942. }
  943.  
  944.  
  945. read_declarations()
  946. {
  947.     register int c, k;
  948.  
  949.     cache_size = 256;
  950.     cache = MALLOC(cache_size);
  951.     if (cache == 0) no_space();
  952.  
  953.     for (;;)
  954.     {
  955.     c = nextc();
  956.     if (c == EOF) unexpected_EOF();
  957.     if (c != '%') syntax_error(lineno, line, cptr);
  958.     switch (k = keyword())
  959.     {
  960.     case MARK:
  961.         return;
  962.  
  963.     case IDENT:
  964.         copy_ident();
  965.         break;
  966.  
  967.     case TEXT:
  968.         copy_text();
  969.         break;
  970.  
  971.     case UNION:
  972.         copy_union();
  973.         break;
  974.  
  975.     case TOKEN:
  976.     case LEFT:
  977.     case RIGHT:
  978.     case NONASSOC:
  979.         declare_tokens(k);
  980.         break;
  981.  
  982.     case TYPE:
  983.         declare_types();
  984.         break;
  985.  
  986.     case START:
  987.         declare_start();
  988.         break;
  989.     }
  990.     }
  991. }
  992.  
  993.  
  994. initialize_grammar()
  995. {
  996.     nitems = 4;
  997.     maxitems = 300;
  998.     pitem = (bucket **) MALLOC(maxitems*sizeof(bucket *));
  999.     if (pitem == 0) no_space();
  1000.     pitem[0] = 0;
  1001.     pitem[1] = 0;
  1002.     pitem[2] = 0;
  1003.     pitem[3] = 0;
  1004.  
  1005.     nrules = 3;
  1006.     maxrules = 100;
  1007.     plhs = (bucket **) MALLOC(maxrules*sizeof(bucket *));
  1008.     if (plhs == 0) no_space();
  1009.     plhs[0] = 0;
  1010.     plhs[1] = 0;
  1011.     plhs[2] = 0;
  1012.     rprec = (short *) MALLOC(maxrules*sizeof(short));
  1013.     if (rprec == 0) no_space();
  1014.     rprec[0] = 0;
  1015.     rprec[1] = 0;
  1016.     rprec[2] = 0;
  1017.     rassoc = (char *) MALLOC(maxrules*sizeof(char));
  1018.     if (rassoc == 0) no_space();
  1019.     rassoc[0] = TOKEN;
  1020.     rassoc[1] = TOKEN;
  1021.     rassoc[2] = TOKEN;
  1022. }
  1023.  
  1024.  
  1025. expand_items()
  1026. {
  1027.     maxitems += 300;
  1028.     pitem = (bucket **) REALLOC(pitem, maxitems*sizeof(bucket *));
  1029.     if (pitem == 0) no_space();
  1030. }
  1031.  
  1032.  
  1033. expand_rules()
  1034. {
  1035.     maxrules += 100;
  1036.     plhs = (bucket **) REALLOC(plhs, maxrules*sizeof(bucket *));
  1037.     if (plhs == 0) no_space();
  1038.     rprec = (short *) REALLOC(rprec, maxrules*sizeof(short));
  1039.     if (rprec == 0) no_space();
  1040.     rassoc = (char *) REALLOC(rassoc, maxrules*sizeof(char));
  1041.     if (rassoc == 0) no_space();
  1042. }
  1043.  
  1044.  
  1045. advance_to_start()
  1046. {
  1047.     register int c;
  1048.     register bucket *bp;
  1049.     char *s_cptr;
  1050.     int s_lineno;
  1051.  
  1052.     for (;;)
  1053.     {
  1054.     c = nextc();
  1055.     if (c != '%') break;
  1056.     s_cptr = cptr;
  1057.     switch (keyword())
  1058.     {
  1059.     case MARK:
  1060.         no_grammar();
  1061.  
  1062.     case TEXT:
  1063.         copy_text();
  1064.         break;
  1065.  
  1066.     case START:
  1067.         declare_start();
  1068.         break;
  1069.  
  1070.     default:
  1071.         syntax_error(lineno, line, s_cptr);
  1072.     }
  1073.     }
  1074.  
  1075.     c = nextc();
  1076.     if (!isalpha(c) && c != '_' && c != '.' && c != '_')
  1077.     syntax_error(lineno, line, cptr);
  1078.     bp = get_name();
  1079.     if (goal == 0)
  1080.     {
  1081.     if (bp->class == TERM)
  1082.         terminal_start(bp->name);
  1083.     goal = bp;
  1084.     }
  1085.  
  1086.     s_lineno = lineno;
  1087.     c = nextc();
  1088.     if (c == EOF) unexpected_EOF();
  1089.     if (c != ':') syntax_error(lineno, line, cptr);
  1090.     start_rule(bp, s_lineno);
  1091.     ++cptr;
  1092. }
  1093.  
  1094.  
  1095. start_rule(bp, s_lineno)
  1096. register bucket *bp;
  1097. int s_lineno;
  1098. {
  1099.     if (bp->class == TERM)
  1100.     terminal_lhs(s_lineno);
  1101.     bp->class = NONTERM;
  1102.     if (nrules >= maxrules)
  1103.     expand_rules();
  1104.     plhs[nrules] = bp;
  1105.     rprec[nrules] = UNDEFINED;
  1106.     rassoc[nrules] = TOKEN;
  1107. }
  1108.  
  1109.  
  1110. end_rule()
  1111. {
  1112.     register int i;
  1113.  
  1114.     if (!last_was_action && plhs[nrules]->tag)
  1115.     {
  1116.     for (i = nitems - 1; pitem[i]; --i) continue;
  1117.     if (pitem[i+1]->tag != plhs[nrules]->tag)
  1118.         default_action_warning();
  1119.     }
  1120.  
  1121.     last_was_action = 0;
  1122.     if (nitems >= maxitems) expand_items();
  1123.     pitem[nitems] = 0;
  1124.     ++nitems;
  1125.     ++nrules;
  1126. }
  1127.  
  1128.  
  1129. insert_empty_rule()
  1130. {
  1131.     register bucket *bp, **bpp;
  1132.  
  1133.     assert(cache);
  1134.     sprintf(cache, "$$%d", ++gensym);
  1135.     bp = make_bucket(cache);
  1136.     bp->tag = plhs[nrules]->tag;
  1137.     bp->class = NONTERM;
  1138.  
  1139.     if ((nitems += 2) > maxitems)
  1140.     expand_items();
  1141.     bpp = pitem + nitems - 1;
  1142.     *bpp-- = bp;
  1143.     while (bpp[0] = bpp[-1]) --bpp;
  1144.  
  1145.     if (++nrules >= maxrules)
  1146.     expand_rules();
  1147.     plhs[nrules] = plhs[nrules-1];
  1148.     plhs[nrules-1] = bp;
  1149.     rprec[nrules] = rprec[nrules-1];
  1150.     rprec[nrules-1] = 0;
  1151.     rassoc[nrules] = rassoc[nrules-1];
  1152.     rassoc[nrules-1] = TOKEN;
  1153. }
  1154.  
  1155.  
  1156. add_symbol()
  1157. {
  1158.     register int c;
  1159.     register bucket *bp;
  1160.     int s_lineno = lineno;
  1161.  
  1162.     c = *cptr;
  1163.     if (c == '\'' || c == '"')
  1164.     bp = get_literal();
  1165.     else
  1166.     bp = get_name();
  1167.  
  1168.     c = nextc();
  1169.     if (c == ':')
  1170.     {
  1171.     end_rule();
  1172.     start_rule(bp, s_lineno);
  1173.     ++cptr;
  1174.     return;
  1175.     }
  1176.  
  1177.     if (last_was_action)
  1178.     insert_empty_rule();
  1179.     last_was_action = 0;
  1180.  
  1181.     if (++nitems > maxitems)
  1182.     expand_items();
  1183.     pitem[nitems-1] = bp;
  1184. }
  1185.  
  1186.  
  1187. copy_action()
  1188. {
  1189.     register int c;
  1190.     register int i, n;
  1191.     int depth;
  1192.     int quote;
  1193.     char *tag;
  1194.     register FILE *f = action_file;
  1195.     int a_lineno = lineno;
  1196.     char *a_line = dup_line();
  1197.     char *a_cptr = a_line + (cptr - line);
  1198.  
  1199.     if (last_was_action)
  1200.     insert_empty_rule();
  1201.     last_was_action = 1;
  1202.  
  1203.     fprintf(f, "case %d:\n", nrules - 2);
  1204.     if (!lflag)
  1205.     fprintf(f, line_format, lineno, input_file_name);
  1206.     if (*cptr == '=') ++cptr;
  1207.  
  1208.     n = 0;
  1209.     for (i = nitems - 1; pitem[i]; --i) ++n;
  1210.  
  1211.     depth = 0;
  1212. loop:
  1213.     c = *cptr;
  1214.     if (c == '$')
  1215.     {
  1216.     if (cptr[1] == '<')
  1217.     {
  1218.         int d_lineno = lineno;
  1219.         char *d_line = dup_line();
  1220.         char *d_cptr = d_line + (cptr - line);
  1221.  
  1222.         ++cptr;
  1223.         tag = get_tag();
  1224.         c = *cptr;
  1225.         if (c == '$')
  1226.         {
  1227.         fprintf(f, "yyval.%s ", tag);
  1228.         ++cptr;
  1229.         FREE(d_line);
  1230.         goto loop;
  1231.         }
  1232.         else if (isdigit(c))
  1233.         {
  1234.         i = get_number();
  1235.         if (i > n) dollar_warning(d_lineno, i);
  1236.         fprintf(f, "yyvsp[%d].%s ", i - n, tag);
  1237.         FREE(d_line);
  1238.         goto loop;
  1239.         }
  1240.         else if (c == '-' && isdigit(cptr[1]))
  1241.         {
  1242.         ++cptr;
  1243.         i = -get_number() - n;
  1244.         fprintf(f, "yyvsp[%d].%s ", i, tag);
  1245.         FREE(d_line);
  1246.         goto loop;
  1247.         }
  1248.         else
  1249.         dollar_error(d_lineno, d_line, d_cptr);
  1250.     }
  1251.     else if (cptr[1] == '$')
  1252.     {
  1253.         if (ntags)
  1254.         {
  1255.         tag = plhs[nrules]->tag;
  1256.         if (tag == 0) untyped_lhs();
  1257.         fprintf(f, "yyval.%s ", tag);
  1258.         }
  1259.         else
  1260.         fprintf(f, "yyval ");
  1261.         cptr += 2;
  1262.         goto loop;
  1263.     }
  1264.     else if (isdigit(cptr[1]))
  1265.     {
  1266.         ++cptr;
  1267.         i = get_number();
  1268.         if (ntags)
  1269.         {
  1270.         if (i <= 0 || i > n)
  1271.             unknown_rhs(i);
  1272.         tag = pitem[nitems + i - n - 1]->tag;
  1273.         if (tag == 0) untyped_rhs(i, pitem[nitems + i - n - 1]->name);
  1274.         fprintf(f, "yyvsp[%d].%s ", i - n, tag);
  1275.         }
  1276.         else
  1277.         {
  1278.         if (i > n) dollar_warning(lineno, i);
  1279.         fprintf(f, "yyvsp[%d]", i - n);
  1280.         }
  1281.         goto loop;
  1282.     }
  1283.     }
  1284.     if (isalpha(c) || c == '_' || c == '$')
  1285.     {
  1286.     do
  1287.     {
  1288.         putc(c, f);
  1289.         c = *++cptr;
  1290.     } while (isalnum(c) || c == '_' || c == '$');
  1291.     goto loop;
  1292.     }
  1293.     putc(c, f);
  1294.     ++cptr;
  1295.     switch (c)
  1296.     {
  1297.     case '\n':
  1298.     next_line:
  1299.     get_line();
  1300.     if (line) goto loop;
  1301.     unterminated_action(a_lineno, a_line, a_cptr);
  1302.  
  1303.     case ';':
  1304.     if (depth > 0) goto loop;
  1305.     fprintf(f, "\nbreak;\n");
  1306.     return;
  1307.  
  1308.     case '{':
  1309.     ++depth;
  1310.     goto loop;
  1311.  
  1312.     case '}':
  1313.     if (--depth > 0) goto loop;
  1314.     fprintf(f, "\nbreak;\n");
  1315.     return;
  1316.  
  1317.     case '\'':
  1318.     case '"':
  1319.     {
  1320.         int s_lineno = lineno;
  1321.         char *s_line = dup_line();
  1322.         char *s_cptr = s_line + (cptr - line - 1);
  1323.  
  1324.         quote = c;
  1325.         for (;;)
  1326.         {
  1327.         c = *cptr++;
  1328.         putc(c, f);
  1329.         if (c == quote)
  1330.         {
  1331.             FREE(s_line);
  1332.             goto loop;
  1333.         }
  1334.         if (c == '\n')
  1335.             unterminated_string(s_lineno, s_line, s_cptr);
  1336.         if (c == '\\')
  1337.         {
  1338.             c = *cptr++;
  1339.             putc(c, f);
  1340.             if (c == '\n')
  1341.             {
  1342.             get_line();
  1343.             if (line == 0)
  1344.                 unterminated_string(s_lineno, s_line, s_cptr);
  1345.             }
  1346.         }
  1347.         }
  1348.     }
  1349.  
  1350.     case '/':
  1351.     c = *cptr;
  1352.     if (c == '/')
  1353.     {
  1354.         putc('*', f);
  1355.         while ((c = *++cptr) != '\n') putc(c, f);
  1356.         fprintf(f, "*/\n");
  1357.         goto next_line;
  1358.     }
  1359.     if (c == '*')
  1360.     {
  1361.         int c_lineno = lineno;
  1362.         char *c_line = dup_line();
  1363.         char *c_cptr = c_line + (cptr - line - 1);
  1364.  
  1365.         putc('*', f);
  1366.         for (;;)
  1367.         {
  1368.         c = *++cptr;
  1369.         putc(c, f);
  1370.         if (c == '*' && cptr[1] == '/')
  1371.         {
  1372.             putc('/', f);
  1373.             cptr += 2;
  1374.             FREE(c_line);
  1375.             goto loop;
  1376.         }
  1377.         if (c == '\n')
  1378.         {
  1379.             get_line();
  1380.             if (line == 0)
  1381.             unterminated_comment(c_lineno, c_line, c_cptr);
  1382.         }
  1383.         }
  1384.     }
  1385.     goto loop;
  1386.  
  1387.     default:
  1388.     goto loop;
  1389.     }
  1390. }
  1391.  
  1392.  
  1393. int
  1394. mark_symbol()
  1395. {
  1396.     register int c;
  1397.     register bucket *bp;
  1398.  
  1399.     c = cptr[1];
  1400.     if (c == '%' || c == '\\')
  1401.     {
  1402.     cptr += 2;
  1403.     return (1);
  1404.     }
  1405.  
  1406.     if (c == '=')
  1407.     cptr += 2;
  1408.     else if ((c == 'p' || c == 'P') &&
  1409.          ((c = cptr[2]) == 'r' || c == 'R') &&
  1410.          ((c = cptr[3]) == 'e' || c == 'E') &&
  1411.          ((c = cptr[4]) == 'c' || c == 'C') &&
  1412.          ((c = cptr[5], !IS_IDENT(c))))
  1413.     cptr += 5;
  1414.     else
  1415.     syntax_error(lineno, line, cptr);
  1416.  
  1417.     c = nextc();
  1418.     if (isalpha(c) || c == '_' || c == '.' || c == '$')
  1419.     bp = get_name();
  1420.     else if (c == '\'' || c == '"')
  1421.     bp = get_literal();
  1422.     else
  1423.     syntax_error(lineno, line, cptr);
  1424.  
  1425.     if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules])
  1426.     prec_redeclared();
  1427.  
  1428.     rprec[nrules] = bp->prec;
  1429.     rassoc[nrules] = bp->assoc;
  1430.     return (0);
  1431. }
  1432.  
  1433.  
  1434. read_grammar()
  1435. {
  1436.     register int c;
  1437.  
  1438.     initialize_grammar();
  1439.     advance_to_start();
  1440.  
  1441.     for (;;)
  1442.     {
  1443.     c = nextc();
  1444.     if (c == EOF) break;
  1445.     if (isalpha(c) || c == '_' || c == '.' || c == '$' || c == '\'' ||
  1446.         c == '"')
  1447.         add_symbol();
  1448.     else if (c == '{' || c == '=')
  1449.         copy_action();
  1450.     else if (c == '|')
  1451.     {
  1452.         end_rule();
  1453.         start_rule(plhs[nrules-1], 0);
  1454.         ++cptr;
  1455.     }
  1456.     else if (c == '%')
  1457.     {
  1458.         if (mark_symbol()) break;
  1459.     }
  1460.     else
  1461.         syntax_error(lineno, line, cptr);
  1462.     }
  1463.     end_rule();
  1464. }
  1465.  
  1466.  
  1467. free_tags()
  1468. {
  1469.     register int i;
  1470.  
  1471.     if (tag_table == 0) return;
  1472.  
  1473.     for (i = 0; i < ntags; ++i)
  1474.     {
  1475.     assert(tag_table[i]);
  1476.     FREE(tag_table[i]);
  1477.     }
  1478.     FREE(tag_table);
  1479. }
  1480.  
  1481.  
  1482. pack_names()
  1483. {
  1484.     register bucket *bp;
  1485.     register char *p, *s, *t;
  1486.  
  1487.     name_pool_size = 13;  /* 13 == sizeof("$end") + sizeof("$accept") */
  1488.     for (bp = first_symbol; bp; bp = bp->next)
  1489.     name_pool_size += strlen(bp->name) + 1;
  1490.     name_pool = MALLOC(name_pool_size);
  1491.     if (name_pool == 0) no_space();
  1492.  
  1493.     strcpy(name_pool, "$accept");
  1494.     strcpy(name_pool+8, "$end");
  1495.     t = name_pool + 13;
  1496.     for (bp = first_symbol; bp; bp = bp->next)
  1497.     {
  1498.     p = t;
  1499.     s = bp->name;
  1500.     while (*t++ = *s++) continue;
  1501.     FREE(bp->name);
  1502.     bp->name = p;
  1503.     }
  1504. }
  1505.  
  1506.  
  1507. check_symbols()
  1508. {
  1509.     register bucket *bp;
  1510.  
  1511.     if (goal->class == UNKNOWN)
  1512.     undefined_goal(goal->name);
  1513.  
  1514.     for (bp = first_symbol; bp; bp = bp->next)
  1515.     {
  1516.     if (bp->class == UNKNOWN)
  1517.     {
  1518.         undefined_symbol_warning(bp->name);
  1519.         bp->class = TERM;
  1520.     }
  1521.     }
  1522. }
  1523.  
  1524.  
  1525. pack_symbols()
  1526. {
  1527.     register bucket *bp;
  1528.     register bucket **v;
  1529.     register int i, j, k, n;
  1530.  
  1531.     nsyms = 2;
  1532.     ntokens = 1;
  1533.     for (bp = first_symbol; bp; bp = bp->next)
  1534.     {
  1535.     ++nsyms;
  1536.     if (bp->class == TERM) ++ntokens;
  1537.     }
  1538.     start_symbol = ntokens;
  1539.     nvars = nsyms - ntokens;
  1540.  
  1541.     symbol_name = (char **) MALLOC(nsyms*sizeof(char *));
  1542.     if (symbol_name == 0) no_space();
  1543.     symbol_value = (short *) MALLOC(nsyms*sizeof(short));
  1544.     if (symbol_value == 0) no_space();
  1545.     symbol_prec = (short *) MALLOC(nsyms*sizeof(short));
  1546.     if (symbol_prec == 0) no_space();
  1547.     symbol_assoc = MALLOC(nsyms);
  1548.     if (symbol_assoc == 0) no_space();
  1549.  
  1550.     v = (bucket **) MALLOC(nsyms*sizeof(bucket *));
  1551.     if (v == 0) no_space();
  1552.  
  1553.     v[0] = 0;
  1554.     v[start_symbol] = 0;
  1555.  
  1556.     i = 1;
  1557.     j = start_symbol + 1;
  1558.     for (bp = first_symbol; bp; bp = bp->next)
  1559.     {
  1560.     if (bp->class == TERM)
  1561.         v[i++] = bp;
  1562.     else
  1563.         v[j++] = bp;
  1564.     }
  1565.     assert(i == ntokens && j == nsyms);
  1566.  
  1567.     for (i = 1; i < ntokens; ++i)
  1568.     v[i]->index = i;
  1569.  
  1570.     goal->index = start_symbol + 1;
  1571.     k = start_symbol + 2;
  1572.     while (++i < nsyms)
  1573.     if (v[i] != goal)
  1574.     {
  1575.         v[i]->index = k;
  1576.         ++k;
  1577.     }
  1578.  
  1579.     goal->value = 0;
  1580.     k = 1;
  1581.     for (i = start_symbol + 1; i < nsyms; ++i)
  1582.     {
  1583.     if (v[i] != goal)
  1584.     {
  1585.         v[i]->value = k;
  1586.         ++k;
  1587.     }
  1588.     }
  1589.  
  1590.     k = 0;
  1591.     for (i = 1; i < ntokens; ++i)
  1592.     {
  1593.     n = v[i]->value;
  1594.     if (n > 256)
  1595.     {
  1596.         for (j = k++; j > 0 && symbol_value[j-1] > n; --j)
  1597.         symbol_value[j] = symbol_value[j-1];
  1598.         symbol_value[j] = n;
  1599.     }
  1600.     }
  1601.  
  1602.     if (v[1]->value == UNDEFINED)
  1603.     v[1]->value = 256;
  1604.  
  1605.     j = 0;
  1606.     n = 257;
  1607.     for (i = 2; i < ntokens; ++i)
  1608.     {
  1609.     if (v[i]->value == UNDEFINED)
  1610.     {
  1611.         while (j < k && n == symbol_value[j])
  1612.         {
  1613.         while (++j < k && n == symbol_value[j]) continue;
  1614.         ++n;
  1615.         }
  1616.         v[i]->value = n;
  1617.         ++n;
  1618.     }
  1619.     }
  1620.  
  1621.     symbol_name[0] = name_pool + 8;
  1622.     symbol_value[0] = 0;
  1623.     symbol_prec[0] = 0;
  1624.     symbol_assoc[0] = TOKEN;
  1625.     for (i = 1; i < ntokens; ++i)
  1626.     {
  1627.     symbol_name[i] = v[i]->name;
  1628.     symbol_value[i] = v[i]->value;
  1629.     symbol_prec[i] = v[i]->prec;
  1630.     symbol_assoc[i] = v[i]->assoc;
  1631.     }
  1632.     symbol_name[start_symbol] = name_pool;
  1633.     symbol_value[start_symbol] = -1;
  1634.     symbol_prec[start_symbol] = 0;
  1635.     symbol_assoc[start_symbol] = TOKEN;
  1636.     for (++i; i < nsyms; ++i)
  1637.     {
  1638.     k = v[i]->index;
  1639.     symbol_name[k] = v[i]->name;
  1640.     symbol_value[k] = v[i]->value;
  1641.     symbol_prec[k] = v[i]->prec;
  1642.     symbol_assoc[k] = v[i]->assoc;
  1643.     }
  1644.  
  1645.     FREE(v);
  1646. }
  1647.  
  1648.  
  1649. pack_grammar()
  1650. {
  1651.     register int i, j;
  1652.     int assoc, prec;
  1653.  
  1654.     ritem = (short *) MALLOC(nitems*sizeof(short));
  1655.     if (ritem == 0) no_space();
  1656.     rlhs = (short *) MALLOC(nrules*sizeof(short));
  1657.     if (rlhs == 0) no_space();
  1658.     rrhs = (short *) MALLOC((nrules+1)*sizeof(short));
  1659.     if (rrhs == 0) no_space();
  1660.     rprec = (short *) REALLOC(rprec, nrules*sizeof(short));
  1661.     if (rprec == 0) no_space();
  1662.     rassoc = REALLOC(rassoc, nrules);
  1663.     if (rassoc == 0) no_space();
  1664.  
  1665.     ritem[0] = -1;
  1666.     ritem[1] = goal->index;
  1667.     ritem[2] = 0;
  1668.     ritem[3] = -2;
  1669.     rlhs[0] = 0;
  1670.     rlhs[1] = 0;
  1671.     rlhs[2] = start_symbol;
  1672.     rrhs[0] = 0;
  1673.     rrhs[1] = 0;
  1674.     rrhs[2] = 1;
  1675.  
  1676.     j = 4;
  1677.     for (i = 3; i < nrules; ++i)
  1678.     {
  1679.     rlhs[i] = plhs[i]->index;
  1680.     rrhs[i] = j;
  1681.     assoc = TOKEN;
  1682.     prec = 0;
  1683.     while (pitem[j])
  1684.     {
  1685.         ritem[j] = pitem[j]->index;
  1686.         if (pitem[j]->class == TERM)
  1687.         {
  1688.         prec = pitem[j]->prec;
  1689.         assoc = pitem[j]->assoc;
  1690.         }
  1691.         ++j;
  1692.     }
  1693.     ritem[j] = -i;
  1694.     ++j;
  1695.     if (rprec[i] == UNDEFINED)
  1696.     {
  1697.         rprec[i] = prec;
  1698.         rassoc[i] = assoc;
  1699.     }
  1700.     }
  1701.     rrhs[i] = j;
  1702.  
  1703.     FREE(plhs);
  1704.     FREE(pitem);
  1705. }
  1706.  
  1707.  
  1708. print_grammar()
  1709. {
  1710.     register int i, j, k;
  1711.     int spacing;
  1712.     register FILE *f = verbose_file;
  1713.  
  1714.     if (!vflag) return;
  1715.  
  1716.     k = 1;
  1717.     for (i = 2; i < nrules; ++i)
  1718.     {
  1719.     if (rlhs[i] != rlhs[i-1])
  1720.     {
  1721.         if (i != 2) fprintf(f, "\n");
  1722.         fprintf(f, "%4d  %s :", i - 2, symbol_name[rlhs[i]]);
  1723.         spacing = strlen(symbol_name[rlhs[i]]) + 1;
  1724.     }
  1725.     else
  1726.     {
  1727.         fprintf(f, "%4d  ", i - 2);
  1728.         j = spacing;
  1729.         while (--j >= 0) putc(' ', f);
  1730.         putc('|', f);
  1731.     }
  1732.  
  1733.     while (ritem[k] >= 0)
  1734.     {
  1735.         fprintf(f, " %s", symbol_name[ritem[k]]);
  1736.         ++k;
  1737.     }
  1738.     ++k;
  1739.     putc('\n', f);
  1740.     }
  1741. }
  1742.  
  1743.  
  1744. reader()
  1745. {
  1746.     write_section(banner);
  1747.     create_symbol_table();
  1748.     read_declarations();
  1749.     read_grammar();
  1750.     free_symbol_table();
  1751.     free_tags();
  1752.     pack_names();
  1753.     check_symbols();
  1754.     pack_symbols();
  1755.     pack_grammar();
  1756.     free_symbols();
  1757.     print_grammar();
  1758. }
  1759. @
  1760.