More safety, also after terms and nonterminals.

This commit is contained in:
ceriel 1985-10-03 12:38:55 +00:00
parent 67beb0c4d5
commit d07e8114c6
4 changed files with 58 additions and 51 deletions

View file

@ -204,13 +204,16 @@ check(p) register p_gram p; {
switch (g_gettype(p)) { switch (g_gettype(p)) {
case EORULE : case EORULE :
return; return;
case NONTERM : case NONTERM : {
if (g_getnpar(p)!=((nonterms[g_getnont(p)].n_flags&077) >> 3)){ register p_nont n;
n = &nonterms[g_getnont(p)];
if (g_getnpar(p) != getntparams(n)) {
error(p->g_lineno, error(p->g_lineno,
"Call of %s : parameter count mismatch", "Call of %s : parameter count mismatch",
(min_nt_ent+g_getnont(p))->h_name); (min_nt_ent+g_getnont(p))->h_name);
} }
break; break; }
case TERM : { case TERM : {
register p_term q; register p_term q;

View file

@ -670,28 +670,28 @@ co_safes() {
/* /*
* Don't know anything yet * Don't know anything yet
*/ */
setntsafe(&(p->n_flags), NOSAFETY); setntsafe(p, NOSAFETY);
setntout(p, NOSAFETY);
} }
for (st = start; st; st = st->ff_next) { for (st = start; st; st = st->ff_next) {
/* /*
* But start symbols are called with lookahead done * But start symbols are called with lookahead done
*/ */
p = st->ff_nont; p = st->ff_nont;
setntsafe(&(p->n_flags),SCANDONE); setntsafe(p,SCANDONE);
} }
change = 1; change = 1;
while (change) { while (change) {
change = 0; change = 0;
for (p = nonterms; p < maxnt; p++) { for (p = nonterms; p < maxnt; p++) {
i = getntsafe(p->n_flags); i = getntsafe(p);
if (i == NOSAFETY) { if (i == NOSAFETY) {
change = 1;
continue; continue;
} }
if (do_safes(p->n_rule, i) == 2 && i = do_safes(p->n_rule, i);
!(p->n_flags & NNOSCAN)) { if (getntout(p) != i) {
p->n_flags |= NNOSCAN;
change = 1; change = 1;
setntout(p, i);
} }
} }
} }
@ -705,8 +705,6 @@ do_safes(p,safe) register p_gram p; {
*/ */
register retval; register retval;
if (safe == NOSCANDONE) retval = 2;
else retval = 1;
for (;;) { for (;;) {
switch (g_gettype(p)) { switch (g_gettype(p)) {
case ACTION: case ACTION:
@ -724,10 +722,10 @@ do_safes(p,safe) register p_gram p; {
rep = r_getkind(&(q->t_reps)); rep = r_getkind(&(q->t_reps));
retval = do_safes(q->t_rule, retval = do_safes(q->t_rule,
t_safety(rep,i,q->t_flags&PERSISTENT,safe)); t_safety(rep,i,q->t_flags&PERSISTENT,safe));
if (retval == 2 && (!(q->t_flags & TNOSCAN))) { if (retval != gettout(q)) {
q->t_flags |= TNOSCAN; settout(q, retval);
} }
safe = t_after(rep, i, q->t_flags & TNOSCAN); safe = t_after(rep, i, gettout(q));
break; } break; }
case ALTERNATION : { case ALTERNATION : {
register p_link l; register p_link l;
@ -736,51 +734,53 @@ do_safes(p,safe) register p_gram p; {
f = 1; f = 1;
while (g_gettype(p) == ALTERNATION) { while (g_gettype(p) == ALTERNATION) {
l = (p_link) pentry[g_getcont(p)]; 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); i = do_safes(l->l_rule,SAFESCANDONE);
} }
else i = do_safes(l->l_rule,SAFE); else i = do_safes(l->l_rule,SAFE);
if (f) retval = i; 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++; p++;
f = 0; f = 0;
} }
return retval; } return retval; }
case NONTERM : { case NONTERM : {
register p_nont n; register p_nont n;
int nsafe, osafe;; int nsafe, osafe;
n = &nonterms[g_getnont(p)]; n = &nonterms[g_getnont(p)];
nsafe = getntsafe(n->n_flags); nsafe = getntsafe(n);
osafe = safe; osafe = safe;
if (!(n->n_flags & NNOSCAN)) { safe = getntout(n);
safe = SCANDONE; if (safe == NOSAFETY) safe = SCANDONE;
}
else safe = NOSCANDONE;
if (osafe == nsafe) break; if (osafe == nsafe) break;
if (nsafe == NOSAFETY) { if (nsafe == NOSAFETY) {
change = 1; change = 1;
setntsafe(&(n->n_flags), osafe); setntsafe(n, osafe);
break; break;
} }
if (osafe == NOSCANDONE || nsafe == NOSCANDONE) { if (osafe == NOSCANDONE || nsafe == NOSCANDONE) {
if (nsafe != SCANDONE) { if (nsafe != SCANDONE) {
change = 1; change = 1;
setntsafe(&(n->n_flags), SCANDONE); setntsafe(n, SCANDONE);
} }
break; break;
} }
if (osafe > nsafe) { if (osafe > nsafe) {
setntsafe(&(n->n_flags), osafe); setntsafe(n, osafe);
change = 1; change = 1;
} }
break; } break; }
case EORULE : case EORULE :
return retval; return safe;
} }
p++; p++;
if (safe == NOSCANDONE) retval = 2;
else retval = 1;
} }
} }
@ -814,10 +814,13 @@ t_safety(rep, count, persistent, safety) {
/* NOTREACHED */ /* NOTREACHED */
} }
t_after(rep, count, noscan) { t_after(rep, count, outsafety) {
if (count == 0 && (rep == STAR || rep == PLUS)) { if (count == 0 && (rep == STAR || rep == PLUS)) {
return SAFESCANDONE; return SAFESCANDONE;
} }
if (rep == FIXED && noscan) return NOSCANDONE; if (rep != FIXED) {
return SCANDONE; if (outsafety <= SAFESCANDONE) return SAFESCANDONE;
return SCANDONE;
}
return outsafety;
} }

