home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 342a.lha / Yacc_v1.0a / reader.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-02-05  |  36.3 KB  |  1,735 lines

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