home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 22 gnu / 22-gnu.zip / BYACC.ZIP / READER.C < prev    next >
C/C++ Source or Header  |  1992-03-16  |  32KB  |  1,736 lines

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