More safety, also after terms and nonterminals.
This commit is contained in:
parent
67beb0c4d5
commit
d07e8114c6
4 changed files with 58 additions and 51 deletions
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in a new issue