💾 Archived View for gemini.spam.works › mirrors › textfiles › programming › yaccex.asc captured on 2020-10-31 at 14:36:53.
View Raw
More Information
-=-=-=-=-=-=-
_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 ((pcyytoken=yylex()) < 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 ((n=yydef[tmpstate]) == -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;
}