ack/util/LLgen/src/reach.c

125 lines
2.6 KiB
C
Raw Normal View History

1984-10-08 14:14:53 +00:00
/*
* (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 "types.h"
# include "extern.h"
# include "io.h"
# include "assert.h"
1984-10-08 17:11:03 +00:00
# ifndef NORCSID
static string rcsid8 = "$Header$";
# endif
1984-10-08 14:14:53 +00:00
/* 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;
register p_order s;
1984-10-08 14:14:53 +00:00
/* Check for undefined nonterminals */
for (p = nonterms; p < maxnt; p++) {
if (! p->n_rule) { /* undefined */
1984-10-08 14:14:53 +00:00
f_input = p->n_string;
error(p->n_lineno,"nonterminal %s not defined",
p->n_name);
1984-10-08 14:14:53 +00:00
}
}
/*
* 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(&nonterms[st->ff_nont]);
}
1984-10-08 14:14:53 +00:00
/*
* Now check for unreachable nonterminals
*/
for (x = files; x < maxfiles; x++) {
1984-10-08 14:14:53 +00:00
f_input = x->f_name;
for (s = x->f_list; s; s = s->o_next) {
p = &nonterms[s->o_index];
1984-10-08 14:14:53 +00:00
if (! (p->n_flags & REACHABLE)) {
error(p->n_lineno,"nonterminal %s unreachable",
p->n_name);
1984-10-08 14:14:53 +00:00
}
}
}
}
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
*/
if (p->n_rule) reachwalk(p->n_rule);
1984-10-08 14:14:53 +00:00
}
}
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(links[g_getcont(p)].l_rule);
1984-10-08 14:14:53 +00:00
break;
case TERM :
reachwalk(terms[g_getcont(p)].t_rule);
1984-10-08 14:14:53 +00:00
break;
case NONTERM :
reachable(&nonterms[g_getnont(p)]);
break;
case EORULE :
return;
}
p++;
}
}