ack/util/LLgen/src/reach.c

126 lines
2.5 KiB
C
Raw Normal View History

1984-10-08 14:14:53 +00:00
/*
1987-03-10 01:26:51 +00:00
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
1984-10-08 14:14:53 +00:00
*
*/
/*
* 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;
1987-06-03 19:05:14 +00:00
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)) {
1987-06-03 19:05:14 +00:00
warning(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 :
1987-05-12 18:23:09 +00:00
reachwalk(g_getlink(p)->l_rule);
1984-10-08 14:14:53 +00:00
break;
case TERM :
1987-05-12 18:23:09 +00:00
reachwalk(g_getterm(p)->t_rule);
1984-10-08 14:14:53 +00:00
break;
1988-08-23 16:05:19 +00:00
case NONTERM : {
register p_nont n = &nonterms[g_getcont(p)];
reachable(n);
if (g_gettype(n->n_rule) == EORULE &&
! g_getnpar(p) && (getntparams(n) == 0)) {
register p_gram np = p;
do {
*np = *(np + 1);
np++;
} while (g_gettype(np) != EORULE);
continue;
}
1984-10-08 14:14:53 +00:00
break;
1988-08-23 16:05:19 +00:00
}
1984-10-08 14:14:53 +00:00
case EORULE :
return;
}
p++;
}
}