Add original unix v6
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
main( argc, argv ) int argc; char *argv[]; {
|
||||
yyinit( argc, argv );
|
||||
if( yyparse() ) return;
|
||||
yyaccpt();
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
# define _maxdepth 150
|
||||
|
||||
/* parser for yacc output */
|
||||
extern int yyval; /* defined in the table file */
|
||||
extern int yylval; /* defined in the table file */
|
||||
extern int *yypv; /* defined in the table file */
|
||||
|
||||
|
||||
int yydebug 0; /* 1 for debugging */
|
||||
int yyv[_maxdepth]; /* where the values are stored */
|
||||
int yystate 0; /* current parser state */
|
||||
int yychar -1; /* current input token number */
|
||||
int yynerrs 0; /* number of errors */
|
||||
int yyerrflag 0; /* error recovery flag */
|
||||
|
||||
|
||||
yyparse() {
|
||||
|
||||
extern int yygo[], yypgo[], yyr1[], yyr2[], yyact[], yypact[];
|
||||
auto int *ps, s[_maxdepth];
|
||||
auto int ac, n, *p;
|
||||
|
||||
yystate = 0;
|
||||
yychar = -1;
|
||||
yynerrs = 0;
|
||||
yyerrflag = 0;
|
||||
ps= &s[0]-1;
|
||||
yypv= &yyv[0]-1;
|
||||
|
||||
stack: /* put a state and value onto the stack */
|
||||
|
||||
if( yydebug ) printf( "state %d, value %d, char %d\n",yystate,yyval,yychar );
|
||||
*++ps = yystate;
|
||||
*++yypv = yyval;
|
||||
|
||||
newstate: /* set ap to point to the parsing actions for the new state */
|
||||
|
||||
p = &yyact[ yypact[yystate+1] ];
|
||||
|
||||
actn: /* get the next action, and perform it */
|
||||
|
||||
n = ( ac = *p++ ) & 07777; /* n is the "address" of the action */
|
||||
|
||||
switch( ac>>12 ) { /* switch on operation */
|
||||
|
||||
case 1: /* skip on test */
|
||||
if( yydebug && (yychar<0) ){
|
||||
yychar = yylex();
|
||||
printf( "character %d read\n", yychar );
|
||||
}
|
||||
if( n != ( (yychar<0) ? ( yychar=yylex() ) : yychar ) ) ++p;
|
||||
goto actn; /* get next action */
|
||||
|
||||
case 2: /* shift */
|
||||
|
||||
yystate=n;
|
||||
yyval=yylval;
|
||||
yychar= -1;
|
||||
if( yyerrflag ) --yyerrflag;
|
||||
goto stack; /* stack new state */
|
||||
|
||||
case 3: /* reduce */
|
||||
|
||||
if( yydebug ) printf("reduce %d\n",n);
|
||||
ps =- yyr2[n];
|
||||
yypv =- yyr2[n];
|
||||
yyval=yypv[1];
|
||||
yyactr(n);
|
||||
/* consult goto table to find next state */
|
||||
for( p= &yygo[yypgo[yyr1[n]]]; *p != *ps && *p >= 0 ; p =+ 2 ) ;
|
||||
yystate = p[1];
|
||||
goto stack; /* stack new state and value */
|
||||
|
||||
case 4: /* accept */
|
||||
return(0);
|
||||
|
||||
case 0: /* error ... attempt to resume parsing */
|
||||
|
||||
switch( yyerrflag ){
|
||||
|
||||
case 0: /* brand new error */
|
||||
|
||||
++yynerrs;
|
||||
yyerror( "syntax error" );
|
||||
|
||||
case 1:
|
||||
case 2: /* incompletely recovered error ... try again */
|
||||
|
||||
yyerrflag = 3;
|
||||
|
||||
/* find a state where "error" is a legal shift action */
|
||||
|
||||
while ( ps >= s ) {
|
||||
for( p= &yyact[ yypact[*ps+1] ] ; (*p>>12) == 1 ; p =+ 2 ) /* search ps actions */
|
||||
if( *p == 4352 ) goto found;
|
||||
|
||||
/* the current ps has no shift onn "error", pop stack */
|
||||
|
||||
if( yydebug ) printf( "error recovery pops state %d, uncovers %d\n", *ps, ps[-1] );
|
||||
--ps;
|
||||
--yypv;
|
||||
}
|
||||
|
||||
/* there is no state on the stack with an error shift ... abort */
|
||||
|
||||
abort:
|
||||
return(1);
|
||||
|
||||
found: /* we have a state with a shift on "error", resume parsing */
|
||||
|
||||
yystate = p[1] & 07777;
|
||||
goto stack;
|
||||
|
||||
case 3: /* no shift yet; clobber input char */
|
||||
|
||||
if( yydebug ) printf( "error recovery discards char %d\n", yychar );
|
||||
|
||||
if( yychar == 0 ) goto abort; /* don't discard EOF, quit */
|
||||
yychar = -1;
|
||||
goto newstate; /* try again in the same state */
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
yyaccpt(){}
|
||||
@@ -0,0 +1,16 @@
|
||||
extern int yyline; /* input line number */
|
||||
|
||||
yyerror(s) char *s; {
|
||||
extern int yychar;
|
||||
extern char *yysterm[];
|
||||
printf("\n%s", s );
|
||||
if( yyline ) printf(", line %d,", yyline );
|
||||
printf(" on input: ");
|
||||
if( yychar >= 0400 ) printf("%s\n", yysterm[yychar-0400] );
|
||||
else switch ( yychar ) {
|
||||
case '\t': printf( "\\t\n" ); return;
|
||||
case '\n': printf( "\\n\n" ); return;
|
||||
case '\0': printf( "$end\n" ); return;
|
||||
default: printf( "%c\n" , yychar ); return;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
yyinit(){}
|
||||
@@ -0,0 +1,9 @@
|
||||
chdir lib
|
||||
cc -c -O *.c
|
||||
ar r /lib/liby.a *.o
|
||||
rm *.o
|
||||
chdir ../source
|
||||
cc -s -O y?.c
|
||||
cmp a.out /usr/bin/yacc
|
||||
cp a.out /usr/bin/yacc
|
||||
rm a.out *.o
|
||||
@@ -0,0 +1,123 @@
|
||||
#
|
||||
/* MANIFEST CONSTANT DEFINITIONS */
|
||||
|
||||
# define NTBASE 010000
|
||||
|
||||
/* internal codes for error and accept actions */
|
||||
|
||||
# define ERRCODE 8190
|
||||
# define ACCEPTCODE 8191
|
||||
|
||||
# define errfileno 1 /* file number for erros and reduction message */
|
||||
# define _tbitset 6 /* 16*_tbitset - 1 >= _nterms */
|
||||
|
||||
extern int tbitset; /* number of wds of lookahead vector */
|
||||
extern int nolook; /* flag to turn off lookahed computations */
|
||||
struct looksets { int lset[ _tbitset ]; } ;
|
||||
struct item { int *pitem; struct looksets *look; } ;
|
||||
|
||||
/* output actions */
|
||||
|
||||
# define ERRACT 0
|
||||
# define TESTACT 4096
|
||||
# define SHIFTACT 8192
|
||||
# define REDUCACT 12288
|
||||
# define ACCEPTACT 16384
|
||||
|
||||
# define _REGISTER register
|
||||
|
||||
extern int nstate ; /* number of states */
|
||||
extern struct item *pstate[]; /* pointers to the descriptions of the states */
|
||||
extern int apstate[]; /* index to actions in amem by state */
|
||||
extern int actsiz; /* size of the action table array */
|
||||
extern int tystate[]; /* contains type information about the states */
|
||||
/* 0 = simple state, completely generated
|
||||
1 = state awaiting generation
|
||||
2 = state with an empty production in closure
|
||||
*/
|
||||
extern int stsize ; /* maximum number of states, at present */
|
||||
extern int memsiz ; /* maximum size for productions and states */
|
||||
extern int mem0[] ; /* added production */
|
||||
extern int *mem ;
|
||||
extern int amem[]; /* action table storage */
|
||||
extern int actsiz; /* action table size */
|
||||
extern int memact ; /* next free action table position */
|
||||
extern int nprod ; /* number of productions */
|
||||
extern int *prdptr[]; /* pointers to descriptions of productions */
|
||||
extern int prdlim; /* the number of productions allowed */
|
||||
extern int levprd[] ; /* contains production levels to break conflicts */
|
||||
/* last two bits code associativity:
|
||||
0 = no definition
|
||||
1 = left associative
|
||||
2 = binary
|
||||
3 = right associative
|
||||
bit 04 is 1 if the production has an action
|
||||
the high 13 bits have the production level
|
||||
*/
|
||||
extern int nterms ; /* number of terminals */
|
||||
extern int nerrors; /* number of errors */
|
||||
extern int fatfl; /* if on, error is fatal */
|
||||
/* the ascii representations of the terminals */
|
||||
extern int extval; /* start of output values */
|
||||
extern struct sxxx1 {char *name; int value;} trmset[];
|
||||
extern char cnames[];
|
||||
extern int cnamsz;
|
||||
extern char *cnamp;
|
||||
extern int maxtmp ; /* the size of the temp arrays */
|
||||
/* temporary vectors, indexable by states, terms, or nterms */
|
||||
extern int temp1[];
|
||||
extern int temp2[];
|
||||
extern int trmlev[]; /* vector with the precedence of the terminals */
|
||||
/* The levels are the same as for levprd, but bit 04 is always 0 */
|
||||
/* the ascii representations of the nonterminals */
|
||||
extern struct sxxx2 { char *name; } nontrst[];
|
||||
extern int indgo[]; /* index to the stored goto table */
|
||||
extern int ***pres; /* vector of pointers to the productions yielding each nonterminal */
|
||||
extern struct looksets **pfirst; /* vector of pointers to first sets for each nonterminal */
|
||||
extern int *pempty ; /* table of nonterminals nontrivially deriving e */
|
||||
extern int nnonter ; /* the number of nonterminals */
|
||||
extern int lastred ; /* the number of the last reduction of a state */
|
||||
extern int ftable; /* y.tab.c file */
|
||||
extern int foutput; /* y.output file */
|
||||
extern int cin; /* current input file */
|
||||
extern int cout; /* current output file */
|
||||
extern int arrndx;
|
||||
extern int zzcwset;
|
||||
extern int zzpairs ;
|
||||
extern int zzgoent ;
|
||||
extern int zzgobest ;
|
||||
extern int zzacent ;
|
||||
extern int zzacsave ;
|
||||
extern int zznsave ;
|
||||
extern int zzclose ;
|
||||
extern int zzrrconf ;
|
||||
extern int zzsrconf ;
|
||||
extern char *ctokn;
|
||||
struct {int **ppi;} ;
|
||||
extern int ntlim ; /* maximum number of nonterminals */
|
||||
extern int tlim ; /* maximum number of terminals */
|
||||
extern int lineno; /* current line number */
|
||||
extern int peekc; /* look-ahead character */
|
||||
extern int tstates[];
|
||||
extern int ntstates[];
|
||||
extern int mstates[];
|
||||
|
||||
extern struct looksets clset;
|
||||
extern struct looksets lkst[];
|
||||
extern int nlset; /* next lookahead set index */
|
||||
extern int lsetsz; /* number of lookahead sets */
|
||||
|
||||
extern struct wset { int *pitem, flag, ws[ _tbitset ]; } wsets[];
|
||||
extern int cwset;
|
||||
extern int wssize;
|
||||
|
||||
extern int numbval; /* the value of an input number */
|
||||
extern int rflag; /* ratfor flag */
|
||||
extern int oflag; /* optimization flag */
|
||||
extern int ndefout; /* number of defined symbols output */
|
||||
|
||||
extern int machine;
|
||||
|
||||
# define UNIX 1
|
||||
# define GCOS 2
|
||||
# define IBM 3
|
||||
@@ -0,0 +1,103 @@
|
||||
# define _actsize 1500
|
||||
# define _memsize 3500
|
||||
# define _nstates 400
|
||||
# define _nterms 95
|
||||
# define _nprod 250
|
||||
# define _nnonterm 100
|
||||
# define _tempsize 400
|
||||
# define _cnamsz 2000
|
||||
# define _lsetsize 200
|
||||
# define _wsetsize 150
|
||||
|
||||
# define _tbitset 6
|
||||
|
||||
int tbitset; /* size of lookahed sets */
|
||||
int nolook 0; /* flag to suppress lookahead computations */
|
||||
struct looksets { int lset[ _tbitset ]; } ;
|
||||
struct item { int *pitem; } ;
|
||||
|
||||
/* this file contains the definitions for most externally known data */
|
||||
|
||||
int nstate 0; /* number of states */
|
||||
struct item *pstate[_nstates]; /* pointers to the descriptions of the states */
|
||||
int apstate[_nstates]; /* index to the actions for the states */
|
||||
int tystate[_nstates]; /* contains type information about the states */
|
||||
int stsize _nstates; /* maximum number of states, at present */
|
||||
int memsiz _memsize; /* maximum size for productions and states */
|
||||
int mem0[_memsize] ; /* production storage */
|
||||
int *mem mem0;
|
||||
int amem[_actsize]; /* action table storage */
|
||||
int actsiz _actsize; /* action table size */
|
||||
int memact 0; /* next free action table position */
|
||||
int nprod 1; /* number of productions */
|
||||
int *prdptr[_nprod]; /* pointers to descriptions of productions */
|
||||
int prdlim _nprod ; /* the maximum number of productions */
|
||||
/* levprd - productions levels to break conflicts */
|
||||
int levprd[_nprod] {0,0};
|
||||
/* last two bits code associativity:
|
||||
0 = no definition
|
||||
1 = left associative
|
||||
2 = binary
|
||||
3 = right associative
|
||||
bit 04 is 1 if the production has an action
|
||||
the high 13 bits have the production level
|
||||
*/
|
||||
int nterms 0; /* number of terminals */
|
||||
int tlim _nterms ; /* the maximum number of terminals */
|
||||
/* the ascii representations of the terminals */
|
||||
int extval 0; /* start of output values */
|
||||
struct sxxx1 {char *name; int value;} trmset[_nterms];
|
||||
char cnames[_cnamsz];
|
||||
int cnamsz _cnamsz;
|
||||
char *cnamp;
|
||||
int maxtmp _tempsize; /* the size of the temp1 array */
|
||||
int temp1[_tempsize]; /* temporary storage, indexed by terms + nterms or states */
|
||||
int temp2[_nnonterm]; /* temporary storage indexed by nonterminals */
|
||||
int trmlev[_nterms]; /* vector with the precedence of the terminals */
|
||||
/* The levels are the same as for levprd, but bit 04 is always 0 */
|
||||
/* the ascii representations of the nonterminals */
|
||||
struct sxxx2 { char *name; } nontrst[_nnonterm];
|
||||
int ntlim _nnonterm ; /* limit to the number of nonterminals */
|
||||
int indgo[_nstates]; /* index to the stored goto table */
|
||||
int ***pres; /* vector of pointers to the productions yielding each nonterminal */
|
||||
struct looksets **pfirst; /* vector of pointers to first sets for each nonterminal */
|
||||
int *pempty 0 ; /* table of nonterminals nontrivially deriving e */
|
||||
int nnonter -1; /* the number of nonterminals */
|
||||
int lastred 0; /* the number of the last reduction of a state */
|
||||
int ftable; /* y.tab.c file */
|
||||
int foutput; /* y.output file */
|
||||
int arrndx; /* used in the output of arrays on y.tab.c */
|
||||
int zzcwset 0;
|
||||
int zzpairs 0;
|
||||
int zzgoent 0;
|
||||
int zzgobest 0;
|
||||
int zzacent 0;
|
||||
int zzacsave 0;
|
||||
int zznsave 0;
|
||||
int zzclose 0;
|
||||
int zzsrconf 0;
|
||||
int zzrrconf 0;
|
||||
char *ctokn;
|
||||
int lineno 1; /* current input line number */
|
||||
int peekc -1; /* look-ahead character */
|
||||
int tstates[ _nterms ]; /* states generated by terminal gotos */
|
||||
int ntstates[ _nnonterm ]; /* states generated by nonterminal gotos */
|
||||
int mstates[ _nstates ]; /* chain of overflows of term/nonterm generation lists */
|
||||
|
||||
struct looksets clset;
|
||||
struct looksets lkst [ _lsetsize ];
|
||||
int nlset 0; /* next lookahead set index */
|
||||
int lsetsz _lsetsize; /* number of lookahead sets */
|
||||
|
||||
struct wset { int *pitem, flag, ws[_tbitset]; } wsets[ _wsetsize ];
|
||||
int cwset;
|
||||
int wssize _wsetsize;
|
||||
|
||||
int numbval; /* the value of an input number */
|
||||
int rflag 0; /* ratfor flag */
|
||||
int oflag 0; /* optimization flag */
|
||||
|
||||
int ndefout 3; /* number of defined symbols output */
|
||||
int nerrors 0; /* number of errors */
|
||||
int fatfl 1; /* if on, error is fatal */
|
||||
int machine; /* has a number describing the machine */
|
||||
@@ -0,0 +1,281 @@
|
||||
# include "dextern"
|
||||
/* * * * * y a c c * * * * */
|
||||
|
||||
/* features to be fixed up ...
|
||||
|
||||
*** Print estimate of total space needed for parser
|
||||
*** Either list inputs on y.output, or list empty prdn's in states
|
||||
*** Mention nonterms not used (or, rules. not reduced) as nonfatal error
|
||||
*** Output states where conflicts were found by default on y.output
|
||||
*** Engage in newspeak: production=>grammar rules, term=>token, etc.
|
||||
*** handle # define, #ifdef, etc., in yacc actions, %{ %}
|
||||
*/
|
||||
|
||||
/* new features to be added
|
||||
|
||||
*** reductions by single productions ( by request )
|
||||
*** follow sets for start symbol
|
||||
*** option to only do slr(1)
|
||||
*** easily changed array names on output
|
||||
*** allocate core, rather than predefined
|
||||
*** input controlled by a grammar
|
||||
*** support multiple choices for conflicts
|
||||
*** better conflict diagnostics
|
||||
*/
|
||||
|
||||
|
||||
|
||||
main(argc,argv) int argc; char *argv[]; {
|
||||
auto int n;
|
||||
|
||||
whereami();
|
||||
setup(argc,argv); /* initialize and read productions */
|
||||
tbitset = (nterms+16)/16;
|
||||
cpres(); /* make table of which productions yield a given nonterminal */
|
||||
cempty(); /* make a table of which nonterminals can match the empty string */
|
||||
cpfir(); /* make a table of e free first lists */
|
||||
stagen(); /* generate the states */
|
||||
output(); /* write the states and the tables */
|
||||
go2out();
|
||||
summary();
|
||||
windup();
|
||||
}
|
||||
|
||||
whereami(){ /* sets the variable machine to UNIX, GCOS, or IBM */
|
||||
|
||||
int i;
|
||||
|
||||
i = 1;
|
||||
i = i << 30;
|
||||
if( i == 0 ) {
|
||||
machine = UNIX;
|
||||
return;
|
||||
}
|
||||
i = i << 4;
|
||||
if( i == 0 ){
|
||||
machine = IBM;
|
||||
return;
|
||||
}
|
||||
machine = GCOS;
|
||||
}
|
||||
|
||||
windup(){
|
||||
/* no errors, do the optimization if appropriate */
|
||||
char *cp;
|
||||
int i;
|
||||
|
||||
cflush(1);
|
||||
if( !oflag ) cexit(0);
|
||||
|
||||
for( i=3; i<10; ++i ) cclose(i);
|
||||
switch( machine ){
|
||||
|
||||
case GCOS:
|
||||
if( rflag ){
|
||||
if( foutput<0 ) system( "./yopt -r" );
|
||||
else system( "./yopt -rv" );
|
||||
}
|
||||
else {
|
||||
if( foutput<0 ) system( "./yopt" );
|
||||
else system( "./yopt -v" );
|
||||
}
|
||||
cexit(0); /* terminate */
|
||||
|
||||
case UNIX:
|
||||
cp = "/usr/yacc/yopti";
|
||||
if( rflag ) execl( cp, cp, (foutput<0)?"-r":"-rv", 0 );
|
||||
else if( foutput<0 ) execl( cp, cp, 0 );
|
||||
else execl( cp, cp, "-v", 0 );
|
||||
error( "optimization execl call fails" );
|
||||
|
||||
case IBM:
|
||||
if( rflag ){
|
||||
if( foutput<0 ) system( "MH2019.yaccopt -r" );
|
||||
else system( "MH2019.yaccopt -rv" );
|
||||
}
|
||||
else {
|
||||
if( foutput<0 ) system( "MH2019.yaccopt" );
|
||||
else system( "MH2019.yaccopt -v" );
|
||||
}
|
||||
cexit(0);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
settty()
|
||||
/* sets the output file to y.output */
|
||||
{
|
||||
cflush( foutput ); /* a bit of a cheat */
|
||||
cout = foutput;
|
||||
}
|
||||
|
||||
settab(){ /* sets the output file to y.tab.c */
|
||||
|
||||
cflush( ftable );
|
||||
cout = ftable;
|
||||
}
|
||||
|
||||
char *chcopy( p, q ) char *p, *q; {
|
||||
/* copies string q into p, returning next free char ptr */
|
||||
while( *p = *q++ ) ++p;
|
||||
return( p );
|
||||
}
|
||||
|
||||
char *writem(pp) struct item *pp; { /* creates output string for item pointed to by pp */
|
||||
int i,*p;
|
||||
static char sarr[100];
|
||||
char *q;
|
||||
|
||||
for( p=pp->pitem; *p>0 ; ++p ) ;
|
||||
p = prdptr[-*p];
|
||||
q = chcopy( sarr, nontrst[*p-NTBASE].name );
|
||||
q = chcopy( q, " : " );
|
||||
|
||||
for(;;){
|
||||
*q++ = ++p==(pp->pitem) ? '_' : ' ';
|
||||
if((i = *p) <= 0) break;
|
||||
q = chcopy( q, symnam(i) );
|
||||
}
|
||||
|
||||
*q = '\0' ;
|
||||
return( sarr );
|
||||
}
|
||||
|
||||
char *symnam(i){ /* return a pointer to the name of symbol i */
|
||||
char *cp;
|
||||
|
||||
cp = (i>=NTBASE) ? nontrst[i-NTBASE].name : trmset[i].name ;
|
||||
if( *cp == ' ' ) ++cp;
|
||||
return( cp );
|
||||
}
|
||||
|
||||
summary(){ /* output the summary on the tty */
|
||||
|
||||
int i, s, *pn;
|
||||
|
||||
|
||||
if( !rflag ){
|
||||
settab();
|
||||
printf("\nint nterms %d;",nterms);
|
||||
printf("\nint nnonter %d;", nnonter);
|
||||
printf("\nint nstate %d;", nstate);
|
||||
printf("\nchar *yysterm[] {");
|
||||
for (i=1;i<=nterms;i++) if( trmset[i].value >= 0400 ) printf("\n\"%s\",",symnam(i));
|
||||
printf( "\n0 };\n" );
|
||||
printf("\nchar *yysnter[] {");
|
||||
for (i=0;i<nnonter;i++) printf("\n\"%s\",",nontrst[i].name);
|
||||
printf("\n\"%s\" };\n",nontrst[nnonter].name);
|
||||
}
|
||||
|
||||
settty();
|
||||
printf("\n%d/%d terminals, %d/%d nonterminals\n", nterms, tlim,
|
||||
nnonter, ntlim );
|
||||
printf("%d/%d grammar rules, %d/%d states\n", nprod, prdlim, nstate, stsize );
|
||||
printf("%d shift/reduce, %d reduce/reduce conflicts reported\n", zzsrconf, zzrrconf );
|
||||
pn = pstate[nstate+1];
|
||||
printf("%d/%d working sets used\n", zzcwset, wssize );
|
||||
printf("memory: states,etc. %d/%d, parser %d/%d\n", pn-mem0, memsiz,
|
||||
memact, actsiz );
|
||||
printf("%d/%d distinct lookahead sets\n", nlset, lsetsz );
|
||||
printf("%d extra closures\n", zzclose - 2*nstate );
|
||||
printf("%d action entries\n", zzacent );
|
||||
printf("%d action entries saved through merging %d states\n",zzacsave,zznsave);
|
||||
printf("%d goto entries\n", zzgoent );
|
||||
printf("%d entries saved by goto default\n", zzgobest );
|
||||
if( zzsrconf!=0 || zzrrconf!=0 ){
|
||||
cflush( errfileno );
|
||||
cout = errfileno;
|
||||
printf("\nconflicts: ");
|
||||
if( zzsrconf )printf( "%d shift/reduce" , zzsrconf );
|
||||
if( zzsrconf && zzrrconf )printf( ", " );
|
||||
if( zzrrconf )printf( "%d reduce/reduce" , zzrrconf );
|
||||
printf( "\n" );
|
||||
}
|
||||
}
|
||||
|
||||
error(s,a1){ /* write out error comment */
|
||||
|
||||
int c;
|
||||
++nerrors;
|
||||
cflush( errfileno );
|
||||
cout = errfileno; /* set output to tty */
|
||||
printf("\n fatal error: ");
|
||||
printf(s,a1);
|
||||
printf(", line %d\n", lineno );
|
||||
if( !fatfl ) return;
|
||||
summary();
|
||||
cexit(1);
|
||||
}
|
||||
|
||||
arrset(s) char s[]; {
|
||||
printf("\nint %s[] {0", s );
|
||||
arrndx = 1;
|
||||
}
|
||||
|
||||
arrval(n){
|
||||
printf(",%d",n);
|
||||
if( (++arrndx%10) == 0 ) printf("\n");
|
||||
}
|
||||
|
||||
arrdone(){
|
||||
printf(",-1};\n");
|
||||
}
|
||||
|
||||
copy(v) char *v; { /* copy ctokn to v */
|
||||
char *p;
|
||||
|
||||
p=ctokn;
|
||||
while( *v++ = *p++ );
|
||||
}
|
||||
|
||||
compare(v) char *v; { /* compare ctokn with v */
|
||||
char *p;
|
||||
|
||||
for( p=ctokn; ; ++p ){
|
||||
if( *p != *v++ ) return( 0 );
|
||||
if( *p == 0 ) return(1);
|
||||
}
|
||||
}
|
||||
|
||||
int *yalloc(n){ /* allocate n+1 words from vector mem */
|
||||
int *omem;
|
||||
omem = mem;
|
||||
mem =+ n+1;
|
||||
if(mem-mem0 >= memsiz) error("memory overflow");
|
||||
return(omem);
|
||||
}
|
||||
|
||||
aryfil( v, n, c ) int *v,n,c; { /* set elements 0 through n-1 to c */
|
||||
int i;
|
||||
for( i=0; i<n; ++i ) v[i] = c;
|
||||
}
|
||||
|
||||
union( a, b, c ) int *a, *b, *c; {
|
||||
/* set a to the union of b and c */
|
||||
/* a may equal b */
|
||||
/* return 1 if c is not a subset of b, 0 otherwise */
|
||||
|
||||
_REGISTER int i, x, sub;
|
||||
|
||||
sub = 0;
|
||||
for( i=0; i<tbitset; ++i ){
|
||||
x = b[i] | c[i];
|
||||
if( x != b[i] ) sub=1;
|
||||
a[i] = x;
|
||||
}
|
||||
return( sub );
|
||||
}
|
||||
|
||||
prlook( pp ) int *pp;{
|
||||
int j;
|
||||
pp = pp->lset;
|
||||
if( pp == 0 ) printf("\tNULL");
|
||||
else {
|
||||
printf(" { " );
|
||||
for( j=1; j<=nterms; ++j ){
|
||||
if( (pp[j>>4]>>(j&017) )&01 != 0 ) printf( "%s ", symnam(j) );
|
||||
}
|
||||
printf( "}" );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,533 @@
|
||||
# include "dextern"
|
||||
# define IDENTIFIER 257
|
||||
# define MARK 258
|
||||
# define TERM 259
|
||||
# define LEFT 260
|
||||
# define BINARY 261
|
||||
# define RIGHT 262
|
||||
# define PREC 263
|
||||
# define LCURLY 264
|
||||
# define C_IDENTIFIER 265 /* name followed by colon */
|
||||
# define NUMBER 266
|
||||
|
||||
setup(argc,argv) int argc; char *argv[];
|
||||
{ int i,j,lev,t;
|
||||
int c;
|
||||
|
||||
foutput = -2;
|
||||
i = 1;
|
||||
while( argc >= 2 && argv[1][0] == '-' ) {
|
||||
while( *++(argv[1]) ){
|
||||
switch( *argv[1] ){
|
||||
case 'v':
|
||||
case 'V':
|
||||
foutput = copen("y.output", 'w' );
|
||||
if( foutput < 0 ) error( "cannot open y.output");
|
||||
continue;
|
||||
case 'o':
|
||||
case 'O':
|
||||
oflag = 1;
|
||||
continue;
|
||||
case 'r':
|
||||
case 'R':
|
||||
oflag = 1;
|
||||
rflag = 1;
|
||||
continue;
|
||||
default: error( "illegal option: %c", *argv[1]);
|
||||
}
|
||||
}
|
||||
argv++;
|
||||
argc--;
|
||||
}
|
||||
|
||||
ftable = copen( oflag ? "yacc.tmp" : "y.tab.c" , 'w' );
|
||||
if( ftable<0 ) error( "cannot open table file" );
|
||||
if( argc > 1 ) cin = copen( argv[1], 'r' );
|
||||
if( cin < 0 ) error( "cannot open input" );
|
||||
settab();
|
||||
printf("#\n");
|
||||
ctokn = "$end";
|
||||
defin(0); /* eof */
|
||||
extval = 0400; /* beginning of assigned values */
|
||||
ctokn = "error";
|
||||
defin(0);
|
||||
ctokn = "$accept";
|
||||
defin(1);
|
||||
mem=mem0;
|
||||
cnamp = cnames;
|
||||
lev=0;
|
||||
i=0;
|
||||
|
||||
while( t = gettok() ){
|
||||
switch( t ){
|
||||
case IDENTIFIER: j = chfind(0);
|
||||
trmlev[j] = lev;
|
||||
continue;
|
||||
case ',':
|
||||
case ';': continue;
|
||||
case TERM: lev=0; continue;
|
||||
case LEFT: lev=(++i<<3)|01; continue;
|
||||
case BINARY: lev=(++i<<3)|02; continue;
|
||||
case RIGHT: lev=(++i<<3)|03; continue;
|
||||
case MARK:
|
||||
defout();
|
||||
if( rflag ){ /* RATFOR */
|
||||
printf( "define yyerrok yyerrf = 0\n" );
|
||||
printf( "define yyclearin yychar = -1\n" );
|
||||
printf( "subroutine yyactr(yyprdn)\n");
|
||||
printf( "common/yycomn/yylval,yyval,yypv,yyvalv(150)\n" );
|
||||
printf( "common/yylcom/yychar,yyerrf,yydebu\n" );
|
||||
printf( "integer yychar, yyerrf, yydebu\n" );
|
||||
printf( "integer yyprdn,yyval,yylval,yypv,yyvalv\n" );
|
||||
}
|
||||
else {
|
||||
printf( "#define yyclearin yychar = -1\n" );
|
||||
printf( "#define yyerrok yyerrflag = 0\n" );
|
||||
printf( "extern int yychar, yyerrflag;\n" );
|
||||
printf("\nint yyval 0;\nint *yypv;\nint yylval 0;");
|
||||
printf("\nyyactr(__np__){\n");
|
||||
}
|
||||
break;
|
||||
case LCURLY: defout();
|
||||
cpycode();
|
||||
continue;
|
||||
case NUMBER:
|
||||
trmset[j].value = numbval;
|
||||
if( j < ndefout && j>2 )
|
||||
error("please define type # of %s earlier", trmset[j].name );
|
||||
continue;
|
||||
default: error("bad precedence syntax, input %d", t );
|
||||
}
|
||||
break;
|
||||
}
|
||||
prdptr[0]=mem;
|
||||
/* added production */
|
||||
*mem++ = NTBASE;
|
||||
*mem++ = NTBASE+1;
|
||||
*mem++ = 1;
|
||||
*mem++ = 0;
|
||||
prdptr[1]=mem;
|
||||
i=0;
|
||||
|
||||
/* i is 0 when a rule can begin, 1 otherwise */
|
||||
|
||||
for(;;) switch( t=gettok() ) {
|
||||
case C_IDENTIFIER: if( mem == prdptr[1] ) { /* first time */
|
||||
if( rflag ){
|
||||
printf( "goto 1000\n" );
|
||||
}
|
||||
else printf("\nswitch(__np__){\n");
|
||||
}
|
||||
if( i != 0 ) error( "previous rule not terminated" );
|
||||
*mem = chfind(1);
|
||||
if( *mem < NTBASE )error( "token illegal on lhs of grammar rule" );
|
||||
i=1;
|
||||
++mem;
|
||||
continue;
|
||||
case IDENTIFIER:
|
||||
*mem=chfind(1);
|
||||
if(*mem < NTBASE)levprd[nprod]=trmlev[*mem];
|
||||
mem++;
|
||||
if(i==0) error("missing :");
|
||||
continue;
|
||||
case '=': levprd[nprod] =| 04;
|
||||
if( i==0 ) error("semicolon preceeds action");
|
||||
printf( rflag?"\n%d ":"\ncase %d:", nprod );
|
||||
cpyact();
|
||||
printf( rflag ? " return" : " break;" );
|
||||
case '|':
|
||||
case ';': if(i){
|
||||
*mem++ = -nprod;
|
||||
prdptr[++nprod] = mem;
|
||||
levprd[nprod]=0;
|
||||
i=0;}
|
||||
if (t=='|'){i=1;*mem++ = *prdptr[nprod-1];}
|
||||
continue;
|
||||
case 0: /* End Of File */
|
||||
case MARK: if( i != 0 ) error( "rule not terminated before %%%% or EOF" );
|
||||
settab();
|
||||
finact();
|
||||
/* copy the programs which follow the rules */
|
||||
if( t == MARK ){
|
||||
while (c=getchar()) putchar(c);
|
||||
}
|
||||
return;
|
||||
case PREC:
|
||||
if( i==0 ) error( "%%prec must appear inside rule" );
|
||||
if( gettok()!=IDENTIFIER)error("illegal %%prec syntax" );
|
||||
j=chfind(2);
|
||||
if(j>=NTBASE)error("nonterminal %s illegal after %%prec", nontrst[j-NTBASE].name);
|
||||
levprd[nprod]=trmlev[j];
|
||||
continue;
|
||||
case LCURLY:
|
||||
if( i!=0 ) error( "%%{ appears within a rule" );
|
||||
cpycode();
|
||||
continue;
|
||||
default: error( "syntax error, input %d", t );
|
||||
}
|
||||
}
|
||||
|
||||
finact(){
|
||||
/* finish action routine */
|
||||
register i;
|
||||
|
||||
if( rflag ){
|
||||
|
||||
printf( "\n1000 goto(" );
|
||||
for( i=1; i<nprod; ++i ){
|
||||
printf( "%d,", (levprd[i]&04)==0?999:i );
|
||||
}
|
||||
printf( "999),yyprdn\n" );
|
||||
printf( "999 return\nend\n" );
|
||||
printf( "define YYERRCODE %d\n", trmset[2].value );
|
||||
}
|
||||
else {
|
||||
printf( "\n}\n}\n" );
|
||||
printf( "int yyerrval %d;\n", trmset[2].value );
|
||||
}
|
||||
}
|
||||
defin(t) {
|
||||
/* define ctokn to be a terminal if t=0
|
||||
or a nonterminal if t=1 */
|
||||
char *cp,*p;
|
||||
int c;
|
||||
|
||||
|
||||
if (t) {
|
||||
if( ++nnonter >= ntlim ) error("too many nonterminals, limit %d",ntlim);
|
||||
nontrst[nnonter].name = ctokn;
|
||||
return( NTBASE + nnonter );
|
||||
}
|
||||
else {
|
||||
if( ++nterms >= tlim ) error("too many terminals, limit %d",tlim );
|
||||
trmset[nterms].name = ctokn;
|
||||
if( ctokn[0]==' ' && ctokn[2]=='\0' ) /* single character literal */
|
||||
trmset[nterms].value = ctokn[1];
|
||||
else if ( ctokn[0]==' ' && ctokn[1]=='\\' ) { /* escape sequence */
|
||||
if( ctokn[3] == '\0' ){ /* single character escape sequence */
|
||||
switch ( ctokn[2] ){
|
||||
/* character which is escaped */
|
||||
case 'n': trmset[nterms].value = '\n'; break;
|
||||
case 'r': trmset[nterms].value = '\r'; break;
|
||||
case 'b': trmset[nterms].value = '\b'; break;
|
||||
case 't': trmset[nterms].value = '\t'; break;
|
||||
case '\'': trmset[nterms].value = '\''; break;
|
||||
case '"': trmset[nterms].value = '"'; break;
|
||||
case '\\': trmset[nterms].value = '\\'; break;
|
||||
default: error( "invalid escape" );
|
||||
}
|
||||
}
|
||||
else if( ctokn[2] <= '7' && ctokn[2]>='0' ){ /* \nnn sequence */
|
||||
if( ctokn[3]<'0' || ctokn[3] > '7' || ctokn[4]<'0' ||
|
||||
ctokn[4]>'7' || ctokn[5] != '\0' ) error("illegal \\nnn construction" );
|
||||
trmset[nterms].value = 64*(ctokn[2]-'0')+8*(ctokn[3]-'0')+ctokn[4]-'0';
|
||||
if( trmset[nterms].value == 0 ) error( "'\\000' is illegal" );
|
||||
}
|
||||
}
|
||||
else {
|
||||
trmset[nterms].value = extval++;
|
||||
|
||||
}
|
||||
trmlev[nterms] = 0;
|
||||
return( nterms );
|
||||
}
|
||||
}
|
||||
|
||||
defout(){ /* write out the defines (at the end of the declaration section) */
|
||||
|
||||
_REGISTER int i, c;
|
||||
_REGISTER char *cp;
|
||||
|
||||
for( i=ndefout; i<=nterms; ++i ){
|
||||
|
||||
cp = trmset[i].name;
|
||||
if( *cp == ' ' ) ++cp; /* literals */
|
||||
|
||||
for( ; (c= *cp)!='\0'; ++cp ){
|
||||
|
||||
if( c>='a' && c<='z' ||
|
||||
c>='A' && c<='Z' ||
|
||||
c>='0' && c<='9' ||
|
||||
c=='_' ) ; /* VOID */
|
||||
else goto nodef;
|
||||
}
|
||||
|
||||
/* define it */
|
||||
|
||||
printf( "%c define %s %d\n", rflag?' ':'#', trmset[i].name, trmset[i].value );
|
||||
|
||||
nodef: ;
|
||||
}
|
||||
|
||||
ndefout = nterms+1;
|
||||
|
||||
}
|
||||
|
||||
chstash( c ){
|
||||
/* put character away into cnames */
|
||||
if( cnamp >= &cnames[cnamsz] ) error("too many characters in id's and literals" );
|
||||
else *cnamp++ = c;
|
||||
}
|
||||
|
||||
int gettok() {
|
||||
int j, base;
|
||||
static int peekline; /* number of '\n' seen in lookahead */
|
||||
auto int c, match, reserve;
|
||||
|
||||
begin:
|
||||
reserve = 0;
|
||||
if( peekc>=0 ) {
|
||||
c = peekc;
|
||||
lineno =+ peekline;
|
||||
peekc = -1;
|
||||
peekline = 0;
|
||||
}
|
||||
else c = getchar();
|
||||
while( c==' ' || c=='\n' || c=='\t' ){
|
||||
if( c == '\n' ) ++lineno;
|
||||
c=getchar();
|
||||
}
|
||||
if (c=='/')
|
||||
{if (getchar()!='*')error("illegal /");
|
||||
c=getchar();
|
||||
while(c) {
|
||||
if( c == '\n' ) ++lineno;
|
||||
if (c=='*')
|
||||
{if((c=getchar())=='/')break;}
|
||||
else c=getchar();}
|
||||
if (!c) return(0);
|
||||
goto begin;}
|
||||
j=0;
|
||||
switch(c){
|
||||
case '"':
|
||||
case '\'': match = c;
|
||||
ctokn = cnamp;
|
||||
chstash( ' ' );
|
||||
while(1){
|
||||
c = getchar();
|
||||
if( c == '\n' || c == '\0' )
|
||||
error("illegal or missing ' or \"");
|
||||
if( c == '\\' ){
|
||||
c = getchar();
|
||||
chstash( '\\' );
|
||||
}
|
||||
else if( c == match ) break;
|
||||
chstash( c );
|
||||
}
|
||||
break;
|
||||
case '%':
|
||||
case '\\': switch(c=getchar())
|
||||
{case '0': return(TERM);
|
||||
case '<': return(LEFT);
|
||||
case '2': return(BINARY);
|
||||
case '>': return(RIGHT);
|
||||
case '%':
|
||||
case '\\': return(MARK);
|
||||
case '=': return(PREC);
|
||||
case '{': return(LCURLY);
|
||||
default: reserve = 1;
|
||||
}
|
||||
default: if( c >= '0' && c <= '9' ){ /* number */
|
||||
numbval = c-'0' ;
|
||||
base = (c=='0') ? 8 : 10 ;
|
||||
for( c=getchar(); c>='0' && c<='9'; c=getchar() ){
|
||||
numbval = numbval*base + c - '0';
|
||||
}
|
||||
peekc = c;
|
||||
return(NUMBER);
|
||||
}
|
||||
else if( (c>='a'&&c<='z')||(c>='A'&&c<='Z')||c=='_'||c=='.'||c=='$'){
|
||||
ctokn = cnamp;
|
||||
while( (c>='a'&&c<='z') ||
|
||||
(c>='A'&&c<='Z') ||
|
||||
(c>='0'&&c<='9') ||
|
||||
c=='_' || c=='.' || c=='$' ) {
|
||||
chstash( c );
|
||||
if( peekc>=0 ) { c = peekc; peekc = -1; }
|
||||
else c = getchar();
|
||||
}
|
||||
}
|
||||
else return(c);
|
||||
|
||||
peekc=c;
|
||||
}
|
||||
chstash( '\0' );
|
||||
|
||||
if( reserve ){ /* find a reserved word */
|
||||
if( compare("term")) return( TERM );
|
||||
if( compare("TERM")) return( TERM );
|
||||
if( compare("token")) return( TERM );
|
||||
if( compare("TOKEN")) return( TERM );
|
||||
if( compare("left")) return( LEFT );
|
||||
if( compare("LEFT")) return( LEFT );
|
||||
if( compare("nonassoc")) return( BINARY );
|
||||
if( compare("NONASSOC")) return( BINARY );
|
||||
if( compare("binary")) return( BINARY );
|
||||
if( compare("BINARY")) return( BINARY );
|
||||
if( compare("right")) return( RIGHT );
|
||||
if( compare("RIGHT")) return( RIGHT );
|
||||
if( compare("prec")) return( PREC );
|
||||
if( compare("PREC")) return( PREC );
|
||||
error("invalid escape, or illegal reserved word: %s", ctokn );
|
||||
}
|
||||
|
||||
/* look ahead to distinguish IDENTIFIER from C_IDENTIFIER */
|
||||
|
||||
look:
|
||||
while( peekc==' ' || peekc=='\t' || peekc == '\n' ) {
|
||||
if( peekc == '\n' ) ++peekline;
|
||||
peekc = getchar();
|
||||
}
|
||||
|
||||
if( peekc != ':' ) return( IDENTIFIER );
|
||||
peekc = -1;
|
||||
lineno =+ peekline;
|
||||
peekline = 0;
|
||||
return( C_IDENTIFIER );
|
||||
}
|
||||
chfind(t)
|
||||
|
||||
{ int i,j;
|
||||
|
||||
if (ctokn[0]==' ')t=0;
|
||||
for(i=1;i<=nterms;i++)
|
||||
if(compare(trmset[i].name)){
|
||||
cnamp = ctokn;
|
||||
return( i );
|
||||
}
|
||||
for(i=1;i<=nnonter;i++)
|
||||
if(compare(nontrst[i].name)) {
|
||||
cnamp = ctokn;
|
||||
return( i+NTBASE );
|
||||
}
|
||||
/* cannot find name */
|
||||
if( t>1 && ctokn[0] != ' ' )
|
||||
error( "%s should have been defined earlier", ctokn );
|
||||
return( defin( t ) );
|
||||
}
|
||||
|
||||
cpycode(){ /* copies code between \{ and \} */
|
||||
|
||||
int c;
|
||||
c = getchar();
|
||||
if( c == '\n' ) {
|
||||
c = getchar();
|
||||
lineno++;
|
||||
}
|
||||
while( c ){
|
||||
if( c=='\\' )
|
||||
if( (c=getchar()) == '}' ) return;
|
||||
else putchar('\\');
|
||||
if( c=='%' )
|
||||
if( (c=getchar()) == '}' ) return;
|
||||
else putchar('%');
|
||||
putchar( c );
|
||||
if( c == '\n' ) ++lineno;
|
||||
c = getchar();
|
||||
}
|
||||
error("eof before %%}");
|
||||
}
|
||||
|
||||
cpyact(){ /* copy C action to the next ; or closing } */
|
||||
int brac, c, match, *i, j, s;
|
||||
|
||||
brac = 0;
|
||||
|
||||
loop:
|
||||
c = getchar();
|
||||
swt:
|
||||
switch( c ){
|
||||
|
||||
case ';':
|
||||
if( brac == 0 ){
|
||||
putchar( c );
|
||||
return;
|
||||
}
|
||||
goto lcopy;
|
||||
|
||||
case '{':
|
||||
brac++;
|
||||
goto lcopy;
|
||||
|
||||
case '$':
|
||||
s = 1;
|
||||
c = getchar();
|
||||
if( c == '$' ){
|
||||
printf("yyval");
|
||||
goto loop;
|
||||
}
|
||||
if( c == '-' ){
|
||||
s = -s;
|
||||
c = getchar();
|
||||
}
|
||||
if( c>='0' && c <= '9' ){
|
||||
j=0;
|
||||
while( c>='0' && c<= '9' ){
|
||||
j= j*10+c-'0';
|
||||
c = getchar();
|
||||
}
|
||||
if( rflag ) printf( "yyvalv(yypv%c%d)", s==1?'+':'-', j );
|
||||
else printf("yypv[%d]", s*j );
|
||||
goto swt;
|
||||
}
|
||||
putchar( '$' );
|
||||
if( s<0 ) putchar('-');
|
||||
goto swt;
|
||||
|
||||
case '}':
|
||||
brac--;
|
||||
if( brac == 0 ){
|
||||
putchar( c );
|
||||
return;
|
||||
}
|
||||
goto lcopy;
|
||||
|
||||
case '/': /* look for comments */
|
||||
putchar( c );
|
||||
c = getchar();
|
||||
if( c != '*' ) goto swt;
|
||||
|
||||
/* it really is a comment */
|
||||
|
||||
putchar( c );
|
||||
while( c=getchar() ){
|
||||
if( c=='*' ){
|
||||
putchar( c );
|
||||
if( (c=getchar()) == '/' ) goto lcopy;
|
||||
}
|
||||
putchar( c );
|
||||
}
|
||||
error( "EOF inside comment" );
|
||||
|
||||
case '\'': /* character constant */
|
||||
match = '\'';
|
||||
goto string;
|
||||
|
||||
case '"': /* character string */
|
||||
match = '"';
|
||||
|
||||
string:
|
||||
|
||||
putchar( c );
|
||||
while( c=getchar() ){
|
||||
|
||||
if( c=='\\' ){
|
||||
putchar( c );
|
||||
c=getchar();
|
||||
}
|
||||
else if( c==match ) goto lcopy;
|
||||
putchar( c );
|
||||
}
|
||||
error( "EOF in string or character constant" );
|
||||
|
||||
case '\0':
|
||||
error("action does not terminate");
|
||||
case '\n': ++lineno;
|
||||
goto lcopy;
|
||||
|
||||
}
|
||||
|
||||
lcopy:
|
||||
putchar( c );
|
||||
goto loop;
|
||||
}
|
||||
@@ -0,0 +1,378 @@
|
||||
# include "dextern"
|
||||
|
||||
cpres(){ /* conpute an array with the beginnings of productions yielding given nonterminals
|
||||
The array pres points to these lists */
|
||||
int i,j,c;
|
||||
pres = yalloc(nnonter+1);
|
||||
for(i=0;i<=nnonter;i++){
|
||||
c = i+NTBASE;
|
||||
pres[i] = mem;
|
||||
fatfl = 0; /* make undefined symbols nonfatal */
|
||||
for(j=0;j<nprod;j++)
|
||||
if (*prdptr[j] == c) *mem++ = prdptr[j]+1;
|
||||
if(pres[i] == mem){
|
||||
error("nonterminal %s not defined!", nontrst[i].name);
|
||||
}
|
||||
}
|
||||
pres[i] = mem;
|
||||
fatfl = 1;
|
||||
if( nerrors ){
|
||||
summary();
|
||||
cexit(1);
|
||||
}
|
||||
}
|
||||
|
||||
int indebug 0;
|
||||
cpfir() {
|
||||
/* compute an array with the first of nonterminals */
|
||||
int i, ch, **s, **t, changes, *p;
|
||||
|
||||
pfirst = yalloc(nnonter+1);
|
||||
for (i=0;i<=nnonter;i++) {
|
||||
aryfil( wsets[i].ws, tbitset, 0 );
|
||||
t = pres[i+1];
|
||||
for( s=pres[i]; s<t; ++s ){ /* initially fill the sets */
|
||||
for( p = *s; (ch = *p) > 0 ; ++p ) {
|
||||
if( ch < NTBASE ) {
|
||||
wsets[i].ws[ch>>4] =| (1 << (ch&017) );
|
||||
break;
|
||||
}
|
||||
else if( !pempty[ch-NTBASE] ) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* now, reflect transitivity */
|
||||
|
||||
changes = 1;
|
||||
while( changes ){
|
||||
changes = 0;
|
||||
for( i=0; i<=nnonter; ++i ){
|
||||
t = pres[i+1];
|
||||
for( s=pres[i]; s<t; ++s ){
|
||||
for( p = *s; ( ch = (*p-NTBASE) ) >= 0; ++p ) {
|
||||
changes =| union( wsets[i].ws, wsets[i].ws, wsets[ch].ws );
|
||||
if( !pempty[ch] ) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for( i=0; i<=nnonter; i++ ) pfirst[i] = flset( wsets[i].ws );
|
||||
if( !indebug ) return;
|
||||
settty();
|
||||
for( i=0; i<=nnonter; i++ ){
|
||||
printf( "\n%s: ", nontrst[i].name );
|
||||
prlook( pfirst[i] );
|
||||
printf( " %d\n", pempty[i] );
|
||||
}
|
||||
}
|
||||
|
||||
state(c){ /* sorts last state,and sees if it equals earlier ones. returns state number */
|
||||
int s,size1,size2;
|
||||
_REGISTER i;
|
||||
struct item *p1, *p2, *k, *l, *q1, *q2;
|
||||
p1 = pstate[nstate];
|
||||
p2 = pstate[nstate+1];
|
||||
if(p1==p2) return(0); /* null state */
|
||||
/* sort the items */
|
||||
for(k=p2-1;k>p1;k--) { /* make k the biggest */
|
||||
for(l=k-1;l>=p1;--l)if( l->pitem > k->pitem ){
|
||||
s = k->pitem;
|
||||
k->pitem = l->pitem;
|
||||
l->pitem = s;
|
||||
s = k->look;
|
||||
k->look = l->look;
|
||||
l->look = s;
|
||||
}
|
||||
}
|
||||
size1 = p2 - p1; /* size of state */
|
||||
|
||||
for( i= (c>=NTBASE)?ntstates[c-NTBASE]:tstates[c]; i != 0; i = mstates[i] ) {
|
||||
/* get ith state */
|
||||
q1 = pstate[i];
|
||||
q2 = pstate[i+1];
|
||||
size2 = q2 - q1;
|
||||
if (size1 != size2) continue;
|
||||
k=p1;
|
||||
for(l=q1;l<q2;l++) {
|
||||
if( l->pitem != k->pitem ) break;
|
||||
++k;
|
||||
}
|
||||
if (l != q2) continue;
|
||||
/* found it */
|
||||
pstate[nstate+1] = pstate[nstate]; /* delete last state */
|
||||
/* fix up lookaheads */
|
||||
k=p1;
|
||||
for( l=q1; l<q2; ++l ){
|
||||
if( union( clset.lset, l->look->lset, k->look->lset ) ) {
|
||||
tystate[i] = 1;
|
||||
/* register the new set */
|
||||
l->look = flset( &clset );
|
||||
}
|
||||
++k;
|
||||
}
|
||||
return (i);
|
||||
}
|
||||
/* state is new */
|
||||
pstate[nstate+2] = p2;
|
||||
if(nstate+1 >= stsize) error("too many states");
|
||||
if( c >= NTBASE ){
|
||||
mstates[ nstate ] = ntstates[ c-NTBASE ];
|
||||
ntstates[ c-NTBASE ] = nstate;
|
||||
}
|
||||
else {
|
||||
mstates[ nstate ] = tstates[ c ];
|
||||
tstates[ c ] = nstate;
|
||||
}
|
||||
tystate[nstate]=1;
|
||||
return(nstate++);
|
||||
}
|
||||
|
||||
int pidebug 0; /* debugging flag for putitem */
|
||||
putitem ( ptr, lptr ) int *ptr; struct looksets *lptr;{
|
||||
int *jip, k;
|
||||
struct item *i, *j;
|
||||
|
||||
if( pidebug ) {
|
||||
settty();
|
||||
printf("putitem(%s), state %d\n", writem(&ptr), nstate );
|
||||
}
|
||||
/* see if it's there */
|
||||
j = pstate[nstate+1];
|
||||
for( i=pstate[nstate]; i<j; ++i )
|
||||
if(i->pitem == ptr) {
|
||||
error("yacc error--duplicate item");
|
||||
}
|
||||
/* not there */
|
||||
j->pitem = ptr;
|
||||
j->look = flset( lptr );
|
||||
pstate[nstate+1] = ++j;
|
||||
jip = j;
|
||||
if(jip-mem0 >= memsiz) error("out of state space");
|
||||
}
|
||||
|
||||
cempty(){ /* mark nonterminals which derive the empty string */
|
||||
|
||||
int i, *p;
|
||||
|
||||
/* set pempty to 0 */
|
||||
pempty = yalloc( nnonter );
|
||||
aryfil( pempty, nnonter+1, 0 );
|
||||
for( i=1; i<nprod; ++i ) /* loop over productions */
|
||||
if( prdptr[i][1] <= 0 ) /* i is empty production */
|
||||
pempty[ *prdptr[i]-NTBASE ] = 1;
|
||||
|
||||
/* now, all explicitly empty nonterminals marked with pempty = 1 */
|
||||
|
||||
/* loop as long as we keep finding nontrivial empty nonterminals */
|
||||
|
||||
again:
|
||||
for( i=1; i<nprod; ++i ){
|
||||
if( pempty[ *prdptr[i]-NTBASE ]==0 ){ /* not known to be empty */
|
||||
for( p=prdptr[i]+1; *p>=NTBASE && pempty[*p-NTBASE]!=0 ; ++p ) ;
|
||||
if( *p < 0 ){ /* we have a nontrivially empty nonterminal */
|
||||
pempty[*prdptr[i]-NTBASE] = 1;
|
||||
goto again; /* got one ... try for another */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int gsdebug 0;
|
||||
stagen(){ /* generate the states */
|
||||
|
||||
int i, j, k, c;
|
||||
|
||||
/* initialize */
|
||||
|
||||
nstate = 0;
|
||||
pstate[0] = pstate[1] = mem;
|
||||
aryfil( clset.lset, tbitset, 0 );
|
||||
putitem( prdptr[0]+1, &clset );
|
||||
tystate[0] = 1;
|
||||
nstate = 1;
|
||||
pstate[2] = pstate[1];
|
||||
|
||||
memact = 0;
|
||||
aryfil( amem, actsiz, 0 );
|
||||
|
||||
/* now, the main state generation loop */
|
||||
|
||||
more:
|
||||
for( i=0; i<nstate; ++i ){
|
||||
if( tystate[i] != 1 ) continue;
|
||||
tystate[i] = 0;
|
||||
aryfil( temp1, nterms+nnonter+1, 0 );
|
||||
/* take state i, close it, and do gotos */
|
||||
closure(i);
|
||||
for( j=0; j<cwset; ++j ){ /* generate gotos */
|
||||
if( wsets[j].flag ) continue;
|
||||
wsets[j].flag = 1;
|
||||
c = *(wsets[j].pitem);
|
||||
if( c <= 1 ) {
|
||||
if( pstate[i+1]-pstate[i] <= j ) tystate[i] = (tystate[i]==1)?1:2;
|
||||
continue;
|
||||
}
|
||||
/* do a goto on c */
|
||||
for( k=j; k<cwset; ++k ){
|
||||
if( c == *(wsets[k].pitem) ){ /* this item contributes to the goto */
|
||||
putitem( wsets[k].pitem + 1, wsets[k].ws );
|
||||
wsets[k].flag = 1;
|
||||
}
|
||||
}
|
||||
if( c < NTBASE ) temp1[c] = state(c);
|
||||
else temp1[c-NTBASE+nterms] = state(c);
|
||||
}
|
||||
if( gsdebug ){
|
||||
settty();
|
||||
printf( "%d: ", i );
|
||||
for( j=1; j<=nterms; ++j ){
|
||||
if( temp1[j] != 0 ) printf( "%s %d, ", symnam(j), temp1[j]);
|
||||
}
|
||||
for( j=1; j<=nnonter; ++j ){
|
||||
if( temp1[j+nterms] ) printf( "%s %d, ", nontrst[j].name, temp1[j+nterms] );
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
apstate[i] = apack( &temp1[0], nterms );
|
||||
indgo[i] = apack( &temp1[nterms+1], nnonter-1 ) - 1;
|
||||
goto more; /* we have done one goto; do some more */
|
||||
}
|
||||
/* no more to do... stop */
|
||||
}
|
||||
|
||||
int cldebug 0; /* debugging flag for closure */
|
||||
closure(i){ /* generate the closure of state i */
|
||||
|
||||
int c, ch, work;
|
||||
_REGISTER j, k;
|
||||
int *pi;
|
||||
int **s, **t;
|
||||
struct item *q;
|
||||
_REGISTER struct item *p;
|
||||
|
||||
++zzclose;
|
||||
|
||||
/* first, copy kernel of state i to wsets */
|
||||
|
||||
cwset = 0;
|
||||
q = pstate[i+1];
|
||||
for( p=pstate[i]; p<q; ++p ){
|
||||
wsets[cwset].pitem = p->pitem;
|
||||
wsets[cwset].flag = 1; /* this item must get closed */
|
||||
for( k=0; k<tbitset; ++k ) wsets[cwset].ws[k] = p->look->lset[k];
|
||||
++cwset;
|
||||
}
|
||||
|
||||
/* now, go through the loop, closing each item */
|
||||
|
||||
work = 1;
|
||||
while( work ){
|
||||
work = 0;
|
||||
for( j=0; j<cwset; ++j ){
|
||||
|
||||
if( wsets[j].flag == 0 ) continue;
|
||||
c = *(wsets[j].pitem); /* dot is before c */
|
||||
|
||||
if( c < NTBASE ){
|
||||
wsets[j].flag = 0;
|
||||
continue; /* only interesting case is where . is before nonterminal */
|
||||
}
|
||||
|
||||
/* compute the lookahead */
|
||||
aryfil( clset.lset, tbitset, 0 );
|
||||
|
||||
/* find items involving c */
|
||||
|
||||
for( k=j; k<cwset; ++k ){
|
||||
if( wsets[k].flag == 1 && *(pi=wsets[k].pitem) == c ){
|
||||
wsets[k].flag = 0;
|
||||
if( nolook ) continue;
|
||||
while( (ch= *++pi)>0 ){
|
||||
if( ch < NTBASE ){ /* terminal symbol */
|
||||
clset.lset[ch>>4] =| (1<<(ch&017));
|
||||
break;
|
||||
}
|
||||
/* nonterminal symbol */
|
||||
union( clset.lset, clset.lset, pfirst[ch-NTBASE] );
|
||||
if( !pempty[ch-NTBASE] ) break;
|
||||
}
|
||||
if( ch<=0 ) union( clset.lset, clset.lset, wsets[k].ws );
|
||||
}
|
||||
}
|
||||
|
||||
/* now loop over productions derived from c */
|
||||
|
||||
c =- NTBASE; /* c is now nonterminal number */
|
||||
|
||||
t = pres[c+1];
|
||||
for( s=pres[c]; s<t; ++s ){
|
||||
/* put these items into the closure */
|
||||
for( k=0; k<cwset; ++k ){ /* is the item there */
|
||||
if( wsets[k].pitem == *s ){ /* yes, it is there */
|
||||
if( nolook ) goto nexts;
|
||||
if( union( wsets[k].ws, wsets[k].ws, clset.lset ) ) wsets[k].flag = work = 1;
|
||||
goto nexts;
|
||||
}
|
||||
}
|
||||
|
||||
/* not there; make a new entry */
|
||||
if( cwset+1 >= wssize ) error( "working set overflow" );
|
||||
wsets[cwset].pitem = *s;
|
||||
wsets[cwset].flag = 1;
|
||||
if( nolook ){
|
||||
cwset++;
|
||||
goto nexts;
|
||||
}
|
||||
work = 1;
|
||||
for( k=0; k<tbitset; ++k ) wsets[cwset].ws[k] = clset.lset[k];
|
||||
cwset++;
|
||||
|
||||
nexts: ;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* have computed closure; flags are reset; return */
|
||||
|
||||
if( cwset > zzcwset ) zzcwset = cwset;
|
||||
if( !cldebug ) return;
|
||||
settty();
|
||||
printf("\nState %d, nolook = %d\n", i, nolook );
|
||||
for( j=0; j<cwset; ++j ){
|
||||
if( wsets[j].flag ) printf("flag set!\n");
|
||||
wsets[j].flag = 0;
|
||||
printf("\t%s", writem(&wsets[j].pitem));
|
||||
prlook( wsets[j].ws );
|
||||
printf( "\n" );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct looksets *flset( p )
|
||||
struct looksets *p;
|
||||
{
|
||||
/* decide if the lookahead set pointed to by p is known */
|
||||
/* return pointer to a perminent location for the set */
|
||||
|
||||
int j, *w;
|
||||
_REGISTER *u, *v, i;
|
||||
|
||||
for( i=0; i<nlset; ++i ){
|
||||
u = p->lset;
|
||||
v = lkst[i].lset;
|
||||
w = & v[tbitset];
|
||||
while( v<w) if( *u++ != *v++ ) goto more;
|
||||
/* we have matched */
|
||||
return( & lkst[i] );
|
||||
more: ;
|
||||
}
|
||||
/* add a new one */
|
||||
if( nlset+1 >= lsetsz )error("too many lookahead sets");
|
||||
for( j=0; j<tbitset; ++j ){
|
||||
lkst[nlset].lset[j] = p->lset[j];
|
||||
}
|
||||
return( & lkst[nlset++]);
|
||||
}
|
||||
@@ -0,0 +1,417 @@
|
||||
# include "dextern"
|
||||
|
||||
output(){ /* print the output for the states */
|
||||
|
||||
int i, j, k, c;
|
||||
|
||||
settab();
|
||||
arrset("yyact");
|
||||
|
||||
for( i=0; i<nstate; ++i ){ /* output the stuff for state i */
|
||||
nolook = (tystate[i]==0);
|
||||
closure(i);
|
||||
/* output actions */
|
||||
aryfil( temp1, nterms+1, 0 );
|
||||
for( j=0; j<cwset; ++j ){ /* look at the items */
|
||||
c = *( wsets[j].pitem );
|
||||
if( c>0 && c<NTBASE && temp1[c]==0 ) temp1[c] = go2(i,c);
|
||||
}
|
||||
|
||||
if( i == 1 ) temp1[1] = ACCEPTCODE;
|
||||
|
||||
/* now, we have the shifts; look at the reductions */
|
||||
|
||||
lastred = 0;
|
||||
for( j=0; j<cwset; ++j ){
|
||||
c = *( wsets[j].pitem );
|
||||
if( c<=0 ){ /* reduction */
|
||||
lastred = -c;
|
||||
for( k=1; k<=nterms; ++k ){
|
||||
if( ((wsets[j].ws[k>>4])&(1<<(k&017))) != 0 ) {
|
||||
if( temp1[k] == 0 ) temp1[k] = c;
|
||||
else if( temp1[k]<0 ){ /* reduce/reduce conflict */
|
||||
settty();
|
||||
printf("\n%d: reduce/reduce conflict (red'ns %d and %d ) on %s",
|
||||
i, -temp1[k], lastred, symnam(k) );
|
||||
if( -temp1[k] > lastred ) temp1[k] = -lastred;
|
||||
++zzrrconf;
|
||||
settab();
|
||||
}
|
||||
else { /* potential shift/reduce conflict */
|
||||
switch( precftn( lastred, k ) ) {
|
||||
|
||||
case 0: /* precedence does not apply */
|
||||
|
||||
settty();
|
||||
printf("\n%d: shift/reduce conflict (shift %d, red'n %d) on %s", i,
|
||||
temp1[k], lastred, symnam(k) );
|
||||
++zzsrconf;
|
||||
settab();
|
||||
break;
|
||||
|
||||
case 1: /* reduce */
|
||||
|
||||
temp1[k] = -lastred;
|
||||
break;
|
||||
|
||||
case 2: /* error, binary operator */
|
||||
|
||||
temp1[k] = ERRCODE;
|
||||
break;
|
||||
|
||||
case 3: /* shift ... leave the entry alone */
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
wract(i);
|
||||
}
|
||||
|
||||
settab();
|
||||
arrdone();
|
||||
|
||||
/* now, output the pointers to the action array */
|
||||
/* also output the info about reductions */
|
||||
prred();
|
||||
}
|
||||
|
||||
prred(){ /* print the information about the actions and the reductions */
|
||||
int index, i;
|
||||
|
||||
arrset("yypact");
|
||||
index = 1; /* position in the output table */
|
||||
|
||||
for( i=0; i<nstate; ++i ){
|
||||
if( tystate[i]>0 ){ /* the state is real */
|
||||
temp1[i] = index;
|
||||
arrval( index );
|
||||
index =+ tystate[i];
|
||||
}
|
||||
else {
|
||||
arrval( temp1[-tystate[i]] );
|
||||
}
|
||||
}
|
||||
|
||||
arrdone();
|
||||
|
||||
arrset("yyr1");
|
||||
for( i=1; i<nprod; ++i ) arrval( *prdptr[i] - NTBASE );
|
||||
arrdone();
|
||||
|
||||
arrset("yyr2");
|
||||
for( i=1; i<nprod; ++i ) arrval( ( prdptr[i+1]-prdptr[i]-2 ) );
|
||||
arrdone();
|
||||
|
||||
}
|
||||
|
||||
go2(i,c){ /* do a goto on the closure state, not worrying about lookaheads */
|
||||
if( c<NTBASE ) return( amem[ apstate[i]+c ] );
|
||||
else return( amem[ apstate[i] + c - NTBASE + nterms ] );
|
||||
}
|
||||
|
||||
int pkdebug 0;
|
||||
apack(p, n ) int *p;{ /* pack state i from temp1 into amem */
|
||||
_REGISTER k, l, off;
|
||||
int j;
|
||||
|
||||
/* find the spot */
|
||||
|
||||
j = n;
|
||||
for( off = 0; off <= j && p[off] == 0; ++off ) ;
|
||||
if( off > j ){ /* no actions */
|
||||
return(0);
|
||||
}
|
||||
j =- off;
|
||||
for( k=0; k<actsiz; ++k ){
|
||||
for( l=0; l<=j; ++l ){
|
||||
if( p[off+l] != 0 ){
|
||||
if( p[off+l] != amem[k+l] && amem[k+l] != 0 ) goto nextk;
|
||||
}
|
||||
}
|
||||
if( pkdebug ){ settty(); printf("off = %d, k = %d\n", off, k ); }
|
||||
/* we have found an acceptable k */
|
||||
for( l=0; l<=j; ++l ){
|
||||
if( p[off+l] ){
|
||||
if( k+l >= actsiz ) error("action table overflow");
|
||||
if( k+l >= memact ) memact = k+l;
|
||||
amem[k+l] = p[off+l];
|
||||
}
|
||||
}
|
||||
if( pkdebug ){
|
||||
for( k=0; k<memact; k=+10){
|
||||
printf("\t");
|
||||
for( l=0; l<=9; ++l ) printf("%d ", amem[k+l] );
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
return(k-off);
|
||||
|
||||
nextk: ;
|
||||
}
|
||||
error("no space in action table");
|
||||
}
|
||||
|
||||
go2out(){ /* output the gotos for the nontermninals */
|
||||
int i, j, k, best, offset, count, cbest, times;
|
||||
|
||||
settab();
|
||||
arrset("yygo");
|
||||
offset = 1;
|
||||
|
||||
for( i=1; i<=nnonter; ++i ) {
|
||||
go2gen(i);
|
||||
|
||||
/* find the best one to make default */
|
||||
|
||||
temp2[i] = offset;
|
||||
|
||||
best = -1;
|
||||
times = 0;
|
||||
|
||||
for( j=0; j<=nstate; ++j ){ /* is j the most frequent */
|
||||
if( tystate[j] == 0 ) continue;
|
||||
if( tystate[j] == best ) continue;
|
||||
|
||||
/* is tystate[j] the most frequent */
|
||||
|
||||
count = 0;
|
||||
cbest = tystate[j];
|
||||
|
||||
for( k=j; k<=nstate; ++k ) if( tystate[k]==cbest ) ++count;
|
||||
|
||||
if( count > times ){
|
||||
best = cbest;
|
||||
times = count;
|
||||
}
|
||||
}
|
||||
|
||||
/* best is now the default entry */
|
||||
|
||||
zzgobest =+ (times-1)*2;
|
||||
settab();
|
||||
for( j=0; j<=nstate; ++j ){
|
||||
if( tystate[j] != 0 && tystate[j]!=best ){
|
||||
arrval( j );
|
||||
arrval( tystate[j] );
|
||||
offset =+ 2;
|
||||
zzgoent =+ 2;
|
||||
}
|
||||
}
|
||||
|
||||
/* now, the default */
|
||||
|
||||
zzgoent =+ 2;
|
||||
arrval( -1 );
|
||||
arrval( best );
|
||||
offset =+ 2;
|
||||
|
||||
}
|
||||
|
||||
arrdone();
|
||||
|
||||
arrset("yypgo");
|
||||
for( i=1; i<=nnonter; ++i ) arrval( temp2[i] );
|
||||
arrdone();
|
||||
|
||||
}
|
||||
|
||||
int g2debug 0;
|
||||
go2gen(c){ /* output the gotos for nonterminal c */
|
||||
|
||||
int i, work, cc;
|
||||
struct item *p, *q;
|
||||
|
||||
/* first, find nonterminals with gotos on c */
|
||||
|
||||
aryfil( temp1, nnonter+1, 0 );
|
||||
temp1[c] = 1;
|
||||
|
||||
work = 1;
|
||||
while( work ){
|
||||
work = 0;
|
||||
for( i=0; i<nprod; ++i ){
|
||||
if( (cc=prdptr[i][1]-NTBASE) >= 0 ){ /* cc is a nonterminal */
|
||||
if( temp1[cc] != 0 ){ /* cc has a goto on c */
|
||||
cc = *prdptr[i]-NTBASE; /* thus, the left side of production i does too */
|
||||
if( temp1[cc] == 0 ){
|
||||
work = 1;
|
||||
temp1[cc] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* now, we have temp1[c] = 1 if a goto on c in closure of cc */
|
||||
|
||||
if( g2debug ){
|
||||
settty();
|
||||
printf("%s: gotos on ", nontrst[c].name );
|
||||
for( i=0; i<=nnonter; ++i ) if( temp1[i]) printf("%s ", nontrst[i].name);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/* now, go through and put gotos into tystate */
|
||||
|
||||
aryfil( tystate, nstate, 0 );
|
||||
settty();
|
||||
printf("\nnonterminal %s\n", nontrst[c].name );
|
||||
for( i=0; i<nstate; ++i ){
|
||||
q = pstate[i+1];
|
||||
for( p=pstate[i]; p<q; ++p ){
|
||||
if( (cc= *p->pitem) >= NTBASE ){
|
||||
if( temp1[cc =- NTBASE] ){ /* goto on c is possible */
|
||||
tystate[i] = amem[indgo[i]+c];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( tystate[i] ) printf("\t%d\t%d\n", i, tystate[i]);
|
||||
}
|
||||
}
|
||||
|
||||
precftn(r,t){ /* decide a shift/reduce conflict by precedence.
|
||||
Returns 0 if action is 'do nothing',1 if action is reduce,
|
||||
2 if the action is 'error,binary operator'
|
||||
and 3 if the action is 'reduce'. */
|
||||
|
||||
int lp,lt;
|
||||
lp = levprd[r];
|
||||
lt = trmlev[t];
|
||||
if ((lt==0)||((lp&03)==0))return(0);
|
||||
if((lt>>3) == (lp>>3)){
|
||||
return(lt&03);
|
||||
}
|
||||
if((lt>>3) > (lp>>3)) return(3);
|
||||
return(1);
|
||||
}
|
||||
|
||||
int cdebug 0; /* debug for common states */
|
||||
wract(i){ /* output state i */
|
||||
/* temp1 has the actions, lastred the default */
|
||||
int p, p0, p1, size;
|
||||
int ntimes, tred, count, j;
|
||||
struct item *q0, *q1;
|
||||
|
||||
/* find the best choice for lastred */
|
||||
|
||||
lastred = 0;
|
||||
ntimes = 0;
|
||||
for( j=1; j<=nterms; ++j ){
|
||||
if( temp1[j] >= 0 ) continue;
|
||||
if( temp1[j]+lastred == 0 ) continue;
|
||||
/* count the number of appearances of temp1[j] */
|
||||
count = 0;
|
||||
tred = -temp1[j];
|
||||
for( p=1; p<=nterms; ++p ){
|
||||
if( temp1[p]+tred == 0 ) ++count;
|
||||
}
|
||||
if( count >ntimes ){
|
||||
lastred = tred;
|
||||
ntimes = count;
|
||||
}
|
||||
}
|
||||
|
||||
/* clear out entries in temp1 which equal lastred */
|
||||
for( p=1; p<= nterms; ++p ) if( temp1[p]+lastred == 0 )temp1[p]=0;
|
||||
|
||||
/* write out the state */
|
||||
|
||||
/* first, check for equality with another state */
|
||||
/* see if there is a nonterminal with all dots before it. */
|
||||
|
||||
p0 = 0;
|
||||
q1 = pstate[i+1];
|
||||
for( q0=pstate[i]; q0<q1; ++q0 ){
|
||||
if( (p1= *(q0->pitem) ) < NTBASE ) goto standard;
|
||||
if( p0 == 0 ) p0 = p1;
|
||||
else if( p0 != p1 ) goto standard;
|
||||
}
|
||||
|
||||
/* now, all items have dots before p0 */
|
||||
if( cdebug ){
|
||||
settty();
|
||||
printf("state %d, pre-nonterminal %s\n",i,nontrst[p0-NTBASE].name);
|
||||
}
|
||||
|
||||
for( j=0; j<i; ++j ){
|
||||
if( apstate[i] != apstate[j] ) continue;
|
||||
|
||||
/* equal positions -- check items */
|
||||
|
||||
if( cdebug )printf("states %d and %d have equal positions\n",i,j);
|
||||
q1 = pstate[j+1];
|
||||
for( q0=pstate[j]; q0<q1; ++q0 ){
|
||||
if( *(q0->pitem) != p0 ) goto nextj;
|
||||
}
|
||||
|
||||
/* we have a match with state j ! */
|
||||
|
||||
tystate[i] = -j;
|
||||
zzacsave =+ tystate[j];
|
||||
zznsave++;
|
||||
wrstate(i);
|
||||
return;
|
||||
|
||||
nextj: ;
|
||||
}
|
||||
|
||||
|
||||
standard:
|
||||
tystate[i] = 2;
|
||||
wrstate(i);
|
||||
|
||||
size = 0;
|
||||
for( p0=1; p0<=nterms; ++p0 )
|
||||
if( (p1=temp1[p0])!=0 ) {
|
||||
arrval( TESTACT+trmset[p0].value );
|
||||
if( p1 < 0 ) arrval( REDUCACT - p1 );
|
||||
else if( p1 == ACCEPTCODE ) arrval( ACCEPTACT );
|
||||
else if( p1 == ERRCODE ) arrval( ERRACT );
|
||||
else arrval( SHIFTACT + p1 );
|
||||
size =+ 2;
|
||||
}
|
||||
if( lastred ) arrval( REDUCACT + lastred );
|
||||
else arrval( ERRACT );
|
||||
tystate[i] = size+1; /* store entry size in tystate */
|
||||
zzacent =+ (size+1);
|
||||
return;
|
||||
}
|
||||
|
||||
wrstate(i){ /* writes state i */
|
||||
int j0,j1,s;
|
||||
struct item *pp, *qq;
|
||||
settty();
|
||||
printf("\nstate %d\n",i);
|
||||
qq = pstate[i+1];
|
||||
for( pp=pstate[i]; pp<qq; ++pp) printf("\t%s\n", writem(pp));
|
||||
|
||||
/* check for state equal to another */
|
||||
|
||||
if( tystate[i] <= 0 ){
|
||||
printf("\n\tsame as %d\n\n", -tystate[i] );
|
||||
return;
|
||||
}
|
||||
|
||||
for( j0=1; j0<=nterms; ++j0 ) if( (j1=temp1[j0]) != 0 ){
|
||||
printf("\n\t%s ", symnam(j0) );
|
||||
if( j1>0 ){ /* shift, error, or accept */
|
||||
if( j1 == ACCEPTCODE ) printf( "accept" );
|
||||
else if( j1 == ERRCODE ) printf( "error" );
|
||||
else printf( "shift %d", j1 );
|
||||
}
|
||||
else printf("reduce %d",-j1 );
|
||||
}
|
||||
|
||||
/* output the final production */
|
||||
|
||||
if( lastred ) printf("\n\t. reduce %d\n\n", lastred );
|
||||
else printf("\n\t. error\n\n" );
|
||||
|
||||
ret:
|
||||
settab();
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/* fake portable I/O routines, for those
|
||||
sites so backward as to not have the
|
||||
port. library */
|
||||
|
||||
int cin, cout;
|
||||
extern int fin, fout;
|
||||
|
||||
copen( s, c ) char *s; {
|
||||
int f;
|
||||
|
||||
if( c == 'r' ){
|
||||
fin = f = open( s, 0 );
|
||||
}
|
||||
|
||||
else if( c == 'a' ){
|
||||
f = open( s, 1 );
|
||||
seek( f, 0, 2 );
|
||||
}
|
||||
|
||||
else { /* c == w */
|
||||
f = creat( s, 0666 );
|
||||
}
|
||||
|
||||
return( f );
|
||||
}
|
||||
|
||||
cflush(x){ /* fake! sets file to x */
|
||||
flush();
|
||||
fout = x;
|
||||
}
|
||||
|
||||
system(){
|
||||
error( "The function \"system\" is called" );
|
||||
}
|
||||
|
||||
cclose(i){
|
||||
close(i);
|
||||
}
|
||||
|
||||
cexit(i){
|
||||
flush();
|
||||
exit();
|
||||
}
|
||||
Reference in New Issue
Block a user