% 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 . % prototypes of all the macros produced by the parser % we will follow the convention: 12string is a string of category 12 characters and spaces, tex_string: a string % of TeX tokens; sptr is a pointer to the stash stream, fptr is a pointer to the format stream \def\yyuniontag{\yyunion} \def\parserstrictnamespace{parser-strict} \def\parserprototypesnamespace{parser-strict:headers} \def\parserdebugnamespace{parser-debug} \def\yyunion{\currentyyunionnamespace} \def\currentyyunionnamespace{generic} % types inserted by the input routines: these should not be tampered with randomly % therefore they are not included in the yyunion list and only defined once below and redefined later % permanently \def\cwebstreamchars{% characters seen by the input routine \|\`\\\{\}\~\ \_\&\^\$\#\n% the last one is inserted by the preprocessing scripts } % insidemost (level 0) \long\def\stashed#1{} % stashed material (usually \Cee\ code) :: \stashed{tex_string} \long\def\sflush#1#2{} % stash flushing marker :: \sflush{tex_string} \def\format#1{} % format material triggered by braces and the start of production :: \format{tex_string} \def\formatlocal#1{} % format material triggered by every term :: \formatlocal{tex_string} % level 1---atoms minimally processed by the parser % types returned by the lexer; the integer type (hex vs. decimal) is determined at the lexer level so % these are tagged by the lexer as well \defp\anint#1#2#3{} % INT :: \anint{digits}{fptr}{sptr} \defp\hexint#1#2#3{} % INT :: \hexint{0[xX][0-9A-F]+}{fptr}{sptr} % types inserted by the parser (* marks the types that are essentially returned by the lexer % and `tagged' by the parser) \defp\idit#1#2#3#4{} % *ID :: \idit{12string}{tex_string}{fptr}{sptr} \defp\charit#1#2#3#4{} % *CHAR :: \charit{12string}{tex_string}{fptr}{sptr} \defp\stringify#1#2#3#4{} % *STRING :: \stringify{12string}{tex_string}{fptr}{sptr} \defp\tagit#1#2#3#4{} % *TAG :: \tagit{12string}{tex_string}{fptr}{sptr} \defp\braceit#1#2#3{} % *BRACED_CODE :: \braceit{tex_string}{fptr}{sptr} \defp\midf#1#2{} % *rule separator :: \midf{fptr}{sptr} \defp\preckind#1#2#3{} % *precedence operator :: \preckind{12string}{fptr}{sptr} % \defp\termname#1#2{} % a production term :: \termname{\idit|\stringify|\charit}{\idit} \defp\mergeop#1#2#3{} % merge directive :: \mergeop{\tagit}{fptr}{sptr} \defp\dprecop#1#2#3{} % dprec directive :: \dprecop{\anint|\hexint}{fptr}{sptr} \defp\sprecop#1#2#3{} % prec directive :: \sprecop{\idit|\stringify|\charit}{fptr}{sptr} \defp\rrhssep#1#2{} % separator :: \rrhssep{fptr}{sptr} \defp\arhssep#1#2{} % separator (between the action and the right hand side) :: \arhssep{fptr}{sptr} \defp\rarhssep#1#2{} % separator :: \rarhssep{fptr}{sptr} \defp\hspace#1#2{} % a space has to take two parameters just like any connector :: \hspace{fptr}{sptr} \defp\emptyterm{} % implicit empty right hand side :: \emptyterm \defp\onesymbol#1#2#3{} % a symbol definition :: \onesymbol{\idit}{\anint|\hexint}{\stringify} \defp\bracedvalue#1#2#3{} % a braced variable value :: \bracedvalue{tex_string}{fptr}{sptr} % level 2---the structures built by the parser \defp\prodheader#1#2#3#4{} % a `left-hand side' of a production :: \prodheader{\idit}{\idit}{fptr}{sptr} \defp\rhs#1#2#3{} % a `right-hand side' :: \rhs{[\termname\hspace\rarhssep\arhssep\actbraces]+}{\arhssep|}{\ifrhsfull} \defp\actbraces#1#2#3#4#5\bdend{} % action braces :: \actbraces{tex_string}{\idit|}{fptr}{sptr}directive*\bdend \defp\bpredicate#1#2#3#4#5\bdend{} % predicate :: \bpredicate{tex_string}{}{fptr}{sptr}directive*\bdend % level 3---the structures composed of structures above \defp\rules#1{} % a complete right-hand side :: \rules{[\rhs|\rrhssep]} \defp\symbolprec#1#2{} % symbol precedence :: \symbolprec{\idit|\stringify|\charit}{\anint|\hexint} %\def\pcluster#1#2{} % a production cluster :: \pcluster{\prodheader}{\termname|...} should never appear in the final output % level 4---larger structures and top level constructions \defp\oneproduction#1#2#3{} % a complete production :: \oneproduction{\prodheader\rules}{fptr}{sptr} \defp\prodprodsepsmall{} % production separator \defp\prodprodsep{} % production separator \defp\prodprodseplarge{} % production separator \defp\optoptsepsmall{} % separator between options \defp\optoptsepnone{} % (trivial) separator between options \defp\posmark#1#2{} % the position marker :: \posmark{fptr}{sptr} \defp\tokendecls#1#2#3{} % token declarations :: \tokendecls{[\onesymbol]+}{fptr}{sptr} \defp\ntermdecls#1#2#3{} % nterm declarations :: \ntermdecls{[\onesymbol]+}{fptr}{sptr} \defp\typedecls#1#2#3#4{} % type declarations :: \typedecls{\tagit}{[\idit\stringify\charit]+}{fptr}{sptr} \defp\precdecls#1#2#3#4#5{} % precedence declarations :: \precdecls{left|right|nonassoc|precedence}{\tagit}{[\idit\stringify\charit]+}{fptr}{sptr} \defp\oneparametricoption#1#2#3#4{} % option :: \oneparametricoption{option-name}{\stringify|\idit}{fptr}{sptr} \defp\optionflag#1#2#3#4{} % option flag :: \optionflag{flag name}{abbreviated name}{fptr}{sptr} \defp\paramdef#1#2#3#4{} % parameters :: \paramdef{\braceit}{parameter domain}{fptr}{sptr} \defp\codepropstype#1#2#3#4#5#6#7{} % term method :: \codepropstype{printer|destructor}{tex_string}{\stringit|\idit}{fptr}{sptr}{fptr}{sptr} \defp\initaction#1#2#3{} % initial action :: \initaction{tex_string}{fptr}{sptr} \defp\codeassoc#1#2#3#4#5#6#7{} % code association :: \codeassoc{code kind}{|\idit}{tex_string}{fptr}{sptr}{fptr}{sptr} \defp\vardef#1#2#3#4{} % variable definition :: \vardef{\idit|\stringify}{|\idit|\stringify|\bracedvalue}{fptr}{sptr} \defp\prologuecode#1#2#3#4#5{} % prologue code :: \prologuecode{tex_string}{fptr}{sptr}{fptr}{sptr} \savecslist{parser-prototypes}\yyunion % table construction: the macros run to build the contents of the table of productions to be % typeset. \newtoks\table \newtoks\tokdectoks \newtoks\opttable \newtoks\typestable \newtoks\prectable \newtoks\tokstoks \newtoks\typesset \let\rhscont\getsecond \let\rhscnct\getthird \let\rhsbool\getfourth \newif\ifrhsfull \newtoks\yystashlocal \newtoks\yyformatlocal \def\astappend{\appendtolist\aststream} \def\astappendx{\appendtolistx\aststream} \def\astisempty{\listisempty\aststream} % index implementation % note that the rank and domain parameters are handed down by the % `outer' macro while the `qualifier' (\term...string) is decided % at the point of invocation; some auxilary sequences first % a macro that always produces the current value of the register \def\thewrap#1#2{% \noexpand\thewrap{\noexpand#1}{\the#1}% } % a macro that always produces the current page number. \def\selfpageno#1{% \noexpand\selfpageno{\the\pageno}% } % a macro that keeps the (single) argument intact \def\stickycs#1{\noexpand\stickycs\noexpand#1} % for finer control over indexing, there are two levels on which % the programmer can disable the production of a whatsit node (\write): % (1) by setting the \iftermindex conditional to \iffalse, and (2) by defining % the \termindex macro to ignore its argument; both of these are expanded % at the point where the index entry is made; the intention is that % the conditional controls indexing at large (say, the index entries % inside the index should not be indexed again), while redefining the macro % provides a finer control over the indexing style \newif\iftermindex \let\termindex\eatone % the index is split into different domains: say, the \bison\ domain contains % the entries for the terms of a grammar; \def\bisonidxdomain{B} % marker for the domain (section of the index) \def\defidxrank{0} % index rank of definitions is lowest so they are listed first \def\headeridxrank{1} % index rank of lhs \def\termidxrank{2} % ordinary term rank % the expansion of the various components of an index entry must be carefully % controlled: it is not possible to predict how many times the entry will be expanded; % there are four types of expandable entries in general: % o the entries that must be expanded at the point of invocation (say, \secno) % o the entries that must be expanded only when the \write is inside a \box that is % being shipped out (say, the \pageno) % o the `lazy' entries that can be expanded any time (although at least one expansion % must take place) % o finally, the entries that must be expanded at a specific point between the point % of invocation and the \shipout % the indexing macro below treats the first three cases for the entries that the macros % below produce; the last case can be implemented by redefining the \stickycs macro % at the appropriate point \def\indxe#1#2{% index entry: % #1 is the output stream % #2 is the entry (see below for the proper form) \expandafter\ind@@\expandafter#2\end{#1}% } \def\ind@@#1\end#2{% \ind@e{#2}{#1}% } \def\ind@e#1#2{% #1 is the output stream % #2 is a 8-parameter sequence, see below \write#1{\in@@e#2\in@@ecomment#2}% } \def\in@@e#1#2#3#4#5#6#7#8{% #1: early expandable (like \secno) % #2: auxilary info (expandable, invariant) % #3: domain % #4: rank % #5: type1 % #6: type2 % #7: key1 % #8: key2 \i@@@e{#1}{\errmessage{\noexpand\\in@@e error: expanded page number placeholder}}% {#2}{#3}{#4}{#5}{#6}{\charstonumberse#7\end}{\charstonumberse#8\end}% } \def\in@@ecomment#1#2#3#4#5#6#7#8{% #1: early expandable (like \secno) % #2: auxilary info (expandable, invariant) % #3: domain % #4: rank % #5: type1 % #6: type2 % #7: key1 % #8: key2 \harmlesscomment\space\charstocharsx#7\end :: \charstocharsx#8\end% } \def\i@@@e#1#2#3#4#5#6#7#8#9{% #1: early expandable (like \secno) % #2: page number placeholder % #3: auxilary info % #4: domain % #5: rank % #6: type1 % #7: type2 % #8: key1 % #9: key2 \noexpand\i@@@e{#1}{\the\pageno}{#3}{#4}{#5}{\noexpand#6}{\noexpand#7}{#8}{#9}% } \def\appendfitotoksa{\toksa\expandafter{\the\toksa\else<>\fi}} % hide \fi inside the loop % defining expandable macros for string transformations \tempca\@ne \toksa{\ifcase#1} \tempcb=\uccode`. % a loop that builds a macro to produce a category 12 character with the given character code \bloop \uccode`.=\tempca \uppercase{\toksb{.}}% \toksa\expandafter\expandafter\expandafter{\expandafter\the\expandafter\toksa\expandafter\or\the\toksb}% \advance\tempca by\@ne \ifnum\tempca>"FF \appendfitotoksa \else \repeat % defining the macro that was built above \edef\next{\toksa{\def\noexpand\asciiprint##1{\the\toksa}}}\next \the\toksa % return . to its regular state \uccode`.=\tempcb \def\charstocharsx#1\end{% expandable version of a `safety' macro, ascii characters only, no tricky space characters \yystartsinspace{#1.}{% \space\ch@rstocharsx#1\end }{% \yystringempty{#1}{}{% \ch@rst@charsx#1\end }% }% } \def\ch@rstocharsx#1 #2\end{\charstocharsx#2\end} \def\ch@rst@charsx#1#2\end{\asciiprint{`#1}\charstocharsx#2\end} \def\writeidxhentry#1{% \indxe\gindex{{\secno}{{\currentrulecontext}{\hostparsernamespace}}{\bisonidxdomain}{\headeridxrank}#1}% } \def\writeidxentry#1{% \indxe\gindex{{\secno}{{\currentrulecontext}{\hostparsernamespace}}{\bisonidxdomain}{\termidxrank}#1}% } \def\writetokenidxentry#1{% \indxe\gindex{{\secno}{{\currentrulecontext}{\hostparsernamespace}}{\bisonidxdomain}{\defidxrank}#1}% } \def\gidxentry#1#2#3{% a generic index entry: % #1 is the type processor, % #2 is the key % #3 is the visual key \iftermindex \termindex{{}{#1}{#2}{#3}}% \fi } \def\ridxentry#1#2#3{% index entry that allows raw input (see \gidxentry{#1}{\end0 \vend{32}\end\toksa{#2}\noexpand\noexpand\noexpand\eatone\vend\eatone}{#3}% % the first \end and \eatone will be removed by \charsto..., the next (innermost) by \numbersto... inside \FI } \def\didxentry#1#2{% (another) index entry that allows raw input (see \csname flex@ption_other\endcsname below) \gidxentryxb{\termraw}{\number#1}{#2}% } \def\gtextidx#1#2#3{% #1 is the entry % #2 is the visual key % #3 is the domain \expandafter\ifx\csname indexterms\endcsname\relax \else {% \storerawidxentry{#1}% \edef\next{% \noexpand\indxe\gindex{{\secno}{{}{\indexpseudonamespace}}{#3}{\termidxrank}{}% {\noexpand\termraw}{\number\getstackpointer\indexterms}{#2}}% }\next \edef\next{\next}\next }% \fi } % a shortcut to simplify using the macro above \def\storerawidxentry#1{% {% \toksa{#1}% \let\parsernamespace\empty\yypushg{\the\toksa}\on\indexterms }% } % a convenient shortcut, as many visual keys come in a token register \def\gidxentryxv#1#2#3{% a generic index entry, e(x)pand (v)isual key: % #1 is the type processor, % #2 is the key % #3 is the visual key \expandafter\gidx@ntryxv\expandafter{#3}{#1}{#2}% } \def\gidxentryxb#1#2#3{% a generic index entry, e(x)pand (b)oth keys: % #1 is the type processor, % #2 is the key % #3 is the visual key \expandafter\gidx@ntryxb\expandafter{#2}{#3}{#1}% } \def\gidx@ntryxb#1#2#3{% \expandafter\gidx@ntryxv\expandafter{#2}{#3}{#1}% } \def\gidx@ntryxv#1#2#3{% \gidxentry{#2}{#3}{#1}% } \def\tidxentry#1#2{% a text index entry, TODO: expand \currentrulecontext \iftermindex \indxe\gindex{{\secno}{{\currentrulecontext}{\indexpseudonamespace}}{\bisonidxdomain}{\termidxrank}{}{#1}{#2}{}}% \fi } \def\idxinline#1{% index the term in text \edef\next{\tidxentry{\termidstring}{#1}}\next } % stash processing wrapper macros \def\yyreadstash#1\to#2\in#3\with#4{% \consumelistupto{#1}{#2}\to{#3}% #4{#3}% \mathsplittoks{#3}{\yyr@adstash}{\eatthree}{#1}{#2}{#3}% } % this macro is based on the assumption that all the math mode % changes are introduced by unadulterated $ tokens (as is done in % \CWEB); \CWEB's handling of math mode is a mistake so there is % no need to introduce another one by using clever math switches; % note that this is not affected by \inmath (see somewhere in this file), % since (as long as!) it is only inserted in the verbatim mode ... % ... or at least it should, so never do something like % @t}\inmath{{@> ... @t}}@> % unless you really know what you are doing (hint: it is only ok % to do this if there are no intervening \vb{...} groups inside % the ... portion above. \def\mathsplittoks#1#2#3{% execute actions depending on whether % token register #1 contains % odd (then insert #2) % or even (insert #3) number of $'s \expandafter\evenmathify\the#1$% \evenmather\end$\evenmather\end$\evenmather\end$% \evenmather\end$\evenmather\end$\evenmather\end$% \emo$\eme$\emo$\eme$\emo$\eme$\emo$\eme$\emo$\end {#2}{#3}% } \def\evenmathcontainer{\evenmather\end} \def\evenmather#1$#2$#3$#4$#5$#6${} \def\emo#1\end{\yyfirstoftwo} \def\eme#1\end{\yysecondoftwo} \def\evenmathify#1$#2$#3$#4$#5$#6${% {% make all changes to \next local \def\next{#6}% \ifx\next\evenmathcontainer \yybreak{}% \else \yybreak{\aftergroup\evenmathify}% \yycontinue }% } \def\yyr@adstash#1#2#3{% #3\expandafter{\the#3{}$}% $upply the math mode switch {% \tempca#2\relax \advance\tempca\@ne \edef\next{% \noexpand\changelistelem{#1}{#2}{}{{}$}% change the consumed stash, so it can be read again \noexpand\changelistelem{#1}{\the\tempca}{{}${}}{}% }\expandafter }\next } \def\readstash#1{% \yyreadstash\yystash\to#1\in\yystashlocal\with\eatone } \def\readstashwredirect#1#2#3{% helper macro to read the stash when the stash and the format pointers appear together % #1(the format pointer) is ignored % #2 is the stash marker % #3 is the local stash register \yyreadstash\yystash\to#2\in#3\with\eatone } % format processing wrapper macros \def\readformat#1{% \let\listiterator\listiteratorsimple \consumelistupto\yyformat{#1}\to\yyformatlocal } \def\readformatlocalonly#1{% \let\listiterator\listiteratorfmtloc \let\wrapupfmtlocal\wrapupyyformatlocal \yyformatlocal{}% \evallistbetween\yyformat{\showlistpointer\yyformat}{#1}% } % iterator to extract \formatlocal \def\listiteratorfmtloc#1#2{% \lookforfmtloc{#1}{}{}.#2\formatlocal{\formatlocal}% } \def\lookforfmtl@c#1#2#3#4#5{% \isthisfmtlocal#5.\formatlocal{% \wrapupfmtlocal{#2}{#3#1}{#4}% }{% \lookforfmtloc{#2}{#3#1}{#4\formatlocal{#5}}.% }% } \def\lookforfmtloc#1#2#3#4\formatlocal#5{% remove the guard . \expandafter\lookforfmtl@c\expandafter{\eatone#4}{#1}{#2}{#3}{#5}% } \def\isthisfmtlocal#1\formatlocal{% \yystringempty{#1}{% a match, clean up the inserted \formatlocal \endoffmtlocal }{% not a match yet, \lookforfmtloc again \yysecondoftwo }% } \def\endoffmtlocal#1\formatlocal{\yyfirstoftwo} \def\wrapupfmtlocal#1#2#3{% a postprocessing macro, to be changed by the one that % invokes the iterator \fdef#1{#2}% } \def\wrapupyyformatlocal#1#2#3{% macro used to save the \formatlocal contents in \yyformatlocal \fdef#1{#2}\yyformatlocal\expandafter{\the\yyformatlocal#3}% } \let\wrapupfmtlocal\wrapupyyformatlocal % use example for the macros above: %\initlist{table} %\toksa{#} %\let\listiterator\listiteratorfmtloc %\appendtolisti{table}{..} %\appendtolisti{table}{a,} %\appendtolisti{table}{\formatlocal{}{b}\formatlocal{k} , } %\appendtolisti{table}{{c},} %\appendtolisti{table}{ \space d,} %\appendtolisti{table}{e\formatlocal{d},} %\appendtolisti{table}{\format{}{f}\formatlocal{j}} %\appendtolisti{table}{.} %\appendtolisti{table}{\end} %\finishlist{table} %\storelist{table}\to\toksa %\the\toksa %\storelist{table}\to\toksa %\message{full list: \the\toksa} %\errmessage{separated: \the\yyformatlocal} % parser invocation \def\newparserstateextra{} \def\d@parse#1{\yyparse#1\yyeof\yyeof\endparseinput\endparse} % as an alternative to lists, stacks (as arrays) can be used to speed up the parser; % the following setup (along with a convenient shortcut to reference the most % recent store) can be employed if desired; unlike lists, stacks do not have % a built-in mechanism for slice expansion. %\yyinitstack\astarray % flattened AST to (possibly) speed up the parser %\def\astarraylastcs{\expandafter\noexpand\romannumeral\gettopofstackcsx\astarray} \long\def\inmath#1{$#1$} %\long\def\stashed#1{\toksa\expandafter{\the\toksa#1}} % to be used with unpackaged stash %\long\def\stashed#1{\toksa\expandafter\expandafter\expandafter{\expandafter\the\expandafter\toksa#1}} % to use with AST array \long\def\stashed#1{\errmessage{making \noexpand\stashed\space expandable is deprecated}} \long\def\sflush#1#2{} \def\ntt{\noexpand\ntt@} % a convenient shortcut \def\ntt@{\tt\let\_\UL} % macros that process the bison grammar terms; % the higher level macros (like the \prodheader below) set up the sequence in % which the processing takes place; the actual typesetting (or whatever other % task is desired, like reference creation) is done by the lower level macros % like \prodhead@r in this case. \defc\prodheader{% a `left-hand side' of a production :: \prodheader{\idit}{\idit}{fptr}{sptr} \readformat{#3}\the\yyformatlocal \let\termindex\writeidxhentry \prodhead@r{#1}{#2}% \let\termindex\eatone } \def\prodhead@r#1#2{% \let\idit\prodhdridit #1\relax\astappendx{\the\toksa}\hrhss@p } \def\hrhss@p{\toksa{&\omit\hfil&\omit\hfil&\omit\hfil\cr\noalign{\penalty100}\omit\hfil&\termspostformat}\astappendx{\the\toksa}} \defc\rrhssep{% separator :: \rrhssep{fptr}{sptr} \readformatlocalonly{#1}% \the\yyformatlocal % this will have a chance to change the definition of \rrhss@p \rrhss@p } \def\rrhss@p{\toksa{\omit\hfil&}\astappendx{\the\toksa}} \defc\arhssep{% separator (between the action and the right hand side) :: \arhssep{fptr}{sptr} \readformat{#1}% \the\yyformatlocal % this will have a chance to change the definition of \arhss@p \arhss@p } %% between the inline action and next term: \def\arhss@p{\toksa{\omit\hfil&\hbox to 2em{\hfil}}\astappendx{\the\toksa}} \defc\rarhssep{% separator :: \rarhssep{fptr}{sptr} \readformat{#1}% \the\yyformatlocal % this will have a chance to change the definition of \rarhss@p \rarhss@p } %% between a term and the following action \def\rarhss@p{\astappend&} \defc\hspace{% a space has to take two parameters just like any connector :: \hspace{fptr}{sptr} \readformatlocalonly{#1}% \the\yyformatlocal % may change \hspac@ \hspac@ } \def\hspac@{% \astappend{ }% } \defc\rhs{#1}% a `right-hand side' :: \rhs{[\termname\hspace\rarhssep\arhssep\actbraces]+}{\arhssep|}{\ifrhsfull} \def\supplybdirective#1#2{% \edef\next{\nx\s@pplybdirective#1{\the#2}\the#1\nx\bdend}\next } \def\s@pplybdirective#1#2#3\bdend\bdend{% #1{#3#2\bdend}% } \defc\termname{% a production term :: \termname{\idit|\stringify|\charit}{\idit} \let\idit\termnameidit \let\stringify\termnamestringify \let\optstrextra\optstrextraesc \let\termindex\writeidxentry \termnam@{#1}{#2}% \let\termindex\eatone } \def\termnam@#1#2{\toksa{}\toksb{}\toksc{}#1\expandafter\termn@m@\expandafter{\the\toksa}{#2}} \def\termn@m@#1#2{\toksa{}\toksb{}\toksc{}#2\expandafter\t@rmn@m@\expandafter{\the\toksa}{#1}} % several versions of term typesetting \def\t@rmn@m@#1#2{% the termname is #2, the bracketed part is in #1 \yystringempty{#1}{\toksa{#2}}{\toksa{#2\hbox{$\langle${}#1{}$\rangle$}}}% \astappendx{\the\toksa}% } \newif\ifbracketedvisible % decide whether to show the bracketed name in productions \def\t@rmn@m@#1#2{% the termname is #2, the bracketed part is in #1 \yystringempty{#1}{\toksa{#2}}{% \ifbracketedvisible \toksa{#2\hbox{$\,\cdot$#1}}% \else \toksa{#2}% \fi }% \astappendx{\the\toksa}% } % \newtoks\bdirects \defc\actbraces{% action braces :: \actbraces{tex_string}{\idit|}{fptr}{sptr}directive*\bdend \readformat{#3}% #5% accumulate all the directives \yytoksempty\bdirects{}{% \edef\next{\bdirects{% $\vtop{\halign{\nx\quad####\nx\hfil&####\nx\hfil\cr\the\bdirects}}$}}\next }% \the\yyformatlocal \actbrac@s{#1}{#2}{#4}% } \def\actbrac@s#1#2#3{% \readstash{#3}% \astappendx{\the\bdirects&\toksa{\the\yystashlocal}\cr}% \bdirects{}% } \def\bpredicate#1#2#3#4#5\bdend{% \readformat{#3}% #5% accumulate all the directives \yytoksempty\bdirects{% \bdirects{\quad$\dashv\ \nx\vdash$}% }{% \edef\next{\bdirects{% $\vtop{\halign{\nx\quad####\nx\hfil&####\nx\hfil\cr$\dashv\ $&\omit\nx\hfil$\nx\vdash$\cr \the\bdirects}}$}}\next }% \the\yyformatlocal \bpredicat@{#1}{#2}{#4}% } \def\bpredicat@#1#2#3{% \readstash{#3}% \astappendx{\the\bdirects&\toksa{\the\yystashlocal}\cr}% \bdirects{}% } \def\bdirective#1#2#3#4{% \savecslist{local-namespace}\yyunion \restorecslist{table-render:directives}\yyunion \toksa{}#2% make a directive list \appendr\bdirects{$\nx\langle${\ntt #1} &\the\toksa$\nx\rangle$\nx\cr}% \restorecslist{local-namespace}\yyunion } \def\mergeop#1#2#3{% \bdirective{merge}{#1}{#2}{#3}% } \def\dprecop#1#2#3{% \bdirective{dprec}{#1}{#2}{#3}% } \def\sprecop#1#2#3{% \bdirective{prec}{#1}{#2}{#3}% } \defc\rules{#1}% a complete right-hand side :: \rules{[\rhs|\rrhssep]} \defc\oneproduction{#1\setrulecontext{}\stopproduction}% a complete production :: \oneproduction{\prodheader\rules}{fptr}{sptr} % to make it possible to typeset tokens depending on their context % the context name is passed to the token typeseting macros; the most % common context name is the left hand side of a production; special % context names (such as *left, *right, etc) are defined for terms that are % not part of a rule; all such context names start with `*' since this % character cannot be part of a term name \def\setrulecontext#1{\def\currentrulecontext{#1}} \let\currentrulecontext\empty % an empty left hand side is indexed in the index pseudonamespace and not in the main % parser namespace, since the name parser never encounters this term (as the \emptyterm % control sequence is inserted by the main parser) while typesetting productions; % because of this it would be unnatural to define a \prettywordpair sequence for it in the main % parser namespace; using a special non-\bison\ name should avoid any confusion with % the regular grammar terms \def\emptyrhssymbol{$\circ$} \defc\emptyterm{\astappendx{\nx\emptyrhssymbol\tidxentry{\termexception}{emptyrhs&}}} \def\termnameidit#1#2#3#4{% \readformatlocalonly{#3}% \the\yyformatlocal \nameproc{#2}\with\parsebin \peekstash{#4}% does not clobber \toksa and \toksb \expandafter\settermstyle\expandafter{\the\toksb}{#1}% } \def\settermstyle#1#2{% put the \whatsit node (\write) at the end so that the % term macros can remove the whitespace preceeding it \edef\next{% \toksa{% \termmetastyle{% \let\nx\idxfont\nx\empty\nx\it\the\toksa \gidxentry{\termidstring}{#2}{#1}\nx\/% }% }% }\next } \def\termnamestringify#1#2#3#4{% \nameproc{#2}\with\parsebin \ifyyparsefail \toksb{"#1"}\toksc{\termstring}% \else \toksc{\termidstring}% \fi \edef\next{\toksa{{% \expandafter\gidxentryxv\expandafter{\the\toksc}{#1}{\the\toksb}% \ntt\the\toksa }}}\next } \def\termmetastyle#1{{#1}} \let\peekstash\eatone \newif\ifinheader \def\prodhdridit#1#2#3#4{% \setrulecontext{}% TODO: perhaps some special context for the left hand side terms is appropriate \nameproc{#2}\with\parsebin \setrulecontext{#1}% \edef\next{\toksa{{% \gidxentryxv{\termidstring}{#1}{\the\toksb}% \nx\inheadertrue\let\nx\idxfont\nx\bf\nx\itbold\the\toksa\nx\/% }}}\next } \defc\charit{% *CHAR :: \charit{12string}{tex_string}{fptr}{sptr} \expandafter\ifx\csname\prettynamecs\hostparsernamespace{#1}\endcsname\relax \toksa{#1}\sansfirst\toksa \edef\next{\toksa{{\ntt\the\toksa}\gidxentryxb{\termvstring}{\the\toksa}{}}}% remove the possible \\ \else \expandafter\ifx\csname\viskeyref\hostparsernamespace{#1}\endcsname\relax \tokse{#1}% we are stripping the quotes so the visible key is adjusted \else \edef\next{\tokse{\expandafter\expandafter\csname\viskeyref \hostparsernamespace{#1}\endcsname\expandafter{\currentrulecontext}}}\next \fi \edef\next{\expandafter\toksa\expandafter{\expandafter\noexpand %\csname\prettynamecs\hostparsernamespace{#1}\endcsname{\currentrulecontext}\gidxentryxv{\termvstring}{'#1'}{\the\tokse}}}% \csname\prettynamecs\hostparsernamespace{#1}\endcsname{\currentrulecontext}\gidxentryxv{\termidstring}{'#1'}{\the\tokse}}}% \fi \next } \defc\anint{% INT :: \anint{digits}{fptr}{sptr} \astappend{#1}% } \defc\hexint{% INT :: \hexint{0[xX][0-9A-F]+}{fptr}{sptr} \expandafter\astappend\expandafter{\eattwo#1$_{16}$}% } \def\optoptsepnone{% \concat\opttable\postoks } \def\optoptsepsmall{% keep the alignment going but insert a small space \concat\opttable\postoks \appendrnx\opttable{\noalign{\smallskip}}% } \def\prodprodsepsmall{% \pushothertables \astappend{\noalign{\penalty-150 \smallskip}}% } \def\prodprodsep{% \pushothertables \astappend{\noalign{\medskip}}% } \def\prodprodseplarge{% \pushothertables \astappend{\noalign{\bigskip}}% } \def\separatorswitcheq{% \oneproduction {% \toksd{\prodprodsepsmall}% } \codepropstype\codeassoc {% \toksd{\optoptsepsmall}% } } \def\separatorswitchdefaulteq{% \toksd{\optoptsepnone}% } % a switch for inserting position information into the parsed table % clobbers \toksd \newtoks\postoks \def\positionswitch{ \empty {% \postoks{}% semicolons should be invisible } \paramdef\oneparametricoption\optionflag\typedecls\vardef {% \getfourth{\yy(2)}\to\postoks % the format marker \getfifth{\yy(2)}\to\toksd % the stash marker \edef\next{\postoks{\nx\posmark{\the\postoks}{\the\toksd}}}\next } \prologuecode\ntermdecls\tokendecls {% \getthird{\yy(2)}\to\postoks % the format marker \getfourth{\yy(2)}\to\toksd % the stash marker \edef\next{\postoks{\nx\posmark{\the\postoks}{\the\toksd}}}\next } \precdecls {% \getfifth{\yy(2)}\to\postoks % the format marker \getsixth{\yy(2)}\to\toksd % the stash marker \edef\next{\postoks{\nx\posmark{\the\postoks}{\the\toksd}}}\next } \oneproduction {% \getsecond{\yy(2)}\to\postoks % the \prodheader \getfourth{\postoks}\to\toksd % the format marker \getfifth{\postoks}\to\postoks % the stash marker \edef\next{\postoks{\nx\posmark{\the\toksd}{\the\postoks}}}\next } \codeassoc\codepropstype {% \getseventh{\yy(2)}\to\postoks % the format marker \geteightth{\yy(2)}\to\toksd % the stash marker \edef\next{\postoks{\nx\posmark{\the\postoks}{\the\toksd}}}\next } } \def\positionswitchdefault{% \errmessage{unknown chunk type in: \the\yy(2)}% } \def\posmark#1#2{% % \readformat{#1}% % no formatting for locations currently % \the\yyformatlocal \posm@rk{#2}% } \def\posm@rk#1{% \readstash{#1}% \yytoksempty\yystashlocal{\postoks{}}{% \toksa\expandafter{\the\yystashlocal}\cleanstash\stripstash \setbox\z@=\vbox{\setlazyc\the\toksa}% \ifnum\ht\z@=\z@ \postoks{}% \else \edef\next{\postoks{\noalign{\indent\toksa{\the\yystashlocal}\nx\makestashbox}}}\next \fi }% } \def\codeoptionlist{% \codepropstype\codeassoc\prologuecode } \def\simpleoptionsplit{% \oneparametricoption\vardef\paramdef\optionflag } \def\noncodeoptionlist{% \oneparametricoption\vardef\paramdef\optionflag \codepropstype\codeassoc\prologuecode } \def\alloptionlist{% \oneparametricoption\vardef\paramdef\optionflag \codepropstype\codeassoc\prologuecode \typedecls\tokendecls\precdecls\oneproduction } \def\emptyoption{\empty} \diagprod\codeoptionlist\noncodeoptionlist\in\codenoncodeseplist \diagprod\simpleoptionsplit\simpleoptionsplit\in\noncodenoncodeseplist \diagprod\alloptionlist\emptyoption\in\emptyotherseplist % this is a switch for inserting separators between dissimilar items \def\separatorswitchneq{% \classexpand\codenoncodeseplist {% separate options with code (\codepropstype, \codeassoc) from other options by a small space \toksd{\optoptsepsmall}% } \classexpand\noncodenoncodeseplist {% \toksd{\optoptsepnone}% } % a separator after the first rule or before or after a semicolon \classexpand\emptyotherseplist {% \toksd{\optoptsepnone}% } } \setspecialcharsfrom\separatorswitchneq \def\separatorswitchdefaultneq{% \toksd{\prodprodsep}% } \def\pushothertables{% %token's \yytoksempty\tokdectoks{}{\attachtokentable}% %type's \yytoksempty\typestable{}{\attachtypestable}% %precedence's \yytoksempty\prectable{}{\attachprectable}% % options \yytoksempty\opttable{}{\attachoptionstable}% \astappendx{\the\postoks}% } % % typesetting token lists, precedence declarations, etc \def\attachtokentable{% typesetting the token declarations as part of the grammar \tempcb3 \tempca\tempcb \expandafter\tokdectoks\expandafter{\expandafter}\the\tokdectoks \ifnum\tempca=\tempcb \else \bloop \tokdectoks\expandafter{\the\tokdectoks&\omit\hfil}% \ifnum\tempca=\z@ \else \advance\tempca\m@ne \repeat \tokdectoks\expandafter{\the\tokdectoks\cr}% \fi \toksa{\tt\strut##\hfil\tabskip=0pt plus 1fil}% \bloop \toksa\expandafter{\the\toksa&\tt\strut##\hfil}% \ifnum\tempcb=\tw@ \else \advance\tempcb\m@ne \repeat \toksa\expandafter{\the\toksa&\tt\strut##\hfil\tabskip\z@\cr}% \concat\toksa\tokdectoks \tokdectoks\toksa \astappendx{\noalign{% \tabskip\parindent %\nx\displaytokenrawtrue % this controls how tokens are displayed % in the declarations: if true, the macro names will be shown \halign to\hsize{\the\tokdectoks}% }% }% \tokdectoks{}% } \def\toksdefline#1#2#3#4#5{% #1 is the parsed version of the internal bison name % #2 is the index entry % #3 is the type % #4 is the explicit value % #5 is the parsed version of the string value \ifnum\tempca=\z@ \tokdectoks\expandafter{\the\tokdectoks&{#2}#1\hfil\cr}% \tempca\tempcb \else \ifnum\tempcb=\tempca \tokdectoks\expandafter{\the\tokdectoks{#2}#1\hfil}% \else \tokdectoks\expandafter{\the\tokdectoks&{#2}#1\hfil}% \fi \advance\tempca\m@ne \fi } \def\attachtypestable{% typesetting the type declarations as part of the grammar \toksa{}\the\typestable \astappendx{\noalign{{\the\toksa}}}\typestable{}% } \long\def\onetype#1#2{% \toksb{{% \hbadness\@M \rightskip=\z@ \tempda\hsize \advance\tempda-1in \indent{$\langle$\tt union$\rangle.#1$:}\ \hfill\nobreak\hfill\nobreak\null\penalty1\relax\null\nobreak\hfill \hbox to\tempda{$\vtop{\noindent\hsize\tempda\raggedright #2\strut}$}\par }}% \concat\toksa\toksb } \def\attachprectable{% typesetting the precedence declarations as part of the grammar \toksa{}\the\prectable \astappendx{\noalign{{\the\toksa}}}\prectable{}% } \long\def\oneprec#1#2#3{% \toksc{% \hbadness\@M \rightskip=\z@ \tempda\hsize \advance\tempda-1in \indent }% \toksd{% \ \hfill\nobreak\hfill\nobreak\null\penalty1\relax\null\nobreak\hfill \hbox to\tempda{$\vtop{\noindent\hsize\tempda\raggedright #3\strut}$}\par } \def\next{#2}% \ifx\next\empty \toksb{}% \else \toksb{${}:{}$#2}% \fi \edef\next{\toksb{{$\nx\langle$\nx\bf #1\the\toksb$\nx\rangle$}}}\next \appendr\toksa{{\the\toksc\the\toksb\the\toksd}}% } \def\attachoptionstable{% typesetting the options as part of the grammar \astappendx{\noalign{% \tabskip\parindent \halign{####\nx\hfil\tabskip\z@&\nx\qquad\nx\it####\nx\hfil\cr \the\opttable }% }% }\opttable{}% } \let\stopproduction\relax \defc\tokendecls{% token declarations :: \tokendecls{[\onesymbol]+}{fptr}{sptr} \savecslist{local-namespace}{\yyunion\termindex}% \restorecslist{table-render:token-declarations}\yyunion \let\termindex\writetokenidxentry \let\currenttokentype\empty#1% \restorecslist{local-namespace}{\yyunion\termindex}% } \defc\typedecls{% type declarations :: \typedecls{\tagit}{[\idit\stringify\charit]+}{fptr}{sptr} \savecslist{local-namespace}{\yyunion\termindex}% \restorecslist{table-render:type-declarations}\yyunion \let\termindex\writetokenidxentry \typesset{}#2\relax#1% \appendr\typestable{\nx\onetype{\the\toksa}{\the\typesset}}% \restorecslist{local-namespace}{\yyunion\termindex}% } \def\precdecls#1#2#3#4#5{% #1 type % #2 tag % #3 list of symbols % #4 format pointer % #5 stash pointer \savecslist{local-namespace}{\yyunion\termindex}% \restorecslist{table-render:prec-declarations}\yyunion \setrulecontext{*#1}% \let\termindex\writetokenidxentry \typesset{}#3\toksa{}#2% \appendr\prectable{\nx\oneprec{#1}{\the\toksa}{\the\typesset}}% \restorecslist{local-namespace}{\yyunion\termindex}% \setrulecontext{}% } % options typesetting \def\oneparametricoption#1#2#3#4{% \restorecs{table-render:token-declarations}{\braceit\stringify\idit\anint\hexint}% \toksa{}\toksb{}\toksc{}#2% \edef\next{\nx\oneparametricopti@n{#1}{\the\toksa}{\the\toksb}{\the\toksc}}\next } \def\oneparametricopti@n#1#2#3#4{% \yystringempty{#2}{% there is no identifier \yystringempty{#4}{% there is no digit \edef\next{\toksa{{\ntt"\the\toksb"}}}\next }{% \edef\next{\toksa{{\nx\rm\the\toksc}}}\next }% }{% \nameproc{#2}\with\parsebin }% now \toksa contains the value of the parameter \toksb{#1}% \let\termindex\writetokenidxentry \appendr\opttable{\gidxentry{\termostring}{#1}{}$\nx\langle${\nx\bf\the\toksb}$\nx\rangle$&\the\toksa\nx\/\nx\cr}% \let\termindex\eatone } \def\paramdef#1#2#3#4{% \restorecs{table-render:token-declarations}\braceit \let\termindex\writetokenidxentry \appendr\opttable{\gidxentry{\termostring}{#2}{}}% \let\termindex\eatone \appendrnx\opttable{$\langle${\bf #2}$\rangle$}% \toksa{}#1% \concat\opttable\toksa } \def\optionflag#1#2#3#4{% \let\termindex\writetokenidxentry \appendr\opttable{\gidxentry{\termostring}{#1}{}}% \let\termindex\eatone \yystringempty{#2}{% \appendrnx\opttable{$\langle${\bf#1}$\rangle$\rlap{$\,\star$}&\cr}% }{% \appendrnx\opttable{$\langle${\bf#1}$\rangle$\rlap{$\,\star$}& {\rm(set as $\langle${\bf#2}$\rangle$)}\cr}% }% } \def\codepropstype#1#2#3#4#5#6#7{% \readformat{#4}\the\yyformatlocal % this can change \codepropstyp@ \codepropstyp@{#2}{#3}{#1}{#5}% } \def\codepropstyp@#1#2#3#4{% \readstash{#4}% \restorecs{table-render:type-declarations}{\idit\stringify\hspace}% \let\termindex\writetokenidxentry \typesset{}#2% collect all the symbols in \typesset \appendr\opttable{\gidxentry{\termostring}{#3}{}$\nx\langle${\nx\bf #3}$\nx\rangle$&% \toksa{\the\yystashlocal}\nx\makestashbox\nx\hfil\cr \noalign{\nx\smallskip}% \noalign{\indent$\nx\rlap{\hbox to2em{\nx\hfil$\nx\star$\nx\hfil}}\vcenter{ \advance\hsize by-\parindent \emergencystretch10pt\nx\raggedright\noindent\hangafter\z@\hangindent2em\nx\strut\the\typesset\nx\strut}$}% }% \let\termindex\eatone } \def\codeassoc#1#2#3#4#5#6#7{% \readformat{#4}\the\yyformatlocal % this can change \codeass@c \codeass@c{#1}{#2}{#3}{#5}% } \def\codeass@c#1#2#3#4{% \readstash{#4}% \let\idit\termnameidit \let\termindex\writetokenidxentry \toksa{}#2% put the typeset form of the identifier in \toksa \appendr\opttable{% \yystringempty{#1}{}{\gidxentry{\termostring}{#1}{}}% $\nx\langle${\nx\bf #1}$\nx\rangle$\nx\quad{\the\toksa}&% \toksa{\the\yystashlocal}\nx\makestashbox\nx\hfil\cr }% \let\termindex\eatone } \def\vardef#1#2#3#4{% \readformat{#3}\the\yyformatlocal % this can change \vard@f \vard@f{#1}{#2}{#4}% } \def\vard@f#1#2#3{% \let\idit\termnameidit \let\stringify\termnamestringify \let\termindex\writetokenidxentry #1% put the typeset form of the identifier or string in \toksa \toksb\toksa \savecslist{local-namespace}\yyunion \restorecslist{table-render:variable-definitions}\yyunion \toksa{}#2% put the value in toksa \toksc\toksa \restorecslist{local-namespace}\yyunion \let\termindex\eatone \appendr\opttable{$\nx\langle${\nx\bf define}$\nx\rangle$\nx\quad{\the\toksb}&\the\toksc\cr}% } \defc\prologuecode{% prologue code :: \prologuecode{tex_string}{fptr}{sptr}{fptr}{sptr} \readstash{#5}% \appendr\opttable{% \omit\span\omit\nx\cdotfill\cr \omit\span\omit\toksa{\the\yystashlocal}\nx\makestashbox\nx\cr \omit\span\omit\nx\cdotfill\cr }% } \def\yyunion@tablerender{% \stashed\rarhss@p\rrhss@p\prodhead@r\hrhss@p\arhss@p\termnam@\termn@m@\t@rmn@m@ \actbrac@s\hspac@\codepropstyp@\vard@f\termmetastyle\peekstash\stopproduction } \savecslist{table-render}\yyunion \savecslist{table-render}\yyunion@tablerender \def\setprodtable{% \def\aststream{bison.rules}% the list where the AST output is gathered \restorecslist{table-render}\yyunion \restorecslist{table-render}\yyunion@tablerender } % formatting macros \def\midf#1#2{} \def\format#1{% #1% } \let\formatlocal\format \let\formatbegin\format \let\formatp\format \newtoks\yystashlastcontent % contents of the last action \newif\ifshowlastaction % if true, show the last action of a flattened set of rules % flatten: omit the actions, just list all the rules in a single line; % if \showlastactiontrue show just the last action, otherwise display \actionfiller % instead \def\flatten{% \let\stopproduction\stopproduction@flatten \let\actbrac@s\actbrac@s@flatten \let\rrhss@p\rrhss@p@flatten \let\arhss@p\relax \let\rarhss@p\relax \def\flattenactiontrace{}% } \def\actbrac@s@flatten#1#2#3{% do everything but add the stash contents to the table \readstash{#3}% \edef\flattenactiontrace{\flattenactiontrace*}% \yystashlastcontent\yystashlocal % keep the contents of the braces % in case we want to show the last action \futurelet\actsep\actbrac@s@fl@tten } % see the remarks before \emptyterm above for the reasons for choosing the index % pseudonamespace for this term \def\inlineactionsymbol{$\diamond$} \def\actbrac@s@fl@tten{% \ifx\actsep\arhssep \astappendx{\nx\ \nx\inlineactionsymbol\nx\ \tidxentry{\termexception}{inline_action&}}% \fi } \def\rrhss@p@flatten{% \astappend{$\ \vert\ $}% }% \def\stopproduction@flatten{% \ifshowlastaction {% \toksa\yystashlastcontent\cleanstash \yytoksempty\toksa{}{% there is a non-empty action \def\next{*}% \ifx\flattenactiontrace\next % if there were more than one action \else % preceeding it, prepend an indicator (ellipsis) \appendlnx\toksa{\hbox{$\ldots\ \vert\ $}{}\ignorespaces}% \fi }% \expandafter }\expandafter\yystashlastcontent\expandafter{\the\toksa}% \yystashlastcontent\expandafter{\expandafter\toksa\expandafter{\the\yystashlastcontent}}% \else \yystashlastcontent{\actionfiller}% \fi \def\flattenactiontrace{}% \astappendx{&&\the\yystashlastcontent\nx\cr}% } % fold: resume normal display \def\fold{% \restorecs{table-render}{\actbrac@s\rrhss@p\arhss@p\rarhss@p\stopproduction}% \stopproduction@flatten } \def\actionfiller{\omit\quad$\ldots$\hfil} % inline: put the left hand side of the production on the same line as the rule \def\inline{% \let\prodhead@r\prodhead@r@inline \let\hrhss@p\hrhss@p@inline } \def\prodhead@r@inline#1#2{% \let\idit\prodhdridit #1\relax \astappendx{\the\toksa}% \setbox\z@=\hbox{\strut\the\toksa\/$\,$\rm:\quad}% \tempda=\wd\z@\relax \advance\tempda-2em \hrhss@p } \newif\ifsquashterms \def\termspostformat{\ifsquashterms\aftergroup\noexpand\squashtermstrue\fi} \def\hrhss@p@inline{% \astappendx{&\termspostformat\hbox to \the\tempda{\hss}}% } % breakline: break the production line \def\breakline{% \let\hspac@\hspac@@breakline } \def\hspac@@breakline{% \astappend{{$\,\hookleftarrow$}&\omit\hfil&\omit\hfil\cr\omit\hfil&\hbox to 2em{\hfil}}% \restorecs{table-render}\hspac@ } % breakahead: break the production line after #1 terms % use: \breakahead{[0-9]+} \newcount\breakaheadcount \def\breakahead#1{% \let\bahspac@\hspac@ \let\hspac@\hspac@@breakahead \breakaheadcount#1\relax } \def\hspac@@breakahead{% \ifnum\breakaheadcount=\@ne \yybreak{% \astappend{{$\,\hookleftarrow$}&\omit\hfil&\omit\hfil\cr\omit\hfil&\hbox to 2em{\hfil}}% \let\hspac@\bahspac@ }% \else \advance\breakaheadcount by \m@ne \yybreak{\bahspac@}% \yycontinue } % skipheader: do not show the left hand side \def\skipheader{% \let\prodhead@r\prodhead@r@skipheader \let\hrhss@p\hrhss@p@skipheader } \def\prodhead@r@skipheader#1#2{% \hrhss@p } \def\hrhss@p@skipheader{\astappend{\omit\hbox to 2em{\hfil}&\termspostformat}\restorecs{table-render}{\hrhss@p}} \def\stashtoterm#1{% in case one needs to insert previous stash as a term % usage: \let\peekstash\stashtoterm \readstash{#1}% {\edef\next{\toksc{{\toksa{\the\yystashlocal}\nx\makestashbox}}}\expandafter}\next \let\termmetastyle\xtoksc \restorecs{table-render}\peekstash } \def\xtoksc#1{\the\toksc}% % resetf: resume normal formatting \def\resetf{% \restorecs{table-render}{\prodheader\prodhead@r\hrhss@p\rrhss@p\arhss@p\rhs\termname\actbraces\actbrac@s\rarhss@p\hspac@\rules \oneproduction\emptyterm\stringify\idit\charit\prodprodsep\onesymbol\stopproduction}% \squashtermsfalse } \def\prodstyle#1{% to typeset token names in text; % CAUTION: when many parsers are at play at the same time, % one should use the version of this macro below that takes a % namespace as a parameter, to make sure the term is typeset properly % when another namespace might be in effect (such as when section names are output) {% \let\optstrextra\optstrextraesc \def\termidxrank{5}% \let\termindex\writeidxentry \nameproc{#1}\with\parsebin \edef\next{% \toksa{% \termmetastyle{% \let\nx\idxfont\nx\empty\nx\it\the\toksa \expandafter\gidxentryxv\expandafter{\romannumeral \ifyyparsefail \yybreak{0 \termidstring}% \else \yybreak{\expandafter\tssextract\the\toksa\end}% \yycontinue}{#1}{\the\toksb}\nx\/% }% }% }\next \let\_\uscore \the\toksa\nobreak }% } \def\tssextract#1#2#3\end{% \yystringempty{#2}{0 \termidstring}{0 #2}% } \def\prodtstyle#1{% to typeset terminal string names in text; {% \let\optstrextra\optstrextraesc \def\termidxrank{5}% \let\termindex\writeidxentry \nameproc{#1}\with\parsebin \yytoksempty\toksb{\toksb{"#1"}}{}% \edef\next{% \toksa{% \termmetastyle{% \let\nx\idxfont\nx\empty\ntt\the\toksa \gidxentryxv{\termstring}{#1}{\the\toksb}% }% }% }\next \let\_\uscore \the\toksa\nobreak }% } \def\prodstylens#1#2{% to typeset token names in text, in a predefined namespace {% \def\hostparsernamespace{#2}% \prodstyle{#1}% }% } % macros used in typesetting the result of the prologue parsing %type declarations \restorecslist{parser-strict}\yyunion \defc\idit{% *ID :: \idit{12string}{tex_string}{fptr}{sptr} \termnameidit{#1}{#2}{#3}{#4}% \concat\typesset\toksa } \defc\stringify{% *STRING :: \stringify{12string}{tex_string}{fptr}{sptr} \termnamestringify{#1}{#2}{#3}{#4}% \concat\typesset\toksa } \defc\hspace{% a space has to take two parameters just like any connector :: \hspace{fptr}{sptr} \appendrnx\typesset{ }% } \defc\charit{% *CHAR :: \charit{12string}{tex_string}{fptr}{sptr} \toksa{\.{#2}}% \concat\typesset\toksa } \defc\tagit{% *TAG :: \tagit{12string}{tex_string}{fptr}{sptr} \toksa{\\{#2}}% } \toyyunion{table-render:type-declarations} %token declarations \newif\iftracetokennames \restorecslist{parser-strict}\yyunion \defc\hspace{} \defc\idit{\toksa{#2}}% *ID :: \idit{12string}{tex_string}{fptr}{sptr} \defc\charit{\toksa{'#1'}}% *CHAR :: \charit{12string}{tex_string}{fptr}{sptr} \defc\stringify{\toksb{#2}}% *STRING :: \stringify{12string}{tex_string}{fptr}{sptr} \defc\anint{\toksc{#1}}% INT :: \anint{digits}{fptr}{sptr} \defc\hexint{\toksc\expandafter{\eattwo#1$_{16}$}}% INT :: \hexint{0[xX][0-9A-F]+}{fptr}{sptr} \defc\tagit{% *TAG :: \tagit{12string}{tex_string}{fptr}{sptr} \def\currenttokentype{#2}% } \def\braceit#1#2#3{% similar to \actbrac@s \readstash{#3}% \edef\next{\toksa{&\toksa{\the\yystashlocal}\nx\makestashbox\nx\cr}}\next } \def\onesymbol#1#2#3{% #1 is the macro name used internally by bison (\idit{}{}{}{}) % #2 is the integer value (\anint{}{}{}) % #3 is the string value (\stringify{}{}{}{}) \toksa{}\toksb{}\toksc{}% #1#2#3\relax \edef\next{\nx\onesymb@l{\the\toksa}{\the\toksc}{\the\toksb}}\next } \def\onesymb@l#1#2#3{% #1 is the macro name used internally by bison % #2 is the integer value % #3 is the string value \let\optstrextra\optstrextraesc \tokse{}\toksf{}\toksg{}% these registers will contain the appropriate visual keys % and index entry processing control sequences \yystringempty{#3}{}{% \nameproc{#3}\with\parsebin \ifyyparsefail % if the parsing failed, create a visible key, process the % index entry as a \.{\\tt} string \tokse{"#3"}\toksf{\termstring}% \else % otherwise use the value of the string as the visual key, % process the string as a \bison\ identifier \tokse\toksb\toksf{\termidstring}% \fi \tokstoks\toksa }% \yystringempty{#1}{}{\nameproc{#1}\with\parsebin\toksg\toksb}% \iftracetokennames\ferrmessage{token: \the\toksa, string: \the\tokstoks}\fi \toksb\expandafter{\currenttokentype}% \appendr\tokdectoks{\nx\toksdefline {\the\toksa}% {% \yystringempty{#1}{}{\gidxentryxv{\termidstring}{#1}{\the\toksg}}% \yystringempty{#3}{}{\expandafter\gidxentryxv\expandafter{\the\toksf}{#3}{\the\tokse}}% }% {\yytoksempty\toksb{auto}{\the\toksb}}% {#2}% {\the\tokstoks}% }% \restorecs{nameparser}{\optstrextra}% } \toyyunion{table-render:token-declarations} %precedence declarations \restorecslist{parser-strict}\yyunion \defc\idit{% *ID :: \idit{12string}{tex_string}{fptr}{sptr} \termnameidit{#1}{#2}{#3}{#4}% \concat\typesset\toksa } \defc\stringify{% *STRING :: \stringify{12string}{tex_string}{fptr}{sptr} \termnamestringify{#1}{#2}{#3}{#4}% \concat\typesset\toksa } \defc\charit{% *CHAR :: \charit{12string}{tex_string}{fptr}{sptr} \expandafter\ifx\csname\prettynamecs\hostparsernamespace{#1}\endcsname\relax \toksa{#1}\sansfirst\toksa \edef\next{\toksa{{\ntt\the\toksa}\gidxentryxb{\termvstring}{\the\toksa}{}}}% remove the possible \\ \else \expandafter\ifx\csname\viskeyref\hostparsernamespace{#1}\endcsname\relax \tokse{#1}% \else \edef\next{\tokse{\expandafter\expandafter\csname\viskeyref \hostparsernamespace{#1}\endcsname\expandafter{\currentrulecontext}}}\next \fi \edef\next{\expandafter\toksa\expandafter{\expandafter\noexpand %\csname\prettynamecs\hostparsernamespace{#1}\endcsname{\currentrulecontext}\gidxentryxv{\termvstring}{'#1'}{\the\tokse}}}% \csname\prettynamecs\hostparsernamespace{#1}\endcsname{\currentrulecontext}\gidxentryxv{\termidstring}{'#1'}{\the\tokse}}}% \fi \next \concat\typesset\toksa } \defc\anint{% INT :: \anint{digits}{fptr}{sptr} \appendrnx\typesset{${}=\hbox{\ntt#1}$}% } \defc\hexint{% INT :: \hexint{0[xX][0-9A-F]+}{fptr}{sptr} \toksa\expandafter{\eattwo#1}% \appendr\typesset{${}=\hbox{\ntt\the\toksa}_{16}$}% } \defc\hspace{% \appendrnx\typesset{ }% } \defc\tagit{% *TAG :: \tagit{12string}{tex_string}{fptr}{sptr} \toksa{\\{#2}}% } \def\symbolprec#1#2{% #1#2% } \toyyunion{table-render:prec-declarations} % variable definitions \restorecslist{parser-strict}\yyunion \defc\idit{\toksa{#2}}% *ID :: \idit{12string}{tex_string}{fptr}{sptr} \defc\stringify{\toksa{#2}}% *STRING :: \stringify{12string}{tex_string}{fptr}{sptr} \def\bracedvalue#1#2#3{% similar to \actbrac@s \readstash{#3}% \edef\next{\toksa{\toksa{\the\yystashlocal}\nx\makestashbox}}\next } \toyyunion{table-render:variable-definitions} % directives \restorecslist{parser-strict}\yyunion \defc\idit{% *ID :: \idit{12string}{tex_string}{fptr}{sptr} \termnameidit{#1}{#2}{#3}{#4}% } \defc\stringify{% *STRING :: \stringify{12string}{tex_string}{fptr}{sptr} \termnamestringify{#1}{#2}{#3}{#4}% } \defc\tagit{% *TAG :: \tagit{12string}{tex_string}{fptr}{sptr} \toksa{\\{#2}}% } \defc\anint{% INT :: \anint{digits}{fptr}{sptr} \toksa{#1}% } \defc\hexint{% INT :: \hexint{0[xX][0-9A-F]+}{fptr}{sptr} \toksa\expandafter{\eattwo#1$_{16}$}% } \toyyunion{table-render:directives} % rule listing macros \restorecslist{parser-prototypes}\yyunion % we just want to ignore the non-rule related code \defc\prodheader{% a `left-hand side' of a production :: \prodheader{\idit}{\idit}{fptr}{sptr} #1\relax \lastlastname\lastname \setnumname\numname \lastname{}% #2\relax \edef\next{\toksc{\numname:}\toksd{\noexpand\lhs{\the\lastlastname}{\the\lastname}}}\next } % the macros below are defined in `parser-prototypes' %\defp\rrhssep#1#2{} %\defp\arhssep#1#2{} %\defp\rarhssep#1#2{} %\defp\hspace#1#2{} %\defp\prodprodsep{} %\defp\onesymbol#1#2#3{} \defc\rhs{% a `right-hand side' :: \rhs{[\termname\hspace\rarhssep\arhssep\actbraces]+}{\arhssep|}{\ifrhsfull} \concat\toksa\toksc \concat\toksb\toksd #1\relax \edef\next{\toksb{\noexpand\onerule{\the\toksb}}}\next \appendr\toksa\def \possibleimplicitfalse \yyreplacestring\toksa\in\newsymswitch\with\toksb \toksa{}\toksb{}% } \newtoks\lastname \newtoks\lastlastname \defc\termname{% a production term :: \termname{\idit|\stringify|\charit}{\idit} \flushact #1\relax \lastlastname\lastname \setnumname\numname \lastname{}% #2\relax \appendr\toksa{ \numname}\appendr\toksb{\noexpand\term{\the\lastlastname}{\the\lastname}}% } \def\setnumname#1{% \expandafter\let\expandafter\next\csname term\parsernamespace\the\lastname \endcsname \ifx\next\relax % this is a terminal that was renamed \expandafter\ifx\csname token\parsernamespace\the\lastname \endcsname\relax % this is probably a symbol from another grammar \def#1{-1}% \errmessage{token \the\lastname\space is undefined}% \else \expandafter\tempca\csname token\parsernamespace\the\lastname \endcsname \edef#1{\fgetelemof{yytranslate}\at\tempca}% \fi \else \let#1\next \fi } \defc\actbraces{% action braces :: \actbraces{tex_string}{\idit|}{fptr}{sptr}directive*\bdend \flushact \lastname{}% #2\relax \edef\next{\lastactsym{\the\lastname}}\next \possibleimplicittrue } \defc\rules{#1}% a complete right-hand side :: \rules{[\rhs|\rrhssep]} \defc\oneproduction{#1}% a complete production :: \oneproduction{\prodheader\rules}{fptr}{sptr} \defc\emptyterm{% \flushact \lastname{}% } \defc\stringify{% *STRING :: \stringify{12string}{tex_string}{fptr}{sptr} \lastname{"#1"}% } \defc\idit{% *ID :: \idit{12string}{tex_string}{fptr}{sptr} \lastname{#1}% } \defc\charit{% *CHAR :: \charit{12string}{tex_string}{fptr}{sptr} \lastname{'#1'}% } \defc\anint{% INT :: \anint{digits}{fptr}{sptr} \lastname{#1}% } \defc\hexint{% INT :: \hexint{0[xX][0-9A-F]+}{fptr}{sptr} \lastname\expandafter{\expandafter\number\eattwo#1$_{16}$}% } \newtoks\lastactsym \newif\ifpossibleimplicit \def\flushact{% \ifpossibleimplicit \appendr\toksa{ @implicit@}\appendr\toksb{\noexpand\implicitterm{@implicit@}{\the\lastactsym}}% \lastactsym{}% \possibleimplicitfalse \fi } \savecslist{symbols}\yyunion %% token typesetting macros \def\prettynamecs#1#2{'parser'#1#2} % naming convention for token typesetting alternatives \def\setsafe#1{\def\saferword{#1}\setspecialcharsfrom\saferword} \def\prettyword#1{\setsafe{#1}\expandafter\edef\csname\prettynamecs\parsernamespace\saferword\endcsname##1{{\ntt\lowercase{\saferword}}}} \def\prettytoken#1{\setsafe{#1}\expandafter\edef\csname\prettynamecs\parsernamespace\saferword\endcsname##1{{\ntt\saferword}}} \def\prettytoken@#1{\toksa{}\numberstocharsandspaces#1\end\expandafter\edef \csname\prettynamecs\parsernamespace{\the\toksa}\endcsname##1{{\ntt\the\toksa}}% } \def\prettywordpair@@#1#2{\setsafe{#1}\expandafter\def\csname\prettynamecs\parsernamespace\saferword\endcsname##1{#2}} \def\prettywordpair#1#2{\prettywordpair@@{#1}{{\ntt@#2}}} \newif\ifdisplaytokenraw \def\prettywordpair@#1#2{% a `weak symbol' version of the above macro, so that the new typesetting can be overriden \setsafe{#1}\toksa{}\numberstocharsandspaces#2\end\expandafter\nameproc\expandafter{\the\toksa}\with\parsebin \expandafter\edef\csname\prettynamecs\parsernamespace\saferword\endcsname##1{% \noexpand\ifdisplaytokenraw {\ntt\saferword}% \ntt expands to \noexpand\ntt@ \noexpand\else {\ntt\def\noexpand\_{\char`\noexpand\_}\the\toksa}% \noexpand\fi }% } \def\prettywordpairwvis#1#2#3{% \prettywordpair{#1}{#2}% \expandafter\def\csname\viskeyref\parsernamespace{\saferword}\endcsname##1{#3}% } \def\prettywordpair@wvis#1#2#3{% \prettywordpair@{#1}{#2}% \expandafter\def\csname\viskeyref\parsernamespace{\saferword}\endcsname##1{#3}% } \def\prettywordpair@@wvis#1#2#3{% \prettywordpair@@{#1}{#2}% \expandafter\def\csname\viskeyref\parsernamespace{\saferword}\endcsname##1{#3}% } % a control sequence to reuse the token definition file for typesetting \newif\iftraceprettytokens % display prettyfying control sequences \def\tokeneqpretty#1#2{% \setsafe{#1}\toksa{}\numberstocharsandspaces#2\end \expandafter\nameproc\expandafter{\the\toksa}\with\parsebin \ifyyparsefail \toksc{{}$_{\rm m}${}}\toksd\toksa \else \toksc{}\toksd\toksb % quotes should trigger the creation of a visible key \fi \expandafter\edef\csname\prettynamecs\parsernamespace\saferword\endcsname##1{% \noexpand\ifdisplaytokenraw {\ntt\saferword}% \noexpand\else {\ntt\def\noexpand\_{\char`\noexpand\_}\the\toksa\the\toksc}% \noexpand\fi }% \expandafter\edef\csname\viskeyref\parsernamespace{\saferword}\endcsname##1{\the\toksd}% \iftraceprettytokens \message{token: \expandafter\meaning\csname\prettynamecs\parsernamespace\saferword\endcsname}% \message{visual key: \expandafter\meaning\csname\viskeyref\parsernamespace{\saferword}\endcsname}% \fi } % the bootstrap macros \def\initbootstrap{% \restorecslist{bootstrap}\yyunion } \restorecslist{parser-prototypes}\yyunion \defc\tokendecls{#1}% token declarations :: \tokendecls{[\onesymbol]+}{fptr}{sptr} \defc\stringify{\toksa{"#1"}}% *STRING :: \stringify{12string}{tex_string}{fptr}{sptr} \defc\idit{\toksb{#1}}% *ID :: \idit{12string}{tex_string}{fptr}{sptr} %\def\anint#1#2#3{\toksc{#1}}% this definition is not needed as all % the information is extracted from yytname % note that the definitions below do not handle cases such as %token '{' "left brace" since the lexer knows how to return '{' \defc\onesymbol{%#1#2#3 % a symbol definition :: \onesymbol{\idit}{\anint|\hexint}{\stringify} \toksa{}\toksb{}%\toksc{}% #1#2#3% \yytoksempty\toksa{\expandafter\charstonumbers\the\toksb\end}% {\expandafter\toksa\expandafter{\expandafter}\expandafter\charstonumbers\the\toksa\end}% \yytoksempty\toksb{% \yytoksempty\toksa{}{% \immediate\write\tokendefs{\noexpand\tokeneq{\the\toksb}{\the\toksa}}% }% }{% \immediate\write\tokendefs{\noexpand\tokeneq{\the\toksb}{\the\toksa}}% }% } % the original, minimal bootstrapping macros were designed to process % \prodstyle{\%token} declarations only and are enough to establish the % interface between the \bison\ parser and the \bison\ lexer; to serve % the secondary task of providing typesetting information to % the \bison\ parser, all forms of token declarations must be processed; % % note that the bootstrap parser cannot process these additional declarations % so these macros are designed to work with a full or prologue parser % in a bootstrap mode; see \.{\\modebootstrap} in ldman.w and % its use in \.{ldlex.w} and \.{ldgram.w} for an example of such % an arrangement. \def\precdecls#1#2#3#4#5{#3} \def\symbolprec#1#2{% \toksa{}\toksb{}% #1% \yytoksempty\toksb{}{\immediate\write\tokendefs{\noexpand\tokenpp{\the\toksb}}}% } \savecslist{bootstrap}\yyunion % correct a few macros for debugging \restorecslist{parser-debug}\yyunion \defc\actbraces{% action braces :: \actbraces{tex_string}{\idit|}{fptr}{sptr}directive*\bdend \noexpand\actbraces{#1}{#2}{#3}{#4}#5\noexpand\bdend } \defc\bpredicate{% predicate :: \bpredicate{tex_string}{}{fptr}{sptr}directive*\bdend \noexpand\bpredicate{#1}{}{#3}{#4}#5\noexpand\bdend } \defc\rhs{% a `right-hand side' :: \rhs{[\termname\hspace\rarhssep\arhssep\actbraces]+}{\arhssep|}{\ifrhsfull} \noexpand\rhs{#1}{#2}{}% omit setting the conditional } \toyyunion{parser-debug} % \romannumeral-expandable macros for character translation \def\charstonumbersre#1\end{\charstonumbersr@0\end#1\end} \def\charstonumbersr@#1\end#2\end{% \yystringempty{#2}{#1}% {\yystartsinspace{#2}{\expandafter\charstonumbers@@swap\expandafter{\number`\ }{#1}#2\end}{\charstonumb@rsr@#1\end#2\end}}% } \def\charstonumb@rsr@#1\end#2{% \expandafter\charstonumbersr@swap\expandafter{\number`#2}{#1}% } \def\charstonumbersr@swap#1#2{\charstonumbersr@#2{#1}\end} \def\charstonumbers@@swap#1#2 {\charstonumbersr@#2{#1}\end} % variations: set \toksa to the expansion, \edef-expandable version \def\charstonumbers#1\end{\toksa\expandafter{\romannumeral\charstonumbersre#1\end}} \def\charstonumberse#1\end{\romannumeral\charstonumbersre#1\end} % name parser macros: currently only one suffix is handled, the very last one \def\yyuniontag{\yynpunion} \def\parserstrictnamespace{nameparser-strict} \def\parserprototypesnamespace{nameparser-strict:headers} \def\parserdebugnamespace{nameparser-debug} \def\yynpunion{\currentyyunionnamespace} \defp\idstr#1#2{} % idenifier :: \defp\bidstr#1#2{} % bison variable :: \defp\chstr#1#2{} % character :: \defp\sfxi#1#2{} % literal suffix :: \defp\sfxn#1#2{} % integer suffix :: \defp\dotsp{} % suffix separator :: \defp\optstr#1#2{} % option :: \defp\qual#1#2{} % qualifier :: \defp\visflag#1#2{} % visible key change flag :: \toyyunion{nameparser-prototypes} \defc\idstr{% \appendrnx\toksa{#1}% \appendrnx\toksc{#2}% \toksb{}% } \defc\bidstr{% \appendrnx\toksa{{}$\Upsilon${}}% \appendrnx\toksc{#2}% \toksb{}% } \defc\chstr{% \appendrnx\toksa{{\ntt@#1}}% \appendrnx\toksc{#2}% \toksb{}% } % the \toksb, set in the next two macros is used by \optstr later \defc\sfxi{\toksb{\/${}_{\idxfont#1}$}\appendrnx\toksa{\/${}_{\idxfont#1}$}} \defc\sfxn{\toksb{#1}\appendrnx\toksa{#1}} \defc\dotsp{\futurelet\next\d@tsp} \def\d@tsp{% \ifx\next\sfxi \else \ifx\next\qual \else \appendrnx\toksa{.}% \fi \fi } \defc\optstr{% \toksb\expandafter{\eatone#1}% \optstrextra \concat\toksa\toksb \appendrnx\toksc{#2}% \toksb{}% } \def\optstrextra{% \edef\next{\toksb{{$\nx\ulcorner$\ntt\the\toksb$\nx\urcorner$}}}\next } \def\optstrextraesc{% \edef\next{\toksb{{$\nx\langle$\ntt\the\toksb$\nx\rangle$}}}\next } \defc\qual{\appendrnx\toksd{\/${}_{\rm#2}$}\toksb{}} \let\idxfont\relax \defc\visflag{\toksf{#1}\appendrnx\tokse{#1}}% flag visible key change % \toksf contains the typesetting hint sequence \toyyunion{nameparser} \newtoks\namechars \newif\iftracebadnames \newif\iftracenames \def\viskeyref#1#2{% getting the possible visual key from the index key % #1 is the namespace of the original key % #2 is the key \restorecsname{[nameparser:visual]}{.\prettynamecs{#1}{#2}}% } % ignore explicit (\ ) spaces while parsing names % the macro will be called whenever \tosmallparser is executed (see yyinit.sty); % this is neccessary due to a shortcut taken by the macros that display % \bison\ productions in text (see \beginprod macros in yyinit.sty). \def\ignoreexplicitspace{\yyinput} % the main name processing routine % does not have any side effects (other than the ones explicitly produced by the final call of #2); % the parsed term is returned as #1 of the sequence in #2; #2 of #2 will hold a visual key if % one exists, otherwise it will be empty; #3 is \yyparsefailtrue or empty % #4 is the prettyfied version of the term if one exists; #5 is the typesetting hint from \visflag sequences; % the version below prettifies tokens only if the parsing was successful; if % needed, prettyfication may be applied after the parsing is complete \def\nameproc#1\with#2{% {% keeping all changes local \iftracenames \toksa{#1}\ferrmessage{original name: \the\toksa}% \fi \tosmallparser\basicparserinit\d@parse{#1}% \ifyyparsefail \iftracebadnames \toksa{#1}\ferrmessage{bad name: \the\toksa}% \fi \toksb{#2{#1}{}{\yyparsefailtrue}{}{}}% \else \npbuildnames{#2}% \fi \expandafter }\the\toksb } \def\npbuildnames#1{% \iftracenames \ferrmessage{parsed name (namespace: \parsernamespace): \the\namechars}% \fi \toksa{}\toksb{}\toksc{}\toksd{}\tokse{}\toksf{}% \restorecslist{nameparser}\yynpunion \the\namechars\relax \iftracenames \ferrmessage{processed name: \the\toksa, \the\toksb, % \the\toksc, \the\toksd, \the\tokse}% \fi \expandafter\npsetkeys\expandafter{\the\toksc}% \iftracenames \ferrmessage{final name: \the\toksa\yytoksempty\toksc{}{, prettyfied name: \the\toksc}% \yytoksempty\toksf{}{, hint: \the\toksf}% \yytoksempty\tokse{}{, visual key: \the\tokse}, % parsing \ifyyparsefail failed\else successful\fi }% \fi \toksb{#1}% \edef\next{% \toksb{% \the\toksb {\the\toksa}% the parsed name {\the\tokse}% the visual key {}% parseflag {\the\toksc}% the prettified name {\the\toksf}% the typesetting hint }% }\next } \def\npsetkeys#1{% \expandafter\ifx\csname\prettynamecs\hostparsernamespace{#1}\endcsname\relax \toksc{}% \else \toksc\expandafter{\csname\prettynamecs\hostparsernamespace{#1}\endcsname}% \appendr\toksc{{\currentrulecontext}\the\toksb\the\toksd}% \toksf{\termidstring}% \fi \concat\toksa\toksd % changes \toksa and \toksc, no need for \toksb or \toksd after this \expandafter\ifx\csname\viskeyref\hostparsernamespace{#1}\endcsname\relax % no special visual key for this token \yybreak{% \yytoksempty\tokse{}{\makeviskeydirect}% if the visual key changed, output the key, % attempt to compute it form the parsed output }% \else \yybreak{\makeviskeyfrompretty{#1}}% modify the production of the visible key to use the % prettified version \yycontinue % changes \toksb, \toksd, and \tokse } % standard postprocessing function \def\parsebin#1#2#3#4#5{% \yystringempty{#4}{% \yystringempty{#3}{\toksa{\eatone{#5}#1}}{\toksa{#1}}% }{% \yystringempty{#3}{\toksa{\eatone{#5}#4}}{\toksa{#4}}% }% \toksb{#2}% \yystringempty{#3}{\yyparsefailfalse}{\yyparsefailtrue}% } % creating a visual key from the stored visual key and the sufixes \restorecslist{nameparser-prototypes}\yynpunion % make most sequences do nothing \defc\qual{\toksb{#2}\concat\toksd\toksb} \toyyunion{nameparser:vispretty} \def\makeviskeyfrompretty#1{% \edef\next{\tokse{\expandafter\expandafter\csname\viskeyref \hostparsernamespace{#1}\endcsname\expandafter{\currentrulecontext}}}\next \restorecslist{nameparser:vispretty}\yynpunion% \toksd{}% \the\namechars \yytoksempty\toksd{}{\appendr\tokse.\concat\tokse\toksd}% } % creating a visual key directly from parsed output \restorecslist{nameparser-strict}\yynpunion \defc\idstr{\toksb{#2}\concat\tokse\toksb} \defc\bidstr{\toksb{#2}\concat\tokse\toksb} \defc\chstr{\toksb{#2}\concat\tokse\toksb} \defc\sfxi{\toksb{#2}\concat\tokse\toksb} \defc\sfxn{\toksb{#2}\concat\tokse\toksb} \defc\dotsp{\appendr\tokse.} \defc\optstr{\toksb{#2}\concat\tokse\toksb} \defc\qual{\toksb{#2}\concat\tokse\toksb} \defc\visflag{} \toyyunion{nameparser:visdirect} \def\makeviskeydirect{% \tokse{}% \restorecslist{nameparser:visdirect}\yynpunion \the\namechars } \restorecslist{nameparser-strict}\yynpunion % \flex\ regex typesetting routine and \flex\ parser value stack types \def\flrecharadjust{ `{% \yybyte{|}% \expandafter\yycp@\expandafter`\the\yybyte\relax \mkpurebyte \yyreturn }% } % no need for \setspecialcharsfrom\flrecharadjust \def\frexproc#1\with#2{% {% keeping all changes local \iftracenames \toksa{#1}\ferrmessage{original regex: \the\toksa}% \fi \toflexreparser \let\acharswitch\flrecharadjust \basicparserinit \flexreparserinit \flexreparserdatainit \d@parse{\ #1}% the parsed regex is put in the \table register \ifyyparsefail \iftracebadnames \toksa{#1}\ferrmessage{bad regex: \the\toksa}% \fi \toksb{#2{#1}{}{\yyparsefailtrue}}% \else \toksd{#1}% \frebuildx{#2}% \fi \expandafter }\the\toksb } \def\frebuildx#1{% \toksb{#1}\toksc{}% \restorecslist{flexparser-re}\yyflunion \the\table % typeset the regex (appears in \toksc) \edef\next{% \toksb{% \the\toksb % the name of the processing routine {\the\toksd}% the original regex {\the\toksc}% processed regex (or empty) {}% parse flag }% }\next } \def\ppregex#1#2#3{% \toksc{#2}% } \def\setregextable{% activate the appropriate AST control sequences \def\aststream{flex.sect2}% the list where the AST output is gathered \restorecslist{flexparser-sect2}\yyflunion } \def\setregexdeftable{% \def\aststream{flex.sect1}% the list where the AST output is gathered \restorecslist{flexparser-sect1}\yyflunion } % \flex\ parser indexing macros \def\flexidxdomain{F} \def\fstatedefidxrank{0} \def\fstateidxrank{1} \def\fregexidxrank{2} \def\ftextrefrank{5} \def\writeidxfsentry#1{% \flex\ state reference entry \indxe\gindex{{\secno}{{}{\flexpseudonamespace}}{\flexidxdomain}{\fstateidxrank}#1}% } \def\writeidxfstextentry#1{% \flex\ state reference in text \indxe\gindex{{\secno}{{}{\flexpseudonamespace}}{\flexidxdomain}{\ftextrefrank}#1}% } \def\writeidxfsdentry#1{% \flex\ state definition entry \indxe\gindex{{\secno}{{}{\flexpseudonamespace}}{\flexidxdomain}{\fstatedefidxrank}#1}% } \def\writeidxfsrdentry#1{% \flex\ regex name definition entry \indxe\gindex{{\secno}{{}{\flexpseudorenamespace}}{\flexidxdomain}{\fstatedefidxrank}#1}% } \def\writeidxfsrnentry#1{% \flex\ regex name entry \indxe\gindex{{\secno}{{}{\flexpseudorenamespace}}{\flexidxdomain}{\fregexidxrank}#1}% } \def\writeidxfscclentry#1{% \flex\ chracter class name entry \indxe\gindex{{\secno}{{}{\flexpseudonamespace}}{\flexidxdomain}{\fregexidxrank}#1}% } % \flex\ parser typesetting macros and stack types \def\yyuniontag{\yyflunion} \def\parserstrictnamespace{flexparser-strict} \def\parserprototypesnamespace{flexparser-strict:headers} \def\parserdebugnamespace{flexparser-debug} \def\yyflunion{\currentyyunionnamespace} \defp\flnametok#1#2{} % named definition :: \flnametok{matched text}{formatting command}, the text is \{text\}\ * % \defp\flcclexpr#1#2#3#4{} % character class expression :: \flcclexpr{matched text}{ccl token}{fptr}{sptr} \defp\flchar#1#2#3#4{} % character :: \flchar{char}{char12}{fptr}{sptr} \defp\flstring#1#2#3{} % string :: \flstring{{fptr}{sptr}}{\flchar{...}*}{{fptr}{sptr}} \defp\flcclrnge#1#2{} % character range :: \flcclrnge{/flchar{...}}{/flchar{...}} \defp\flbraceccl#1#2#3{} % character class :: \flbraceccl{{fptr}{sptr}}{ccl}{{fptr}{sptr}} \defp\flbracecclneg#1#2#3{} % negative character class :: \flbracecclneg{{fptr}{sptr}}{ccl}{{fptr}{sptr}} \defp\flcclunion#1#2{} % union of character classes :: \flcclunion{ccl}{ccl} \defp\flccldiff#1#2{} % difference of character classes :: \flccldiff{ccl}{ccl} \defp\flrepeat#1{} % * (asterisk) operation :: \flrepeat{re} \defp\flrepeatstrict#1{} % + (plus) operation :: \flrepeatstrict{re} \defp\flrepeatonce#1{} % ? operation :: \flrepeatonce{re} \defp\flrepeatnm#1#2#3{} % {n, m} operation :: \flrepeatnm{re}{num}{num} \defp\flrepeatgen#1#2{} % {n,} operation :: \flrepeatgen{re}{num} \defp\flrepeatn#1#2{} % {n} operation :: \flrepeatn{re}{num} \defp\flparens#1#2#3#4{} % parenthesized regular expression :: \flparens{{fptr}{sptr}}{re}{{fptr}{sptr}}{formatting command} \defp\fldot#1#2{} % . (dot) expression :: \fldot{fptr}{sptr} \defp\flor#1#2{} % `|' expression :: \flor{fptr}{sptr} \defp\fltrail#1#2{} % regular expression sans trailing suffix :: \fltrail{re}{{fptr}{sptr}} \defp\flretrail#1#2#3{} % regular expression with a trailing context :: \flretrail{re}{{fptr}{sptr}}{re} \defp\flreateol#1#2#3{} % regular expression with the end of line as a trailing context :: \flreateol{re}{fptr}{sptr} \defp\flrule#1#2{} % full regular expression :: \flrule{re}{formatting command} \defp\flbolrule#1#2{} % full regular expression at the beginning of the line :: \flbolrule{re}{formatting command} \defp\fleof#1#2{} % end of file rule :: \fleof{fptr}{sptr} \defp\flsconlist#1#2#3{} % start condition list :: \flsconlist{{fptr}{sptr}}{\flname...}{{fptr}{sptr}} \defp\flsconuniv#1#2{} % universal start condition :: \flsconuniv{fptr}{sptr} \defp\flnamesep#1#2{} % separator between names :: \flnamesep{fptr}{sptr} \defp\flname#1#2#3#4{} % name :: \flname{name}{name12}{fptr}{sptr} \defp\flopt#1#2#3#4#5{} % \flex option :: \flopt{option}{text}{text12}{fptr}{sptr} \defp\floptions#1{} % \flex options :: \floptions{\flopt ...} \defp\flscondecl#1#2#3#4{} % start condition declarations :: \flscondecl{x|s}{fptr}{sptr}{\flname ...} \defp\flaction#1#2#3#4#5#6#7{} % \flex action :: \flaction{\flsconlist...}{\fl..rule ...}{fptr}{sptr}{fptr}{sptr}{formatting command} \defp\flactionc#1#2#3#4#5#6#7{} % \flex continued action :: \flaction{\flsconlist...}{\fl..rule ...}{fptr}{sptr}{fptr}{sptr}{formatting command} \defp\flactiongroup#1#2#3#4#5#6{} % a group of \flex actions :: \flactiongroup{\flsconlist...}{fptr}{sptr}{\flaction...}{fptr}{sptr} \defp\flbareaction#1#2#3#4#5#6{} % bare action :: \flbareaction{fptr}{sptr} \defp\flptropt#1#2{} % %ponter directive :: \flptropt{fptr}{sptr} \defp\flarrayopt#1#2{} % %array directive :: \flarrayopt{fptr}{sptr} \defp\fltopopt#1#2#3#4{} % %top directive :: \fltopopt{fptr}{sptr}{fptr}{sptr} \defp\flredef#1#2#3#4#5#6#7#8{} % regular expression definition :: \flredef{name}{name12}{fptr}{sptr}{text}{text12}{fptr}{sptr} \toyyunion{flexparser-prototypes} \restorecslist{flexparser-strict}\yyflunion \defc\flrule{%#1#2% full regular expression :: \flrule{re}{formatting command} {\toksc{}#1#2\expandafter}\expandafter\toksd\expandafter{\the\toksc}% \concat\toksc\toksd } \newif\iftextre % check if this is a free standing regular expression or appears in the definitions table \defc\flbolrule{%#1#2% full regular expression at the beginning of the line :: \flbolrule{re}{formatting command} {\toksc{}#1#2\appendlnx\toksc{\raise0.5pt% \iftextre\yybreak{\hbox}\else\yybreak{\llap}\yycontinue{\sscmd$\dashv$\ }}\expandafter}\expandafter% \toksd\expandafter{\the\toksc}\concat\toksc\toksd } \let\astformat@flrule\empty \def\inscomment#1{% insert a comment before the rule \def\astformat@flrule{% \appendlnx\toksc{\noalign{#1}}% }% } \def\insrulealign#1#2{% \def\astformat@flrule{% \tokse{#1}\toksf{#2}% \concatl\tokse\toksc \concat\toksc\toksf }% } \def\rulealigntemplate{% to hide the hash symbols from \\edef operators \vbox\bgroup\halign\bgroup##\hfil&##\hfil\cr } % regular expression symbols \defc\flstring{%#1#2#3% string :: \flstring{{fptr}{sptr}}{\flchar{...}*}{{fptr}{sptr}} % \toksc\expandafter{\the\toksc\hbox{#2}}% #2% } \defc\flnametok{%#1#2% named definition :: \flnametok{matched text}{formatting command}, the text is \{text\}\ * \let\termindex\writeidxfsrnentry \fln@metok#1\end{#2}% \let\termindex\eatone } \def\fln@metok\{#1\}#2\end#3{% {% \let\hostparsernamespace\flexpseudorenamespace \nameproc{#1}\with\parsebin \edef\next{% \toksd{\toksd{\the\toksa}\tokse{\the\toksb}}% }\next % a trick to `reshuffle' the output of \nameproc: % the parsed name goes to \toksd and the visual key is put in \tokse \expandafter }\the\toksd \toksf{}\toksg{}% #3% \edef\next{% \toksc{\the\toksc\the\toksf{}\nx\flexrendisplay{\the\toksd}% \gidxentryxv{\termfsrestring}{#1}{\the\tokse}\the\toksg }% }\next } \def\insnamealign#1#2{% \def\astformat@flnametok{% \toksf{#1}% \toksg{#2}% }% } \let\astformat@flnametok\empty \defc\flchar{%#1#2#3#4% character :: \flchar{char}{char12}{fptr}{sptr} \yystringempty{#2}{#1}{\flch@r#2\end}% } \def\flch@r#1#2\end{% \ifnum`#1=`\\ \fl@h@r#2\end \else \toksc\expandafter{\the\toksc{\ntt#1#2}}% \fi } \def\fl@h@r#1#2\end{% process the sequence after an escape {% \let\default\flescdefault \tokse{#1}\toksd{#2}% \switchon{\the\tokse}\in\flesccharswitch \edef\next{\toksc{\toksc{\the\toksc\the\toksd}}}\next \expandafter }\the\toksc } \def\flesccharswitch{% recognizing different types of escape sequences 01234567 {% octal constant \edef\next{\toksd{\nx\.{\the\tokse\the\toksd}$_8${}}}\next } nfrtabv {% \Cee\ escape sequence \edef\next{\toksd{{\nx\sscmd\nx\sscmd$\nx\langle$\nx\.{\the\tokse\the\toksd}$\nx\rangle$}}}\next } x {% hexadecimal constant \edef\next{\toksd{\nx\.{\the\toksd}$_{16}${}}}\next } } \def\flescdefault{% \edef\next{\toksd{\nx\.{\the\tokse\the\toksd}}}\next } \setspecialcharsfrom\flesccharswitch \defc\fldot{%#1#2% dot expression :: \fldot{fptr}{sptr} \toksc\expandafter{\the\toksc.}% } \defc\flparens{%#1#2#3#4% parenthesized regular expression :: \flparens{{fptr}{sptr}}{re}{{fptr}{sptr}}{format command} {\toksc{}#2\expandafter}\expandafter\toksd\expandafter {\the\toksc{\rm)}}% \toksf{}\toksg{}#4% \tokse\expandafter{\the\toksf{\rm(}}% \concatl\tokse\toksd \concat\toksc\toksd \concat\toksc\toksg } \def\insparensalign#1#2{% \def\astformat@flparens{% \toksf{#1}% \toksg{#2}% }% } \let\astformat@flparens\empty \defc\flrepeat{%#1% asterisk operation :: \flrepeat{re} {\toksc{}#1\expandafter}\expandafter\toksd\expandafter {\the\toksc{{}${}_{*}$}}% \flselectiveseparator \concat\toksc\toksd% } \defc\flrepeatn{%#1#2% {n} operation :: \flrepeatn{re}{num} {\toksc{}#1\expandafter}\expandafter\toksd\expandafter {\the\toksc{{}${}_{\{\yyfirstoftwo#2\}}$}}% \flselectiveseparator \concat\toksc\toksd% } \defc\flrepeatnm{%#1#2#3% {n, m} operation :: \flrepeatnm{re}{num}{num} {\toksc{}#1\expandafter}\expandafter\toksd\expandafter {\the\toksc{{}${}_{\{\yyfirstoftwo#2,\yyfirstoftwo#3\}}$}}% \flselectiveseparator \concat\toksc\toksd% } \defc\flrepeatonce{%#1% ? operation :: \flrepeatonce{re} {\toksc{}#1\expandafter}\expandafter\toksd\expandafter {\the\toksc{{}${}_{?}$}}% \flselectiveseparator \concat\toksc\toksd% } \defc\flrepeatstrict{%#1% plus operation :: \flrepeatstrict{re} {\toksc{}#1\expandafter}\expandafter\toksd\expandafter{\the\toksc{{}${}_{+}$}}% \flselectiveseparator \concat\toksc\toksd% } \def\flselectiveseparator{% \yytoksempty\toksc{}{% \tokse{{{}$\,$}}% \concatl\tokse\toksd }% } \defc\flcclrnge{%#1#2% character range :: \flcclrnge{\flchar{...}}{\flchar{...}} % \toksd{#1}\getfirst\toksd\to\toksd % \tokse{#2}\getfirst\tokse\to\tokse #1\appendr\toksc{{\nx\rm--}}#2% % \edef\next{\toksc{\the\toksc\the\toksd{\nx\rm--}\the\tokse}}\next } \defc\flcclexpr{%#1#2#3#4% character class expression :: \flcclexpr{matched text}{ccl token}{fptr}{sptr} {% \let\hostparsernamespace\flexpseudonamespace \nameproc{#2}\with\parsebin \edef\next{% \toksd{\toksd{\the\toksa}\tokse{\the\toksb}}% }\next % a trick to `reshuffle' the output of \nameproc: % the parsed name goes to \toksd and the visual key is put in \tokse \expandafter }\the\toksd \let\termindex\writeidxfscclentry \edef\next{\toksc{\the\toksc{\the\toksd}% \gidxentryxv{\termidstring}{#2}{\the\tokse}% }}\next \let\termindex\eatone } \defc\flbraceccl{%#1#2#3% character class :: \flbraceccl{{fptr}{sptr}}{ccl}{{fptr}{sptr}} \appendrnx\toksc{{}$[${}}% #2% \appendrnx\toksc{{}$]${}}% } \def\flbraceccldemo#1#2#3{% character class :: \flbraceccl{{fptr}{sptr}}{ccl}{{fptr}{sptr}} % a demo version without the beginning bracket \appendrnx\toksc{{}$\ldots${}}% #2% \appendrnx\toksc{{}$]${}}% } \defc\flccldiff{%#1#2% difference of character classes :: \flccldiff{ccl}{ccl} #1% \appendr\toksc{${}\nx\setminus{}$}% #2% } \defc\flbracecclneg{%#1#2#3% negative character class :: \flbracecclneg{{fptr}{sptr}}{ccl}{{fptr}{sptr}} \appendr\toksc{{}$[${}}% #2% \appendr\toksc{{}$]^c${}}% } \defc\fleof{%#1#2% end of file rule :: \fleof{fptr}{sptr} \let\termindex\writeidxfsrnentry \edef\next{\toksc{\the\toksc{}\nx\flexrendisplay{EOF}% \gidxentry{\termfsrestring}{EOF}{EOF}}}\next \let\termindex\eatone } \defc\flor{%#1#2% `|' expression :: \flor{fptr}{sptr} \appendr\toksc{{}${}\nx\mid{}${}}% } \defc\flsconuniv{%#1#2% universal start condition :: \flsconuniv{fptr}{sptr} \let\termindex\writeidxfsentry \edef\next{\toksb{\the\toksb{}$\langle*\rangle${}% \gidxentryxv{\termvstring}{*}{*}}}\next % TODO: create a separate name space for state names \let\termindex\eatone } \defc\fltrail{%#1#2% regular expression sans trailing suffix :: \fltrail{re}{{fptr}{sptr}} \errmessage{\nx\fltrail\space macro has should not be expanded.} } \defc\flretrail{%#1#2#3% regular expression with a trailing context :: \flretrail{re}{{fptr}{sptr}}{re} % #1 is the regular expression to be matched % #2 is the pointer to the context marker (/) % #3 is the context \errmessage{\nx\flretrail\space macro has not been implemented (see yyunion.sty).} } \defc\flreateol{%#1#2#3% regular expression with the end of line as a trailing context :: \flreateol{re}{fptr}{sptr} {\toksc{}#1\expandafter}\expandafter\toksd\expandafter{\the\toksc{\raise0.5pt\rlap{\sscmd\ $\vdash$}}}% \concat\toksc\toksd% } \toyyunion{flexparser-re} \def\flexsndisplay#1{% state name typesetting style {\let\ntt@\relax\idss#1}% } \def\flexrendisplay#1{% regular expression name typesetting style \penalty-100 \hbox{$\langle$\tt#1$\rangle$}% } \def\flexsnstyle#1{% typesetting \flex\ state names in text {% \let\parsernamespace\flexpseudonamespace \nameproc{#1}\with\parsebin \edef\next{% \toksd{\the\toksa}\tokse{\the\toksb}% }\next % a trick to `reshuffle' the output of \nameproc: % the parsed name goes to \toksd and the visual key is put in \tokse \let\termindex\writeidxfstextentry \edef\next{\toksd{\nx\flexsndisplay{\the\toksd}% \gidxentryxv{\termfsscstring}{#1}{\the\tokse}}}\next \expandafter }\the\toksd } \def\flexrenstyle#1{% typesetting \flex\ regular expression names in text {% \let\parsernamespace\flexpseudorenamespace \nameproc{#1}\with\parsebin \edef\next{% \toksd{\the\toksa}\tokse{\the\toksb}% }\next % a trick to `reshuffle' the output of \nameproc: % the parsed name goes to \toksd and the visual key is put in \tokse \let\termindex\writeidxfstextentry \edef\next{\toksd{\nx\flexrendisplay{\the\toksd}% \gidxentryxv{\termfsrestring}{#1}{\the\tokse}}}\next \expandafter }\the\toksd } \def\flexrestyle#1{% typesetting \flex\ regular expressions in text {% \frexproc{#1}\with\ppregex \edef\next{\toksc{\toksc{\the\toksc}}}\next \expandafter }\the\toksc \hbox{\textretrue\tt\the\toksc}% } % \flex\ section~2 typesetting \defc\flactiongroup{% #1#2#3#4#5#6% a group of \flex actions :: \flactiongroup{\flsconlist...}{fptr}{sptr}{\flaction...}{fptr}{sptr} \toksb{}#1% collect all the state name information in \toksb % gather the preceeding stash \readstash{#3}% read stash late, after \flsconlist (ignore it) \edef\next{% \toksb{\noalign{\hbox to\nx\hsize{\hskip\the\rgindent \nx\flexsndisplay{\the\toksb$^{++}$}\toksa{\relax\the\toksg}\nx\makestashbox\nx\hfil}}}% }\next \astisempty{}{\astappend{\noalign{\medskip}}}% \astappendx{\the\toksb}% \advance\rgindent by\parindent #4% \advance\rgindent by-\parindent } \defc\flsconlist{% #1#2#3% start condition list :: \flsconlist{{fptr}{sptr}}{\flname...}{{fptr}{sptr}} \readstashwredirect#1\toksg % save the stash preceeding the conditions list to reinsert later \savecslist{local-namespace}\yyflunion \restorecslist{flexparser-sect2:state-name-display}\yyflunion #2% collect the state names (and the stash in between) \restorecslist{local-namespace}\yyflunion \readstashwredirect#3\toksf \appendr\toksb{\nx\rm\toksa{\the\toksf}\nx\makestashbox}% } \newskip\rgindent \rgindent=\parindent \def\appendinteractionskip{% \ifnum\prevdepth<\dp\strutbox \vskip-\prevdepth\vskip\dp\strutbox \fi \nointerlineskip } \def\flaction@generic#1#2#3#4#5{% #1 is the #1 of \flaction.* % #2 is the #2 of \flaction.* % #3 is the #6 of \flaction.* % #4 is the #7 of \flaction.* % #5 is the \toksa prefix (should be expandable) \toksb{}#1% collect all the state name information in \toksb \toksc{}#2% #4% apply formatting \readstash{#3}% read stash late, after \flsconlist and \fl...rule \yytoksempty\toksb{% no state names were collected \astappendx{\hskip\the\rgindent\hbox{\nx\tt\nx\strut\the\toksc}}% }{% put state names first \astisempty{}{\astappend{\noalign{\medskip}}}% \astappendx{% \noalign{\nx\appendinteractionskip}% \hskip\the\rgindent \vbox{% %{\nx\sscmd\nx\expandafter}\nx\expandafter\baselineskip\nx\the\baselineskip % the line above would allow a smaller vertical skip to be inserted in case % the font for state names is reduced in size; \halign{&####\hfil\cr \flexstatelisttypeset\cr \hskip\parindent\nx\tt\nx\strut\the\toksc\cr }% }% }% }% \astappendx{&\toksa{#5\relax\the\yystashlocal}\nx\cr}% } \def\flexstatelisttypeset{% \hbox to\rgindent{% \vbox{\advance\hsize by -\rgindent \noindent \nx\strut\nx\flexsndisplay{\the\toksb$^+$} }\hss }% } \defc\flaction{%#1#2#3#4#5#6#7% \flex action :: \flaction{\flsconlist...}{\fl..rule ...}{fptr}{sptr}{fptr}{sptr}{formatting command} \flaction@generic{#1}{#2}{#6}{#7}{}% } \defc\flactionc{%#1#2#3#4#5#6#7% \flex action :: \flaction{\flsconlist...}{\fl..rule ...}{fptr}{sptr}{fptr}{sptr}{formatting command} \flaction@generic{#1}{#2}{#6}{#7}{{}$\nx\hookleftarrow$}% } \def\inscomment#1{% \def\astformat@flaction{% \toksd{#1}% \astappendx{\noalign{\nx\smallskip\noindent\hskip\the\rgindent $\nx\triangleright\;$\the\toksd\nx\smallskip}}% }% } \let\astformat@flaction\empty \toyyunion{flexparser-sect2} % flex state names display inside action groups \restorecslist{flexparser-strict}\yyflunion \defc\flname{% #1#2#3#4% name :: \flname{name}{name12}{fptr}{sptr} {% \let\parsernamespace\flexpseudonamespace \nameproc{#1}\with\parsebin \edef\next{% \toksd{\toksd{\the\toksa}\tokse{\the\toksb}}% }\next % a trick to `reshuffle' the output of \nameproc: % the parsed name goes to \toksd and the visual key is put in \tokse \expandafter }\the\toksd \let\termindex\writeidxfsentry \readstashwredirect{}{#4}\toksf % do not touch \yystashlocal \appendr\toksb{{\nx\rm\toksa{\the\toksf}\nx\makestashbox}% \the\toksd\gidxentryxv{\termfsscstring}{#1}{\the\tokse}}% \let\termindex\eatone } \defc\flnamesep{%#1#2% separator between names :: \flnamesep{fptr}{sptr} \toksb\expandafter{\the\toksb\ }% } \toyyunion{flexparser-sect2:state-name-display} % \flex\ section~1 typesetting \restorecslist{flexparser-strict}\yyflunion \defc\flredef{%#1#2#3#4#5#6#7#8% regular expression definition :: \flredef{name}{name12}{fptr}{sptr}{text}{text12}{fptr}{sptr} \let\termindex\writeidxfsrdentry {% \let\hostparsernamespace\flexpseudorenamespace \nameproc{#1}\with\parsebin \edef\next{% \toksd{\toksd{\the\toksa}\tokse{\the\toksb}}% }\next % a trick to `reshuffle' the output of \nameproc: % the parsed name goes to \toksd and the visual key is put in \tokse \expandafter }\the\toksd \frexproc{#5}\with\ppregex \astappendx{{}$\nx\langle\hbox{\ntt\the\toksd}\nx\rangle${}% \gidxentryxv{\termfsrestring}{#1}{\the\tokse}&\the\toksc\cr }% \let\termindex\eatone } % \flex\ options \defc\floptions{%#1 \flex options :: \floptions{\flopt ...} #1% } \defc\flopt{%#1#2#3#4#5% \flex option :: \flopt{option}{text:(no||opt_name)}{text12}{fptr}{sptr} \expandafter\ifx\csname flex@ption_#1\endcsname\relax \yybreak{% \errmessage{!option <#1> with value (#3) is not handled.}% }% \else \yybreak{% \csname flex@ption_#1\endcsname{#2}{#3}{#4}{#5}% }% \yycontinue } % specific options \expandafter\def\csname flex@ption_other\endcsname#1#2#3#4{% \let\termindex\writeidxfsrnentry \storerawidxentry{\tt{\rm(}#1{\rm)}#2}% \astappendx{$\nx\langle${\ntt option}$\nx\rangle_{\nx\rm f}$% \gidxentryxv{\termfsopstring}{option}{option}% \yystringempty{#1}{% \gidxentry{\termttstring}{#2}{#2}% index the