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)) {
|
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;
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
if (outsafety <= SAFESCANDONE) return SAFESCANDONE;
|
||||||
return SCANDONE;
|
return SCANDONE;
|
||||||
|
}
|
||||||
|
return outsafety;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
Loading…
Add table
Reference in a new issue