% 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 }