ack/util/LLgen/src/reach.c

136 lines
2.8 KiB
C
Raw Normal View History

/* Copyright (c) 1991 by the Vrije Universiteit, Amsterdam, the Netherlands.
1995-07-31 09:17:14 +00:00
* For full copyright and restrictions on use see the file COPYING in the top
1995-07-31 09:10:42 +00:00
* level of the LLgen tree.
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
1994-06-24 11:31:16 +00:00
static string rcsid8 = "$Id$";
1984-10-08 17:11:03 +00:00
# endif
1984-10-08 14:14:53 +00:00
/* In this file the following routines are defined: */
extern co_reach();
STATIC reachable();
STATIC void reachwalk();
1984-10-08 14:14:53 +00:00
co_reach() {
/*
* Check for undefined or unreachable nonterminals.
*/
register p_nont p;
register p_token t;
1984-10-08 14:14:53 +00:00
register p_start st;
register p_file x;
register int 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
}
}
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_nonterminals; s != -1; s = p->n_next) {
p = &nonterms[s];
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
}
}
for (s = x->f_terminals; s != -1; s = t->t_next) {
t = &tokens[s];
if (! (t->t_flags & REACHABLE)) {
warning(t->t_lineno,"terminal %s not used",
t->t_string);
}
}
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 void
1984-10-08 14:14:53 +00:00
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);
1989-03-07 09:26:42 +00:00
if (n->n_rule && g_gettype(n->n_rule) == EORULE &&
1988-08-23 16:05:19 +00:00
! 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
}
case TERMINAL:
tokens[g_getcont(p)].t_flags |= REACHABLE;
break;
1984-10-08 14:14:53 +00:00
case EORULE :
return;
}
p++;
}
}