diff options
Diffstat (limited to 'appl/cmd/mash/eyaccpar')
| -rw-r--r-- | appl/cmd/mash/eyaccpar | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/appl/cmd/mash/eyaccpar b/appl/cmd/mash/eyaccpar new file mode 100644 index 00000000..2bbb0355 --- /dev/null +++ b/appl/cmd/mash/eyaccpar @@ -0,0 +1,223 @@ +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; +} |
