switch (g_gettype(p)) {
case EORULE :
return;
- case NONTERM :
- if (g_getnpar(p)!=((nonterms[g_getnont(p)].n_flags&077) >> 3)){
+ case NONTERM : {
+ register p_nont n;
+
+ n = &nonterms[g_getnont(p)];
+ if (g_getnpar(p) != getntparams(n)) {
error(p->g_lineno,
"Call of %s : parameter count mismatch",
(min_nt_ent+g_getnont(p))->h_name);
}
- break;
+ break; }
case TERM : {
register p_term q;
/*
* Don't know anything yet
*/
- setntsafe(&(p->n_flags), NOSAFETY);
+ setntsafe(p, NOSAFETY);
+ setntout(p, NOSAFETY);
}
for (st = start; st; st = st->ff_next) {
/*
* But start symbols are called with lookahead done
*/
p = st->ff_nont;
- setntsafe(&(p->n_flags),SCANDONE);
+ setntsafe(p,SCANDONE);
}
change = 1;
while (change) {
change = 0;
for (p = nonterms; p < maxnt; p++) {
- i = getntsafe(p->n_flags);
+ i = getntsafe(p);
if (i == NOSAFETY) {
- change = 1;
continue;
}
- if (do_safes(p->n_rule, i) == 2 &&
- !(p->n_flags & NNOSCAN)) {
- p->n_flags |= NNOSCAN;
+ i = do_safes(p->n_rule, i);
+ if (getntout(p) != i) {
change = 1;
+ setntout(p, i);
}
}
}
*/
register retval;
- if (safe == NOSCANDONE) retval = 2;
- else retval = 1;
for (;;) {
switch (g_gettype(p)) {
case ACTION:
rep = r_getkind(&(q->t_reps));
retval = do_safes(q->t_rule,
t_safety(rep,i,q->t_flags&PERSISTENT,safe));
- if (retval == 2 && (!(q->t_flags & TNOSCAN))) {
- q->t_flags |= TNOSCAN;
+ if (retval != gettout(q)) {
+ settout(q, retval);
}
- safe = t_after(rep, i, q->t_flags & TNOSCAN);
+ safe = t_after(rep, i, gettout(q));
break; }
case ALTERNATION : {
register p_link l;
f = 1;
while (g_gettype(p) == ALTERNATION) {
l = (p_link) pentry[g_getcont(p)];
- if (safe && (l->l_flag & DEF)) {
+ if (safe > SAFE && (l->l_flag & DEF)) {
i = do_safes(l->l_rule,SAFESCANDONE);
}
else i = do_safes(l->l_rule,SAFE);
if (f) retval = i;
- else retval &= i;
+ else if (i != retval) {
+ if (i == NOSCANDONE ||
+ retval == NOSCANDONE) {
+ retval = SCANDONE;
+ }
+ else if (i > retval) retval = i;
+ }
p++;
f = 0;
}
return retval; }
case NONTERM : {
register p_nont n;
- int nsafe, osafe;;
+ int nsafe, osafe;
n = &nonterms[g_getnont(p)];
- nsafe = getntsafe(n->n_flags);
+ nsafe = getntsafe(n);
osafe = safe;
- if (!(n->n_flags & NNOSCAN)) {
- safe = SCANDONE;
- }
- else safe = NOSCANDONE;
+ safe = getntout(n);
+ if (safe == NOSAFETY) safe = SCANDONE;
if (osafe == nsafe) break;
if (nsafe == NOSAFETY) {
change = 1;
- setntsafe(&(n->n_flags), osafe);
+ setntsafe(n, osafe);
break;
}
if (osafe == NOSCANDONE || nsafe == NOSCANDONE) {
if (nsafe != SCANDONE) {
change = 1;
- setntsafe(&(n->n_flags), SCANDONE);
+ setntsafe(n, SCANDONE);
}
break;
}
if (osafe > nsafe) {
- setntsafe(&(n->n_flags), osafe);
+ setntsafe(n, osafe);
change = 1;
}
break; }
case EORULE :
- return retval;
+ return safe;
}
p++;
- if (safe == NOSCANDONE) retval = 2;
- else retval = 1;
}
}
/* NOTREACHED */
}
-t_after(rep, count, noscan) {
+t_after(rep, count, outsafety) {
if (count == 0 && (rep == STAR || rep == PLUS)) {
return SAFESCANDONE;
}
- if (rep == FIXED && noscan) return NOSCANDONE;
- return SCANDONE;
+ if (rep != FIXED) {
+ if (outsafety <= SAFESCANDONE) return SAFESCANDONE;
+ return SCANDONE;
+ }
+ return outsafety;
}
fprintf(f, "\tL%d_%s();\n",
st->ff_nont-nonterms,
(min_nt_ent+(st->ff_nont-nonterms))->h_name);
- if (st->ff_nont->n_flags & NNOSCAN) {
+ if (getntout(st->ff_nont) == NOSCANDONE) {
fputs("\tLLscan(EOFILE);\n",f);
}
else fputs("\tif (LLsymb != EOFILE) LLerror(EOFILE);\n",f);
else fputs(") {\n", fd);
fputs("register struct LLxx *LLx = &LLxx;\n#ifdef lint\nLLx=LLx;\n#endif\n", fd);
if (p->n_flags & LOCALS) getaction(1);
- i = getntsafe(p->n_flags);
+ i = getntsafe(p);
mustpop = 0;
if (g_gettype(p->n_rule) == ALTERNATION) {
mustpop = 1;
nlabel = 1;
rulecode(p->n_rule,
i,
- !(p->n_flags & NNOSCAN), mustpop);
+ getntout(p) != NOSCANDONE,
+ mustpop);
fputs(c_close, fd);
}
}
n = &nonterms[g_getnont(p)];
t= min_nt_ent+(n-nonterms);
if (safety == NOSCANDONE &&
- getntsafe(n->n_flags) < NOSCANDONE) fputs(c_read, f);
+ getntsafe(n) < NOSCANDONE) fputs(c_read, f);
if (toplevel == 0 &&
g_gettype(n->n_rule) != ALTERNATION) {
fputs(c_LLptrmin, f);
fprintf(f,"L%d_%s(",n-nonterms, t->h_name);
if (params) getaction(0);
fputs(");\n",f);
- safety = NOSCANDONE;
- if (!(n->n_flags & NNOSCAN)) safety = SCANDONE;
+ safety = getntout(n);
break; }
case TERM :
safety = codeforterm((p_term) pentry[g_getcont(p)],
register int i;
register int rep;
int persistent;
- int noscan;
f = fpars;
i = r_getnum(&(q->t_reps));
rep = r_getkind(&(q->t_reps));
persistent = (q->t_flags & PERSISTENT);
- noscan = (q->t_flags & TNOSCAN);
if (safety == NOSCANDONE && (rep != FIXED || i == 0)) {
fputs(c_read, f);
if (rep == FIXED && g_gettype(q->t_rule) != ALTERNATION) {
fputs("for (;;) {\nif (!LL_i--) {\nLLptr++;\n", f);
fputs("break;\n}\n", f);
if (rep == FIXED) {
- if (noscan && safety == NOSCANDONE) {
+ if (gettout(q) == NOSCANDONE && safety == NOSCANDONE) {
fputs(c_read,f);
}
}
genifhead(q,rep);
}
rulecode(q->t_rule,t_safety(rep,i,persistent,safety),
- rep != FIXED || !noscan,
+ rep != FIXED || gettout(q) != NOSCANDONE,
rep == FIXED && i == 0 && g_gettype(q->t_rule) == ALTERNATION);
/* in the case of '+', the if is after the code for the rule */
if (rep == PLUS) {
fputs(c_close, f);/* Close Register ... */
}
}
- return t_after(rep, i, noscan);
+ return t_after(rep, i, gettout(q));
}
STATIC
*/
typedef struct {
short n_flags; /* low order three bits are reserved
- * for "safety" information,
- * the next three bits are reserved for
* the parameter count
*/
-# define getntsafe(f) ((f)&07)
-# define setntsafe(p,i) {assert(((unsigned)(i))<=7);*(p)&=~07;*(p)|=(i);}
-
+# define getntparams(p) ((p)->n_flags&07)
+# define setntparams(p,i) {assert(((unsigned)(i))<=7);(p)->n_flags&=~07;(p)->n_flags|=(i);}
# define RECURSIVE 00100 /* Set if the default rule is recursive */
-# define NNOSCAN 00200 /* Set if the nonterminal does not scan ahead */
# define CONTIN 00400 /* continuation already computed? */
# define BUSY 01000 /* or are we busy computing it? */
# define PARAMS 02000 /* tells if a nonterminal has parameters */
# define LOCALS 020000 /* local declarations ? */
# define REACHABLE 040000 /* can this nonterminal be reached ? */
# define VERBOSE 0100000 /* Set if in LL.output file */
+ char n_insafety;
+ char n_outsafety;
+# define getntsafe(p) ((p)->n_insafety)
+# define setntsafe(p,i) {assert(((unsigned)(i))<=NOSAFETY);(p)->n_insafety=(i);}
+# define getntout(p) ((p)->n_outsafety)
+# define setntout(p,i) {assert(((unsigned)(i))<=NOSAFETY);(p)->n_outsafety=(i);}
short n_count; /* pieces of code before this rule */
- int n_lineno; /* declared on line ... */
+ short n_lineno; /* declared on line ... */
p_gram n_rule; /* pointer to right hand side of rule */
union {
p_set n_f; /* ptr to "first" set */
typedef struct term {
t_reps t_reps; /* repeats ? */
short t_flags;
+# define gettout(q) ((q)->t_flags&07)
+# define settout(q,i) {assert(((unsigned)(i))<=NOSAFETY);(q)->t_flags&=~07;(q)->t_flags|=i;}
# define PERSISTENT 010 /* Set if this term has %persistent */
# define RESOLVER 020 /* Set if this term has %while */
# define EMPTYFIRST 0100 /* Error, empty first */
# define EMPTYTERM 0200 /* Error, term can produce empty */
-# define TNOSCAN 0400 /* Set if this term does not scan ahead */
/* # define NOCONF 01000 see link structure */
p_gram t_rule; /* pointer to this term */