* Copyright (c) 1989 The Regents of the University of California.
* This code is derived from software contributed to Berkeley by
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
static char sccsid
[] = "@(#)reader.c 5.7 (Berkeley) 1/20/91";
/* The line size must be a positive integer. One hundred was chosen */
/* because few lines in Yacc input grammars exceed 100 characters. */
/* Note that if a line exceeds LINESIZE characters, the line buffer */
/* will be expanded to accomodate it. */
char line_format
[] = "#line %d \"%s\"\n";
cache
= REALLOC(cache
, cache_size
);
if (cache
== 0) no_space();
register FILE *f
= input_file
;
if (saw_eof
|| (c
= getc(f
)) == EOF
)
if (line
) { FREE(line
); line
= 0; }
if (line
== 0 || linesize
!= (LINESIZE
+ 1))
if (line
== 0) no_space();
if (c
== '\n') { cptr
= line
; return; }
line
= REALLOC(line
, linesize
);
if (line
== 0) no_space();
register char *p
, *s
, *t
;
if (line
== 0) return (0);
p
= MALLOC(s
- line
+ 1);
while ((*t
++ = *s
++) != '\n') continue;
char *st_line
= dup_line();
char *st_cptr
= st_line
+ (cptr
- line
);
if (*s
== '*' && s
[1] == '/')
unterminated_comment(st_lineno
, st_line
, st_cptr
);
if (line
== 0) return (EOF
);
if (line
== 0) return (EOF
);
if (isupper(c
)) c
= tolower(c
);
else if (isdigit(c
) || c
== '_' || c
== '.' || c
== '$')
if (strcmp(cache
, "token") == 0 || strcmp(cache
, "term") == 0)
if (strcmp(cache
, "type") == 0)
if (strcmp(cache
, "left") == 0)
if (strcmp(cache
, "right") == 0)
if (strcmp(cache
, "nonassoc") == 0 || strcmp(cache
, "binary") == 0)
if (strcmp(cache
, "start") == 0)
if (strcmp(cache
, "union") == 0)
if (strcmp(cache
, "ident") == 0)
if (c
== '%' || c
== '\\')
syntax_error(lineno
, line
, t_cptr
);
register FILE *f
= output_file
;
if (c
== EOF
) unexpected_EOF();
if (c
!= '"') syntax_error(lineno
, line
, cptr
);
register FILE *f
= text_file
;
char *t_line
= dup_line();
char *t_cptr
= t_line
+ (cptr
- line
- 2);
unterminated_text(t_lineno
, t_line
, t_cptr
);
if (!lflag
) fprintf(f
, line_format
, lineno
, input_file_name
);
unterminated_text(t_lineno
, t_line
, t_cptr
);
char *s_line
= dup_line();
char *s_cptr
= s_line
+ (cptr
- line
- 1);
unterminated_string(s_lineno
, s_line
, s_cptr
);
unterminated_string(s_lineno
, s_line
, s_cptr
);
while ((c
= *++cptr
) != '\n')
if (c
== '*' && cptr
[1] == '/')
char *c_line
= dup_line();
char *c_cptr
= c_line
+ (cptr
- line
- 1);
if (c
== '*' && *cptr
== '/')
unterminated_comment(c_lineno
, c_line
, c_cptr
);
if (need_newline
) putc('\n', f
);
char *u_line
= dup_line();
char *u_cptr
= u_line
+ (cptr
- line
- 6);
if (unionized
) over_unionized(cptr
- 6);
fprintf(text_file
, line_format
, lineno
, input_file_name
);
fprintf(text_file
, "typedef union");
if (dflag
) fprintf(union_file
, "typedef union");
if (dflag
) putc(c
, union_file
);
if (line
== 0) unterminated_union(u_lineno
, u_line
, u_cptr
);
fprintf(text_file
, " YYSTYPE;\n");
char *s_line
= dup_line();
char *s_cptr
= s_line
+ (cptr
- line
- 1);
if (dflag
) putc(c
, union_file
);
unterminated_string(s_lineno
, s_line
, s_cptr
);
if (dflag
) putc(c
, union_file
);
unterminated_string(s_lineno
, s_line
, s_cptr
);
if (dflag
) putc('*', union_file
);
while ((c
= *++cptr
) != '\n')
if (c
== '*' && cptr
[1] == '/')
fprintf(text_file
, "* ");
if (dflag
) fprintf(union_file
, "* ");
if (dflag
) putc(c
, union_file
);
fprintf(text_file
, "*/\n");
if (dflag
) fprintf(union_file
, "*/\n");
char *c_line
= dup_line();
char *c_cptr
= c_line
+ (cptr
- line
- 1);
if (dflag
) putc('*', union_file
);
if (dflag
) putc(c
, union_file
);
if (c
== '*' && *cptr
== '/')
if (dflag
) putc('/', union_file
);
unterminated_comment(c_lineno
, c_line
, c_cptr
);
if (c
>= '0' && c
<= '9')
if (c
>= 'A' && c
<= 'F')
if (c
>= 'a' && c
<= 'f')
char *s_line
= dup_line();
char *s_cptr
= s_line
+ (cptr
- line
);
if (c
== '\n') unterminated_string(s_lineno
, s_line
, s_cptr
);
if (line
== 0) unterminated_string(s_lineno
, s_line
, s_cptr
);
case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7':
n
= (n
<< 3) + (c
- '0');
n
= (n
<< 3) + (c
- '0');
if (n
> MAXCHAR
) illegal_character(c_cptr
);
illegal_character(c_cptr
);
if (i
< 0 || i
>= 16) break;
if (n
> MAXCHAR
) illegal_character(c_cptr
);
case 'b': c
= '\b'; break;
case 'f': c
= '\f'; break;
case 'n': c
= '\n'; break;
case 'r': c
= '\r'; break;
case 't': c
= '\t'; break;
case 'v': c
= '\v'; break;
c
= ((unsigned char *)s
)[i
];
if (c
== '\\' || c
== cache
[0])
case 7: cachec('a'); break;
case '\b': cachec('b'); break;
case '\f': cachec('f'); break;
case '\n': cachec('n'); break;
case '\r': cachec('r'); break;
case '\t': cachec('t'); break;
case '\v': cachec('v'); break;
cachec(((c
>> 6) & 7) + '0');
cachec(((c
>> 3) & 7) + '0');
if (n
== 1 && bp
->value
== UNDEFINED
)
bp
->value
= *(unsigned char *)s
;
if (strcmp(name
, ".") == 0 ||
strcmp(name
, "$accept") == 0 ||
strcmp(name
, "$end") == 0)
if (name
[0] == '$' && name
[1] == '$' && isdigit(name
[2]))
if (*s
== NUL
) return (1);
for (c
= *cptr
; IS_IDENT(c
); c
= *++cptr
)
if (is_reserved(cache
)) used_reserved(cache
);
for (c
= *cptr
; isdigit(c
); c
= *++cptr
)
char *t_line
= dup_line();
char *t_cptr
= t_line
+ (cptr
- line
);
if (c
== EOF
) unexpected_EOF();
if (!isalpha(c
) && c
!= '_' && c
!= '$')
illegal_tag(t_lineno
, t_line
, t_cptr
);
do { cachec(c
); c
= *++cptr
; } while (IS_IDENT(c
));
if (c
== EOF
) unexpected_EOF();
illegal_tag(t_lineno
, t_line
, t_cptr
);
for (i
= 0; i
< ntags
; ++i
)
if (strcmp(cache
, tag_table
[i
]) == 0)
(tag_table
? REALLOC(tag_table
, tagmax
*sizeof(char *))
: MALLOC(tagmax
*sizeof(char *)));
if (tag_table
== 0) no_space();
if (assoc
!= TOKEN
) ++prec
;
if (c
== EOF
) unexpected_EOF();
if (c
== EOF
) unexpected_EOF();
if (isalpha(c
) || c
== '_' || c
== '.' || c
== '$')
else if (c
== '\'' || c
== '"')
if (bp
== goal
) tokenized_start(bp
->name
);
if (bp
->tag
&& tag
!= bp
->tag
)
retyped_warning(bp
->name
);
if (bp
->prec
&& prec
!= bp
->prec
)
reprec_warning(bp
->name
);
if (c
== EOF
) unexpected_EOF();
if (bp
->value
!= UNDEFINED
&& value
!= bp
->value
)
revalued_warning(bp
->name
);
if (c
== EOF
) unexpected_EOF();
if (c
== EOF
) unexpected_EOF();
if (c
!= '<') syntax_error(lineno
, line
, cptr
);
if (isalpha(c
) || c
== '_' || c
== '.' || c
== '$')
else if (c
== '\'' || c
== '"')
if (bp
->tag
&& tag
!= bp
->tag
)
retyped_warning(bp
->name
);
if (c
== EOF
) unexpected_EOF();
if (!isalpha(c
) && c
!= '_' && c
!= '.' && c
!= '$')
syntax_error(lineno
, line
, cptr
);
terminal_start(bp
->name
);
cache
= MALLOC(cache_size
);
if (cache
== 0) no_space();
if (c
== EOF
) unexpected_EOF();
if (c
!= '%') syntax_error(lineno
, line
, cptr
);
pitem
= (bucket
**) MALLOC(maxitems
*sizeof(bucket
*));
if (pitem
== 0) no_space();
plhs
= (bucket
**) MALLOC(maxrules
*sizeof(bucket
*));
if (plhs
== 0) no_space();
rprec
= (short *) MALLOC(maxrules
*sizeof(short));
if (rprec
== 0) no_space();
rassoc
= (char *) MALLOC(maxrules
*sizeof(char));
if (rassoc
== 0) no_space();
pitem
= (bucket
**) REALLOC(pitem
, maxitems
*sizeof(bucket
*));
if (pitem
== 0) no_space();
plhs
= (bucket
**) REALLOC(plhs
, maxrules
*sizeof(bucket
*));
if (plhs
== 0) no_space();
rprec
= (short *) REALLOC(rprec
, maxrules
*sizeof(short));
if (rprec
== 0) no_space();
rassoc
= (char *) REALLOC(rassoc
, maxrules
*sizeof(char));
if (rassoc
== 0) no_space();
syntax_error(lineno
, line
, s_cptr
);
if (!isalpha(c
) && c
!= '_' && c
!= '.' && c
!= '_')
syntax_error(lineno
, line
, cptr
);
terminal_start(bp
->name
);
if (c
== EOF
) unexpected_EOF();
if (c
!= ':') syntax_error(lineno
, line
, cptr
);
start_rule(bp
, s_lineno
);
rprec
[nrules
] = UNDEFINED
;
if (!last_was_action
&& plhs
[nrules
]->tag
)
for (i
= nitems
- 1; pitem
[i
]; --i
) continue;
if (pitem
[i
+1] == 0 || pitem
[i
+1]->tag
!= plhs
[nrules
]->tag
)
default_action_warning();
if (nitems
>= maxitems
) expand_items();
register bucket
*bp
, **bpp
;
sprintf(cache
, "$$%d", ++gensym
);
bp
->tag
= plhs
[nrules
]->tag
;
if ((nitems
+= 2) > maxitems
)
bpp
= pitem
+ nitems
- 1;
while (bpp
[0] = bpp
[-1]) --bpp
;
if (++nrules
>= maxrules
)
plhs
[nrules
] = plhs
[nrules
-1];
rprec
[nrules
] = rprec
[nrules
-1];
rassoc
[nrules
] = rassoc
[nrules
-1];
rassoc
[nrules
-1] = TOKEN
;
if (c
== '\'' || c
== '"')
start_rule(bp
, s_lineno
);
register FILE *f
= action_file
;
char *a_line
= dup_line();
char *a_cptr
= a_line
+ (cptr
- line
);
fprintf(f
, "case %d:\n", nrules
- 2);
fprintf(f
, line_format
, lineno
, input_file_name
);
if (*cptr
== '=') ++cptr
;
for (i
= nitems
- 1; pitem
[i
]; --i
) ++n
;
char *d_line
= dup_line();
char *d_cptr
= d_line
+ (cptr
- line
);
fprintf(f
, "yyval.%s", tag
);
if (i
> n
) dollar_warning(d_lineno
, i
);
fprintf(f
, "yyvsp[%d].%s", i
- n
, tag
);
else if (c
== '-' && isdigit(cptr
[1]))
fprintf(f
, "yyvsp[%d].%s", i
, tag
);
dollar_error(d_lineno
, d_line
, d_cptr
);
if (tag
== 0) untyped_lhs();
fprintf(f
, "yyval.%s", tag
);
else if (isdigit(cptr
[1]))
tag
= pitem
[nitems
+ i
- n
- 1]->tag
;
if (tag
== 0) untyped_rhs(i
, pitem
[nitems
+ i
- n
- 1]->name
);
fprintf(f
, "yyvsp[%d].%s", i
- n
, tag
);
dollar_warning(lineno
, i
);
fprintf(f
, "yyvsp[%d]", i
- n
);
fprintf(f
, "yyvsp[%d]", -i
- n
);
if (isalpha(c
) || c
== '_' || c
== '$')
} while (isalnum(c
) || c
== '_' || c
== '$');
unterminated_action(a_lineno
, a_line
, a_cptr
);
if (depth
> 0) goto loop
;
fprintf(f
, "\nbreak;\n");
if (--depth
> 0) goto loop
;
fprintf(f
, "\nbreak;\n");
char *s_line
= dup_line();
char *s_cptr
= s_line
+ (cptr
- line
- 1);
unterminated_string(s_lineno
, s_line
, s_cptr
);
unterminated_string(s_lineno
, s_line
, s_cptr
);
while ((c
= *++cptr
) != '\n')
if (c
== '*' && cptr
[1] == '/')
char *c_line
= dup_line();
char *c_cptr
= c_line
+ (cptr
- line
- 1);
if (c
== '*' && *cptr
== '/')
unterminated_comment(c_lineno
, c_line
, c_cptr
);
if (c
== '%' || c
== '\\')
else if ((c
== 'p' || c
== 'P') &&
((c
= cptr
[2]) == 'r' || c
== 'R') &&
((c
= cptr
[3]) == 'e' || c
== 'E') &&
((c
= cptr
[4]) == 'c' || c
== 'C') &&
((c
= cptr
[5], !IS_IDENT(c
))))
syntax_error(lineno
, line
, cptr
);
if (isalpha(c
) || c
== '_' || c
== '.' || c
== '$')
else if (c
== '\'' || c
== '"')
syntax_error(lineno
, line
, cptr
);
if (rprec
[nrules
] != UNDEFINED
&& bp
->prec
!= rprec
[nrules
])
rprec
[nrules
] = bp
->prec
;
rassoc
[nrules
] = bp
->assoc
;
if (isalpha(c
) || c
== '_' || c
== '.' || c
== '$' || c
== '\'' ||
else if (c
== '{' || c
== '=')
start_rule(plhs
[nrules
-1], 0);
if (mark_symbol()) break;
syntax_error(lineno
, line
, cptr
);
if (tag_table
== 0) return;
for (i
= 0; i
< ntags
; ++i
)
register char *p
, *s
, *t
;
name_pool_size
= 13; /* 13 == sizeof("$end") + sizeof("$accept") */
for (bp
= first_symbol
; bp
; bp
= bp
->next
)
name_pool_size
+= strlen(bp
->name
) + 1;
name_pool
= MALLOC(name_pool_size
);
if (name_pool
== 0) no_space();
strcpy(name_pool
, "$accept");
strcpy(name_pool
+8, "$end");
for (bp
= first_symbol
; bp
; bp
= bp
->next
)
while (*t
++ = *s
++) continue;
if (goal
->class == UNKNOWN
)
undefined_goal(goal
->name
);
for (bp
= first_symbol
; bp
; bp
= bp
->next
)
if (bp
->class == UNKNOWN
)
undefined_symbol_warning(bp
->name
);
for (bp
= first_symbol
; bp
; bp
= bp
->next
)
if (bp
->class == TERM
) ++ntokens
;
symbol_name
= (char **) MALLOC(nsyms
*sizeof(char *));
if (symbol_name
== 0) no_space();
symbol_value
= (short *) MALLOC(nsyms
*sizeof(short));
if (symbol_value
== 0) no_space();
symbol_prec
= (short *) MALLOC(nsyms
*sizeof(short));
if (symbol_prec
== 0) no_space();
symbol_assoc
= MALLOC(nsyms
);
if (symbol_assoc
== 0) no_space();
v
= (bucket
**) MALLOC(nsyms
*sizeof(bucket
*));
for (bp
= first_symbol
; bp
; bp
= bp
->next
)
assert(i
== ntokens
&& j
== nsyms
);
for (i
= 1; i
< ntokens
; ++i
)
goal
->index
= start_symbol
+ 1;
for (i
= start_symbol
+ 1; i
< nsyms
; ++i
)
for (i
= 1; i
< ntokens
; ++i
)
for (j
= k
++; j
> 0 && symbol_value
[j
-1] > n
; --j
)
symbol_value
[j
] = symbol_value
[j
-1];
if (v
[1]->value
== UNDEFINED
)
for (i
= 2; i
< ntokens
; ++i
)
if (v
[i
]->value
== UNDEFINED
)
while (j
< k
&& n
== symbol_value
[j
])
while (++j
< k
&& n
== symbol_value
[j
]) continue;
symbol_name
[0] = name_pool
+ 8;
for (i
= 1; i
< ntokens
; ++i
)
symbol_name
[i
] = v
[i
]->name
;
symbol_value
[i
] = v
[i
]->value
;
symbol_prec
[i
] = v
[i
]->prec
;
symbol_assoc
[i
] = v
[i
]->assoc
;
symbol_name
[start_symbol
] = name_pool
;
symbol_value
[start_symbol
] = -1;
symbol_prec
[start_symbol
] = 0;
symbol_assoc
[start_symbol
] = TOKEN
;
for (++i
; i
< nsyms
; ++i
)
symbol_name
[k
] = v
[i
]->name
;
symbol_value
[k
] = v
[i
]->value
;
symbol_prec
[k
] = v
[i
]->prec
;
symbol_assoc
[k
] = v
[i
]->assoc
;
ritem
= (short *) MALLOC(nitems
*sizeof(short));
if (ritem
== 0) no_space();
rlhs
= (short *) MALLOC(nrules
*sizeof(short));
if (rlhs
== 0) no_space();
rrhs
= (short *) MALLOC((nrules
+1)*sizeof(short));
if (rrhs
== 0) no_space();
rprec
= (short *) REALLOC(rprec
, nrules
*sizeof(short));
if (rprec
== 0) no_space();
rassoc
= REALLOC(rassoc
, nrules
);
if (rassoc
== 0) no_space();
for (i
= 3; i
< nrules
; ++i
)
rlhs
[i
] = plhs
[i
]->index
;
ritem
[j
] = pitem
[j
]->index
;
if (pitem
[j
]->class == TERM
)
if (rprec
[i
] == UNDEFINED
)
register FILE *f
= verbose_file
;
for (i
= 2; i
< nrules
; ++i
)
if (rlhs
[i
] != rlhs
[i
-1])
if (i
!= 2) fprintf(f
, "\n");
fprintf(f
, "%4d %s :", i
- 2, symbol_name
[rlhs
[i
]]);
spacing
= strlen(symbol_name
[rlhs
[i
]]) + 1;
fprintf(f
, "%4d ", i
- 2);
while (--j
>= 0) putc(' ', f
);
fprintf(f
, " %s", symbol_name
[ritem
[k
]]);