139781Sbostic /*
239781Sbostic * Copyright (c) 1989 The Regents of the University of California.
339781Sbostic * All rights reserved.
439781Sbostic *
539781Sbostic * This code is derived from software contributed to Berkeley by
639781Sbostic * Robert Paul Corbett.
739781Sbostic *
842698Sbostic * %sccs.include.redist.c%
939781Sbostic */
1039781Sbostic
1139781Sbostic #ifndef lint
12*46064Scorbett static char sccsid[] = "@(#)reader.c 5.7 (Berkeley) 01/20/91";
1339781Sbostic #endif /* not lint */
1439781Sbostic
1539781Sbostic #include "defs.h"
1639781Sbostic
1739781Sbostic /* The line size must be a positive integer. One hundred was chosen */
1839781Sbostic /* because few lines in Yacc input grammars exceed 100 characters. */
1939781Sbostic /* Note that if a line exceeds LINESIZE characters, the line buffer */
2039781Sbostic /* will be expanded to accomodate it. */
2139781Sbostic
2239781Sbostic #define LINESIZE 100
2339781Sbostic
2439781Sbostic char *cache;
2539781Sbostic int cinc, cache_size;
2639781Sbostic
2739781Sbostic int ntags, tagmax;
2839781Sbostic char **tag_table;
2939781Sbostic
3039781Sbostic char saw_eof, unionized;
3139781Sbostic char *cptr, *line;
3239781Sbostic int linesize;
3339781Sbostic
3439781Sbostic bucket *goal;
3539781Sbostic int prec;
3639781Sbostic int gensym;
3739781Sbostic char last_was_action;
3839781Sbostic
3939781Sbostic int maxitems;
4039781Sbostic bucket **pitem;
4139781Sbostic
4239781Sbostic int maxrules;
4339781Sbostic bucket **plhs;
4439781Sbostic
4539781Sbostic int name_pool_size;
4639781Sbostic char *name_pool;
4739781Sbostic
4839781Sbostic char line_format[] = "#line %d \"%s\"\n";
4939781Sbostic
5039781Sbostic
cachec(c)5139781Sbostic cachec(c)
5239781Sbostic int c;
5339781Sbostic {
5439781Sbostic assert(cinc >= 0);
5539781Sbostic if (cinc >= cache_size)
5639781Sbostic {
5739781Sbostic cache_size += 256;
5839781Sbostic cache = REALLOC(cache, cache_size);
5939781Sbostic if (cache == 0) no_space();
6039781Sbostic }
6139781Sbostic cache[cinc] = c;
6239781Sbostic ++cinc;
6339781Sbostic }
6439781Sbostic
6539781Sbostic
get_line()6639781Sbostic get_line()
6739781Sbostic {
6839781Sbostic register FILE *f = input_file;
6939781Sbostic register int c;
7039781Sbostic register int i;
7139781Sbostic
7239781Sbostic if (saw_eof || (c = getc(f)) == EOF)
7339781Sbostic {
7439781Sbostic if (line) { FREE(line); line = 0; }
7539781Sbostic cptr = 0;
7639781Sbostic saw_eof = 1;
7739781Sbostic return;
7839781Sbostic }
7939781Sbostic
8039781Sbostic if (line == 0 || linesize != (LINESIZE + 1))
8139781Sbostic {
8239781Sbostic if (line) FREE(line);
8339781Sbostic linesize = LINESIZE + 1;
8439781Sbostic line = MALLOC(linesize);
8539781Sbostic if (line == 0) no_space();
8639781Sbostic }
8739781Sbostic
8839781Sbostic i = 0;
8939781Sbostic ++lineno;
9039781Sbostic for (;;)
9139781Sbostic {
9239781Sbostic line[i] = c;
9339781Sbostic if (c == '\n') { cptr = line; return; }
9439781Sbostic if (++i >= linesize)
9539781Sbostic {
9639781Sbostic linesize += LINESIZE;
9739781Sbostic line = REALLOC(line, linesize);
9839781Sbostic if (line == 0) no_space();
9939781Sbostic }
10039781Sbostic c = getc(f);
10139781Sbostic if (c == EOF)
10239781Sbostic {
10339781Sbostic line[i] = '\n';
10439781Sbostic saw_eof = 1;
10539781Sbostic cptr = line;
10639781Sbostic return;
10739781Sbostic }
10839781Sbostic }
10939781Sbostic }
11039781Sbostic
11139781Sbostic
11239781Sbostic char *
dup_line()11339781Sbostic dup_line()
11439781Sbostic {
11539781Sbostic register char *p, *s, *t;
11639781Sbostic
11739781Sbostic if (line == 0) return (0);
11839781Sbostic s = line;
11939781Sbostic while (*s != '\n') ++s;
12039781Sbostic p = MALLOC(s - line + 1);
12139781Sbostic if (p == 0) no_space();
12239781Sbostic
12339781Sbostic s = line;
12439781Sbostic t = p;
12539781Sbostic while ((*t++ = *s++) != '\n') continue;
12639781Sbostic return (p);
12739781Sbostic }
12839781Sbostic
12939781Sbostic
skip_comment()13039781Sbostic skip_comment()
13139781Sbostic {
13239781Sbostic register char *s;
13339781Sbostic
13439781Sbostic int st_lineno = lineno;
13539781Sbostic char *st_line = dup_line();
13639781Sbostic char *st_cptr = st_line + (cptr - line);
13739781Sbostic
13839781Sbostic s = cptr + 2;
13939781Sbostic for (;;)
14039781Sbostic {
14139781Sbostic if (*s == '*' && s[1] == '/')
14239781Sbostic {
14339781Sbostic cptr = s + 2;
14439781Sbostic FREE(st_line);
14539781Sbostic return;
14639781Sbostic }
14739781Sbostic if (*s == '\n')
14839781Sbostic {
14939781Sbostic get_line();
15039781Sbostic if (line == 0)
15139781Sbostic unterminated_comment(st_lineno, st_line, st_cptr);
15239781Sbostic s = cptr;
15339781Sbostic }
15439781Sbostic else
15539781Sbostic ++s;
15639781Sbostic }
15739781Sbostic }
15839781Sbostic
15939781Sbostic
16039781Sbostic int
nextc()16139781Sbostic nextc()
16239781Sbostic {
16339781Sbostic register char *s;
16439781Sbostic
16539781Sbostic if (line == 0)
16639781Sbostic {
16739781Sbostic get_line();
16839781Sbostic if (line == 0)
16939781Sbostic return (EOF);
17039781Sbostic }
17139781Sbostic
17239781Sbostic s = cptr;
17339781Sbostic for (;;)
17439781Sbostic {
17539781Sbostic switch (*s)
17639781Sbostic {
17739781Sbostic case '\n':
17839781Sbostic get_line();
17939781Sbostic if (line == 0) return (EOF);
18039781Sbostic s = cptr;
18139781Sbostic break;
18239781Sbostic
18339781Sbostic case ' ':
18439781Sbostic case '\t':
18539781Sbostic case '\f':
18639781Sbostic case '\r':
18739781Sbostic case '\v':
18839781Sbostic case ',':
18939781Sbostic case ';':
19039781Sbostic ++s;
19139781Sbostic break;
19239781Sbostic
19339781Sbostic case '\\':
19439781Sbostic cptr = s;
19539781Sbostic return ('%');
19639781Sbostic
19739781Sbostic case '/':
19839781Sbostic if (s[1] == '*')
19939781Sbostic {
20039781Sbostic cptr = s;
20139781Sbostic skip_comment();
20239781Sbostic s = cptr;
20339781Sbostic break;
20439781Sbostic }
20539781Sbostic else if (s[1] == '/')
20639781Sbostic {
20739781Sbostic get_line();
20839781Sbostic if (line == 0) return (EOF);
20939781Sbostic s = cptr;
21039781Sbostic break;
21139781Sbostic }
21239781Sbostic /* fall through */
21339781Sbostic
21439781Sbostic default:
21539781Sbostic cptr = s;
21639781Sbostic return (*s);
21739781Sbostic }
21839781Sbostic }
21939781Sbostic }
22039781Sbostic
22139781Sbostic
22239781Sbostic int
keyword()22339781Sbostic keyword()
22439781Sbostic {
22539781Sbostic register int c;
22639781Sbostic char *t_cptr = cptr;
22739781Sbostic
22839781Sbostic c = *++cptr;
22939781Sbostic if (isalpha(c))
23039781Sbostic {
23139781Sbostic cinc = 0;
23239781Sbostic for (;;)
23339781Sbostic {
23439781Sbostic if (isalpha(c))
23539781Sbostic {
23639781Sbostic if (isupper(c)) c = tolower(c);
23739781Sbostic cachec(c);
23839781Sbostic }
23939781Sbostic else if (isdigit(c) || c == '_' || c == '.' || c == '$')
24039781Sbostic cachec(c);
24139781Sbostic else
24239781Sbostic break;
24339781Sbostic c = *++cptr;
24439781Sbostic }
24539781Sbostic cachec(NUL);
24639781Sbostic
24739781Sbostic if (strcmp(cache, "token") == 0 || strcmp(cache, "term") == 0)
24839781Sbostic return (TOKEN);
24939781Sbostic if (strcmp(cache, "type") == 0)
25039781Sbostic return (TYPE);
25139781Sbostic if (strcmp(cache, "left") == 0)
25239781Sbostic return (LEFT);
25339781Sbostic if (strcmp(cache, "right") == 0)
25439781Sbostic return (RIGHT);
25539781Sbostic if (strcmp(cache, "nonassoc") == 0 || strcmp(cache, "binary") == 0)
25639781Sbostic return (NONASSOC);
25739781Sbostic if (strcmp(cache, "start") == 0)
25839781Sbostic return (START);
25939781Sbostic if (strcmp(cache, "union") == 0)
26039781Sbostic return (UNION);
26139781Sbostic if (strcmp(cache, "ident") == 0)
26239781Sbostic return (IDENT);
26339781Sbostic }
26439781Sbostic else
26539781Sbostic {
26639781Sbostic ++cptr;
26739781Sbostic if (c == '{')
26839781Sbostic return (TEXT);
26939781Sbostic if (c == '%' || c == '\\')
27039781Sbostic return (MARK);
27139781Sbostic if (c == '<')
27239781Sbostic return (LEFT);
27339781Sbostic if (c == '>')
27439781Sbostic return (RIGHT);
27539781Sbostic if (c == '0')
27639781Sbostic return (TOKEN);
27739781Sbostic if (c == '2')
27839781Sbostic return (NONASSOC);
27939781Sbostic }
28039781Sbostic syntax_error(lineno, line, t_cptr);
28139781Sbostic /*NOTREACHED*/
28239781Sbostic }
28339781Sbostic
28439781Sbostic
copy_ident()28539781Sbostic copy_ident()
28639781Sbostic {
28739781Sbostic register int c;
28839781Sbostic register FILE *f = output_file;
28939781Sbostic
29039781Sbostic c = nextc();
29139781Sbostic if (c == EOF) unexpected_EOF();
29239781Sbostic if (c != '"') syntax_error(lineno, line, cptr);
29339781Sbostic ++outline;
29439781Sbostic fprintf(f, "#ident \"");
29539781Sbostic for (;;)
29639781Sbostic {
29739781Sbostic c = *++cptr;
29839781Sbostic if (c == '\n')
29939781Sbostic {
30039781Sbostic fprintf(f, "\"\n");
30139781Sbostic return;
30239781Sbostic }
30339781Sbostic putc(c, f);
30439781Sbostic if (c == '"')
30539781Sbostic {
30639781Sbostic putc('\n', f);
30739781Sbostic ++cptr;
30839781Sbostic return;
30939781Sbostic }
31039781Sbostic }
31139781Sbostic }
31239781Sbostic
31339781Sbostic
copy_text()31439781Sbostic copy_text()
31539781Sbostic {
31639781Sbostic register int c;
31739781Sbostic int quote;
31839781Sbostic register FILE *f = text_file;
31939781Sbostic int need_newline = 0;
32039781Sbostic int t_lineno = lineno;
32139781Sbostic char *t_line = dup_line();
32239781Sbostic char *t_cptr = t_line + (cptr - line - 2);
32339781Sbostic
32439781Sbostic if (*cptr == '\n')
32539781Sbostic {
32639781Sbostic get_line();
32739781Sbostic if (line == 0)
32839781Sbostic unterminated_text(t_lineno, t_line, t_cptr);
32939781Sbostic }
33039781Sbostic if (!lflag) fprintf(f, line_format, lineno, input_file_name);
33139781Sbostic
33239781Sbostic loop:
33339781Sbostic c = *cptr++;
33439781Sbostic switch (c)
33539781Sbostic {
33639781Sbostic case '\n':
33739781Sbostic next_line:
33839781Sbostic putc('\n', f);
33939781Sbostic need_newline = 0;
34039781Sbostic get_line();
34139781Sbostic if (line) goto loop;
34239781Sbostic unterminated_text(t_lineno, t_line, t_cptr);
34339781Sbostic
34439781Sbostic case '\'':
34539781Sbostic case '"':
34639781Sbostic {
34739781Sbostic int s_lineno = lineno;
34839781Sbostic char *s_line = dup_line();
34939781Sbostic char *s_cptr = s_line + (cptr - line - 1);
35039781Sbostic
35139781Sbostic quote = c;
35239781Sbostic putc(c, f);
35339781Sbostic for (;;)
35439781Sbostic {
35539781Sbostic c = *cptr++;
35639781Sbostic putc(c, f);
35739781Sbostic if (c == quote)
35839781Sbostic {
35939781Sbostic need_newline = 1;
36039781Sbostic FREE(s_line);
36139781Sbostic goto loop;
36239781Sbostic }
36339781Sbostic if (c == '\n')
36439781Sbostic unterminated_string(s_lineno, s_line, s_cptr);
36539781Sbostic if (c == '\\')
36639781Sbostic {
36739781Sbostic c = *cptr++;
36839781Sbostic putc(c, f);
36939781Sbostic if (c == '\n')
37039781Sbostic {
37139781Sbostic get_line();
37239781Sbostic if (line == 0)
37339781Sbostic unterminated_string(s_lineno, s_line, s_cptr);
37439781Sbostic }
37539781Sbostic }
37639781Sbostic }
37739781Sbostic }
37839781Sbostic
37939781Sbostic case '/':
38039781Sbostic putc(c, f);
38139781Sbostic need_newline = 1;
38239781Sbostic c = *cptr;
38339781Sbostic if (c == '/')
38439781Sbostic {
38539781Sbostic putc('*', f);
38640085Sbostic while ((c = *++cptr) != '\n')
38740085Sbostic {
38840085Sbostic if (c == '*' && cptr[1] == '/')
38940085Sbostic fprintf(f, "* ");
39040085Sbostic else
39140085Sbostic putc(c, f);
39240085Sbostic }
39339781Sbostic fprintf(f, "*/");
39439781Sbostic goto next_line;
39539781Sbostic }
39639781Sbostic if (c == '*')
39739781Sbostic {
39839781Sbostic int c_lineno = lineno;
39939781Sbostic char *c_line = dup_line();
40039781Sbostic char *c_cptr = c_line + (cptr - line - 1);
40139781Sbostic
40239781Sbostic putc('*', f);
40339781Sbostic ++cptr;
40439781Sbostic for (;;)
40539781Sbostic {
40639781Sbostic c = *cptr++;
40739781Sbostic putc(c, f);
40839781Sbostic if (c == '*' && *cptr == '/')
40939781Sbostic {
41039781Sbostic putc('/', f);
41139781Sbostic ++cptr;
41239781Sbostic FREE(c_line);
41339781Sbostic goto loop;
41439781Sbostic }
41539781Sbostic if (c == '\n')
41639781Sbostic {
41739781Sbostic get_line();
41839781Sbostic if (line == 0)
41939781Sbostic unterminated_comment(c_lineno, c_line, c_cptr);
42039781Sbostic }
42139781Sbostic }
42239781Sbostic }
42339781Sbostic need_newline = 1;
42439781Sbostic goto loop;
42539781Sbostic
42639781Sbostic case '%':
42739781Sbostic case '\\':
42839781Sbostic if (*cptr == '}')
42939781Sbostic {
43039781Sbostic if (need_newline) putc('\n', f);
43139781Sbostic ++cptr;
43239781Sbostic FREE(t_line);
43339781Sbostic return;
43439781Sbostic }
43539781Sbostic /* fall through */
43639781Sbostic
43739781Sbostic default:
43839781Sbostic putc(c, f);
43939781Sbostic need_newline = 1;
44039781Sbostic goto loop;
44139781Sbostic }
44239781Sbostic }
44339781Sbostic
44439781Sbostic
copy_union()44539781Sbostic copy_union()
44639781Sbostic {
44739781Sbostic register int c;
44839781Sbostic int quote;
44939781Sbostic int depth;
45039781Sbostic int u_lineno = lineno;
45139781Sbostic char *u_line = dup_line();
45239781Sbostic char *u_cptr = u_line + (cptr - line - 6);
45339781Sbostic
45439781Sbostic if (unionized) over_unionized(cptr - 6);
45539781Sbostic unionized = 1;
45639781Sbostic
45739781Sbostic if (!lflag)
45839781Sbostic fprintf(text_file, line_format, lineno, input_file_name);
45939781Sbostic
46039781Sbostic fprintf(text_file, "typedef union");
46139781Sbostic if (dflag) fprintf(union_file, "typedef union");
46239781Sbostic
46339781Sbostic depth = 0;
46439781Sbostic loop:
46539781Sbostic c = *cptr++;
46639781Sbostic putc(c, text_file);
46739781Sbostic if (dflag) putc(c, union_file);
46839781Sbostic switch (c)
46939781Sbostic {
47039781Sbostic case '\n':
47139781Sbostic next_line:
47239781Sbostic get_line();
47339781Sbostic if (line == 0) unterminated_union(u_lineno, u_line, u_cptr);
47439781Sbostic goto loop;
47539781Sbostic
47639781Sbostic case '{':
47739781Sbostic ++depth;
47839781Sbostic goto loop;
47939781Sbostic
48039781Sbostic case '}':
48139781Sbostic if (--depth == 0)
48239781Sbostic {
48339781Sbostic fprintf(text_file, " YYSTYPE;\n");
48439781Sbostic FREE(u_line);
48539781Sbostic return;
48639781Sbostic }
48739781Sbostic goto loop;
48839781Sbostic
48939781Sbostic case '\'':
49039781Sbostic case '"':
49139781Sbostic {
49239781Sbostic int s_lineno = lineno;
49339781Sbostic char *s_line = dup_line();
49439781Sbostic char *s_cptr = s_line + (cptr - line - 1);
49539781Sbostic
49639781Sbostic quote = c;
49739781Sbostic for (;;)
49839781Sbostic {
49939781Sbostic c = *cptr++;
50039781Sbostic putc(c, text_file);
50139781Sbostic if (dflag) putc(c, union_file);
50239781Sbostic if (c == quote)
50339781Sbostic {
50439781Sbostic FREE(s_line);
50539781Sbostic goto loop;
50639781Sbostic }
50739781Sbostic if (c == '\n')
50839781Sbostic unterminated_string(s_lineno, s_line, s_cptr);
50939781Sbostic if (c == '\\')
51039781Sbostic {
51139781Sbostic c = *cptr++;
51239781Sbostic putc(c, text_file);
51339781Sbostic if (dflag) putc(c, union_file);
51439781Sbostic if (c == '\n')
51539781Sbostic {
51639781Sbostic get_line();
51739781Sbostic if (line == 0)
51839781Sbostic unterminated_string(s_lineno, s_line, s_cptr);
51939781Sbostic }
52039781Sbostic }
52139781Sbostic }
52239781Sbostic }
52339781Sbostic
52439781Sbostic case '/':
52539781Sbostic c = *cptr;
52639781Sbostic if (c == '/')
52739781Sbostic {
52839781Sbostic putc('*', text_file);
52939781Sbostic if (dflag) putc('*', union_file);
53039781Sbostic while ((c = *++cptr) != '\n')
53139781Sbostic {
53240085Sbostic if (c == '*' && cptr[1] == '/')
53340085Sbostic {
53440085Sbostic fprintf(text_file, "* ");
53540085Sbostic if (dflag) fprintf(union_file, "* ");
53640085Sbostic }
53740085Sbostic else
53840085Sbostic {
53940085Sbostic putc(c, text_file);
54040085Sbostic if (dflag) putc(c, union_file);
54140085Sbostic }
54239781Sbostic }
54339781Sbostic fprintf(text_file, "*/\n");
54439781Sbostic if (dflag) fprintf(union_file, "*/\n");
54539781Sbostic goto next_line;
54639781Sbostic }
54739781Sbostic if (c == '*')
54839781Sbostic {
54939781Sbostic int c_lineno = lineno;
55039781Sbostic char *c_line = dup_line();
55139781Sbostic char *c_cptr = c_line + (cptr - line - 1);
55239781Sbostic
55339781Sbostic putc('*', text_file);
55439781Sbostic if (dflag) putc('*', union_file);
55540085Sbostic ++cptr;
55639781Sbostic for (;;)
55739781Sbostic {
55840085Sbostic c = *cptr++;
55939781Sbostic putc(c, text_file);
56039781Sbostic if (dflag) putc(c, union_file);
56140085Sbostic if (c == '*' && *cptr == '/')
56239781Sbostic {
56339781Sbostic putc('/', text_file);
56439781Sbostic if (dflag) putc('/', union_file);
56540085Sbostic ++cptr;
56639781Sbostic FREE(c_line);
56739781Sbostic goto loop;
56839781Sbostic }
56939781Sbostic if (c == '\n')
57039781Sbostic {
57139781Sbostic get_line();
57239781Sbostic if (line == 0)
57339781Sbostic unterminated_comment(c_lineno, c_line, c_cptr);
57439781Sbostic }
57539781Sbostic }
57639781Sbostic }
57739781Sbostic goto loop;
57839781Sbostic
57939781Sbostic default:
58039781Sbostic goto loop;
58139781Sbostic }
58239781Sbostic }
58339781Sbostic
58439781Sbostic
58539781Sbostic int
hexval(c)58639781Sbostic hexval(c)
58739781Sbostic int c;
58839781Sbostic {
58939781Sbostic if (c >= '0' && c <= '9')
59039781Sbostic return (c - '0');
59139781Sbostic if (c >= 'A' && c <= 'F')
59239781Sbostic return (c - 'A' + 10);
59339781Sbostic if (c >= 'a' && c <= 'f')
59439781Sbostic return (c - 'a' + 10);
59539781Sbostic return (-1);
59639781Sbostic }
59739781Sbostic
59839781Sbostic
59939781Sbostic bucket *
get_literal()60039781Sbostic get_literal()
60139781Sbostic {
60239781Sbostic register int c, quote;
60339781Sbostic register int i;
60439781Sbostic register int n;
60539781Sbostic register char *s;
60639781Sbostic register bucket *bp;
60739781Sbostic int s_lineno = lineno;
60839781Sbostic char *s_line = dup_line();
60939781Sbostic char *s_cptr = s_line + (cptr - line);
61039781Sbostic
61139781Sbostic quote = *cptr++;
61239781Sbostic cinc = 0;
61339781Sbostic for (;;)
61439781Sbostic {
61539781Sbostic c = *cptr++;
61639781Sbostic if (c == quote) break;
61739781Sbostic if (c == '\n') unterminated_string(s_lineno, s_line, s_cptr);
61839781Sbostic if (c == '\\')
61939781Sbostic {
62039781Sbostic char *c_cptr = cptr - 1;
62139781Sbostic
62239781Sbostic c = *cptr++;
62339781Sbostic switch (c)
62439781Sbostic {
62539781Sbostic case '\n':
62639781Sbostic get_line();
62739781Sbostic if (line == 0) unterminated_string(s_lineno, s_line, s_cptr);
62839781Sbostic continue;
62939781Sbostic
63039781Sbostic case '0': case '1': case '2': case '3':
63139781Sbostic case '4': case '5': case '6': case '7':
63239781Sbostic n = c - '0';
63340417Scorbett c = *cptr;
63439781Sbostic if (IS_OCTAL(c))
63539781Sbostic {
63639781Sbostic n = (n << 3) + (c - '0');
63740417Scorbett c = *++cptr;
63839781Sbostic if (IS_OCTAL(c))
63939781Sbostic {
64039781Sbostic n = (n << 3) + (c - '0');
64139781Sbostic ++cptr;
64239781Sbostic }
64339781Sbostic }
64439781Sbostic if (n > MAXCHAR) illegal_character(c_cptr);
64539781Sbostic c = n;
64639781Sbostic break;
64739781Sbostic
64839781Sbostic case 'x':
64939781Sbostic c = *cptr++;
65039781Sbostic n = hexval(c);
65139781Sbostic if (n < 0 || n >= 16)
65239781Sbostic illegal_character(c_cptr);
65339781Sbostic for (;;)
65439781Sbostic {
65540417Scorbett c = *cptr;
65639781Sbostic i = hexval(c);
65739781Sbostic if (i < 0 || i >= 16) break;
65840417Scorbett ++cptr;
65939781Sbostic n = (n << 4) + i;
66039781Sbostic if (n > MAXCHAR) illegal_character(c_cptr);
66139781Sbostic }
66239781Sbostic c = n;
66339781Sbostic break;
66439781Sbostic
66539781Sbostic case 'a': c = 7; break;
66639781Sbostic case 'b': c = '\b'; break;
66739781Sbostic case 'f': c = '\f'; break;
66839781Sbostic case 'n': c = '\n'; break;
66939781Sbostic case 'r': c = '\r'; break;
67039781Sbostic case 't': c = '\t'; break;
67139781Sbostic case 'v': c = '\v'; break;
67239781Sbostic }
67339781Sbostic }
67439781Sbostic cachec(c);
67539781Sbostic }
67639781Sbostic FREE(s_line);
67739781Sbostic
67839781Sbostic n = cinc;
67939781Sbostic s = MALLOC(n);
68039781Sbostic if (s == 0) no_space();
68139781Sbostic
68239781Sbostic for (i = 0; i < n; ++i)
68339781Sbostic s[i] = cache[i];
68439781Sbostic
68539781Sbostic cinc = 0;
68639781Sbostic if (n == 1)
68739781Sbostic cachec('\'');
68839781Sbostic else
68939781Sbostic cachec('"');
69039781Sbostic
69139781Sbostic for (i = 0; i < n; ++i)
69239781Sbostic {
69339781Sbostic c = ((unsigned char *)s)[i];
69439781Sbostic if (c == '\\' || c == cache[0])
69539781Sbostic {
69639781Sbostic cachec('\\');
69739781Sbostic cachec(c);
69839781Sbostic }
69939781Sbostic else if (isprint(c))
70039781Sbostic cachec(c);
70139781Sbostic else
70239781Sbostic {
70339781Sbostic cachec('\\');
70439781Sbostic switch (c)
70539781Sbostic {
70639781Sbostic case 7: cachec('a'); break;
70739781Sbostic case '\b': cachec('b'); break;
70839781Sbostic case '\f': cachec('f'); break;
70939781Sbostic case '\n': cachec('n'); break;
71039781Sbostic case '\r': cachec('r'); break;
71139781Sbostic case '\t': cachec('t'); break;
71239781Sbostic case '\v': cachec('v'); break;
71339781Sbostic default:
71440417Scorbett cachec(((c >> 6) & 7) + '0');
71540417Scorbett cachec(((c >> 3) & 7) + '0');
71640417Scorbett cachec((c & 7) + '0');
71739781Sbostic break;
71839781Sbostic }
71939781Sbostic }
72039781Sbostic }
72139781Sbostic
72239781Sbostic if (n == 1)
72339781Sbostic cachec('\'');
72439781Sbostic else
72539781Sbostic cachec('"');
72639781Sbostic
72739781Sbostic cachec(NUL);
72839781Sbostic bp = lookup(cache);
72939781Sbostic bp->class = TERM;
73039781Sbostic if (n == 1 && bp->value == UNDEFINED)
73139781Sbostic bp->value = *(unsigned char *)s;
73239781Sbostic FREE(s);
73339781Sbostic
73439781Sbostic return (bp);
73539781Sbostic }
73639781Sbostic
73739781Sbostic
73839781Sbostic int
is_reserved(name)73939781Sbostic is_reserved(name)
74039781Sbostic char *name;
74139781Sbostic {
74239781Sbostic char *s;
74339781Sbostic
74439781Sbostic if (strcmp(name, ".") == 0 ||
74539781Sbostic strcmp(name, "$accept") == 0 ||
74639781Sbostic strcmp(name, "$end") == 0)
74739781Sbostic return (1);
74839781Sbostic
74939781Sbostic if (name[0] == '$' && name[1] == '$' && isdigit(name[2]))
75039781Sbostic {
75139781Sbostic s = name + 3;
75239781Sbostic while (isdigit(*s)) ++s;
75339781Sbostic if (*s == NUL) return (1);
75439781Sbostic }
75539781Sbostic
75639781Sbostic return (0);
75739781Sbostic }
75839781Sbostic
75939781Sbostic
76039781Sbostic bucket *
get_name()76139781Sbostic get_name()
76239781Sbostic {
76339781Sbostic register int c;
76439781Sbostic
76539781Sbostic cinc = 0;
76639781Sbostic for (c = *cptr; IS_IDENT(c); c = *++cptr)
76739781Sbostic cachec(c);
76839781Sbostic cachec(NUL);
76939781Sbostic
77039781Sbostic if (is_reserved(cache)) used_reserved(cache);
77139781Sbostic
77239781Sbostic return (lookup(cache));
77339781Sbostic }
77439781Sbostic
77539781Sbostic
77639781Sbostic int
get_number()77739781Sbostic get_number()
77839781Sbostic {
77939781Sbostic register int c;
78039781Sbostic register int n;
78139781Sbostic
78239781Sbostic n = 0;
78339781Sbostic for (c = *cptr; isdigit(c); c = *++cptr)
78439781Sbostic n = 10*n + (c - '0');
78539781Sbostic
78639781Sbostic return (n);
78739781Sbostic }
78839781Sbostic
78939781Sbostic
79039781Sbostic char *
get_tag()79139781Sbostic get_tag()
79239781Sbostic {
79339781Sbostic register int c;
79439781Sbostic register int i;
79539781Sbostic register char *s;
79639781Sbostic int t_lineno = lineno;
79739781Sbostic char *t_line = dup_line();
79839781Sbostic char *t_cptr = t_line + (cptr - line);
79939781Sbostic
80039781Sbostic ++cptr;
80139781Sbostic c = nextc();
80239781Sbostic if (c == EOF) unexpected_EOF();
80339781Sbostic if (!isalpha(c) && c != '_' && c != '$')
80439781Sbostic illegal_tag(t_lineno, t_line, t_cptr);
80539781Sbostic
80639781Sbostic cinc = 0;
80739781Sbostic do { cachec(c); c = *++cptr; } while (IS_IDENT(c));
80839781Sbostic cachec(NUL);
80939781Sbostic
81039781Sbostic c = nextc();
81139781Sbostic if (c == EOF) unexpected_EOF();
81239781Sbostic if (c != '>')
81339781Sbostic illegal_tag(t_lineno, t_line, t_cptr);
81439781Sbostic ++cptr;
81539781Sbostic
81639781Sbostic for (i = 0; i < ntags; ++i)
81739781Sbostic {
81839781Sbostic if (strcmp(cache, tag_table[i]) == 0)
81939781Sbostic return (tag_table[i]);
82039781Sbostic }
82139781Sbostic
82239781Sbostic if (ntags >= tagmax)
82339781Sbostic {
82439781Sbostic tagmax += 16;
82539781Sbostic tag_table = (char **)
82639781Sbostic (tag_table ? REALLOC(tag_table, tagmax*sizeof(char *))
82739781Sbostic : MALLOC(tagmax*sizeof(char *)));
82839781Sbostic if (tag_table == 0) no_space();
82939781Sbostic }
83039781Sbostic
83139781Sbostic s = MALLOC(cinc);
83239781Sbostic if (s == 0) no_space();
83339781Sbostic strcpy(s, cache);
83439781Sbostic tag_table[ntags] = s;
83539781Sbostic ++ntags;
83639781Sbostic FREE(t_line);
83739781Sbostic return (s);
83839781Sbostic }
83939781Sbostic
84039781Sbostic
declare_tokens(assoc)84139781Sbostic declare_tokens(assoc)
84239781Sbostic int assoc;
84339781Sbostic {
84439781Sbostic register int c;
84539781Sbostic register bucket *bp;
84639781Sbostic int value;
84739781Sbostic char *tag = 0;
84839781Sbostic
84939781Sbostic if (assoc != TOKEN) ++prec;
85039781Sbostic
85139781Sbostic c = nextc();
85239781Sbostic if (c == EOF) unexpected_EOF();
85339781Sbostic if (c == '<')
85439781Sbostic {
85539781Sbostic tag = get_tag();
85639781Sbostic c = nextc();
85739781Sbostic if (c == EOF) unexpected_EOF();
85839781Sbostic }
85939781Sbostic
86039781Sbostic for (;;)
86139781Sbostic {
86239781Sbostic if (isalpha(c) || c == '_' || c == '.' || c == '$')
86339781Sbostic bp = get_name();
86439781Sbostic else if (c == '\'' || c == '"')
86539781Sbostic bp = get_literal();
86639781Sbostic else
86739781Sbostic return;
86839781Sbostic
86939781Sbostic if (bp == goal) tokenized_start(bp->name);
87039781Sbostic bp->class = TERM;
87139781Sbostic
87239781Sbostic if (tag)
87339781Sbostic {
87439781Sbostic if (bp->tag && tag != bp->tag)
87539781Sbostic retyped_warning(bp->name);
87639781Sbostic bp->tag = tag;
87739781Sbostic }
87839781Sbostic
87939781Sbostic if (assoc != TOKEN)
88039781Sbostic {
88139781Sbostic if (bp->prec && prec != bp->prec)
88239781Sbostic reprec_warning(bp->name);
88339781Sbostic bp->assoc = assoc;
88439781Sbostic bp->prec = prec;
88539781Sbostic }
88639781Sbostic
88739781Sbostic c = nextc();
88839781Sbostic if (c == EOF) unexpected_EOF();
88939781Sbostic value = UNDEFINED;
89039781Sbostic if (isdigit(c))
89139781Sbostic {
89239781Sbostic value = get_number();
89339781Sbostic if (bp->value != UNDEFINED && value != bp->value)
89439781Sbostic revalued_warning(bp->name);
89539781Sbostic bp->value = value;
89639781Sbostic c = nextc();
89739781Sbostic if (c == EOF) unexpected_EOF();
89839781Sbostic }
89939781Sbostic }
90039781Sbostic }
90139781Sbostic
90239781Sbostic
declare_types()90339781Sbostic declare_types()
90439781Sbostic {
90539781Sbostic register int c;
90639781Sbostic register bucket *bp;
90739781Sbostic char *tag;
90839781Sbostic
90939781Sbostic c = nextc();
91039781Sbostic if (c == EOF) unexpected_EOF();
91139781Sbostic if (c != '<') syntax_error(lineno, line, cptr);
91239781Sbostic tag = get_tag();
91339781Sbostic
91439781Sbostic for (;;)
91539781Sbostic {
91639781Sbostic c = nextc();
91739781Sbostic if (isalpha(c) || c == '_' || c == '.' || c == '$')
91839781Sbostic bp = get_name();
91939781Sbostic else if (c == '\'' || c == '"')
92039781Sbostic bp = get_literal();
92139781Sbostic else
92239781Sbostic return;
92339781Sbostic
92439781Sbostic if (bp->tag && tag != bp->tag)
92539781Sbostic retyped_warning(bp->name);
92639781Sbostic bp->tag = tag;
92739781Sbostic }
92839781Sbostic }
92939781Sbostic
93039781Sbostic
declare_start()93139781Sbostic declare_start()
93239781Sbostic {
93339781Sbostic register int c;
93439781Sbostic register bucket *bp;
93539781Sbostic
93639781Sbostic c = nextc();
93739781Sbostic if (c == EOF) unexpected_EOF();
93839781Sbostic if (!isalpha(c) && c != '_' && c != '.' && c != '$')
93939781Sbostic syntax_error(lineno, line, cptr);
94039781Sbostic bp = get_name();
94139781Sbostic if (bp->class == TERM)
94239781Sbostic terminal_start(bp->name);
94339781Sbostic if (goal && goal != bp)
94439781Sbostic restarted_warning();
94539781Sbostic goal = bp;
94639781Sbostic }
94739781Sbostic
94839781Sbostic
read_declarations()94939781Sbostic read_declarations()
95039781Sbostic {
95139781Sbostic register int c, k;
95239781Sbostic
95339781Sbostic cache_size = 256;
95439781Sbostic cache = MALLOC(cache_size);
95539781Sbostic if (cache == 0) no_space();
95639781Sbostic
95739781Sbostic for (;;)
95839781Sbostic {
95939781Sbostic c = nextc();
96039781Sbostic if (c == EOF) unexpected_EOF();
96139781Sbostic if (c != '%') syntax_error(lineno, line, cptr);
96239781Sbostic switch (k = keyword())
96339781Sbostic {
96439781Sbostic case MARK:
96539781Sbostic return;
96639781Sbostic
96739781Sbostic case IDENT:
96839781Sbostic copy_ident();
96939781Sbostic break;
97039781Sbostic
97139781Sbostic case TEXT:
97239781Sbostic copy_text();
97339781Sbostic break;
97439781Sbostic
97539781Sbostic case UNION:
97639781Sbostic copy_union();
97739781Sbostic break;
97839781Sbostic
97939781Sbostic case TOKEN:
98039781Sbostic case LEFT:
98139781Sbostic case RIGHT:
98239781Sbostic case NONASSOC:
98339781Sbostic declare_tokens(k);
98439781Sbostic break;
98539781Sbostic
98639781Sbostic case TYPE:
98739781Sbostic declare_types();
98839781Sbostic break;
98939781Sbostic
99039781Sbostic case START:
99139781Sbostic declare_start();
99239781Sbostic break;
99339781Sbostic }
99439781Sbostic }
99539781Sbostic }
99639781Sbostic
99739781Sbostic
initialize_grammar()99839781Sbostic initialize_grammar()
99939781Sbostic {
100039781Sbostic nitems = 4;
100139781Sbostic maxitems = 300;
100239781Sbostic pitem = (bucket **) MALLOC(maxitems*sizeof(bucket *));
100339781Sbostic if (pitem == 0) no_space();
100439781Sbostic pitem[0] = 0;
100539781Sbostic pitem[1] = 0;
100639781Sbostic pitem[2] = 0;
100739781Sbostic pitem[3] = 0;
100839781Sbostic
100939781Sbostic nrules = 3;
101039781Sbostic maxrules = 100;
101139781Sbostic plhs = (bucket **) MALLOC(maxrules*sizeof(bucket *));
101239781Sbostic if (plhs == 0) no_space();
101339781Sbostic plhs[0] = 0;
101439781Sbostic plhs[1] = 0;
101539781Sbostic plhs[2] = 0;
101639781Sbostic rprec = (short *) MALLOC(maxrules*sizeof(short));
101739781Sbostic if (rprec == 0) no_space();
101839781Sbostic rprec[0] = 0;
101939781Sbostic rprec[1] = 0;
102039781Sbostic rprec[2] = 0;
102139781Sbostic rassoc = (char *) MALLOC(maxrules*sizeof(char));
102239781Sbostic if (rassoc == 0) no_space();
102339781Sbostic rassoc[0] = TOKEN;
102439781Sbostic rassoc[1] = TOKEN;
102539781Sbostic rassoc[2] = TOKEN;
102639781Sbostic }
102739781Sbostic
102839781Sbostic
expand_items()102939781Sbostic expand_items()
103039781Sbostic {
103139781Sbostic maxitems += 300;
103239781Sbostic pitem = (bucket **) REALLOC(pitem, maxitems*sizeof(bucket *));
103339781Sbostic if (pitem == 0) no_space();
103439781Sbostic }
103539781Sbostic
103639781Sbostic
expand_rules()103739781Sbostic expand_rules()
103839781Sbostic {
103939781Sbostic maxrules += 100;
104039781Sbostic plhs = (bucket **) REALLOC(plhs, maxrules*sizeof(bucket *));
104139781Sbostic if (plhs == 0) no_space();
104239781Sbostic rprec = (short *) REALLOC(rprec, maxrules*sizeof(short));
104339781Sbostic if (rprec == 0) no_space();
104439781Sbostic rassoc = (char *) REALLOC(rassoc, maxrules*sizeof(char));
104539781Sbostic if (rassoc == 0) no_space();
104639781Sbostic }
104739781Sbostic
104839781Sbostic
advance_to_start()104939781Sbostic advance_to_start()
105039781Sbostic {
105139781Sbostic register int c;
105239781Sbostic register bucket *bp;
105339781Sbostic char *s_cptr;
105439781Sbostic int s_lineno;
105539781Sbostic
105639781Sbostic for (;;)
105739781Sbostic {
105839781Sbostic c = nextc();
105939781Sbostic if (c != '%') break;
106039781Sbostic s_cptr = cptr;
106139781Sbostic switch (keyword())
106239781Sbostic {
106339781Sbostic case MARK:
106439781Sbostic no_grammar();
106539781Sbostic
106639781Sbostic case TEXT:
106739781Sbostic copy_text();
106839781Sbostic break;
106939781Sbostic
107039781Sbostic case START:
107139781Sbostic declare_start();
107239781Sbostic break;
107339781Sbostic
107439781Sbostic default:
107539781Sbostic syntax_error(lineno, line, s_cptr);
107639781Sbostic }
107739781Sbostic }
107839781Sbostic
107939781Sbostic c = nextc();
108039781Sbostic if (!isalpha(c) && c != '_' && c != '.' && c != '_')
108139781Sbostic syntax_error(lineno, line, cptr);
108239781Sbostic bp = get_name();
108339781Sbostic if (goal == 0)
108439781Sbostic {
108539781Sbostic if (bp->class == TERM)
108639781Sbostic terminal_start(bp->name);
108739781Sbostic goal = bp;
108839781Sbostic }
108939781Sbostic
109039781Sbostic s_lineno = lineno;
109139781Sbostic c = nextc();
109239781Sbostic if (c == EOF) unexpected_EOF();
109339781Sbostic if (c != ':') syntax_error(lineno, line, cptr);
109439781Sbostic start_rule(bp, s_lineno);
109539781Sbostic ++cptr;
109639781Sbostic }
109739781Sbostic
109839781Sbostic
start_rule(bp,s_lineno)109939781Sbostic start_rule(bp, s_lineno)
110039781Sbostic register bucket *bp;
110139781Sbostic int s_lineno;
110239781Sbostic {
110339781Sbostic if (bp->class == TERM)
110439781Sbostic terminal_lhs(s_lineno);
110539781Sbostic bp->class = NONTERM;
110639781Sbostic if (nrules >= maxrules)
110739781Sbostic expand_rules();
110839781Sbostic plhs[nrules] = bp;
110939781Sbostic rprec[nrules] = UNDEFINED;
111039781Sbostic rassoc[nrules] = TOKEN;
111139781Sbostic }
111239781Sbostic
111339781Sbostic
end_rule()111439781Sbostic end_rule()
111539781Sbostic {
111639781Sbostic register int i;
111739781Sbostic
111839781Sbostic if (!last_was_action && plhs[nrules]->tag)
111939781Sbostic {
112039781Sbostic for (i = nitems - 1; pitem[i]; --i) continue;
112140759Scorbett if (pitem[i+1] == 0 || pitem[i+1]->tag != plhs[nrules]->tag)
112239781Sbostic default_action_warning();
112339781Sbostic }
112439781Sbostic
112539781Sbostic last_was_action = 0;
112639781Sbostic if (nitems >= maxitems) expand_items();
112739781Sbostic pitem[nitems] = 0;
112839781Sbostic ++nitems;
112939781Sbostic ++nrules;
113039781Sbostic }
113139781Sbostic
113239781Sbostic
insert_empty_rule()113339781Sbostic insert_empty_rule()
113439781Sbostic {
113539781Sbostic register bucket *bp, **bpp;
113639781Sbostic
113739781Sbostic assert(cache);
113839781Sbostic sprintf(cache, "$$%d", ++gensym);
113939781Sbostic bp = make_bucket(cache);
114039781Sbostic last_symbol->next = bp;
114139781Sbostic last_symbol = bp;
114239781Sbostic bp->tag = plhs[nrules]->tag;
114339781Sbostic bp->class = NONTERM;
114439781Sbostic
114539781Sbostic if ((nitems += 2) > maxitems)
114639781Sbostic expand_items();
114739781Sbostic bpp = pitem + nitems - 1;
114839781Sbostic *bpp-- = bp;
114939781Sbostic while (bpp[0] = bpp[-1]) --bpp;
115039781Sbostic
115139781Sbostic if (++nrules >= maxrules)
115239781Sbostic expand_rules();
115339781Sbostic plhs[nrules] = plhs[nrules-1];
115439781Sbostic plhs[nrules-1] = bp;
115539781Sbostic rprec[nrules] = rprec[nrules-1];
115639781Sbostic rprec[nrules-1] = 0;
115739781Sbostic rassoc[nrules] = rassoc[nrules-1];
115839781Sbostic rassoc[nrules-1] = TOKEN;
115939781Sbostic }
116039781Sbostic
116139781Sbostic
add_symbol()116239781Sbostic add_symbol()
116339781Sbostic {
116439781Sbostic register int c;
116539781Sbostic register bucket *bp;
116639781Sbostic int s_lineno = lineno;
116739781Sbostic
116839781Sbostic c = *cptr;
116939781Sbostic if (c == '\'' || c == '"')
117039781Sbostic bp = get_literal();
117139781Sbostic else
117239781Sbostic bp = get_name();
117339781Sbostic
117439781Sbostic c = nextc();
117539781Sbostic if (c == ':')
117639781Sbostic {
117739781Sbostic end_rule();
117839781Sbostic start_rule(bp, s_lineno);
117939781Sbostic ++cptr;
118039781Sbostic return;
118139781Sbostic }
118239781Sbostic
118339781Sbostic if (last_was_action)
118439781Sbostic insert_empty_rule();
118539781Sbostic last_was_action = 0;
118639781Sbostic
118739781Sbostic if (++nitems > maxitems)
118839781Sbostic expand_items();
118939781Sbostic pitem[nitems-1] = bp;
119039781Sbostic }
119139781Sbostic
119239781Sbostic
copy_action()119339781Sbostic copy_action()
119439781Sbostic {
119539781Sbostic register int c;
119639781Sbostic register int i, n;
119739781Sbostic int depth;
119839781Sbostic int quote;
119939781Sbostic char *tag;
120039781Sbostic register FILE *f = action_file;
120139781Sbostic int a_lineno = lineno;
120239781Sbostic char *a_line = dup_line();
120339781Sbostic char *a_cptr = a_line + (cptr - line);
120439781Sbostic
120539781Sbostic if (last_was_action)
120639781Sbostic insert_empty_rule();
120739781Sbostic last_was_action = 1;
120839781Sbostic
120939781Sbostic fprintf(f, "case %d:\n", nrules - 2);
121039781Sbostic if (!lflag)
121139781Sbostic fprintf(f, line_format, lineno, input_file_name);
121239781Sbostic if (*cptr == '=') ++cptr;
121339781Sbostic
121439781Sbostic n = 0;
121539781Sbostic for (i = nitems - 1; pitem[i]; --i) ++n;
121639781Sbostic
121739781Sbostic depth = 0;
121839781Sbostic loop:
121939781Sbostic c = *cptr;
122039781Sbostic if (c == '$')
122139781Sbostic {
122239781Sbostic if (cptr[1] == '<')
122339781Sbostic {
122439781Sbostic int d_lineno = lineno;
122539781Sbostic char *d_line = dup_line();
122639781Sbostic char *d_cptr = d_line + (cptr - line);
122739781Sbostic
122839781Sbostic ++cptr;
122939781Sbostic tag = get_tag();
123039781Sbostic c = *cptr;
123139781Sbostic if (c == '$')
123239781Sbostic {
1233*46064Scorbett fprintf(f, "yyval.%s", tag);
123439781Sbostic ++cptr;
123539781Sbostic FREE(d_line);
123639781Sbostic goto loop;
123739781Sbostic }
123839781Sbostic else if (isdigit(c))
123939781Sbostic {
124039781Sbostic i = get_number();
124139781Sbostic if (i > n) dollar_warning(d_lineno, i);
1242*46064Scorbett fprintf(f, "yyvsp[%d].%s", i - n, tag);
124339781Sbostic FREE(d_line);
124439781Sbostic goto loop;
124539781Sbostic }
124639781Sbostic else if (c == '-' && isdigit(cptr[1]))
124739781Sbostic {
124839781Sbostic ++cptr;
124939781Sbostic i = -get_number() - n;
1250*46064Scorbett fprintf(f, "yyvsp[%d].%s", i, tag);
125139781Sbostic FREE(d_line);
125239781Sbostic goto loop;
125339781Sbostic }
125439781Sbostic else
125539781Sbostic dollar_error(d_lineno, d_line, d_cptr);
125639781Sbostic }
125739781Sbostic else if (cptr[1] == '$')
125839781Sbostic {
125939781Sbostic if (ntags)
126039781Sbostic {
126139781Sbostic tag = plhs[nrules]->tag;
126239781Sbostic if (tag == 0) untyped_lhs();
1263*46064Scorbett fprintf(f, "yyval.%s", tag);
126439781Sbostic }
126539781Sbostic else
1266*46064Scorbett fprintf(f, "yyval");
126739781Sbostic cptr += 2;
126839781Sbostic goto loop;
126939781Sbostic }
127039781Sbostic else if (isdigit(cptr[1]))
127139781Sbostic {
127239781Sbostic ++cptr;
127339781Sbostic i = get_number();
127439781Sbostic if (ntags)
127539781Sbostic {
127639781Sbostic if (i <= 0 || i > n)
127739781Sbostic unknown_rhs(i);
127839781Sbostic tag = pitem[nitems + i - n - 1]->tag;
127939781Sbostic if (tag == 0) untyped_rhs(i, pitem[nitems + i - n - 1]->name);
1280*46064Scorbett fprintf(f, "yyvsp[%d].%s", i - n, tag);
128139781Sbostic }
128239781Sbostic else
128339781Sbostic {
128439781Sbostic if (i > n)
128539781Sbostic dollar_warning(lineno, i);
128639781Sbostic fprintf(f, "yyvsp[%d]", i - n);
128739781Sbostic }
128839781Sbostic goto loop;
128939781Sbostic }
129039781Sbostic else if (cptr[1] == '-')
129139781Sbostic {
129239781Sbostic cptr += 2;
129339781Sbostic i = get_number();
129439781Sbostic if (ntags)
129539781Sbostic unknown_rhs(-i);
129639781Sbostic fprintf(f, "yyvsp[%d]", -i - n);
129739781Sbostic goto loop;
129839781Sbostic }
129939781Sbostic }
130039781Sbostic if (isalpha(c) || c == '_' || c == '$')
130139781Sbostic {
130239781Sbostic do
130339781Sbostic {
130439781Sbostic putc(c, f);
130539781Sbostic c = *++cptr;
130639781Sbostic } while (isalnum(c) || c == '_' || c == '$');
130739781Sbostic goto loop;
130839781Sbostic }
130939781Sbostic putc(c, f);
131039781Sbostic ++cptr;
131139781Sbostic switch (c)
131239781Sbostic {
131339781Sbostic case '\n':
131439781Sbostic next_line:
131539781Sbostic get_line();
131639781Sbostic if (line) goto loop;
131739781Sbostic unterminated_action(a_lineno, a_line, a_cptr);
131839781Sbostic
131939781Sbostic case ';':
132039781Sbostic if (depth > 0) goto loop;
132139781Sbostic fprintf(f, "\nbreak;\n");
132239781Sbostic return;
132339781Sbostic
132439781Sbostic case '{':
132539781Sbostic ++depth;
132639781Sbostic goto loop;
132739781Sbostic
132839781Sbostic case '}':
132939781Sbostic if (--depth > 0) goto loop;
133039781Sbostic fprintf(f, "\nbreak;\n");
133139781Sbostic return;
133239781Sbostic
133339781Sbostic case '\'':
133439781Sbostic case '"':
133539781Sbostic {
133639781Sbostic int s_lineno = lineno;
133739781Sbostic char *s_line = dup_line();
133839781Sbostic char *s_cptr = s_line + (cptr - line - 1);
133939781Sbostic
134039781Sbostic quote = c;
134139781Sbostic for (;;)
134239781Sbostic {
134339781Sbostic c = *cptr++;
134439781Sbostic putc(c, f);
134539781Sbostic if (c == quote)
134639781Sbostic {
134739781Sbostic FREE(s_line);
134839781Sbostic goto loop;
134939781Sbostic }
135039781Sbostic if (c == '\n')
135139781Sbostic unterminated_string(s_lineno, s_line, s_cptr);
135239781Sbostic if (c == '\\')
135339781Sbostic {
135439781Sbostic c = *cptr++;
135539781Sbostic putc(c, f);
135639781Sbostic if (c == '\n')
135739781Sbostic {
135839781Sbostic get_line();
135939781Sbostic if (line == 0)
136039781Sbostic unterminated_string(s_lineno, s_line, s_cptr);
136139781Sbostic }
136239781Sbostic }
136339781Sbostic }
136439781Sbostic }
136539781Sbostic
136639781Sbostic case '/':
136739781Sbostic c = *cptr;
136839781Sbostic if (c == '/')
136939781Sbostic {
137039781Sbostic putc('*', f);
137140085Sbostic while ((c = *++cptr) != '\n')
137240085Sbostic {
137340085Sbostic if (c == '*' && cptr[1] == '/')
137440085Sbostic fprintf(f, "* ");
137540085Sbostic else
137640085Sbostic putc(c, f);
137740085Sbostic }
137839781Sbostic fprintf(f, "*/\n");
137939781Sbostic goto next_line;
138039781Sbostic }
138139781Sbostic if (c == '*')
138239781Sbostic {
138339781Sbostic int c_lineno = lineno;
138439781Sbostic char *c_line = dup_line();
138539781Sbostic char *c_cptr = c_line + (cptr - line - 1);
138639781Sbostic
138739781Sbostic putc('*', f);
138840085Sbostic ++cptr;
138939781Sbostic for (;;)
139039781Sbostic {
139140085Sbostic c = *cptr++;
139239781Sbostic putc(c, f);
139340085Sbostic if (c == '*' && *cptr == '/')
139439781Sbostic {
139539781Sbostic putc('/', f);
139640085Sbostic ++cptr;
139739781Sbostic FREE(c_line);
139839781Sbostic goto loop;
139939781Sbostic }
140039781Sbostic if (c == '\n')
140139781Sbostic {
140239781Sbostic get_line();
140339781Sbostic if (line == 0)
140439781Sbostic unterminated_comment(c_lineno, c_line, c_cptr);
140539781Sbostic }
140639781Sbostic }
140739781Sbostic }
140839781Sbostic goto loop;
140939781Sbostic
141039781Sbostic default:
141139781Sbostic goto loop;
141239781Sbostic }
141339781Sbostic }
141439781Sbostic
141539781Sbostic
141639781Sbostic int
mark_symbol()141739781Sbostic mark_symbol()
141839781Sbostic {
141939781Sbostic register int c;
142039781Sbostic register bucket *bp;
142139781Sbostic
142239781Sbostic c = cptr[1];
142339781Sbostic if (c == '%' || c == '\\')
142439781Sbostic {
142539781Sbostic cptr += 2;
142639781Sbostic return (1);
142739781Sbostic }
142839781Sbostic
142939781Sbostic if (c == '=')
143039781Sbostic cptr += 2;
143139781Sbostic else if ((c == 'p' || c == 'P') &&
143239781Sbostic ((c = cptr[2]) == 'r' || c == 'R') &&
143339781Sbostic ((c = cptr[3]) == 'e' || c == 'E') &&
143439781Sbostic ((c = cptr[4]) == 'c' || c == 'C') &&
143539781Sbostic ((c = cptr[5], !IS_IDENT(c))))
143639781Sbostic cptr += 5;
143739781Sbostic else
143839781Sbostic syntax_error(lineno, line, cptr);
143939781Sbostic
144039781Sbostic c = nextc();
144139781Sbostic if (isalpha(c) || c == '_' || c == '.' || c == '$')
144239781Sbostic bp = get_name();
144339781Sbostic else if (c == '\'' || c == '"')
144439781Sbostic bp = get_literal();
144539781Sbostic else
144639781Sbostic {
144739781Sbostic syntax_error(lineno, line, cptr);
144839781Sbostic /*NOTREACHED*/
144939781Sbostic }
145039781Sbostic
145139781Sbostic if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules])
145239781Sbostic prec_redeclared();
145339781Sbostic
145439781Sbostic rprec[nrules] = bp->prec;
145539781Sbostic rassoc[nrules] = bp->assoc;
145639781Sbostic return (0);
145739781Sbostic }
145839781Sbostic
145939781Sbostic
read_grammar()146039781Sbostic read_grammar()
146139781Sbostic {
146239781Sbostic register int c;
146339781Sbostic
146439781Sbostic initialize_grammar();
146539781Sbostic advance_to_start();
146639781Sbostic
146739781Sbostic for (;;)
146839781Sbostic {
146939781Sbostic c = nextc();
147039781Sbostic if (c == EOF) break;
147139781Sbostic if (isalpha(c) || c == '_' || c == '.' || c == '$' || c == '\'' ||
147239781Sbostic c == '"')
147339781Sbostic add_symbol();
147439781Sbostic else if (c == '{' || c == '=')
147539781Sbostic copy_action();
147639781Sbostic else if (c == '|')
147739781Sbostic {
147839781Sbostic end_rule();
147939781Sbostic start_rule(plhs[nrules-1], 0);
148039781Sbostic ++cptr;
148139781Sbostic }
148239781Sbostic else if (c == '%')
148339781Sbostic {
148439781Sbostic if (mark_symbol()) break;
148539781Sbostic }
148639781Sbostic else
148739781Sbostic syntax_error(lineno, line, cptr);
148839781Sbostic }
148939781Sbostic end_rule();
149039781Sbostic }
149139781Sbostic
149239781Sbostic
free_tags()149339781Sbostic free_tags()
149439781Sbostic {
149539781Sbostic register int i;
149639781Sbostic
149739781Sbostic if (tag_table == 0) return;
149839781Sbostic
149939781Sbostic for (i = 0; i < ntags; ++i)
150039781Sbostic {
150139781Sbostic assert(tag_table[i]);
150239781Sbostic FREE(tag_table[i]);
150339781Sbostic }
150439781Sbostic FREE(tag_table);
150539781Sbostic }
150639781Sbostic
150739781Sbostic
pack_names()150839781Sbostic pack_names()
150939781Sbostic {
151039781Sbostic register bucket *bp;
151139781Sbostic register char *p, *s, *t;
151239781Sbostic
151339781Sbostic name_pool_size = 13; /* 13 == sizeof("$end") + sizeof("$accept") */
151439781Sbostic for (bp = first_symbol; bp; bp = bp->next)
151539781Sbostic name_pool_size += strlen(bp->name) + 1;
151639781Sbostic name_pool = MALLOC(name_pool_size);
151739781Sbostic if (name_pool == 0) no_space();
151839781Sbostic
151939781Sbostic strcpy(name_pool, "$accept");
152039781Sbostic strcpy(name_pool+8, "$end");
152139781Sbostic t = name_pool + 13;
152239781Sbostic for (bp = first_symbol; bp; bp = bp->next)
152339781Sbostic {
152439781Sbostic p = t;
152539781Sbostic s = bp->name;
152639781Sbostic while (*t++ = *s++) continue;
152739781Sbostic FREE(bp->name);
152839781Sbostic bp->name = p;
152939781Sbostic }
153039781Sbostic }
153139781Sbostic
153239781Sbostic
check_symbols()153339781Sbostic check_symbols()
153439781Sbostic {
153539781Sbostic register bucket *bp;
153639781Sbostic
153739781Sbostic if (goal->class == UNKNOWN)
153839781Sbostic undefined_goal(goal->name);
153939781Sbostic
154039781Sbostic for (bp = first_symbol; bp; bp = bp->next)
154139781Sbostic {
154239781Sbostic if (bp->class == UNKNOWN)
154339781Sbostic {
154439781Sbostic undefined_symbol_warning(bp->name);
154539781Sbostic bp->class = TERM;
154639781Sbostic }
154739781Sbostic }
154839781Sbostic }
154939781Sbostic
155039781Sbostic
pack_symbols()155139781Sbostic pack_symbols()
155239781Sbostic {
155339781Sbostic register bucket *bp;
155439781Sbostic register bucket **v;
155539781Sbostic register int i, j, k, n;
155639781Sbostic
155739781Sbostic nsyms = 2;
155839781Sbostic ntokens = 1;
155939781Sbostic for (bp = first_symbol; bp; bp = bp->next)
156039781Sbostic {
156139781Sbostic ++nsyms;
156239781Sbostic if (bp->class == TERM) ++ntokens;
156339781Sbostic }
156439781Sbostic start_symbol = ntokens;
156539781Sbostic nvars = nsyms - ntokens;
156639781Sbostic
156739781Sbostic symbol_name = (char **) MALLOC(nsyms*sizeof(char *));
156839781Sbostic if (symbol_name == 0) no_space();
156939781Sbostic symbol_value = (short *) MALLOC(nsyms*sizeof(short));
157039781Sbostic if (symbol_value == 0) no_space();
157139781Sbostic symbol_prec = (short *) MALLOC(nsyms*sizeof(short));
157239781Sbostic if (symbol_prec == 0) no_space();
157339781Sbostic symbol_assoc = MALLOC(nsyms);
157439781Sbostic if (symbol_assoc == 0) no_space();
157539781Sbostic
157639781Sbostic v = (bucket **) MALLOC(nsyms*sizeof(bucket *));
157739781Sbostic if (v == 0) no_space();
157839781Sbostic
157939781Sbostic v[0] = 0;
158039781Sbostic v[start_symbol] = 0;
158139781Sbostic
158239781Sbostic i = 1;
158339781Sbostic j = start_symbol + 1;
158439781Sbostic for (bp = first_symbol; bp; bp = bp->next)
158539781Sbostic {
158639781Sbostic if (bp->class == TERM)
158739781Sbostic v[i++] = bp;
158839781Sbostic else
158939781Sbostic v[j++] = bp;
159039781Sbostic }
159139781Sbostic assert(i == ntokens && j == nsyms);
159239781Sbostic
159339781Sbostic for (i = 1; i < ntokens; ++i)
159439781Sbostic v[i]->index = i;
159539781Sbostic
159639781Sbostic goal->index = start_symbol + 1;
159739781Sbostic k = start_symbol + 2;
159839781Sbostic while (++i < nsyms)
159939781Sbostic if (v[i] != goal)
160039781Sbostic {
160139781Sbostic v[i]->index = k;
160239781Sbostic ++k;
160339781Sbostic }
160439781Sbostic
160539781Sbostic goal->value = 0;
160639781Sbostic k = 1;
160739781Sbostic for (i = start_symbol + 1; i < nsyms; ++i)
160839781Sbostic {
160939781Sbostic if (v[i] != goal)
161039781Sbostic {
161139781Sbostic v[i]->value = k;
161239781Sbostic ++k;
161339781Sbostic }
161439781Sbostic }
161539781Sbostic
161639781Sbostic k = 0;
161739781Sbostic for (i = 1; i < ntokens; ++i)
161839781Sbostic {
161939781Sbostic n = v[i]->value;
162039781Sbostic if (n > 256)
162139781Sbostic {
162239781Sbostic for (j = k++; j > 0 && symbol_value[j-1] > n; --j)
162339781Sbostic symbol_value[j] = symbol_value[j-1];
162439781Sbostic symbol_value[j] = n;
162539781Sbostic }
162639781Sbostic }
162739781Sbostic
162839781Sbostic if (v[1]->value == UNDEFINED)
162939781Sbostic v[1]->value = 256;
163039781Sbostic
163139781Sbostic j = 0;
163239781Sbostic n = 257;
163339781Sbostic for (i = 2; i < ntokens; ++i)
163439781Sbostic {
163539781Sbostic if (v[i]->value == UNDEFINED)
163639781Sbostic {
163739781Sbostic while (j < k && n == symbol_value[j])
163839781Sbostic {
163939781Sbostic while (++j < k && n == symbol_value[j]) continue;
164039781Sbostic ++n;
164139781Sbostic }
164239781Sbostic v[i]->value = n;
164339781Sbostic ++n;
164439781Sbostic }
164539781Sbostic }
164639781Sbostic
164739781Sbostic symbol_name[0] = name_pool + 8;
164839781Sbostic symbol_value[0] = 0;
164939781Sbostic symbol_prec[0] = 0;
165039781Sbostic symbol_assoc[0] = TOKEN;
165139781Sbostic for (i = 1; i < ntokens; ++i)
165239781Sbostic {
165339781Sbostic symbol_name[i] = v[i]->name;
165439781Sbostic symbol_value[i] = v[i]->value;
165539781Sbostic symbol_prec[i] = v[i]->prec;
165639781Sbostic symbol_assoc[i] = v[i]->assoc;
165739781Sbostic }
165839781Sbostic symbol_name[start_symbol] = name_pool;
165939781Sbostic symbol_value[start_symbol] = -1;
166039781Sbostic symbol_prec[start_symbol] = 0;
166139781Sbostic symbol_assoc[start_symbol] = TOKEN;
166239781Sbostic for (++i; i < nsyms; ++i)
166339781Sbostic {
166439781Sbostic k = v[i]->index;
166539781Sbostic symbol_name[k] = v[i]->name;
166639781Sbostic symbol_value[k] = v[i]->value;
166739781Sbostic symbol_prec[k] = v[i]->prec;
166839781Sbostic symbol_assoc[k] = v[i]->assoc;
166939781Sbostic }
167039781Sbostic
167139781Sbostic FREE(v);
167239781Sbostic }
167339781Sbostic
167439781Sbostic
pack_grammar()167539781Sbostic pack_grammar()
167639781Sbostic {
167739781Sbostic register int i, j;
167839781Sbostic int assoc, prec;
167939781Sbostic
168039781Sbostic ritem = (short *) MALLOC(nitems*sizeof(short));
168139781Sbostic if (ritem == 0) no_space();
168239781Sbostic rlhs = (short *) MALLOC(nrules*sizeof(short));
168339781Sbostic if (rlhs == 0) no_space();
168439781Sbostic rrhs = (short *) MALLOC((nrules+1)*sizeof(short));
168539781Sbostic if (rrhs == 0) no_space();
168639781Sbostic rprec = (short *) REALLOC(rprec, nrules*sizeof(short));
168739781Sbostic if (rprec == 0) no_space();
168839781Sbostic rassoc = REALLOC(rassoc, nrules);
168939781Sbostic if (rassoc == 0) no_space();
169039781Sbostic
169139781Sbostic ritem[0] = -1;
169239781Sbostic ritem[1] = goal->index;
169339781Sbostic ritem[2] = 0;
169439781Sbostic ritem[3] = -2;
169539781Sbostic rlhs[0] = 0;
169639781Sbostic rlhs[1] = 0;
169739781Sbostic rlhs[2] = start_symbol;
169839781Sbostic rrhs[0] = 0;
169939781Sbostic rrhs[1] = 0;
170039781Sbostic rrhs[2] = 1;
170139781Sbostic
170239781Sbostic j = 4;
170339781Sbostic for (i = 3; i < nrules; ++i)
170439781Sbostic {
170539781Sbostic rlhs[i] = plhs[i]->index;
170639781Sbostic rrhs[i] = j;
170739781Sbostic assoc = TOKEN;
170839781Sbostic prec = 0;
170939781Sbostic while (pitem[j])
171039781Sbostic {
171139781Sbostic ritem[j] = pitem[j]->index;
171239781Sbostic if (pitem[j]->class == TERM)
171339781Sbostic {
171439781Sbostic prec = pitem[j]->prec;
171539781Sbostic assoc = pitem[j]->assoc;
171639781Sbostic }
171739781Sbostic ++j;
171839781Sbostic }
171939781Sbostic ritem[j] = -i;
172039781Sbostic ++j;
172139781Sbostic if (rprec[i] == UNDEFINED)
172239781Sbostic {
172339781Sbostic rprec[i] = prec;
172439781Sbostic rassoc[i] = assoc;
172539781Sbostic }
172639781Sbostic }
172739781Sbostic rrhs[i] = j;
172839781Sbostic
172939781Sbostic FREE(plhs);
173039781Sbostic FREE(pitem);
173139781Sbostic }
173239781Sbostic
173339781Sbostic
print_grammar()173439781Sbostic print_grammar()
173539781Sbostic {
173639781Sbostic register int i, j, k;
173739781Sbostic int spacing;
173839781Sbostic register FILE *f = verbose_file;
173939781Sbostic
174039781Sbostic if (!vflag) return;
174139781Sbostic
174239781Sbostic k = 1;
174339781Sbostic for (i = 2; i < nrules; ++i)
174439781Sbostic {
174539781Sbostic if (rlhs[i] != rlhs[i-1])
174639781Sbostic {
174739781Sbostic if (i != 2) fprintf(f, "\n");
174839781Sbostic fprintf(f, "%4d %s :", i - 2, symbol_name[rlhs[i]]);
174939781Sbostic spacing = strlen(symbol_name[rlhs[i]]) + 1;
175039781Sbostic }
175139781Sbostic else
175239781Sbostic {
175339781Sbostic fprintf(f, "%4d ", i - 2);
175439781Sbostic j = spacing;
175539781Sbostic while (--j >= 0) putc(' ', f);
175639781Sbostic putc('|', f);
175739781Sbostic }
175839781Sbostic
175939781Sbostic while (ritem[k] >= 0)
176039781Sbostic {
176139781Sbostic fprintf(f, " %s", symbol_name[ritem[k]]);
176239781Sbostic ++k;
176339781Sbostic }
176439781Sbostic ++k;
176539781Sbostic putc('\n', f);
176639781Sbostic }
176739781Sbostic }
176839781Sbostic
176939781Sbostic
reader()177039781Sbostic reader()
177139781Sbostic {
177239781Sbostic write_section(banner);
177339781Sbostic create_symbol_table();
177439781Sbostic read_declarations();
177539781Sbostic read_grammar();
177639781Sbostic free_symbol_table();
177739781Sbostic free_tags();
177839781Sbostic pack_names();
177939781Sbostic check_symbols();
178039781Sbostic pack_symbols();
178139781Sbostic pack_grammar();
178239781Sbostic free_symbols();
178339781Sbostic print_grammar();
178439781Sbostic }
1785