% Copyright 2012-2022, 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 <
http://www.gnu.org/licenses/>.
% assigning symbolic names to production terms (this is only a demonstration)
% no attempt is made to make this code modular or namespace safe;
% the approach is not very elegant and can stand a lot of improvement;
% it was decided against such optimization to present a more explicit demonstration
% of the procedures
\def\makesymbols{%
\ifsymdemo
\restorecslist{symbols}\yyunion
\toksa{}\toksb{}\toksc{}\toksd{}%
%\showthe\newsymswitch
\the\table
\global\newsymswitch\newsymswitch
\else
\newsymswitch{}% otherwise \yysymswitch is trying to expand the wrong names (\namepair is not present to do \csname ... )
\fi
}
% symbolic reference name parser
\newtoks\newsymswitch
\newread\symnames
\newwrite\symbolicswitch
\newif\ifsymdemo
\symdemotrue
\ifbootstrapmode
\symdemofalse
\fi
\ifsymdemo
\def\inamespace{[intermediate]}%
\let\parsernamespace\inamespace
\let\hostparsernamespace\mainnamespace % purely for testing reasons
\pinittoks{}%
\input cweb/gyytab.tex % this should be the parser that will be used later
% in this case it is just an example
\edef\tointermediateparser{%
\let\noexpand\parsernamespace\noexpand\inamespace % switch to the new namespace
\the\pinittoks % restore all the tables, tokens and constants, and stacks
\let\noexpand\getcurrentparser\noexpand\tointermediateparser
}%
\settokens % this simply assigns values to tokens where the name of each token is taken out of yytname ...
\input bo.tok % this will set up token equivalences in the namespace above ...
% those are the values gleaned during the bootstrapping stage.
% in the general case, one needs to run a bootsrapping (or similar)
% parser to extract the token information.
\optimizeall % this is necessary for correct rule listing in the output stage:
% otherwise \fgetelemof will use the current value of the \yy... token registers which
% will hold the values of the full parser that is loaded next
\newsymswitch{}%
\listrules % ... to be used while listing the rules
% note that we do not bother to set up a lexer for this parser (even though we already have one and the
% \optimizeall macro above will create a set of associative tables for it---this is merely an unwanted
% sideffect); after the rules have been listed, the intemediate parser is no longer needed.
%\showthe\newsymswitch
\def\fullnamespace{[full]}% this is the parser that parses the bison grammar from a raw
% bison file; it can play a role of the bootstrap parser for
% the grammar above, as well, since its input is a complete
% bison file; note that it cannot be a bootstrap parser for itself
% because it will reject any input that does not form a complete
% bison file; this is why a special grammar was created that includes
% only a small subset of the full set of productions (%token rules only) to
% serve as a bootstrap grammar.
%\tomainparser % this will set the value of \setflexstates, so that, if the lexer initialization
% below is omitted, the \setflexstates macro can still be used to correctly set the
% lexer states
\let\parsernamespace\fullnamespace
\pinittoks{}% %%
\input cweb/fyytab.tex
\input cweb/ltab.tex % we reinitialize the lexer out of necessity:
% \collecttokennames needs to know how to switch
% between two lexer/parser environments so both states
% have to be preserved; if one is sure that
% grammar_declarations will not used in the productions
% part of the file, this can simply be disabled
\settokens
\setflexstates % the main lexer can be reused in this case; the states still need to be set up
\input bo.tok % set up the tokens for the bison grammar parser
\newparserstate
\newlexerstate
\newlexerstateextra
%
\setnulstack{yyirulestack}%
%
\edef\tofullparser{%
\let\noexpand\parsernamespace\noexpand\fullnamespace % switch to the new namespace
\the\pinittoks % restore all the tables, tokens and constants, and stacks
\let\noexpand\getcurrentparser\noexpand\tofullparser
}%
\optimizeall
\toksa{\input bg.y}% start building the parsing command
% this has to be done carefully, since all the characters input
% from the parser file have to be `harmless', so their categories
% have to be reset; in order for the parser to be able to stop,
% appropriate command sequences would have to be inserted at the end
\toksb{\yyeof\yyeof\endparseinput\endparse
\let\yyinput\yyinputold
\undoascii
\ifyyparsefail
\errmessage{could not process symbols}%
\else
\tointermediateparser % the parsing is finished, so we have two very long strings:
% o the rules of the hosted parser ([intermediate])
% o the rules of the same parser just parsed
% these two strings are used to associate the symbolic names
% (which only exist in the second list) to the rule numbers and
% the relevant terms;
% switching the parse namespace above is done so that the term
% indices are looked up in the appropriate table
%\showthe\table
\makesymbols % list all the rules deriving explicit non-terminals
%\showthe\newsymswitch
\setexplicitinlinerules\newsymswitch % process implicit non-terminals resulting from inline actions
%\showthe\newsymswitch
\makesymrefs\newsymswitch % create the switch to be used by the parser (\yyparse)
\fi
}%
% build the command to create the symbolic name switch
\toksc{\tofullparser\basicparserinit\bisonparserinit\bisonparserdatainit
\let\yyinputold\yyinput
\let\yyinput\yyinputtrivial % a demo of a stripped down, slightly faster input routine
\doascii{11}\expandafter\yyparse}%
\edef\next{\the\toksc\the\toksa\relax\the\toksb}\next % \relax is to stop \TeX\ from trying to expand the file name further
% it is not flagged as a bad character because it is part of the epilogue
\immediate\openout\symbolicswitch=\jobname.sns
%
\edef\next{\setsncommands{\def\noexpand\symswitch\hashletter1{\harmlesscomment^^J\noexpand\ifcase\hashletter1\relax
\harmlesscomment^^J\the\setsncommands
\noexpand\else\harmlesscomment^^J%
\noexpand\fi\harmlesscomment^^J%
}\harmlesscomment^^J^^J}}\next
\edef\next{\unsetsncommands{\def\noexpand\symswitchoff\hashletter1{\harmlesscomment^^J\noexpand\ifcase\hashletter1\relax
\harmlesscomment^^J\the\unsetsncommands
\noexpand\else\harmlesscomment^^J%
\noexpand\fi\harmlesscomment^^J%
}\harmlesscomment^^J^^J}}\next
{\newlinechar=`\^^J \immediate\write\symbolicswitch{\the\setsncommands\the\unsetsncommands}}%
\immediate\closeout\symbolicswitch
\tomainparser % go back to the main parser
%
% \flex\ parser test
%
{%
\toflexreparser
\basicparserinit
\flexreparserinit
\flexreparserdatainit
\yyBEGIN{SECT2}%
\flin@ruletrue
% special status of `\yl' in \CWEB\ makes the following workaround necessary
% if the code is unsed inside a \CWEB\ file
%|@t}\expandafter\yyparse\space [a-b]*(c|d|e)?\yyeof\yyeof\endparseinput\endparse{@>|
\expandafter\yyparse\space [a-b]*(c|d|e)?\yyeof\yyeof\endparseinput\endparse
\ifyyparsefail\else
\ferrmessage{done processing flex}%
\fi
}%
%
{%
\def\flnamespace{[flex]}
\let\parsernamespace\flnamespace
\toflexparser
\basicparserinit
%\flexparserinit
\flexparserdatainit
\yylessusedtrue % TODO: put it in the \genericparser command
\let\f@nishparse\finishparse
\def\finishparse{\endinput\message{end of input}\relax\let\cleanupcs\f@nishparse}%
\def\next{%
\catcode`\\=12
\catcode`\^^J=12
\catcode`\%=12
\catcode`\^^M=12
\catcode`\{=12
\catcode`\}=12
\catcode`\#=12
\catcode`\_=12
%\yydebugmost
\expandafter\yyparse\input cweb/lo.l \cleanupcs\yyeof\yyeof\endparseinput\endparse % note that the space after the file name is necessary
\ifyyparsefail
\errmessage{stopped}%
\fi
\yydebugnone
\basicparserinit
\expandafter\yyparse\input cweb/fil.l \cleanupcs\yyeof\yyeof\endparseinput\endparse
% note that the space after the file name is necessary
}\expandafter\next % to lock the \catcode of the brace
}%
\fi