View file

@ -173,7 +173,7 @@ genrecovery() {
fprintf(f, "\tL%d_%s();\n", fprintf(f, "\tL%d_%s();\n",
st->ff_nont-nonterms, st->ff_nont-nonterms,
(min_nt_ent+(st->ff_nont-nonterms))->h_name); (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); fputs("\tLLscan(EOFILE);\n",f);
} }
else fputs("\tif (LLsymb != EOFILE) LLerror(EOFILE);\n",f); else fputs("\tif (LLsymb != EOFILE) LLerror(EOFILE);\n",f);
@ -240,7 +240,7 @@ generate(f) p_file f; {
else fputs(") {\n", fd); else fputs(") {\n", fd);
fputs("register struct LLxx *LLx = &LLxx;\n#ifdef lint\nLLx=LLx;\n#endif\n", fd); fputs("register struct LLxx *LLx = &LLxx;\n#ifdef lint\nLLx=LLx;\n#endif\n", fd);
if (p->n_flags & LOCALS) getaction(1); if (p->n_flags & LOCALS) getaction(1);
i = getntsafe(p->n_flags); i = getntsafe(p);
mustpop = 0; mustpop = 0;
if (g_gettype(p->n_rule) == ALTERNATION) { if (g_gettype(p->n_rule) == ALTERNATION) {
mustpop = 1; mustpop = 1;
@ -252,7 +252,8 @@ generate(f) p_file f; {
nlabel = 1; nlabel = 1;
rulecode(p->n_rule, rulecode(p->n_rule,
i, i,
!(p->n_flags & NNOSCAN), mustpop); getntout(p) != NOSCANDONE,
mustpop);
fputs(c_close, fd); fputs(c_close, fd);
} }
} }
@ -443,7 +444,7 @@ rulecode(p,safety,mustscan,mustpop) register p_gram p; {
n = &nonterms[g_getnont(p)]; n = &nonterms[g_getnont(p)];
t= min_nt_ent+(n-nonterms); t= min_nt_ent+(n-nonterms);
if (safety == NOSCANDONE && if (safety == NOSCANDONE &&
getntsafe(n->n_flags) < NOSCANDONE) fputs(c_read, f); getntsafe(n) < NOSCANDONE) fputs(c_read, f);
if (toplevel == 0 && if (toplevel == 0 &&
g_gettype(n->n_rule) != ALTERNATION) { g_gettype(n->n_rule) != ALTERNATION) {
fputs(c_LLptrmin, f); fputs(c_LLptrmin, f);
@ -453,8 +454,7 @@ rulecode(p,safety,mustscan,mustpop) register p_gram p; {
fprintf(f,"L%d_%s(",n-nonterms, t->h_name); fprintf(f,"L%d_%s(",n-nonterms, t->h_name);
if (params) getaction(0); if (params) getaction(0);
fputs(");\n",f); fputs(");\n",f);
safety = NOSCANDONE; safety = getntout(n);
if (!(n->n_flags & NNOSCAN)) safety = SCANDONE;
break; } break; }
case TERM : case TERM :
safety = codeforterm((p_term) pentry[g_getcont(p)], safety = codeforterm((p_term) pentry[g_getcont(p)],
@ -707,13 +707,11 @@ codeforterm(q,safety,toplevel) register p_term q; {
register int i; register int i;
register int rep; register int rep;
int persistent; int persistent;
int noscan;
f = fpars; f = fpars;
i = r_getnum(&(q->t_reps)); i = r_getnum(&(q->t_reps));
rep = r_getkind(&(q->t_reps)); rep = r_getkind(&(q->t_reps));
persistent = (q->t_flags & PERSISTENT); persistent = (q->t_flags & PERSISTENT);
noscan = (q->t_flags & TNOSCAN);
if (safety == NOSCANDONE && (rep != FIXED || i == 0)) { if (safety == NOSCANDONE && (rep != FIXED || i == 0)) {
fputs(c_read, f); fputs(c_read, f);
if (rep == FIXED && g_gettype(q->t_rule) != ALTERNATION) { if (rep == FIXED && g_gettype(q->t_rule) != ALTERNATION) {
@ -726,7 +724,7 @@ codeforterm(q,safety,toplevel) register p_term q; {
fputs("for (;;) {\nif (!LL_i--) {\nLLptr++;\n", f); fputs("for (;;) {\nif (!LL_i--) {\nLLptr++;\n", f);
fputs("break;\n}\n", f); fputs("break;\n}\n", f);
if (rep == FIXED) { if (rep == FIXED) {
if (noscan && safety == NOSCANDONE) { if (gettout(q) == NOSCANDONE && safety == NOSCANDONE) {
fputs(c_read,f); fputs(c_read,f);
} }
} }
@ -739,7 +737,7 @@ codeforterm(q,safety,toplevel) register p_term q; {
genifhead(q,rep); genifhead(q,rep);
} }
rulecode(q->t_rule,t_safety(rep,i,persistent,safety), 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); rep == FIXED && i == 0 && g_gettype(q->t_rule) == ALTERNATION);
/* in the case of '+', the if is after the code for the rule */ /* in the case of '+', the if is after the code for the rule */
if (rep == PLUS) { if (rep == PLUS) {
@ -761,7 +759,7 @@ codeforterm(q,safety,toplevel) register p_term q; {
fputs(c_close, f);/* Close Register ... */ fputs(c_close, f);/* Close Register ... */
} }
} }
return t_after(rep, i, noscan); return t_after(rep, i, gettout(q));
} }
STATIC STATIC

View file

@ -108,15 +108,11 @@ typedef struct gram {
*/ */
typedef struct { typedef struct {
short n_flags; /* low order three bits are reserved short n_flags; /* low order three bits are reserved
* for "safety" information,
* the next three bits are reserved for
* the parameter count * the parameter count
*/ */
# define getntsafe(f) ((f)&07) # define getntparams(p) ((p)->n_flags&07)
# define setntsafe(p,i) {assert(((unsigned)(i))<=7);*(p)&=~07;*(p)|=(i);} # 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 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 CONTIN 00400 /* continuation already computed? */
# define BUSY 01000 /* or are we busy computing it? */ # define BUSY 01000 /* or are we busy computing it? */
# define PARAMS 02000 /* tells if a nonterminal has parameters */ # define PARAMS 02000 /* tells if a nonterminal has parameters */
@ -125,8 +121,14 @@ typedef struct {
# define LOCALS 020000 /* local declarations ? */ # define LOCALS 020000 /* local declarations ? */
# define REACHABLE 040000 /* can this nonterminal be reached ? */ # define REACHABLE 040000 /* can this nonterminal be reached ? */
# define VERBOSE 0100000 /* Set if in LL.output file */ # 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 */ 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 */ p_gram n_rule; /* pointer to right hand side of rule */
union { union {
p_set n_f; /* ptr to "first" set */ p_set n_f; /* ptr to "first" set */
@ -192,11 +194,12 @@ typedef short t_reps,*p_reps;
typedef struct term { typedef struct term {
t_reps t_reps; /* repeats ? */ t_reps t_reps; /* repeats ? */
short t_flags; 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 PERSISTENT 010 /* Set if this term has %persistent */
# define RESOLVER 020 /* Set if this term has %while */ # define RESOLVER 020 /* Set if this term has %while */
# define EMPTYFIRST 0100 /* Error, empty first */ # define EMPTYFIRST 0100 /* Error, empty first */
# define EMPTYTERM 0200 /* Error, term can produce empty */ # 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 */ /* # define NOCONF 01000 see link structure */
p_gram t_rule; /* pointer to this term */ p_gram t_rule; /* pointer to this term */