1 /* $Id: reader.c,v 1.66 2016/12/02 20:14:34 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_initial_action(void);
26 static void copy_destructor(void);
27 static char *process_destructor_XX(char *code, char *tag);
30 #define CACHE_SIZE 256
32 static int cinc, cache_size;
35 static int tagmax, havetags;
36 static char **tag_table;
46 static char last_was_action;
48 static int trialaction;
52 static bucket **pitem;
57 static size_t name_pool_size;
58 static char *name_pool;
60 char line_format[] = "#line %d \"%s\"\n";
66 int destructor = 0; /* =1 if at least one %destructor */
68 static bucket *default_destructor[3] =
71 #define UNTYPED_DEFAULT 0
72 #define TYPED_DEFAULT 1
73 #define TYPE_SPECIFIED 2
76 lookup_type_destructor(char *tag)
78 const char fmt[] = "%.*s destructor";
79 char name[1024] = "\0";
80 bucket *bp, **bpp = &default_destructor[TYPE_SPECIFIED];
82 while ((bp = *bpp) != NULL)
89 sprintf(name, fmt, (int)(sizeof(name) - sizeof(fmt)), tag);
90 *bpp = bp = make_bucket(name);
95 #endif /* defined(YYBTYACC) */
101 if (cinc >= cache_size)
103 cache_size += CACHE_SIZE;
104 cache = TREALLOC(char, cache, cache_size);
107 cache[cinc] = (char)c;
114 FILE *f = input_file;
118 if (saw_eof || (c = getc(f)) == EOF)
130 if (line == NULL || linesize != (LINESIZE + 1))
134 linesize = LINESIZE + 1;
135 line = TMALLOC(char, linesize);
146 if ((i + 3) >= linesize)
148 linesize += LINESIZE;
149 line = TREALLOC(char, line, linesize);
175 p = TMALLOC(char, s - line + 1);
180 while ((*t++ = *s++) != '\n')
191 a.a_line = dup_line();
192 a.a_cptr = a.a_line + (cptr - line);
197 if (*s == '*' && s[1] == '/')
207 unterminated_comment(&a);
240 else if (s[1] == '/')
265 switch (ch = next_inline())
292 static struct keyword
298 { "binary", NONASSOC },
299 { "debug", XXXDEBUG },
300 #if defined(YYBTYACC)
301 { "destructor", DESTRUCTOR },
303 { "error-verbose",ERROR_VERBOSE },
304 { "expect", EXPECT },
305 { "expect-rr", EXPECT_RR },
307 #if defined(YYBTYACC)
308 { "initial-action", INITIAL_ACTION },
311 { "lex-param", LEX_PARAM },
312 #if defined(YYBTYACC)
313 { "locations", LOCATIONS },
315 { "nonassoc", NONASSOC },
316 { "parse-param", PARSE_PARAM },
317 { "pure-parser", PURE_PARSER },
322 { "token-table", TOKEN_TABLE },
325 { "yacc", POSIX_YACC },
330 compare_keys(const void *a, const void *b)
332 const struct keyword *p = (const struct keyword *)a;
333 const struct keyword *q = (const struct keyword *)b;
334 return strcmp(p->name, q->name);
365 /* treat keywords spelled with '_' as if it were '-' */
376 if ((key = bsearch(cache, keywords,
377 sizeof(keywords) / sizeof(*key),
378 sizeof(*key), compare_keys)))
386 if (c == '%' || c == '\\')
397 syntax_error(lineno, line, t_cptr);
405 FILE *f = output_file;
411 syntax_error(lineno, line, cptr);
413 fprintf(f, "#ident \"");
433 copy_string(int quote)
435 struct mstring *temp = msnew();
439 a.a_line = dup_line();
440 a.a_cptr = a.a_line + (cptr - line - 1);
452 unterminated_string(&a);
461 unterminated_string(&a);
470 struct mstring *temp = msnew();
477 while ((c = *++cptr) != '\n')
480 if (c == '*' && cptr[1] == '/')
490 a.a_line = dup_line();
491 a.a_cptr = a.a_line + (cptr - line - 1);
499 if (c == '*' && *cptr == '/')
510 unterminated_comment(&a);
522 int need_newline = 0;
525 a.a_line = dup_line();
526 a.a_cptr = a.a_line + (cptr - line - 2);
532 unterminated_text(&a);
535 fprintf(f, line_format, lineno, input_file_name);
547 unterminated_text(&a);
553 char *s = copy_string(c);
563 char *s = copy_comment();
590 puts_both(const char *s)
594 fputs(s, union_file);
612 a.a_line = dup_line();
613 a.a_cptr = a.a_line + (cptr - line - 6);
616 over_unionized(cptr - 6);
619 puts_both("#ifdef YYSTYPE\n");
620 puts_both("#undef YYSTYPE_IS_DECLARED\n");
621 puts_both("#define YYSTYPE_IS_DECLARED 1\n");
622 puts_both("#endif\n");
623 puts_both("#ifndef YYSTYPE_IS_DECLARED\n");
624 puts_both("#define YYSTYPE_IS_DECLARED 1\n");
627 fprintf(text_file, line_format, lineno, input_file_name);
628 puts_both("typedef union");
639 unterminated_union(&a);
649 puts_both(" YYSTYPE;\n");
650 puts_both("#endif /* !YYSTYPE_IS_DECLARED */\n");
659 char *s = copy_string(c);
667 char *s = copy_comment();
679 after_blanks(char *s)
681 while (*s != '\0' && isspace(UCH(*s)))
687 * Trim leading/trailing blanks, and collapse multiple embedded blanks to a
688 * single space. Return index to last character in the buffer.
691 trim_blanks(char *buffer)
696 char *s = after_blanks(d);
698 while ((*d++ = *s++) != '\0')
704 while ((--d != buffer) && isspace(UCH(*d)))
707 for (s = d = buffer; (*d++ = *s++) != '\0';)
709 if (isspace(UCH(*s)))
712 while (isspace(UCH(*s)))
721 return (int)strlen(buffer) - 1;
725 * Scan forward in the current line-buffer looking for a right-curly bracket.
727 * Parameters begin with a left-curly bracket, and continue until there are no
728 * more interesting characters after the last right-curly bracket on the
729 * current line. Bison documents parameters as separated like this:
730 * {type param1} {type2 param2}
731 * but also accepts commas (although some versions of bison mishandle this)
732 * {type param1, type2 param2}
742 switch (next_inline())
761 save_param(int k, char *buffer, int name, int type2)
765 p = TMALLOC(param, 1);
768 p->type2 = strdup(buffer + type2);
770 buffer[type2] = '\0';
771 (void)trim_blanks(p->type2);
773 p->name = strdup(buffer + name);
776 (void)trim_blanks(p->name);
778 p->type = strdup(buffer);
780 (void)trim_blanks(p->type);
804 * Keep a linked list of parameters. This may be multi-line, if the trailing
805 * right-curly bracket is absent.
816 int st_lineno = lineno;
850 if ((curly == 1) && (cptr == line))
860 if (curly == 0 && !isspace(UCH(c)))
868 buf_size = (size_t) linesize;
869 buf = TMALLOC(char, buf_size);
877 buf_size += (size_t) linesize;
878 buf = TREALLOC(char, buf, buf_size);
883 if ((state == 2) && (c == L_CURL))
887 else if ((state == 2) && isspace(UCH(c)))
891 else if ((c != L_CURL) && (c != R_CURL))
898 while (curly < 2 || more_curly());
911 (void)trim_blanks(buf);
916 char *parms = (comma + 1);
917 comma = strchr(parms, ',');
921 (void)trim_blanks(parms);
922 i = (int)strlen(parms) - 1;
931 while (i >= 0 && level > 0 && parms[i] != '[')
935 else if (parms[i] == '[')
948 while (i > 0 && (isalnum(UCH(parms[i])) || UCH(parms[i]) == '_'))
951 if (!isspace(UCH(parms[i])) && parms[i] != '*')
956 save_param(k, parms, name, type2);
964 syntax_error(lineno, line, cptr);
970 if (c >= '0' && c <= '9')
972 if (c >= 'A' && c <= 'F')
973 return (c - 'A' + 10);
974 if (c >= 'a' && c <= 'f')
975 return (c - 'a' + 10);
989 a.a_line = dup_line();
990 a.a_cptr = a.a_line + (cptr - line);
1000 unterminated_string(&a);
1003 char *c_cptr = cptr - 1;
1011 unterminated_string(&a);
1026 n = (n << 3) + (c - '0');
1030 n = (n << 3) + (c - '0');
1035 illegal_character(c_cptr);
1042 if (n < 0 || n >= 16)
1043 illegal_character(c_cptr);
1048 if (i < 0 || i >= 16)
1053 illegal_character(c_cptr);
1086 s = TMALLOC(char, n);
1089 for (i = 0; i < n; ++i)
1098 for (i = 0; i < n; ++i)
1101 if (c == '\\' || c == cache[0])
1106 else if (isprint(c))
1135 cachec(((c >> 6) & 7) + '0');
1136 cachec(((c >> 3) & 7) + '0');
1137 cachec((c & 7) + '0');
1151 if (n == 1 && bp->value == UNDEFINED)
1152 bp->value = UCH(*s);
1159 is_reserved(char *name)
1163 if (strcmp(name, ".") == 0 ||
1164 strcmp(name, "$accept") == 0 ||
1165 strcmp(name, "$end") == 0)
1168 if (name[0] == '$' && name[1] == '$' && isdigit(UCH(name[2])))
1171 while (isdigit(UCH(*s)))
1186 for (c = *cptr; IS_IDENT(c); c = *++cptr)
1190 if (is_reserved(cache))
1191 used_reserved(cache);
1193 return (lookup(cache));
1203 for (c = *cptr; isdigit(c); c = *++cptr)
1204 n = (Value_t)(10 * n + (c - '0'));
1210 cache_tag(char *tag, size_t len)
1215 for (i = 0; i < ntags; ++i)
1217 if (strncmp(tag, tag_table[i], len) == 0 &&
1218 tag_table[i][len] == NUL)
1219 return (tag_table[i]);
1222 if (ntags >= tagmax)
1227 ? TREALLOC(char *, tag_table, tagmax)
1228 : TMALLOC(char *, tagmax));
1229 NO_SPACE(tag_table);
1232 s = TMALLOC(char, len + 1);
1235 strncpy(s, tag, len);
1237 tag_table[ntags++] = s;
1245 int t_lineno = lineno;
1246 char *t_line = dup_line();
1247 char *t_cptr = t_line + (cptr - line);
1253 if (!isalpha(c) && c != '_' && c != '$')
1254 illegal_tag(t_lineno, t_line, t_cptr);
1262 while (IS_IDENT(c));
1269 illegal_tag(t_lineno, t_line, t_cptr);
1274 return cache_tag(cache, (size_t) cinc);
1277 #if defined(YYBTYACC)
1283 while (isalnum(UCH(*cptr)) || *cptr == '_' || *cptr == '$')
1285 return cache_tag(b, (size_t) (cptr - b));
1290 declare_tokens(int assoc)
1313 if (isalpha(c) || c == '_' || c == '.' || c == '$')
1315 else if (c == '\'' || c == '"')
1321 tokenized_start(bp->name);
1326 if (bp->tag && tag != bp->tag)
1327 retyped_warning(bp->name);
1333 if (bp->prec && prec != bp->prec)
1334 reprec_warning(bp->name);
1335 bp->assoc = (Assoc_t)assoc;
1346 value = get_number();
1347 if (bp->value != UNDEFINED && value != bp->value)
1348 revalued_warning(bp->name);
1358 * %expect requires special handling
1359 * as it really isn't part of the yacc
1360 * grammar only a flag for yacc proper.
1363 declare_expect(int assoc)
1367 if (assoc != EXPECT && assoc != EXPECT_RR)
1371 * Stay away from nextc - doesn't
1372 * detect EOL and will read to EOF.
1382 if (assoc == EXPECT)
1383 SRexpect = get_number();
1385 RRexpect = get_number();
1389 * Looking for number before EOL.
1390 * Spaces, tabs, and numbers are ok,
1391 * words, punc., etc. are syntax errors.
1393 else if (c == '\n' || isalpha(c) || !isspace(c))
1395 syntax_error(lineno, line, cptr);
1406 #if defined(YYBTYACC)
1408 declare_argtypes(bucket *bp)
1410 char *tags[MAXARGS];
1414 retyped_warning(bp->name);
1415 cptr++; /* skip open paren */
1422 syntax_error(lineno, line, cptr);
1423 tags[args++] = get_tag();
1430 cptr++; /* skip close paren */
1432 bp->argnames = TMALLOC(char *, args);
1433 NO_SPACE(bp->argnames);
1434 bp->argtags = CALLOC(sizeof(char *), args + 1);
1435 NO_SPACE(bp->argtags);
1438 bp->argtags[args] = tags[args];
1439 bp->argnames[args] = NULL;
1462 if (isalpha(c) || c == '_' || c == '.' || c == '$')
1465 #if defined(YYBTYACC)
1466 if (nextc() == L_PAREN)
1467 declare_argtypes(bp);
1472 else if (c == '\'' || c == '"')
1475 #if defined(YYBTYACC)
1484 if (bp->tag && tag != bp->tag)
1485 retyped_warning(bp->name);
1500 if (!isalpha(c) && c != '_' && c != '.' && c != '$')
1501 syntax_error(lineno, line, cptr);
1503 if (bp->class == TERM)
1504 terminal_start(bp->name);
1505 if (goal && goal != bp)
1506 restarted_warning();
1511 read_declarations(void)
1515 cache_size = CACHE_SIZE;
1516 cache = TMALLOC(char, cache_size);
1525 syntax_error(lineno, line, cptr);
1526 switch (k = keyword())
1580 #if defined(YYBTYACC)
1589 case INITIAL_ACTION:
1590 copy_initial_action();
1599 /* noop for bison compatibility. byacc is already designed to be posix
1600 * yacc compatible. */
1607 initialize_grammar(void)
1612 pitem = TMALLOC(bucket *, maxitems);
1623 plhs = TMALLOC(bucket *, maxrules);
1630 rprec = TMALLOC(Value_t, maxrules);
1637 rassoc = TMALLOC(Assoc_t, maxrules);
1649 pitem = TREALLOC(bucket *, pitem, maxitems);
1658 plhs = TREALLOC(bucket *, plhs, maxrules);
1661 rprec = TREALLOC(Value_t, rprec, maxrules);
1664 rassoc = TREALLOC(Assoc_t, rassoc, maxrules);
1668 /* set immediately prior to where copy_args() could be called, and incremented by
1669 the various routines that will rescan the argument list as appropriate */
1670 static int rescan_lineno;
1671 #if defined(YYBTYACC)
1674 copy_args(int *alen)
1676 struct mstring *s = msnew();
1677 int depth = 0, len = 1;
1681 a.a_lineno = lineno;
1682 a.a_line = dup_line();
1683 a.a_cptr = a.a_line + (cptr - line - 1);
1685 while ((c = *cptr++) != R_PAREN || depth || quote)
1687 if (c == ',' && !quote && !depth)
1700 unterminated_string(&a);
1702 unterminated_arglist(&a);
1719 else if (c == R_PAREN)
1721 else if (c == '\"' || c == '\'')
1732 parse_id(char *p, char **save)
1736 while (isspace(UCH(*p)))
1739 if (!isalpha(UCH(*p)) && *p != '_')
1742 while (isalnum(UCH(*p)) || *p == '_' || *p == '$')
1746 *save = cache_tag(b, (size_t) (p - b));
1752 parse_int(char *p, int *save)
1754 int neg = 0, val = 0;
1756 while (isspace(UCH(*p)))
1764 if (!isdigit(UCH(*p)))
1766 while (isdigit(UCH(*p)))
1767 val = val * 10 + *p++ - '0';
1776 parse_arginfo(bucket *a, char *args, int argslen)
1778 char *p = args, *tmp;
1783 if (a->args != argslen)
1784 arg_number_disagree_warning(rescan_lineno, a->name);
1789 if ((a->args = argslen) == 0)
1791 a->argnames = TMALLOC(char *, argslen);
1792 NO_SPACE(a->argnames);
1793 a->argtags = TMALLOC(char *, argslen);
1794 NO_SPACE(a->argtags);
1798 for (i = 0; i < argslen; i++)
1800 while (isspace(UCH(*p)))
1805 while (isspace(UCH(*p)))
1811 if (!(p = parse_id(p + 1, &tmp)))
1813 while (isspace(UCH(*p)))
1820 if (a->argtags[i] != tmp)
1821 arg_type_disagree_warning(rescan_lineno, i + 1, a->name);
1824 a->argtags[i] = tmp;
1827 a->argtags[i] = NULL;
1828 if (!(p = parse_id(p, &a->argnames[i])))
1830 while (isspace(UCH(*p)))
1840 compile_arg(char **theptr, char *yyvaltag)
1843 struct mstring *c = msnew();
1845 Value_t *offsets = NULL, maxoffset;
1850 for (i = nitems - 1; pitem[i]; --i)
1853 if (pitem[i]->class != ARGUMENT)
1858 offsets = TMALLOC(Value_t, maxoffset + 1);
1861 for (j = 0, i++; i < nitems; i++)
1862 if (pitem[i]->class != ARGUMENT)
1863 offsets[++j] = (Value_t)(i - nitems + 1);
1865 rhs = pitem + nitems - 1;
1868 msprintf(c, "yyval.%s = ", yyvaltag);
1870 msprintf(c, "yyval = ");
1877 if (!(p = parse_id(++p, &tag)) || *p++ != '>')
1878 illegal_tag(rescan_lineno, NULL, NULL);
1879 if (isdigit(UCH(*p)) || *p == '-')
1882 if (!(p = parse_int(p, &val)))
1883 dollar_error(rescan_lineno, NULL, NULL);
1886 else if (val > maxoffset)
1888 dollar_warning(rescan_lineno, val);
1889 i = val - maxoffset;
1891 else if (maxoffset > 0)
1894 if (!tag && !(tag = rhs[i]->tag) && havetags)
1895 untyped_rhs(val, rhs[i]->name);
1897 msprintf(c, "yystack.l_mark[%d]", i);
1899 msprintf(c, ".%s", tag);
1903 else if (isalpha(UCH(*p)) || *p == '_')
1906 if (!(p = parse_id(p, &arg)))
1907 dollar_error(rescan_lineno, NULL, NULL);
1908 for (i = plhs[nrules]->args - 1; i >= 0; i--)
1909 if (arg == plhs[nrules]->argnames[i])
1912 unknown_arg_warning(rescan_lineno, "$", arg, NULL, NULL);
1914 tag = plhs[nrules]->argtags[i];
1915 msprintf(c, "yystack.l_mark[%d]",
1916 i - plhs[nrules]->args + 1 - n);
1918 msprintf(c, ".%s", tag);
1920 untyped_arg_warning(rescan_lineno, "$", arg);
1923 dollar_error(rescan_lineno, NULL, NULL);
1927 at_error(rescan_lineno, NULL, NULL);
1943 can_elide_arg(char **theptr, char *yyvaltag)
1948 Value_t *offsets = NULL, maxoffset = 0;
1956 if (!(p = parse_id(++p, &tag)) || *p++ != '>')
1959 for (i = nitems - 1; pitem[i]; --i)
1962 if (pitem[i]->class != ARGUMENT)
1967 offsets = TMALLOC(Value_t, maxoffset + 1);
1970 for (j = 0, i++; i < nitems; i++)
1971 if (pitem[i]->class != ARGUMENT)
1972 offsets[++j] = (Value_t)(i - nitems + 1);
1974 rhs = pitem + nitems - 1;
1976 if (isdigit(UCH(*p)) || *p == '-')
1979 if (!(p = parse_int(p, &val)))
1985 else if (val > maxoffset)
1996 else if (isalpha(UCH(*p)) || *p == '_')
1999 if (!(p = parse_id(p, &arg)))
2001 for (i = plhs[nrules]->args - 1; i >= 0; i--)
2002 if (arg == plhs[nrules]->argnames[i])
2007 tag = plhs[nrules]->argtags[i];
2008 rv = plhs[nrules]->args + n - i;
2011 if (tag && yyvaltag)
2013 if (strcmp(tag, yyvaltag))
2016 else if (tag || yyvaltag)
2026 #define ARG_CACHE_SIZE 1024
2027 static struct arg_cache
2029 struct arg_cache *next;
2033 *arg_cache[ARG_CACHE_SIZE];
2036 lookup_arg_cache(char *code)
2038 struct arg_cache *entry;
2040 entry = arg_cache[strnshash(code) % ARG_CACHE_SIZE];
2043 if (!strnscmp(entry->code, code))
2045 entry = entry->next;
2051 insert_arg_cache(char *code, int rule)
2053 struct arg_cache *entry = NEW(struct arg_cache);
2057 i = strnshash(code) % ARG_CACHE_SIZE;
2060 entry->next = arg_cache[i];
2061 arg_cache[i] = entry;
2065 clean_arg_cache(void)
2067 struct arg_cache *e, *t;
2070 for (i = 0; i < ARG_CACHE_SIZE; i++)
2072 for (e = arg_cache[i]; (t = e); e = e->next, FREE(t))
2074 arg_cache[i] = NULL;
2077 #endif /* defined(YYBTYACC) */
2080 advance_to_start(void)
2086 #if defined(YYBTYACC)
2111 syntax_error(lineno, line, s_cptr);
2116 if (!isalpha(c) && c != '_' && c != '.' && c != '_')
2117 syntax_error(lineno, line, cptr);
2121 if (bp->class == TERM)
2122 terminal_start(bp->name);
2130 rescan_lineno = lineno; /* line# for possible inherited args rescan */
2131 #if defined(YYBTYACC)
2135 args = copy_args(&argslen);
2141 syntax_error(lineno, line, cptr);
2142 start_rule(bp, s_lineno);
2143 #if defined(YYBTYACC)
2144 parse_arginfo(bp, args, argslen);
2150 start_rule(bucket *bp, int s_lineno)
2152 if (bp->class == TERM)
2153 terminal_lhs(s_lineno);
2154 bp->class = NONTERM;
2157 if (nrules >= maxrules)
2160 rprec[nrules] = UNDEFINED;
2161 rassoc[nrules] = TOKEN;
2169 if (!last_was_action && plhs[nrules]->tag)
2171 if (pitem[nitems - 1])
2173 for (i = nitems - 1; (i > 0) && pitem[i]; --i)
2175 if (pitem[i + 1] == 0 || pitem[i + 1]->tag != plhs[nrules]->tag)
2176 default_action_warning(plhs[nrules]->name);
2179 default_action_warning(plhs[nrules]->name);
2182 last_was_action = 0;
2183 if (nitems >= maxitems)
2191 insert_empty_rule(void)
2196 assert(cache_size >= CACHE_SIZE);
2197 sprintf(cache, "$$%d", ++gensym);
2198 bp = make_bucket(cache);
2199 last_symbol->next = bp;
2201 bp->tag = plhs[nrules]->tag;
2203 #if defined(YYBTYACC)
2207 nitems = (Value_t)(nitems + 2);
2208 if (nitems > maxitems)
2210 bpp = pitem + nitems - 1;
2212 while ((bpp[0] = bpp[-1]) != 0)
2215 if (++nrules >= maxrules)
2217 plhs[nrules] = plhs[nrules - 1];
2218 plhs[nrules - 1] = bp;
2219 rprec[nrules] = rprec[nrules - 1];
2220 rprec[nrules - 1] = 0;
2221 rassoc[nrules] = rassoc[nrules - 1];
2222 rassoc[nrules - 1] = TOKEN;
2225 #if defined(YYBTYACC)
2227 insert_arg_rule(char *arg, char *tag)
2229 int line_number = rescan_lineno;
2230 char *code = compile_arg(&arg, tag);
2231 int rule = lookup_arg_cache(code);
2232 FILE *f = action_file;
2237 insert_arg_cache(code, rule);
2238 trialaction = 1; /* arg rules always run in trial mode */
2239 fprintf(f, "case %d:\n", rule - 2);
2241 fprintf(f, line_format, line_number, input_file_name);
2242 fprintf(f, "%s;\n", code);
2243 fprintf(f, "break;\n");
2244 insert_empty_rule();
2245 plhs[rule]->tag = cache_tag(tag, strlen(tag));
2246 plhs[rule]->class = ARGUMENT;
2250 if (++nitems > maxitems)
2252 pitem[nitems - 1] = plhs[rule];
2264 int s_lineno = lineno;
2265 #if defined(YYBTYACC)
2271 if (c == '\'' || c == '"')
2277 rescan_lineno = lineno; /* line# for possible inherited args rescan */
2278 #if defined(YYBTYACC)
2282 args = copy_args(&argslen);
2290 start_rule(bp, s_lineno);
2291 #if defined(YYBTYACC)
2292 parse_arginfo(bp, args, argslen);
2298 if (last_was_action)
2299 insert_empty_rule();
2300 last_was_action = 0;
2302 #if defined(YYBTYACC)
2305 if (argslen == 0 && bp->args > 0 && pitem[nitems - 1] == NULL)
2308 if (plhs[nrules]->args != bp->args)
2309 wrong_number_args_warning("default ", bp->name);
2310 for (i = bp->args - 1; i >= 0; i--)
2311 if (plhs[nrules]->argtags[i] != bp->argtags[i])
2312 wrong_type_for_arg_warning(i + 1, bp->name);
2314 else if (bp->args != argslen)
2315 wrong_number_args_warning("", bp->name);
2320 int elide_cnt = can_elide_arg(&ap, bp->argtags[0]);
2322 if (elide_cnt > argslen)
2326 for (i = 1; i < elide_cnt; i++)
2327 if (can_elide_arg(&ap, bp->argtags[i]) != elide_cnt - i)
2335 assert(i == elide_cnt);
2342 for (; i < argslen; i++)
2343 ap = insert_arg_rule(ap, bp->argtags[i]);
2346 #endif /* defined(YYBTYACC) */
2348 if (++nitems > maxitems)
2350 pitem[nitems - 1] = bp;
2359 #if defined(YYBTYACC)
2363 FILE *f = action_file;
2365 Value_t *offsets = NULL, maxoffset;
2368 a.a_lineno = lineno;
2369 a.a_line = dup_line();
2370 a.a_cptr = a.a_line + (cptr - line);
2372 if (last_was_action)
2373 insert_empty_rule();
2374 last_was_action = 1;
2375 #if defined(YYBTYACC)
2376 trialaction = (*cptr == L_BRAC);
2379 fprintf(f, "case %d:\n", nrules - 2);
2380 #if defined(YYBTYACC)
2384 fprintf(f, " if (!yytrial)\n");
2388 fprintf(f, line_format, lineno, input_file_name);
2392 /* avoid putting curly-braces in first column, to ease editing */
2393 if (*after_blanks(cptr) == L_CURL)
2396 cptr = after_blanks(cptr);
2401 for (i = nitems - 1; pitem[i]; --i)
2404 if (pitem[i]->class != ARGUMENT)
2409 offsets = TMALLOC(Value_t, maxoffset + 1);
2412 for (j = 0, i++; i < nitems; i++)
2414 if (pitem[i]->class != ARGUMENT)
2416 offsets[++j] = (Value_t)(i - nitems + 1);
2420 rhs = pitem + nitems - 1;
2429 int d_lineno = lineno;
2430 char *d_line = dup_line();
2431 char *d_cptr = d_line + (cptr - line);
2438 fprintf(f, "yyval.%s", tag);
2443 else if (isdigit(c))
2447 fprintf(f, "yystack.l_mark[%d].%s", -n, tag);
2448 else if (i > maxoffset)
2450 dollar_warning(d_lineno, i);
2451 fprintf(f, "yystack.l_mark[%d].%s", i - maxoffset, tag);
2454 fprintf(f, "yystack.l_mark[%d].%s", offsets[i], tag);
2458 else if (c == '-' && isdigit(UCH(cptr[1])))
2461 i = -get_number() - n;
2462 fprintf(f, "yystack.l_mark[%d].%s", i, tag);
2466 #if defined(YYBTYACC)
2467 else if (isalpha(c) || c == '_')
2469 char *arg = scan_id();
2470 for (i = plhs[nrules]->args - 1; i >= 0; i--)
2471 if (arg == plhs[nrules]->argnames[i])
2474 unknown_arg_warning(d_lineno, "$", arg, d_line, d_cptr);
2475 fprintf(f, "yystack.l_mark[%d].%s",
2476 i - plhs[nrules]->args + 1 - n, tag);
2482 dollar_error(d_lineno, d_line, d_cptr);
2484 else if (cptr[1] == '$')
2488 tag = plhs[nrules]->tag;
2491 fprintf(f, "yyval.%s", tag);
2494 fprintf(f, "yyval");
2496 #if defined(YYBTYACC)
2501 else if (isdigit(UCH(cptr[1])))
2505 if (havetags && offsets)
2507 if (i <= 0 || i > maxoffset)
2509 tag = rhs[offsets[i]]->tag;
2511 untyped_rhs(i, rhs[offsets[i]]->name);
2512 fprintf(f, "yystack.l_mark[%d].%s", offsets[i], tag);
2517 fprintf(f, "yystack.l_mark[%d]", -n);
2518 else if (i > maxoffset)
2520 dollar_warning(lineno, i);
2521 fprintf(f, "yystack.l_mark[%d]", i - maxoffset);
2524 fprintf(f, "yystack.l_mark[%d]", offsets[i]);
2528 else if (cptr[1] == '-')
2534 fprintf(f, "yystack.l_mark[%d]", -i - n);
2537 #if defined(YYBTYACC)
2538 else if (isalpha(UCH(cptr[1])) || cptr[1] == '_')
2543 for (i = plhs[nrules]->args - 1; i >= 0; i--)
2544 if (arg == plhs[nrules]->argnames[i])
2547 unknown_arg_warning(lineno, "$", arg, line, cptr);
2548 tag = (i < 0 ? NULL : plhs[nrules]->argtags[i]);
2549 fprintf(f, "yystack.l_mark[%d]", i - plhs[nrules]->args + 1 - n);
2551 fprintf(f, ".%s", tag);
2553 untyped_arg_warning(lineno, "$", arg);
2558 #if defined(YYBTYACC)
2563 int l_lineno = lineno;
2564 char *l_line = dup_line();
2565 char *l_cptr = l_line + (cptr - line);
2566 syntax_error(l_lineno, l_line, l_cptr);
2570 fprintf(f, "yyloc");
2574 else if (isdigit(UCH(cptr[1])))
2579 fprintf(f, "yystack.p_mark[%d]", -n);
2580 else if (i > maxoffset)
2582 at_warning(lineno, i);
2583 fprintf(f, "yystack.p_mark[%d]", i - maxoffset);
2586 fprintf(f, "yystack.p_mark[%d]", offsets[i]);
2589 else if (cptr[1] == '-')
2593 fprintf(f, "yystack.p_mark[%d]", -i - n);
2598 if (isalpha(c) || c == '_' || c == '$')
2605 while (isalnum(c) || c == '_' || c == '$');
2609 #if defined(YYBTYACC)
2612 if (trialaction && c == L_BRAC && depth == 0)
2618 if (trialaction && c == R_BRAC && depth == 1)
2623 if (c == L_BRAC && !haveyyval)
2627 if (c == L_CURL && !haveyyval)
2629 fprintf(f, " if (!yytrial)\n");
2631 fprintf(f, line_format, lineno, input_file_name);
2635 fprintf(f, "\nbreak;\n");
2650 unterminated_action(&a);
2655 fprintf(f, "\nbreak;\n");
2661 #if defined(YYBTYACC)
2680 #if defined(YYBTYACC)
2684 if (c == L_BRAC && !haveyyval)
2689 if (c == L_CURL && !haveyyval)
2691 fprintf(f, " if (!yytrial)\n");
2693 fprintf(f, line_format, lineno, input_file_name);
2698 fprintf(f, "\nbreak;\n");
2707 char *s = copy_string(c);
2715 char *s = copy_comment();
2726 #if defined(YYBTYACC)
2728 get_code(struct ainfo *a, const char *loc)
2733 struct mstring *code_mstr = msnew();
2736 msprintf(code_mstr, line_format, lineno, input_file_name);
2738 cptr = after_blanks(cptr);
2739 if (*cptr == L_CURL)
2740 /* avoid putting curly-braces in first column, to ease editing */
2741 mputc(code_mstr, '\t');
2743 syntax_error(lineno, line, cptr);
2745 a->a_lineno = lineno;
2746 a->a_line = dup_line();
2747 a->a_cptr = a->a_line + (cptr - line);
2756 int d_lineno = lineno;
2757 char *d_line = dup_line();
2758 char *d_cptr = d_line + (cptr - line);
2765 msprintf(code_mstr, "(*val).%s", tag);
2771 dollar_error(d_lineno, d_line, d_cptr);
2773 else if (cptr[1] == '$')
2775 /* process '$$' later; replacement is context dependent */
2776 msprintf(code_mstr, "$$");
2781 if (c == '@' && cptr[1] == '$')
2785 int l_lineno = lineno;
2786 char *l_line = dup_line();
2787 char *l_cptr = l_line + (cptr - line);
2788 syntax_error(l_lineno, l_line, l_cptr);
2790 msprintf(code_mstr, "%s", loc);
2794 if (isalpha(c) || c == '_' || c == '$')
2798 mputc(code_mstr, c);
2801 while (isalnum(c) || c == '_' || c == '$');
2805 mputc(code_mstr, c);
2812 unterminated_action(a);
2826 char *s = copy_string(c);
2827 msprintf(code_mstr, "%s", s);
2834 char *s = copy_comment();
2835 msprintf(code_mstr, "%s", s);
2844 return msdone(code_mstr);
2848 copy_initial_action(void)
2852 initial_action = get_code(&a, "yyloc");
2857 copy_destructor(void)
2864 code_text = get_code(&a, "(*loc)");
2874 { /* "no semantic type" default destructor */
2876 if ((bp = default_destructor[UNTYPED_DEFAULT]) == NULL)
2878 static char untyped_default[] = "<>";
2879 bp = make_bucket("untyped default");
2880 bp->tag = untyped_default;
2881 default_destructor[UNTYPED_DEFAULT] = bp;
2883 if (bp->destructor != NULL)
2884 destructor_redeclared_warning(&a);
2886 /* replace "$$" with "(*val)" in destructor code */
2887 bp->destructor = process_destructor_XX(code_text, NULL);
2889 else if (cptr[1] == '*' && cptr[2] == '>')
2890 { /* "no per-symbol or per-type" default destructor */
2892 if ((bp = default_destructor[TYPED_DEFAULT]) == NULL)
2894 static char typed_default[] = "<*>";
2895 bp = make_bucket("typed default");
2896 bp->tag = typed_default;
2897 default_destructor[TYPED_DEFAULT] = bp;
2899 if (bp->destructor != NULL)
2900 destructor_redeclared_warning(&a);
2903 /* postpone re-processing destructor $$s until end of grammar spec */
2904 bp->destructor = TMALLOC(char, strlen(code_text) + 1);
2905 NO_SPACE(bp->destructor);
2906 strcpy(bp->destructor, code_text);
2910 { /* "semantic type" default destructor */
2911 char *tag = get_tag();
2912 bp = lookup_type_destructor(tag);
2913 if (bp->destructor != NULL)
2914 destructor_redeclared_warning(&a);
2916 /* replace "$$" with "(*val).tag" in destructor code */
2917 bp->destructor = process_destructor_XX(code_text, tag);
2920 else if (isalpha(c) || c == '_' || c == '.' || c == '$')
2921 { /* "symbol" destructor */
2923 if (bp->destructor != NULL)
2924 destructor_redeclared_warning(&a);
2927 /* postpone re-processing destructor $$s until end of grammar spec */
2928 bp->destructor = TMALLOC(char, strlen(code_text) + 1);
2929 NO_SPACE(bp->destructor);
2930 strcpy(bp->destructor, code_text);
2941 process_destructor_XX(char *code, char *tag)
2946 struct mstring *new_code = msnew();
2947 char *codeptr = code;
2950 loop: /* step thru code */
2952 if (c == '$' && codeptr[1] == '$')
2956 msprintf(new_code, "(*val)");
2958 msprintf(new_code, "(*val).%s", tag);
2961 if (isalpha(c) || c == '_' || c == '$')
2968 while (isalnum(c) || c == '_' || c == '$');
2982 return msdone(new_code);
3010 if (c == '*' && *codeptr == '/')
3012 mputc(new_code, '/');
3024 #endif /* defined(YYBTYACC) */
3033 if (c == '%' || c == '\\')
3041 else if ((c == 'p' || c == 'P') &&
3042 ((c = cptr[2]) == 'r' || c == 'R') &&
3043 ((c = cptr[3]) == 'e' || c == 'E') &&
3044 ((c = cptr[4]) == 'c' || c == 'C') &&
3045 ((c = cptr[5], !IS_IDENT(c))))
3048 syntax_error(lineno, line, cptr);
3051 if (isalpha(c) || c == '_' || c == '.' || c == '$')
3053 else if (c == '\'' || c == '"')
3057 syntax_error(lineno, line, cptr);
3061 if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules])
3064 rprec[nrules] = bp->prec;
3065 rassoc[nrules] = bp->assoc;
3074 initialize_grammar();
3089 #if defined(YYBTYACC)
3090 else if (c == L_CURL || c == '=' || (backtrack && c == L_BRAC))
3092 else if (c == L_CURL || c == '=')
3098 start_rule(plhs[nrules - 1], 0);
3107 syntax_error(lineno, line, cptr);
3110 #if defined(YYBTYACC)
3112 start_requires_args(goal->name);
3124 for (i = 0; i < ntags; ++i)
3126 assert(tag_table[i]);
3138 name_pool_size = 13; /* 13 == sizeof("$end") + sizeof("$accept") */
3139 for (bp = first_symbol; bp; bp = bp->next)
3140 name_pool_size += strlen(bp->name) + 1;
3142 name_pool = TMALLOC(char, name_pool_size);
3143 NO_SPACE(name_pool);
3145 strcpy(name_pool, "$accept");
3146 strcpy(name_pool + 8, "$end");
3148 for (bp = first_symbol; bp; bp = bp->next)
3152 while ((*t++ = *s++) != 0)
3164 if (goal->class == UNKNOWN)
3165 undefined_goal(goal->name);
3167 for (bp = first_symbol; bp; bp = bp->next)
3169 if (bp->class == UNKNOWN)
3171 undefined_symbol_warning(bp->name);
3178 protect_string(char *src, char **des)
3191 if ('\\' == *s || '"' == *s)
3197 *des = d = TMALLOC(char, len);
3203 if ('\\' == *s || '"' == *s)
3217 #if defined(YYBTYACC)
3218 Value_t max_tok_pval;
3223 for (bp = first_symbol; bp; bp = bp->next)
3226 if (bp->class == TERM)
3229 start_symbol = (Value_t)ntokens;
3230 nvars = (Value_t)(nsyms - ntokens);
3232 symbol_name = TMALLOC(char *, nsyms);
3233 NO_SPACE(symbol_name);
3235 symbol_value = TMALLOC(Value_t, nsyms);
3236 NO_SPACE(symbol_value);
3238 symbol_prec = TMALLOC(Value_t, nsyms);
3239 NO_SPACE(symbol_prec);
3241 symbol_assoc = TMALLOC(char, nsyms);
3242 NO_SPACE(symbol_assoc);
3244 #if defined(YYBTYACC)
3245 symbol_pval = TMALLOC(Value_t, nsyms);
3246 NO_SPACE(symbol_pval);
3250 symbol_destructor = CALLOC(sizeof(char *), nsyms);
3251 NO_SPACE(symbol_destructor);
3253 symbol_type_tag = CALLOC(sizeof(char *), nsyms);
3254 NO_SPACE(symbol_type_tag);
3258 v = TMALLOC(bucket *, nsyms);
3262 v[start_symbol] = 0;
3265 j = (Value_t)(start_symbol + 1);
3266 for (bp = first_symbol; bp; bp = bp->next)
3268 if (bp->class == TERM)
3273 assert(i == ntokens && j == nsyms);
3275 for (i = 1; i < ntokens; ++i)
3278 goal->index = (Index_t)(start_symbol + 1);
3279 k = (Value_t)(start_symbol + 2);
3289 for (i = (Value_t)(start_symbol + 1); i < nsyms; ++i)
3299 for (i = 1; i < ntokens; ++i)
3304 for (j = k++; j > 0 && symbol_value[j - 1] > n; --j)
3305 symbol_value[j] = symbol_value[j - 1];
3306 symbol_value[j] = n;
3312 if (v[1]->value == UNDEFINED)
3317 for (i = 2; i < ntokens; ++i)
3319 if (v[i]->value == UNDEFINED)
3321 while (j < k && n == symbol_value[j])
3323 while (++j < k && n == symbol_value[j])
3332 symbol_name[0] = name_pool + 8;
3333 symbol_value[0] = 0;
3335 symbol_assoc[0] = TOKEN;
3336 #if defined(YYBTYACC)
3340 for (i = 1; i < ntokens; ++i)
3342 symbol_name[i] = v[i]->name;
3343 symbol_value[i] = v[i]->value;
3344 symbol_prec[i] = v[i]->prec;
3345 symbol_assoc[i] = v[i]->assoc;
3346 #if defined(YYBTYACC)
3347 symbol_pval[i] = v[i]->value;
3348 if (symbol_pval[i] > max_tok_pval)
3349 max_tok_pval = symbol_pval[i];
3352 symbol_destructor[i] = v[i]->destructor;
3353 symbol_type_tag[i] = v[i]->tag;
3357 symbol_name[start_symbol] = name_pool;
3358 symbol_value[start_symbol] = -1;
3359 symbol_prec[start_symbol] = 0;
3360 symbol_assoc[start_symbol] = TOKEN;
3361 #if defined(YYBTYACC)
3362 symbol_pval[start_symbol] = (Value_t)(max_tok_pval + 1);
3364 for (++i; i < nsyms; ++i)
3367 symbol_name[k] = v[i]->name;
3368 symbol_value[k] = v[i]->value;
3369 symbol_prec[k] = v[i]->prec;
3370 symbol_assoc[k] = v[i]->assoc;
3371 #if defined(YYBTYACC)
3372 symbol_pval[k] = (Value_t)((max_tok_pval + 1) + v[i]->value + 1);
3375 symbol_destructor[k] = v[i]->destructor;
3376 symbol_type_tag[k] = v[i]->tag;
3383 symbol_pname = TMALLOC(char *, nsyms);
3384 NO_SPACE(symbol_pname);
3386 for (i = 0; i < nsyms; ++i)
3387 protect_string(symbol_name[i], &(symbol_pname[i]));
3401 ritem = TMALLOC(Value_t, nitems);
3404 rlhs = TMALLOC(Value_t, nrules);
3407 rrhs = TMALLOC(Value_t, nrules + 1);
3410 rprec = TREALLOC(Value_t, rprec, nrules);
3413 rassoc = TREALLOC(Assoc_t, rassoc, nrules);
3417 ritem[1] = goal->index;
3422 rlhs[2] = start_symbol;
3428 for (i = 3; i < nrules; ++i)
3430 #if defined(YYBTYACC)
3431 if (plhs[i]->args > 0)
3433 if (plhs[i]->argnames)
3435 FREE(plhs[i]->argnames);
3436 plhs[i]->argnames = NULL;
3438 if (plhs[i]->argtags)
3440 FREE(plhs[i]->argtags);
3441 plhs[i]->argtags = NULL;
3444 #endif /* defined(YYBTYACC) */
3445 rlhs[i] = plhs[i]->index;
3451 ritem[j] = pitem[j]->index;
3452 if (pitem[j]->class == TERM)
3454 prec2 = pitem[j]->prec;
3455 assoc = pitem[j]->assoc;
3459 ritem[j] = (Value_t)-i;
3461 if (rprec[i] == UNDEFINED)
3471 #if defined(YYBTYACC)
3480 size_t j, spacing = 0;
3481 FILE *f = verbose_file;
3487 for (i = 2; i < nrules; ++i)
3489 if (rlhs[i] != rlhs[i - 1])
3493 fprintf(f, "%4d %s :", i - 2, symbol_name[rlhs[i]]);
3494 spacing = strlen(symbol_name[rlhs[i]]) + 1;
3498 fprintf(f, "%4d ", i - 2);
3505 while (ritem[k] >= 0)
3507 fprintf(f, " %s", symbol_name[ritem[k]]);
3515 #if defined(YYBTYACC)
3517 finalize_destructors(void)
3523 for (i = 2; i < nsyms; ++i)
3525 tag = symbol_type_tag[i];
3526 if (symbol_destructor[i] == NULL)
3529 { /* use <> destructor, if there is one */
3530 if ((bp = default_destructor[UNTYPED_DEFAULT]) != NULL)
3532 symbol_destructor[i] = TMALLOC(char,
3533 strlen(bp->destructor) + 1);
3534 NO_SPACE(symbol_destructor[i]);
3535 strcpy(symbol_destructor[i], bp->destructor);
3539 { /* use type destructor for this tag, if there is one */
3540 bp = lookup_type_destructor(tag);
3541 if (bp->destructor != NULL)
3543 symbol_destructor[i] = TMALLOC(char,
3544 strlen(bp->destructor) + 1);
3545 NO_SPACE(symbol_destructor[i]);
3546 strcpy(symbol_destructor[i], bp->destructor);
3549 { /* use <*> destructor, if there is one */
3550 if ((bp = default_destructor[TYPED_DEFAULT]) != NULL)
3551 /* replace "$$" with "(*val).tag" in destructor code */
3552 symbol_destructor[i]
3553 = process_destructor_XX(bp->destructor, tag);
3558 { /* replace "$$" with "(*val)[.tag]" in destructor code */
3559 symbol_destructor[i]
3560 = process_destructor_XX(symbol_destructor[i], tag);
3563 /* 'symbol_type_tag[]' elements are freed by 'free_tags()' */
3564 DO_FREE(symbol_type_tag); /* no longer needed */
3565 if ((bp = default_destructor[UNTYPED_DEFAULT]) != NULL)
3568 /* 'bp->tag' is a static value, don't free */
3569 FREE(bp->destructor);
3572 if ((bp = default_destructor[TYPED_DEFAULT]) != NULL)
3575 /* 'bp->tag' is a static value, don't free */
3576 FREE(bp->destructor);
3579 if ((bp = default_destructor[TYPE_SPECIFIED]) != NULL)
3586 /* 'bp->tag' freed by 'free_tags()' */
3587 FREE(bp->destructor);
3592 #endif /* defined(YYBTYACC) */
3597 write_section(code_file, banner);
3598 create_symbol_table();
3599 read_declarations();
3601 free_symbol_table();
3608 #if defined(YYBTYACC)
3610 finalize_destructors();
3617 free_declarations(param *list)
3621 param *next = list->next;
3634 lex_param = free_declarations(lex_param);
3635 parse_param = free_declarations(parse_param);
3645 DO_FREE(symbol_name);
3646 DO_FREE(symbol_prec);
3647 DO_FREE(symbol_assoc);
3648 DO_FREE(symbol_value);
3649 #if defined(YYBTYACC)
3650 DO_FREE(symbol_pval);
3651 DO_FREE(symbol_destructor);
3652 DO_FREE(symbol_type_tag);