_GENERATING PARSERS WITH PCYACC_ by Alex Lane
[LISTING ONE]
yacc specification
/* TEST.Y
This specification is based largely on the yacc specification for a simple desk calculator from "Compilers: Principles, Techniques and Tools," by Aho, et al. (p. 259, Addison-Wesley, 1986).
2/2/89 a.lane */
%{ #include <stdio.h> #include <ctype.h> %}
%token DIGIT %left '+' %left '*'
line : /* nothing */ | expr '\n' { printf("%d\n", $1); } ; expr : expr '+' term { $$ = $1 + $3; } | term ; term : term '*' factor { $$ = $1 * $3; } | factor ; factor: '(' expr ')' { $$ = $2; } | DIGIT ; main() { yyparse(); }
yylex() {
int c; if ( isdigit( ( c = getchar() ) ) ) { yylval = c - '0'; return DIGIT; } return c;
}
yyerror(s) char *s; {
fprintf(stderr, "PYERR: %s\n", s);
}
[LISTING TWO]
# line 11 "test.y" #include <stdio.h> #include <ctype.h> #define DIGIT 257 #ifndef YYSTYPE #define YYSTYPE int #endif YYSTYPE yylval, yyval; #define YYERRCODE 256
# line 33 "test.y"
main() { yyparse(); }
yylex() {
int c; if ( isdigit( ( c = getchar() ) ) ) { yylval = c - '0'; return DIGIT; } return c;
}
yyerror(s) char *s; {
fprintf(stderr, "PYERR: %s\n", s);
}
FILE *yytfilep; char *yytfilen; int yytflag = 0; int svdprd[2]; char svdnams[2][2];
int yyexca[] = {
- 1, 1,
0, -1,
- 2, 0,
0, };
#define YYNPROD 9 #define YYLAST 218
int yyact[] = {
5, 7, 13, 4, 8, 9, 3, 1, 2, 0, 0, 0, 0, 12, 10, 11, 4, 0, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6,
};
int yypact[] = {
- 40, -1000, -9, -37, -1000, -40, -1000, -1000,
- 40, -40, -39, -37, -1000, -1000,
};
int yypgo[] = {
0, 7, 8, 6, 3,
};
int yyr1[] = {
0, 1, 1, 2, 2, 3, 3, 4, 4,
};
int yyr2[] = {
2, 0, 2, 3, 1, 3, 1, 3, 1,
};
int yychk[] = {
- 1000, -1, -2, -3, -4, 40, 257, 10,
43, 42, -2, -3, -4, 41, };
int yydef[] = {
1, -2, 0, 4, 6, 0, 8, 2, 0, 0, 0, 3, 5, 7,
};
int *yyxi;
/*/ /* PCYACC LALR parser driver routine – a table driven procedure */ /* for recognizing sentences of a language defined by the */ /* grammar that PCYACC analyzes. An LALR parsing table is then */ /* constructed for the grammar and the skeletal parser uses the */ /* table when performing syntactical analysis on input source */ /* programs. The actions associated with grammar rules are */ /* inserted into a switch statement for execution. */ /*/
#ifndef YYMAXDEPTH #define YYMAXDEPTH 200 #endif #ifndef YYREDMAX #define YYREDMAX 1000 #endif #define PCYYFLAG -1000 #define WAS0ERR 0 #define WAS1ERR 1 #define WAS2ERR 2 #define WAS3ERR 3 #define yyclearin pcyytoken = -1 #define yyerrok pcyyerrfl = 0 YYSTYPE yyv[YYMAXDEPTH]; /* value stack */ int pcyyerrct = 0; /* error count */ int pcyyerrfl = 0; /* error flag */ int redseq[YYREDMAX]; int redcnt = 0; int pcyytoken = -1; /* input token */
yyparse() {
int statestack[YYMAXDEPTH]; /* state stack */ int j, m; /* working index */ YYSTYPE *yypvt; int tmpstate, tmptoken, *yyps, n; YYSTYPE *yypv;
tmpstate = 0;
pcyytoken = -1;
#ifdef YYDEBUG
tmptoken = -1;
#endif
pcyyerrct = 0; pcyyerrfl = 0; yyps = &statestack[-1]; yypv = &yyv[-1];
enstack: /* push stack */ #ifdef YYDEBUG
printf("at state %d, next token %d\n", tmpstate, tmptoken);
#endif
if (++yyps - &statestack[YYMAXDEPTH] > 0) { yyerror("pcyacc internal stack overflow"); return(1); } *yyps = tmpstate; ++yypv; *yypv = yyval;
newstate:
n = yypact[tmpstate]; if (n <= PCYYFLAG) goto defaultact; /* a simple state */
if (pcyytoken < 0) if 1) < 0) pcyytoken = 0;
if ((n += pcyytoken) < 0 || n >= YYLAST) goto defaultact;
if (yychk[n=yyact[n]] == pcyytoken) { /* a shift */ #ifdef YYDEBUG
tmptoken = pcyytoken;
#endif
pcyytoken = -1; yyval = yylval; tmpstate = n; if (pcyyerrfl > 0) --pcyyerrfl; goto enstack; }
defaultact:
if 2)
if (pcyytoken < 0) if ((pcyytoken=yylex())<0) pcyytoken = 0; for (yyxi=yyexca; (*yyxi!= (-1)) || (yyxi[1]!=tmpstate); yyxi += 2); while (*(yyxi+=2) >= 0) if (*yyxi == pcyytoken) break; if ((n=yyxi[1]) < 0) { /* an accept action */ if (yytflag) { int ti; int tj; yytfilep = fopen(yytfilen, "w"); if (yytfilep == NULL) { fprintf(stderr, "Can't open t file: %s\n", yytfilen); return(0); } for (ti=redcnt-1; ti>=0; ti--) { tj = svdprd[redseq[ti]]; while (strcmp(svdnams[tj], "$EOP")) fprintf(yytfilep, "%s ", svdnams[tj++]); fprintf(yytfilep, "\n"); } fclose(yytfilep); } return (0); } }
if (n == 0) { /* error situation */ switch (pcyyerrfl) { case WAS0ERR: /* an error just occurred */ yyerror("syntax error"); yyerrlab: ++pcyyerrct; case WAS1ERR: case WAS2ERR: /* try again */ pcyyerrfl = 3; /* find a state for a legal shift action */ while (yyps >= statestack) { n = yypact[*yyps] + YYERRCODE; if (n >= 0 && n < YYLAST && yychk[yyact[n]] == YYERRCODE) { tmpstate = yyact[n]; /* simulate a shift of "error" */ goto enstack; } n = yypact[*yyps];
/* the current yyps has no shift on "error", pop stack */#ifdef YYDEBUG
printf("error: pop state %d, recover state %d\n", *yyps, yyps[-1]); #endif
- -yyps;
- -yypv;
yyabort: if (yytflag) { int ti; int tj; yytfilep = fopen(yytfilen, "w"); if (yytfilep == NULL) { fprintf(stderr, "Can't open t file: %s\n", yytfilen); return(1); } for (ti=1; ti<redcnt; ti++) { tj = svdprd[redseq[ti]]; while (strcmp(svdnams[tj], "$EOP")) fprintf(yytfilep, "%s ", svdnams[tj++]); fprintf(yytfilep, "\n"); } fclose(yytfilep); } return(1);
case WAS3ERR: /* clobber input char */#ifdef YYDEBUG
printf("error: discard token %d\n", pcyytoken);#endif
if (pcyytoken == 0) goto yyabort; /* quit */ pcyytoken = -1; goto newstate; } /* switch */ } /* if */
/* reduction, given a production n */#ifdef YYDEBUG
printf("reduce with rule %d\n", n);#endif
if (yytflag && redcnt<YYREDMAX) redseq[redcnt++] = n; yyps -= yyr2[n]; yypvt = yypv; yypv -= yyr2[n]; yyval = yypv[1]; m = n; /* find next state from goto table */ n = yyr1[n]; j = yypgo[n] + *yyps + 1; if (j>=YYLAST || yychk[ tmpstate = yyact[j] ] != -n) tmpstate =yyact[yypgo[n]];
switch (m) { /* actions associated with grammar rules */
case 2:# line 22 "test.y"
{ printf("%d\n", yypvt[-1]); } break; case 3:# line 24 "test.y"
{ yyval = yypvt[-2] + yypvt[-0]; } break; case 5:# line 27 "test.y"
{ yyval = yypvt[-2] * yypvt[-0]; } break; case 7:# line 30 "test.y"
{ yyval = yypvt[-1]; } break; } goto enstack;}