xref: /csrg-svn/usr.bin/yacc/reader.c (revision 46064)
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