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)) {
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;

View file

@ -670,28 +670,28 @@ co_safes() {
/*
* 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);
}
}
}
@ -705,8 +705,6 @@ do_safes(p,safe) register p_gram p; {
*/
register retval;
if (safe == NOSCANDONE) retval = 2;
else retval = 1;
for (;;) {
switch (g_gettype(p)) {
case ACTION:
@ -724,10 +722,10 @@ do_safes(p,safe) register p_gram p; {
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;
@ -736,51 +734,53 @@ do_safes(p,safe) register p_gram p; {
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;
}
}
@ -814,10 +814,13 @@ t_safety(rep, count, persistent, safety) {
/* 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;
}

View file

@ -173,7 +173,7 @@ genrecovery() {
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);
@ -240,7 +240,7 @@ generate(f) p_file 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;
@ -252,7 +252,8 @@ generate(f) p_file f; {
nlabel = 1;
rulecode(p->n_rule,
i,
!(p->n_flags & NNOSCAN), mustpop);
getntout(p) != NOSCANDONE,
mustpop);
fputs(c_close, fd);
}
}
@ -443,7 +444,7 @@ rulecode(p,safety,mustscan,mustpop) register p_gram p; {
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);
@ -453,8 +454,7 @@ rulecode(p,safety,mustscan,mustpop) register p_gram p; {
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)],
@ -707,13 +707,11 @@ codeforterm(q,safety,toplevel) register p_term q; {
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) {
@ -726,7 +724,7 @@ codeforterm(q,safety,toplevel) register p_term q; {
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);
}
}
@ -739,7 +737,7 @@ codeforterm(q,safety,toplevel) register p_term q; {
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) {
@ -761,7 +759,7 @@ codeforterm(q,safety,toplevel) register p_term q; {
fputs(c_close, f);/* Close Register ... */
}
}
return t_after(rep, i, noscan);
return t_after(rep, i, gettout(q));
}
STATIC

View file

@ -108,15 +108,11 @@ typedef struct gram {
*/
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 */
@ -125,8 +121,14 @@ typedef struct {
# 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 */
@ -192,11 +194,12 @@ typedef short t_reps,*p_reps;
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 */