% 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 . % indexing macros % set up the list of unindexable terms \newwrite\gindex % macros to determine if the current term is indexable \newif\ifindexverbose \def\yyifindexable#1{% {% \def\n@xt{#1}% \expandafter\s@tindexable\unindexable\relax\end % the \relax is to preserve the braces % in the last list element }% } \def\s@tindexable#1#2\end{% {% \def\next{#1}% \ifx\next\n@xt % match found, stop \yybreak{\aftergroup\s@t@ndexable}% \else \yybreak{% \yystringempty{#2}{% unindexable sequence list has been exhausted, stop \aftergroup\s@t@nd@xable }{% no match yet, continue \aftergroup\s@tindexable }% }% \yycontinue }% #2\end } \def\s@t@ndexable#1\end{\aftergroup\yysecondoftwo} \def\s@t@nd@xable#1\end{\aftergroup\yyfirstoftwo} \def\makeunindexable#1{% \expandafter\m@keunindexable\expandafter{\unindexable}{#1}% } \def\m@keunindexable#1#2{% \def\unindexable{#1#2}% } \def\makeunindexablex#1{% {\edef\unindexable{#1}\expandafter}\expandafter\makeunindexable\expandafter{\unindexable}% } % \Cee\ index entry (produced by \CWEAVE\ and typeset directly from the file) \def\Ii#1, #2.{% \makeoneindexentry{#1}{#1}{#2}{\setxreflistplain}{\filterxrefsplain}% } % other language index entries (produced by \GI, \FI, and \HI macros) % the standard reference format (no page number references) \def\Ji#1#2, #3.{% #1 is the `visible key', #2 and #3 are similar to #1 and #2 in \I above \makeoneindexentry{#1}{#2}{#3}{\setxreflistplain}{\filterxrefsplain}% }% % the `fine' reference format \def\Fi#1#2, #3.{% #1 is the `visible key', #2 and #3 are similar to #1 and #2 in \I above \makeoneindexentry{#1}{#2}{#3}{\setxreflist}{\filterxrefs}% }% % special index entries: redirects, etc. (generated by bindx.pl) \def\Jk#1#2, #3.{% \makeoneindexentry{#1}{#2}{#3}{\yyid}{\eatone}% }% \def\makeoneindexentry#1#2#3#4#5{% #1 is the `visible key' % #2 is the term (including typesetting) % #3 is the list of references % #4 is the command to process #3 % #5 is the command to filter and process #3 \yyifindexable{#1}{\oneindexentry{#2}{#3}{#4}}{% \ifindexverbose{\toksa{#1}\message{filtering term: \the\toksa}}\fi \oneindexentryfiltered{#2}{#3}{#5}% }% } % insert the original control sequence name after the `graphic' version (\thisnamex % is set by yytexlex.sty macros \def\defypostambleshowcs{{ \rm(}\hbox{\sixpoint\tt\char`\\}\.{\thisnamex}{\rm)}}% % let the author set the format for a cross reference list. \def\setxreflistplain#1{% \ifacro\pdfnote#1.\else#1.\fi } \def\oneindexentry#1#2#3{% \checkforninecs#1\9\end{% \the\toksg\toksg{}% set the index section header \let\defypreamble\empty \let\defypostamble\defypostambleshowcs \hangindent\inxhangindent\noindent\strut#1:% \hskip0pt plus2em\penalty1000\hskip0pt plus-2em\relax\kern\inxaiskip #3{#2}% \par }{% \checkforthree#1\end{% \toksg{#1}% }{% \the\toksg\toksg{}% set the index section header \let\defypreamble\empty \let\defypostamble\defypostambleshowcs \hangindent\inxhangindent\noindent\strut\ninercs#1:% \hskip0pt plus2em\penalty1000\hskip0pt plus-2em\relax\kern\inxaiskip #3{#2}% \par }% }% } \def\filterxrefsplain#1{\setxrefsplain{\f@lterdefsplain}{#1}} \def\filterxrefs#1{\setxrefs{\f@lterdefs}{#1}} \def\oneindexentryfiltered#1#2#3{% \the\toksg\toksg{}% set the index section header \let\defypreamble\empty \let\defypostamble\defypostambleshowcs \hangindent\inxhangindent\noindent\strut#1:% \hskip0pt plus2em\penalty1000\hskip0pt plus-2em\relax\kern\inxaiskip #3{#2}% \par } \def\checkforninecs#1\9#2\end{% \yystringempty{#2}{\yyfirstoftwo}{\yysecondoftwo}% } \def\checkforthree#1#2#3\end{% \yystringempty{#3}{\yyfirstoftwo}{\yysecondoftwo}% } % if the term is unindexable, only collect the definitions (i.e. references enclosed in \[ and \]) \def\filterdefs#1#2{% #1{}{}, #2, \[]{}% the last empty braces are not necessary but this way % both \f@lterdefs and \f@lterdefsplain can be defined } \def\f@lterdefsplain#1#2#3, \[#4]{% \yystringempty{#4}{ {#1}{#2}}{% \yystringempty{#1}{% \f@lterdefsplain{\[#4]}{#2#3}% }{% \f@lterdefsplain{#1, \[#4]}{#2#3}% }% }% } \def\f@lterdefs#1#2#3, \[#4]#5{% \yystringempty{#4}{ {#1}{#2}}{% \yystringempty{#1}{% \f@lterdefs{\[#4]{#5}}{#2#3}% }{% \f@lterdefs{#1, \[#4]{#5}}{#2#3}% }% }% } \def\setxrefs#1#2{% typeset filtered references (with page references) \expandafter\s@txrefs\romannumeral0\filterdefs{#1}{#2}% } \def\s@txrefs#1#2{% \yystringempty{#1}{% several refs.% }{% \setxreflist{#1}% \yystringempty{#2}{}{, other refs.}% }% } \def\setxrefsplain#1#2{% typeset filtered references (without page references) \expandafter\s@txrefsplain\romannumeral0\filterdefs{#1}{#2}% } \def\s@txrefsplain#1#2{% \yystringempty{#1}{% several refs.% }{% \ifacro\pdfnote#1.\else#1.\fi \yystringempty{#2}{}{, other refs.}% }% } \def\setxreflist#1{% \yystringempty{#1}{}{% \grabfinexrefs{}, #1, {}{}% }% } \def\grabfinexrefs#1, #2#3#{% collect (and process) fine references (i.e. references like lnnnr{p1, p2, ... } \yystringempty{#2#3}{% this is the last reference, clean up (the last empty group is left unchanged) \expandafter\relax\eatacomma#1% }{% \ifcat\noexpand#20% this is a bare number \yybreak{\consumeonexref{{}{}{#1}}{#2#3}}% \else % this is a qualified number \yybreak{\stripxrefdelims{{#2}{#1}}{}#3}% \yycontinue }% } \def\eatacomma, {} % get the right delimeter; we assume that at least one token is present \def\stripxrefdelims#1#2#3{% \ifnum`#3<`0 \yybreak{\consumeonexref{{#3}#1}{#2}}% this is a delimeter \else \ifnum`#3>`9 \yybreak@{\consumeonexref{{#3}#1}{#2}}% this is a delimeter \else % `0<=`#4<=`9 \yybreak@{\stripxrefdelims{#1}{#2#3}}% keep looking for the next digit \fi \yycontinue } \ifx\consumeonexref\UNDEFINED \def\consumeonexref#1#2#3{% #1 is the accumulated references % #2 is the section number % #3 is the list of pages \addnewpair#1{#2}% } \fi % ignore paging information \def\addnewpair#1#2#3#4{% #1 is the right delimeter % #2 is the left delimeter % #3 is the list of references % #4 is the section number \grabfinexrefs{#3, #2\compoundlink{#4}{#4}#1}% } \def\compoundlink#1#2{% \ifacro \pdflink{#1}{#2}% \else #2% \fi } \def\pagelink#1{% \ifacro \pdfpagelink{#1}% use the section number \else #1% \fi } % indexing macros for grammar terms \def\termidstring#1{% processed name in italics \numberstocharsandspaces#1\end \let\optstrextra\optstrextraesc \expandafter\nameproc\expandafter{\the\toksa}\with\parsebin \def\idxentry{{\it\the\toksa}}% }% \def\termvstring#1{% processed name in typewriter style \numberstochars#1\end \let\optstrextra\optstrextraesc \expandafter\nameproc\expandafter{\the\toksa}\with\parsebin \def\idxentry{{\tt\def\_{\char`\_}\the\toksa}}% }% \def\termttstring#1{% straightforward typewriter text \numberstocharsandspaces#1\end \def\idxentry{{\tt\the\toksa}}% }% \def\termhostidstring#1{% processed name in italics (using the host name parser) \numberstocharsandspaces#1\end \let\optstrextra\optstrextraesc {% \expandafter\let\expandafter\tosmallparser \csname to\stripbrackets\hostparsernamespace parser\endcsname \expandafter\nameproc\expandafter{\the\toksa}\with\parsebin \aftergroup\toksa \expandafter }\expandafter{\the\toksa}% \def\idxentry{{\it\the\toksa}}% }% \def\termhostvstring#1{% processed name in typewriter style (using the host name parser) \numberstocharsandspaces#1\end \let\optstrextra\optstrextraesc {% \expandafter\let\expandafter\tosmallparser \csname to\stripbrackets\hostparsernamespace parser\endcsname \expandafter\nameproc\expandafter{\the\toksa}\with\parsebin \aftergroup\toksa \expandafter }\expandafter{\the\toksa}% \def\idxentry{{\tt\def\_{\char`\_}\the\toksa}}% }% \def\termostring#1{% options (e.g. \flex\ and \bison\) \numberstocharsandspaces#1\end \def\idxentry{{$\langle$\bf\the\toksa$\rangle$}}% }% \def\termfsrestring#1{% flex regular expression definition names \numberstocharsandspaces#1\end \let\optstrextra\optstrextraesc \expandafter\nameproc\expandafter{\the\toksa}\with\parsebin \def\idxentry{{\def\_{\char`\_}\flexrendisplay{\the\toksa}}}% }% \def\termfsopstring#1{% flex option names \numberstocharsandspaces#1\end \let\optstrextra\optstrextraesc \expandafter\nameproc\expandafter{\the\toksa}\with\parsebin \def\idxentry{{\def\_{\char`\_}\hbox{\tt$\langle$\the\toksa$\rangle_{\rm f}$}}}% }% \def\termfsscstring#1{% flex sate names \numberstocharsandspaces#1\end \let\optstrextra\optstrextraesc \expandafter\nameproc\expandafter{\the\toksa}\with\parsebin \def\idxentry{{\def\_{\char`\_}\hbox{\flexsnstyle{\the\toksa}}}}% }% \def\termstring#1{% \numberstocharsandspaces#1\end \let\optstrextra\optstrextraesc \expandafter\nameproc\expandafter{\the\toksa}\with\parsebin \def\idxentry{{\tt"\the\toksa"}}% }% \def\termexception#1{% special names \numberstocharsandspaces#1\end \toksc\toksa \expandafter\nameproc\expandafter{\the\toksa}\with\parsebin \ifyyparsefail \expandafter\ifx\csname\prettynamecs\hostparsernamespace{\the\toksa}\endcsname\relax \errmessage{The name \the\toksc\space is exceptional but is not defined.}% \else \def\idxentry{{\it\csname\prettynamecs\hostparsernamespace{\the\toksa}\endcsname{#1}}}% \fi \else \errmessage{The name \the\toksc\space is not exceptional.}% \fi }% % \TeX\ conrol sequence output \def\texcsstring#1{% \numberstocharsandspaces#1\end \def\idxentry{% \let\texnspace\hostparsernamespace \def\getcescape{% an \ seen is really an \, and will not go through C string processing \def\next{escape}% \switchon\next\in\currentstate }% \termindexfalse\expandafter\inlineTeXx\expandafter{\expandafter/\the\toksa}% }% }% \def\termtrivial#1{% trivial index entry for debugging purposes % can also be used as a starting point for other index processors \def\idxentry{% {\rm index entry goes here}% }% }% % the raw/direct macros below should be used sparingly because they potentially introduce % style inconsistencies while outputting index terms; a special scheme can be designed to counter % that ... or one can just be careful; in addition, \termdirect relies on the exact number of expansions % (2) undergone by the entry's contents; % of the two options, \termraw is probably preferable as it does not pass any volatile information % (such as expandable sequences) in the index entries and thus allows much more elaborate and % safe setup of index terms; the only advantage of the \termdirect variation is the lack of global % assignments (the \termraw changes the \indexterms array); indices by their nature are global % so this should be a secondary consideration in the majority of cases. \def\termdirect#1{% \def\idxentry{% {\t@rmdirect#1}% }% }% \def\t@rmdirect#1\end\toksa#2\eatone{#2} \let\vend\relax % the delimeter to let the indexing script know that this is a raw entry % here is an example of the \termdirect macros in action: % % the entry setup below is a bit elaborate since parts of the entry must be passed in a safe way % in case it contains dangerous characters like _ % \toksa{\noexpand\tt{\noexpand\rm(}#1{\noexpand\rm)}\noexpand\charstocharsx#2\end}% % the \noexpand's above are necessary to block the final expansion by \write % the assignment below would also work; note the '0 ' which is required to stop the expansion % of \romannumeral which is part of \charstonumberse; in this case \vend can be left undefined % \toksa{\end0 \noexpand\noexpand\noexpand\vend(#1)#2\noexpand\noexpand\noexpand\vend\eatone}% % the setup above works with the following indexing command %\ridxentry{\termdirect}{\the\toksa}{#2}% \def\termraw#1{% raw entry, shows terms saved in a global array, #1 is the index into the array \numberstocharsandspaces#1\end \def\idxentry{% {\let\parsernamespace\empty\getmidstackcs\indexterms{\the\toksa}}% }% }% \setnulstack{indexterms} % the array for the terms processed by \termraw \expandafter\def\csname acharswitch:index\endcsname{% correct reserved \TeX\ characters a la CWEB verbatim %$\%\\ % unaffected %\#\ % these never appear _{% \yybyte\expandafter{\csname \the\yybyte\endcsname}% \expandafter\yycp@\expandafter`\the\yybyte\relax \mkpurebyte \yyreturn } }% \expandafter\setspecialcharsfrom\csname acharswitch:index\endcsname \def\texlexerindex{% now that all character codes are 12 \let\default\yygetchar \let\next\yycp@ \ifnum\yycp@>"3F % \ifnum\yycp@<"5B % an uppercase letter or @ \def\next{letter}% \fi \fi \ifnum\yycp@>"60 % \ifnum\yycp@<"7B % \def\next{letter}% \fi \fi \switchonwithtype\next\in\currentstate }% \def\indexseparator#1#2{% generic separator \vskip.5\baselineskip \centerline{\dinkus}% \vskip.5\baselineskip } \def\indexseparator#1#2{% \vskip.3\baselineskip \centerline{% \toksa\expandafter\expandafter\expandafter {\expandafter\yyfirstofthree\romannumeral0\csname index domain translation [#1]\endcsname}% \toksb\expandafter\expandafter\expandafter {\expandafter\yysecondofthree\romannumeral0\csname index domain translation [#1]\endcsname}% \toksc\expandafter\expandafter\expandafter {\expandafter\yythirdofthree\romannumeral0\csname index domain translation [#1]\endcsname}% \the\toksc \edef\next{\write\cont{%\noexpand\noexpand\noexpand\eatone{\noexpand\meaning\noexpand\ZZ}% \noexpand\noexpand\noexpand\YY{\the\toksa}{2}{\secno}% write to contents file {\noexpand\the\pageno}{\the\toksb}}}\next % \YY{title}{depth}{sec}{page}{ss} }% \vskip.3\baselineskip } \expandafter\def\csname index domain translation [F]\endcsname{{\noexpand\flex\ index}{flex index}{F{\sc LEX INDEX}}} \expandafter\def\csname index domain translation [T]\endcsname{{\noexpand\TeX\ index}{TeX index}{\TeX\ {\sc INDEX}}} \def\indexsection#1{% \vskip.3\baselineskip \penalty-1000 \hbox to \hsize{\strut\ssfbn #1\ \cdotfill}% \penalty10000 \vskip.2\baselineskip } \def\9#1{% \indexs@ction#1\end } \def\indexs@ction#1#2\end{ \indexsection{\uppercase{#1}}% } \def\otherlangindexseparator{% \enddoublecols \vskip.8\baselineskip \centerline{\otherlangindexheader \edef\next{\write\cont{%\noexpand\noexpand\noexpand\eatone{\noexpand\meaning\noexpand\ZZ}% \noexpand\noexpand\noexpand\YY{\noexpand\noexpand\noexpand\bison\ index}{2}{\secno}% write to contents file {\noexpand\the\pageno}{bison Index}}}\next % \ZZ{title}{depth}{sec}{page}{ss} }% \vskip.5\baselineskip \begindoublecols } \def\otherlangindexheader{% B{\sc ISON}, F{\sc LEX, AND} \TeX\ {\sc INDICES}% } %\def\otherlangindexseparator{} % general index entries (generated by bindx.pl) \def\GI#1#2#3#4.{% raw index entries (standard format, with no page references) {% \edef\hostparsernamespace{\yysecondoftwo#1}% \edef\currentrulecontext{\yyfirstoftwo#1}% \toksa{}\numberstocharsandspaces#3\end \edef\indexkeyseq{\the\toksa}% \toksa{}#2{#3}% \expandafter\Ji\expandafter{\indexkeyseq}{\idxentry}#4.% }% }% \def\FI#1#2#3#4.{% raw index entries (fine format) {% \edef\hostparsernamespace{\yysecondoftwo#1}% \edef\currentrulecontext{\yyfirstoftwo#1}% \toksa{}\numberstocharsandspaces#3\end \edef\indexkeyseq{\the\toksa}% \toksa{}#2{#3}% \expandafter\Fi\expandafter{\indexkeyseq}{\idxentry}#4.% }% }% \def\HI#1#2#3#4{% special raw index entries {% \def\hostparsernamespace{#2}% \let\defypreamble\empty \let\defypostamble\empty \toksa{}\numberstocharsandspaces#4\end \edef\indexkeyseq{\the\toksa}% \toksa{}#3{#4}% \expandafter\Jk\expandafter{\indexkeyseq}{\idxentry}, see {\tt\hbox{\sixpoint\tt\char`\\}\indexkeyseq}.% }% }% % reference styles (ordinary terms are set in roman face) \def\[#1]{{\it#1}} % term definitions (such as lhs in productions) \def\(#1){$\underline{#1}$} % declarations (such as token declarations), underlined index item \def\(#1){{\bf #1}} % declarations, an alternative to the above \def\e#1e{#1{\sevenpoint$^\circ\!$}} % terms in examples \def\f#1f{{\it#1\/\kern.2ex}${}^\circ\!$} % lhs in examples (italic correction does not seem to be enough) \def\g#1g{$\underline{#1}^\circ\!$} % declarations in examples \def\g#1g{{\bf #1}$^\circ\!$} % declarations in examples, an alternative to the above \def\inxhangindent{1em} \def\inxaiskip{.5em} \def\inxicgap{5pt} \ifx\unindexable\UNDEFINED \def\unindexable{{$\TeXx$}{$\TeXa$}{$\TeXb$}{$\TeXf$}{$\TeXao$}{$\TeXfo$}{$\BZ$}}% \else \expandafter\def\expandafter\unindexable\expandafter {\unindexable{$\TeXx$}{$\TeXa$}{$\TeXb$}{$\TeXf$}{$\TeXao$}{$\TeXfo$}{$\BZ$}}% \fi \def\idxsafe{% redefine some control sequences to behave safely in the index \def\TeXx{\hbox{\let\_\UL\tt\TeX\_}} \def\TeXa{\hbox{\tt\TeX\rm(a)}} \def\TeXb{\hbox{\tt\TeX\rm(b)}} \def\TeXf{\hbox{\tt\TeX\rm(f)}} \def\TeXao{\hbox{\tt\TeX\rm(ao)}} \def\TeXfo{\hbox{\tt\TeX\rm(fo)}} \def\BZ{\hbox{\tt BZ}} } \def\inxmod{% new indexing macro \closeout\exampletable \termindexfalse \idxsafe \closeout\gindex \message{Index:} \medskip \eightpoint\raggedright \emergencystretch=.1em % for especially tight cases \fnotesstart=2 \fnotesspan=1 \noofcolumns=3 \icgap=\inxicgap% \linecount=3 \setmcparams \dsskip=0pt% \adjskip=0pt plus 9pt% % \TeX\ conrol sequence output \expandafter\let\expandafter\acharswitch\csname acharswitch:index\endcsname \let\texlexer\texlexerindex \let\*=\lapstar \let\I\Ii % make \CWEAVE\ generated entries typeset in our style \begindoublecols \readindex \readgindex \write\cont{}% ensure that the contents file isn't empty \write\cont{\catcode `\noexpand\@=12\relax}% \makeatother \closeout\cont % the contents information has been fully gathered \enddoublecols } \newread\trygindex \def\readgindex{% \openin\trygindex=\jobname.gdy \ifeof\trygindex \else \closein\trygindex \otherlangindexseparator \input \jobname.gdy \fi }