📄 y2.c
字号:
#include "dextern.h"#define IDENTIFIER 257#define MARK 258#define TERM 259#define LEFT 260#define RIGHT 261#define BINARY 262#define PREC 263#define LCURLY 264#define C_IDENTIFIER 265 /* name followed by colon */#define NUMBER 266#define START 267#define TYPEDEF 268#define TYPENAME 269#define UNION 270#define ENDFILE 0/* * communication variables between various I/O routines */char *infile; /* input file name */union { int number; /* value of an input number */ char* tokname; /* input token name */} yylval;char tokname[NAMESIZE]; /* storage for input token name *//* * storage of names */char cnames[CNAMSZ]; /* place where token and nonterminal names are stored */int cnamsz = CNAMSZ; /* size of cnames */char * cnamp = cnames; /* place where next name is to be put in */int ndefout = 3; /* number of defined symbols output *//* * storage of types */int ntypes; /* number of types defined */char * typeset[NTYPES]; /* pointers to type tags *//* * symbol tables for tokens and nonterminals */int ntokens = 0;struct toksymb tokset[NTERMS];int toklev[NTERMS];int nnonter = -1;struct ntsymb nontrst[NNONTERM];int start; /* start symbol *//* * assigned token type values */int extval = 0;/* * input and output file descriptors */FILE * finput; /* yacc input file */FILE * faction; /* file for saving actions */FILE * fdefine; /* file for #defines */FILE * ftable; /* y.tab.c file */FILE * ftemp; /* tempfile to pass 2 */FILE * foutput; /* y.output file *//* * storage for grammar rules */int mem0[MEMSIZE] ; /* production storage */int *mem = mem0;int nprod= 1; /* number of productions */int *prdptr[NPROD]; /* pointers to descriptions of productions */int levprd[NPROD] ; /* precedence levels for the productions */void setup(int argc,char *argv[]);int yyparse(void);void finact(void);int defin(int t, register char *s);void defout(void);char *cstash(register char * s);int yylex(void);int fdtype(int t);int chfind(int t, register char *s);void cpyunion(void);void cpycode(void);int skipcom(void);void cpyact(int offset);void setup(int argc,char *argv[]){ foutput = NULL; fdefine = NULL; while(argc >= 2 && argv[1][0] == '-') { while(*++(argv[1])){ switch(*argv[1]){ case 'v': case 'V': foutput = fopen(FILEU, "w"); if(foutput == NULL) error("cannot open y.output"); continue; case 'D': case 'd': fdefine = fopen(FILED, "w"); continue; case 'o': case 'O': fprintf(stderr, "`o' flag now default in yacc\n"); continue; case 'r': case 'R': error("Ratfor Yacc is dead: sorry...\n"); default: error("illegal option: %c", *argv[1]); } } argv++; argc--; } ftable = fopen(OFILE, "w"); if(ftable == NULL) error("cannot open table file"); ftemp = fopen(TEMPNAME, "w"); faction = fopen(ACTNAME, "w"); if(ftemp==NULL || faction==NULL) error("cannot open temp file"); if(argc < 2 || ((finput=fopen(infile=argv[1], "r")) == NULL)){ error("cannot open input file"); }}int yyparse(void){ int i,j,lev,t, ty; int c; int *p; char actname[8]; cnamp = cnames; defin(0,"$end"); extval = 0400; defin(0,"error"); defin(1,"$accept"); mem=mem0; lev = 0; ty = 0; i=0; /* sorry -- no yacc parser here..... we must bootstrap somehow... */ for(t=yylex(); t!=MARK && t!= ENDFILE;){ switch(t){ case ';': t = yylex(); break; case START: if((t=yylex()) != IDENTIFIER){ error("bad %%start construction"); } start = chfind(1,yylval.tokname); t = yylex(); continue; case TYPEDEF: if((t=yylex()) != TYPENAME) error("bad syntax in %%type"); ty = yylval.number; for(;;){ t = yylex(); switch(t){ case IDENTIFIER: if((t=chfind(1, yylval.tokname)) < NTBASE) { j = TYPE(toklev[t]); if(j!= 0 && j != ty){ error("type redeclaration of token %s", tokset[t].name); } else SETTYPE(toklev[t],ty); } else { j = nontrst[t-NTBASE].tvalue; if(j != 0 && j != ty){ error("type redeclaration of nonterminal %s", nontrst[t-NTBASE].name); } else nontrst[t-NTBASE].tvalue = ty; } case ',': continue; case ';': t = yylex(); break; default: break; } break; } continue; case UNION: /* copy the union declaration to the output */ cpyunion(); t = yylex(); continue; case LEFT: case BINARY: case RIGHT: ++i; case TERM: lev = t-TERM; /* nonzero means new prec. and assoc. */ ty = 0; /* get identifiers so defined */ t = yylex(); if(t == TYPENAME){ /* there is a type defined */ ty = yylval.number; t = yylex(); } for(;;) { switch(t){ case ',': t = yylex(); continue; case ';': break; case IDENTIFIER: j = chfind(0,yylval.tokname); if(lev){ if(ASSOC(toklev[j])) error("redeclaration of precedence of %s", yylval.tokname); SETASC(toklev[j],lev); SETPLEV(toklev[j],i); } if(ty){ if(TYPE(toklev[j])) error("redeclaration of type of %s", yylval.tokname); SETTYPE(toklev[j],ty); } if((t=yylex()) == NUMBER){ tokset[j].value = yylval.number; if(j < ndefout && j>2){ error("please define type number of %s earlier", tokset[j].name); } t=yylex(); } continue; } break; } continue; case LCURLY: defout(); cpycode(); t = yylex(); continue; default: error("syntax error"); } } if(t == ENDFILE){ error("unexpected EOF before %%"); } /* t is MARK */ defout(); fprintf(ftable, "#define yyclearin yychar = -1\n"); fprintf(ftable, "#define yyerrok yyerrflag = 0\n"); fprintf(ftable, "extern int yychar;\nextern short yyerrflag;\n"); fprintf(ftable, "#ifndef YYMAXDEPTH\n#define YYMAXDEPTH 150\n#endif\n"); if(!ntypes) fprintf(ftable, "#ifndef YYSTYPE\n#define YYSTYPE int\n#endif\n"); fprintf(ftable, "YYSTYPE yylval, yyval;\n"); prdptr[0]=mem; /* added production */ *mem++ = NTBASE; *mem++ = start; /* if start is 0, we will overwrite with the lhs of the first rule */ *mem++ = 1; *mem++ = 0; prdptr[1]=mem; while((t=yylex()) == LCURLY) cpycode(); if(t != C_IDENTIFIER) error("bad syntax on first rule"); if(!start) prdptr[0][1] = chfind(1,yylval.tokname); /* read rules */ while(t!=MARK && t!=ENDFILE){ /* process a rule */ if(t == '|'){ *mem++ = *prdptr[nprod-1]; } else if(t == C_IDENTIFIER){ *mem = chfind(1,yylval.tokname); if(*mem < NTBASE) error("token illegal on LHS of grammar rule"); ++mem; } else error("illegal rule: missing semicolon or | ?"); /* read rule body */ t = yylex(); for (;;) { while(t == IDENTIFIER) { *mem = chfind(1,yylval.tokname); if(*mem<NTBASE) levprd[nprod] = toklev[*mem]; ++mem; t = yylex(); } if(t == PREC){ if(yylex()!=IDENTIFIER) error("illegal %%prec syntax"); j = chfind(2,yylval.tokname); if(j>=NTBASE) error("nonterminal %s illegal after %%prec", nontrst[j-NTBASE].name); levprd[nprod]=toklev[j]; t = yylex(); if (t == IDENTIFIER) continue; } if(t == '='){ levprd[nprod] |= ACTFLAG; fprintf(faction, "\ncase %d:", nprod); cpyact(mem-prdptr[nprod]-1); fprintf(faction, " break;"); if((t=yylex()) == IDENTIFIER){ /* action within rule... */ sprintf(actname, "$$%d", nprod); j = chfind(1,actname); /* make it a nonterminal */ /* the current rule will become rule number nprod+1 */ /* move the contents down, and make room for the null */ for(p=mem; p>=prdptr[nprod]; --p) p[2] = *p; mem += 2; /* enter null production for action */ p = prdptr[nprod]; *p++ = j; *p++ = -nprod; /* update the production information */ levprd[nprod+1] = levprd[nprod] & ~ACTFLAG; levprd[nprod] = ACTFLAG; if(++nprod >= NPROD) error("more than %d rules", NPROD); prdptr[nprod] = p; /* make the action appear in the original rule */ *mem++ = j; /* get some more of the rule */ continue; } } break; } while(t == ';') t = yylex(); *mem++ = -nprod; /* check that default action is reasonable */ if(ntypes && !(levprd[nprod]&ACTFLAG) && nontrst[*prdptr[nprod]-NTBASE].tvalue){ /* no explicit action, LHS has value */ register int tempty; tempty = prdptr[nprod][1]; if(tempty < 0) error("must return a value, since LHS has a type"); else if(tempty >= NTBASE) tempty = nontrst[tempty-NTBASE].tvalue; else tempty = TYPE(toklev[tempty]); if(tempty != nontrst[*prdptr[nprod]-NTBASE].tvalue){ error("default action causes potential type clash"); } } if(++nprod >= NPROD) error("more than %d rules", NPROD); prdptr[nprod] = mem; levprd[nprod]=0; } /* end of all rules */ finact(); if(t == MARK){ fprintf(ftable, "\n#line %d \"%s\"\n", lineno, infile); while((c=getc(finput)) != EOF) putc(c, ftable); } fclose(finput); return 0;}/* * finish action routine */void finact(void){ fclose(faction); fprintf(ftable, "#define YYERRCODE %d\n", tokset[2].value);}/* * define s to be a terminal if t=0 * or a nonterminal if t=1 */int defin(int t, register char *s){ register int val=0; if (t) { if(++nnonter >= NNONTERM) error("too many nonterminals, limit %d",NNONTERM); nontrst[nnonter].name = cstash(s); return(NTBASE + nnonter); } /* must be a token */ if(++ntokens >= NTERMS) error("too many terminals, limit %d",NTERMS); tokset[ntokens].name = cstash(s); /* establish value for token */ if(s[0]==' ' && s[2]=='\0') /* single character literal */ val = s[1]; else if (s[0]==' ' && s[1]=='\\') { /* escape sequence */ if(s[3] == '\0'){ /* single character escape sequence */ switch (s[2]){ /* character which is escaped */ case 'n': val = '\n'; break; case 'r': val = '\r'; break; case 'b': val = '\b'; break; case 't': val = '\t'; break; case 'f': val = '\f'; break; case '\'': val = '\''; break; case '"': val = '"'; break; case '\\': val = '\\'; break; default: error("invalid escape"); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -