1 /* $Id: reader.c,v 1.47 2014/04/09 21:09:27 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);
30 static int cinc, cache_size;
33 static int tagmax, havetags;
34 static char **tag_table;
44 static char last_was_action;
47 static bucket **pitem;
52 static size_t name_pool_size;
53 static char *name_pool;
55 char line_format[] = "#line %d \"%s\"\n";
61 int destructor = 0; /* =1 if at least one %destructor */
63 static bucket *default_destructor[3] =
66 #define UNTYPED_DEFAULT 0
67 #define TYPED_DEFAULT 1
68 #define TYPE_SPECIFIED 2
71 lookup_type_destructor(char *tag)
73 char name[1024] = "\0";
74 bucket *bp, **bpp = &default_destructor[TYPE_SPECIFIED];
76 while ((bp = *bpp) != NULL)
83 *bpp = bp = make_bucket(strcat(strcpy(name, tag), " destructor"));
88 #endif /* defined(YYBTYACC) */
94 if (cinc >= cache_size)
97 cache = TREALLOC(char, cache, cache_size);
100 cache[cinc] = (char)c;
107 FILE *f = input_file;
111 if (saw_eof || (c = getc(f)) == EOF)
123 if (line == 0 || linesize != (LINESIZE + 1))
127 linesize = LINESIZE + 1;
128 line = TCMALLOC(char, linesize);
141 linesize += LINESIZE;
142 line = TREALLOC(char, line, linesize);
167 p = TMALLOC(char, s - line + 1);
172 while ((*t++ = *s++) != '\n')
182 int st_lineno = lineno;
183 char *st_line = dup_line();
184 char *st_cptr = st_line + (cptr - line);
189 if (*s == '*' && s[1] == '/')
199 unterminated_comment(st_lineno, st_line, st_cptr);
253 else if (s[1] == '/')
270 static struct keyword
276 { "binary", NONASSOC },
277 #if defined(YYBTYACC)
278 { "destructor", DESTRUCTOR },
280 { "expect", EXPECT },
281 { "expect-rr", EXPECT_RR },
284 { "lex-param", LEX_PARAM },
285 #if defined(YYBTYACC)
286 { "locations", LOCATIONS },
288 { "nonassoc", NONASSOC },
289 { "parse-param", PARSE_PARAM },
290 { "pure-parser", PURE_PARSER },
295 { "token-table", TOKEN_TABLE },
298 { "yacc", POSIX_YACC },
303 compare_keys(const void *a, const void *b)
305 const struct keyword *p = (const struct keyword *)a;
306 const struct keyword *q = (const struct keyword *)b;
307 return strcmp(p->name, q->name);
338 /* treat keywords spelled with '_' as if it were '-' */
349 if ((key = bsearch(cache, keywords,
350 sizeof(keywords) / sizeof(*key),
351 sizeof(*key), compare_keys)))
359 if (c == '%' || c == '\\')
370 syntax_error(lineno, line, t_cptr);
378 FILE *f = output_file;
384 syntax_error(lineno, line, cptr);
386 fprintf(f, "#ident \"");
406 copy_string(int quote)
408 struct mstring *temp = msnew();
410 int s_lineno = lineno;
411 char *s_line = dup_line();
412 char *s_cptr = s_line + (cptr - line - 1);
424 unterminated_string(s_lineno, s_line, s_cptr);
433 unterminated_string(s_lineno, s_line, s_cptr);
442 struct mstring *temp = msnew();
449 while ((c = *++cptr) != '\n')
452 if (c == '*' && cptr[1] == '/')
460 int c_lineno = lineno;
461 char *c_line = dup_line();
462 char *c_cptr = c_line + (cptr - line - 1);
470 if (c == '*' && *cptr == '/')
481 unterminated_comment(c_lineno, c_line, c_cptr);
493 int need_newline = 0;
494 int t_lineno = lineno;
495 char *t_line = dup_line();
496 char *t_cptr = t_line + (cptr - line - 2);
502 unterminated_text(t_lineno, t_line, t_cptr);
505 fprintf(f, line_format, lineno, input_file_name);
517 unterminated_text(t_lineno, t_line, t_cptr);
523 char *s = copy_string(c);
533 char *s = copy_comment();
560 puts_both(const char *s)
564 fputs(s, union_file);
580 int u_lineno = lineno;
581 char *u_line = dup_line();
582 char *u_cptr = u_line + (cptr - line - 6);
585 over_unionized(cptr - 6);
589 fprintf(text_file, line_format, lineno, input_file_name);
591 puts_both("#ifdef YYSTYPE\n");
592 puts_both("#undef YYSTYPE_IS_DECLARED\n");
593 puts_both("#define YYSTYPE_IS_DECLARED 1\n");
594 puts_both("#endif\n");
595 puts_both("#ifndef YYSTYPE_IS_DECLARED\n");
596 puts_both("#define YYSTYPE_IS_DECLARED 1\n");
597 puts_both("typedef union");
608 unterminated_union(u_lineno, u_line, u_cptr);
618 puts_both(" YYSTYPE;\n");
619 puts_both("#endif /* !YYSTYPE_IS_DECLARED */\n");
628 char *s = copy_string(c);
636 char *s = copy_comment();
648 * Keep a linked list of parameters
672 buf = TMALLOC(char, linesize);
675 for (i = 0; (c = *cptr++) != R_CURL; i++)
688 while (i > 0 && isspace(UCH(buf[i])))
694 while (i >= 0 && level > 0 && buf[i] != '[')
698 else if (buf[i] == '[')
711 while (i > 0 && (isalnum(UCH(buf[i])) ||
715 if (!isspace(UCH(buf[i])) && buf[i] != '*')
720 p = TMALLOC(param, 1);
723 p->type2 = strdup(buf + type2);
728 p->name = strdup(buf + name);
756 syntax_error(lineno, line, cptr);
762 if (c >= '0' && c <= '9')
764 if (c >= 'A' && c <= 'F')
765 return (c - 'A' + 10);
766 if (c >= 'a' && c <= 'f')
767 return (c - 'a' + 10);
779 int s_lineno = lineno;
780 char *s_line = dup_line();
781 char *s_cptr = s_line + (cptr - line);
791 unterminated_string(s_lineno, s_line, s_cptr);
794 char *c_cptr = cptr - 1;
802 unterminated_string(s_lineno, s_line, s_cptr);
817 n = (n << 3) + (c - '0');
821 n = (n << 3) + (c - '0');
826 illegal_character(c_cptr);
833 if (n < 0 || n >= 16)
834 illegal_character(c_cptr);
839 if (i < 0 || i >= 16)
844 illegal_character(c_cptr);
877 s = TMALLOC(char, n);
880 for (i = 0; i < n; ++i)
889 for (i = 0; i < n; ++i)
892 if (c == '\\' || c == cache[0])
926 cachec(((c >> 6) & 7) + '0');
927 cachec(((c >> 3) & 7) + '0');
928 cachec((c & 7) + '0');
942 if (n == 1 && bp->value == UNDEFINED)
950 is_reserved(char *name)
954 if (strcmp(name, ".") == 0 ||
955 strcmp(name, "$accept") == 0 ||
956 strcmp(name, "$end") == 0)
959 if (name[0] == '$' && name[1] == '$' && isdigit(UCH(name[2])))
962 while (isdigit(UCH(*s)))
977 for (c = *cptr; IS_IDENT(c); c = *++cptr)
981 if (is_reserved(cache))
982 used_reserved(cache);
984 return (lookup(cache));
994 for (c = *cptr; isdigit(c); c = *++cptr)
995 n = (Value_t) (10 * n + (c - '0'));
1001 cache_tag(char *tag, size_t len)
1006 for (i = 0; i < ntags; ++i)
1008 if (strncmp(tag, tag_table[i], len) == 0 &&
1009 tag_table[i][len] == NUL)
1010 return (tag_table[i]);
1013 if (ntags >= tagmax)
1018 ? TREALLOC(char *, tag_table, tagmax)
1019 : TMALLOC(char *, tagmax));
1020 NO_SPACE(tag_table);
1023 s = TMALLOC(char, len + 1);
1026 strncpy(s, tag, len);
1028 tag_table[ntags++] = s;
1036 int t_lineno = lineno;
1037 char *t_line = dup_line();
1038 char *t_cptr = t_line + (cptr - line);
1044 if (!isalpha(c) && c != '_' && c != '$')
1045 illegal_tag(t_lineno, t_line, t_cptr);
1053 while (IS_IDENT(c));
1060 illegal_tag(t_lineno, t_line, t_cptr);
1065 return cache_tag(cache, (size_t) cinc);
1068 #if defined(YYBTYACC)
1074 while (isalnum(*cptr) || *cptr == '_' || *cptr == '$')
1076 return cache_tag(b, (size_t) (cptr - b));
1081 declare_tokens(int assoc)
1104 if (isalpha(c) || c == '_' || c == '.' || c == '$')
1106 else if (c == '\'' || c == '"')
1112 tokenized_start(bp->name);
1117 if (bp->tag && tag != bp->tag)
1118 retyped_warning(bp->name);
1124 if (bp->prec && prec != bp->prec)
1125 reprec_warning(bp->name);
1126 bp->assoc = (Assoc_t) assoc;
1136 value = get_number();
1137 if (bp->value != UNDEFINED && value != bp->value)
1138 revalued_warning(bp->name);
1148 * %expect requires special handling
1149 * as it really isn't part of the yacc
1150 * grammar only a flag for yacc proper.
1153 declare_expect(int assoc)
1157 if (assoc != EXPECT && assoc != EXPECT_RR)
1161 * Stay away from nextc - doesn't
1162 * detect EOL and will read to EOF.
1172 if (assoc == EXPECT)
1173 SRexpect = get_number();
1175 RRexpect = get_number();
1179 * Looking for number before EOL.
1180 * Spaces, tabs, and numbers are ok,
1181 * words, punc., etc. are syntax errors.
1183 else if (c == '\n' || isalpha(c) || !isspace(c))
1185 syntax_error(lineno, line, cptr);
1196 #if defined(YYBTYACC)
1198 declare_argtypes(bucket *bp)
1200 char *tags[MAXARGS];
1204 retyped_warning(bp->name);
1205 cptr++; /* skip open paren */
1212 syntax_error(lineno, line, cptr);
1213 tags[args++] = get_tag();
1220 cptr++; /* skip close paren */
1222 bp->argnames = TMALLOC(char *, args);
1223 NO_SPACE(bp->argnames);
1224 bp->argtags = CALLOC(sizeof(char *), args + 1);
1225 NO_SPACE(bp->argtags);
1228 bp->argtags[args] = tags[args];
1229 bp->argnames[args] = NULL;
1252 if (isalpha(c) || c == '_' || c == '.' || c == '$')
1255 #if defined(YYBTYACC)
1256 if (nextc() == L_PAREN)
1257 declare_argtypes(bp);
1262 else if (c == '\'' || c == '"')
1265 #if defined(YYBTYACC)
1274 if (bp->tag && tag != bp->tag)
1275 retyped_warning(bp->name);
1290 if (!isalpha(c) && c != '_' && c != '.' && c != '$')
1291 syntax_error(lineno, line, cptr);
1293 if (bp->class == TERM)
1294 terminal_start(bp->name);
1295 if (goal && goal != bp)
1296 restarted_warning();
1301 read_declarations(void)
1306 cache = TMALLOC(char, cache_size);
1315 syntax_error(lineno, line, cptr);
1316 switch (k = keyword())
1366 #if defined(YYBTYACC)
1378 /* noop for bison compatibility. byacc is already designed to be posix
1379 * yacc compatible. */
1386 initialize_grammar(void)
1391 pitem = TMALLOC(bucket *, maxitems);
1402 plhs = TMALLOC(bucket *, maxrules);
1409 rprec = TMALLOC(Value_t, maxrules);
1416 rassoc = TMALLOC(Assoc_t, maxrules);
1428 pitem = TREALLOC(bucket *, pitem, maxitems);
1437 plhs = TREALLOC(bucket *, plhs, maxrules);
1440 rprec = TREALLOC(Value_t, rprec, maxrules);
1443 rassoc = TREALLOC(Assoc_t, rassoc, maxrules);
1447 /* set immediately prior to where copy_args() could be called, and incremented by
1448 the various routines that will rescan the argument list as appropriate */
1449 static int rescan_lineno;
1450 #if defined(YYBTYACC)
1453 copy_args(int *alen)
1455 struct mstring *s = msnew();
1456 int depth = 0, len = 1;
1458 int a_lineno = lineno;
1459 char *a_line = dup_line();
1460 char *a_cptr = a_line + (cptr - line - 1);
1462 while ((c = *cptr++) != R_PAREN || depth || quote)
1464 if (c == ',' && !quote && !depth)
1477 unterminated_string(a_lineno, a_line, a_cptr);
1479 unterminated_arglist(a_lineno, a_line, a_cptr);
1496 else if (c == R_PAREN)
1498 else if (c == '\"' || c == '\'')
1509 parse_id(char *p, char **save)
1516 if (!isalpha(*p) && *p != '_')
1519 while (isalnum(*p) || *p == '_' || *p == '$')
1523 *save = cache_tag(b, (size_t) (p - b));
1529 parse_int(char *p, int *save)
1531 int neg = 0, val = 0;
1544 val = val * 10 + *p++ - '0';
1553 parse_arginfo(bucket *a, char *args, int argslen)
1555 char *p = args, *tmp;
1560 if (a->args != argslen)
1561 arg_number_disagree_warning(rescan_lineno, a->name);
1566 if ((a->args = argslen) == 0)
1568 a->argnames = TMALLOC(char *, argslen);
1569 NO_SPACE(a->argnames);
1570 a->argtags = TMALLOC(char *, argslen);
1571 NO_SPACE(a->argtags);
1575 for (i = 0; i < argslen; i++)
1588 if (!(p = parse_id(p + 1, &tmp)))
1597 if (a->argtags[i] != tmp)
1598 arg_type_disagree_warning(rescan_lineno, i + 1, a->name);
1601 a->argtags[i] = tmp;
1604 a->argtags[i] = NULL;
1605 if (!(p = parse_id(p, &a->argnames[i])))
1617 compile_arg(char **theptr, char *yyvaltag)
1620 struct mstring *c = msnew();
1622 Value_t *offsets = NULL, maxoffset;
1627 for (i = nitems - 1; pitem[i]; --i)
1630 if (pitem[i]->class != ARGUMENT)
1635 offsets = TMALLOC(Value_t, maxoffset + 1);
1638 for (j = 0, i++; i < nitems; i++)
1639 if (pitem[i]->class != ARGUMENT)
1640 offsets[++j] = (Value_t) (i - nitems + 1);
1641 rhs = pitem + nitems - 1;
1644 msprintf(c, "yyval.%s = ", yyvaltag);
1646 msprintf(c, "yyval = ");
1653 if (!(p = parse_id(++p, &tag)) || *p++ != '>')
1654 illegal_tag(rescan_lineno, NULL, NULL);
1655 if (isdigit(*p) || *p == '-')
1658 if (!(p = parse_int(p, &val)))
1659 dollar_error(rescan_lineno, NULL, NULL);
1662 else if (val > maxoffset)
1664 dollar_warning(rescan_lineno, val);
1665 i = val - maxoffset;
1670 if (!tag && !(tag = rhs[i]->tag) && havetags)
1671 untyped_rhs(val, rhs[i]->name);
1673 msprintf(c, "yystack.l_mark[%d]", i);
1675 msprintf(c, ".%s", tag);
1679 else if (isalpha(*p) || *p == '_')
1682 if (!(p = parse_id(p, &arg)))
1683 dollar_error(rescan_lineno, NULL, NULL);
1684 for (i = plhs[nrules]->args - 1; i >= 0; i--)
1685 if (arg == plhs[nrules]->argnames[i])
1688 unknown_arg_warning(rescan_lineno, "$", arg, NULL, NULL);
1690 tag = plhs[nrules]->argtags[i];
1691 msprintf(c, "yystack.l_mark[%d]", i - plhs[nrules]->args + 1
1694 msprintf(c, ".%s", tag);
1696 untyped_arg_warning(rescan_lineno, "$", arg);
1699 dollar_error(rescan_lineno, NULL, NULL);
1703 at_error(rescan_lineno, NULL, NULL);
1718 #define ARG_CACHE_SIZE 1024
1719 static struct arg_cache
1721 struct arg_cache *next;
1725 *arg_cache[ARG_CACHE_SIZE];
1728 lookup_arg_cache(char *code)
1730 struct arg_cache *entry;
1732 entry = arg_cache[strnshash(code) % ARG_CACHE_SIZE];
1735 if (!strnscmp(entry->code, code))
1737 entry = entry->next;
1743 insert_arg_cache(char *code, int rule)
1745 struct arg_cache *entry = NEW(struct arg_cache);
1749 i = strnshash(code) % ARG_CACHE_SIZE;
1752 entry->next = arg_cache[i];
1753 arg_cache[i] = entry;
1757 clean_arg_cache(void)
1759 struct arg_cache *e, *t;
1762 for (i = 0; i < ARG_CACHE_SIZE; i++)
1764 for (e = arg_cache[i]; (t = e); e = e->next, FREE(t))
1766 arg_cache[i] = NULL;
1772 advance_to_start(void)
1778 #if defined(YYBTYACC)
1803 syntax_error(lineno, line, s_cptr);
1808 if (!isalpha(c) && c != '_' && c != '.' && c != '_')
1809 syntax_error(lineno, line, cptr);
1813 if (bp->class == TERM)
1814 terminal_start(bp->name);
1822 rescan_lineno = lineno; /* line# for possible inherited args rescan */
1823 #if defined(YYBTYACC)
1827 args = copy_args(&argslen);
1833 syntax_error(lineno, line, cptr);
1834 start_rule(bp, s_lineno);
1835 #if defined(YYBTYACC)
1836 parse_arginfo(bp, args, argslen);
1842 start_rule(bucket *bp, int s_lineno)
1844 if (bp->class == TERM)
1845 terminal_lhs(s_lineno);
1846 bp->class = NONTERM;
1849 if (nrules >= maxrules)
1852 rprec[nrules] = UNDEFINED;
1853 rassoc[nrules] = TOKEN;
1861 if (!last_was_action && plhs[nrules]->tag)
1863 if (pitem[nitems - 1])
1865 for (i = nitems - 1; (i > 0) && pitem[i]; --i)
1867 if (pitem[i + 1] == 0 || pitem[i + 1]->tag != plhs[nrules]->tag)
1868 default_action_warning();
1872 default_action_warning();
1876 last_was_action = 0;
1877 if (nitems >= maxitems)
1885 insert_empty_rule(void)
1890 sprintf(cache, "$$%d", ++gensym);
1891 bp = make_bucket(cache);
1892 last_symbol->next = bp;
1894 bp->tag = plhs[nrules]->tag;
1896 #if defined(YYBTYACC)
1900 nitems = (Value_t) (nitems + 2);
1901 if (nitems > maxitems)
1903 bpp = pitem + nitems - 1;
1905 while ((bpp[0] = bpp[-1]) != 0)
1908 if (++nrules >= maxrules)
1910 plhs[nrules] = plhs[nrules - 1];
1911 plhs[nrules - 1] = bp;
1912 rprec[nrules] = rprec[nrules - 1];
1913 rprec[nrules - 1] = 0;
1914 rassoc[nrules] = rassoc[nrules - 1];
1915 rassoc[nrules - 1] = TOKEN;
1918 #if defined(YYBTYACC)
1920 insert_arg_rule(char *arg, char *tag)
1922 int line_number = rescan_lineno;
1923 char *code = compile_arg(&arg, tag);
1924 int rule = lookup_arg_cache(code);
1925 FILE *f = action_file;
1930 insert_arg_cache(code, rule);
1931 fprintf(f, "case %d:\n", rule - 2);
1933 fprintf(f, line_format, line_number, input_file_name);
1934 fprintf(f, "%s;\n", code);
1935 fprintf(f, "break;\n");
1936 insert_empty_rule();
1937 plhs[rule]->tag = tag;
1938 plhs[rule]->class = ARGUMENT;
1942 if (++nitems > maxitems)
1944 pitem[nitems - 1] = plhs[rule];
1956 int s_lineno = lineno;
1957 #if defined(YYBTYACC)
1963 if (c == '\'' || c == '"')
1969 rescan_lineno = lineno; /* line# for possible inherited args rescan */
1970 #if defined(YYBTYACC)
1974 args = copy_args(&argslen);
1982 start_rule(bp, s_lineno);
1983 #if defined(YYBTYACC)
1984 parse_arginfo(bp, args, argslen);
1990 if (last_was_action)
1991 insert_empty_rule();
1992 last_was_action = 0;
1994 #if defined(YYBTYACC)
1997 if (argslen == 0 && bp->args > 0 && pitem[nitems - 1] == NULL)
2000 if (plhs[nrules]->args != bp->args)
2001 wrong_number_args_warning("default ", bp->name);
2002 for (i = bp->args - 1; i >= 0; i--)
2003 if (plhs[nrules]->argtags[i] != bp->argtags[i])
2004 wrong_type_for_arg_warning(i + 1, bp->name);
2006 else if (bp->args != argslen)
2007 wrong_number_args_warning("", bp->name);
2008 if (bp->args > 0 && argslen > 0)
2012 for (ap = args, i = 0; i < argslen; i++)
2013 ap = insert_arg_rule(ap, bp->argtags[i]);
2016 #endif /* defined(YYBTYACC) */
2018 if (++nitems > maxitems)
2020 pitem[nitems - 1] = bp;
2024 after_blanks(char *s)
2026 while (*s != '\0' && isspace(UCH(*s)))
2037 #if defined(YYBTYACC)
2038 int trialaction = 0;
2042 FILE *f = action_file;
2043 int a_lineno = lineno;
2044 char *a_line = dup_line();
2045 char *a_cptr = a_line + (cptr - line);
2046 Value_t *offsets = NULL, maxoffset;
2049 if (last_was_action)
2050 insert_empty_rule();
2051 last_was_action = 1;
2053 fprintf(f, "case %d:\n", nrules - 2);
2054 #if defined(YYBTYACC)
2057 if (*cptr != L_BRAC)
2058 fprintf(f, " if (!yytrial)\n");
2064 fprintf(f, line_format, lineno, input_file_name);
2068 /* avoid putting curly-braces in first column, to ease editing */
2069 if (*after_blanks(cptr) == L_CURL)
2072 cptr = after_blanks(cptr);
2077 for (i = nitems - 1; pitem[i]; --i)
2080 if (pitem[i]->class != ARGUMENT)
2085 offsets = TMALLOC(Value_t, maxoffset + 1);
2088 for (j = 0, i++; i < nitems; i++)
2090 if (pitem[i]->class != ARGUMENT)
2092 offsets[++j] = (Value_t) (i - nitems + 1);
2095 rhs = pitem + nitems - 1;
2104 int d_lineno = lineno;
2105 char *d_line = dup_line();
2106 char *d_cptr = d_line + (cptr - line);
2113 fprintf(f, "yyval.%s", tag);
2118 else if (isdigit(c))
2122 fprintf(f, "yystack.l_mark[%d].%s", -n, tag);
2123 else if (i > maxoffset)
2125 dollar_warning(d_lineno, i);
2126 fprintf(f, "yystack.l_mark[%d].%s", i - maxoffset, tag);
2129 fprintf(f, "yystack.l_mark[%d].%s", offsets[i], tag);
2133 else if (c == '-' && isdigit(UCH(cptr[1])))
2136 i = -get_number() - n;
2137 fprintf(f, "yystack.l_mark[%d].%s", i, tag);
2141 #if defined(YYBTYACC)
2142 else if (isalpha(c) || c == '_')
2144 char *arg = scan_id();
2145 for (i = plhs[nrules]->args - 1; i >= 0; i--)
2146 if (arg == plhs[nrules]->argnames[i])
2149 unknown_arg_warning(d_lineno, "$", arg, d_line, d_cptr);
2150 fprintf(f, "yystack.l_mark[%d].%s", i - plhs[nrules]->args +
2157 dollar_error(d_lineno, d_line, d_cptr);
2159 else if (cptr[1] == '$')
2163 tag = plhs[nrules]->tag;
2166 fprintf(f, "yyval.%s", tag);
2169 fprintf(f, "yyval");
2171 #if defined(YYBTYACC)
2176 else if (isdigit(UCH(cptr[1])))
2182 if (i <= 0 || i > maxoffset)
2184 tag = rhs[offsets[i]]->tag;
2186 untyped_rhs(i, rhs[offsets[i]]->name);
2187 fprintf(f, "yystack.l_mark[%d].%s", offsets[i], tag);
2192 fprintf(f, "yystack.l_mark[%d]", -n);
2193 else if (i > maxoffset)
2195 dollar_warning(lineno, i);
2196 fprintf(f, "yystack.l_mark[%d]", i - maxoffset);
2199 fprintf(f, "yystack.l_mark[%d]", offsets[i]);
2203 else if (cptr[1] == '-')
2209 fprintf(f, "yystack.l_mark[%d]", -i - n);
2212 #if defined(YYBTYACC)
2213 else if (isalpha(cptr[1]) || cptr[1] == '_')
2218 for (i = plhs[nrules]->args - 1; i >= 0; i--)
2219 if (arg == plhs[nrules]->argnames[i])
2222 unknown_arg_warning(lineno, "$", arg, line, cptr);
2223 tag = (i < 0 ? NULL : plhs[nrules]->argtags[i]);
2224 fprintf(f, "yystack.l_mark[%d]", i - plhs[nrules]->args + 1 - n);
2226 fprintf(f, ".%s", tag);
2228 untyped_arg_warning(lineno, "$", arg);
2233 #if defined(YYBTYACC)
2238 int l_lineno = lineno;
2239 char *l_line = dup_line();
2240 char *l_cptr = l_line + (cptr - line);
2241 syntax_error(l_lineno, l_line, l_cptr);
2245 fprintf(f, "yyloc");
2249 else if (isdigit(UCH(cptr[1])))
2254 fprintf(f, "yystack.p_mark[%d]", -n);
2255 else if (i > maxoffset)
2257 at_warning(lineno, i);
2258 fprintf(f, "yystack.p_mark[%d]", i - maxoffset);
2261 fprintf(f, "yystack.p_mark[%d]", offsets[i]);
2266 if (isalpha(c) || c == '_' || c == '$')
2273 while (isalnum(c) || c == '_' || c == '$');
2277 #if defined(YYBTYACC)
2280 if (trialaction && c == L_BRAC && depth == 0)
2286 if (trialaction && c == R_BRAC && depth == 1)
2291 if (c == L_BRAC && !haveyyval)
2295 if (c == L_CURL && !haveyyval)
2297 fprintf(f, " if (!yytrial)\n");
2299 fprintf(f, line_format, lineno, input_file_name);
2303 fprintf(f, "\nbreak;\n");
2318 unterminated_action(a_lineno, a_line, a_cptr);
2323 fprintf(f, "\nbreak;\n");
2329 #if defined(YYBTYACC)
2348 #if defined(YYBTYACC)
2352 if (c == L_BRAC && !haveyyval)
2357 if (c == L_CURL && !haveyyval)
2359 fprintf(f, " if (!yytrial)\n");
2361 fprintf(f, line_format, lineno, input_file_name);
2366 fprintf(f, "\nbreak;\n");
2375 char *s = copy_string(c);
2383 char *s = copy_comment();
2394 #if defined(YYBTYACC)
2396 copy_destructor(void)
2402 struct mstring *destructor_text = msnew();
2409 msprintf(destructor_text, line_format, lineno, input_file_name);
2411 cptr = after_blanks(cptr);
2412 if (*cptr == L_CURL)
2413 /* avoid putting curly-braces in first column, to ease editing */
2414 mputc(destructor_text, '\t');
2416 syntax_error(lineno, line, cptr);
2419 a_line = dup_line();
2420 a_cptr = a_line + (cptr - line);
2429 int d_lineno = lineno;
2430 char *d_line = dup_line();
2431 char *d_cptr = d_line + (cptr - line);
2438 msprintf(destructor_text, "(*val).%s", tag);
2444 dollar_error(d_lineno, d_line, d_cptr);
2446 else if (cptr[1] == '$')
2448 /* process '$$' later; replacement is context dependent */
2449 msprintf(destructor_text, "$$");
2454 if (c == '@' && cptr[1] == '$')
2458 int l_lineno = lineno;
2459 char *l_line = dup_line();
2460 char *l_cptr = l_line + (cptr - line);
2461 syntax_error(l_lineno, l_line, l_cptr);
2463 msprintf(destructor_text, "(*loc)");
2467 if (isalpha(c) || c == '_' || c == '$')
2471 mputc(destructor_text, c);
2474 while (isalnum(c) || c == '_' || c == '$');
2478 mputc(destructor_text, c);
2485 unterminated_action(a_lineno, a_line, a_cptr);
2494 goto process_symbols;
2499 char *s = copy_string(c);
2500 msprintf(destructor_text, "%s", s);
2507 char *s = copy_comment();
2508 msprintf(destructor_text, "%s", s);
2517 code_text = msdone(destructor_text);
2526 { /* "no semantic type" default destructor */
2528 if ((bp = default_destructor[UNTYPED_DEFAULT]) == NULL)
2530 static char untyped_default[] = "<>";
2531 bp = make_bucket("untyped default");
2532 bp->tag = untyped_default;
2533 default_destructor[UNTYPED_DEFAULT] = bp;
2535 if (bp->destructor != NULL)
2536 destructor_redeclared_warning(a_lineno, a_line, a_cptr);
2538 /* replace "$$" with "(*val)" in destructor code */
2539 bp->destructor = process_destructor_XX(code_text, NULL);
2541 else if (cptr[1] == '*' && cptr[2] == '>')
2542 { /* "no per-symbol or per-type" default destructor */
2544 if ((bp = default_destructor[TYPED_DEFAULT]) == NULL)
2546 static char typed_default[] = "<*>";
2547 bp = make_bucket("typed default");
2548 bp->tag = typed_default;
2549 default_destructor[TYPED_DEFAULT] = bp;
2551 if (bp->destructor != NULL)
2552 destructor_redeclared_warning(a_lineno, a_line, a_cptr);
2555 /* postpone re-processing destructor $$s until end of grammar spec */
2556 bp->destructor = TMALLOC(char, strlen(code_text) + 1);
2557 NO_SPACE(bp->destructor);
2558 strcpy(bp->destructor, code_text);
2562 { /* "semantic type" default destructor */
2564 bp = lookup_type_destructor(tag);
2565 if (bp->destructor != NULL)
2566 destructor_redeclared_warning(a_lineno, a_line, a_cptr);
2568 /* replace "$$" with "(*val).tag" in destructor code */
2569 bp->destructor = process_destructor_XX(code_text, tag);
2572 else if (isalpha(c) || c == '_' || c == '.' || c == '$')
2573 { /* "symbol" destructor */
2575 if (bp->destructor != NULL)
2576 destructor_redeclared_warning(a_lineno, a_line, a_cptr);
2579 /* postpone re-processing destructor $$s until end of grammar spec */
2580 bp->destructor = TMALLOC(char, strlen(code_text) + 1);
2581 NO_SPACE(bp->destructor);
2582 strcpy(bp->destructor, code_text);
2593 process_destructor_XX(char *code, char *tag)
2598 struct mstring *new_code = msnew();
2599 char *codeptr = code;
2602 loop: /* step thru code */
2604 if (c == '$' && codeptr[1] == '$')
2608 msprintf(new_code, "(*val)");
2610 msprintf(new_code, "(*val).%s", tag);
2613 if (isalpha(c) || c == '_' || c == '$')
2620 while (isalnum(c) || c == '_' || c == '$');
2634 return msdone(new_code);
2662 if (c == '*' && *codeptr == '/')
2664 mputc(new_code, '/');
2676 #endif /* defined(YYBTYACC) */
2685 if (c == '%' || c == '\\')
2693 else if ((c == 'p' || c == 'P') &&
2694 ((c = cptr[2]) == 'r' || c == 'R') &&
2695 ((c = cptr[3]) == 'e' || c == 'E') &&
2696 ((c = cptr[4]) == 'c' || c == 'C') &&
2697 ((c = cptr[5], !IS_IDENT(c))))
2700 syntax_error(lineno, line, cptr);
2703 if (isalpha(c) || c == '_' || c == '.' || c == '$')
2705 else if (c == '\'' || c == '"')
2709 syntax_error(lineno, line, cptr);
2712 if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules])
2715 rprec[nrules] = bp->prec;
2716 rassoc[nrules] = bp->assoc;
2725 initialize_grammar();
2740 #if defined(YYBTYACC)
2741 else if (c == L_CURL || c == '=' || (backtrack && c == L_BRAC))
2743 else if (c == L_CURL || c == '=')
2749 start_rule(plhs[nrules - 1], 0);
2758 syntax_error(lineno, line, cptr);
2761 #if defined(YYBTYACC)
2763 start_requires_args(goal->name);
2775 for (i = 0; i < ntags; ++i)
2777 assert(tag_table[i]);
2789 name_pool_size = 13; /* 13 == sizeof("$end") + sizeof("$accept") */
2790 for (bp = first_symbol; bp; bp = bp->next)
2791 name_pool_size += strlen(bp->name) + 1;
2793 name_pool = TMALLOC(char, name_pool_size);
2794 NO_SPACE(name_pool);
2796 strcpy(name_pool, "$accept");
2797 strcpy(name_pool + 8, "$end");
2799 for (bp = first_symbol; bp; bp = bp->next)
2803 while ((*t++ = *s++) != 0)
2815 if (goal->class == UNKNOWN)
2816 undefined_goal(goal->name);
2818 for (bp = first_symbol; bp; bp = bp->next)
2820 if (bp->class == UNKNOWN)
2822 undefined_symbol_warning(bp->name);
2829 protect_string(char *src, char **des)
2842 if ('\\' == *s || '"' == *s)
2848 *des = d = TMALLOC(char, len);
2854 if ('\\' == *s || '"' == *s)
2868 #if defined(YYBTYACC)
2869 Value_t max_tok_pval;
2874 for (bp = first_symbol; bp; bp = bp->next)
2877 if (bp->class == TERM)
2880 start_symbol = (Value_t) ntokens;
2881 nvars = (Value_t) (nsyms - ntokens);
2883 symbol_name = TMALLOC(char *, nsyms);
2884 NO_SPACE(symbol_name);
2886 symbol_value = TMALLOC(Value_t, nsyms);
2887 NO_SPACE(symbol_value);
2889 symbol_prec = TMALLOC(Value_t, nsyms);
2890 NO_SPACE(symbol_prec);
2892 symbol_assoc = TMALLOC(char, nsyms);
2893 NO_SPACE(symbol_assoc);
2895 #if defined(YYBTYACC)
2896 symbol_pval = TMALLOC(Value_t, nsyms);
2897 NO_SPACE(symbol_pval);
2901 symbol_destructor = CALLOC(sizeof(char *), nsyms);
2902 NO_SPACE(symbol_destructor);
2904 symbol_type_tag = CALLOC(sizeof(char *), nsyms);
2905 NO_SPACE(symbol_type_tag);
2909 v = TMALLOC(bucket *, nsyms);
2913 v[start_symbol] = 0;
2916 j = (Value_t) (start_symbol + 1);
2917 for (bp = first_symbol; bp; bp = bp->next)
2919 if (bp->class == TERM)
2924 assert(i == ntokens && j == nsyms);
2926 for (i = 1; i < ntokens; ++i)
2929 goal->index = (Index_t) (start_symbol + 1);
2930 k = (Value_t) (start_symbol + 2);
2940 for (i = (Value_t) (start_symbol + 1); i < nsyms; ++i)
2950 for (i = 1; i < ntokens; ++i)
2955 for (j = k++; j > 0 && symbol_value[j - 1] > n; --j)
2956 symbol_value[j] = symbol_value[j - 1];
2957 symbol_value[j] = n;
2963 if (v[1]->value == UNDEFINED)
2968 for (i = 2; i < ntokens; ++i)
2970 if (v[i]->value == UNDEFINED)
2972 while (j < k && n == symbol_value[j])
2974 while (++j < k && n == symbol_value[j])
2983 symbol_name[0] = name_pool + 8;
2984 symbol_value[0] = 0;
2986 symbol_assoc[0] = TOKEN;
2987 #if defined(YYBTYACC)
2991 for (i = 1; i < ntokens; ++i)
2993 symbol_name[i] = v[i]->name;
2994 symbol_value[i] = v[i]->value;
2995 symbol_prec[i] = v[i]->prec;
2996 symbol_assoc[i] = v[i]->assoc;
2997 #if defined(YYBTYACC)
2998 symbol_pval[i] = v[i]->value;
2999 if (symbol_pval[i] > max_tok_pval)
3000 max_tok_pval = symbol_pval[i];
3003 symbol_destructor[i] = v[i]->destructor;
3004 symbol_type_tag[i] = v[i]->tag;
3008 symbol_name[start_symbol] = name_pool;
3009 symbol_value[start_symbol] = -1;
3010 symbol_prec[start_symbol] = 0;
3011 symbol_assoc[start_symbol] = TOKEN;
3012 #if defined(YYBTYACC)
3013 symbol_pval[start_symbol] = (Value_t) (max_tok_pval + 1);
3015 for (++i; i < nsyms; ++i)
3018 symbol_name[k] = v[i]->name;
3019 symbol_value[k] = v[i]->value;
3020 symbol_prec[k] = v[i]->prec;
3021 symbol_assoc[k] = v[i]->assoc;
3022 #if defined(YYBTYACC)
3023 symbol_pval[k] = (Value_t) ((max_tok_pval + 1) + v[i]->value + 1);
3026 symbol_destructor[k] = v[i]->destructor;
3027 symbol_type_tag[k] = v[i]->tag;
3034 symbol_pname = TMALLOC(char *, nsyms);
3035 NO_SPACE(symbol_pname);
3037 for (i = 0; i < nsyms; ++i)
3038 protect_string(symbol_name[i], &(symbol_pname[i]));
3052 ritem = TMALLOC(Value_t, nitems);
3055 rlhs = TMALLOC(Value_t, nrules);
3058 rrhs = TMALLOC(Value_t, nrules + 1);
3061 rprec = TREALLOC(Value_t, rprec, nrules);
3064 rassoc = TREALLOC(Assoc_t, rassoc, nrules);
3068 ritem[1] = goal->index;
3073 rlhs[2] = start_symbol;
3079 for (i = 3; i < nrules; ++i)
3081 #if defined(YYBTYACC)
3082 if (plhs[i]->args > 0)
3084 if (plhs[i]->argnames)
3086 FREE(plhs[i]->argnames);
3087 plhs[i]->argnames = NULL;
3089 if (plhs[i]->argtags)
3091 FREE(plhs[i]->argtags);
3092 plhs[i]->argtags = NULL;
3095 #endif /* defined(YYBTYACC) */
3096 rlhs[i] = plhs[i]->index;
3102 ritem[j] = pitem[j]->index;
3103 if (pitem[j]->class == TERM)
3105 prec2 = pitem[j]->prec;
3106 assoc = pitem[j]->assoc;
3110 ritem[j] = (Value_t) - i;
3112 if (rprec[i] == UNDEFINED)
3122 #if defined(YYBTYACC)
3131 size_t j, spacing = 0;
3132 FILE *f = verbose_file;
3138 for (i = 2; i < nrules; ++i)
3140 if (rlhs[i] != rlhs[i - 1])
3144 fprintf(f, "%4d %s :", i - 2, symbol_name[rlhs[i]]);
3145 spacing = strlen(symbol_name[rlhs[i]]) + 1;
3149 fprintf(f, "%4d ", i - 2);
3156 while (ritem[k] >= 0)
3158 fprintf(f, " %s", symbol_name[ritem[k]]);
3166 #if defined(YYBTYACC)
3168 finalize_destructors(void)
3174 for (i = 2; i < nsyms; ++i)
3176 tag = symbol_type_tag[i];
3177 if (symbol_destructor[i] == NULL)
3180 { /* use <> destructor, if there is one */
3181 if ((bp = default_destructor[UNTYPED_DEFAULT]) != NULL)
3183 symbol_destructor[i] = TMALLOC(char,
3184 strlen(bp->destructor) + 1);
3185 NO_SPACE(symbol_destructor[i]);
3186 strcpy(symbol_destructor[i], bp->destructor);
3190 { /* use type destructor for this tag, if there is one */
3191 bp = lookup_type_destructor(tag);
3192 if (bp->destructor != NULL)
3194 symbol_destructor[i] = TMALLOC(char,
3195 strlen(bp->destructor) + 1);
3196 NO_SPACE(symbol_destructor[i]);
3197 strcpy(symbol_destructor[i], bp->destructor);
3200 { /* use <*> destructor, if there is one */
3201 if ((bp = default_destructor[TYPED_DEFAULT]) != NULL)
3202 /* replace "$$" with "(*val).tag" in destructor code */
3203 symbol_destructor[i]
3204 = process_destructor_XX(bp->destructor, tag);
3209 { /* replace "$$" with "(*val)[.tag]" in destructor code */
3210 symbol_destructor[i]
3211 = process_destructor_XX(symbol_destructor[i], tag);
3214 /* 'symbol_type_tag[]' elements are freed by 'free_tags()' */
3215 DO_FREE(symbol_type_tag); /* no longer needed */
3216 if ((bp = default_destructor[UNTYPED_DEFAULT]) != NULL)
3219 /* 'bp->tag' is a static value, don't free */
3220 FREE(bp->destructor);
3223 if ((bp = default_destructor[TYPED_DEFAULT]) != NULL)
3226 /* 'bp->tag' is a static value, don't free */
3227 FREE(bp->destructor);
3230 if ((bp = default_destructor[TYPE_SPECIFIED]) != NULL)
3237 /* 'bp->tag' freed by 'free_tags()' */
3238 FREE(bp->destructor);
3243 #endif /* defined(YYBTYACC) */
3248 write_section(code_file, banner);
3249 create_symbol_table();
3250 read_declarations();
3252 free_symbol_table();
3259 #if defined(YYBTYACC)
3261 finalize_destructors();
3268 free_declarations(param * list)
3272 param *next = list->next;
3285 lex_param = free_declarations(lex_param);
3286 parse_param = free_declarations(parse_param);
3296 DO_FREE(symbol_name);
3297 DO_FREE(symbol_prec);
3298 DO_FREE(symbol_assoc);
3299 DO_FREE(symbol_value);
3300 #if defined(YYBTYACC)
3301 DO_FREE(symbol_pval);
3302 DO_FREE(symbol_destructor);
3303 DO_FREE(symbol_type_tag);