ref: 02ac617541ca1a7bf82b1615fb5a58235469b5d3
dir: /appl/cmd/mash/eyaccpar/
YYFLAG: con -1000;
# parser for yacc output
YYENV: adt
{
yylval: ref YYSTYPE; # lexical value
yyval: YYSTYPE; # goto value
yyenv: YYETYPE; # useer environment
yynerrs: int; # number of errors
yyerrflag: int; # error recovery flag
yysys: Sys;
yystderr: ref Sys->FD;
};
yytokname(yyc: int): string
{
if(yyc > 0 && yyc <= len yytoknames && yytoknames[yyc-1] != nil)
return yytoknames[yyc-1];
return "<"+string yyc+">";
}
yystatname(yys: int): string
{
if(yys >= 0 && yys < len yystates && yystates[yys] != nil)
return yystates[yys];
return "<"+string yys+">\n";
}
yylex1(e: ref YYENV): int
{
c, yychar : int;
yychar = yyelex(e);
if(yychar <= 0)
c = yytok1[0];
else if(yychar < len yytok1)
c = yytok1[yychar];
else if(yychar >= YYPRIVATE && yychar < YYPRIVATE+len yytok2)
c = yytok2[yychar-YYPRIVATE];
else{
n := len yytok3;
c = 0;
for(i := 0; i < n; i+=2) {
if(yytok3[i+0] == yychar) {
c = yytok3[i+1];
break;
}
}
if(c == 0)
c = yytok2[1]; # unknown char
}
if(yydebug >= 3)
e.yysys->fprint(e.yystderr, "lex %.4ux %s\n", yychar, yytokname(c));
return c;
}
YYS: adt
{
yyv: YYSTYPE;
yys: int;
};
yyparse(): int
{
return yyeparse(nil);
}
yyeparse(e: ref YYENV): int
{
if(e == nil)
e = ref YYENV;
if(e.yylval == nil)
e.yylval = ref YYSTYPE;
if(e.yysys == nil) {
e.yysys = load Sys "$Sys";
e.yystderr = e.yysys->fildes(2);
}
yys := array[YYMAXDEPTH] of YYS;
yystate := 0;
yychar := -1;
e.yynerrs = 0;
e.yyerrflag = 0;
yyp := -1;
yyn := 0;
yystack:
for(;;){
# put a state and value onto the stack
if(yydebug >= 4)
e.yysys->fprint(e.yystderr, "char %s in %s", yytokname(yychar), yystatname(yystate));
yyp++;
if(yyp >= YYMAXDEPTH) {
yyerror(e, "yacc stack overflow");
yyn = 1;
break yystack;
}
yys[yyp].yys = yystate;
yys[yyp].yyv = e.yyval;
for(;;){
yyn = yypact[yystate];
if(yyn > YYFLAG) { # simple state
if(yychar < 0)
yychar = yylex1(e);
yyn += yychar;
if(yyn >= 0 && yyn < YYLAST) {
yyn = yyact[yyn];
if(yychk[yyn] == yychar) { # valid shift
yychar = -1;
yyp++;
if(yyp >= YYMAXDEPTH) {
yyerror(e, "yacc stack overflow");
yyn = 1;
break yystack;
}
yystate = yyn;
yys[yyp].yys = yystate;
yys[yyp].yyv = *e.yylval;
if(e.yyerrflag > 0)
e.yyerrflag--;
if(yydebug >= 4)
e.yysys->fprint(e.yystderr, "char %s in %s", yytokname(yychar), yystatname(yystate));
continue;
}
}
}
# default state action
yyn = yydef[yystate];
if(yyn == -2) {
if(yychar < 0)
yychar = yylex1(e);
# look through exception table
for(yyxi:=0;; yyxi+=2)
if(yyexca[yyxi] == -1 && yyexca[yyxi+1] == yystate)
break;
for(yyxi += 2;; yyxi += 2) {
yyn = yyexca[yyxi];
if(yyn < 0 || yyn == yychar)
break;
}
yyn = yyexca[yyxi+1];
if(yyn < 0){
yyn = 0;
break yystack;
}
}
if(yyn != 0)
break;
# error ... attempt to resume parsing
if(e.yyerrflag == 0) { # brand new error
yyerror(e, "syntax error");
e.yynerrs++;
if(yydebug >= 1) {
e.yysys->fprint(e.yystderr, "%s", yystatname(yystate));
e.yysys->fprint(e.yystderr, "saw %s\n", yytokname(yychar));
}
}
if(e.yyerrflag != 3) { # incompletely recovered error ... try again
e.yyerrflag = 3;
# find a state where "error" is a legal shift action
while(yyp >= 0) {
yyn = yypact[yys[yyp].yys] + YYERRCODE;
if(yyn >= 0 && yyn < YYLAST) {
yystate = yyact[yyn]; # simulate a shift of "error"
if(yychk[yystate] == YYERRCODE) {
yychar = -1;
continue yystack;
}
}
# the current yyp has no shift on "error", pop stack
if(yydebug >= 2)
e.yysys->fprint(e.yystderr, "error recovery pops state %d, uncovers %d\n",
yys[yyp].yys, yys[yyp-1].yys );
yyp--;
}
# there is no state on the stack with an error shift ... abort
yyn = 1;
break yystack;
}
# no shift yet; clobber input char
if(yydebug >= 2)
e.yysys->fprint(e.yystderr, "error recovery discards %s\n", yytokname(yychar));
if(yychar == YYEOFCODE) {
yyn = 1;
break yystack;
}
yychar = -1;
# try again in the same state
}
# reduction by production yyn
if(yydebug >= 2)
e.yysys->fprint(e.yystderr, "reduce %d in:\n\t%s", yyn, yystatname(yystate));
yypt := yyp;
yyp -= yyr2[yyn];
# yyval = yys[yyp+1].yyv;
yym := yyn;
# consult goto table to find next state
yyn = yyr1[yyn];
yyg := yypgo[yyn];
yyj := yyg + yys[yyp].yys + 1;
if(yyj >= YYLAST || yychk[yystate=yyact[yyj]] != -yyn)
yystate = yyact[yyg];
case yym {
$A
}
}
return yyn;
}