% Copyright 2012-2024, Alexander Shibakov
% This file is part of SPLinT
%
% SPLinT is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% SPLinT is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with SPLinT. If not, see .
% global variables: current token, state, variable to store various table indices
\def\yyparse{%
\yylen=\z@ %
\yyinitstack\yyssa % state stack
\yyinitstack\yyvsa % data stack
\yystate=\z@ %
\yychar=\YYEMPTY\relax
\yylval{}% bogus value
\yynewstate
}
\newif\iftracestacks
\newif\iftraceparserstates
\newif\iftracerules
\def\yynewstate{%
\ifnum\yystate=\YYFINAL\relax
\yybreak\yypaccept
\else
\yypushr\yystate\on\yyssa
{%
\iftraceparserstates
\ferrmessage{^^Jstate \the\yystate\iftracestacks, \fi}%
\fi
\iftracestacks
\iftraceparserstates
\else
\ferrmessage{^^J}%
\fi
\showstack\yyssa\ferrmessage{state stack: \stackcs^^J}%
\fi
}%
\yybreak\yybackup
\yycontinue
}
\def\yybackup{%
\yyn=\fgetelemof{yypact}\at\yystate\relax
% yyn = yypact[yystate]
\ifnum\yyn=\YYPACTNINF\relax % if (yyn == YYPACT_NINF) (if(yypact_value_is_default(yyn)))
\yybreak\yydefault % goto yydefault
\else % else
\ifnum\yychar=\YYEMPTY\relax % if (yychar == YYEMPTY)
% ... ... if desired, this is where `hidden context' may be inserted
% ... ... for example:
% ... ... \gethidden\yychar
% ... ... \ifnum\yychar=\YYEMPTY\relax
% ... ... \yybreak@@\yylex
% ... ... \else
% ... ... \yybreak@@\yyparsetail
% ... ... \fi
% ... ... here \gethidden#1 is a hidden context-extracting macro that
% ... ... takes a token value from a special stream and puts it in #1
% ... ... filling this special stream should be done by the lexer,
% ... ... respecting any state changes required.
\yybreak@\yylex % yychar = YYLEX
\else
\yybreak@\yyparsetail
\fi
\yycontinue
}
\newif\iftracelookahead
\def\yyparsetail{% this is where the lexer returns
\ifnum\yychar>\z@\relax % if (yychar > YYEOF)
\yytoken=\fgetelemof{yytranslate}\at\yychar\relax
\iftracelookahead
\derrmessage{lookahead: \tokname, value: \the\yylval^^J}%
\fi
% yytoken = yytranslate[yychar]
\else % else
\yychar=\z@\relax % yychar = yytoken = YYEOF
\yytoken=\YYSYMBOLxYYEOF\relax
\fi% valid lookahead token
\advance\yyn by\yytoken % yyn = yypact[yystate] + yytoken
\ifnum\yyn<\z@
\yybreak\yydefault
\else
\ifnum\yyn>\YYLAST\relax
\yybreak@\yydefault
\else
\ifnum\fgetelemof{yycheck}\at\yyn=\yytoken
% if (yyn >= 0 && yyn <= YYLAST &&
% yytoken == yycheck[yyn])
\yyn=\fgetelemof{yytable}\at\yyn\relax
% yyn = yytable[ yypact[yystate] + yytoken ]
\ifnum\yyn>\z@ % if (yyn > 0) ...shift
\iftraceactions
\derrmessage{shifting \tokname^^J}%
\fi
\yystate=\yyn % yystate = yytable[ yypact[yystate] + yytoken ]
\yychar=\YYEMPTY\relax
% yychar = YYEMPTY ...drop
% ...the
% ...shifted token
\yypushr\yylval\on\yyvsa
% ...shift the value
% *++yyvsa = yylval
\yybreak@@@\yynewstate % new state will be shifted
\else % ...if (yyn < 0)
\iffalse % if (yytable_value_is_error(yyn))
% /* #define yytable_value_is_error(Yytable_value) YYID (0) */
\yybreak@@@@\yyerr
\else
\yyn=-\yyn
\yybreak@@@@\yyreduce
\fi
\fi
\else
\yybreak@@\yydefault% goto yydefault
\fi
\fi
\yycontinue
}
\newif\iftraceactions
\def\yydefault{%
\yyn=\fgetelemof{yydefact}\at\yystate\relax
% yyn = yydefact[yystate]
\iftraceactions
\ferrmessage{default action^^J}%
\fi
\ifnum\yyn=\z@
\xskiptofi\yyerr
\else
\xskiptofi\yyreduce % if (yyn != 0) goto yyreduce
\fi
}
\def\yyreduce{%
\yylen=\fgetelemof{yyrtwo}\at\yyn\relax
\preparevaluestack
\yyaction % value
%
\yypopstack\yyvsa\by\yylen
\yypopstack\yyssa\by\yylen % YYPOPSTACK(yylen)
\yypushr\yyval\on\yyvsa
% ...push the computed
% ...value on the value stack
%
\yyn=\fgetelemof{yyrone}\at\yyn\relax
% yyn = yyr1[yyn]
%
\yylen\yyn %
\advance\yylen-\YYNTOKENS\relax % ...reuse yylen
\yystate=\fgetelemof{yypgoto}\at\yylen\relax
% yystate = yypgoto[ yyn - YYNTOKENS ]
\yyreadstackr\yyssa\at\z@\to\yyilen %
% ...reuse yyilen
\advance\yystate\yyilen % yystate = yypgoto[ yyn - YYNTOKENS ] + yyssa[0]
%
\ifnum\yystate<\z@ % if (yystate < 0)
\yystate=\fgetelemof{yydefgoto}\at\yylen\relax
% yystate = yydefgoto[ yyn - YYNTOKENS ]
\else % else
\ifnum\yystate>\YYLAST\relax % ...
\yystate=\fgetelemof{yydefgoto}\at\yylen\relax
\else
\ifnum\fgetelemof{yycheck}\at\yystate=\yyilen
% if (yystate >= 0 && yystate <= YYLAST && yyssa[0] == yycheck[yystate])
%
\yystate=\fgetelemof{yytable}\at\yystate\relax
% yystate = yytable[yystate]
\else
\yystate=\fgetelemof{yydefgoto}\at\yylen\relax
\fi
\fi
\fi
\yylen=\z@
\yynewstate
}
\def\preparevaluestack{%
\iftracerules
\ferrmessage{^^Jreducing (rule \the\yyn)}\printrule{\yyn}%
\fi
{%
\iftracestacks
\iftracerules
\else
\ferrmessage{^^J}%
\fi
\showstack\yyssa
\ferrmessage{stack: \stackcs^^Jpopping \the\yylen^^J}%
\fi
}%
\yyilen=\fgetelemof{yyrthree}\at\yyn\relax
\ifnum\yyilen>\z@ % this is an inline rule
\ifnum\yylen>\z@
\errmessage{an inline rule with a nontrivial left hand side: rule \the\yyn}%
\fi
\else
\yyilen\yylen
\fi
\ifnum\yyilen>\z@
\yypeekvstack\yyvsa\upto\yyilen % see yymisc.sty for the definition
\yyval\csname $$'1\endcsname % $$ = $1
\else
\yypeekustack\yyvsa
\fi
}
\newif\iftraceparseresults
\def\yypaccept{%
\iftraceparseresults
\ferrmessage{accepted^^J}%
\fi
\finishparse
}
% most of the error processing mechanisms supplied by the `genuine' \bison\ parsers
% have been omitted for simplicity
\def\yyerr{%
\iftraceparseresults
\ferrmessage{(parse) error^^J}%
\fi
\cleanupparse
}
% no symbolic name support by default
\let\yysymswitch\eatone
\let\yysymcleanup\eatone
% parser specific output message: defines the current token name to output
\def\derrmessage#1{{%
\newlinechar=`\^^J%
\edef\tokname{\fgetelemof{yytname}\at\yytoken}%
\ferrmessage{#1}%
}}
% these macros reuse dedicated counters ... locally
\def\printrule#1{{% some values are computed several times to save on register assignments
% this has more to do with not polluting the namespace than speed
\edef\ruleline{\space\space\space\fgetelemof{yytname}\at{\fgetelemof{yyrone}\at{#1}}:}%
\yyn=\fgetelemof{yyprhs}\at{#1}
\ifnum\fgetelemof{yyrhs}\at\yyn>\m@ne
\loop
\edef\ruleline{\ruleline\space\fgetelemof{yytname}\at{\fgetelemof{yyrhs}\at\yyn}}%
\advance\yyn\@ne
\ifnum\fgetelemof{yyrhs}\at\yyn>\m@ne
\repeat
\else
\edef\ruleline{\ruleline\space}%
\fi
\ferrmessage{ -->\ruleline}%
}}
% print the rule without using yyprhs and yyrhs (necessary if using
% bison version 3.0 or above)
\def\printrule#1{{%
\edef\ruleline{\space\space\space\fgetelemof{yytname}\at{\fgetelemof{yyrone}\at{#1}}:}%
\ifnum\yylen>\z@
\yypeeksstack\yyssa\upto\yylen\withprefix{\appendtoruleline}%
\else
\edef\ruleline{\ruleline\space}%
\fi
\ferrmessage{ -->\ruleline}%
}}
\def\appendtoruleline#1{%
\edef\ruleline{\ruleline\space\fgetelemof{yytname}\at{\fgetelemof{yystos}\at{#1}}}%
}
% the two control sequences below are replaced in yyfaststack.sty
% to match the appropriate stack implementation
\def\showstacksym#1{%
\edef\stackcs{\stackcs^^J \space\space\fgetelemof{yytname}\at{\fgetelemof{yystos}\at{#1}}}%
}
\def\showstack#1{%
\def\stackcs{}%
\let\sts\showstacksym
#1%
}
\newif\iftracediscardedinput
\long\def\cleanupparse#1\endparse{%
\iftracediscardedinput
{\toksa{#1}\immediate\write16{discarding the rest of the input: \the\toksa}}%
\fi
\yyerror
}
\newif\ifyyparsefail
\def\yyerror{\yyparsefailtrue}
\long\def\finishparse#1\endparseinput{%
\yystringempty{#1}{}{\yylval{#1}\immediate\write16{skipping: \the\yylval}}%
}
\let\endparse\relax
\let\endparseinput\relax
% action code
\def\yyaction{%
\yysymswitch{\yyn}% setting symbol names
% the big switch, set \yyval
\yybigswitch{\yyn}%
%
\yysymcleanup{\yyn}% removing symbol names from the namespace
}
% common parser initializations; note that some initializations (such as resetting the data
% and state stacks) are done at parser startup (see the definition of \yyparse)
\def\basicparserinit{%
\yytext{}%
\yysubtext{}%
\yytext@{}%
\yytextpure{}%
\yytextseenpure{}%
\yytextseen{}%
\yytext@seen{}%
\yybyte{}%
\initlist\yystash
\appendtolist\yystash{}% increment the list counter
\initlist\yyformat
\appendtolist\yyformat{}% increment the list counter
\yyfutureyytext{}%
\yyinitstack\yystatestack
\yyfmark=\z@
\yysmark=\z@
\yyfmarklast=\z@
\yyfmark@accept=\z@
\formatmarker=\z@
\yysmarklast=\z@
\yysmark@accept=\z@
\stashmarker=\z@
\yytextbackupfalse
\yyg@yyinit=\z@
\yyg@yystart=\z@
\YYATBOL=\@ne
\yyparsefailfalse
\YYEOBLASTMATCHtrue
}