Completely new version, generating a much faster parser.

This commit is contained in:
ceriel 1985-11-25 15:47:51 +00:00
parent 5ac646f89f
commit f055d610d3
16 changed files with 1579 additions and 1394 deletions

View file

@ -26,33 +26,64 @@
/* /*
* LLgen.g * LLgen.g
* Defines the grammar of LLgen. * Defines the grammar of LLgen.
* Some routines that are included build the internal structure * Some routines that build the internal structure are also included
*/ */
{ {
# include "types.h" # include "types.h"
# include "io.h" # include "io.h"
# include "tunable.h"
# include "extern.h" # include "extern.h"
# include "assert.h" # include "assert.h"
# include "cclass.h"
# ifndef NORCSID # ifndef NORCSID
static string rcsidb = "$Header$"; static string rcsid = "$Header$";
# endif # endif
p_mem alloc(); p_mem alloc(), new_mem();
string store(); string store();
t_gram search(); p_gram search();
static int nparams; /* parameter count for nonterminals */ static int nparams; /* parameter count for nonterminals */
static t_gram elem; /* temporary space */
static int acount; /* count #of global actions */ static int acount; /* count #of global actions */
static t_info term_info,
link_info;
static p_order order,
maxorder;
/* Here are defined : */ /* Here are defined : */
extern a_init();
STATIC p_order neworder();
STATIC copyact(); STATIC copyact();
STATIC unsigned get(); STATIC mkalt();
STATIC t_gram mkalt(); STATIC mkterm();
STATIC t_gram mkterm();
STATIC p_gram copyrule(); STATIC p_gram copyrule();
/* and of course LLparse() */
a_init() {
term_info.i_esize = sizeof (t_term);
term_info.i_incr = 50;
link_info.i_esize = sizeof (t_link);
link_info.i_incr = 50;
name_init();
}
STATIC p_order
neworder(index) {
register p_order po;
if ((po = order) == maxorder) {
po = (p_order) alloc(20 * sizeof(*order));
maxorder = po + 20;
}
order = po + 1;
po->o_next = 0;
po->o_index = index;
if (porder) {
porder->o_next = po;
}
else sorder = po;
return po;
}
} }
%start LLparse, spec; %start LLparse, spec;
@ -62,7 +93,7 @@ spec : { acount = 0; }
{ /* { /*
* Put an endmarker in temporary file * Put an endmarker in temporary file
*/ */
putc('\0',fact); putc('\0',fact); fprintf(fact,"%c%c",'\0', '\0');
} }
; ;
@ -85,12 +116,12 @@ def { register string p; }
* Put the declaration in the list * Put the declaration in the list
* of start symbols * of start symbols
*/ */
t_gram temp; register p_gram temp;
register p_start ff; register p_start ff;
temp = search(NONTERM,lextoken.t_string,BOTH); temp = search(NONTERM,lextoken.t_string,BOTH);
ff = (p_start) alloc(sizeof(t_start)); ff = (p_start) alloc(sizeof(t_start));
ff->ff_nont = &nonterms[g_getnont(&temp)]; ff->ff_nont = g_getnont(temp);
ff->ff_name = p; ff->ff_name = p;
ff->ff_next = start; ff->ff_next = start;
start = ff; start = ff;
@ -98,7 +129,8 @@ def { register string p; }
| C_LEXICAL C_IDENT | C_LEXICAL C_IDENT
{ if (!lexical) { { if (!lexical) {
lexical = store(lextoken.t_string); lexical = store(lextoken.t_string);
} else error(linecount,"Duplicate %%lexical"); }
else error(linecount,"Duplicate %%lexical");
} }
';' ';'
/* /*
@ -118,17 +150,18 @@ def { register string p; }
listel : C_IDENT { search(TERMINAL,lextoken.t_string,ENTERING); } listel : C_IDENT { search(TERMINAL,lextoken.t_string,ENTERING); }
; ;
rule { register p_nont p;} rule { register p_nont p;
p_gram rr;
register p_gram temp;
}
: /* : /*
* grammar for a production rule * grammar for a production rule
*/ */
C_IDENT { t_gram temp; C_IDENT { temp = search(NONTERM,lextoken.t_string,BOTH);
p = &nonterms[g_getnont(temp)];
temp = search(NONTERM,lextoken.t_string,BOTH);
p = &nonterms[g_getnont(&temp)];
if (p->n_rule) { if (p->n_rule) {
error(linecount, error(linecount,
"nonterminal already defined"); "nonterminal %s already defined", lextoken.t_string);
} }
/* /*
* Remember the order in which the nonterminals * Remember the order in which the nonterminals
@ -136,20 +169,26 @@ rule { register p_nont p;}
* order to keep track with the actions on the * order to keep track with the actions on the
* temporary file * temporary file
*/ */
*maxorder++ = p - nonterms; porder = neworder(p - nonterms);
p->n_count = acount; p->n_count = acount;
acount = 0; acount = 0;
p->n_lineno = linecount; p->n_lineno = linecount;
} }
[ params(2) { p->n_flags |= PARAMS; [ params(2) { p->n_flags |= PARAMS;
if (nparams > 7) { if (nparams > 15) {
error(linecount,"Too many parameters"); error(linecount,"Too many parameters");
} else setntparams(p,nparams); }
else setntparams(p,nparams);
} }
]? ]?
[ action(0) { p->n_flags |= LOCALS; } [ action(0) { p->n_flags |= LOCALS; }
]? ]?
':' productions(&(p->n_rule)) ';' ':' productions(&rr) ';'
/*
* Do not use p->n_rule now! The nonterms array
* might have been re-allocated.
*/
{ nonterms[g_getnont(temp)].n_rule = rr;}
; ;
action(int n;) action(int n;)
@ -173,73 +212,80 @@ productions(p_gram *p;)
register p_gram p_alts = alts; register p_gram p_alts = alts;
int o_lc, n_lc; int o_lc, n_lc;
} : } :
{ n_lc = o_lc = linecount; } { o_lc = linecount; }
simpleproduction(p,&conflres) simpleproduction(p,&conflres)
{ if (conflres & DEF) haddefault = 1; }
[
[ '|' { n_lc = linecount; } [ '|' { n_lc = linecount; }
[ C_DEFAULT { if (haddefault) {
error(linecount,
"multiple %%default");
}
haddefault = 1;
t |= DEF;
}
]?
simpleproduction(&prod,&t) simpleproduction(&prod,&t)
{ if (p_alts - alts >= 97) { { if (p_alts - alts >= 97) {
error(n_lc,"Too many alternatives"); error(n_lc,"Too many alternatives");
p_alts = alts; p_alts = alts;
} }
*p_alts++ = mkalt(*p,conflres,o_lc); if (t & DEF) {
if (haddefault) {
error(n_lc,
"More than one %%default in alternation");
}
haddefault = 1;
}
mkalt(*p,conflres,o_lc,p_alts++);
o_lc = n_lc; o_lc = n_lc;
conflres = t; conflres = t;
t = 0; t = 0;
*p = prod; *p = prod;
} }
]* { if (conflres & ~DEF) { ]+ { if (conflres & ~DEF) {
error(n_lc, error(n_lc,
"Resolver on last alternative"); "Resolver on last alternative not allowed");
} }
if (p_alts > alts) { mkalt(*p,conflres,n_lc,p_alts++);
*p_alts++ = mkalt(*p,conflres,n_lc);
g_settype(p_alts,EORULE); g_settype(p_alts,EORULE);
*p = copyrule(alts,p_alts+1-alts); *p = copyrule(alts,p_alts+1-alts);
if (!haddefault) {
((p_link) pentry[g_getcont(*p)])
->l_flag |= DEF;
} }
|
{ if (conflres & ~DEF) {
error(o_lc,
"No alternation conflict resolver allowed here");
} }
/*
if (conflres & DEF) {
error(o_lc,
"No %%default allowed here");
} }
*/
}
]
; ;
{ {
STATIC t_gram STATIC
mkalt(prod,condition,lc) p_gram prod; { mkalt(prod,condition,lc,res) p_gram prod; register p_gram res; {
/* /*
* Create an alternation, initialise it and return * Create an alternation and initialise it.
* a grammar element containing it
*/ */
register unsigned hulp; register int hulp;
register p_link l; register p_link l;
t_gram r;
g_init(&r); l = (p_link) new_mem(&link_info);
hulp = get(sizeof(*l)); links = (p_link) link_info.i_ptr;
l = (p_link) pentry[hulp]; hulp = l - links;
l->l_rule = prod; l->l_rule = prod;
l->l_flag = condition; l->l_flag = condition;
g_setcont(&r,hulp); g_setcont(res,hulp);
g_settype(&r,ALTERNATION); g_settype(res,ALTERNATION);
r.g_lineno = lc; res->g_lineno = lc;
return r;
} }
} }
simpleproduction(p_gram *p; register int *conflres;) simpleproduction(p_gram *p; register int *conflres;)
{ t_gram rule[100]; { t_gram rule[100];
t_gram elem;
register p_gram p_rule = rule; register p_gram p_rule = rule;
t_reps reps; int cnt, kind;
} : } :
{ r_init(&reps); } [ C_DEFAULT { *conflres = DEF; }
]?
[ [
/* /*
* Optional conflict reslover * Optional conflict reslover
@ -248,92 +294,91 @@ simpleproduction(p_gram *p; register int *conflres;)
| C_PREFER { *conflres |= PREFERING; } | C_PREFER { *conflres |= PREFERING; }
| C_AVOID { *conflres |= AVOIDING; } | C_AVOID { *conflres |= AVOIDING; }
]? ]?
[ %persistent elem [ %persistent elem(&elem)
{ if (p_rule - rule >= 98) { { if (p_rule - rule >= 98) {
error(linecount,"Production too long"); error(linecount,"Production too long");
p_rule = rule; p_rule = rule;
} }
r_setkind(&reps,FIXED); kind = FIXED;
r_setnum(&reps,0); cnt = 0;
} }
[ repeats(&reps) [ repeats(&kind, &cnt)
{ if (g_gettype(&elem) != TERM) { { if (g_gettype(&elem) != TERM) {
*p_rule = elem; *p_rule = elem;
g_settype(p_rule+1,EORULE); g_settype(p_rule+1,EORULE);
elem = mkterm(copyrule(p_rule,2), mkterm(copyrule(p_rule,2),
0, 0,
&reps, p_rule->g_lineno,
p_rule->g_lineno); &elem);
} }
} }
]? { if (g_gettype(&elem) == TERM) { ]? { if (g_gettype(&elem) == TERM) {
register p_term q; register p_term q;
q = (p_term) pentry[g_getcont(&elem)]; q = &terms[g_getcont(&elem)];
q->t_reps = reps; r_setkind(q,kind);
if (q->t_flags & RESOLVER && r_setnum(q,cnt);
(r_getkind(&reps) == PLUS || if ((q->t_flags & RESOLVER) &&
r_getkind(&reps) == FIXED)) { (kind == PLUS || kind == FIXED)) {
error(linecount, error(linecount,
"illegal %%while"); "%%while not allowed in this term");
} }
if (q->t_flags & PERSISTENT && /*
r_getkind(&reps) == FIXED) { * A persistent fixed term is the same
* as a non-persistent fixed term.
* Should we complain?
if ((q->t_flags & PERSISTENT) &&
kind == FIXED) {
error(linecount, error(linecount,
"illegal %%persistent"); "illegal %%persistent");
} }
*/
} }
*p_rule++ = elem; *p_rule++ = elem;
} }
]* { register p_term q; ]* { register p_term q;
g_settype(p_rule,EORULE); g_settype(p_rule,EORULE);
*p = 0;
if (g_gettype(&rule[0]) == TERM && if (g_gettype(&rule[0]) == TERM &&
p_rule-rule == 1) { p_rule-rule == 1) {
q=(p_term)pentry[g_getcont(&rule[0])]; q = &terms[g_getcont(&rule[0])];
if (r_getkind(&(q->t_reps))==FIXED && if (r_getkind(q) == FIXED &&
r_getnum(&(q->t_reps)) == 0) { r_getnum(q) == 0) {
*p = q->t_rule; *p = q->t_rule;
} }
else *p = copyrule(rule,2);
} }
else *p = copyrule(rule,p_rule-rule+1); if (!*p) *p = copyrule(rule,p_rule-rule+1);
} }
; ;
{ {
STATIC t_gram STATIC
mkterm(prod,flags,reps,lc) p_gram prod; register p_reps reps; { mkterm(prod,flags,lc, result) p_gram prod; register p_gram result; {
/* /*
* Create a term, initialise it and return * Create a term, initialise it and return
* a grammar element contianing it * a grammar element containing it
*/ */
register p_term q; register p_term q;
register unsigned hulp; unsigned hulp;
t_gram r;
g_init(&r); q = (p_term) new_mem(&term_info);
hulp = get(sizeof(*q)); terms = (p_term) term_info.i_ptr;
q = (p_term) pentry[hulp]; hulp = q - terms;
q->t_rule = prod; q->t_rule = prod;
q->t_contains = 0; q->t_contains = 0;
/* "*1" = "?" */
if (r_getnum(reps) == 1 && r_getkind(reps) == STAR) {
r_setkind(reps,OPT);
}
q->t_reps = *reps;
q->t_flags = flags; q->t_flags = flags;
g_settype(&r,TERM); g_settype(result,TERM);
g_setcont(&r,hulp); g_setcont(result,hulp);
r.g_lineno = lc; result->g_lineno = lc;
return r;
} }
} }
elem { register short t = 0; elem (register p_gram pres;)
{ register short t = 0;
p_gram p1; p_gram p1;
t_reps reps;
int ln; int ln;
p_gram pe;
} : } :
'[' { ln = linecount; } '[' { ln = linecount; }
[ C_WHILE expr { t |= RESOLVER; } [ C_WHILE expr { t |= RESOLVER; }
@ -341,23 +386,27 @@ elem { register short t = 0;
[ C_PERSISTENT { t |= PERSISTENT; } [ C_PERSISTENT { t |= PERSISTENT; }
]? ]?
productions(&p1) productions(&p1)
']' { r_init(&reps); ']' {
elem = mkterm(p1,t,&reps,ln); mkterm(p1,t,ln,pres);
} }
| %default |
C_IDENT { elem = search(UNKNOWN,lextoken.t_string,BOTH); } C_IDENT { pe = search(UNKNOWN,lextoken.t_string,BOTH);
[ params(0) { if (nparams > 6) { *pres = *pe;
}
[ params(0) { if (nparams > 14) {
error(linecount,"Too many parameters"); error(linecount,"Too many parameters");
} else g_setnpar(&elem,nparams+1); } else g_setnpar(pres,nparams+1);
if (g_gettype(&elem) == TERMINAL) { if (g_gettype(pres) == TERMINAL) {
error(linecount, error(linecount,
"Terminal with parameters"); "Terminal with parameters");
} }
} }
]? ]?
| C_LITERAL { elem = search(LITERAL,lextoken.t_string,BOTH); } | C_LITERAL { pe = search(LITERAL,lextoken.t_string,BOTH);
| { g_settype(&elem,ACTION); *pres = *pe;
elem.g_lineno = linecount; }
| { g_settype(pres,ACTION);
pres->g_lineno = linecount;
} }
action(1) action(1)
; ;
@ -371,20 +420,21 @@ expr : '(' { copyact('(',')',1,0); }
')' ')'
; ;
repeats(t_reps *t;) { int t1 = 0; } : repeats(int *kind, *cnt;) { int t1 = 0; } :
[ [
'?' { r_setkind(t,OPT); } '?' { *kind = OPT; }
| [ '*' { r_setkind(t,STAR); } | [ '*' { *kind = STAR; }
| '+' { r_setkind(t,PLUS); } | '+' { *kind = PLUS; }
] ]
number(&t1)? number(&t1)?
{ if (t1 == 1 && r_getkind(t) == PLUS) { { if (t1 == 1) {
error(linecount, t1 = 0;
"Illegal repetition specifier"); if (*kind == STAR) *kind = OPT;
if (*kind == PLUS) *kind = FIXED;
} }
} }
| number(&t1) | number(&t1)
] { r_setnum(t,t1); } ] { *cnt = t1; }
; ;
number(int *t;) number(int *t;)
@ -404,12 +454,12 @@ firsts { register string p; }
* Store this %first in the list belonging * Store this %first in the list belonging
* to this input file * to this input file
*/ */
t_gram temp; p_gram temp;
register p_first ff; register p_first ff;
temp = search(NONTERM,lextoken.t_string,BOTH); temp = search(NONTERM,lextoken.t_string,BOTH);
ff = (p_first) alloc(sizeof(t_first)); ff = (p_first) alloc(sizeof(t_first));
ff->ff_nont = &nonterms[g_getnont(&temp)]; ff->ff_nont = g_getnont(temp);
ff->ff_name = p; ff->ff_name = p;
ff->ff_next = pfile->f_firsts; ff->ff_next = pfile->f_firsts;
pfile->f_firsts = ff; pfile->f_firsts = ff;
@ -436,11 +486,9 @@ copyact(ch1,ch2,flag,level) char ch1,ch2; {
if (!level) { if (!level) {
saved = linecount; saved = linecount;
nparams = 0; /* count comma's */ nparams = 0; /* count comma's */
putc('\0',f); fprintf(f,"%c# line %d \"%s\"\n", '\0', linecount,f_input);
fprintf(f,"# line %d \"%s\"\n", linecount,f_input);
if (flag == 1) putc(ch1,f);
} }
else putc(ch1,f); if (level || flag == 1) putc(ch1,f);
for (;;) { for (;;) {
ch = input(); ch = input();
if (ch == ch2) { if (ch == ch2) {
@ -451,7 +499,7 @@ copyact(ch1,ch2,flag,level) char ch1,ch2; {
} }
return; return;
} }
if (! isspace(ch)) semicolon = 0; if (c_class[ch] != ISSPA) semicolon = 0;
switch(ch) { switch(ch) {
case ')': case ')':
case '}': case '}':
@ -474,6 +522,7 @@ copyact(ch1,ch2,flag,level) char ch1,ch2; {
skipcomment(1); skipcomment(1);
continue; continue;
} }
ch = '/';
break; break;
case ';': case ';':
semicolon = 1; semicolon = 1;
@ -516,21 +565,8 @@ copyact(ch1,ch2,flag,level) char ch1,ch2; {
} }
} }
static int ecount; /* Index in "pentry" array */
STATIC unsigned
get(size) unsigned size; {
/*
* Get some core, save a pointer to it in "pentry",
* return index in pentry
*/
if (ecount >= ENTSIZ) fatal(linecount,"Entry table overflow");
pentry[ecount] = alloc(size);
return ecount++;
}
STATIC p_gram STATIC p_gram
copyrule(p,length) register p_gram p; register length; { copyrule(p,length) register p_gram p; {
/* /*
* Returns a pointer to a grammar rule that was created in * Returns a pointer to a grammar rule that was created in
* p. The space pointed to by p can now be reused * p. The space pointed to by p can now be reused

View file

@ -1,11 +1,11 @@
# $Header$ # $Header$
PROF= PROF=
LLOPT= # -vvv -x LLOPT= # -vvv -x
CFLAGS=$(PROF) -O -DNDEBUG # -R CFLAGS=$(PROF) -O -DNDEBUG
LDFLAGS=-i LDFLAGS=-i
OBJECTS = main.o gencode.o compute.o LLgen.o tokens.o check.o reach.o global.o name.o sets.o Lpars.o alloc.o machdep.o OBJECTS = main.o gencode.o compute.o LLgen.o tokens.o check.o reach.o global.o name.o sets.o Lpars.o alloc.o machdep.o cclass.o
CFILES = main.c gencode.c compute.c LLgen.c tokens.c check.c reach.c global.c name.c sets.c Lpars.c alloc.c machdep.c CFILES = main.c gencode.c compute.c LLgen.c tokens.c check.c reach.c global.c name.c sets.c Lpars.c alloc.c machdep.c cclass.c
FILES =types.h tunable.h extern.h io.h sets.h assert.h tokens.g LLgen.g main.c name.c compute.c sets.c gencode.c global.c check.c reach.c alloc.c machdep.c Makefile FILES =types.h tunable.h extern.h io.h sets.h assert.h tokens.g LLgen.g main.c name.c compute.c sets.c gencode.c global.c check.c reach.c alloc.c machdep.c Makefile cclass.c
GFILES = tokens.g LLgen.g GFILES = tokens.g LLgen.g
LINT = lint -b -DNDEBUG -DNORCSID LINT = lint -b -DNDEBUG -DNORCSID
@ -39,9 +39,9 @@ distr:
# AUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTO # AUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTO
LLgen.o: Lpars.h LLgen.o: Lpars.h
LLgen.o: assert.h LLgen.o: assert.h
LLgen.o: cclass.h
LLgen.o: extern.h LLgen.o: extern.h
LLgen.o: io.h LLgen.o: io.h
LLgen.o: tunable.h
LLgen.o: types.h LLgen.o: types.h
Lpars.o: Lpars.h Lpars.o: Lpars.h
alloc.o: extern.h alloc.o: extern.h
@ -50,22 +50,20 @@ check.o: assert.h
check.o: extern.h check.o: extern.h
check.o: io.h check.o: io.h
check.o: sets.h check.o: sets.h
check.o: tunable.h
check.o: types.h check.o: types.h
compute.o: assert.h compute.o: assert.h
compute.o: extern.h compute.o: extern.h
compute.o: io.h compute.o: io.h
compute.o: sets.h compute.o: sets.h
compute.o: tunable.h
compute.o: types.h compute.o: types.h
gencode.o: assert.h gencode.o: assert.h
gencode.o: cclass.h
gencode.o: extern.h gencode.o: extern.h
gencode.o: io.h gencode.o: io.h
gencode.o: sets.h gencode.o: sets.h
gencode.o: tunable.h
gencode.o: types.h gencode.o: types.h
global.o: extern.h
global.o: io.h global.o: io.h
global.o: tunable.h
global.o: types.h global.o: types.h
machdep.o: ../../../h/em_path.h machdep.o: ../../../h/em_path.h
machdep.o: types.h machdep.o: types.h
@ -77,12 +75,10 @@ main.o: types.h
name.o: assert.h name.o: assert.h
name.o: extern.h name.o: extern.h
name.o: io.h name.o: io.h
name.o: tunable.h
name.o: types.h name.o: types.h
reach.o: assert.h reach.o: assert.h
reach.o: extern.h reach.o: extern.h
reach.o: io.h reach.o: io.h
reach.o: tunable.h
reach.o: types.h reach.o: types.h
sets.o: assert.h sets.o: assert.h
sets.o: extern.h sets.o: extern.h
@ -90,7 +86,7 @@ sets.o: sets.h
sets.o: types.h sets.o: types.h
tokens.o: Lpars.h tokens.o: Lpars.h
tokens.o: assert.h tokens.o: assert.h
tokens.o: cclass.h
tokens.o: extern.h tokens.o: extern.h
tokens.o: io.h tokens.o: io.h
tokens.o: tunable.h
tokens.o: types.h tokens.o: types.h

View file

@ -32,14 +32,17 @@
# include "extern.h" # include "extern.h"
# ifndef NORCSID # ifndef NORCSID
static string rcsida = "$Header$"; static string rcsid = "$Header$";
# endif # endif
static string e_nomem = "Out of memory"; static string e_nomem = "Out of memory";
p_mem p_mem
alloc(size) unsigned size; { alloc(size) unsigned size; {
register p_mem p; /*
Allocate "size" bytes. Panic if it fails
*/
p_mem p;
p_mem malloc(); p_mem malloc();
if ((p = malloc(size)) == 0) fatal(linecount,e_nomem); if ((p = malloc(size)) == 0) fatal(linecount,e_nomem);
@ -48,9 +51,41 @@ alloc(size) unsigned size; {
p_mem p_mem
ralloc(p,size) p_mem p; unsigned size; { ralloc(p,size) p_mem p; unsigned size; {
register p_mem q; /*
Re-allocate the chunk of memory indicated by "p", to
occupy "size" bytes
*/
p_mem realloc(); p_mem realloc();
if ((q = realloc(p,size)) == 0) fatal(linecount,e_nomem); if ((p = realloc(p,size)) == 0) fatal(linecount,e_nomem);
return q; return p;
}
p_mem
new_mem(p) p_info p; {
/*
This routine implements arrays that can grow.
It must be called every time a new element is added to it.
Also, the array has associated with it a "info_alloc" structure,
which contains info on the element size, total allocated size,
a pointer to the array, a pointer to the first free element,
and a pointer to the top.
If the base of the array is remembered elsewhere, it should
be updated each time this routine is called
*/
p_mem rp;
unsigned sz;
if (p->i_max >= p->i_top) { /* No more free elements */
sz = p->i_size;
p->i_size += p->i_incr * p->i_esize;
p->i_ptr = !p->i_ptr ?
alloc(p->i_size) :
ralloc(p->i_ptr, p->i_size);
p->i_max = p->i_ptr + sz;
p->i_top = p->i_ptr + p->i_size;
}
rp = p->i_max;
p->i_max += p->i_esize;
return rp;
} }

View file

@ -30,7 +30,6 @@
# include "types.h" # include "types.h"
# include "extern.h" # include "extern.h"
# include "tunable.h"
# include "io.h" # include "io.h"
# include "sets.h" # include "sets.h"
# include "assert.h" # include "assert.h"
@ -39,21 +38,18 @@
static string rcsid1 = "$Header$"; static string rcsid1 = "$Header$";
# endif # endif
# define PTERM(p) fprintf(fout,(p)->h_num < 0400 ? "'%s' " : "%s ",(p)->h_name);
static string c_first = "> firstset "; static string c_first = "> firstset ";
static string c_contains = "> containset "; static string c_contains = "> containset ";
static string c_follow = "> followset "; static string c_follow = "> followset ";
p_set setalloc(); p_set setalloc();
static string ntname; /* nonterminal that is currently checked */
static p_nont nt; /* pointer to its struct */
static int level; static int level;
/* In this file are defined : */ /* In this file are defined : */
extern conflchecks(); extern conflchecks();
STATIC newline(); STATIC prline();
STATIC printset(); STATIC printset();
STATIC check(); STATIC int check();
STATIC moreverbose(); STATIC moreverbose();
STATIC prrule(); STATIC prrule();
STATIC cfcheck(); STATIC cfcheck();
@ -70,8 +66,7 @@ conflchecks() {
* must be disjunct. * must be disjunct.
*/ */
register p_nont p; register p_nont p;
register FILE *f; register p_order s;
register short *s;
p_file x = files; p_file x = files;
f_input = x->f_name; f_input = x->f_name;
@ -79,38 +74,43 @@ conflchecks() {
for (p = nonterms; p < maxnt; p++) p->n_flags |= VERBOSE; for (p = nonterms; p < maxnt; p++) p->n_flags |= VERBOSE;
} }
if (verbose) { if (verbose) {
if ((f = fopen(f_out,"w")) == NULL) fatal(1,e_noopen,f_out); if ((fout = fopen(f_out,"w")) == NULL) fatal(1,e_noopen,f_out);
fout = f;
} }
/* /*
* Check the rules in the order in which they are declared, * Check the rules in the order in which they are declared,
* and input file by input file, to give proper error messages * and input file by input file, to give proper error messages
*/ */
for (; x->f_end < maxorder; x++) { for (; x < maxfiles; x++) {
f_input = x->f_name; f_input = x->f_name;
for (s = x->f_start; s <= x->f_end; s++) { for (s = x->f_list; s; s = s->o_next) {
nt = p = &nonterms[*s]; p = &nonterms[s->o_index];
ntname = (min_nt_ent + *s)->h_name; if (check(p->n_rule)) p->n_flags |= VERBOSE;
}
}
for (x = files; x < maxfiles; x++) {
f_input = x->f_name;
for (s = x->f_list; s; s = s->o_next) {
p = &nonterms[s->o_index];
if (p->n_flags & RECURSIVE) { if (p->n_flags & RECURSIVE) {
error(p->n_lineno, error(p->n_lineno,
"Recursion in default for nonterminal %s", "Recursion in default for nonterminal %s",
ntname); p->n_name);
} }
check(p->n_rule);
/* /*
* If a printout is needed for this rule in * If a printout is needed for this rule in
* LL.output, just do it * LL.output, just do it
*/ */
if (verbose && (p->n_flags & VERBOSE)) { if (verbose && (p->n_flags & VERBOSE)) {
fprintf(f,"\n%s :\n",ntname); fprintf(fout,"\n%s :\n",p->n_name);
printset(p->n_first,c_first); printset(p->n_first,c_first);
printset(p->n_contains,c_contains); printset(p->n_contains,c_contains);
printset(p->n_follow,c_follow); printset(p->n_follow,c_follow);
fputs("> rule\n\t",f); fprintf(fout,"> rule%s\n\t",
p->n_flags&EMPTY ? "\t(EMPTY producing)" : "");
level = 8; level = 8;
prrule(p->n_rule); prrule(p->n_rule);
level = 0; level = 0;
newline(); prline("\n");
} }
/* /*
* Now, the conflicts may be resolved * Now, the conflicts may be resolved
@ -118,16 +118,13 @@ conflchecks() {
resolve(p->n_rule); resolve(p->n_rule);
} }
} }
if (verbose) fclose(f); if (verbose) fclose(fout);
} }
STATIC STATIC
newline() { prline(s) char *s; {
/* fputs(s, fout);
* Newline and "level" spaces indentation spaces();
*/
if (level > 0) fprintf(fout,"\n%*c",level,' ');
else putc('\n',fout);
} }
STATIC STATIC
@ -135,37 +132,35 @@ printset(p,s) register p_set p; string s; {
/* /*
* Print the elements of a set * Print the elements of a set
*/ */
register FILE *f; register int i;
register i; register int j;
register j; register p_token pt;
string name;
int k; int k;
int hulp; int hulp;
k = strlen(s)+1; k = strlen(s) + 2 + level;
/* /*
* k contains relative level of indentation * k contains relative level of indentation
*/ */
f = fout; fprintf(fout,"%s{ ",s);
fprintf(f,"%s{ ",s); j = k;
j = level+1+k;
/* /*
* j will gather the total length of the line * j will gather the total length of the line
*/ */
if (p == (p_set) 0) fputs(">non existent (yet?)< ",f); for (i = 0, pt = tokens; i < ntokens; i++,pt++) {
else {
for (i = 0; i < nterminals; i++) {
if (IN(p,i)) { if (IN(p,i)) {
hulp = strlen(h_entry[i].h_name)+1; hulp = strlen(pt->t_string)+1;
if (h_entry[i].h_num < 0400) hulp += 2; if (pt->t_tokno < 0400) hulp += 2;
if ((j += hulp) >= 78) { if ((j += hulp) >= 78) {
/* /*
* Line becoming too long * Line becoming too long
*/ */
j = level+k+1+hulp; j = k+hulp;
newline(); prline("\n");
fprintf(f,">%*c",k,' '); fprintf(fout,">%*c",k - level - 1,' ');
} }
PTERM(&h_entry[i]); fprintf(fout, pt->t_tokno<0400 ? "'%s' " : "%s ",pt->t_string);
} }
} }
if (ntprint) for (i = 0; i < nnonterms; i++) { if (ntprint) for (i = 0; i < nnonterms; i++) {
@ -173,31 +168,32 @@ printset(p,s) register p_set p; string s; {
* Nonterminals in the set must also be printed * Nonterminals in the set must also be printed
*/ */
if (NTIN(p,i)) { if (NTIN(p,i)) {
hulp = strlen((min_nt_ent+i)->h_name)+3; name = nonterms[i].n_name;
hulp = strlen(name) + 3;
if ((j += hulp) >= 78) { if ((j += hulp) >= 78) {
j = level + k + 1 + hulp; j = k + hulp;
newline(); prline("\n");
fprintf(f,">%*c",k,' '); fprintf(fout,">%*c",k - level - 1,' ');
} }
fprintf(f,"<%s> ",(min_nt_ent+i)->h_name); fprintf(fout,"<%s> ",name);
} }
} }
} prline("}\n");
putc('}',f);
newline();
} }
STATIC STATIC int
check(p) register p_gram p; { check(p) register p_gram p; {
/* /*
* Search for conflicts in a grammar rule. * Search for conflicts in a grammar rule.
*/ */
p_set temp; register p_set temp;
register int retval;
retval = 0;
for (;;) { for (;;) {
switch (g_gettype(p)) { switch (g_gettype(p)) {
case EORULE : case EORULE :
return; return retval;
case NONTERM : { case NONTERM : {
register p_nont n; register p_nont n;
@ -205,28 +201,28 @@ check(p) register p_gram p; {
if (g_getnpar(p) != getntparams(n)) { 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); n->n_name);
} }
break; } break; }
case TERM : { case TERM : {
register p_term q; register p_term q;
q = (p_term) pentry[g_getcont(p)]; q = &terms[g_getcont(p)];
check(q->t_rule); retval |= check(q->t_rule);
if (r_getkind(&(q->t_reps)) == FIXED) break; if (r_getkind(q) == FIXED) break;
if (setempty(q->t_first)) { if (setempty(q->t_first)) {
q->t_flags |= EMPTYFIRST; q->t_flags |= EMPTYFIRST;
nt->n_flags |= VERBOSE; retval = 1;
error(p->g_lineno, "No symbols in term"); error(p->g_lineno, "No symbols in term");
} }
if (empty(q->t_rule)) { if (empty(q->t_rule)) {
q->t_flags |= EMPTYTERM; q->t_flags |= EMPTYTERM;
nt->n_flags |= VERBOSE; retval = 1;
error(p->g_lineno, "Term produces empty"); error(p->g_lineno, "Term produces empty");
} }
temp = setalloc(setsize); temp = setalloc();
setunion(temp,q->t_first,setsize); setunion(temp,q->t_first);
if (!setintersect(temp,q->t_follow,setsize)) { if (!setintersect(temp,q->t_follow)) {
/* /*
* q->t_first * q->t_follow != EMPTY * q->t_first * q->t_follow != EMPTY
*/ */
@ -235,16 +231,17 @@ check(p) register p_gram p; {
* No conflict resolver * No conflict resolver
*/ */
error(p->g_lineno, error(p->g_lineno,
"Repitition conflict"); "Repetition conflict");
nt->n_flags |= VERBOSE; retval = 1;
if (verbose == 2) moreverbose(temp); moreverbose(temp);
} }
} else { }
else {
if (q->t_flags & RESOLVER) { if (q->t_flags & RESOLVER) {
q->t_flags |= NOCONF; q->t_flags |= NOCONF;
error(p->g_lineno, error(p->g_lineno,
"%%while, no conflict"); "%%while, no conflict");
nt->n_flags |= VERBOSE; retval = 1;
} }
} }
free((p_mem) temp); free((p_mem) temp);
@ -252,29 +249,30 @@ check(p) register p_gram p; {
case ALTERNATION : { case ALTERNATION : {
register p_link l; register p_link l;
l = (p_link) pentry[g_getcont(p)]; l = &links[g_getcont(p)];
temp = setalloc(setsize); temp = setalloc();
setunion(temp,l->l_symbs,setsize); setunion(temp,l->l_symbs);
if(!setintersect(temp,l->l_others,setsize)) { if(!setintersect(temp,l->l_others)) {
/* /*
* temp now contains the conflicting * temp now contains the conflicting
* symbols * symbols
*/ */
if (!(l->l_flag & (COND|PREFERING|AVOIDING))) { if (!(l->l_flag & (COND|PREFERING|AVOIDING))) {
error(p->g_lineno, error(p->g_lineno,
"Alternation conflict"); "Alternation conflict");
nt->n_flags |= VERBOSE; retval = 1;
if (verbose == 2) moreverbose(temp); moreverbose(temp);
} }
} else { } else {
if (l->l_flag & (COND|PREFERING|AVOIDING)) { if (l->l_flag & (COND|PREFERING|AVOIDING)) {
l->l_flag |= NOCONF; l->l_flag |= NOCONF;
error(p->g_lineno,"No conflict"); error(p->g_lineno,
nt->n_flags |= VERBOSE; "Conflict resolver without conflict");
retval = 1;
} }
} }
free( (p_mem) temp); free( (p_mem) temp);
check(l->l_rule); retval |= check(l->l_rule);
break; } break; }
} }
p++; p++;
@ -288,10 +286,11 @@ moreverbose(t) register p_set t; {
* also containing nonterminals. * also containing nonterminals.
* Take care that a printout will be prepared for these nonterminals * Take care that a printout will be prepared for these nonterminals
*/ */
register i; register int i;
register p_nont p;
if (verbose) for (i = 0; i < nnonterms; i++) { if (verbose == 2) for (i = 0, p = nonterms; i < nnonterms; i++, p++) {
if (NTIN(t,i)) nonterms[i].n_flags |= VERBOSE; if (NTIN(t,i)) p->n_flags |= VERBOSE;
} }
} }
@ -307,33 +306,31 @@ prrule(p) register p_gram p; {
for (;;) { for (;;) {
switch (g_gettype(p)) { switch (g_gettype(p)) {
case EORULE : case EORULE :
putc('\n',f); fputs("\n",f);
return; return;
case TERM : { case TERM : {
register p_term q; register p_term q;
register c; register int c;
q = (p_term) pentry[g_getcont(p)]; q = &terms[g_getcont(p)];
if (present) newline(); if (present) prline("\n");
if (r_getkind(&(q->t_reps)) != FIXED ||
r_getnum(&(q->t_reps)) != 0) {
fputs("[ ",f); fputs("[ ",f);
level += 4; level += 4;
if (q->t_flags & RESOLVER) { if (q->t_flags & RESOLVER) {
fputs("%%while (..)",f); prline("%while (..)\n");
newline();
} }
if (r_getkind(&(q->t_reps)) != FIXED) { if (q->t_flags & PERSISTENT) {
prline("%persistent\n");
}
if (r_getkind(q) != FIXED) {
printset(q->t_first, c_first); printset(q->t_first, c_first);
printset(q->t_contains, c_contains); printset(q->t_contains, c_contains);
printset(q->t_follow,c_follow); printset(q->t_follow,c_follow);
if (q->t_flags & EMPTYFIRST) { if (q->t_flags & EMPTYFIRST) {
fputs(">>> empty first",f); prline(">>> empty first\n");
newline();
} }
if (q->t_flags & EMPTYTERM) { if (q->t_flags & EMPTYTERM) {
fputs(">>> term produces empty",f); prline(">>> term produces empty\n");
newline();
} }
cfcheck(q->t_first,q->t_follow, cfcheck(q->t_first,q->t_follow,
q->t_flags & RESOLVER); q->t_flags & RESOLVER);
@ -341,20 +338,13 @@ prrule(p) register p_gram p; {
prrule(q->t_rule); prrule(q->t_rule);
level -= 4; level -= 4;
spaces(); spaces();
c = r_getkind(&(q->t_reps)); c = r_getkind(q);
putc(']',f); fputs(c == STAR ? "]*" : c == PLUS ? "]+" :
if (c != FIXED) { c == OPT ? "]?" : "]", f);
c = (c==STAR)?'*':(c==PLUS)?'+':'?'; if (c = r_getnum(q)) {
putc(c,f);
}
if (c = r_getnum(&(q->t_reps))) {
fprintf(f,"%d",c); fprintf(f,"%d",c);
} }
newline(); prline("\n");
} else {
prrule(q->t_rule);
spaces();
}
break; } break; }
case ACTION : case ACTION :
fputs("{..} ",f); fputs("{..} ",f);
@ -362,28 +352,44 @@ prrule(p) register p_gram p; {
case ALTERNATION : { case ALTERNATION : {
register p_link l; register p_link l;
l = (p_link) pentry[g_getcont(p)]; l = &links[g_getcont(p)];
if (l->l_flag & (COND|PREFERING|AVOIDING)) { if (g_gettype(p-1) == ALTERNATION) {
printset(l->l_symbs,"> alt with resolver on "); prline("|\n");
} else printset(l->l_symbs,"> alternative on "); }
printset(l->l_symbs,"> alternative on ");
cfcheck(l->l_symbs, cfcheck(l->l_symbs,
l->l_others, l->l_others,
(int)(l->l_flag&(COND|PREFERING|AVOIDING))); (int)(l->l_flag&(COND|PREFERING|AVOIDING)));
fputs(" ",f); fputs(" ",f);
level += 4; level += 4;
if (l->l_flag & DEF) {
prline("%default\n");
}
if (l->l_flag & AVOIDING) {
prline("%avoid\n");
}
if (l->l_flag & PREFERING) {
prline("%prefer\n");
}
if (l->l_flag & COND) {
prline("%if ( ... )\n");
}
prrule(l->l_rule); prrule(l->l_rule);
level -= 4; level -= 4;
spaces();
if (g_gettype(p+1) == EORULE) { if (g_gettype(p+1) == EORULE) {
fputs("> end alternatives\n",f);
return; return;
} }
spaces();
p++; continue; } p++; continue; }
case TERMINAL : case LITERAL :
PTERM(&h_entry[g_getcont(p)]); case TERMINAL : {
break; register p_token pt = &tokens[g_getcont(p)];
fprintf(f,pt->t_tokno<0400 ?
"'%s' " : "%s ", pt->t_string);
break; }
case NONTERM : case NONTERM :
fprintf(f,"%s ",(g_getnont(p)+min_nt_ent)->h_name); fprintf(f,"%s ",nonterms[g_getnont(p)].n_name);
break; break;
} }
p++; p++;
@ -401,17 +407,16 @@ cfcheck(s1,s2,flag) p_set s1,s2; {
*/ */
register p_set temp; register p_set temp;
temp = setalloc(setsize); temp = setalloc();
setunion(temp,s1,setsize); setunion(temp,s1);
if (!setintersect(temp,s2,setsize)) { if (!setintersect(temp,s2)) {
if (! flag) { if (! flag) {
printset(temp,">>> conflict on "); printset(temp,">>> conflict on ");
newline(); prline("\n");
} }
} else { } else {
if (flag) { if (flag) {
fputs(">>> %if/%while, no conflict",fout); prline(">>> %if/%while, no conflict\n");
newline();
} }
} }
free((p_mem) temp); free((p_mem) temp);
@ -427,18 +432,18 @@ resolve(p) register p_gram p; {
case EORULE : case EORULE :
return; return;
case TERM : case TERM :
resolve(((p_term) pentry[g_getcont(p)])->t_rule); resolve(terms[g_getcont(p)].t_rule);
break; break;
case ALTERNATION : { case ALTERNATION : {
register p_link l; register p_link l;
l = (p_link) pentry[g_getcont(p)]; l = &links[g_getcont(p)];
if (l->l_flag & AVOIDING) { if (l->l_flag & AVOIDING) {
/* /*
* On conflicting symbols, this rule * On conflicting symbols, this rule
* is never chosen * is never chosen
*/ */
setminus(l->l_symbs,l->l_others,setsize); setminus(l->l_symbs,l->l_others);
} }
if (setempty(l->l_symbs)) { if (setempty(l->l_symbs)) {
/* /*
@ -461,7 +466,7 @@ propagate(set,p) p_set set; register p_gram p; {
* p will not be chosen. * p will not be chosen.
*/ */
while (g_gettype(p) != EORULE) { while (g_gettype(p) != EORULE) {
setminus(((p_link) pentry[g_getcont(p)])->l_symbs,set,setsize); setminus(links[g_getcont(p)].l_symbs,set);
p++; p++;
} }
} }

File diff suppressed because it is too large Load diff

View file

@ -29,10 +29,12 @@
* some variables that are visible in more than one file * some variables that are visible in more than one file
*/ */
# define LTEXTSZ 51 /* Size of longest token */
/* /*
* options for the identifier search routine * options for the identifier search routine
*/ */
# define JUSTLOOKING 0
# define ENTERING 1 # define ENTERING 1
# define BOTH 2 # define BOTH 2
@ -42,27 +44,22 @@
extern char ltext[]; /* input buffer */ extern char ltext[]; /* input buffer */
extern int nnonterms; /* number of nonterminals */ extern int nnonterms; /* number of nonterminals */
extern int nterminals; /* number of terminals */ extern int ntokens; /* number of terminals */
extern p_start start; /* will contain startsymbols */ extern p_start start; /* will contain startsymbols */
extern int linecount; /* line number */ extern int linecount; /* line number */
extern int assval; /* to create difference between literals extern int assval; /* to create difference between literals
* and other terminals * and other terminals
*/ */
extern t_nont nonterms[]; /* the nonterminal array */ extern p_nont nonterms; /* the nonterminal array */
extern p_nont maxnt; /* is filled up until here */ extern p_nont maxnt; /* is filled up until here */
extern int order[]; /* order of nonterminals in the grammar, extern p_token tokens; /* the token array */
extern p_token maxt; /* is filled up until here */
extern struct order *sorder, *porder;
/* order of nonterminals in the grammar,
* important because actions are copied to * important because actions are copied to
* a temporary file in the order in which they * a temporary file in the order in which they
* were read * were read
*/ */
extern int *maxorder; /* will contain &order[nnonterms] */
extern t_entry h_entry[]; /* terminal and nonterminal entrys,
* first NTERMINAL entrys reserved
* for terminals
*/
extern p_entry max_t_ent; /* will contain &h_entry[nterminals] */
# define min_nt_ent &h_entry[NTERMINALS]
extern string pentry[]; /* pointers to various allocated things */
extern string e_noopen; /* Error message string used often */ extern string e_noopen; /* Error message string used often */
extern int verbose; /* Level of verbosity */ extern int verbose; /* Level of verbosity */
extern string lexical; /* name of lexical analyser */ extern string lexical; /* name of lexical analyser */
@ -78,9 +75,10 @@ extern int debug;
extern p_file files,pfile; /* pointers to file structure. extern p_file files,pfile; /* pointers to file structure.
* "files" points to the start of the * "files" points to the start of the
* list */ * list */
extern p_file maxfiles;
extern string LLgenid; /* LLgen identification string */ extern string LLgenid; /* LLgen identification string */
extern t_token lextoken; /* the current token */ extern t_token lextoken; /* the current token */
extern int nerrors; extern int nerrors;
extern int fflag; /* Enable compiler to generate jump tables extern string rec_file, incl_file;
* for switches? extern p_term terms;
*/ extern p_link links;

View file

@ -32,10 +32,10 @@
# include "types.h" # include "types.h"
# include "io.h" # include "io.h"
# include "tunable.h"
# include "extern.h" # include "extern.h"
# include "sets.h" # include "sets.h"
# include "assert.h" # include "assert.h"
# include "cclass.h"
# ifndef NORCSID # ifndef NORCSID
static string rcsid3 = "$Header$"; static string rcsid3 = "$Header$";
@ -47,7 +47,6 @@ static string rcsid3 = "$Header$";
static string c_arrend = "0 };\n"; static string c_arrend = "0 };\n";
static string c_close = "}\n"; static string c_close = "}\n";
static string c_LLptrmin = "LLptr++;\n";
static string c_break = "break;\n"; static string c_break = "break;\n";
static string c_read = "LLread();\n"; static string c_read = "LLread();\n";
@ -57,10 +56,7 @@ static string c_read = "LLread();\n";
static int nlabel; /* count for the generation of labels */ static int nlabel; /* count for the generation of labels */
static int nvar; /* count for generation of variables */ static int nvar; /* count for generation of variables */
static int pushlist[100]; static int firsts; /* are there any? */
static int *ppushlist;
static int *lists,*maxlists,*plists;
p_mem ralloc(),alloc();
/* In this file the following routines are defined: */ /* In this file the following routines are defined: */
extern gencode(); extern gencode();
@ -75,30 +71,27 @@ STATIC controlline();
STATIC getparams(); STATIC getparams();
STATIC gettok(); STATIC gettok();
STATIC rulecode(); STATIC rulecode();
STATIC int dopush(); STATIC int * dopush();
STATIC pushcode();
STATIC getaction(); STATIC getaction();
STATIC alternation();
STATIC codeforterm(); STATIC codeforterm();
STATIC genifhead(); STATIC genswhead();
STATIC gencases(); STATIC gencases();
STATIC genpush(); STATIC genpush();
STATIC genpop();
STATIC genincrdecr();
/* Macro to print a terminal */ # define NOPOP -20000
# define PTERM(f,p) fprintf(f,(p)->h_num<0400?"'%s'":"%s",(p)->h_name)
p_mem alloc();
gencode(argc) { gencode(argc) {
register p_file p = files; register p_file p = files;
/* Generate include file Lpars.h */
geninclude();
/* Set up for code generation */ /* Set up for code generation */
if ((fact = fopen(f_temp,"r")) == NULL) { if ((fact = fopen(f_temp,"r")) == NULL) {
fatal(0,e_noopen,f_temp); fatal(0,e_noopen,f_temp);
} }
lists = (int *) alloc(50 * sizeof(int));
plists = lists;
maxlists = lists+49;
/* For every source file .... */ /* For every source file .... */
while (argc--) { while (argc--) {
@ -106,7 +99,7 @@ gencode(argc) {
f_input = p->f_name; f_input = p->f_name;
opentemp(f_input); opentemp(f_input);
/* generate code ... */ /* generate code ... */
copyfile(0); copyfile(incl_file);
generate(p); generate(p);
getaction(2); getaction(2);
if (ferror(fpars) != 0) { if (ferror(fpars) != 0) {
@ -117,6 +110,7 @@ gencode(argc) {
install(genname(p->f_name),p->f_name); install(genname(p->f_name),p->f_name);
p++; p++;
} }
geninclude();
genrecovery(); genrecovery();
} }
@ -126,86 +120,98 @@ opentemp(str) string str; {
if ((fpars = fopen(f_pars,"w")) == NULL) { if ((fpars = fopen(f_pars,"w")) == NULL) {
fatal(0,e_noopen,f_pars); fatal(0,e_noopen,f_pars);
} }
fprintf(fpars,LLgenid,str ? str : "."); if (!str) str = ".";
fprintf(fpars,LLgenid,str);
} }
STATIC STATIC
geninclude() { geninclude() {
register p_entry p; register p_token p;
register FILE *f;
opentemp((string) 0); opentemp((string) 0);
f = fpars; for (p = tokens; p < maxt; p++) {
for (p = h_entry; p < max_t_ent; p++) { if (p->t_tokno >= 0400) {
if (p->h_num >= 0400) { fprintf(fpars,"# define %s %d\n",
fprintf(f,"# define %s %d\n", p->h_name,p->h_num); p->t_string,
p->t_tokno);
} }
} }
if (ferror(f) != 0) { if (ferror(fpars) != 0) {
fatal(0,"write error on temporary"); fatal(0,"write error on temporary");
} }
fclose(f); fclose(fpars);
install(HFILE, (string) 0); install(HFILE, ".");
} }
STATIC STATIC
genrecovery() { genrecovery() {
register FILE *f; register FILE *f;
register p_entry t; register p_token t;
register int i;
register int *q; register int *q;
int index[256+NTERMINALS]; register p_nont p;
register p_set *psetl;
int *index;
int i;
register p_start st; register p_start st;
opentemp((string) 0); opentemp((string) 0);
f = fpars; f = fpars;
copyfile(0); copyfile(incl_file);
if (!firsts) fputs("#define LLNOFIRSTS\n", f);
for (st = start; st; st = st->ff_next) {
/* Make sure that every set the parser needs is in the list
* before generating a define of the number of them!
*/
p = &nonterms[st->ff_nont];
if (g_gettype(p->n_rule) == ALTERNATION) {
findindex(p->n_contains);
}
}
i = maxptr - setptr;
fprintf(fpars,
"#define LL_LEXI %s\n#define LL_SSIZE %d\n#define LL_NSETS %d\n#define LL_NTERMINALS %d\n",
lexical,
nbytes,
i > 0 ? i : 1,
ntokens);
/* Now generate the routines that call the startsymbols */ /* Now generate the routines that call the startsymbols */
fputs("#define LLSTSIZ 1024\n",f); for (st = start; st; st = st->ff_next) {
for (i = 1, st = start; st; st = st->ff_next) {
i++;
fputs(st->ff_name, f); fputs(st->ff_name, f);
fputs("() {\n\tint LLstack[LLSTSIZ];\n\tLLnewlevel(LLstack);\n\tLLread();\n", f); p = &nonterms[st->ff_nont];
if (g_gettype(st->ff_nont->n_rule) == ALTERNATION) { fputs("() {\n\tunsigned int s[LL_NTERMINALS+LL_NSETS+1];\n\tLLnewlevel(s);\n\tLLread();\n", f);
fprintf(f, "\tLLxx.LLx_p--; *LLxx.LLx_p = %d;\n", if (g_gettype(p->n_rule) == ALTERNATION) {
findindex(&(st->ff_nont->n_contains))); genpush(findindex(p->n_contains));
} }
fprintf(f, "\tL%d_%s();\n", fprintf(f, "\tL%d_%s();\n",
st->ff_nont-nonterms, st->ff_nont,
(min_nt_ent+(st->ff_nont-nonterms))->h_name); p->n_name);
if (getntout(st->ff_nont) == NOSCANDONE) { if (getntout(p) == 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);
fputs("\tLLoldlevel();\n}\n",f); fputs("\tLLoldlevel(s);\n}\n",f);
} }
fprintf(f,"#define LL_MAX %d\n#define LL_LEXI %s\n", i, lexical);
fputs("static short LLlists[] = {\n", f);
/* Now generate lists */
q = lists;
while (q < plists) {
fprintf(f,"%d,\n",*q++);
}
fputs(c_arrend, f);
/* Now generate the sets */ /* Now generate the sets */
fputs("char LLsets[] = {\n",f); fputs("char LLsets[] = {\n",f);
for (i = 0; i < maxptr-setptr; i++) prset(setptr[i]); for (psetl = setptr; psetl < maxptr; psetl++) prset(*psetl);
fputs(c_arrend, f); fputs(c_arrend, f);
for (q = index; q <= &index[255 + NTERMINALS];) *q++ = -1; index = (int *) alloc((unsigned) (assval * sizeof(int)));
for (t = h_entry; t < max_t_ent; t++) { for (q = index; q < &index[assval];) *q++ = -1;
index[t->h_num] = t - h_entry; for (t = tokens; t < maxt; t++) {
index[t->t_tokno] = t - tokens;
} }
fputs("short LLindex[] = {\n",f); fputs("short LLindex[] = {\n",f);
for (q = index; q <= &index[assval-1]; q++) { for (q = index; q < &index[assval]; q++) {
fprintf(f, "%d,\n", *q); fprintf(f, "%d,\n", *q);
} }
fputs(c_arrend, f); fputs(c_arrend, f);
copyfile(1); free((p_mem) index);
copyfile(rec_file);
if (ferror(f) != 0) { if (ferror(f) != 0) {
fatal(0,"write error on temporary"); fatal(0,"write error on temporary");
} }
fclose(f); fclose(f);
install(RFILE, (string) 0); install(RFILE, ".");
} }
STATIC STATIC
@ -213,48 +219,49 @@ generate(f) p_file f; {
/* /*
* Generates a parsing routine for every nonterminal * Generates a parsing routine for every nonterminal
*/ */
register short *s; register p_order s;
register p_nont p; register p_nont p;
register FILE *fd;
int i; int i;
p_first ff; register p_first ff;
int mustpop; int mustpop;
/* Generate first sets */ /* Generate first sets */
for (ff = f->f_firsts; ff; ff = ff->ff_next) { for (ff = f->f_firsts; ff; ff = ff->ff_next) {
macro(ff->ff_name,ff->ff_nont); macro(ff->ff_name,&nonterms[ff->ff_nont]);
} }
/* For every nonterminal generate a function */ /* For every nonterminal generate a function */
fd = fpars; for (s = f->f_list; s; s = s->o_next) {
for (s = f->f_start; s <= f->f_end; s++) { p = &nonterms[s->o_index];
p = &nonterms[*s];
/* Generate functions in the order in which the nonterminals /* Generate functions in the order in which the nonterminals
* were defined in the grammar. This is important, because * were defined in the grammar. This is important, because
* of synchronisation with the action file * of synchronisation with the action file
*/ */
while (p->n_count--) getaction(1); while (p->n_count--) getaction(1);
if (p->n_flags & PARAMS) controlline(); fprintf(fpars,"L%d_%s (\n",s->o_index,p->n_name);
fprintf(fd,"L%d_%s (",*s,(min_nt_ent + *s)->h_name); if (p->n_flags & PARAMS) {
if (p->n_flags & PARAMS) getparams(); controlline();
else fputs(") {\n", fd); getparams();
fputs("register struct LLxx *LLx = &LLxx;\n#ifdef lint\nLLx=LLx;\n#endif\n", fd); }
else fputs(") {\n", fpars);
if (p->n_flags & LOCALS) getaction(1); if (p->n_flags & LOCALS) getaction(1);
i = getntsafe(p); i = getntsafe(p);
mustpop = 0; mustpop = NOPOP;
if (g_gettype(p->n_rule) == ALTERNATION) { if (g_gettype(p->n_rule) == ALTERNATION &&
mustpop = 1; i > SAFESCANDONE) {
mustpop = findindex(p->n_contains);
if (i == NOSCANDONE) { if (i == NOSCANDONE) {
fputs(c_read, fd); fputs(c_read, fpars);
i = SCANDONE; i = SCANDONE;
} }
} }
nlabel = 1; nlabel = 1;
nvar = 1;
rulecode(p->n_rule, rulecode(p->n_rule,
i, i,
getntout(p) != NOSCANDONE, getntout(p) != NOSCANDONE,
mustpop); mustpop);
fputs(c_close, fd); fputs(c_close, fpars);
} }
} }
@ -264,7 +271,7 @@ prset(p) p_set p; {
register unsigned i; register unsigned i;
int j; int j;
j = NBYTES(nterminals); j = nbytes;
for (;;) { for (;;) {
i = (unsigned) *p++; i = (unsigned) *p++;
for (k = 0; k < sizeof(int); k++) { for (k = 0; k < sizeof(int); k++) {
@ -281,17 +288,17 @@ prset(p) p_set p; {
STATIC STATIC
macro(s,n) string s; p_nont n; { macro(s,n) string s; p_nont n; {
register FILE *f;
int i; int i;
f = fpars; i = findindex(n->n_first);
i = findindex(&(n->n_first));
fprintf(f,"#define %s(x) ", s);
if (i < 0) { if (i < 0) {
fprintf(f, "((x) == %d)\n", -i); fprintf(fpars, "#define %s(x) ((x) == %d)\n",
s,
tokens[-(i+1)].t_tokno);
return; return;
} }
fprintf(f,"LLfirst((x), %d)\n", i); firsts = 1;
fprintf(fpars,"#define %s(x) LLfirst((x), %d)\n", s, i);
} }
STATIC STATIC
@ -303,8 +310,6 @@ controlline() {
f1 = fact; f2 = fpars; f1 = fact; f2 = fpars;
l = getc(f1); l = getc(f1);
assert(l == '\0'); assert(l == '\0');
l = getc(f1); putc(l,f2);
assert( l == '#' ) ;
do { do {
l = getc(f1); l = getc(f1);
putc(l,f2); putc(l,f2);
@ -318,12 +323,10 @@ getparams() {
*/ */
long off; long off;
register int l; register int l;
register FILE *f;
long ftell(); long ftell();
char first; char first;
first = ' '; first = ' ';
f = fpars;
/* save offset in file to be able to copy the declaration later */ /* save offset in file to be able to copy the declaration later */
off = ftell(fact); off = ftell(fact);
/* First pass through declaration, find the parameter names */ /* First pass through declaration, find the parameter names */
@ -333,17 +336,17 @@ getparams() {
* The last identifier found before a ';' or a ',' * The last identifier found before a ';' or a ','
* must be a parameter * must be a parameter
*/ */
fprintf(f,"%c%s", first, ltext); fprintf(fpars,"%c%s", first, ltext);
first = ','; first = ',';
} }
} }
fputs(") ",f); fputs(") ",fpars);
/* /*
* Now copy the declarations * Now copy the declarations
*/ */
fseek(fact,off,0); fseek(fact,off,0);
getaction(0); getaction(0);
fputs(" {\n",f); fputs(" {\n",fpars);
} }
STATIC STATIC
@ -369,13 +372,13 @@ gettok() {
case EOF : case EOF :
return ENDDECL; return ENDDECL;
default : default :
if (isalpha(ch) || ch == '_') { if (c_class[ch] == ISLET) {
c = ltext; c = ltext;
while (isalnum(ch) || ch == '_') { do {
*c++ = ch; *c++ = ch;
if (c-ltext >= LTEXTSZ) --c; if (c-ltext >= LTEXTSZ) --c;
ch = getc(f); ch = getc(f);
} } while (c_class[ch] == ISLET || c_class[ch] == ISDIG);
if (ch != EOF) ungetc(ch,f); if (ch != EOF) ungetc(ch,f);
*c = '\0'; *c = '\0';
return IDENT; return IDENT;
@ -392,13 +395,27 @@ rulecode(p,safety,mustscan,mustpop) register p_gram p; {
register int toplevel = 1; register int toplevel = 1;
register FILE *f; register FILE *f;
register int *ppu;
int pushlist[100];
int *ppushlist;
/* /*
* First generate code to push the contains sets of this rule * First generate code to push the contains sets of this rule
* on a stack * on a stack
*/ */
ppushlist = pushlist; ppu = pushlist;
if (dopush(p,safety,1) > 0) pushcode(); ppushlist = dopush(p,safety,1,ppu);
if (mustpop != NOPOP) for (; ppu < ppushlist; ppu++) {
if (*ppu == mustpop) {
*ppu = mustpop = NOPOP;
break;
}
}
if (g_gettype(p) != ALTERNATION) {
genpop(mustpop);
mustpop = NOPOP;
}
for (ppu = pushlist; ppu < ppushlist; ppu++) genpush(*ppu);
f = fpars; f = fpars;
for (;;) { for (;;) {
switch (g_gettype(p)) { switch (g_gettype(p)) {
@ -407,25 +424,31 @@ rulecode(p,safety,mustscan,mustpop) register p_gram p; {
fputs(c_read,f); fputs(c_read,f);
} }
return; return;
case LITERAL :
case TERMINAL : { case TERMINAL : {
register p_entry t; register p_token t;
string s;
t = &h_entry[g_getcont(p)]; t = &tokens[g_getcont(p)];
if (toplevel == 0) { if (toplevel == 0) {
fputs(c_LLptrmin,f); fprintf(f,"LLtdecr(%d);\n", g_getcont(p));
} }
if (safety == SAFE) { if (safety == SAFE) {
fputs("LL_SAFE(",f); fputs("LL_SAFE(",f);
} }
else if (safety <= SCANDONE) { else if (safety == SAFESCANDONE) {
fputs("LL_SSCANDONE(",f);
}
else if (safety == SCANDONE) {
fputs("LL_SCANDONE(",f); fputs("LL_SCANDONE(",f);
} }
else if (safety == NOSCANDONE) { else /* if (safety == NOSCANDONE) */ {
fputs("LL_T_NOSCANDONE(", f); fputs("LL_T_NOSCANDONE(", f);
} }
PTERM(f,t); if (t->t_tokno < 0400) s = "'%s');\n";
fputs(");\n", f); else s = "%s);\n";
if (safety == SAFE && toplevel > 0) { fprintf(f,s,t->t_string);
if (safety <= SAFESCANDONE && toplevel > 0) {
safety = NOSCANDONE; safety = NOSCANDONE;
toplevel = -1; toplevel = -1;
p++; p++;
@ -434,27 +457,26 @@ rulecode(p,safety,mustscan,mustpop) register p_gram p; {
safety = NOSCANDONE; safety = NOSCANDONE;
break; } break; }
case NONTERM : { case NONTERM : {
p_entry t;
register p_nont n; register p_nont n;
int params;
n = &nonterms[g_getnont(p)]; n = &nonterms[g_getnont(p)];
t= min_nt_ent+(n-nonterms);
if (safety == NOSCANDONE && if (safety == NOSCANDONE &&
getntsafe(n) < 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); getntsafe(n) <= SAFESCANDONE)) {
genpop(findindex(n->n_contains));
}
fprintf(f,"L%d_%s(\n",g_getnont(p), n->n_name);
if (g_getnpar(p)) {
controlline();
getaction(0);
} }
params = g_getnpar(p);
if (params) controlline();
fprintf(f,"L%d_%s(",n-nonterms, t->h_name);
if (params) getaction(0);
fputs(");\n",f); fputs(");\n",f);
safety = getntout(n); safety = getntout(n);
break; } break; }
case TERM : case TERM :
safety = codeforterm((p_term) pentry[g_getcont(p)], safety = codeforterm(&terms[g_getcont(p)],
safety, safety,
toplevel); toplevel);
break; break;
@ -463,7 +485,7 @@ rulecode(p,safety,mustscan,mustpop) register p_gram p; {
p++; p++;
continue; continue;
case ALTERNATION : case ALTERNATION :
alternation(p, safety, mustscan,mustpop, 0); alternation(p, safety, mustscan, mustpop, 0, 0);
return; return;
} }
p++; p++;
@ -471,11 +493,11 @@ rulecode(p,safety,mustscan,mustpop) register p_gram p; {
} }
} }
alternation(p, safety, mustscan, mustpop, lb) register p_gram p; { STATIC
alternation(p, safety, mustscan, mustpop, lb, var) register p_gram p; {
register FILE *f = fpars; register FILE *f = fpars;
register p_link l; register p_link l;
int hulp, hulp1,hulp2; int hulp, hulp1,hulp2;
int var;
int haddefault = 0; int haddefault = 0;
int unsafe = 1; int unsafe = 1;
int nsafe; int nsafe;
@ -483,24 +505,23 @@ alternation(p, safety, mustscan, mustpop, lb) register p_gram p; {
p_set setalloc(); p_set setalloc();
assert(safety < NOSCANDONE); assert(safety < NOSCANDONE);
l = (p_link) pentry[g_getcont(p)]; l = &links[g_getcont(p)];
hulp = nlabel++; hulp = nlabel++;
hulp1 = nlabel++; hulp1 = nlabel++;
hulp2 = nlabel++; hulp2 = nlabel++;
var = nvar++;
if (!lb) lb = hulp1; if (!lb) lb = hulp1;
if (safety <= SAFESCANDONE) unsafe = 0; if (safety <= SAFESCANDONE) unsafe = 0;
if (!unsafe && mustpop) { if (!unsafe) {
mustpop = 0; genpop(mustpop);
fputs(c_LLptrmin, f); mustpop = NOPOP;
} }
if (unsafe) { if (unsafe && hulp1 == lb) {
fprintf(f,"{ int LL_%d = 0;\n", var); var = ++nvar;
if (hulp1 == lb) fprintf(f, "L_%d: \n", hulp1); fprintf(f,"{ int LL_%d = 0;\nL_%d: \n", var, hulp1);
} }
fputs("switch(LLcsymb) {\n", f); fputs("switch(LLcsymb) {\n", f);
while (g_gettype(p) != EORULE) { while (g_gettype(p) != EORULE) {
l = (p_link) pentry[g_getcont(p)]; l = &links[g_getcont(p)];
if (unsafe && (l->l_flag & DEF)) { if (unsafe && (l->l_flag & DEF)) {
haddefault = 1; haddefault = 1;
fprintf(f, fprintf(f,
@ -508,19 +529,18 @@ alternation(p, safety, mustscan, mustpop, lb) register p_gram p; {
var, var, lb, hulp2); var, var, lb, hulp2);
} }
if (l->l_flag & COND) { if (l->l_flag & COND) {
set = setalloc(tsetsize); set = setalloc();
setunion(set, l->l_others, tsetsize); setunion(set, l->l_others);
setintersect(set, l->l_symbs, tsetsize); setintersect(set, l->l_symbs);
setminus(l->l_symbs, set, tsetsize); setminus(l->l_symbs, set);
setminus(l->l_others, set, tsetsize); setminus(l->l_others, set);
gencases(set); gencases(set);
free((p_mem) set);
controlline(); controlline();
fputs("if (!",f); fputs("if (!",f);
getaction(0); getaction(0);
fprintf(f,") goto L_%d;\n", hulp); fprintf(f,") goto L_%d;\n", hulp);
} }
if (!unsafe && (l->l_flag & DEF)) { if (!haddefault && (l->l_flag & DEF)) {
fputs("default:\n", f); fputs("default:\n", f);
haddefault = 1; haddefault = 1;
} }
@ -532,10 +552,17 @@ alternation(p, safety, mustscan, mustpop, lb) register p_gram p; {
} }
if (safety != SAFE) nsafe = SAFESCANDONE; if (safety != SAFE) nsafe = SAFESCANDONE;
} }
if (mustpop) fputs(c_LLptrmin, f); rulecode(l->l_rule, nsafe, mustscan, mustpop);
rulecode(l->l_rule, nsafe, mustscan, 0);
fputs(c_break,f); fputs(c_break,f);
if (l->l_flag & COND) { if (l->l_flag & COND) {
p++;
fprintf(f,"L_%d : ;\n",hulp);
if (g_gettype(p+1) == EORULE) {
setminus(links[g_getcont(p)].l_symbs, set);
free((p_mem) set);
continue;
}
free((p_mem) set);
if (!haddefault) { if (!haddefault) {
fputs("default:\n", f); fputs("default:\n", f);
} }
@ -543,100 +570,73 @@ alternation(p, safety, mustscan, mustpop, lb) register p_gram p; {
gencases(l->l_others); gencases(l->l_others);
safety = SAFE; safety = SAFE;
} }
fprintf(f,"L_%d : ;\n",hulp); if (safety <= SAFESCANDONE) {
p++; genpop(mustpop);
if (!unsafe && g_gettype(p+1) == EORULE) { mustpop = NOPOP;
if (mustpop) fputs(c_LLptrmin, f);
rulecode(((p_link)pentry[g_getcont(p)])->l_rule,
safety,mustscan,0);
} }
else alternation(p,safety,mustscan,mustpop,lb); alternation(p,safety,mustscan,mustpop,lb,var);
break; break;
} }
p++; p++;
} }
fputs(c_close, f); fputs(c_close, f);
if (unsafe) fputs(c_close, f); if (unsafe && hulp1 == lb) fputs(c_close, f);
return;
} }
STATIC int STATIC int *
dopush(p,safety,toplevel) register p_gram p; { dopush(p,safety,toplevel,pp) register p_gram p; register int *pp; {
/* /*
* The safety only matters if toplevel != 0 * The safety only matters if toplevel != 0
*/ */
register int count = 0;
for (;;) { for (;;) {
switch(g_gettype(p)) { switch(g_gettype(p)) {
case EORULE : case EORULE :
case ALTERNATION : case ALTERNATION :
return count; return pp;
case TERM : { case TERM : {
register p_term q; register p_term q;
int rep, cnt; int rep, cnt;
q = (p_term) pentry[g_getcont(p)]; q = &terms[g_getcont(p)];
rep = r_getkind(&(q->t_reps)); rep = r_getkind(q);
cnt = r_getnum(&(q->t_reps)); cnt = r_getnum(q);
count += dopush(p+1,SCANDONE,0); if (!(toplevel > 0 && safety <= SAFESCANDONE &&
if (toplevel > 0 && (rep == OPT || (rep == FIXED && cnt == 0)))) {
(rep == OPT || (rep == FIXED && cnt == 0))) { *pp++ = findindex(q->t_contains);
if (safety <= SAFESCANDONE) return count;
} }
*ppushlist++ = findindex(&(q->t_contains)); break; }
return count+1; } case LITERAL :
case TERMINAL : case TERMINAL :
if (toplevel > 0 && safety == SAFE) { if (toplevel > 0 && safety <= SAFESCANDONE) {
count += dopush(p+1,NOSCANDONE,-1); toplevel = -1;
p++;
safety = NOSCANDONE;
continue;
} }
else count += dopush(p+1, NOSCANDONE, 0); if (toplevel == 0) *pp++ = -(g_getcont(p)+1);
if (toplevel != 0) { break;
return count;
}
*ppushlist++ = -h_entry[g_getcont(p)].h_num;
return count + 1;
case NONTERM : { case NONTERM : {
register p_nont n; register p_nont n;
n = &nonterms[g_getnont(p)]; n = &nonterms[g_getnont(p)];
count += dopush(p+1, SCANDONE, 0);
if (toplevel == 0 || if (toplevel == 0 ||
g_gettype(n->n_rule) == ALTERNATION) { (g_gettype(n->n_rule) == ALTERNATION &&
*ppushlist++ = findindex(&n->n_contains); getntsafe(n) > SAFESCANDONE)) {
count++; *pp++ = findindex(n->n_contains);
} }
return count; } break; }
case ACTION :
p++;
continue;
} }
toplevel = 0;
safety = NOSCANDONE;
p++; p++;
} }
} }
# define max(a,b) ((a) < (b) ? (b) : (a)) # define max(a,b) ((a) < (b) ? (b) : (a))
STATIC
pushcode() {
register int i,j,k;
register int *p = pushlist;
if ((i = ppushlist - p) == 0) return;
if (i <= 2) {
genpush(p[0]);
if (i == 2) genpush(p[1]);
return;
}
fprintf(fpars,"\LLlpush(%d, %d);\n",plists-lists, i);
if (maxlists - plists < i) {
j = plists - lists;
k = maxlists-lists+max(i+1,50);
lists = (int *) ralloc( (p_mem)lists,
(unsigned)(k+1)*sizeof(int));
plists = lists+j;
maxlists = lists+k;
}
while (i--) {
*plists++ = *p++;
}
}
STATIC STATIC
getaction(flag) { getaction(flag) {
@ -674,14 +674,14 @@ getaction(flag) {
newline = 0; newline = 0;
} }
match = ch; match = ch;
for (;;) {
putc(ch,f); putc(ch,f);
while (ch = getc(fact)) { ch = getc(fact);
if (ch == match) break; if (ch == match || !ch) break;
if (ch == '\\') { if (ch == '\\') {
putc(ch,f); putc(ch,f);
ch = getc(fact); ch = getc(fact);
} }
putc(ch,f);
} }
break; break;
case IDENT : case IDENT :
@ -711,35 +711,44 @@ codeforterm(q,safety,toplevel) register p_term q; {
register int rep; register int rep;
int persistent; int persistent;
int ispushed; int ispushed;
int sw = SAFE;
f = fpars; f = fpars;
i = r_getnum(&(q->t_reps)); i = r_getnum(q);
rep = r_getkind(&(q->t_reps)); rep = r_getkind(q);
ispushed = !(toplevel > 0 && safety <= SAFESCANDONE &&
(rep == OPT || (rep == FIXED && i == 0)));
persistent = (q->t_flags & PERSISTENT); persistent = (q->t_flags & PERSISTENT);
if (safety == NOSCANDONE && (rep != FIXED || i == 0)) { ispushed = NOPOP;
if (!(toplevel > 0 && safety <= SAFESCANDONE &&
(rep == OPT || (rep == FIXED && i == 0)))) {
ispushed = findindex(q->t_contains);
}
if (safety == NOSCANDONE && (rep != FIXED || i == 0 ||
gettout(q) != NOSCANDONE)) {
fputs(c_read, f); fputs(c_read, f);
safety = SCANDONE; safety = SCANDONE;
} }
if (ispushed) { if (rep == PLUS && !persistent) {
if ((safety <= SAFESCANDONE && int temp;
(rep == OPT || (rep == FIXED && i == 0))) ||
(rep == FIXED && i == 0 && temp = findindex(q->t_first);
g_gettype(q->t_rule) != ALTERNATION)) { if (temp != ispushed) {
fputs(c_LLptrmin, f); genpop(ispushed);
ispushed = 0; ispushed = temp;
genpush(temp);
} }
} }
if (i) { if (i) {
/* N > 0, so generate fixed forloop */ /* N > 0, so generate fixed forloop */
fprintf(f,"{\nregister LL_i = %d;\n",i); fputs("{\nregister LL_i;\n", f);
fputs("for (;;) {\nif (!LL_i--) {\nLLptr++;\n", f); assert(ispushed != NOPOP);
fputs("break;\n}\n", f); fprintf(f, "for (LL_i = %d; LL_i >= 0; LL_i--) {\n", i - 1);
if (rep == FIXED) { if (rep == FIXED) {
if (gettout(q) == NOSCANDONE && safety == NOSCANDONE) { fputs("if (!LL_i) ", f);
fputs(c_read,f); genpop(ispushed);
safety = SCANDONE; genpush(ispushed);
if (safety == NOSCANDONE) {
assert(gettout(q) == NOSCANDONE);
fputs(c_read, f);
} }
} }
} }
@ -747,26 +756,36 @@ codeforterm(q,safety,toplevel) register p_term q; {
/* '+' or '*', so generate infinite loop */ /* '+' or '*', so generate infinite loop */
fputs("for (;;) {\n",f); fputs("for (;;) {\n",f);
} }
if (rep == STAR || rep == OPT) { else if (safety <= SAFESCANDONE && rep == OPT) {
genifhead(q, rep, safety, ispushed); genpop(ispushed);
ispushed = NOPOP;
}
if (rep == STAR || rep == OPT) {
sw = genswhead(q, rep, i, safety, ispushed);
}
rulecode(q->t_rule,
t_safety(rep,i,persistent,safety),
gettout(q) != NOSCANDONE,
rep == FIXED ? ispushed : NOPOP);
if (gettout(q) == NOSCANDONE && rep != FIXED) {
fputs(c_read, f);
} }
rulecode(q->t_rule,t_safety(rep,i,persistent,safety),
rep != FIXED || gettout(q) != NOSCANDONE,
rep == FIXED && i == 0 && ispushed);
/* 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) {
if (!persistent) { if (i) {
fprintf(f, "*LLptr = %d;\n", findindex(&(q->t_first))); fputs("if (!LL_i) break;\n", f);
/* ??? */
} }
genifhead(q,rep,safety, ispushed); sw = genswhead(q, rep, i, safety, ispushed);
} }
if (rep != OPT && rep != FIXED) fputs("continue;\n", f); if (rep != OPT && rep != FIXED) fputs("continue;\n", f);
if (rep != FIXED) { if (rep != FIXED) {
fputs(c_close, f); /* Close switch */ fputs(c_close, f); /* Close switch */
if (sw > SAFESCANDONE && (q->t_flags & RESOLVER)) {
fputs(c_close, f);
}
if (rep != OPT) { if (rep != OPT) {
if (ispushed) fputs(c_LLptrmin, f); genpop(ispushed);
fputs("break;\n", f); fputs(c_break, f);
} }
} }
if (rep != OPT && (rep != FIXED || i > 0)) { if (rep != OPT && (rep != FIXED || i > 0)) {
@ -779,34 +798,38 @@ codeforterm(q,safety,toplevel) register p_term q; {
} }
STATIC STATIC
genifhead(q, rep, safety, ispushed) register p_term q; { genswhead(q, rep, cnt, safety, ispushed) register p_term q; {
/* /*
* Generate if statement for term q * Generate switch statement for term q
*/ */
register FILE *f; register FILE *f;
p_set p1; p_set p1;
p_set setalloc(); p_set setalloc();
int hulp1; int hulp1, hulp2, var;
int safeterm; int safeterm;
f = fpars; f = fpars;
hulp1 = nlabel++; if (rep == PLUS) safeterm = gettout(q);
if (rep == PLUS) safeterm = gettout(q) <= SAFESCANDONE; else if (rep == OPT) safeterm = safety;
else if (rep == OPT) safeterm = safety <= SAFESCANDONE; else /* if (rep == STAR) */ safeterm = max(safety, gettout(q));
else /* if (rep == STAR) */ { if ((q->t_flags & RESOLVER) && safeterm > SAFESCANDONE) {
safeterm = safety <= SAFESCANDONE && gettout(q) <= SAFESCANDONE; hulp2 = nlabel++;
var = nvar++;
fprintf(f, "{ int LL_%d = 0;\nL_%d : ", var, hulp2);
} }
fputs("switch(LLcsymb) {\n", f); fputs("switch(LLcsymb) {\n", f);
if (q->t_flags & RESOLVER) { if (q->t_flags & RESOLVER) {
p1 = setalloc(tsetsize); hulp1 = nlabel++;
setunion(p1,q->t_first,tsetsize); p1 = setalloc();
setintersect(p1,q->t_follow,tsetsize); setunion(p1,q->t_first);
setintersect(p1,q->t_follow);
/* /*
* p1 now points to a set containing the conflicting * p1 now points to a set containing the conflicting
* symbols * symbols
*/ */
setminus(q->t_first, p1, tsetsize); setminus(q->t_first, p1);
setminus(q->t_follow, p1, tsetsize); setminus(q->t_follow, p1);
setminus(q->t_contains, p1);
gencases(p1); gencases(p1);
free((p_mem) p1); free((p_mem) p1);
controlline(); controlline();
@ -814,18 +837,42 @@ genifhead(q, rep, safety, ispushed) register p_term q; {
getaction(0); getaction(0);
fprintf(f, ") goto L_%d;\n", hulp1); fprintf(f, ") goto L_%d;\n", hulp1);
} }
gencases(q->t_follow); if (safeterm <= SAFESCANDONE) fputs("default:\n", f);
if (ispushed && rep == OPT) fputs(c_LLptrmin, f); else gencases(q->t_follow);
fputs("break;\n", f); if (rep == OPT) genpop(ispushed);
if (!safeterm) { fputs(c_break, f);
fputs("default: if (!LLnext()) break;\n", f); if (safeterm > SAFESCANDONE) {
gencases(q->t_first); int i;
assert(ispushed != NOPOP);
if (ispushed >= 0) i = -ispushed;
else i = tokens[-(ispushed+1)].t_tokno;
fputs("default: if (", f);
if (q->t_flags & RESOLVER) {
fprintf(f, "LL_%d ||", var);
} }
else fputs("default: ;\n", f); fprintf(f, "!LLnext(%d)) {\n", i);
if (rep == OPT) genpop(ispushed);
fputs(c_break, f);
fputs(c_close, f);
if (q->t_flags & RESOLVER) {
fprintf(f,"LL_%d = 1;\ngoto L_%d;\n", var, hulp2);
}
}
if ((q->t_flags & PERSISTENT) && safeterm != SAFE) {
gencases(q->t_contains);
}
else gencases(q->t_first);
if (q->t_flags & RESOLVER) { if (q->t_flags & RESOLVER) {
fprintf(f, "L_%d : ;\n", hulp1); fprintf(f, "L_%d : ;\n", hulp1);
} }
if (ispushed && rep == OPT) fputs(c_LLptrmin, f); if (rep == OPT) genpop(ispushed);
if (cnt > 0) {
assert(ispushed != NOPOP);
fputs(rep == STAR ? "if (!LL_i) " : "if (LL_i == 1) ", f);
genpop(ispushed);
}
return safeterm;
} }
STATIC STATIC
@ -845,27 +892,19 @@ gencases(setp) register p_set setp; {
* labeledstatement : labels statement ; * labeledstatement : labels statement ;
* labels : labels label | ; * labels : labels label | ;
*/ */
register p_entry p; register p_token p;
register i; register int i;
p = h_entry; for (i = 0, p = tokens; i < ntokens; i++, p++) {
for (i=0; i < nterminals; i++) {
if (IN(setp,i)) { if (IN(setp,i)) {
fprintf(fpars, fprintf(fpars,
p->h_num<0400 ? "case /* '%s' */ %d : ;\n" p->t_tokno<0400 ? "case /* '%s' */ %d : ;\n"
: "case /* %s */ %d : ;\n", : "case /* %s */ %d : ;\n",
p->h_name, i); p->t_string, i);
} }
p++;
} }
} }
STATIC
genpush(d) {
fprintf(fpars, "LLptr--;\n*LLptr = %d;\n",d);
}
static char namebuf[20]; static char namebuf[20];
STATIC string STATIC string
@ -895,3 +934,23 @@ genname(s) string s; {
*d = '\0'; *d = '\0';
return namebuf; return namebuf;
} }
STATIC
genpush(d) {
genincrdecr("incr", d);
}
STATIC
genincrdecr(s, d) string s; {
if (d == NOPOP) return;
if (d >= 0) {
fprintf(fpars, "LLs%s(%d);\n", s, d / nbytes);
return;
}
fprintf(fpars, "LLt%s(%d);\n", s, -(d + 1));
}
STATIC
genpop(d) {
genincrdecr("decr", d);
}

View file

@ -29,30 +29,28 @@
*/ */
# include "types.h" # include "types.h"
# include "extern.h"
# include "io.h" # include "io.h"
# include "tunable.h"
# ifndef NORCSID # ifndef NORCSID
static string rcsid4 = "$Header$"; static string rcsid4 = "$Header$";
# endif # endif
char ltext[LTEXTSZ]; char ltext[LTEXTSZ];
t_entry h_entry[NTERMINALS+NNONTERMS+1]; p_nont nonterms;
p_entry max_t_ent; p_nont maxnt;
t_nont nonterms[NNONTERMS+1];
int nnonterms; int nnonterms;
int nterminals; p_token tokens;
int order[NNONTERMS+1]; p_token maxt;
int *maxorder; int ntokens;
p_order porder, sorder;
p_start start; p_start start;
int linecount; int linecount;
int assval; int assval;
string pentry[ENTSIZ];
FILE *fout; FILE *fout;
FILE *fpars; FILE *fpars;
FILE *finput; FILE *finput;
FILE *fact; FILE *fact;
p_nont maxnt;
string f_pars = PARSERFILE; string f_pars = PARSERFILE;
string f_out = OUTFILE; string f_out = OUTFILE;
string f_temp = ACTFILE; string f_temp = ACTFILE;
@ -66,8 +64,11 @@ int ntprint;
int debug; int debug;
# endif not NDEBUG # endif not NDEBUG
p_file files; p_file files;
p_file maxfiles;
p_file pfile; p_file pfile;
string LLgenid = "/* LLgen generated code from source %s */\n"; string LLgenid = "/* LLgen generated code from source %s */\n";
t_token lextoken; t_token lextoken;
int nerrors; int nerrors;
int fflag; string rec_file, incl_file;
p_link links;
p_term terms;

View file

@ -29,7 +29,6 @@
*/ */
# include <stdio.h> # include <stdio.h>
# include <ctype.h>
/* FILES */ /* FILES */

View file

@ -38,12 +38,10 @@
static string rcsid6 = "$Header$"; static string rcsid6 = "$Header$";
# endif # endif
static string rec_file;
static string incl_file;
/* In this file the following routines are defined: */ /* In this file the following routines are defined: */
extern int main(); extern int main();
STATIC readgrammar(); STATIC readgrammar();
STATIC doparse();
extern error(); extern error();
extern fatal(); extern fatal();
extern comfatal(); extern comfatal();
@ -56,11 +54,9 @@ extern badassertion();
main(argc,argv) register string argv[]; { main(argc,argv) register string argv[]; {
register string arg; register string arg;
string libpath(); string libpath();
int nflag = 0;
/* Initialize */ /* Initialize */
maxorder = order;
assval = 0400; assval = 0400;
/* read options */ /* read options */
@ -71,20 +67,11 @@ main(argc,argv) register string argv[]; {
case 'V': case 'V':
verbose++; verbose++;
continue; continue;
case 'n':
case 'N':
nflag++;
continue;
case 'f':
case 'F':
fflag++;
continue;
# ifndef NDEBUG # ifndef NDEBUG
case 'a': case 'd':
case 'A': case 'D':
debug++; debug++;
continue; continue;
# endif not NDEBUG
case 'r': case 'r':
case 'R': case 'R':
if (rec_file) { if (rec_file) {
@ -101,6 +88,7 @@ main(argc,argv) register string argv[]; {
} }
incl_file = ++arg; incl_file = ++arg;
break; break;
# endif not NDEBUG
case 'x': case 'x':
case 'X': case 'X':
ntneeded = 1; ntneeded = 1;
@ -110,7 +98,9 @@ main(argc,argv) register string argv[]; {
fprintf(stderr,"illegal option : %c\n",*arg); fprintf(stderr,"illegal option : %c\n",*arg);
return 1; return 1;
} }
# ifndef NDEBUG
break; break;
# endif
} }
argv++; argv++;
argc--; argc--;
@ -119,46 +109,44 @@ main(argc,argv) register string argv[]; {
* Now check wether the sets should include nonterminals * Now check wether the sets should include nonterminals
*/ */
if (verbose == 2) ntneeded = 1; if (verbose == 2) ntneeded = 1;
else if (! verbose) ntneeded = 0;
/* /*
* Initialise * Initialise
*/ */
if (!rec_file) rec_file = libpath("rec"); # ifndef NDEBUG
if (!incl_file) incl_file = libpath("incl"); if (!rec_file) {
# endif
rec_file = libpath("rec");
# ifndef NDEBUG
}
if (!incl_file) {
# endif
incl_file = libpath("incl");
# ifndef NDEBUG
}
# endif
if ((fact = fopen(f_temp,"w")) == NULL) { if ((fact = fopen(f_temp,"w")) == NULL) {
fputs("Cannot create temporary\n",stderr); fputs("Cannot create temporary\n",stderr);
return 1; return 1;
} }
name_init(); a_init();
readgrammar(argc,argv); readgrammar(argc,argv);
if (nflag) comfatal();
setinit(ntneeded); setinit(ntneeded);
maxnt = &nonterms[nnonterms]; maxnt = &nonterms[nnonterms];
max_t_ent = &h_entry[nterminals]; maxt = &tokens[ntokens];
fclose(fact); fclose(fact);
/* /*
* Now, the grammar is read. Do some computations * Now, the grammar is read. Do some computations
*/ */
co_reach(); /* Check for undefined and unreachable */ co_reach(); /* Check for undefined and unreachable */
if (nerrors) comfatal(); if (nerrors) comfatal();
createsets(); do_compute();
co_empty(); /* Which nonterminals produce empty? */ conflchecks();
co_first(); /* Computes first sets */
co_follow(); /* Computes follow sets */
co_symb(); /* Computes choice sets in alternations */
conflchecks(); /* Checks for conflicts etc, and also
* takes care of LL.output etc
*/
if (nerrors) comfatal(); if (nerrors) comfatal();
co_contains(); /* Computes the contains sets */
co_safes(); /* Computes safe terms and nonterminals.
* Safe means : always called with a terminal
* symbol that is guarantied to be eaten by
* the term
*/
if (argc-- == 1) { if (argc-- == 1) {
fputs("No code generation for input from standard input\n",stderr); fputs("No code generation for input from standard input\n",
} else gencode(argc); stderr);
}
else gencode(argc);
UNLINK(f_temp); UNLINK(f_temp);
UNLINK(f_pars); UNLINK(f_pars);
return 0; return 0;
@ -180,32 +168,19 @@ readgrammar(argc,argv) char *argv[]; {
files = p = (p_file) alloc((unsigned) (argc+1) * sizeof(t_file)); files = p = (p_file) alloc((unsigned) (argc+1) * sizeof(t_file));
if (argc-- == 1) { if (argc-- == 1) {
finput = stdin; finput = stdin;
p->f_name = f_input = "standard input"; f_input = "standard input";
p->f_firsts = 0; doparse(p++);
p->f_start = maxorder;
pfile = p;
LLparse();
p->f_end = maxorder - 1;
p++;
} else { } else {
while (argc--) { while (argc--) {
if ((finput = fopen(f_input=argv[1],"r")) == NULL) { if ((finput = fopen(f_input=argv[1],"r")) == NULL) {
fatal(0,e_noopen,f_input); fatal(0,e_noopen,f_input);
} }
linecount = 0; doparse(p++);
p->f_name = f_input;
p->f_start = maxorder;
p->f_firsts = 0;
pfile = p;
LLparse();
p->f_end = maxorder-1;
p++;
argv++; argv++;
fclose(finput); fclose(finput);
} }
} }
p->f_start = maxorder+1; maxfiles = p;
p->f_end = maxorder;
if (! lexical) lexical = "yylex"; if (! lexical) lexical = "yylex";
/* /*
* There must be a start symbol! * There must be a start symbol!
@ -216,19 +191,30 @@ readgrammar(argc,argv) char *argv[]; {
if (nerrors) comfatal(); if (nerrors) comfatal();
} }
STATIC
doparse(p) register p_file p; {
linecount = 0;
p->f_name = f_input;
p->f_firsts = 0;
pfile = p;
sorder = 0;
porder = 0;
LLparse();
p->f_list = sorder;
}
/* VARARGS1 */ /* VARARGS1 */
error(lineno,s,t,u) string s,t,u; { error(lineno,s,t,u) string s,t,u; {
/* /*
* Just an error message * Just an error message
*/ */
register FILE *f;
f = stderr;
++nerrors; ++nerrors;
if (lineno) fprintf(f,"\"%s\", line %d : ",f_input,lineno); if (!lineno) lineno = 1;
else fprintf(f,"\"%s\" : ",f_input); fprintf(stderr,"\"%s\", line %d : ",f_input, lineno);
fprintf(f,s,t,u); fprintf(stderr,s,t,u);
putc('\n',f); fputs("\n",stderr);
} }
/* VARARGS1 */ /* VARARGS1 */
@ -253,16 +239,14 @@ comfatal() {
exit(1); exit(1);
} }
copyfile(n) { copyfile(file) string file; {
/* /*
* Copies a file indicated by the parameter to filedescriptor fpars. * Copies a file indicated by the parameter to filedescriptor fpars.
* If n != 0, the error recovery routines are copied,
* otherwise a standard header is.
*/ */
register c; register int c;
register FILE *f; register FILE *f;
if ((f = fopen(n?rec_file:incl_file,"r")) == NULL) { if ((f = fopen(file,"r")) == NULL) {
fatal(0,"Cannot open libraryfile, call an expert"); fatal(0,"Cannot open libraryfile, call an expert");
} }
while ((c = getc(f)) != EOF) putc(c,fpars); while ((c = getc(f)) != EOF) putc(c,fpars);
@ -275,12 +259,9 @@ install(target, source) string target, source; {
* if allowed (which means that the target must be generated * if allowed (which means that the target must be generated
* by LLgen from the source, or that the target is not present * by LLgen from the source, or that the target is not present
*/ */
register c; register int c1, c2;
register FILE *f1; register FILE *f1, *f2;
register FILE *f2; int cnt;
register string s1;
register int i;
char buf[100];
/* /*
* First open temporary, generated for source * First open temporary, generated for source
@ -288,41 +269,38 @@ install(target, source) string target, source; {
if ((f1 = fopen(f_pars,"r")) == NULL) { if ((f1 = fopen(f_pars,"r")) == NULL) {
fatal(0,e_noopen,f_pars); fatal(0,e_noopen,f_pars);
} }
i = 0;
/* /*
* Now open target for reading * Now open target for reading
*/ */
if ((f2 = fopen(target,"r")) == NULL) { if ((f2 = fopen(target,"r")) == NULL) {
i = 1;
fclose(f1); fclose(f1);
RENAME(f_pars, target);
return;
} }
else {
/* /*
* Create string recognised by LLgen. The target must * Compute length of LLgen identification string. The target must
* start with that! * start with that!
*/ */
(int) sprintf(buf,LLgenid,source ? source : "."); cnt = strlen(LLgenid) + strlen(source) - 2;
s1 = buf;
while (*s1 != '\0' && *s1++ == getc(f2)) { /* nothing */ }
/*
* Ai,ai, it did not
*/
if (*s1 != '\0') {
fatal(0,"%s : not a file generated by LLgen",target);
}
rewind(f2);
/* /*
* Now compare the target with the temporary * Now compare the target with the temporary
*/ */
while ((c = getc(f1)) != EOF && c == getc(f2)) { /* nothing */} do {
if (c != EOF || getc(f2) != EOF) i = 1; c1 = getc(f1);
c2 = getc(f2);
if (cnt >= 0) cnt--;
} while (c1 == c2 && c1 != EOF);
fclose(f1); fclose(f1);
fclose(f2); fclose(f2);
}
/* /*
* Here, if i != 0 the target must be recreated * Here, if c1 != c2 the target must be recreated
*/ */
if (i) RENAME(f_pars,target); if (c1 != c2) {
if (cnt >= 0) {
fatal(0,"%s : not a file generated by LLgen",target);
}
RENAME(f_pars,target);
}
} }
#ifndef NDEBUG #ifndef NDEBUG

View file

@ -25,11 +25,11 @@
/* /*
* name.c * name.c
* Defines the symboltable search routine and an initialising routine * Defines the symboltable search routine, a name store routine and an
* initialising routine.
*/ */
# include "types.h" # include "types.h"
# include "tunable.h"
# include "extern.h" # include "extern.h"
# include "assert.h" # include "assert.h"
# include "io.h" # include "io.h"
@ -39,42 +39,68 @@ static string rcsid7 = "$Header$";
# endif # endif
# define HASHSIZE 128 # define HASHSIZE 128
# define NMSIZ 2048 /* Room for names allocated NMSIZ bytes at a time */
static char name[NAMESZ]; /* space for names */ static char *name, *maxname;
static int iname; /* index in nametable */
static p_entry h_root[HASHSIZE]; /* hash table */ static p_entry h_root[HASHSIZE]; /* hash table */
static string e_literal = "Illegal literal"; static string e_literal = "Illegal literal";
static p_entry entries, maxentries;
static t_info token_info, nont_info;
/* Defined in this file are: */ /* Defined in this file are: */
extern string store(); extern string store();
extern name_init(); extern name_init();
STATIC int hash(); STATIC int hash();
extern t_gram search(); STATIC p_entry newentry();
extern p_gram search();
p_mem alloc();
p_mem new_mem();
name_init() {
token_info.i_esize = sizeof (t_token);
token_info.i_incr = 25;
nont_info.i_esize = sizeof (t_nont);
nont_info.i_incr = 25;
search(TERMINAL,"EOFILE",ENTERING);
}
STATIC p_entry
newentry(str, next) string str; p_entry next; {
register p_entry p;
if ((p = entries) == maxentries) {
p = (p_entry) alloc(50 * sizeof(t_entry));
maxentries = p + 50;
}
entries = p + 1;
p->h_name = str;
p->h_next = next;
p->h_type.g_lineno = linecount;
return p;
}
string string
store(s) register string s; { store(s) string s; {
/* /*
* Store a string s in the name table * Store a string s in the name table
*/ */
register string t,u; register string s1, t ,u;
u = t = &name[iname]; u = name;
do { if (u > &name[NAMESZ-1]) fatal(linecount,"name table overflow"); t = s;
else *u++ = *s; s1 = u;
} while (*s++); do {
iname = u - name; if (u >= maxname) {
return t; u = alloc(NMSIZ);
} maxname = u + NMSIZ;
t = s;
name_init() { s1 = u;
/* }
* Initialise hash-table and enter special terminal EOFILE *u++ = *t;
*/ } while (*t++);
register p_entry *p; name = u;
t_gram search(); return s1;
for(p = h_root; p<= &h_root[HASHSIZE-1]; p++) *p = 0;
search(TERMINAL,"EOFILE",ENTERING);
} }
STATIC int STATIC int
@ -82,7 +108,7 @@ hash(str) string str; {
/* /*
* Compute the hash for string str * Compute the hash for string str
*/ */
register i; register int i;
register string l; register string l;
l = str; l = str;
@ -92,94 +118,52 @@ hash(str) string str; {
return i % HASHSIZE; return i % HASHSIZE;
} }
t_gram p_gram
search(type,str,option) register string str; { search(type,str,option) register string str; {
/* /*
* Search for object str. * Search for object str.
* It has type UNKNOWN, LITERAL, TERMINAL or NONTERM. * It has type UNKNOWN, LITERAL, TERMINAL or NONTERM.
* option can be ENTERING, JUSTLOOKING or BOTH. * option can be ENTERING or BOTH (also looking).
*/ */
register int val; register int val;
register p_entry p; register p_entry p;
t_gram r;
register int i; register int i;
int type1;
g_init(&r);
g_setcont(&r,UNDEFINED);
r.g_lineno = linecount;
i = hash(str); i = hash(str);
/* /*
* Walk hash chain * Walk hash chain
*/ */
for (p = h_root[i]; p != (p_entry) 0; p = p->h_next) { for (p = h_root[i]; p != (p_entry) 0; p = p->h_next) {
if(!strcmp(p->h_name,str)) { if(!strcmp(p->h_name,str)) {
val = p - h_entry; type1 = g_gettype(&(p->h_type));
if (type == LITERAL && if (type1 != type) {
(val >= NTERMINALS || p->h_num >= 0400)) continue; if (type1 == LITERAL || type == LITERAL) {
if (val>=NTERMINALS) {
/* Should be a nonterminal */
if (type == TERMINAL) {
error(linecount,
"%s : terminal expected",
str);
}
g_settype(&r,NONTERM);
g_setnont(&r,val - NTERMINALS);
} else {
if (type != LITERAL && p->h_num < 0400) {
continue; continue;
} }
if (type == NONTERM) { if (type != UNKNOWN) {
error(linecount, error(linecount,
"%s : nonterminal expected", "%s : illegal type",
str); str);
continue; continue;
} }
g_setnont(&r, val);
g_settype(&r, TERMINAL);
} }
if (option==ENTERING) { if (option==ENTERING) {
error(linecount, error(linecount,
"%s : already defined",str); "%s : already defined",str);
} }
return r; p->h_type.g_lineno = linecount;
return &(p->h_type);
} }
} }
if (option == JUSTLOOKING) return r; p = newentry(store(str), h_root[i]);
if (type == TERMINAL || type == LITERAL) {
if (nterminals == NTERMINALS) {
fatal(linecount,"too many terminals");
}
p = &h_entry[nterminals];
} else {
/*
* type == NONTERM || type == UNKNOWN
* UNKNOWN and not yet declared means : NONTERM
*/
if (nnonterms == NNONTERMS) {
fatal(linecount,"too many nonterminals");
}
p = &h_entry[NTERMINALS+nnonterms];
}
p->h_name = store(str);
p->h_next = h_root[i];
h_root[i] = p; h_root[i] = p;
if (type == NONTERM || type == UNKNOWN) { if (type == TERMINAL || type == LITERAL) {
register p_nont q; register p_token pt;
q = &nonterms[nnonterms]; pt = (p_token) new_mem(&token_info);
q->n_rule = 0; tokens = (p_token) token_info.i_ptr;
q->n_lineno = linecount; pt->t_string = p->h_name;
q->n_string = f_input;
q->n_follow = 0;
q->n_flags = 0;
q->n_contains = 0;
p->h_num = 0;
g_settype(&r, NONTERM);
g_setnont(&r, nnonterms);
nnonterms++;
return r;
}
if (type == LITERAL) { if (type == LITERAL) {
if (str[0] == '\\') { if (str[0] == '\\') {
/* /*
@ -219,7 +203,8 @@ search(type,str,option) register string str; {
str[2] > '7' || str[2] < '0' || str[2] > '7' || str[2] < '0' ||
str[3] > '7' || str[3] < '0' || str[3] > '7' || str[3] < '0' ||
str[4] != '\0') error(linecount,e_literal); str[4] != '\0') error(linecount,e_literal);
val = 64*str[1] - 73*'0' + 8*str[2] + str[3]; val = 64*str[1] - 73*'0' +
8*str[2] + str[3];
} }
} else { } else {
/* /*
@ -228,15 +213,38 @@ search(type,str,option) register string str; {
if (str[1] == '\0') val = str[0]; if (str[1] == '\0') val = str[0];
else error(linecount,e_literal); else error(linecount,e_literal);
} }
p->h_num = val; pt->t_tokno = val;
g_settype(&(p->h_type), LITERAL);
} else { } else {
/* /*
* Here, type = TERMINAL * Here, type = TERMINAL
*/ */
p->h_num = assval++; pt->t_tokno = assval++;
g_settype(&(p->h_type), TERMINAL);
}
g_setcont(&(p->h_type), ntokens);
ntokens++;
return &(p->h_type);
}
/*
* type == NONTERM || type == UNKNOWN
* UNKNOWN and not yet declared means : NONTERM
*/
{
register p_nont q;
q = (p_nont) new_mem(&nont_info);
nonterms = (p_nont) nont_info.i_ptr;
q->n_name = p->h_name;
q->n_rule = 0;
q->n_lineno = linecount;
q->n_string = f_input;
q->n_follow = 0;
q->n_flags = 0;
q->n_contains = 0;
g_settype(&(p->h_type), NONTERM);
g_setcont(&(p->h_type), nnonterms);
nnonterms++;
return &(p->h_type);
} }
g_settype(&r, TERMINAL);
g_setnont(&r, nterminals);
nterminals++;
return r;
} }

View file

@ -29,7 +29,6 @@
* are all defined. * are all defined.
*/ */
# include "tunable.h"
# include "types.h" # include "types.h"
# include "extern.h" # include "extern.h"
# include "io.h" # include "io.h"
@ -51,15 +50,15 @@ co_reach() {
*/ */
register p_nont p; register p_nont p;
register p_start st; register p_start st;
register p_file x = files; register p_file x;
register int *s; register p_order s;
/* Check for undefined nonterminals */ /* Check for undefined nonterminals */
for (p = nonterms; p < maxnt; p++) { for (p = nonterms; p < maxnt; p++) {
if (! p->n_rule) { if (! p->n_rule) { /* undefined */
f_input = p->n_string; f_input = p->n_string;
error(p->n_lineno,"nonterminal %s not defined", error(p->n_lineno,"nonterminal %s not defined",
(min_nt_ent + (p - nonterms))->h_name); p->n_name);
} }
} }
/* /*
@ -67,17 +66,19 @@ co_reach() {
* Mark the nonterminals that are encountered with the flag * Mark the nonterminals that are encountered with the flag
* REACHABLE, and walk their rules, if not done before * REACHABLE, and walk their rules, if not done before
*/ */
for (st = start; st; st = st->ff_next) reachable(st->ff_nont); for (st = start; st; st = st->ff_next) {
reachable(&nonterms[st->ff_nont]);
}
/* /*
* Now check for unreachable nonterminals * Now check for unreachable nonterminals
*/ */
for (; x->f_end < maxorder; x++) { for (x = files; x < maxfiles; x++) {
f_input = x->f_name; f_input = x->f_name;
for (s = x->f_start; s <= x->f_end; s++) { for (s = x->f_list; s; s = s->o_next) {
p = &nonterms[*s]; p = &nonterms[s->o_index];
if (! (p->n_flags & REACHABLE)) { if (! (p->n_flags & REACHABLE)) {
error(p->n_lineno,"nonterminal %s unreachable", error(p->n_lineno,"nonterminal %s unreachable",
(min_nt_ent + (p - nonterms))->h_name); p->n_name);
} }
} }
} }
@ -107,10 +108,10 @@ reachwalk(p) register p_gram p; {
for (;;) { for (;;) {
switch(g_gettype(p)) { switch(g_gettype(p)) {
case ALTERNATION : case ALTERNATION :
reachwalk(((p_link) pentry[g_getcont(p)])->l_rule); reachwalk(links[g_getcont(p)].l_rule);
break; break;
case TERM : case TERM :
reachwalk(((p_term) pentry[g_getcont(p)])->t_rule); reachwalk(terms[g_getcont(p)].t_rule);
break; break;
case NONTERM : case NONTERM :
reachable(&nonterms[g_getnont(p)]); reachable(&nonterms[g_getnont(p)]);

View file

@ -25,8 +25,7 @@
/* /*
* sets.c * sets.c
* Some general setmanipulation routines are defined, * Set manipulation and allocation routines.
* and also two set allocating routines are defined
*/ */
# include "types.h" # include "types.h"
@ -41,6 +40,7 @@ static string rcsid9 = "$Header$";
/* In this file the following routines are defined: */ /* In this file the following routines are defined: */
extern setinit(); extern setinit();
extern p_set setalloc(); extern p_set setalloc();
extern p_set get_set();
extern int setunion(); extern int setunion();
extern int setintersect(); extern int setintersect();
extern setminus(); extern setminus();
@ -48,11 +48,12 @@ extern int setempty();
extern int findindex(); extern int findindex();
extern int setcount(); extern int setcount();
int tbitset; int nbytes;
int setsize,tsetsize; static int setsize;
p_set *setptr, *maxptr, *topptr; int tsetsize;
p_set *setptr, *maxptr;
static unsigned size,nbytes; static t_info set_info;
p_mem alloc();
setinit(ntneeded) { setinit(ntneeded) {
/* /*
@ -60,84 +61,99 @@ setinit(ntneeded) {
*/ */
register int bitset; register int bitset;
nbytes = NBYTES(nterminals); nbytes = NBYTES(ntokens);
tbitset = ALIGN(nbytes); bitset = ALIGN(nbytes);
tsetsize = NINTS(tbitset); tsetsize = NINTS(bitset);
bitset = tbitset;
if (ntneeded) { if (ntneeded) {
/* nonterminals must be included in the sets */ /* nonterminals must be included in the sets */
bitset += NBYTES(nnonterms); bitset += NBYTES(nnonterms);
} }
setsize = NINTS(bitset); setsize = NINTS(bitset);
tbitset *= 8; set_info.i_esize = sizeof(p_set);
set_info.i_incr = 20;
} }
p_set p_set
setalloc(size) int size; { get_set() {
/* /*
* Allocate a set of size "size" ints * Allocate a set that cannot be freed
*/ */
register p_set t; register p_set p, q;
register int i; static p_set sets, maxsets;
p_mem alloc();
assert(size == tsetsize || size == setsize); if ((p = sets) >= maxsets) {
t = (p_set) alloc((unsigned) (size * sizeof(int))); q = p = (p_set) alloc((unsigned) (50*setsize*sizeof(*sets)));
i = size; maxsets = p + 50 * setsize;
t += i; do {
for (; i; i--) { *q++ = 0;
*--t = 0; } while (q < maxsets);
} }
return t; sets = p + setsize;;
return p;
}
p_set
setalloc() {
/*
* Allocate a set which can later be freed.
*/
register p_set p;
register int size = setsize;
p = (p_set) alloc((unsigned) (size * sizeof(*p))) + size;
do {
*--p = 0;
} while (--size);
return p;
} }
int int
setunion(a,b,size) register p_set a,b; int size; { setunion(a,b) register p_set a,b; {
/* /*
* a = a union b. * a = a union b.
* Return 1 if the set a changed * Return 1 if the set a changed
*/ */
register i; register int i;
register j; register int j;
int nsub = 0; register int nsub = 0;
assert(size == tsetsize || size == setsize); i = setsize;
for (i = size; i; i--) { do {
*a = (j = *a) | *b++; *a = (j = *a) | *b++;
if (*a++ != j) { if (*a++ != j) {
nsub = 1; nsub = 1;
} }
} } while (--i);
return nsub; return nsub;
} }
int int
setintersect(a,b,size) register p_set a,b; int size; { setintersect(a,b) register p_set a,b; {
/* /*
* a = a intersect b. * a = a intersect b.
* return 1 if the resut is empty * return 1 if the result is empty
*/ */
register i; register int i;
register nempty; register int nempty;
assert(size == tsetsize || size == setsize);
nempty = 1; nempty = 1;
for (i = size; i; i--) { i = setsize;
do {
if (*a++ &= *b++) nempty = 0; if (*a++ &= *b++) nempty = 0;
} } while (--i);
return nempty; return nempty;
} }
setminus(a,b,size) register p_set a,b; int size; { setminus(a,b) register p_set a,b; {
/* /*
* a = a setminus b * a = a setminus b
*/ */
register i; register int i;
assert(size == tsetsize || size == setsize); i = setsize;
for (i = size; i; i--) { do {
*a++ &= ~(*b++); *a++ &= ~(*b++);
} } while (--i);
} }
int int
@ -145,26 +161,28 @@ setempty(p) register p_set p; {
/* /*
* Return 1 if the set p is empty * Return 1 if the set p is empty
*/ */
register i; register int i;
for (i = tsetsize; i; i--) { i = tsetsize;
do {
if (*p++) return 0; if (*p++) return 0;
} } while (--i);
return 1; return 1;
} }
int int
findindex(set) p_set *set; { findindex(set) p_set set; {
/* /*
* The set "set" will serve as a recovery set. * The set "set" will serve as a recovery set.
* Search for it in the table. If not present, enter it * Search for it in the table. If not present, enter it.
* Here is room for improvement. At the moment, the list of
* sets is examined with linear search.
*/ */
register p_set *t; register p_set *t;
p_mem alloc(),ralloc(); p_mem new_mem();
register p_set a; register p_set a;
register p_set b; register p_set b;
register i; register int i;
register j;
int saved; int saved;
/* /*
@ -172,10 +190,11 @@ findindex(set) p_set *set; {
*/ */
for (t = setptr; t < maxptr; t++) { for (t = setptr; t < maxptr; t++) {
a = *t; a = *t;
b = *set; b = set;
for (i = tsetsize; i; i--) { i = tsetsize;
do {
if (*a++ != *b++) break; if (*a++ != *b++) break;
} } while (--i);
if (i) continue; if (i) continue;
/* /*
* Here, the sets are equal. * Here, the sets are equal.
@ -186,28 +205,14 @@ findindex(set) p_set *set; {
* Now check if the set consists of only one element. * Now check if the set consists of only one element.
* It would be a waste to use a set for that * It would be a waste to use a set for that
*/ */
if (setcount(*set, &saved) == 1) return -h_entry[saved].h_num; if (setcount(set, &saved) == 1) return -(saved + 1);
/* /*
* If it does, return its number as a negative number. * If it does, return its number as a negative number.
*/ */
if (maxptr >= topptr) { maxptr = (p_set *) new_mem(&set_info);
/* setptr = (p_set *) set_info.i_ptr;
* Need new space for the list, in chunks of 50 pointers *maxptr = setalloc();
*/ setunion(*maxptr, set);
if (setptr == 0) {
setptr = (p_set *) alloc(50 * sizeof(p_set));
size = 50;
maxptr = setptr;
} else {
setptr = (p_set *) ralloc((p_mem) setptr,
(50+size)*sizeof(p_set));
maxptr = &setptr[size-1];
size += 50;
}
topptr = &setptr[size-1];
}
*maxptr = setalloc(tsetsize);
setunion(*maxptr, *set, tsetsize);
return nbytes * (maxptr++ - setptr); return nbytes * (maxptr++ - setptr);
} }
@ -215,7 +220,7 @@ int
setcount(set, saved) register p_set set; int *saved; { setcount(set, saved) register p_set set; int *saved; {
register int i, j; register int i, j;
for (j = 0, i = 0; i < nterminals; i++) { for (j = 0, i = 0; i < ntokens; i++) {
if (IN(set,i)) { if (IN(set,i)) {
j++; j++;
*saved = i; *saved = i;

View file

@ -30,9 +30,9 @@
# define BITS (8 * sizeof (int)) # define BITS (8 * sizeof (int))
# define IN(a,i) ((a)[(i)/BITS] & (1<<((i) % BITS))) # define IN(a,i) ((a)[(i)/BITS] & (1<<((i) % BITS)))
# define NTIN(a,i) ((a)[((i)+tbitset)/BITS]&(1<<((i)%BITS))) # define NTIN(a,i) ((a)[(i)/BITS+tsetsize]&(1<<((i)%BITS)))
# define PUTIN(a,i) ((a)[(i)/BITS] |=(1<<((i) % BITS))) # define PUTIN(a,i) ((a)[(i)/BITS] |=(1<<((i) % BITS)))
# define NTPUTIN(a,i) ((a)[((i)+tbitset)/BITS]|=(1<<((i)%BITS))) # define NTPUTIN(a,i) ((a)[(i)/BITS+tsetsize]|=(1<<((i)%BITS)))
# define NBYTES(n) (((n) + 7) / 8) # define NBYTES(n) (((n) + 7) / 8)
/* /*
* The next two macros operate on byte counts! * The next two macros operate on byte counts!
@ -40,6 +40,6 @@
# define NINTS(n) (((n) + (int) (sizeof(int) - 1)) / (int) sizeof(int)) # define NINTS(n) (((n) + (int) (sizeof(int) - 1)) / (int) sizeof(int))
# define ALIGN(n) (NINTS(n) * (int) sizeof (int)) # define ALIGN(n) (NINTS(n) * (int) sizeof (int))
extern int tbitset; extern int tsetsize;
extern p_set *setptr,*maxptr,*topptr; extern p_set *setptr, *maxptr;
extern int tsetsize,setsize; extern int nbytes;

View file

@ -26,15 +26,15 @@
/* /*
* tokens.g * tokens.g
* Defines the tokens for the grammar of LLgen. * Defines the tokens for the grammar of LLgen.
* The lexical analyser and LLmes are also included here. * The lexical analyser and LLmessage are also included here.
*/ */
{ {
# include "types.h" # include "types.h"
# include "io.h" # include "io.h"
# include "tunable.h"
# include "extern.h" # include "extern.h"
# include "assert.h" # include "assert.h"
# include "cclass.h"
# ifndef NORCSID # ifndef NORCSID
static string rcsidc = "$Header$"; static string rcsidc = "$Header$";
@ -46,11 +46,12 @@ extern LLmessage();
extern int input(); extern int input();
extern unput(); extern unput();
extern skipcomment(); extern skipcomment();
# ifdef LINE_DIRECTIVE
STATIC linedirective(); STATIC linedirective();
# endif
STATIC string cpy(); STATIC string cpy();
STATIC string vallookup(); STATIC string vallookup();
} }
/* Classes */ /* Classes */
%token C_IDENT ; /* lextoken.t_string contains the identifier read */ %token C_IDENT ; /* lextoken.t_string contains the identifier read */
@ -78,17 +79,17 @@ STATIC string vallookup();
* Structure for a keyword * Structure for a keyword
*/ */
struct keyword { typedef struct keyword {
string w_word; string w_word;
int w_value; int w_value;
}; } t_keyw, *p_keyw;
/* /*
* The list of keywords, the most often used keywords come first. * The list of keywords, the most often used keywords come first.
* Linear search is used, as there are not many keywords * Linear search is used, as there are not many keywords
*/ */
static struct keyword resword[] = { static t_keyw resword[] = {
{ "token", C_TOKEN }, { "token", C_TOKEN },
{ "avoid", C_AVOID }, { "avoid", C_AVOID },
{ "prefer", C_PREFER }, { "prefer", C_PREFER },
@ -103,44 +104,39 @@ static struct keyword resword[] = {
}; };
static t_token savedtok; /* to save lextoken in case of an insertion */ static t_token savedtok; /* to save lextoken in case of an insertion */
# ifdef LINE_DIRECTIVE
static int nostartline; /* = 0 if at the start of a line */ static int nostartline; /* = 0 if at the start of a line */
# endif
scanner() { scanner() {
/* /*
* Lexical analyser, what else * Lexical analyser, what else
*/ */
register ch; /* Current char */ register int ch; /* Current char */
register i; register char *p = ltext;
register reserved = 0; /* reserved word? */ int reserved = 0; /* reserved word? */
int last; /* Char before current char */ int last; /* Char before current char */
char *max = &ltext[LTEXTSZ - 1];
if (savedtok.t_tokno) { /* if (ch = savedtok.t_tokno) {
* A token has been inserted. /* A token has been inserted.
* Now deliver the last lextoken again * Now deliver the last lextoken again
*/ */
lextoken = savedtok; lextoken = savedtok;
savedtok.t_tokno = 0; savedtok.t_tokno = 0;
return lextoken.t_tokno; return ch;
} }
for (;;) { /* for (;;) {
* First, skip space, comments, line directives, etc ch = input();
*/ if (ch == EOF) return ch;
do ch = input(); # ifdef LINE_DIRECTIVE
while(isspace(ch)); if (ch == '#' && !nostartline) {
if (ch == '/') skipcomment(0); linedirective();
else if (ch == '#' && !nostartline) linedirective(); continue;
else break;
} }
/* # endif
* Now we have a first character of a token switch(c_class[ch]) {
*/ case ISLIT :
switch(ch) {
case EOF :
return EOF;
case '\'': /*
* Literal, put it in ltext
*/
i = 0;
for (;;) { for (;;) {
last = ch; last = ch;
ch = input(); ch = input();
@ -149,53 +145,53 @@ scanner() {
break; break;
} }
if (ch == '\'' && last != '\\') break; if (ch == '\'' && last != '\\') break;
ltext[i] = ch; *p++ = ch;
if (i < LTEXTSZ - 1) ++i; if (p > max) p--;
} }
ltext[i] = '\0'; *p = '\0';
lextoken.t_string = ltext; lextoken.t_string = ltext;
return C_LITERAL; return C_LITERAL;
case '%' : /* case ISCOM :
* Start of a reserved word skipcomment(0);
*/ /* Fall through */
case ISSPA :
continue;
case ISDIG : {
register i = 0;
do {
i = 10 * i + (ch - '0');
ch= input();
} while (c_class[ch] == ISDIG);
lextoken.t_num = i;
unput(ch);
return C_NUMBER; }
default:
return ch;
case ISKEY :
reserved = 1; reserved = 1;
ch = input(); ch = input();
/* Fall through */ /* Fall through */
default : case ISLET :
i = 0;
if (isdigit(ch)) {
if (reserved) {
error(linecount," A reserved number ?");
}
while (isdigit(ch)) {
i = 10 * i + (ch - '0');
ch= input();
}
lextoken.t_num = i;
unput(ch);
return C_NUMBER;
}
if (isalpha(ch) || ch == '_') {
do { do {
if (reserved && isupper(ch)) ch += 'a' - 'A'; if (reserved && ch >= 'A' && ch <= 'Z') {
ltext[i] = ch; ch += 'a' - 'A';
if (i < LTEXTSZ - 1) ++i;
ch = input();
} while (isalnum(ch) || ch == '_');
} else return ch;
unput(ch);
} }
ltext[i] = '\0'; *p++ = ch;
if (p > max) p--;
ch = input();
} while (c_class[ch] == ISDIG || c_class[ch] == ISLET);
unput(ch);
*p = '\0';
if (reserved) { /* if (reserved) { /*
* Now search for the keyword * Now search for the keyword
*/ */
register struct keyword *w; register p_keyw w;
w = resword; w = resword;
while (w->w_word) { while (w->w_word) {
if (! strcmp(ltext,w->w_word)) { if (! strcmp(ltext,w->w_word)) {
/* /*
* Found it. Return token number. * Return token number.
*/ */
return w->w_value; return w->w_value;
} }
@ -205,6 +201,8 @@ scanner() {
} }
lextoken.t_string = ltext; lextoken.t_string = ltext;
return C_IDENT; return C_IDENT;
}
}
} }
static int backupc; /* for unput() */ static int backupc; /* for unput() */
@ -215,21 +213,22 @@ input() {
* Low level input routine, used by all other input routines * Low level input routine, used by all other input routines
*/ */
register c; register c;
register FILE *f;
if(backupc) { /* if (c = backupc) {
* Last char was "unput()". Deliver it again /* Last char was "unput()". Deliver it again
*/ */
c = backupc;
backupc = 0; backupc = 0;
return c; return c;
} }
f = finput; if ((c = getc(finput)) == EOF) return c;
if ((c = getc(f)) == EOF) return c; # ifdef LINE_DIRECTIVE
nostartline = 1; nostartline = 1;
# endif
if (!nonline) { if (!nonline) {
linecount++; linecount++;
# ifdef LINE_DIRECTIVE
nostartline = 0; nostartline = 0;
# endif
nonline = 1; nonline = 1;
} }
if (c == '\n') nonline = 0; if (c == '\n') nonline = 0;
@ -249,30 +248,29 @@ skipcomment(flag) {
* of C-code, so the newlines in it must be copied to enable the * of C-code, so the newlines in it must be copied to enable the
* C-compiler to keep a correct line count * C-compiler to keep a correct line count
*/ */
register ch; register int ch;
int saved; /* line count on which comment starts */ int saved; /* line count on which comment starts */
saved = linecount; saved = linecount;
if (input() != '*') error(linecount,"illegal comment"); if (input() != '*') error(linecount,"illegal comment");
do {
ch = input(); ch = input();
while (ch != EOF) {
if (flag && ch == '\n') putc(ch,fact);
while (ch == '*') { while (ch == '*') {
if ((ch = input()) == '/') return; if ((ch = input()) == '/') return;
}
if (flag && ch == '\n') putc(ch,fact); if (flag && ch == '\n') putc(ch,fact);
} } while (ch != EOF);
ch = input();
}
error(saved,"Comment does not terminate"); error(saved,"Comment does not terminate");
} }
# ifdef LINE_DIRECTIVE
STATIC STATIC
linedirective() { linedirective() {
/* /*
* Read a line directive * Read a line directive
*/ */
register ch; register int ch;
register i; register int i;
string s_error = "Illegal line directive"; string s_error = "Illegal line directive";
string store(); string store();
register string c; register string c;
@ -282,17 +280,16 @@ linedirective() {
* Do not skip newlines * Do not skip newlines
*/ */
ch = input(); ch = input();
} while (ch != '\n' && ! isdigit(ch)); } while (ch != '\n' && c_class[ch] != ISDIG);
if (ch == '\n') { if (ch == '\n') {
error(linecount,s_error); error(linecount,s_error);
return; return;
} }
i = ch - '0'; i = 0;
ch = input(); do {
while (isdigit(ch)) {
i = i*10 + (ch - '0'); i = i*10 + (ch - '0');
ch = input(); ch = input();
} } while (c_class[ch] == ISDIG);
while (ch != '\n' && ch != '"') ch = input(); while (ch != '\n' && ch != '"') ch = input();
if (ch == '"') { if (ch == '"') {
c = ltext; c = ltext;
@ -314,13 +311,14 @@ linedirective() {
} }
linecount = i; linecount = i;
} }
# endif
STATIC string STATIC string
vallookup(s) { vallookup(s) {
/* /*
* Look up the keyword that has token number s * Look up the keyword that has token number s
*/ */
register struct keyword *p = resword; register p_keyw p = resword;
while (p->w_value) { while (p->w_value) {
if (p->w_value == s) return p->w_word; if (p->w_value == s) return p->w_word;
@ -330,25 +328,24 @@ vallookup(s) {
} }
STATIC string STATIC string
cpy(s,p,flag) register s; register string p; { cpy(s,p,inserted) register string p; {
/* /*
* Create a piece of error message for token s and put it at p. * Create a piece of error message for token s and put it at p.
* flag = 0 if the token s was deleted (in which case we have * inserted = 0 if the token s was deleted (in which case we have
* attributes), else it was inserted * attributes), else it was inserted
*/ */
register string t = 0; register string t = 0;
switch(s) { switch(s) {
case C_IDENT : case C_IDENT :
if (!flag) t = lextoken.t_string; if (!inserted) t = lextoken.t_string;
else t = "identifier"; else t = "identifier";
break; break;
case C_NUMBER : case C_NUMBER :
t = "number"; t = "number";
break; break;
case C_LITERAL : case C_LITERAL :
if (!flag) { if (!inserted) {
*p++ = '"';
*p++ = '\''; *p++ = '\'';
t = lextoken.t_string; t = lextoken.t_string;
break; break;
@ -359,19 +356,15 @@ cpy(s,p,flag) register s; register string p; {
t = "endoffile"; t = "endoffile";
break; break;
} }
if (!t) { if (!t && (t = vallookup(s))) {
t = vallookup(s);
if (t) {
*p++ = '%'; *p++ = '%';
} }
}
if (t) { /* if (t) { /*
* We have a string for the token. Copy it * We have a string for the token. Copy it
*/ */
while (*t) *p++ = *t++; while (*t) *p++ = *t++;
if (s == C_LITERAL && !flag) { if (s == C_LITERAL && !inserted) {
*p++ = '\''; *p++ = '\'';
*p++ = '"';
} }
return p; return p;
} }
@ -380,15 +373,18 @@ cpy(s,p,flag) register s; register string p; {
*/ */
*p++ = '\''; *p++ = '\'';
if (s >= 040 && s <= 0176) *p++ = s; if (s >= 040 && s <= 0176) *p++ = s;
else switch(s) { else {
case '\b' : *p++ = '\\'; *p++ = 'b'; break; *p++ = '\\';
case '\f' : *p++ = '\\'; *p++ = 'f'; break; switch(s) {
case '\n' : *p++ = '\\'; *p++ = 'n'; break; case '\b' : *p++ = 'b'; break;
case '\r' : *p++ = '\\'; *p++ = 'r'; break; case '\f' : *p++ = 'f'; break;
case '\t' : *p++ = '\\'; *p++ = 't'; break; case '\n' : *p++ = 'n'; break;
case '\r' : *p++ = 'r'; break;
case '\t' : *p++ = 't'; break;
default : *p++='0'+((s&0377)>>6); *p++='0'+((s>>3)&07); default : *p++='0'+((s&0377)>>6); *p++='0'+((s>>3)&07);
*p++='0'+(s&07); *p++='0'+(s&07);
} }
}
*p++ = '\''; *p++ = '\'';
return p; return p;
} }

View file

@ -43,7 +43,7 @@ typedef struct token {
} t_x; } t_x;
# define t_string t_x.t_s # define t_string t_x.t_s
# define t_num t_x.t_v # define t_num t_x.t_v
} t_token; } t_token, *p_token;
/* /*
* structure for the grammar elements * structure for the grammar elements
@ -74,49 +74,49 @@ typedef struct gram {
# define TERMINAL 03 /* A terminal */ # define TERMINAL 03 /* A terminal */
# define TERM 04 /* Something between square brackets */ # define TERM 04 /* Something between square brackets */
# define ALTERNATION 05 /* Alternation (|) */ # define ALTERNATION 05 /* Alternation (|) */
# define LITERAL 06 /* Also a terminal */
/* /*
* Access macros for the x-field of a grammar element * Access macros for the x-field of a grammar element
*/ */
# define g_init(p) {(p)->x = 0;}
# define g_gettype(p) (((p)->x>>13)&07) # define g_gettype(p) (((p)->x>>13)&07)
# define g_getcont(p) ((p)->x&017777) # define g_getcont(p) ((p)->x&017777)
# define g_getnont(p) ((p)->x&0777) # define g_getnont(p) ((p)->x&0777)
# define g_getnpar(p) (((p)->x>>9)&07) # define g_getnpar(p) (((p)->x>>9)&017)
# define g_settype(p,s) { assert(((unsigned)(s))<=07);(p)->x=((p)->x&017777)|((s)<<13);} # define g_settype(p,s) { assert(((unsigned)(s))<=07);(p)->x=((p)->x&017777)|((s)<<13);}
# define g_setcont(p,s) { assert(((unsigned)(s))<=017777);(p)->x=((p)->x&0160000)|(s);} # define g_setcont(p,s) { assert(((unsigned)(s))<=017777);(p)->x=((p)->x&0160000)|(s);}
# define g_setnont(p,s) { assert(((unsigned)(s))<=0777);(p)->x=((p)->x&0177000)|(s);} # define g_setnont(p,s) { assert(((unsigned)(s))<=0777);(p)->x=((p)->x&0177000)|(s);}
# define g_setnpar(p,s) { assert(((unsigned)(s))<=07);(p)->x=((p)->x&0170777)|((s)<<9);} # define g_setnpar(p,s) { assert(((unsigned)(s))<=017);(p)->x=((p)->x&0160777)|((s)<<9);}
/* /*
* Some constants to communicate with the symbol table search routine * Some constants to communicate with the symbol table search routine
*/ */
# define LITERAL 01 /* Not equal to NONTERM or TERMINAL */
# define UNKNOWN 00 /* Not equal to NONTERM, TERMINAL or LITERAL */ # define UNKNOWN 00 /* Not equal to NONTERM, TERMINAL or LITERAL */
/* /*
* Some constants for safety * Some constants for safety
*/ */
# define SAFE 0 # define SAFE 0 /* Indicates that a scan is done, and that the
# define SAFESCANDONE 1 * token is correct
# define SCANDONE 2 */
# define NOSCANDONE 3 # define SAFESCANDONE 1 /* Indicates that a scan is done, and that the
# define NOSAFETY 4 * token will not be skipped
*/
# define SCANDONE 2 /* Indicates that a scan is done */
# define NOSCANDONE 3 /* Indicates that no scan is done */
# define NOSAFETY 4 /* Safety not yet computed */
/* /*
* nonterminal structure * nonterminal structure
*/ */
typedef struct { typedef struct {
short n_flags; /* low order three bits are reserved short n_flags; /* low order four bits are reserved
* the parameter count * the parameter count
*/ */
# define getntparams(p) ((p)->n_flags&07) # define getntparams(p) ((p)->n_flags&017)
# define setntparams(p,i) {assert(((unsigned)(i))<=7);(p)->n_flags&=~07;(p)->n_flags|=(i);} # define setntparams(p,i) {assert(((unsigned)(i))<=017);(p)->n_flags&=~017;(p)->n_flags|=(i);}
# define RECURSIVE 00100 /* Set if the default rule is recursive */ # define RECURSIVE 02000 /* Set if the default rule is recursive */
# define CONTIN 00400 /* continuation already computed? */ # define PARAMS 04000 /* tells if a nonterminal has parameters */
# define BUSY 01000 /* or are we busy computing it? */
# define PARAMS 02000 /* tells if a nonterminal has parameters */
# define PRODUCE 04000 /* tells if a nonterminal produces anything */
# define EMPTY 010000 /* tells if a nonterminal produces empty */ # define EMPTY 010000 /* tells if a nonterminal produces empty */
# 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 ? */
@ -141,6 +141,7 @@ typedef struct {
# define n_string n_x.n_s # define n_string n_x.n_s
p_set n_follow; /* pointer to the "follow" set */ p_set n_follow; /* pointer to the "follow" set */
p_set n_contains; /* pointer to symbols that can be produced */ p_set n_contains; /* pointer to symbols that can be produced */
string n_name; /* name of nonterminal */
} t_nont, *p_nont; } t_nont, *p_nont;
/* /*
@ -148,7 +149,7 @@ typedef struct {
*/ */
typedef struct h_entry { typedef struct h_entry {
string h_name; /* pointer to name */ string h_name; /* pointer to name */
int h_num; /* numbering of terminals */ t_gram h_type; /* Type and index */
struct h_entry *h_next; /* next in hash chain */ struct h_entry *h_next; /* next in hash chain */
} t_entry, *p_entry; } t_entry, *p_entry;
@ -180,20 +181,19 @@ typedef short t_reps,*p_reps;
# define OPT 03 /* 0 or 1 times */ # define OPT 03 /* 0 or 1 times */
/* /*
* Access macros for repitition * Access macros for repitition in term
*/ */
# define r_init(p) {*(p)=0;} # define r_getkind(q) ((q)->t_reps&03)
# define r_getkind(p) (*(p)&03) # define r_getnum(q) (((q)->t_reps>>2)&037777)
# define r_getnum(p) ((*(p)>>2)&037777) # define r_setkind(q,s) { assert(((unsigned)(s))<=03);(q)->t_reps=((q)->t_reps&0177774)|(s);}
# define r_setkind(p,s) { assert(((unsigned)(s))<=03);*(p)=(*(p)&0177774)|(s);} # define r_setnum(q,s) { assert(((unsigned)(s))<=037777);(q)->t_reps=((q)->t_reps&03)|((s)<<2);}
# define r_setnum(p,s) { assert(((unsigned)(s))<=037777);*(p)=(*(p)&03)|((s)<<2);}
/* /*
* header structure for a term * header structure for a term
*/ */
typedef struct term { typedef struct term {
t_reps t_reps; /* repeats ? */ t_reps t_reps; /* repeats ? */
short t_flags; short t_flags; /* Low order three bits for safety */
# define gettout(q) ((q)->t_flags&07) # define gettout(q) ((q)->t_flags&07)
# define settout(q,i) {assert(((unsigned)(i))<=NOSAFETY);(q)->t_flags&=~07;(q)->t_flags|=i;} # 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 */
@ -205,7 +205,7 @@ typedef struct term {
p_gram t_rule; /* pointer to this term */ p_gram t_rule; /* pointer to this term */
p_set t_follow; /* set of followers */ p_set t_follow; /* set of followers */
p_set t_first; /* set of firsts */ p_set t_first; /* set of firsts */
p_set t_contains; p_set t_contains; /* contains set */
} t_term, *p_term; } t_term, *p_term;
/* /*
@ -213,7 +213,7 @@ typedef struct term {
*/ */
typedef struct ff_firsts { typedef struct ff_firsts {
string ff_name; /* Name of the macro */ string ff_name; /* Name of the macro */
p_nont ff_nont; /* for this nonterminal */ int ff_nont; /* for this nonterminal */
struct ff_firsts *ff_next; struct ff_firsts *ff_next;
} t_first, *p_first; } t_first, *p_first;
@ -223,6 +223,11 @@ typedef struct ff_firsts {
typedef t_first t_start; typedef t_first t_start;
typedef p_first p_start; typedef p_first p_start;
typedef struct order {
int o_index; /* index in nonterminal array */
struct order *o_next;
} t_order, *p_order;
/* /*
* structure for file names and info * structure for file names and info
*/ */
@ -232,11 +237,21 @@ typedef struct f_file {
* generated in the target file for this * generated in the target file for this
* grammar file * grammar file
*/ */
short *f_start,*f_end;/* pointers in the "order" array, struct order *f_list; /* list of nonterminals in this file */
* Indicating which nonterminals were defined
* in this file
*/
} t_file, *p_file; } t_file, *p_file;
typedef struct info_alloc {
/*
* Structure used for dynamically growing arrays
*/
unsigned i_size; /* Size of the array */
unsigned i_esize; /* Size of an element */
unsigned i_incr; /* When filled, add room for i_incr elements */
p_mem i_ptr; /* ptr to base of array */
p_mem i_max; /* ptr to first free */
p_mem i_top; /* ptr to top of array */
} t_info, *p_info;
# ifdef NDEBUG # ifdef NDEBUG
# define STATIC static # define STATIC static
# else not NDEBUG # else not NDEBUG