Add original unix v6

This commit is contained in:
memnoth
2018-01-27 22:35:41 +09:00
commit 2c7099ee50
664 changed files with 106254 additions and 0 deletions
+5
View File
@@ -0,0 +1,5 @@
main( argc, argv ) int argc; char *argv[]; {
yyinit( argc, argv );
if( yyparse() ) return;
yyaccpt();
}
+125
View File
@@ -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 */
}
}
}
+1
View File
@@ -0,0 +1 @@
yyaccpt(){}
+16
View File
@@ -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;
}
}
+1
View File
@@ -0,0 +1 @@
yyinit(){}
+9
View File
@@ -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
+123
View File
@@ -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
+103
View File
@@ -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 */
+281
View File
@@ -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( "}" );
}
}
+533
View File
@@ -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;
}
+378
View File
@@ -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++]);
}
+417
View File
@@ -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();
}
+43
View File
@@ -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();
}