122 lines
2.6 KiB
C
122 lines
2.6 KiB
C
|
/*
|
||
|
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||
|
*
|
||
|
* This product is part of the Amsterdam Compiler Kit.
|
||
|
*
|
||
|
* Permission to use, sell, duplicate or disclose this software must be
|
||
|
* obtained in writing. Requests for such permissions may be sent to
|
||
|
*
|
||
|
* Dr. Andrew S. Tanenbaum
|
||
|
* Wiskundig Seminarium
|
||
|
* Vrije Universiteit
|
||
|
* Postbox 7161
|
||
|
* 1007 MC Amsterdam
|
||
|
* The Netherlands
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
* L L G E N
|
||
|
*
|
||
|
* An Extended LL(1) Parser Generator
|
||
|
*
|
||
|
* Author : Ceriel J.H. Jacobs
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
* reach.c
|
||
|
* Determine which nonterminals are reachable, and also check that they
|
||
|
* are all defined.
|
||
|
*/
|
||
|
|
||
|
# include "tunable.h"
|
||
|
# include "types.h"
|
||
|
# include "extern.h"
|
||
|
# include "io.h"
|
||
|
# include "assert.h"
|
||
|
|
||
|
static string rcsid = "$Header$";
|
||
|
|
||
|
/* In this file the following routines are defined: */
|
||
|
extern co_reach();
|
||
|
STATIC reachable();
|
||
|
STATIC reachwalk();
|
||
|
|
||
|
co_reach() {
|
||
|
/*
|
||
|
* Check for undefined or unreachable nonterminals.
|
||
|
* An undefined nonterminal is a fatal error!
|
||
|
*/
|
||
|
register p_nont p;
|
||
|
register p_start st;
|
||
|
register p_file x = files;
|
||
|
register int *s;
|
||
|
|
||
|
/* Check for undefined nonterminals */
|
||
|
for (p = nonterms; p < maxnt; p++) {
|
||
|
if (! p->n_rule) {
|
||
|
f_input = p->n_string;
|
||
|
fatal(p->n_lineno,"nonterminal %s not defined",
|
||
|
(min_nt_ent + (p - nonterms))->h_name);
|
||
|
}
|
||
|
}
|
||
|
/*
|
||
|
* Walk the grammar rules, starting with the startsymbols
|
||
|
* Mark the nonterminals that are encountered with the flag
|
||
|
* REACHABLE, and walk their rules, if not done before
|
||
|
*/
|
||
|
for (st = start; st; st = st->ff_next) reachable(st->ff_nont);
|
||
|
/*
|
||
|
* Now check for unreachable nonterminals
|
||
|
*/
|
||
|
for (; x->f_end < maxorder; x++) {
|
||
|
f_input = x->f_name;
|
||
|
for (s = x->f_start; s <= x->f_end; s++) {
|
||
|
p = &nonterms[*s];
|
||
|
if (! (p->n_flags & REACHABLE)) {
|
||
|
error(p->n_lineno,"nonterminal %s unreachable",
|
||
|
(min_nt_ent + (p - nonterms))->h_name);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
STATIC
|
||
|
reachable(p) register p_nont p; {
|
||
|
/*
|
||
|
* Enter the fact that p is reachable, and look for implications
|
||
|
*/
|
||
|
if (! (p->n_flags & REACHABLE)) {
|
||
|
p->n_flags |= REACHABLE;
|
||
|
/*
|
||
|
* Now walk its grammar rule
|
||
|
*/
|
||
|
reachwalk(p->n_rule);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
STATIC
|
||
|
reachwalk(p) register p_gram p; {
|
||
|
/*
|
||
|
* Walk through rule p, looking for nonterminals.
|
||
|
* The nonterminals found are entered as reachable
|
||
|
*/
|
||
|
|
||
|
for (;;) {
|
||
|
switch(g_gettype(p)) {
|
||
|
case ALTERNATION :
|
||
|
reachwalk(((p_link) pentry[g_getcont(p)])->l_rule);
|
||
|
break;
|
||
|
case TERM :
|
||
|
reachwalk(((p_term) pentry[g_getcont(p)])->t_rule);
|
||
|
break;
|
||
|
case NONTERM :
|
||
|
reachable(&nonterms[g_getnont(p)]);
|
||
|
break;
|
||
|
case EORULE :
|
||
|
return;
|
||
|
}
|
||
|
p++;
|
||
|
}
|
||
|
}
|