|
DataMuseum.dkPresents historical artifacts from the history of: Commodore CBM-900 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Commodore CBM-900 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - download
Length: 14966 (0x3a76) Types: TextFile Notes: UNIX file Names: »y2.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code └─⟦f4b8d8c84⟧ UNIX Filesystem └─ ⟦this⟧ »cmd/yacc/y2.c«
/* * LALR-1 parser generator * read in rules * - read in definitions * - gobble rules * - copy anything complicated to the output */ #include "yacc.h" #include "action.h" struct sym *defsym(), *elook(); YYSTYPE yylval; struct { int lex; YYSTYPE val; } last = {-1}; readrules() { struct sym *saccept, *seof, *serror; int t, t1, t2, nt, asc, pred, tokno, toktyp, c; struct sym *sp; #if DGC printf("Read rules\n"); #endif saccept = defsym("$accept", TNTERM); seof = defsym("$end", TTERM); serror = defsym("error", TTERM); seof->s_val = YYEOFVAL; serror->s_val = YYERRVAL; /* part 1 - read in rules */ while( (t = yylex()) != MARK ) { #if DGC printf("t = %d\n", t); #endif switch( t ) { case EOF: yyerror(FATAL, "end of file in definition section\n"); break; /* stupid C switch statement */ case START: if( yylex() != IDENT ) yyerror(!FATAL, "bad %start syntax"); else { defsym(yylval.sptr->s_name,TNTERM); startsym = yylval.sptr->s_no; } break; case UNION: copyunion(); break; case TOKEN: case LEFT: case RIGHT: case NONASSOC: asc = t-TOKEN; if( t!=TOKEN ) pred = predlev++; else pred = UNKNOWN; case TYPE: toktyp = UINT; while( (t1 = yylex()) == IDENT || t1 == T_IDENT ) { if( t1==T_IDENT ) { toktyp = yylval.sptr->s_no; continue; } sp = yylval.sptr; if( (t2 = yylex()) == INTEGER ) if( t==TYPE ) /*MWC DSC*/ yyerror(!FATAL, "token value assignment not allowed for %type"); else tokno = yylval.ival; else { backup(t2); if( sp->s_name[0]!='\'' ) tokno = tno++; else tokno = UNKNOWN; } if( t==TYPE && toktyp==UINT ) yyerror(!FATAL,"Type id needed for %%type"); switch( t ) { case TOKEN: case LEFT: case RIGHT: case NONASSOC: /* C needs ranges on case */ deftok(sp, toktyp, asc, pred, tokno); break; case TYPE: defnttyp(sp, toktyp); break; } if( (t2 = yylex()) != COMMA ) backup(t2); } backup(t1); break; default: yyerror(FATAL, "unexpected symbol in definition section", t); } } wrtdefs(); wrthdr(); /* part 2 - read in rules */ prdptr[0] = (struct prod *)yalloc(1, sizeof *prdptr[0] + 3 * sizeof *prdptr[0]->p_right); prdptr[0]->p_prodno = 0; prdptr[0]->p_prc = prdptr[0]->p_ass = UNKNOWN; prdptr[0]->p_left = -saccept->s_no; prdptr[0]->p_right[0] = startsym; prdptr[0]->p_right[1] = seof->s_no; prdptr[0]->p_right[2] = -1; nprod = 1; while( (t = yylex()) == C_IDENT ) { defsym(yylval.sptr->s_name, TNTERM); nt = yylval.sptr->s_no; while( getrule(nt) ); } if( t==MARK ) { /* gobble up rest of file */ linepos(tabout); while( (c = llgetc()) != EOF ) putc(c, tabout); } else if( t!=EOF ) yyerror(FATAL, "bad rule syntax"); wrtnames(); fclose(defin); fclose(actout); } /* * lexical input reader * - copy comments and percent curlies to the output w/o change * - lookup the list of reserved keywords * - enter identifiers and character constants in the symbol table * character constants are special because they start with a apostrophe * as do internally generated non terminals * - the "value" of the token read is left in the global variable yylval * this is either a symbol table pointer or an integer (for NUMBER) */ yylex() { int c, i, lesk; char s[SYMSIZE]; if( last.lex != -1 ) { yylval = last.val; lesk = last.lex; last.lex = -1; return( lesk ); } last.lex = -1; read: while( whitespace( c = llgetc() ) ) ; switch( c ) { case '|': return( VBAR ); case ';': return( SEMICOLON ); case '/': if( (c = llgetc()) != '*' ) goto error; copycomment("*/", NULL, 0); /* write to the rathole */ goto read; case '<': gettype(s); yylval.sptr = defsym(s, TTYPE); return( T_IDENT ); case '{': return( LBRAC ); case ',': return( COMMA ); case '%': if( (c = llgetc()) == '{' ) { linepos(tabout); copycomment("%}", tabout, 0); goto read; } else if( c=='%' ) return( MARK ); llungetc(c); getword(s); for( i=0; restab[i].r_name ; i++ ) if( strcmp(s, restab[i].r_name)==0 ) return( restab[i].r_val ); yyerror(!FATAL|SKIP, "illegal \"%%keyword\""); goto read; case '\'': c = readchar(); if( llgetc() != '\'' ) { yyerror(!FATAL|SKIP, "bad character constant\n"); goto read; } sprintf(s, "%s", prsym(c)); yylval.sptr = defsym(s, TTERM); yylval.sptr->s_val = c; return( IDENT ); case EOF: return(EOF); default: if( digit(c) ) { yylval.ival = readnum(c); return( INTEGER ); } else if( alpha(c) ) { llungetc(c); getword(s); yylval.sptr = defsym(s, UNKNOWN); while( whit2space(c = llgetc()) ); if( c==':' ) return( C_IDENT ); llungetc(c); return(IDENT); } else { error: yyerror(!FATAL|SKIP, "illegal character %c", c); goto read; } } } /* read a production (the bi's for a <- b0 .. bn ) until a ';' or '|' */ getrule(nt) int nt; { int precused, t, n, size, actpres; char s[SYMSIZE]; register struct prod *pp; register struct sym *sp; nitprod->p_left = -nt; nitprod->p_prc = nitprod->p_ass = UNKNOWN; actpres = n = precused = 0; t = yylex(); while( t==PREC || t==IDENT || t==LBRAC ) { switch( t ) { case PREC: t = yylex(); sp = yylval.sptr; if( sp->s_genre!=TTERM || sp->s_prc<0 ) yyerror(!FATAL,"bad %prec construct"); else { nitprod->p_prc = sp->s_prc; nitprod->p_ass = sp->s_ass; precused++; } break; case IDENT: sp = yylval.sptr; if( sp->s_genre == UNKNOWN ) defsym(sp->s_name, TNTERM); if( sp->s_genre==TTERM && sp->s_ass>UNASSOC && !precused ) { nitprod->p_ass = sp->s_ass; nitprod->p_prc = sp->s_prc; } if( n >= MAXPRODL-1 ) yyerror(FATAL, "production too long"); nitprod->p_right[n++] = sp->s_no; break; case LBRAC: cpyact(n, ntrmptr[nt-NTBASE]); if( (t = yylex()) == IDENT ) { /* action inside rule */ pp = (struct prod *)yalloc(1, sizeof *pp + sizeof(int)); sprintf(s, "$$%d", nprod); sp = defsym(s, TNTERM); pp->p_prodno = nprod; pp->p_prc = pp->p_ass = UNKNOWN; pp->p_left = -sp->s_no; pp->p_right[0] = -1; bounded(nprod, maxprod, "productions"); prdptr[nprod++] = pp; nitprod->p_right[n++] = sp->s_no; } else actpres++; continue; } t = yylex(); } if( !actpres && ntrmptr[nt-NTBASE]->s_type>=0 ) { if( n==0 ) yyerror(!FATAL, "must return value since lhs has type\n"); else if( elook(*nitprod->p_right)->s_type != ntrmptr[nt-NTBASE]->s_type ) yyerror(WARNING, "default action may cause type clash"); } if( t!=VBAR && t!=SEMICOLON ) yyerror(FATAL, "rule terminator not ';' or '|'"); bounded(nprod, maxprod, "productions"); nitprod->p_prodno = nprod; nitprod->p_right[n++] = -1; size = sizeof *nitprod + n * sizeof(int); copyb(nitprod, prdptr[nprod++] = (struct prod *)yalloc(1, size), size); return( t==VBAR ); } struct sym * defsym(s, typ) char *s; { register struct sym *sp; register struct genre *gp; /* MWC DSC */ register i; int start; i = start = hash(s); while( (sp = symtab[i])!=NULL && strcmp(s, sp->s_name) ) if( (i = (i+1) % maxsym ) == start ) /* MWC DSC */ yyerror(FATAL, "symbol table overflow"); if( sp==NULL ) { #if DEBUG printf("defsym: %s new\n", s); #endif sp = symtab[i] = (struct sym *)yalloc(1, sizeof *sp); #ifdef DAVELIB sprintf(sp->s_name, "%.?s", SYMSIZE-1, s); #else sprintf(sp->s_name, "%.*s", SYMSIZE-1, s); #endif sp->s_no = -1; sp->s_prc = sp->s_ass = UNKNOWN; sp->s_type = UINT; sp->s_genre = UNKNOWN; } if( typ!=UNKNOWN && sp->s_genre!=typ ) { if( sp->s_genre!=UNKNOWN ) yyerror(FATAL, "internal error - type redefinition"); sp->s_genre = typ; if( (sp->s_no = gtab[typ].g_ordno++) >= gtab[typ].g_maxord ) yyerror(FATAL, "too many %s, actual limit %d", gtab[typ].g_name, gtab[typ].g_maxord); gp = >ab[typ]; (*gp->g_sptr) [ sp->s_no ] = sp; sp->s_no += gp->g_base; #if DEBUG printf("defsym: %s %d %d\n", s, typ, sp->s_no); #endif } return(sp); } int hash(s) /* Could have more scatter on 32-bit int machine */ register char *s; { register unsigned sum; if( (sum = *s) == '\0' ) return(0); do { sum += s[0] | s[1]<<8; s += 2; } while( s[-1]!='\0' && s[0]!='\0' ); return( sum % maxsym ); /* MWC DSC */ } gettype(s) char *s; { register c; while( whit2space( c = llgetc() ) ) ; /* just for howard */ llungetc(c); getword(s); if( llgetc()!='>' ) yyerror(!FATAL|SKIP, "missing '>' in type ref"); } deftok(sp, typ, asc, pred, tokno) struct sym *sp; int typ, asc, pred, tokno; { if( yydebug ) fprintf(listout, "deftok(%s) = type %d, ass %d, pred %d, # %d\n", sp->s_name, typ, asc, pred, tokno); if( typ!=UNKNOWN ) sp->s_type = typ; if( asc!=UNKNOWN ) sp->s_ass = asc; if( pred!=UNKNOWN ) sp->s_prc = pred; if( tokno!=UNKNOWN ) sp->s_val = tokno; defsym(sp->s_name, TTERM); } wrtdefs() { register i; register struct sym *sp; for(i=0; i<nterm; i++) { sp = trmptr[i]; if( alpha(sp->s_name[0]) && strcmp(sp->s_name, "error") ) fprintf(fhdr, "#define %s %d\n", sp->s_name, sp->s_val); } if (ntype==0) fprintf(fhdr, "typedef int YYSTYPE;\n"); fprintf(fhdr, "#ifdef YYTNAMES\n"); fprintf(fhdr, "extern struct yytname\n{\n"); fprintf(fhdr, "\tchar\t*tn_name;\n\tint\ttn_val;\n} yytnames[];\n"); fprintf(fhdr, "#endif\n"); fprintf(fhdr, "extern YYSTYPE yylval;\n"); fclose(fhdr); } wrthdr() { fprintf(tabout, "\n#include \"%s\"\n", ytabh); fprintf(tabout, "#define YYCLEARIN yychar = -1000\n"); fprintf(tabout, "#define YYERROK yyerrflag = 0\n"); fprintf(tabout, "extern int yychar;\n"); fprintf(tabout, "extern short yyerrflag;\n"); fprintf(tabout,"#ifndef YYMAXDEPTH\n#define YYMAXDEPTH 150\n"); fprintf(tabout,"#endif\n"); fprintf(tabout, "YYSTYPE yyval, yylval;\n"); } wrtnames() { register i; register char *sp; fprintf(tabout, "#ifdef YYTNAMES\n"); fprintf(tabout, "struct yytname yytnames[%d] =\n{\n", nterm); for(i=0; i<nterm; i++) { fprintf(tabout, "\t\""); sp = trmptr[i]->s_name; while( *sp ) { if( *sp=='\\' || *sp=='"' ) putc('\\', tabout); putc(*sp, tabout); sp++; } fprintf(tabout, "\", %d, \n", trmptr[i]->s_val); } fprintf(tabout, "\tNULL\n} ;\n"); fprintf(tabout, "#endif\n"); } defnttyp(sp, typ) struct sym *sp; { sp->s_type = typ; } cpyact(nel, ntp) struct sym *ntp; { register c, istyp, n; int accolade, sign, c1; char s[SYMSIZE]; struct sym *sp; accolade = 1; fprintf(actout, "\ncase %d: {\n", nprod); linepos(actout); do { c = llgetc(); switch( c ) { case EOF: yyerror(FATAL, "end of file in action"); break; case '{': accolade++; break; case '}': accolade--; break; case '/': if( (c1 = llgetc()) == '*' ) { fprintf(actout, "/*"); copycomment("*/", actout, 0); fprintf(actout, "*/"); continue; } llungetc(c1); break; case '"': putc('"', actout); copycomment("\"", actout, 1); putc('"', actout); continue; case '\'': putc('\'', actout); copycomment("'", actout, 1); putc('\'', actout); continue; case '$': if( istyp = (c = llgetc())=='<' ) gettype(s); else llungetc(c); switch( c = llgetc() ) { case '$': if( !istyp && (istyp = ntp->s_type!=UINT) ) strcpy(s, typeptr[ntp->s_type]->s_name); fprintf(actout, "yyval"); if( istyp ) fprintf(actout,".%s",s); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '-': if( sign = c=='-' ) c = llgetc(); n = readnum(c); n += -2*sign*n; /* jazzy linear eq. sign switch */ if( n>nel ) { yyerror(!FATAL, "illegal $%d construct", n); break; } if( n>0 && !istyp && (sp = elook(nitprod->p_right[n-1]))-> s_type!=UINT ) { sp = typeptr[sp->s_type]; istyp++; strcpy(s, sp->s_name); } fprintf(actout,"yypvt[%d]", n-nel); if( istyp ) fprintf(actout,".%s",s); break; default: yyerror(!FATAL|SKIP, "illegal construct $%c", c); break; } continue; } putc(c, actout); } while( accolade ); fprintf(actout, "break;\n"); } backup(t) { last.lex = t; last.val = yylval; } linepos(f) FILE *f; { fprintf(f, "\n#line %d \"%s\"\n", yyline, gramy); } copycomment(s, f, flag) register char *s; FILE *f; { register c, c1; do { c = llgetc(); while( c=='\\' && flag ) { if( f!=NULL ) fprintf(f, "\\%c", llgetc()); c = llgetc(); } if( c==EOF ) yyerror(FATAL, "end of file god knows where"); if (c=='\n' && flag) yyerror(FATAL, "newline in string"); if(c!=s[0]){ if(f!=NULL) putc(c, f); } else if( s[1]!='\0' && (c1 = llgetc()) != s[1] ){ if(f!=NULL) putc(c, f); llungetc(c1); } } while( c!=s[0] || (s[1]!='\0' && (c1!=s[1])) ); } getword(s) char *s; { register char *sp; register c; sp = s; c = llgetc(); do { if( sp>=&s[SYMSIZE-1] ) yyerror(FATAL, "symbol too long"); *sp++ = c; } while( alphanum(c = llgetc()) ); *sp++ = '\0'; llungetc(c); } llgetc() { register c; if( (c = getc(defin)) == '\n' ) yyline++; return(c); } llungetc(c) register c; { if( c=='\n' ) yyline--; ungetc(c, defin); } readchar() { register c; if( (c = llgetc()) == '\\' ) { switch( c = llgetc() ) { case 'n': return( '\n' ); case 'r': return( '\r' ); case 't': return( '\t' ); case '\'': return( '\'' ); case 'b': return( '\b' ); case 'f': return( '\f' ); default: if( c>='0' && c<='7' ) return( readnum(c) ); else return(c); } } return(c); } copyunion() { register c, accolade; while( whitespace( c = llgetc() ) ); if( c!='{' ) yyerror(!FATAL,"Bad %union syntax"); linepos(fhdr); fprintf(fhdr, "typedef union {"); accolade = 1; do { if( (c = llgetc()) == EOF ) yyerror(FATAL, "eof in union declaration"); putc(c, fhdr); if( c=='{' ) accolade++; else if( c=='}' ) accolade--; else if( c=='/' ) { if( (c = llgetc()) == '*' ) { putc('*', fhdr); copycomment("*/", fhdr, 0); fprintf(fhdr, "*/"); } else llungetc(c); } } while( accolade ); fprintf(fhdr, " YYSTYPE;\n"); } readnum(c) register c; { register n; n = c - '0'; while( digit( c=llgetc() ) ) n = n*10 + c - '0'; llungetc(c); return(n); } alpha(c) { return( (c>='A' && c<='Z') || (c>='a' && c<='z') || c=='_' ); } digit(c) { return( c>='0' && c<='9' ); } alphanum(c) { return( (c>='A' && c<='Z') || (c>='a' && c<='z') || (c>='0' && c<='9') || c=='_' ); } whitespace(c) { return( c==' ' || c=='\t' || c=='\f' || c=='\n' ); } whit2space(c) { return( c==' ' || c=='\t' || c=='\f' ); } struct sym * elook(n) register n; { if( n>=NTBASE ) return( ntrmptr[n-NTBASE] ); else return( trmptr[n] ); } min(a,b) { return( a<b ? a : b); }