1 /* $Id: reader.c,v 1.60 2016/03/25 00:51:07 tom Exp $ */
5 /* The line size must be a positive integer. One hundred was chosen */
6 /* because few lines in Yacc input grammars exceed 100 characters. */
7 /* Note that if a line exceeds LINESIZE characters, the line buffer */
8 /* will be expanded to accomodate it. */
19 /* the maximum number of arguments (inherited attributes) to a non-terminal */
20 /* this is a hard limit, but seems more than adequate */
23 static void start_rule(bucket *bp, int s_lineno);
25 static void copy_destructor(void);
26 static char *process_destructor_XX(char *code, char *tag);
29 #define CACHE_SIZE 256
31 static int cinc, cache_size;
34 static int tagmax, havetags;
35 static char **tag_table;
45 static char last_was_action;
48 static bucket **pitem;
53 static size_t name_pool_size;
54 static char *name_pool;
56 char line_format[] = "#line %d \"%s\"\n";
62 int destructor = 0; /* =1 if at least one %destructor */
64 static bucket *default_destructor[3] =
67 #define UNTYPED_DEFAULT 0
68 #define TYPED_DEFAULT 1
69 #define TYPE_SPECIFIED 2
72 lookup_type_destructor(char *tag)
74 const char fmt[] = "%.*s destructor";
75 char name[1024] = "\0";
76 bucket *bp, **bpp = &default_destructor[TYPE_SPECIFIED];
78 while ((bp = *bpp) != NULL)
85 sprintf(name, fmt, (int)(sizeof(name) - sizeof(fmt)), tag);
86 *bpp = bp = make_bucket(name);
91 #endif /* defined(YYBTYACC) */
97 if (cinc >= cache_size)
99 cache_size += CACHE_SIZE;
100 cache = TREALLOC(char, cache, cache_size);
103 cache[cinc] = (char)c;
110 FILE *f = input_file;
114 if (saw_eof || (c = getc(f)) == EOF)
126 if (line == 0 || linesize != (LINESIZE + 1))
130 linesize = LINESIZE + 1;
131 line = TMALLOC(char, linesize);
142 if ((i + 3) >= linesize)
144 linesize += LINESIZE;
145 line = TREALLOC(char, line, linesize);
171 p = TMALLOC(char, s - line + 1);
176 while ((*t++ = *s++) != '\n')
186 int st_lineno = lineno;
187 char *st_line = dup_line();
188 char *st_cptr = st_line + (cptr - line);
193 if (*s == '*' && s[1] == '/')
203 unterminated_comment(st_lineno, st_line, st_cptr);
236 else if (s[1] == '/')
261 switch (ch = next_inline())
288 static struct keyword
294 { "binary", NONASSOC },
295 #if defined(YYBTYACC)
296 { "destructor", DESTRUCTOR },
298 { "expect", EXPECT },
299 { "expect-rr", EXPECT_RR },
302 { "lex-param", LEX_PARAM },
303 #if defined(YYBTYACC)
304 { "locations", LOCATIONS },
306 { "nonassoc", NONASSOC },
307 { "parse-param", PARSE_PARAM },
308 { "pure-parser", PURE_PARSER },
313 { "token-table", TOKEN_TABLE },
316 { "yacc", POSIX_YACC },
321 compare_keys(const void *a, const void *b)
323 const struct keyword *p = (const struct keyword *)a;
324 const struct keyword *q = (const struct keyword *)b;
325 return strcmp(p->name, q->name);
356 /* treat keywords spelled with '_' as if it were '-' */
367 if ((key = bsearch(cache, keywords,
368 sizeof(keywords) / sizeof(*key),
369 sizeof(*key), compare_keys)))
377 if (c == '%' || c == '\\')
388 syntax_error(lineno, line, t_cptr);
395 FILE *f = output_file;
401 syntax_error(lineno, line, cptr);
403 fprintf(f, "#ident \"");
423 copy_string(int quote)
425 struct mstring *temp = msnew();
427 int s_lineno = lineno;
428 char *s_line = dup_line();
429 char *s_cptr = s_line + (cptr - line - 1);
441 unterminated_string(s_lineno, s_line, s_cptr);
450 unterminated_string(s_lineno, s_line, s_cptr);
459 struct mstring *temp = msnew();
466 while ((c = *++cptr) != '\n')
469 if (c == '*' && cptr[1] == '/')
477 int c_lineno = lineno;
478 char *c_line = dup_line();
479 char *c_cptr = c_line + (cptr - line - 1);
487 if (c == '*' && *cptr == '/')
498 unterminated_comment(c_lineno, c_line, c_cptr);
510 int need_newline = 0;
511 int t_lineno = lineno;
512 char *t_line = dup_line();
513 char *t_cptr = t_line + (cptr - line - 2);
519 unterminated_text(t_lineno, t_line, t_cptr);
522 fprintf(f, line_format, lineno, input_file_name);
534 unterminated_text(t_lineno, t_line, t_cptr);
540 char *s = copy_string(c);
550 char *s = copy_comment();
577 puts_both(const char *s)
581 fputs(s, union_file);
597 int u_lineno = lineno;
598 char *u_line = dup_line();
599 char *u_cptr = u_line + (cptr - line - 6);
602 over_unionized(cptr - 6);
606 fprintf(text_file, line_format, lineno, input_file_name);
608 puts_both("#ifdef YYSTYPE\n");
609 puts_both("#undef YYSTYPE_IS_DECLARED\n");
610 puts_both("#define YYSTYPE_IS_DECLARED 1\n");
611 puts_both("#endif\n");
612 puts_both("#ifndef YYSTYPE_IS_DECLARED\n");
613 puts_both("#define YYSTYPE_IS_DECLARED 1\n");
614 puts_both("typedef union");
625 unterminated_union(u_lineno, u_line, u_cptr);
635 puts_both(" YYSTYPE;\n");
636 puts_both("#endif /* !YYSTYPE_IS_DECLARED */\n");
645 char *s = copy_string(c);
653 char *s = copy_comment();
665 after_blanks(char *s)
667 while (*s != '\0' && isspace(UCH(*s)))
673 * Trim leading/trailing blanks, and collapse multiple embedded blanks to a
674 * single space. Return index to last character in the buffer.
677 trim_blanks(char *buffer)
682 char *s = after_blanks(d);
684 while ((*d++ = *s++) != '\0')
690 while ((--d != buffer) && isspace(UCH(*d)))
693 for (s = d = buffer; (*d++ = *s++) != '\0';)
695 if (isspace(UCH(*s)))
698 while (isspace(UCH(*s)))
707 return (int)strlen(buffer) - 1;
711 * Scan forward in the current line-buffer looking for a right-curly bracket.
713 * Parameters begin with a left-curly bracket, and continue until there are no
714 * more interesting characters after the last right-curly bracket on the
715 * current line. Bison documents parameters as separated like this:
716 * {type param1} {type2 param2}
717 * but also accepts commas (although some versions of bison mishandle this)
718 * {type param1, type2 param2}
728 switch (next_inline())
747 save_param(int k, char *buffer, int name, int type2)
751 p = TMALLOC(param, 1);
754 p->type2 = strdup(buffer + type2);
756 buffer[type2] = '\0';
757 (void)trim_blanks(p->type2);
759 p->name = strdup(buffer + name);
762 (void)trim_blanks(p->name);
764 p->type = strdup(buffer);
766 (void)trim_blanks(p->type);
790 * Keep a linked list of parameters. This may be multi-line, if the trailing
791 * right-curly bracket is absent.
802 int st_lineno = lineno;
836 if ((curly == 1) && (cptr == line))
846 if (curly == 0 && !isspace(UCH(c)))
854 buf_size = (size_t) linesize;
855 buf = TMALLOC(char, buf_size);
863 buf_size += (size_t) linesize;
864 buf = TREALLOC(char, buf, buf_size);
869 if ((state == 2) && (c == L_CURL))
873 else if ((state == 2) && isspace(UCH(c)))
877 else if ((c != L_CURL) && (c != R_CURL))
884 while (curly < 2 || more_curly());
897 (void)trim_blanks(buf);
902 char *parms = (comma + 1);
903 comma = strchr(parms, ',');
907 (void)trim_blanks(parms);
908 i = (int)strlen(parms) - 1;
917 while (i >= 0 && level > 0 && parms[i] != '[')
921 else if (parms[i] == '[')
934 while (i > 0 && (isalnum(UCH(parms[i])) || UCH(parms[i]) == '_'))
937 if (!isspace(UCH(parms[i])) && parms[i] != '*')
942 save_param(k, parms, name, type2);
950 syntax_error(lineno, line, cptr);
956 if (c >= '0' && c <= '9')
958 if (c >= 'A' && c <= 'F')
959 return (c - 'A' + 10);
960 if (c >= 'a' && c <= 'f')
961 return (c - 'a' + 10);
973 int s_lineno = lineno;
974 char *s_line = dup_line();
975 char *s_cptr = s_line + (cptr - line);
985 unterminated_string(s_lineno, s_line, s_cptr);
988 char *c_cptr = cptr - 1;
996 unterminated_string(s_lineno, s_line, s_cptr);
1011 n = (n << 3) + (c - '0');
1015 n = (n << 3) + (c - '0');
1020 illegal_character(c_cptr);
1027 if (n < 0 || n >= 16)
1028 illegal_character(c_cptr);
1033 if (i < 0 || i >= 16)
1038 illegal_character(c_cptr);
1071 s = TMALLOC(char, n);
1074 for (i = 0; i < n; ++i)
1083 for (i = 0; i < n; ++i)
1086 if (c == '\\' || c == cache[0])
1091 else if (isprint(c))
1120 cachec(((c >> 6) & 7) + '0');
1121 cachec(((c >> 3) & 7) + '0');
1122 cachec((c & 7) + '0');
1136 if (n == 1 && bp->value == UNDEFINED)
1137 bp->value = UCH(*s);
1144 is_reserved(char *name)
1148 if (strcmp(name, ".") == 0 ||
1149 strcmp(name, "$accept") == 0 ||
1150 strcmp(name, "$end") == 0)
1153 if (name[0] == '$' && name[1] == '$' && isdigit(UCH(name[2])))
1156 while (isdigit(UCH(*s)))
1171 for (c = *cptr; IS_IDENT(c); c = *++cptr)
1175 if (is_reserved(cache))
1176 used_reserved(cache);
1178 return (lookup(cache));
1188 for (c = *cptr; isdigit(c); c = *++cptr)
1189 n = (Value_t) (10 * n + (c - '0'));
1195 cache_tag(char *tag, size_t len)
1200 for (i = 0; i < ntags; ++i)
1202 if (strncmp(tag, tag_table[i], len) == 0 &&
1203 tag_table[i][len] == NUL)
1204 return (tag_table[i]);
1207 if (ntags >= tagmax)
1212 ? TREALLOC(char *, tag_table, tagmax)
1213 : TMALLOC(char *, tagmax));
1214 NO_SPACE(tag_table);
1217 s = TMALLOC(char, len + 1);
1220 strncpy(s, tag, len);
1222 tag_table[ntags++] = s;
1230 int t_lineno = lineno;
1231 char *t_line = dup_line();
1232 char *t_cptr = t_line + (cptr - line);
1238 if (!isalpha(c) && c != '_' && c != '$')
1239 illegal_tag(t_lineno, t_line, t_cptr);
1247 while (IS_IDENT(c));
1254 illegal_tag(t_lineno, t_line, t_cptr);
1259 return cache_tag(cache, (size_t) cinc);
1262 #if defined(YYBTYACC)
1268 while (isalnum(*cptr) || *cptr == '_' || *cptr == '$')
1270 return cache_tag(b, (size_t) (cptr - b));
1275 declare_tokens(int assoc)
1298 if (isalpha(c) || c == '_' || c == '.' || c == '$')
1300 else if (c == '\'' || c == '"')
1306 tokenized_start(bp->name);
1311 if (bp->tag && tag != bp->tag)
1312 retyped_warning(bp->name);
1318 if (bp->prec && prec != bp->prec)
1319 reprec_warning(bp->name);
1320 bp->assoc = (Assoc_t) assoc;
1330 value = get_number();
1331 if (bp->value != UNDEFINED && value != bp->value)
1332 revalued_warning(bp->name);
1342 * %expect requires special handling
1343 * as it really isn't part of the yacc
1344 * grammar only a flag for yacc proper.
1347 declare_expect(int assoc)
1351 if (assoc != EXPECT && assoc != EXPECT_RR)
1355 * Stay away from nextc - doesn't
1356 * detect EOL and will read to EOF.
1366 if (assoc == EXPECT)
1367 SRexpect = get_number();
1369 RRexpect = get_number();
1373 * Looking for number before EOL.
1374 * Spaces, tabs, and numbers are ok,
1375 * words, punc., etc. are syntax errors.
1377 else if (c == '\n' || isalpha(c) || !isspace(c))
1379 syntax_error(lineno, line, cptr);
1390 #if defined(YYBTYACC)
1392 declare_argtypes(bucket *bp)
1394 char *tags[MAXARGS];
1398 retyped_warning(bp->name);
1399 cptr++; /* skip open paren */
1406 syntax_error(lineno, line, cptr);
1407 tags[args++] = get_tag();
1414 cptr++; /* skip close paren */
1416 bp->argnames = TMALLOC(char *, args);
1417 NO_SPACE(bp->argnames);
1418 bp->argtags = CALLOC(sizeof(char *), args + 1);
1419 NO_SPACE(bp->argtags);
1422 bp->argtags[args] = tags[args];
1423 bp->argnames[args] = NULL;
1446 if (isalpha(c) || c == '_' || c == '.' || c == '$')
1449 #if defined(YYBTYACC)
1450 if (nextc() == L_PAREN)
1451 declare_argtypes(bp);
1456 else if (c == '\'' || c == '"')
1459 #if defined(YYBTYACC)
1468 if (bp->tag && tag != bp->tag)
1469 retyped_warning(bp->name);
1484 if (!isalpha(c) && c != '_' && c != '.' && c != '$')
1485 syntax_error(lineno, line, cptr);
1487 if (bp->class == TERM)
1488 terminal_start(bp->name);
1489 if (goal && goal != bp)
1490 restarted_warning();
1495 read_declarations(void)
1499 cache_size = CACHE_SIZE;
1500 cache = TMALLOC(char, cache_size);
1509 syntax_error(lineno, line, cptr);
1510 switch (k = keyword())
1560 #if defined(YYBTYACC)
1572 /* noop for bison compatibility. byacc is already designed to be posix
1573 * yacc compatible. */
1580 initialize_grammar(void)
1585 pitem = TMALLOC(bucket *, maxitems);
1596 plhs = TMALLOC(bucket *, maxrules);
1603 rprec = TMALLOC(Value_t, maxrules);
1610 rassoc = TMALLOC(Assoc_t, maxrules);
1622 pitem = TREALLOC(bucket *, pitem, maxitems);
1631 plhs = TREALLOC(bucket *, plhs, maxrules);
1634 rprec = TREALLOC(Value_t, rprec, maxrules);
1637 rassoc = TREALLOC(Assoc_t, rassoc, maxrules);
1641 /* set immediately prior to where copy_args() could be called, and incremented by
1642 the various routines that will rescan the argument list as appropriate */
1643 static int rescan_lineno;
1644 #if defined(YYBTYACC)
1647 copy_args(int *alen)
1649 struct mstring *s = msnew();
1650 int depth = 0, len = 1;
1652 int a_lineno = lineno;
1653 char *a_line = dup_line();
1654 char *a_cptr = a_line + (cptr - line - 1);
1656 while ((c = *cptr++) != R_PAREN || depth || quote)
1658 if (c == ',' && !quote && !depth)
1671 unterminated_string(a_lineno, a_line, a_cptr);
1673 unterminated_arglist(a_lineno, a_line, a_cptr);
1690 else if (c == R_PAREN)
1692 else if (c == '\"' || c == '\'')
1703 parse_id(char *p, char **save)
1710 if (!isalpha(*p) && *p != '_')
1713 while (isalnum(*p) || *p == '_' || *p == '$')
1717 *save = cache_tag(b, (size_t) (p - b));
1723 parse_int(char *p, int *save)
1725 int neg = 0, val = 0;
1738 val = val * 10 + *p++ - '0';
1747 parse_arginfo(bucket *a, char *args, int argslen)
1749 char *p = args, *tmp;
1754 if (a->args != argslen)
1755 arg_number_disagree_warning(rescan_lineno, a->name);
1760 if ((a->args = argslen) == 0)
1762 a->argnames = TMALLOC(char *, argslen);
1763 NO_SPACE(a->argnames);
1764 a->argtags = TMALLOC(char *, argslen);
1765 NO_SPACE(a->argtags);
1769 for (i = 0; i < argslen; i++)
1782 if (!(p = parse_id(p + 1, &tmp)))
1791 if (a->argtags[i] != tmp)
1792 arg_type_disagree_warning(rescan_lineno, i + 1, a->name);
1795 a->argtags[i] = tmp;
1798 a->argtags[i] = NULL;
1799 if (!(p = parse_id(p, &a->argnames[i])))
1811 compile_arg(char **theptr, char *yyvaltag)
1814 struct mstring *c = msnew();
1816 Value_t *offsets = NULL, maxoffset;
1821 for (i = nitems - 1; pitem[i]; --i)
1824 if (pitem[i]->class != ARGUMENT)
1829 offsets = TMALLOC(Value_t, maxoffset + 1);
1832 for (j = 0, i++; i < nitems; i++)
1833 if (pitem[i]->class != ARGUMENT)
1834 offsets[++j] = (Value_t) (i - nitems + 1);
1836 rhs = pitem + nitems - 1;
1839 msprintf(c, "yyval.%s = ", yyvaltag);
1841 msprintf(c, "yyval = ");
1848 if (!(p = parse_id(++p, &tag)) || *p++ != '>')
1849 illegal_tag(rescan_lineno, NULL, NULL);
1850 if (isdigit(*p) || *p == '-')
1853 if (!(p = parse_int(p, &val)))
1854 dollar_error(rescan_lineno, NULL, NULL);
1857 else if (val > maxoffset)
1859 dollar_warning(rescan_lineno, val);
1860 i = val - maxoffset;
1862 else if (maxoffset > 0)
1865 if (!tag && !(tag = rhs[i]->tag) && havetags)
1866 untyped_rhs(val, rhs[i]->name);
1868 msprintf(c, "yystack.l_mark[%d]", i);
1870 msprintf(c, ".%s", tag);
1874 else if (isalpha(*p) || *p == '_')
1877 if (!(p = parse_id(p, &arg)))
1878 dollar_error(rescan_lineno, NULL, NULL);
1879 for (i = plhs[nrules]->args - 1; i >= 0; i--)
1880 if (arg == plhs[nrules]->argnames[i])
1883 unknown_arg_warning(rescan_lineno, "$", arg, NULL, NULL);
1885 tag = plhs[nrules]->argtags[i];
1886 msprintf(c, "yystack.l_mark[%d]", i - plhs[nrules]->args + 1
1889 msprintf(c, ".%s", tag);
1891 untyped_arg_warning(rescan_lineno, "$", arg);
1894 dollar_error(rescan_lineno, NULL, NULL);
1898 at_error(rescan_lineno, NULL, NULL);
1913 #define ARG_CACHE_SIZE 1024
1914 static struct arg_cache
1916 struct arg_cache *next;
1920 *arg_cache[ARG_CACHE_SIZE];
1923 lookup_arg_cache(char *code)
1925 struct arg_cache *entry;
1927 entry = arg_cache[strnshash(code) % ARG_CACHE_SIZE];
1930 if (!strnscmp(entry->code, code))
1932 entry = entry->next;
1938 insert_arg_cache(char *code, int rule)
1940 struct arg_cache *entry = NEW(struct arg_cache);
1944 i = strnshash(code) % ARG_CACHE_SIZE;
1947 entry->next = arg_cache[i];
1948 arg_cache[i] = entry;
1952 clean_arg_cache(void)
1954 struct arg_cache *e, *t;
1957 for (i = 0; i < ARG_CACHE_SIZE; i++)
1959 for (e = arg_cache[i]; (t = e); e = e->next, FREE(t))
1961 arg_cache[i] = NULL;
1967 advance_to_start(void)
1973 #if defined(YYBTYACC)
1998 syntax_error(lineno, line, s_cptr);
2003 if (!isalpha(c) && c != '_' && c != '.' && c != '_')
2004 syntax_error(lineno, line, cptr);
2008 if (bp->class == TERM)
2009 terminal_start(bp->name);
2017 rescan_lineno = lineno; /* line# for possible inherited args rescan */
2018 #if defined(YYBTYACC)
2022 args = copy_args(&argslen);
2028 syntax_error(lineno, line, cptr);
2029 start_rule(bp, s_lineno);
2030 #if defined(YYBTYACC)
2031 parse_arginfo(bp, args, argslen);
2037 start_rule(bucket *bp, int s_lineno)
2039 if (bp->class == TERM)
2040 terminal_lhs(s_lineno);
2041 bp->class = NONTERM;
2044 if (nrules >= maxrules)
2047 rprec[nrules] = UNDEFINED;
2048 rassoc[nrules] = TOKEN;
2056 if (!last_was_action && plhs[nrules]->tag)
2058 if (pitem[nitems - 1])
2060 for (i = nitems - 1; (i > 0) && pitem[i]; --i)
2062 if (pitem[i + 1] == 0 || pitem[i + 1]->tag != plhs[nrules]->tag)
2063 default_action_warning();
2067 default_action_warning();
2071 last_was_action = 0;
2072 if (nitems >= maxitems)
2080 insert_empty_rule(void)
2085 assert(cache_size >= CACHE_SIZE);
2086 sprintf(cache, "$$%d", ++gensym);
2087 bp = make_bucket(cache);
2088 last_symbol->next = bp;
2090 bp->tag = plhs[nrules]->tag;
2092 #if defined(YYBTYACC)
2096 nitems = (Value_t) (nitems + 2);
2097 if (nitems > maxitems)
2099 bpp = pitem + nitems - 1;
2101 while ((bpp[0] = bpp[-1]) != 0)
2104 if (++nrules >= maxrules)
2106 plhs[nrules] = plhs[nrules - 1];
2107 plhs[nrules - 1] = bp;
2108 rprec[nrules] = rprec[nrules - 1];
2109 rprec[nrules - 1] = 0;
2110 rassoc[nrules] = rassoc[nrules - 1];
2111 rassoc[nrules - 1] = TOKEN;
2114 #if defined(YYBTYACC)
2116 insert_arg_rule(char *arg, char *tag)
2118 int line_number = rescan_lineno;
2119 char *code = compile_arg(&arg, tag);
2120 int rule = lookup_arg_cache(code);
2121 FILE *f = action_file;
2126 insert_arg_cache(code, rule);
2127 fprintf(f, "case %d:\n", rule - 2);
2129 fprintf(f, line_format, line_number, input_file_name);
2130 fprintf(f, "%s;\n", code);
2131 fprintf(f, "break;\n");
2132 insert_empty_rule();
2133 plhs[rule]->tag = tag;
2134 plhs[rule]->class = ARGUMENT;
2138 if (++nitems > maxitems)
2140 pitem[nitems - 1] = plhs[rule];
2152 int s_lineno = lineno;
2153 #if defined(YYBTYACC)
2159 if (c == '\'' || c == '"')
2165 rescan_lineno = lineno; /* line# for possible inherited args rescan */
2166 #if defined(YYBTYACC)
2170 args = copy_args(&argslen);
2178 start_rule(bp, s_lineno);
2179 #if defined(YYBTYACC)
2180 parse_arginfo(bp, args, argslen);
2186 if (last_was_action)
2187 insert_empty_rule();
2188 last_was_action = 0;
2190 #if defined(YYBTYACC)
2193 if (argslen == 0 && bp->args > 0 && pitem[nitems - 1] == NULL)
2196 if (plhs[nrules]->args != bp->args)
2197 wrong_number_args_warning("default ", bp->name);
2198 for (i = bp->args - 1; i >= 0; i--)
2199 if (plhs[nrules]->argtags[i] != bp->argtags[i])
2200 wrong_type_for_arg_warning(i + 1, bp->name);
2202 else if (bp->args != argslen)
2203 wrong_number_args_warning("", bp->name);
2204 if (bp->args > 0 && argslen > 0)
2208 for (ap = args, i = 0; i < argslen; i++)
2209 ap = insert_arg_rule(ap, bp->argtags[i]);
2212 #endif /* defined(YYBTYACC) */
2214 if (++nitems > maxitems)
2216 pitem[nitems - 1] = bp;
2225 #if defined(YYBTYACC)
2226 int trialaction = 0;
2230 FILE *f = action_file;
2231 int a_lineno = lineno;
2232 char *a_line = dup_line();
2233 char *a_cptr = a_line + (cptr - line);
2234 Value_t *offsets = NULL, maxoffset;
2237 if (last_was_action)
2238 insert_empty_rule();
2239 last_was_action = 1;
2241 fprintf(f, "case %d:\n", nrules - 2);
2242 #if defined(YYBTYACC)
2245 if (*cptr != L_BRAC)
2246 fprintf(f, " if (!yytrial)\n");
2252 fprintf(f, line_format, lineno, input_file_name);
2256 /* avoid putting curly-braces in first column, to ease editing */
2257 if (*after_blanks(cptr) == L_CURL)
2260 cptr = after_blanks(cptr);
2265 for (i = nitems - 1; pitem[i]; --i)
2268 if (pitem[i]->class != ARGUMENT)
2273 offsets = TMALLOC(Value_t, maxoffset + 1);
2276 for (j = 0, i++; i < nitems; i++)
2278 if (pitem[i]->class != ARGUMENT)
2280 offsets[++j] = (Value_t) (i - nitems + 1);
2284 rhs = pitem + nitems - 1;
2293 int d_lineno = lineno;
2294 char *d_line = dup_line();
2295 char *d_cptr = d_line + (cptr - line);
2302 fprintf(f, "yyval.%s", tag);
2307 else if (isdigit(c))
2311 fprintf(f, "yystack.l_mark[%d].%s", -n, tag);
2312 else if (i > maxoffset)
2314 dollar_warning(d_lineno, i);
2315 fprintf(f, "yystack.l_mark[%d].%s", i - maxoffset, tag);
2318 fprintf(f, "yystack.l_mark[%d].%s", offsets[i], tag);
2322 else if (c == '-' && isdigit(UCH(cptr[1])))
2325 i = -get_number() - n;
2326 fprintf(f, "yystack.l_mark[%d].%s", i, tag);
2330 #if defined(YYBTYACC)
2331 else if (isalpha(c) || c == '_')
2333 char *arg = scan_id();
2334 for (i = plhs[nrules]->args - 1; i >= 0; i--)
2335 if (arg == plhs[nrules]->argnames[i])
2338 unknown_arg_warning(d_lineno, "$", arg, d_line, d_cptr);
2339 fprintf(f, "yystack.l_mark[%d].%s", i - plhs[nrules]->args +
2346 dollar_error(d_lineno, d_line, d_cptr);
2348 else if (cptr[1] == '$')
2352 tag = plhs[nrules]->tag;
2355 fprintf(f, "yyval.%s", tag);
2358 fprintf(f, "yyval");
2360 #if defined(YYBTYACC)
2365 else if (isdigit(UCH(cptr[1])))
2369 if (havetags && offsets)
2371 if (i <= 0 || i > maxoffset)
2373 tag = rhs[offsets[i]]->tag;
2375 untyped_rhs(i, rhs[offsets[i]]->name);
2376 fprintf(f, "yystack.l_mark[%d].%s", offsets[i], tag);
2381 fprintf(f, "yystack.l_mark[%d]", -n);
2382 else if (i > maxoffset)
2384 dollar_warning(lineno, i);
2385 fprintf(f, "yystack.l_mark[%d]", i - maxoffset);
2388 fprintf(f, "yystack.l_mark[%d]", offsets[i]);
2392 else if (cptr[1] == '-')
2398 fprintf(f, "yystack.l_mark[%d]", -i - n);
2401 #if defined(YYBTYACC)
2402 else if (isalpha(cptr[1]) || cptr[1] == '_')
2407 for (i = plhs[nrules]->args - 1; i >= 0; i--)
2408 if (arg == plhs[nrules]->argnames[i])
2411 unknown_arg_warning(lineno, "$", arg, line, cptr);
2412 tag = (i < 0 ? NULL : plhs[nrules]->argtags[i]);
2413 fprintf(f, "yystack.l_mark[%d]", i - plhs[nrules]->args + 1 - n);
2415 fprintf(f, ".%s", tag);
2417 untyped_arg_warning(lineno, "$", arg);
2422 #if defined(YYBTYACC)
2427 int l_lineno = lineno;
2428 char *l_line = dup_line();
2429 char *l_cptr = l_line + (cptr - line);
2430 syntax_error(l_lineno, l_line, l_cptr);
2434 fprintf(f, "yyloc");
2438 else if (isdigit(UCH(cptr[1])))
2443 fprintf(f, "yystack.p_mark[%d]", -n);
2444 else if (i > maxoffset)
2446 at_warning(lineno, i);
2447 fprintf(f, "yystack.p_mark[%d]", i - maxoffset);
2450 fprintf(f, "yystack.p_mark[%d]", offsets[i]);
2455 if (isalpha(c) || c == '_' || c == '$')
2462 while (isalnum(c) || c == '_' || c == '$');
2466 #if defined(YYBTYACC)
2469 if (trialaction && c == L_BRAC && depth == 0)
2475 if (trialaction && c == R_BRAC && depth == 1)
2480 if (c == L_BRAC && !haveyyval)
2484 if (c == L_CURL && !haveyyval)
2486 fprintf(f, " if (!yytrial)\n");
2488 fprintf(f, line_format, lineno, input_file_name);
2492 fprintf(f, "\nbreak;\n");
2507 unterminated_action(a_lineno, a_line, a_cptr);
2512 fprintf(f, "\nbreak;\n");
2518 #if defined(YYBTYACC)
2537 #if defined(YYBTYACC)
2541 if (c == L_BRAC && !haveyyval)
2546 if (c == L_CURL && !haveyyval)
2548 fprintf(f, " if (!yytrial)\n");
2550 fprintf(f, line_format, lineno, input_file_name);
2555 fprintf(f, "\nbreak;\n");
2564 char *s = copy_string(c);
2572 char *s = copy_comment();
2583 #if defined(YYBTYACC)
2585 copy_destructor(void)
2591 struct mstring *destructor_text = msnew();
2598 msprintf(destructor_text, line_format, lineno, input_file_name);
2600 cptr = after_blanks(cptr);
2601 if (*cptr == L_CURL)
2602 /* avoid putting curly-braces in first column, to ease editing */
2603 mputc(destructor_text, '\t');
2605 syntax_error(lineno, line, cptr);
2608 a_line = dup_line();
2609 a_cptr = a_line + (cptr - line);
2618 int d_lineno = lineno;
2619 char *d_line = dup_line();
2620 char *d_cptr = d_line + (cptr - line);
2627 msprintf(destructor_text, "(*val).%s", tag);
2633 dollar_error(d_lineno, d_line, d_cptr);
2635 else if (cptr[1] == '$')
2637 /* process '$$' later; replacement is context dependent */
2638 msprintf(destructor_text, "$$");
2643 if (c == '@' && cptr[1] == '$')
2647 int l_lineno = lineno;
2648 char *l_line = dup_line();
2649 char *l_cptr = l_line + (cptr - line);
2650 syntax_error(l_lineno, l_line, l_cptr);
2652 msprintf(destructor_text, "(*loc)");
2656 if (isalpha(c) || c == '_' || c == '$')
2660 mputc(destructor_text, c);
2663 while (isalnum(c) || c == '_' || c == '$');
2667 mputc(destructor_text, c);
2674 unterminated_action(a_lineno, a_line, a_cptr);
2683 goto process_symbols;
2688 char *s = copy_string(c);
2689 msprintf(destructor_text, "%s", s);
2696 char *s = copy_comment();
2697 msprintf(destructor_text, "%s", s);
2706 code_text = msdone(destructor_text);
2715 { /* "no semantic type" default destructor */
2717 if ((bp = default_destructor[UNTYPED_DEFAULT]) == NULL)
2719 static char untyped_default[] = "<>";
2720 bp = make_bucket("untyped default");
2721 bp->tag = untyped_default;
2722 default_destructor[UNTYPED_DEFAULT] = bp;
2724 if (bp->destructor != NULL)
2725 destructor_redeclared_warning(a_lineno, a_line, a_cptr);
2727 /* replace "$$" with "(*val)" in destructor code */
2728 bp->destructor = process_destructor_XX(code_text, NULL);
2730 else if (cptr[1] == '*' && cptr[2] == '>')
2731 { /* "no per-symbol or per-type" default destructor */
2733 if ((bp = default_destructor[TYPED_DEFAULT]) == NULL)
2735 static char typed_default[] = "<*>";
2736 bp = make_bucket("typed default");
2737 bp->tag = typed_default;
2738 default_destructor[TYPED_DEFAULT] = bp;
2740 if (bp->destructor != NULL)
2741 destructor_redeclared_warning(a_lineno, a_line, a_cptr);
2744 /* postpone re-processing destructor $$s until end of grammar spec */
2745 bp->destructor = TMALLOC(char, strlen(code_text) + 1);
2746 NO_SPACE(bp->destructor);
2747 strcpy(bp->destructor, code_text);
2751 { /* "semantic type" default destructor */
2753 bp = lookup_type_destructor(tag);
2754 if (bp->destructor != NULL)
2755 destructor_redeclared_warning(a_lineno, a_line, a_cptr);
2757 /* replace "$$" with "(*val).tag" in destructor code */
2758 bp->destructor = process_destructor_XX(code_text, tag);
2761 else if (isalpha(c) || c == '_' || c == '.' || c == '$')
2762 { /* "symbol" destructor */
2764 if (bp->destructor != NULL)
2765 destructor_redeclared_warning(a_lineno, a_line, a_cptr);
2768 /* postpone re-processing destructor $$s until end of grammar spec */
2769 bp->destructor = TMALLOC(char, strlen(code_text) + 1);
2770 NO_SPACE(bp->destructor);
2771 strcpy(bp->destructor, code_text);
2782 process_destructor_XX(char *code, char *tag)
2787 struct mstring *new_code = msnew();
2788 char *codeptr = code;
2791 loop: /* step thru code */
2793 if (c == '$' && codeptr[1] == '$')
2797 msprintf(new_code, "(*val)");
2799 msprintf(new_code, "(*val).%s", tag);
2802 if (isalpha(c) || c == '_' || c == '$')
2809 while (isalnum(c) || c == '_' || c == '$');
2823 return msdone(new_code);
2851 if (c == '*' && *codeptr == '/')
2853 mputc(new_code, '/');
2865 #endif /* defined(YYBTYACC) */
2874 if (c == '%' || c == '\\')
2882 else if ((c == 'p' || c == 'P') &&
2883 ((c = cptr[2]) == 'r' || c == 'R') &&
2884 ((c = cptr[3]) == 'e' || c == 'E') &&
2885 ((c = cptr[4]) == 'c' || c == 'C') &&
2886 ((c = cptr[5], !IS_IDENT(c))))
2889 syntax_error(lineno, line, cptr);
2892 if (isalpha(c) || c == '_' || c == '.' || c == '$')
2894 else if (c == '\'' || c == '"')
2898 syntax_error(lineno, line, cptr);
2901 if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules])
2904 rprec[nrules] = bp->prec;
2905 rassoc[nrules] = bp->assoc;
2914 initialize_grammar();
2929 #if defined(YYBTYACC)
2930 else if (c == L_CURL || c == '=' || (backtrack && c == L_BRAC))
2932 else if (c == L_CURL || c == '=')
2938 start_rule(plhs[nrules - 1], 0);
2947 syntax_error(lineno, line, cptr);
2950 #if defined(YYBTYACC)
2952 start_requires_args(goal->name);
2964 for (i = 0; i < ntags; ++i)
2966 assert(tag_table[i]);
2978 name_pool_size = 13; /* 13 == sizeof("$end") + sizeof("$accept") */
2979 for (bp = first_symbol; bp; bp = bp->next)
2980 name_pool_size += strlen(bp->name) + 1;
2982 name_pool = TMALLOC(char, name_pool_size);
2983 NO_SPACE(name_pool);
2985 strcpy(name_pool, "$accept");
2986 strcpy(name_pool + 8, "$end");
2988 for (bp = first_symbol; bp; bp = bp->next)
2992 while ((*t++ = *s++) != 0)
3004 if (goal->class == UNKNOWN)
3005 undefined_goal(goal->name);
3007 for (bp = first_symbol; bp; bp = bp->next)
3009 if (bp->class == UNKNOWN)
3011 undefined_symbol_warning(bp->name);
3018 protect_string(char *src, char **des)
3031 if ('\\' == *s || '"' == *s)
3037 *des = d = TMALLOC(char, len);
3043 if ('\\' == *s || '"' == *s)
3057 #if defined(YYBTYACC)
3058 Value_t max_tok_pval;
3063 for (bp = first_symbol; bp; bp = bp->next)
3066 if (bp->class == TERM)
3069 start_symbol = (Value_t) ntokens;
3070 nvars = (Value_t) (nsyms - ntokens);
3072 symbol_name = TMALLOC(char *, nsyms);
3073 NO_SPACE(symbol_name);
3075 symbol_value = TMALLOC(Value_t, nsyms);
3076 NO_SPACE(symbol_value);
3078 symbol_prec = TMALLOC(Value_t, nsyms);
3079 NO_SPACE(symbol_prec);
3081 symbol_assoc = TMALLOC(char, nsyms);
3082 NO_SPACE(symbol_assoc);
3084 #if defined(YYBTYACC)
3085 symbol_pval = TMALLOC(Value_t, nsyms);
3086 NO_SPACE(symbol_pval);
3090 symbol_destructor = CALLOC(sizeof(char *), nsyms);
3091 NO_SPACE(symbol_destructor);
3093 symbol_type_tag = CALLOC(sizeof(char *), nsyms);
3094 NO_SPACE(symbol_type_tag);
3098 v = TMALLOC(bucket *, nsyms);
3102 v[start_symbol] = 0;
3105 j = (Value_t) (start_symbol + 1);
3106 for (bp = first_symbol; bp; bp = bp->next)
3108 if (bp->class == TERM)
3113 assert(i == ntokens && j == nsyms);
3115 for (i = 1; i < ntokens; ++i)
3118 goal->index = (Index_t) (start_symbol + 1);
3119 k = (Value_t) (start_symbol + 2);
3129 for (i = (Value_t) (start_symbol + 1); i < nsyms; ++i)
3139 for (i = 1; i < ntokens; ++i)
3144 for (j = k++; j > 0 && symbol_value[j - 1] > n; --j)
3145 symbol_value[j] = symbol_value[j - 1];
3146 symbol_value[j] = n;
3152 if (v[1]->value == UNDEFINED)
3157 for (i = 2; i < ntokens; ++i)
3159 if (v[i]->value == UNDEFINED)
3161 while (j < k && n == symbol_value[j])
3163 while (++j < k && n == symbol_value[j])
3172 symbol_name[0] = name_pool + 8;
3173 symbol_value[0] = 0;
3175 symbol_assoc[0] = TOKEN;
3176 #if defined(YYBTYACC)
3180 for (i = 1; i < ntokens; ++i)
3182 symbol_name[i] = v[i]->name;
3183 symbol_value[i] = v[i]->value;
3184 symbol_prec[i] = v[i]->prec;
3185 symbol_assoc[i] = v[i]->assoc;
3186 #if defined(YYBTYACC)
3187 symbol_pval[i] = v[i]->value;
3188 if (symbol_pval[i] > max_tok_pval)
3189 max_tok_pval = symbol_pval[i];
3192 symbol_destructor[i] = v[i]->destructor;
3193 symbol_type_tag[i] = v[i]->tag;
3197 symbol_name[start_symbol] = name_pool;
3198 symbol_value[start_symbol] = -1;
3199 symbol_prec[start_symbol] = 0;
3200 symbol_assoc[start_symbol] = TOKEN;
3201 #if defined(YYBTYACC)
3202 symbol_pval[start_symbol] = (Value_t) (max_tok_pval + 1);
3204 for (++i; i < nsyms; ++i)
3207 symbol_name[k] = v[i]->name;
3208 symbol_value[k] = v[i]->value;
3209 symbol_prec[k] = v[i]->prec;
3210 symbol_assoc[k] = v[i]->assoc;
3211 #if defined(YYBTYACC)
3212 symbol_pval[k] = (Value_t) ((max_tok_pval + 1) + v[i]->value + 1);
3215 symbol_destructor[k] = v[i]->destructor;
3216 symbol_type_tag[k] = v[i]->tag;
3223 symbol_pname = TMALLOC(char *, nsyms);
3224 NO_SPACE(symbol_pname);
3226 for (i = 0; i < nsyms; ++i)
3227 protect_string(symbol_name[i], &(symbol_pname[i]));
3241 ritem = TMALLOC(Value_t, nitems);
3244 rlhs = TMALLOC(Value_t, nrules);
3247 rrhs = TMALLOC(Value_t, nrules + 1);
3250 rprec = TREALLOC(Value_t, rprec, nrules);
3253 rassoc = TREALLOC(Assoc_t, rassoc, nrules);
3257 ritem[1] = goal->index;
3262 rlhs[2] = start_symbol;
3268 for (i = 3; i < nrules; ++i)
3270 #if defined(YYBTYACC)
3271 if (plhs[i]->args > 0)
3273 if (plhs[i]->argnames)
3275 FREE(plhs[i]->argnames);
3276 plhs[i]->argnames = NULL;
3278 if (plhs[i]->argtags)
3280 FREE(plhs[i]->argtags);
3281 plhs[i]->argtags = NULL;
3284 #endif /* defined(YYBTYACC) */
3285 rlhs[i] = plhs[i]->index;
3291 ritem[j] = pitem[j]->index;
3292 if (pitem[j]->class == TERM)
3294 prec2 = pitem[j]->prec;
3295 assoc = pitem[j]->assoc;
3299 ritem[j] = (Value_t) - i;
3301 if (rprec[i] == UNDEFINED)
3311 #if defined(YYBTYACC)
3320 size_t j, spacing = 0;
3321 FILE *f = verbose_file;
3327 for (i = 2; i < nrules; ++i)
3329 if (rlhs[i] != rlhs[i - 1])
3333 fprintf(f, "%4d %s :", i - 2, symbol_name[rlhs[i]]);
3334 spacing = strlen(symbol_name[rlhs[i]]) + 1;
3338 fprintf(f, "%4d ", i - 2);
3345 while (ritem[k] >= 0)
3347 fprintf(f, " %s", symbol_name[ritem[k]]);
3355 #if defined(YYBTYACC)
3357 finalize_destructors(void)
3363 for (i = 2; i < nsyms; ++i)
3365 tag = symbol_type_tag[i];
3366 if (symbol_destructor[i] == NULL)
3369 { /* use <> destructor, if there is one */
3370 if ((bp = default_destructor[UNTYPED_DEFAULT]) != NULL)
3372 symbol_destructor[i] = TMALLOC(char,
3373 strlen(bp->destructor) + 1);
3374 NO_SPACE(symbol_destructor[i]);
3375 strcpy(symbol_destructor[i], bp->destructor);
3379 { /* use type destructor for this tag, if there is one */
3380 bp = lookup_type_destructor(tag);
3381 if (bp->destructor != NULL)
3383 symbol_destructor[i] = TMALLOC(char,
3384 strlen(bp->destructor) + 1);
3385 NO_SPACE(symbol_destructor[i]);
3386 strcpy(symbol_destructor[i], bp->destructor);
3389 { /* use <*> destructor, if there is one */
3390 if ((bp = default_destructor[TYPED_DEFAULT]) != NULL)
3391 /* replace "$$" with "(*val).tag" in destructor code */
3392 symbol_destructor[i]
3393 = process_destructor_XX(bp->destructor, tag);
3398 { /* replace "$$" with "(*val)[.tag]" in destructor code */
3399 symbol_destructor[i]
3400 = process_destructor_XX(symbol_destructor[i], tag);
3403 /* 'symbol_type_tag[]' elements are freed by 'free_tags()' */
3404 DO_FREE(symbol_type_tag); /* no longer needed */
3405 if ((bp = default_destructor[UNTYPED_DEFAULT]) != NULL)
3408 /* 'bp->tag' is a static value, don't free */
3409 FREE(bp->destructor);
3412 if ((bp = default_destructor[TYPED_DEFAULT]) != NULL)
3415 /* 'bp->tag' is a static value, don't free */
3416 FREE(bp->destructor);
3419 if ((bp = default_destructor[TYPE_SPECIFIED]) != NULL)
3426 /* 'bp->tag' freed by 'free_tags()' */
3427 FREE(bp->destructor);
3432 #endif /* defined(YYBTYACC) */
3437 write_section(code_file, banner);
3438 create_symbol_table();
3439 read_declarations();
3441 free_symbol_table();
3448 #if defined(YYBTYACC)
3450 finalize_destructors();
3457 free_declarations(param * list)
3461 param *next = list->next;
3474 lex_param = free_declarations(lex_param);
3475 parse_param = free_declarations(parse_param);
3485 DO_FREE(symbol_name);
3486 DO_FREE(symbol_prec);
3487 DO_FREE(symbol_assoc);
3488 DO_FREE(symbol_value);
3489 #if defined(YYBTYACC)
3490 DO_FREE(symbol_pval);
3491 DO_FREE(symbol_destructor);
3492 DO_FREE(symbol_type_tag);