diff options
Diffstat (limited to 'support/splint/tex')
30 files changed, 6193 insertions, 2217 deletions
diff --git a/support/splint/tex/btokenset.sty b/support/splint/tex/btokenset.sty index 07affb717e..72d3b3394f 100644 --- a/support/splint/tex/btokenset.sty +++ b/support/splint/tex/btokenset.sty @@ -1,4 +1,4 @@ -% Copyright 2012-2014, Alexander Shibakov +% Copyright 2012-2020, Alexander Shibakov % This file is part of SPLinT % % SPLinT is free software: you can redistribute it and/or modify @@ -14,18 +14,21 @@ % You should have received a copy of the GNU General Public License % along with SPLinT. If not, see <http://www.gnu.org/licenses/>. -\prettywordpair{\%<flag>}{{$\langle\star\rangle$}} -\prettywordpair{\%nondeterministic-parser}{{$\langle$non...ic-parser$\rangle$}} -\prettywordpair{PERCENT_NONDETERMINISTIC_PARSER}{PER...NON...IC\_PARSER} -\prettywordpair{semi}{{\tt;}} +% definitions for typesetting tokens in \bison's grammar + +\prettywordpairwvis{\%<flag>}{{$\langle\star\rangle$}}{<*>} +\prettywordpair{\%nondeterministic-parser}{{$\langle$nondet. parser$\rangle$}} +\prettywordpair{PERCENT_NONDETERMINISTIC_PARSER}{{$\langle$nondet. parser$\rangle$}} +\prettywordpairwvis{semi}{{\tt;}}{;} \prettywordpair{TAG}{{{\tt<}{\it tag\/}{\tt>}}} +\prettywordpair{$\ undefined}{{\tt\$undefined}} \prettywordpair{<tag>}{{{\tt<}{\it tag\/}{\tt>}}} -\prettywordpair{FLEX_OPTION}{{$\langle$\bf option$\rangle_{\rm f}$}} -\prettywordpair{FLEX_STATE_X}{{$\langle$\bf state-x$\rangle_{\rm f}$}} -\prettywordpair{FLEX_STATE_S}{{$\langle$\bf state-s$\rangle_{\rm f}$}} +\prettywordpairwvis{FLEX_OPTION}{{$\langle$\bf option$\rangle_{\rm f}$}}{option_f} +\prettywordpairwvis{FLEX_STATE_X}{{$\langle$\bf state-x$\rangle_{\rm f}$}}{state-x} +\prettywordpairwvis{FLEX_STATE_S}{{$\langle$\bf state-s$\rangle_{\rm f}$}}{state-s} \prettywordpair{ID}{{\cyr\lqq{\rm identifier}\rqq}} \prettywordpair{ID_COLON}{{\cyr\lqq{\rm identifier: }\rqq}} -\prettywordpair{NUL}{{$\Lambda$}} +\prettywordpairwvis{NUL}{{$\Lambda$}}{Lambda} \prettywordpair{INT}{{\bf int}} \prettywordpair{CHAR}{{\bf char}} \prettywordpair{STRING}{{\cyr\lqq{\tt string}\rqq}} diff --git a/support/splint/tex/dcols.sty b/support/splint/tex/dcols.sty index 2560495d45..71176efd14 100644 --- a/support/splint/tex/dcols.sty +++ b/support/splint/tex/dcols.sty @@ -1,4 +1,4 @@ -% Copyright 2004-2014, Alexander Shibakov +% Copyright 2004-2020, Alexander Shibakov % This file is part of SPLinT % % SPLinT is free software: you can redistribute it and/or modify @@ -74,8 +74,9 @@ \footglue=1em plus.2em minus.1em \adjskip=0pt plus 6pt -\topskip=9pt - +%\topskip=9pt +%\normalbottom % one of these must accompany the use of the macros below + % so that the columns are aligned % \def\setmcparams{% @@ -231,7 +232,7 @@ \dsskip\smallskipamount -\def\begindoublecols{\begingroup\r@ggedbottomfalse\parindent=0pt +\def\begindoublecols{\begingroup\normalbottom\parindent=0pt \count\footins=\@m \multiply\count\footins by\fnotesspan \skip\footins=\fnotesspan\realfootins \remaindergaps=\noofcolumns @@ -718,7 +719,19 @@ % footnote counting macros \let\footthenotes\empty -\footline{\footthenotes}% so the footnotes know where to reset + +\footline{% + \footthenotes % so the footnotes know where to reset + \ifchapterhead + \vbox to 0pt{ + \hbox to\pagewidth{\hfil + \mainfont\vrule width 0pt height 2pc\oldstyle\the\pageno + \hfil} + \vss + }% + \global\chapterheadfalse + \fi +} \def\fnmark#1{{% \ifnum#1<\@M @@ -741,20 +754,25 @@ % auxiliary file (we have to read it in whole because it will be % rewritten as the document is being typeset); this opening has to be % done carefully for the file might not be there yet; check for it first. +% as a side note, one should not use the same stream number (at least the +% one allocated by a \new... command) for both the input and the output +% streams, since one might accidentally close a different stream that +% happened to have the same index but allocated by a \new... command as a +% stream of a different type. -\newread\fnlabels +\newread\tryfnlabels % to check if the file exists \newwrite\fnlabels \newcount\localfn % footnote count \newcount\fniteration \def\setupfootnotes{% this macro should be used at the beginning of the file, after a box (preferably) - \def\footthenotes{\write\fnlabels{\noexpand\addpgendlabel}}% - \openin\fnlabels=\jobname.ftn\relax - \ifeof\fnlabels - \closein\fnlabels\relax + \let\footthenotes\markbottomofpage + \openin\tryfnlabels=\jobname.ftn\relax + \ifeof\tryfnlabels + \closein\tryfnlabels\relax \fniteration\z@ \else - \closein\fnlabels\relax + \closein\tryfnlabels\relax \input \jobname.ftn\relax \fi \edef\savedfnstream{\the\fnstream}% @@ -764,30 +782,38 @@ \write\fnlabels{\noexpand\fniteration\the\fniteration\space}% } -\def\unsetfootnotes{% a clean(er) way to terminate footnote accounting -% \let\footthenotes\footthenoteslast - \def\footthenotes{\closeout\fnlabels\let\footthenotes\empty}% +\def\markbottomofpage{% + \write\fnlabels{\noexpand\addpgendlabel}% } -% the control sequence below is not used, although the idea is clear; -% unfortunately, this does not work, since \closeout\fnlabels is delayed -% so \input \jobname.ftn is likely to import an empty file; -% a more elaborate strategy is possible whereby all the macros inside -% \jobname.ftn are made expandable and the test below (along with \input \jobname.ftn) -% is put inside \write\m@ne{ ... } (so that the expansion of \input \jobname.ftn is -% delayed) using string comparison macros defined elsewhere -% but at the moment it seems excessive - -\def\footthenoteslast{% unused, see above - \closeout\fnlabels +\def\unsetfootnotes{% + \def\footthenotes{% + \write\fnlabels{\noexpand\endinput}% + \closeout\fnlabels + \global\let\footthenotes\checkfootnotestream% + % it is tempting to say \input \jobname.ftn + % at this point to use in the test below but this is not + % going to work: the \closeout will get invoked during the + % \shipout, which happens after the page is set and these + % macros are expanded. + % note that using another `stream' sequence for this purpose + % would not work either, since a footnote at the bottom of the + % page might `fire' but would be put on the next page by + % the epage builder. + }% +} + +\def\checkfootnotestream{% this needs at least one extra page to work correctly ... \fnstream{}% - \input \jobname.ftn + \input\jobname.ftn \edef\next{\the\fnstream}% \ifx\next\savedfnstream - \else + \message{Footnotes are stable ...}% + \else % this test is too strict, a better way would be to check that + % \next is a prefix in \savedfnstream and the remaining characters are all `|' \message{Footnotes may be set incorrectly ...}% \fi - \let\footthenotes\relax + \global\let\footthenotes\empty } \def\setfnmark{{% @@ -807,7 +833,7 @@ \def\splitfnstream{\edef\tempdefone{\the\fnstream}% \ifx\tempdefone\empty - \def\nexttok{?}\message{You need to recount the footnotes ...}% + \def\nexttok{?}\message{You may have to reposition the footnotes ...}% \else \expandafter\splitfnstre@m\tempdefone\end \fi diff --git a/support/splint/tex/flex.sty b/support/splint/tex/flex.sty index da3aa7b0b7..59e23785b3 100644 --- a/support/splint/tex/flex.sty +++ b/support/splint/tex/flex.sty @@ -1,4 +1,4 @@ -% Copyright 2012-2014, Alexander Shibakov +% Copyright 2012-2020, Alexander Shibakov % This file is part of SPLinT % % SPLinT is free software: you can redistribute it and/or modify @@ -14,10 +14,20 @@ % You should have received a copy of the GNU General Public License % along with SPLinT. If not, see <http://www.gnu.org/licenses/>. -\newtoks\tayybyte % throwaway token register -\newcount\tayymarker % throwaway count register - -\chardef\EOL=`\^^J% +% the implementation of (some part of) the \flex automata mechanisms; +% note that a few important features have been omitted and some that +% have been implemented may follow a (sometimes subtly) different +% semantics (see \unput and \yyless below); +% among the features that are missing are REJECT, ECHO and YYMORE; +% another important missing feature is the lack of trailing +% context matching; fixed length trailing context or fixed length +% match with variable length context can be easily emulated with +% regular rules and \yyless (or \unput); when both the match and +% the context are variable length, different automaton code is +% required; same code is required to implement REJECT; in addition, +% the action code for the actions matching trailing context rules +% must also be modified; while all of this may be implemented, it +% is better not to (ab)use trailing context rules. \def\yylex{% \ifnum\yyg@yyinit=\z@ % if ( !yyg->yy_init ) { @@ -29,6 +39,13 @@ \yylwhile } +\newif\ifyylessused +\newtoks\yylesslastformat +\newtoks\yylesslaststash +\newcount\yylesslastfmark +\newcount\yylesslastsmark +\newcount\yylesslastchar + \def\yylwhile{% % yy_cp = yyg->yy_c_buf_p; % *yy_cp = yyg->yy_hold_char; @@ -36,6 +53,14 @@ % \yycurrentstate=\yyg@yystart % yy_current_state = yyg->yy_start; \advance\yycurrentstate\YYATBOL % yy_current_state += YY_AT_BOL(); + % save the format and stash streams for \yyless + \ifyylessused + \yylesslastformat\yyformat + \yylesslaststash\yystash + \yylesslastfmark\yyfmark + \yylesslastsmark\yysmark + \yylesslastchar\yytextlastchar + \fi \yymatch } @@ -50,39 +75,46 @@ \fi } -\def\yyreinput{\expandafter\yyresetstreams\expandafter\yyinput\the\yytextseen} +\def\yyreinput{\expandafter\yyresetstreams\expandafter\yyinput\the\yytext@seen} \def\yyresetstreams{% - \iftraceflexbuffers\ferrmessage{will rescan: \the\yytextseen}\fi - \yytextseen{}% - \yytextseenpure\yytextseen - \yyformatseen\yytextseen - \yystashseen\yytextseen + \iftraceflexbuffers\ferrmessage{will rescan: <\the\yytext@seen> (stash: \the\yystashseen)}\fi + \yytextseen{}\yytext@seen{}\yytextseenpure{}% + \yyformatseen{}\yystashseen{}% \yytextbackupfalse } +% \yym@tch is the return point from the low-level input routine + \def\yym@tch{% do { \yyc=\fgetelemof{yyec}\at\yycp@\relax % yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; \yyact=\fgetelemof{yyaccept}\at\yycurrentstate\relax % ... ... reuse \yyact ( yy_act = yy_accept[yy_current_state] ) + \ifyyflexdebug\ferrmessage{match action: \the\yyact\space(yytext: \the\yytext@:^^Jyytextseen: \the\yytext@seen>\the\yybyte)}\fi \ifnum\yyact=\z@ % if ( yy_accept[yy_current_state] ) { \else % + \ifyyflexdebug\ferrmessage{yym@tch: stash seen: \the\yystashseen^^Jsmark: \the\yysmarklast}\fi \yyg@yylastacceptingstate=\yycurrentstate % yyg->yy_last_accepting_state = yy_current_state; \concat\yytext\yytextseen % yyg->yy_last_accepting_cpos = yy_cp; - \concat\yytextpure\yytextseenpure % ... ... + \concat\yytext@\yytext@seen % ... ... + \concat\yytextpure\yytextseenpure % ... ... \concat\yyformat\yyformatseen % ... ... \concat\yystash\yystashseen % ... ... \yytextlastchar=\yytextseenlastchar % \yyfmark=\yyfmarklast % ... ... \yysmark=\yysmarklast % ... ... - \yytextseen={}% - \yytextseenpure\yytextseen - \yyformatseen\yytextseen - \yystashseen\yytextseen + \yyfmark@accept=\yyfmark + \yysmark@accept=\yysmark + \yytextseen={}\yytext@seen={}\yytextseenpure{}% + \yyformatseen{}\yystashseen{}% \fi % } \yyllwhile } +\let\yyreturn\yym@tch + +% \yyllwhile searches for an accepting of rejecting state + \def\yyllwhile{% ... yyllwhile: \yyact=\fgetelemof{yybase}\at\yycurrentstate\relax % ... ... reusing \yyact ( yy_act = yy_base[yy_current_state] ) \advance\yyact\yyc % ... ... ( yy_act = yy_act + yy_c ) @@ -103,21 +135,27 @@ \def\yymatchtail{% \yycurrentstate=\fgetelemof{yybase}\at\yycurrentstate\relax \advance\yycurrentstate\yyc % - \yycurrentstate=\fgetelemof{yynxt}\at\yycurrentstate\relax + \yycurrentstate=\fgetelemof{yynxt}\at\yycurrentstate\relax + \ifyyflexdebug\ferrmessage{yysubtext: (\the\yysubtext),^^Jyysbyte: (\the\yysbyte),^^Jyybyte: (\the\yybyte)}\fi % yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; \concat\yytextseen\yybyte % ++yy_cp; + \concat\yytext@seen\yysubtext \yysubtext{}% % ... + \concat\yytext@seen\yybyte % ... \concat\yytextseenpure\yybytepure % ... - \concat\yyformatseen\yyfbyte\yyfbyte{}% % ... - \concat\yystashseen\yysbyte\yysbyte{}% % ... + \concat\yyformatseen\yyfbyte \yyfbyte{}% % ... + \concat\yystashseen\yysbyte \yysbyte{}% % ... \yytextseenlastchar=\yycp@ % \yyfmarklast=\formatmarker % ... \yysmarklast=\stashmarker % ... \yyact=\fgetelemof{yybase}\at\yycurrentstate\relax % ... reusing \yyact ( yy_act = yy_base[yy_current_state] ) + \ifyyflexdebug\ferrmessage{matching the rest: <\the\yytext@seen>^^J(stash: \the\yystash:^^J\the\yystashseen)}\fi \ifnum\yyact=\YYBASEMAXENTRY\relax % } while ( yy_base[yy_current_state] != max( yy_base ) ); - \xskiptofi\yyfindaction % ... if ( yy_base[yy_current_state] == max( yy_base ) ) goto yy_find_action; + \ifyyflexdebug\ferrmessage{looking for the action}\fi + \yybreak\yyfindaction % ... if ( yy_base[yy_current_state] == max( yy_base ) ) goto yy_find_action; \else % ... else goto yy_match; - \xskiptofi\yymatch - \fi + \ifyyflexdebug\ferrmessage{looking for more input}\fi + \yybreak\yymatch + \yycontinue } \newif\ifyyflexdebug @@ -129,190 +167,38 @@ \yytextbackuptrue % yy_cp = yyg->yy_last_accepting_cpos; \yycurrentstate=\yyg@yylastacceptingstate % yy_current_state = yyg->yy_last_accepting_state; \yyact=\fgetelemof{yyaccept}\at\yycurrentstate\relax% yy_act = yy_accept[yy_current_state]; - \ifyyflexdebug\ferrmessage{backup: \the\yytext:\the\yytextseen}\fi + \formatmarker=\yyfmark@accept % ... + \stashmarker=\yysmark@accept % ... + \ifyyflexdebug\ferrmessage{backup: \the\yytext@:\the\yytext@seen^^J^^J% + from state: \the\yyg@yylastacceptingstate\space + stashmarker: \the\stashmarker}\fi \else - % + % note that at this point \yytextbackupfalse is already set \concat\yytext\yytextseen + \concat\yytext@\yytext@seen \concat\yytextpure\yytextseenpure \concat\yyformat\yyformatseen \concat\yystash\yystashseen \yytextlastchar=\yytextseenlastchar - \yyfmark=\yyfmarklast - \yysmark=\yysmarklast - \yytextseen{}% - \yytextseenpure{}% - \yyformatseen{}% - \yystashseen{}% + \yyfmark=\yyfmarklast % == \formatmarker + \yysmark=\yysmarklast % == \stashmarker + \yytextseen{}\yytext@seen{}\yytextseenpure{}% + \yyformatseen{}\yystashseen{}% % \fi % } -% \YYDOBEFOREACTION % YY_DO_BEFORE_ACTION; + \YYDOBEFOREACTION % YY_DO_BEFORE_ACTION; \ifyyflexdebug - \ferrmessage{action: \the\yyact, state: \the\yycurrentstate\space(\the\yytext)}% + \ferrmessage{action: \the\yyact,^^J% + state: \the\yycurrentstate\space(\the\yytext@:\the\yytext@seen)^^J% + stash: \the\yystash:\the\yystashseen^^J% + yysbyte: \the\yysbyte}% \fi \doaction } -\def\YYRULESETUP{% %#define YY_RULE_SETUP \ - \yytoksempty{\yytext}{}{% % if ( yyleng > 0 ) \ - \ifnum\EOL=\yytextlastchar % YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (yytext[yyleng - 1] == '\n'); \ - \YYATBOL=\@ne % YY_USER_ACTION - \else %#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) - \YYATBOL=\z@ - \fi - }% -} - -%#define BEGIN yyg->yy_start = 1 + 2 * -% should be: -%#define BEGIN(state) yyg->yy_start = 1 + 2 * ( state ) - -\newif\iftracestates - -\def\yylexstate#1{\csname flexstate\parsernamespace #1\endcsname} - -\def\yyBEGIN#1{% - \yyg@yystart - \expandafter\ifx\csname flexstate\parsernamespace #1\endcsname\relax - #1 \iftracestates\ferrmessage{now in state: #1}\fi - \else - \csname flexstate\parsernamespace #1\endcsname\relax - \iftracestates\ferrmessage{now in state: #1 (\number\csname flexstate\parsernamespace #1\endcsname)}\fi - \fi - \multiply\yyg@yystart\tw@ - \advance\yyg@yystart\@ne -} - -\def\yyBEGINr#1{% - \yyg@yystart#1% - \iftracestates\ferrmessage{new state: \the\yyg@yystart}\fi - \multiply\yyg@yystart\tw@ - \advance\yyg@yystart\@ne -} - -%#define YY_START ((yyg->yy_start - 1) / 2) - -\def\YYSTART{% - \expandafter\xdivbytwo\expandafter{\number - \expandafter\xdecrement\expandafter{\number\yyg@yystart}} -} - -\def\yypushstate#1{% - \expandafter\yypush\expandafter{\number\YYSTART}\on\yystatestack - \yyBEGIN{#1}% -} - -\def\yypopstate{% - \yypop\yystatestack\into{\expandafter\yyBEGIN\romannumeral0}% - \iftracestates\message{new state (* 2 + 1 scrambled): \the\yyg@yystart}\fi -} - -\def\yytopstate#1{% - \yyreadstack\yystatestack\at\z@\to#1% -} - -\let\yylexcontinue\yylwhile % complete the while loop (requires \yylexnext) -\def\yylexcontinue{\yytext{}\yytextpure\yytext\yylwhile} % complete the while loop - -% \yylextail is the return point from the lexer - -\let\yyreturn\yym@tch % the return point from the low-level input - -\def\yylexreturnbootstrap#1{% - \yytext{}\yytextpure\yytext - \expandafter\ifx\csname token\parsernamespace #1\endcsname\relax - % this token value is undefined - \let\yylextail\yylex % so lex the next token - \else - \yychar\csname token\parsernamespace #1\endcsname\relax - \let\yylextail\yyparsetail - \fi -} - -\def\yylexreturnregular#1{\yychar\csname token\parsernamespace #1\endcsname\relax\yytext{}\yytextpure{}\let\yylextail\yyparsetail} - -\def\yylexreturnval#1{% return value (yytext) only - \yychar\csname token\parsernamespace #1\endcsname\relax - \yylval\expandafter{\expandafter{\the\yytext}}% - \yylval\expandafter\expandafter\expandafter{\expandafter\the\expandafter\yylval\expandafter{\the\yytextpure}}% - % the above is an equivalent of - % \edef\next{\yylval{{\the\yytext}{\the\yytextpure}}}\next - % but does not `pollute' the definition of \next - \yytext{}\yytextpure\yytext\let\yylextail\yyparsetail -} - -\def\yylexreturnptr#1{% return stream pointers only - \yylval\expandafter{\expandafter{\the\yyfmark}}% - \yylval\expandafter\expandafter\expandafter{\expandafter\the\expandafter\yylval\expandafter{\the\yysmark}}% - % the above is an equivalent of - % \edef\next{\yylval{{\the\yyfmark}{\the\yysmark}}}\next - % but does not `pollute' the definition of \next - \yylexreturn{#1}% -} +\newif\iftraceactioncode -\def\yylexreturntext{\yylexreturnptr{\the\yytextpure}} - -\def\yylexreturnraw#1{% return the character value - \yychar`#1\relax - \yytext{}\yytextpure{}\let\yylextail\yyparsetail -} - -\def\yylexreturnchar{% - \expandafter\yylexreturnraw\the\yytextpure -} - -\def\yylexnext{\yytext{}\yytextpure{}} % use this with a trivial \yylexcontinue -\let\yylexnext\empty - -\def\yyterminate{\yychar\YYEOF\yylval{}\yytext{}\yytextpure{}\let\yylextail\yyparsetail} - -\def\yyerrterminate{\yylexreturn{$undefined}} %$ - -\def\ferrmessage#1{\immediate\write16{#1}} - -% \yyless is slow and the macros below have not been tested in their current -% form: avoid them - -\def\yyless#1{% - \ifnum#1=\z@ - \ROLLBACKCURRENTTOKEN - \else - \let\oldyyreturn\yyreturn - \edef\yyreturn{\noexpand\yyskipnchars{\number#1}}% - \expandafter\yyinput\the\yytext\yyeof - \fi -} - -\def\yyskipnchars#1{% - \ifnum\yycp@=\YYENDOFBUFFERCHAR % read \yyeof - \yycomplain{yyless buffer overflow: #1 characters too many}% - \else - \ifnum#1=\@ne % skipped the required number of tokens - \yybreak@\yyl@ss - \else - \edef\yyreturn{\noexpand\yyskipnchars{\xdecrement{#1}}}% - \yybreak@\yyinput - \fi - \yycontinue -} - -\def\yyl@ss#1\yyeof{% - \yytext{#1}% - \concatl\yytext\yytextseen - \yytext{}\yytextpure{}% - \yytextbackuptrue - \let\yyreturn\oldyyreturn -} - -%#define ROLLBACK_CURRENT_TOKEN \ -% do { \ -% scanner_cursor.column -= mbsnwidth (yytext, yyleng, 0); \ -% yyless (0); \ -% } while (0) - -\def\ROLLBACKCURRENTTOKEN{% - \concatl\yytext\yytextseen - \yytext{}\yytextpure{}% - \yytextbackuptrue +\def\YYDOBEFOREACTION{% } % \yytext---current yytext @@ -332,6 +218,13 @@ % yyg->yy_c_buf_p = yy_cp; \def\doaction{% + \iftraceactioncode + {% + \expandafter\toksa + \expandafter\expandafter\expandafter{\csname doflexaction\number\yyact\parsernamespace\endcsname}% + \ferrmessage{action code (\the\yyact):^^J\the\toksa}% + }% + \fi \yydoactionswitch\yyact } @@ -344,10 +237,14 @@ % another; \def\yylexeofaction{% + \ifyyflexdebug + \ferrmessage{eof action: .\the\yytext@>>\the\yytext@seen(\the\yytext)}% + \fi \yygetnextbuffer \ifYYEOBLASTMATCH \yygetpreviousstate - \ifyyflexdebug\ferrmessage{found previous state: \the\yycurrentstatelocal\space matched text: \the\yytext>>\the\yytextseen(\the\yybyte))}\fi + \ifyyflexdebug\ferrmessage{found previous state: \the\yycurrentstatelocal\space + matched text: \the\yytext@>>\the\yytext@seen(\the\yybyte)}\fi \yycurrentstate\yycurrentstatelocal \let\yylextail\yyfind@ction \YYEOBLASTMATCHfalse @@ -356,55 +253,60 @@ \advance\yyact\YYSTART \advance\yyact\@ne % yy_act = YY_STATE_EOF(YY_START); \let\yylextail\doaction % goto do_action; - \appendl\yytextseen{\the\yytext}\yytextbackuptrue % in case the scanner gets called again - \ifyyflexdebug + \concatl\yytext\yytext@seen \yytextbackuptrue % in case the scanner gets called again \yytoksempty{\yytext}% {\errmessage{internal error: matched nothing in eob state}}% - {\yyisthiscsr\yytext\yyeof{}{\errmessage{internal error: matched more that a single eob}}}% - \ferrmessage{eob in user state: \the\yyact\space matched text: \the\yytext(\the\yytextpure)\space - to read: \the\yytextseen}% + {\yyisthiscsr\yytext\yyeof{}{\errmessage{internal error: matched more than a single eob: (\the\yytext)}}}% + \ifyyflexdebug + \ferrmessage{eob in user state: \the\yyact\space matched text: \the\yytext@(\the\yytext)\space + to read: \the\yytext@seen}% \fi - \yytext{}% + \yytext{}\yytext@{}% \fi } \def\yygetnextbuffer{% \yytoksempty{\yytext}{\errmessage{internal error: empty matched text in eob state}}% - {% - \expandafter\expandafter\expandafter - \yystringempty % we have matched exactly one token - \expandafter\expandafter\expandafter{\expandafter\eatone\the\yytext}% - {\YYEOBLASTMATCHfalse}{\YYEOBLASTMATCHtrue}% + {% this somewhat complicated definition is needed in case the last character is an ordinary + % space character + \expandafter\yystartsinspace\expandafter{\the\yytext}{% + \expandafter\expandafter\expandafter + \yystringempty % we have matched exactly one token (space) + \expandafter\expandafter\expandafter{\expandafter\eattospace\the\yytext}% + {\YYEOBLASTMATCHfalse}{\YYEOBLASTMATCHtrue}% + }{% + \expandafter\expandafter\expandafter + \yystringempty % we have matched exactly one token + \expandafter\expandafter\expandafter{\expandafter\eatone\the\yytext}% + {\YYEOBLASTMATCHfalse}{\YYEOBLASTMATCHtrue}% + }% }% } -\def\yyeofcontainer{\yyeof} - \newif\ifYYEOBLASTMATCH \def\yygetpreviousstate{% \yycurrentstatelocal=\yyg@yystart \advance\yycurrentstatelocal\YYATBOL + \ifyyflexdebug\ferrmessage{state setup.: start(\the\yyg@yystart), bol(\number\YYATBOL)}\fi % \yytoksempty{\yytext}{\errmessage{internal error: empty matched text in eob state}}{}% - \expandafter\yysplitoff\expandafter.\the\yytext\yyeof\end - \appendl\yytextseen{\noexpand\yyeof}\yytextbackuptrue - \ifyyflexdebug\ferrmessage{searching for last match in text: \the\yytext}\fi % TODO: delete + % move the scanned \yyeof to the buffer of seen characters + \expandafter\yysplitoff\expandafter.\the\yytext\yyeof\end\yytext + \expandafter\yysplitoff\expandafter.\the\yytext@\yyeof\end\yytext@ + \appendlnx\yytextseen\yyeof + \appendlnx\yytext@seen\yyeof \yytextbackuptrue + \ifyyflexdebug\ferrmessage{searching for last match in text: \the\yytext@}\fi \yytoksempty{\yytext}{}{% yyg->yytext_ptr >= yyg->yy_c_buf_p /* do not enter the for loop */ - \yytextpure{}% - \yyfutureyytext\yytextseen % to be reinserted in yyfind@action - \yytextseen{}\yytextseenpure{}% - \expandafter\yytext\expandafter - {\expandafter}\expandafter - \yygetpreviousstatefor\the\yytext\splitoffend % at least one iteration of the for loop - }% + \expandafter\yygetpreviousstatefor\the\yytext@\splitoffend % at least one iteration of the for loop + }% } -\def\yysplitoff#1\yyeof#2\end{% +\def\yysplitoff#1\yyeof#2\end#3{% \yystringempty{#2}{% - \errmessage{internal error: something other than \noexpand\yyeof\space triggered eob action}% + \errmessage{internal error: something other than \noexpand\yyeof\space triggered eob action: <\the\yytext@>}% }{% - \yytext\expandafter{\eatone#1}% to remove the `.' at the beginning + #3\expandafter{\eatone#1}% to remove the `.' at the beginning }% } @@ -413,46 +315,41 @@ % to be restored on exit from the `for' loop % i.e.~when the \splitoff token is read \let\currentyyreturn\yyreturn -% - \let\currentyyfbyte\yyfbyte - \let\currentyysbyte\yysbyte - \let\currentstashmarker\stashmarker - \let\currentformatmarker\formatmarker -% - \let\yyfbyte\tayybyte - \let\yysbyte\tayybyte - \let\stashmarker\tayymarker - \let\formatmarker\tayymarker -% + \yyfutureyytext\yytext@seen % to be reinserted in yyfind@action + \yytext{}\yytext@{}\yytextpure{}% + \yytextseen{}\yytext@seen{}\yytextseenpure{}% + \formatmarker=\yyfmark@accept + \stashmarker=\yysmark@accept + \yyfmarklast=\formatmarker + \yysmarklast=\stashmarker + \yyformatseen{}\yystashseen{}% \let\yyreturn\yygetpreviousstatef@r \yyinput } \def\yygetpreviousstatef@r{% \let\default\yygetpreviousstatedefault - \ifyyflexdebug\ferrmessage{just read: \the\yybyte}\fi % TODO: delete + \ifyyflexdebug\ferrmessage{just read: \the\yybyte (so far: \the\yytext@><\the\yytext@seen)}\fi % TODO: delete \switchon{\expandafter\getfirsttoken\expandafter{\the\yybyte}}\in\yygetpreviousstateswitch } \def\yygetpreviousstateswitch{% - \yyeof {% scanned a NUL + \yyeof {% scanned a NUL: currently NUL transitions are not implemented + % (so one cannot use NUL's in the input) so this state is never used \yyclocal\YYECMAGIC\relax % the constant extracted from yy_get_next_state + \edef\yycurrentstatelocal@prejam{\the\yycurrentstatelocal}% \yygetpreviousstat@f@r - } + }% \splitoffend {% yyg->yytext_ptr >= yyg->yy_c_buf_p /* exit the for loop */ % this is not an actual character but a marker for the end of the `for' loop - \let\yyfbyte\currentyyfbyte - \let\yysbyte\currentyysbyte - \let\stashmarker\currentstashmarker - \let\formatmarker\currentformatmarker \yycp@=\YYENDOFBUFFERCHAR\relax % this is not necessary \yybyte{}\yybytepure{}% % \let\yyreturn\currentyyreturn - } + }% \endparse \endparseinput {% \errmessage{internal error.: reading past the end of the input buffer}% - } + }% } \def\yygetpreviousstatedefault{% @@ -465,20 +362,41 @@ \ifnum\fgetelemof{yyaccept}\at\yycurrentstatelocal=\z@ % if ( yy_accept[yy_current_state] ) { \concat\yytextseen\yybyte + \concat\yytext@seen\yysubtext \yysubtext{}% + \concat\yytext@seen\yybyte \concat\yytextseenpure\yybytepure - \yybyte{}\yybytepure\yybyte + \yybyte{}\yybytepure{}% + \yyfmarklast=\formatmarker + \yysmarklast=\stashmarker + \concat\yyformatseen\yyfbyte \yyfbyte{}% + \concat\yystashseen\yysbyte \yysbyte{}% \else % - \ifyyflexdebug\ferrmessage{possible accepting state: \the\yycurrentstatelocal:% - \fgetelemof{yyaccept}\at\yycurrentstatelocal}\fi % TODO: delete + \ifyyflexdebug + \ferrmessage{possible accepting state.: \the\yycurrentstatelocal:% + \fgetelemof{yyaccept}\at\yycurrentstatelocal}% + \fi \yyg@yylastacceptingstate=\yycurrentstatelocal % yyg->yy_last_accepting_state = yy_current_state; \concat\yytext\yytextseen % yyg->yy_last_accepting_cpos = yy_cp; TODO:????????? - \concat\yytextpure\yytextseenpure % ... ... - \yytextseen=\yybyte - \yytextseenpure=\yybytepure + \concat\yytext@\yytext@seen % ... + \concat\yytextpure\yytextseenpure % ... + \yytextseen=\yybyte % ... + \yytext@seen=\yysubtext \yysubtext{}% % ... + \concat\yytext@seen\yybyte \yybyte{}% % ... + \yytextseenpure=\yybytepure\yybytepure{}% % \yytextbackuptrue - \yybyte{}\yybytepure\yybyte \yytextlastchar=\yytextseenlastchar % + % + \yyfmark=\yyfmarklast % ... ... + \yysmark=\yysmarklast % ... ... + \yyfmark@accept=\yyfmark + \yysmark@accept=\yysmark + \yyfmarklast=\formatmarker + \yysmarklast=\stashmarker + \concat\yyformat\yyformatseen + \concat\yystash\yystashseen + \yyformatseen\yyfbyte\yyfbyte{}% + \yystashseen\yysbyte\yysbyte{}% \fi \yygpswhile } @@ -501,11 +419,26 @@ \yycontinue % } } -\def\yygpsfornext{% +\newif\ifyyflexisjammed + +\def\yygpsfornext{% this combines yy_get_previous_state() and yy_get_NUL_trans() + \ifyyflexdebug\ferrmessage{starting in state.: \the\yycurrentstatelocal}\fi % TODO: delete \yycurrentstatelocal=\fgetelemof{yybase}\at\yycurrentstatelocal\relax \advance\yycurrentstatelocal\yyclocal \yycurrentstatelocal=\fgetelemof{yynxt}\at\yycurrentstatelocal\relax - \ifyyflexdebug\ferrmessage{switching to state: \the\yycurrentstatelocal}\fi % TODO: delete + % yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + % currently, we do not allow NULs in the input so the code below is not used + % when NUL transitions are implemented, this code will come into play + \ifnum\yycurrentstatelocal=\YYMAXREALCHAR\relax + \yycurrentstatelocal=\yycurrentstatelocal@prejam\relax + \ifyyflexdebug\ferrmessage{jammed, switching to \yycurrentstatelocal@prejam}\fi + \yyflexisjammedtrue + \else + \yyflexisjammedfalse + \fi + %yy_is_jam = (yy_current_state == ...); + %return yy_is_jam ? 0 : yy_current_state; + \ifyyflexdebug\ferrmessage{switching to state.: \the\yycurrentstatelocal\space on char \the\yyclocal}\fi % TODO: delete \yyinput } @@ -518,30 +451,266 @@ % yy_cp = yyg->yy_last_accepting_cpos; \yycurrentstate=\yyg@yylastacceptingstate % yy_current_state = yyg->yy_last_accepting_state; \yyact=\fgetelemof{yyaccept}\at\yycurrentstate\relax% yy_act = yy_accept[yy_current_state]; + \formatmarker=\yyfmark@accept % ... + \stashmarker=\yysmark@accept % ... \ifyyflexdebug\ferrmessage{backup.: \the\yytext:\the\yytextseen}\fi \else % \concat\yytext\yytextseen - \concat\yytext\yybyte - \yybyte{}% - \yytextseen{}% + \concat\yytext@\yytext@seen \concat\yytextpure\yytextseenpure - \concat\yyformat\yyformatseen - \concat\yystash\yystashseen + \concat\yytext\yybyte + \concat\yytext@\yysubtext \yysubtext{}% + \concat\yytext@\yybyte + \concat\yytextpure\yybytepure + \yybyte{}\yybytepure{}% + \yytextseen{}\yytext@seen{}\yytextseenpure{}% + \concat\yyformat\yyformatseen\yyformatseen{}% + \concat\yystash\yystashseen\yystashseen{}% \yytextlastchar=\yytextseenlastchar \yyfmark=\yyfmarklast \yysmark=\yysmarklast - \yyformatseen{}% - \yystashseen{}% % \fi % } - \concat\yytextseen\yyfutureyytext % ... reinsert the tokens seen by the lexer before + \concat\yytext@seen\yyfutureyytext % ... reinsert the tokens seen by the lexer before % ... \yygetpreviousaction got rolling \yyfutureyytext{}% \yytextbackuptrue -% \YYDOBEFOREACTION % YY_DO_BEFORE_ACTION; + \YYDOBEFOREACTION % YY_DO_BEFORE_ACTION; \ifyyflexdebug \ferrmessage{action.: \the\yyact, state: \the\yycurrentstate\space(\the\yytext) \parsernamespace}% \fi \doaction } + +\def\YYRULESETUP{% %#define YY_RULE_SETUP \ + \yytoksempty{\yytext}{}{% % if ( yyleng > 0 ) \ + \ifnum\n=\yytextlastchar % YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (yytext[yyleng - 1] == '\n'); \ + \YYATBOL=\@ne % YY_USER_ACTION + \else %#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + \YYATBOL=\z@ + \ifyyflexdebug\ferrmessage{YYATBOL: 0}\fi + \fi + }% +} + +%#define yy_set_bol(at_bol) \ +% { \ +% if ( ! YY_CURRENT_BUFFER ){\ +% yyensure_buffer_stack (); \ +% YY_CURRENT_BUFFER_LVALUE = \ +% yy_create_buffer(yyin,YY_BUF_SIZE ); \ +% } \ +% YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ +% } + +\def\yysetbol#1{\YYATBOL=#1\relax} % we do not switch or create buffers + +%#define BEGIN yyg->yy_start = 1 + 2 * +% should be: +%#define BEGIN(state) yyg->yy_start = 1 + 2 * ( state ) + +\newif\iftracestates + +\def\yylexstate#1{\csname flexstate\parsernamespace #1\endcsname} + +\def\yyBEGIN#1{% + \yyg@yystart + \expandafter\ifx\csname flexstate\parsernamespace #1\endcsname\relax + #1 \iftracestates\ferrmessage{now in state: #1}\fi + \else + \csname flexstate\parsernamespace #1\endcsname\relax + \iftracestates\ferrmessage{now in state: #1 (\number\csname flexstate\parsernamespace #1\endcsname)}\fi + \fi + \multiply\yyg@yystart\tw@ + \advance\yyg@yystart\@ne +} + +\def\yyBEGINr#1{% + \yyg@yystart#1% + \iftracestates\ferrmessage{new state: \the\yyg@yystart}\fi + \multiply\yyg@yystart\tw@ + \advance\yyg@yystart\@ne +} + +%#define YY_START ((yyg->yy_start - 1) / 2) + +\def\YYSTART{% + \expandafter\xdivbytwo\expandafter{\number + \expandafter\xdecrement\expandafter{\number\yyg@yystart}} +} + +\def\yypushstate#1{% + \expandafter\yypush\expandafter{\number\YYSTART}\on\yystatestack + \yyBEGIN{#1}% +} + +\def\yypopstate{% + \yypop\yystatestack\into{\expandafter\yyBEGIN\romannumeral0}% + \iftracestates\ferrmessage{new state (* 2 + 1 scrambled): \the\yyg@yystart}\fi +} + +\def\yytopstate#1{% + \yyreadstack\yystatestack\at\z@\to#1% +} + +\let\yylexcontinue\yylwhile % complete the while loop (requires \yylexnext) +\def\yylexcontinue{\yytext{}\yytextpure{}\yytext@{}\yylwhile} % complete the while loop + +% \yylextail is the return point from the lexer + +\def\yylexreturnbootstrap#1{% + \yytext{}\yytext@{}\yytextpure{}% + \expandafter\ifx\csname token\parsernamespace #1\endcsname\relax + % this token value is undefined + \let\yylextail\yylex % so lex the next token + \else + \yychar\csname token\parsernamespace #1\endcsname\relax + \let\yylextail\yyparsetail + \fi +} + +\def\yylexreturnregular#1{% + \yychar\csname token\parsernamespace #1\endcsname\relax + \yytext{}\yytext@{}\yytextpure{}\let\yylextail\yyparsetail +} + +\def\yylexreturnval#1{% return value (yytext) only + \yychar\csname token\parsernamespace #1\endcsname\relax + \yylval\expandafter{\expandafter{\the\yytext}}% + \yylval\expandafter\expandafter\expandafter{\expandafter\the\expandafter\yylval\expandafter{\the\yytextpure}}% + % the above is an equivalent of + % \edef\next{\yylval{{\the\yytext}{\the\yytextpure}}}\next + % but does not `pollute' the definition of \next + \yytext{}\yytext@{}\yytextpure{}\let\yylextail\yyparsetail +} + +\def\yylexreturnptr#1{% return stream pointers only + \yylval\expandafter{\expandafter{\the\yyfmark}}% + \yylval\expandafter\expandafter\expandafter{\expandafter\the\expandafter\yylval\expandafter{\the\yysmark}}% + % the above is an equivalent of + % \edef\next{\yylval{{\the\yyfmark}{\the\yysmark}}}\next + % but does not `pollute' the definition of \next + \yylexreturn{#1}% +} + +\def\yylexreturnsym#1{% return the value (yytext) followed by the pointers + \yychar\csname token\parsernamespace #1\endcsname\relax + \yylval\expandafter{\expandafter{\the\yytext}}% + \yylval\expandafter\expandafter\expandafter{\expandafter\the\expandafter\yylval\expandafter{\the\yytextpure}}% + \yylval\expandafter\expandafter\expandafter{\expandafter\the\expandafter\yylval\expandafter{\the\yyfmark}}% + \yylval\expandafter\expandafter\expandafter{\expandafter\the\expandafter\yylval\expandafter{\the\yysmark}}% + % the above is an equivalent of + % \edef\next{\yylval{{\the\yytext}{\the\yytextpure}{\the\yyfmark}{\the\yysmark}}}\next + % but does not `pollute' the definition of \next + \yytext{}\yytext@{}\yytextpure{}\let\yylextail\yyparsetail +} + +\def\yylexreturntext{\yylexreturnptr{\the\yytextpure}} + +\def\yylexreturnraw#1{% return the character, pointers as the value + \yylval\expandafter{\expandafter{\the\yyfmark}}% + \yylval\expandafter\expandafter\expandafter{\expandafter\the\expandafter\yylval\expandafter{\the\yysmark}}% + \yychar`#1\relax + \yytext{}\yytext@{}\yytextpure{}\let\yylextail\yyparsetail +} + +\def\yylexreturnchar{% + \expandafter\yylexreturnraw\the\yytextpure +} + +\def\yylexreturnxchar#1{% return the numeric value, pointers as the value + \yylval\expandafter{\expandafter{\the\yyfmark}}% + \yylval\expandafter\expandafter\expandafter{\expandafter\the\expandafter\yylval\expandafter{\the\yysmark}}% + \yychar#1\relax + \yytext{}\yytext@{}\yytextpure{}\let\yylextail\yyparsetail +} + +\def\yylexnext{\yytext{}\yytext@{}\yytextpure{}} % use this with a trivial \yylexcontinue +\let\yylexnext\empty + +\def\yyterminate{\yychar\YYEOF\yylval{}\yytext{}\yytext@{}\yytextpure{}\let\yylextail\yyparsetail} + +\def\yyerrterminate{\yylexreturn{$undefined}} %$ + +\def\yyfatal#1{\yycomplain{#1}\yyerrterminate} + +\def\yywarn#1{\yycomplain{#1}\yylexnext} + +% \yyless is slow and the macros below have not been tested in their current +% form: avoid them + +\def\yyless#1{% + \yyless@backup + \ifnum#1=\z@ + \yyfmark=\formatmarker + \yysmark=\stashmarker + \ROLLBACKCURRENTTOKEN + \else + \let\oldyyreturn\yyreturn + \edef\yyreturn{\noexpand\yyskipnchars{\number#1}}% + \expandafter\yyinput\the\yytext@\yyeof + \fi +} + +\def\yyless@backup{% + \yyformat\yylesslastformat + \yystash\yylesslaststash + \yysbyte{}\yyfbyte{}% + \formatmarker\yylesslastfmark + \stashmarker\yylesslastsmark +} + +\def\yyless@updatestreams{% + \concat\yyformat\yyfbyte\yyfbyte{}% + \concat\yystash\yysbyte\yysbyte{}% +} + +\def\yyskipnchars#1{% + \ifnum\yycp@=\YYENDOFBUFFERCHAR % read \yyeof + \yycomplain{yyless buffer overflow: #1 characters too many}% + \else + \yyless@updatestreams + \ifnum#1=\@ne % skipped the required number of tokens + \yybreak@\yyl@ss + \else + \edef\yyreturn{\noexpand\yyskipnchars{\xdecrement{#1}}}% + \yybreak@\yyinput + \fi + \yycontinue +} + +\def\yyl@ss#1\yyeof{% + \yyfmark=\formatmarker + \yysmark=\stashmarker + \yylesslaststash\yystash + \yylesslastformat\yyformat + \unput{#1}% + \let\yyreturn\oldyyreturn +} + +% \unput has a slightly different semantics from \flex's unput() since +% it puts back an arbitrary string rather than a character; it clobbers +% the values of \yytext, \yytext@, and \yytextpure so these must be saved before +% \unput is used + +\def\unput#1{% + \yytext@{#1}% + \concatl\yytext@\yytext@seen + \yytext{}\yytext@{}\yytextpure{}% +% \yystringempty{#1}{}{\yytextbackuptrue}% TODO: just set \yytexbackuptrue + \yytextbackuptrue +} + +%#define ROLLBACK_CURRENT_TOKEN \ +% do { \ +% scanner_cursor.column -= mbsnwidth (yytext, yyleng, 0); \ +% yyless (0); \ +% } while (0) + +\def\ROLLBACKCURRENTTOKEN{% this does not reset the streams + \concatl\yytext\yytextseen + \concatl\yytext\yytext@seen % do not rollback collected streams + \yytext{}\yytext@{}\yytextpure{}% + \yytextbackuptrue +} diff --git a/support/splint/tex/fretokenset.sty b/support/splint/tex/fretokenset.sty new file mode 100644 index 0000000000..6dfba7ea58 --- /dev/null +++ b/support/splint/tex/fretokenset.sty @@ -0,0 +1,21 @@ +% Copyright 2012-2020, Alexander Shibakov +% This file is part of SPLinT +% +% SPLinT is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% SPLinT is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with SPLinT. If not, see <http://www.gnu.org/licenses/>. + +% typesetting regular expression names in \flex's scanner + +\prettywordpairwvis{WS}{\.{\ }${}_+$}{ +} +\prettywordpairwvis{NL}{\hbox{$\hookleftarrow$}}{\n} +\prettywordpairwvis{OPTWS}{\.{\ }${}_*$}{ *} diff --git a/support/splint/tex/ftokenset.sty b/support/splint/tex/ftokenset.sty new file mode 100644 index 0000000000..9eb5fbd70d --- /dev/null +++ b/support/splint/tex/ftokenset.sty @@ -0,0 +1,72 @@ +% Copyright 2012-2020, Alexander Shibakov +% This file is part of SPLinT +% +% SPLinT is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% SPLinT is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with SPLinT. If not, see <http://www.gnu.org/licenses/>. + +% typesetting tokens in \flex's grammar + +\prettywordpairwvis{CHAR}{{\bf char}}{char} +\prettywordpairwvis{NUMBER}{{\bf num}}{num} +\prettywordpairwvis{NAME}{{\cyr\lqq{\rm name}\rqq}}{name} +\prettywordpairwvis{OPTION_OP}{\hbox{$\langle\hbox{\.{option}}\rangle$}}{option} +\prettywordpairwvis{EOF_OP}{\hbox{$\langle\hbox{\.{EOF}}\rangle$}}{EOF} + +\def\prettyccepairwvis#1#2{% + \prettywordpairwvis{#1}{\hbox{$\csname xccl@#1\endcsname$}}{#2}% + \prettyccep@irwvis#1.{#2}% +} + +\def\prettyccep@irwvis CCE_#1.#2{% + \prettywordpairwvis{CCE_NEG_#1}{\hbox{$\csname xccl@CCE_NEG_#1\endcsname$}}{neg #2}% +} + +\prettyccepairwvis{CCE_ALNUM}{alphan} +\prettyccepairwvis{CCE_ALPHA}{alpha} +\prettyccepairwvis{CCE_BLANK}{ .} +\prettyccepairwvis{CCE_GRAPH}{beta} +\prettyccepairwvis{CCE_DIGIT}{0} +\prettyccepairwvis{CCE_XDIGIT}{0..Z} +\prettyccepairwvis{CCE_SPACE}{ } +\prettyccepairwvis{CCE_LOWER}{a..z} +\prettyccepairwvis{CCE_UPPER}{A..Z} +\prettyccepairwvis{CCE_PRINT}{zzz} +\prettyccepairwvis{CCE_PUNCT}{.} +\prettyccepairwvis{CCE_CNTRL}{->} +% +\prettywordpairwvis{BEGIN_REPEAT_POSIX}{{\.{\{}$_{\rm p}$}}{\lbchar p} +\prettywordpairwvis{END_REPEAT_POSIX}{{\.{\}}$_{\rm p}$}}{\rbchar p} +\prettywordpairwvis{BEGIN_REPEAT_FLEX}{{\.{\{}$_{\rm f}$}}{\lbchar f} +\prettywordpairwvis{END_REPEAT_FLEX}{{\.{\}}$_{\rm f}$}}{\rbchar f} +\prettywordpairwvis{CCL_OP_DIFF}{\hbox{$\setminus$}}{\benignescape} +\prettywordpairwvis{CCL_OP_UNION}{\hbox{$\cup$}}{U}% see lstokenset.sty for setting up context-dependent indexing/display +\prettywordpairwvis{OPT_OUTFILE}{\hbox{$\langle\hbox{\.{outfile}}\rangle$}}{outfile} +\prettywordpairwvis{OPT_EXTRA_TYPE}{\hbox{$\langle\hbox{\.{extra type}}\rangle$}}{extra type} +\prettywordpairwvis{OPT_PREFIX}{\hbox{$\langle\hbox{\.{prefix}}\rangle$}}{prefix} +\prettywordpairwvis{OPT_YYCLASS}{\hbox{$\langle\hbox{\.{yyclass}}\rangle$}}{yyclass} +\prettywordpairwvis{OPT_HEADER}{\hbox{$\langle\hbox{\.{header}}\rangle$}}{header} +\prettywordpairwvis{OPT_TABLES}{\hbox{$\langle\hbox{\.{tables}}\rangle$}}{tables} + +\prettywordpairwvis{TOP_OP}{\hbox{$\langle\hbox{\.{top}}\rangle$}}{top_op} +\prettywordpairwvis{POINTER_OP}{\hbox{$\langle\hbox{\.{pointer*}}\rangle$}}{pointer_op} +\prettywordpairwvis{ARRAY_OP}{\hbox{$\langle\hbox{\.{array}}\rangle$}}{array_op} +\prettywordpairwvis{DEF_OP}{\hbox{$\langle\hbox{\.{def}}\rangle$}}{def_op} +\prettywordpairwvis{OPT_OTHER}{\hbox{$\langle\hbox{\.{other}}\rangle$}}{other_op} +\prettywordpairwvis{OPT_DEPRECATED}{\hbox{$\langle\hbox{\.{deprecated}}\rangle$}}{deprecated_op} +\prettywordpairwvis{RE_DEF}{\hbox{$\langle\hbox{\.{def}$_{\rm re}$}\rangle$}}{def_re} + +\prettywordpairwvis{SCDECL}{\hbox{$\langle\hbox{\bf state}\rangle$}}{state} +\prettywordpairwvis{XSCDECL}{\hbox{$\langle\hbox{\bf xtate}\rangle$}}{xtate} +\prettywordpairwvis{\\n}{\hbox{{\sixpoint\.{\\}}\.{n}}}{\benignescape n} +\prettywordpairwvis{-}{\hbox{\rm--}}{--} + diff --git a/support/splint/tex/gindex.sty b/support/splint/tex/gindex.sty new file mode 100644 index 0000000000..9d8ed2d334 --- /dev/null +++ b/support/splint/tex/gindex.sty @@ -0,0 +1,522 @@ +% Copyright 2012-2020, Alexander Shibakov +% This file is part of SPLinT +% +% SPLinT is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% SPLinT is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with SPLinT. If not, see <http://www.gnu.org/licenses/>. + +% indexing macros + +% set up the list of unindexable terms + +\ifx\unindexable\UNDEFINED + \def\unindexable{{$\TeXx$}{$\TeXa$}{$\TeXb$}{$\TeXf$}{$\TeXao$}{$\TeXfo$}}% +\else + \expandafter\def\expandafter\unindexable\expandafter + {\unindexable{$\TeXx$}{$\TeXa$}{$\TeXb$}{$\TeXf$}{$\TeXao$}{$\TeXfo$}}% +\fi + +\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)}} + +% 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} + +% \Cee\ index entry (produced by \CWEAVE\ and typeset directly from the file) + +\def\I#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 + }{% + \toksg{#1}% + }% +} + +\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\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\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}% + }% +}% + +\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{\csname index domain translation [#1]\endcsname}% + \vskip.3\baselineskip +} + +\expandafter\def\csname index domain translation [F]\endcsname{{\sc FLEX INDEX}} +\expandafter\def\csname index domain translation [T]\endcsname{{\sc\TeX\ 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{B{\sc ISON}, F{\sc LEX, AND} \TeX\ {\sc INDICES}}% + \vskip.5\baselineskip + \begindoublecols +} + +% 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} + +\def\inxmod{% new indexing macro + \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 + \message{Index:} + \medskip + \eightpoint\raggedright + \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 + \begindoublecols + \readindex + \otherlangindexseparator + \readgindex +} + +\newread\trygindex + +\def\readgindex{% + \openin\trygindex=\jobname.gdy + \ifeof\trygindex + \else + \closein\trygindex + \input \jobname.gdy + \fi +} diff --git a/support/splint/tex/grabstates.sty b/support/splint/tex/grabstates.sty index 6fa805168a..1024d99432 100644 --- a/support/splint/tex/grabstates.sty +++ b/support/splint/tex/grabstates.sty @@ -1,4 +1,4 @@ -% Copyright 2012-2015, Alexander Shibakov +% Copyright 2012-2020, Alexander Shibakov % This file is part of SPLinT % % SPLinT is free software: you can redistribute it and/or modify @@ -18,15 +18,27 @@ \input yycommon.sty % general routines for stack and array access \input yymisc.sty % helper macros (stack manipulation, table processing, value stack pointers) + % parser initialization, optimization \input yyinput.sty % input functions \input yyparse.sty % parser machinery \input flex.sty % lexer functions \input yyfaststack.sty % sped up stack access functions -\input yyboth.sty % parser initialization, optimization \input yyunion.sty +\def\yycomplain#1{\immediate\write16{#1}} % lexer errors + +% modify the input routine to recognize \yyendgame; the somewhat verbose end of +% the section is necessary to gracefully handle parser failures: the \endparse +% control sequence must appear outside of any \vb block for \cleanupparse +% to do its job; the \yyinput reads \vb blocks in pairs so the closing \vb{} is +% necessary and is removed by \removefinalvb (see limbo.sty and brack.pl for +% details). + +\expandafter\def\expandafter\multicharswitch\expandafter +{\multicharswitch\yyendgame{\yyinput\yyeof\yyeof\endparseinput\removefinalvb}} + \genericparser - name: main, + name: grabstates, ptables: cweb/byytab.tex, ltables: cweb/lstab.tex, tokens: {}, @@ -35,35 +47,54 @@ rsetup: {}, optimization: \optimizeall;% -\let\parsernamespace\mainnamespace +\let\parsernamespace\grabstatesnamespace \let\yylexreturn\yylexreturnregular -% main section macro +% stage two parsing macros \let\nx\noexpand -\expandafter\def\csname parserstack[b]\endcsname#1#2{% - \basicparserinit\yyparse#1\yyeof\yyeof\endparseinput\endparse - \ifyyparsefail % do nothing if parsing failed - \yybreak{}% - \else % Stage three, process the parsed table - \yybreak{% - \restorecslist{bootstrap}\yyunion - \the\table\relax - }% - \yycontinue +\def\preparsegrabstates{% + \let\postparse\postparsegrabstates + \basicparserinit + \yyparse } -\expandafter\def\csname parserstack[]\endcsname#1#2{% - \basicparserinit\yyparse#1\yyeof\yyeof\endparseinput\endparse +\def\postparsegrabstates{% \ifyyparsefail % do nothing if parsing failed \yybreak{}% \else % Stage three, process the parsed table \yybreak{% - \restorecslist{bootstrap}\yyunion + \restorecslist{bootstrap}\yyunion % TODO: this will not work in fs1 sections \the\table\relax }% \yycontinue } +\fillpstack{b}{% + \preparsegrabstates + \relax +} + +\fillpstack{fs1}{% + \preparsegrabstates + \relax +} + +% ignore in text production examples (there is no way or need to parse them anyway) + +\long\def\beginprod#1\endprod{} + +\let\begincprod\beginprod + +\def\nameproc#1\with#2{% + #2{}{}{}{}{}% pretend the name is empty +} + +\def\frexproc#1\with#2{% + #2{}{}{}% pretend the regex is empty +} + +\def\prodstyle#1{} + \newwrite\stlist diff --git a/support/splint/tex/hext.sty b/support/splint/tex/hext.sty new file mode 100644 index 0000000000..433d53ac5c --- /dev/null +++ b/support/splint/tex/hext.sty @@ -0,0 +1,346 @@ +% macros to typeset hex values in customized form (useful when typesetting embedded code) + +% the line translator: take a sequence of tokens and translate it into another sequence +% #1 is the sequence of tokens (will be expanded) to insert at the beginning +% #2 is the sequence of tokens (will be expanded) to insert before every token in the sequence +% #3 is the first sequence of tokens (will be expanded) to insert between tokens in the sequence +% #4 is the second sequence of tokens (will be expanded) to insert between tokens in the sequence +% #5 is the sequence of tokens (will be expanded) to insert at the end +% #6 is the command to execute after each token +% #7 is original sequence +% #8 is the resulting sequence + +\def\linetranslator#1#2#3#4#5#6:#7>#8{% + \def\ins@rt{#2}\def\insert@{#3}\def\@insert{#4}% + \def\@nd{#5}\def\c@mmand{#6}\let\t@kens#8% + \edef\next{\t@kens{\the\t@kens#1}}\next + \expandafter\linetr@nslator\the#7\end} + +\def\linetr@nslator#1#2{% + \ifx#1\end + \let\next\relax % no more tokens left + \else + \ifx#2\end % #1 is the last token + \edef\next{\t@kens{\the\t@kens\ins@rt#1\@nd}}\next + \else + \edef\next{\t@kens{\the\t@kens\ins@rt#1\insert@\@insert}}\next + \c@mmand + \fi + \let\next\linetr@nslator + \fi\next#2 +} + +% the mask translator: take a sequence of pairs {length:number}{contents} and translate it into another sequence +% #1 is the sequence of tokens (will be expanded) to insert at the beginning +% #2 is the sequence of tokens (will be expanded) to insert before every pair in the sequence +% #3 is the first sequence of tokens (will be expanded) to insert between pairs in the sequence +% #4 is the second sequence of tokens (will be expanded) to insert between pairs in the sequence +% #5 is the sequence of tokens (will be expanded) to insert at the end +% #6 is the command to execute after each pair +% #7 is original sequence +% #8 is the resulting sequence + +\def\masktranslator#1#2#3#4#5#6:#7>#8{% + \def\ins@rt{#2}\def\insert@{#3}\def\@insert{#4}% + \def\@nd{#5}\def\c@mmand{#6}\let\t@kens#8% + \edef\next{\t@kens{\the\t@kens#1}}\next + \m@sktranslator#7{"40000000}\relax\relax} + +\def\m@sktranslator#1#2#3{% + \ifnum#1<"40000000 % only happens when there are no pairs + \ifnum#3<"40000000 % not the last pair + \edef\next{\t@kens{\the\t@kens\ins@rt{#1}{#2}\insert@\@insert}}\next + \c@mmand + \let\next\m@sktranslator + \else + \edef\next{\t@kens{\the\t@kens\ins@rt{#1}{#2}\@nd}}\next + \let\next\m@sktr@nslator + \fi + \else + \let\next\m@sktr@nslator + \fi + \next{#3}% +} + +\def\m@sktr@nslator#1{} + +% binary converter + +\def\binary#1{% + \ifx#1\end + \let\next\relax + \else + \bin@ry#1\let\next\binary + \fi\next} + +\let\bits\toksa % storage for binary conversion bits +\newtoks\bytes % storage for the binary representation +\let\quotient\tempca +\let\oldquotient\tempcb + +\def\bin@ry#1{\bits{}\tempcc=4 \quotient="#1 \oldquotient=\quotient +\loop \divide\quotient by2 \multiply\quotient by2 \advance\oldquotient by-\quotient + \advance\tempcc by\m@ne + \edef\next{\bits{\the\oldquotient\the\bits}}\next + \divide\quotient by2 \oldquotient=\quotient +\ifnum\tempcc > \z@ +\repeat +\edef\next{\bytes{\the\bytes\the\bits}}\next} + +% display macros: +% +% o registers + +\newtoks\digittable % the table representing the register +\newcount\columncount % counter for the current column + +% o fonts + +\font\fivessb=phvb at4pt + +% o generic control sequences + +\def\incrementcc{\advance\columncount by\@ne} +\def\decrementcc{\advance\columncount by\m@ne} + +% o mask highlighting + +% the strange looking definition of \m@skspan originates from \multispan in plain.tex: +% \newcount\mscount +% \def\multispan#1{\omit \mscount#1\relax +% \loop\ifnum\mscount>\@ne \sp@n\repeat} +% \def\sp@n{\span\omit\advance\mscount\m@ne} +% +% the number of `physical' columns to span is (2 * columns - 1) due to the fact that we +% have to span the gaps between columns as well. + +\def\m@skspan#1#2{% + \multispan{#1\advance\mscount by\mscount\advance\mscount by-1}{\vrule\highltcl{\leaders\hrule height 4pt\hfil}\vrule}% +} + +% o mask underlining + +\def\m@sksp@n#1#2{% + \multispan{#1\advance\mscount by\mscount\advance\mscount by-1}{\hrulefill}% +} + +% o mask legend typesetting + +\def\m@sklegend#1#2{% + \multispan{#1\advance\mscount by\mscount\advance\mscount by-1}{\hfil\lgndcl{\fivessb#2}\hfil}% +} + +% o displaying each digit + +\def\dgtdispl@y#1#2{% + \ifx#20% + \let\colorbg\lightcl\let\colord\darkcl + \else + \let\colorbg\darkcl\let\colord\lightcl + \fi + \vrule\colorbg{\vrule height4pt width 12.5pt}% + \llap{\raise.6pt\hbox{\colord{\fivessb#1}$\,$}}\vrule +} + +% o typesetting space between digits + +\def\c@lumnspacer#1{\tempca#1\tempcb\tempca\divide\tempca by8\multiply\tempca by8 + \ifnum\tempca=\tempcb + \middlediamond + \else + \tempca#1\tempcb\tempca\divide\tempca by4\multiply\tempca by4 + \ifnum\tempca=\tempcb + \middledot + \else + \hfil + \fi + \fi} + +% oo dimond to separate bytes + +\def\middlediamond{\setbox0=\hbox{$\scriptscriptstyle\diamond$}\tempda=4pt \advance\tempda by-\ht0 + \divide\tempda by2 \hss\raise\tempda\box0\hss}% + +% oo dot to separate nybbles + +\def\middledot{\setbox0=\hbox{.}\tempda=4pt \advance\tempda by-\ht0 + \divide\tempda by2 \hss\raise\tempda\box0\hss}% + +% o put it all together + +\let\stcr\cr % so that this can be used inside \tabalign which redef's \cr + +\def\regdisplay#1#2{{% + \binary#1\end + \linetranslator{}{\hrulefill\noexpand\eatone}{&$\,\,$}{&}{\stcr}{\incrementcc}:\bytes>\digittable + \linetranslator{}{\noexpand\dgtdispl@y{\the\columncount}}{&\noexpand\c@lumnspacer{\the\columncount}}{&}% + {\stcr}{\decrementcc}:\bytes>\digittable + \masktranslator{}{\noexpand\m@sksp@n}{&\hfil}{&}{\stcr}{\relax}:{#2}>\digittable + \masktranslator{}{\noexpand\m@skspan}{&\hfil}{&}{\stcr}{\relax}:{#2}>\digittable + \masktranslator{}{\noexpand\m@sksp@n}{&\hfil}{&}{\stcr}{\relax}:{#2}>\digittable + \expandafter\digittable\expandafter{\the\digittable\noalign{\vskip-3.8pt}}% + \masktranslator{}{\noexpand\m@sklegend}{&\hfil}{&}{\stcr}{\relax}:{#2}>\digittable + \vbox{\offinterlineskip + \halign{&##\stcr + \the\digittable + } + }% +}} + +% colors + +\newif\iffullcolorpalette +\fullcolorpalettetrue + +\iffullcolorpalette + \let\lightcl=\colorpeach + \let\shadedcl=\colorcorn + \let\highltcl=\colorgray + \let\lgndcl=\colorwhite +\else + \let\lightcl=\colorwhite + \let\shadedcl=\colorgray + \let\highltcl=\colorwhite + \let\lgndcl=\colorblack +% \let\colorlinkstart=\begingroup +% \let\colorlinkend=\endgroup +\fi + \let\darkcl=\colorblack + +% an alternate display + +\def\altmiddledot{\setbox0=\hbox{.}% + \tempda=\ht\thezero \advance\tempda by-\ht0 + \divide\tempda by2 \advance\tempda by -\dp\thezero + $\,$\raise\tempda\box0$\,$% +} + +\def\altmiddlediamond{\setbox0=\hbox{$\scriptscriptstyle\diamond$}% + \tempda=\ht\thezero \advance\tempda by-\ht0 + \divide\tempda by2 \advance\tempda by -\dp\thezero + \hss\raise\tempda\box0\hss +} + +\def\altdgtdispl@y#1#2{% + \ifx#20% + \let\colorbg\lightcl\let\colord\darkcl + \else + \let\colorbg\darkcl\let\colord\lightcl + \fi + \setbox0=\hbox{$\,$0$\,$}\tempda\ht0 + \advance\tempda by 2pt \ht0\tempda + \vrule\colorbg{\lower1pt\hbox{\vrule height\ht0 depth\dp0 width \wd0}}% + \llap{\colord{\raise.5pt\hbox{\fivessb#1$\,$}}}\vrule +} + +\def\altc@lumnspacer#1{\tempca#1\tempcb\tempca + \divide\tempca by4\multiply\tempca by4 + \ifnum\tempca=\tempcb + \ % + \else + \kern1pt% + \fi +} + +\def\bytedisplay#1{{% + \binary#1\end + \linetranslator{}{\hrulefill\noexpand\eatone}{&\hfil}{&}{\stcr}{\incrementcc}:\bytes>\digittable + \linetranslator{}{\noexpand\altdgtdispl@y{\the\columncount}}{&\noexpand\altc@lumnspacer{\the\columncount}}{&}% + {\stcr}{\decrementcc}:\bytes>\digittable + \linetranslator{}{\hrulefill\noexpand\eatone}{&\hfil}{&}{\stcr}{\incrementcc}:\bytes>\digittable + \lower\dp\thezero\vbox{\offinterlineskip + \halign{&##\stcr + \the\digittable + } + }% +}} + +% macros to typeset the hex numbers in `graphic' format + +\newtoks\registerlegend + +\def\registerdisplay#1\end{\edef\next{\the\registerlegend}% + \ifx\next\empty + \edef\next{\noexpand\bytedisplay{#1}}\next + \else + \edef\next{\noexpand\regdisplay{#1}{\the\registerlegend}}\next + \fi +} + +\newbox\thezero + +\setbox\thezero=\hbox{\lower1pt\hbox{\vbox{\offinterlineskip +\halign{#&$\,$#$\,$&#\cr +\noalign{\hrule} +\omit\vrule height1pt&&\omit\vrule height1pt\cr +\vrule&\phantom0&\vrule\cr +\omit\vrule height1pt&&\omit\vrule height1pt\cr +\noalign{\hrule} +}}}} + +\def\texbinary{\global\let\oldT\T + \global\def\T##1{{\let\end\relax\let\^\registerdisplay##1\end{\tt :}\let\^\hexify##1\end}}} + +\def\endtexbinary{\global\let\T\oldT} + +\def\hexify#1\end{\hbox{{\tt #1}$_{\scriptscriptstyle1\kern-.7pt6}$}} + +% delay functions prettyprinting and other miscellanea; + +\def\delayhalfsec{\hbox{wait \kern-.5pt\raise1pt\hbox{$\scriptstyle1$}% +\kern-1pt/\kern-1pt\lower1pt\hbox{$\scriptstyle2$} sec, }} +\def\delayquartersec{\hbox{wait \kern-.5pt\raise1pt\hbox{$\scriptstyle1$}% +\kern-1pt/\kern-1pt\lower1pt\hbox{$\scriptstyle4$} sec, }} + +\def\delay#1sec{% +\hbox{\def\secmult{}wait +\getsecmult#1\end +\if\secmult u\def\secmodifier{ $\mu$\kern.05pt }\else +\if\secmult m\def\secmodifier{ m}\else +\if\secmult n\def\secmodifier{ n}\else + \secmult\def\secmodifier{ }% +\fi\fi\fi +\secmodifier sec$\rm\scriptstyle s$, } +} + +\def\getsecmult#1{% +\ifx#1\end\let\next\relax\else + \secmult\def\secmult{#1}\let\next\getsecmult +\fi\next +} + +% attribute prettyprinting; + +\long\def\parseattrib#1#2\end{\csname attrib#1\endcsname} + +\def\xxattributexx#1{\ifx(#1\let\next\xxattributex\else\let\next\xxattribute\fi\next#1} +\def\xxattributex((\\#1{% + \expandafter\let\expandafter\currentattrib\csname attrib#1\endcsname + \ifx\currentattrib\attribpacked + \strut\colorblack{% + \lower2pt\hbox{\vrule width \wd\thezero height + \ht\thezero depth + \dp\thezero}}\llap{\colorwhite{\hbox{$\scriptscriptstyle\bf 01\kern.5pt$}}}% + \let\next\eatparentheses + \fi + \ifx\currentattrib\attribnoinline + {\ \bf noinline\rm_a}% + \let\next\eatparentheses + \fi + \ifx\currentattrib\attribformat + {\ \bf format\rm_a}% + \let\next\eatarguments + \fi + \next +} + +\def\eatparentheses#1)){} +\def\eatarguments(\\#1,#2,#3))){(\hbox{\rm as }\.{#1})} + +\def\xxattribute#1{\.{\_\_attribute\_\_} (\sc GNU) #1} + +\let\attribnoinline=1 +\let\attribpacked=2 +\let\attribformat=3 + +%\registerlegend{{8}{\noexpand\phantom{B}}} diff --git a/support/splint/tex/limbo.sty b/support/splint/tex/limbo.sty index 1ab76629a4..c810cd55da 100644 --- a/support/splint/tex/limbo.sty +++ b/support/splint/tex/limbo.sty @@ -1,4 +1,4 @@ -% Copyright 2012-2015, Alexander Shibakov +% Copyright 2012-2020, Alexander Shibakov % This file is part of SPLinT % % SPLinT is free software: you can redistribute it and/or modify @@ -14,7 +14,7 @@ % You should have received a copy of the GNU General Public License % along with SPLinT. If not, see <http://www.gnu.org/licenses/>. -% limbo.sty version 2.3 +% limbo.sty version 3.0 \input epsf.tex \input amssym.def @@ -52,9 +52,29 @@ \font\seventitle=cmssbx7 \font\titlefrak=eufb10 at 12pt +%\font\eightss=cmssq8 +%\font\eightssi=cmssqi8 + \font\tenss=cmss10 \font\niness=cmss9 \font\eightss=cmss8 +\font\sevenss=cmss7 +\font\sixss=cmss6 +\font\fivess=cmss5 + +\font\tenssn=cmssdc10 +\font\ninessn=cmssdc9 +\font\eightssn=cmssdc8 +\font\sevenssn=cmssdc7 +\font\sixssn=cmssdc6 +\font\fivessn=cmssdc5 + +\font\tenssb=cmssbx10 +\font\ninessb=cmssbx9 +\font\eightssb=cmssbx8 +\font\sevenssb=cmssbx7 +\font\sixssb=cmssbx6 +\font\fivessb=cmssbx5 \font\twelvetitleit=cmssbxo10 at 12pt \font\ninetitleit=cmssbxo10 at 9pt @@ -75,10 +95,11 @@ \font\ninerm=cmr9 \font\eightrm=cmr8 \font\sevenrm=cmr7 +\font\sixrm=cmr6 + \font\ninecyr=lhr9 \font\eightcyr=lhr8 \font\sevencyr=lhr7 -\font\sixrm=cmr6 \font\ninei=cmmi9 \font\eighti=cmmi8 @@ -90,10 +111,6 @@ \font\sixsy=cmsy6 \skewchar\ninesy='60 \skewchar\eightsy='60 \skewchar\sixsy='60 -\font\eightss=cmssq8 - -\font\eightssi=cmssqi8 - \font\twelvebf=cmbx12 \font\ninebf=cmbx9 \font\eightbf=cmbx8 @@ -102,6 +119,13 @@ \font\ninett=cmtt9 \font\eighttt=cmtt8 \font\seventt=cmtt7 +\font\sixtt=cmtt6 + +\font\tentti=cmitt10 % typewriter italic +\font\ninetti=cmitt9 +\font\eighttti=cmitt8 +\font\seventti=cmitt7 +\font\sixtti=cmitt6 \hyphenchar\tentt=-1 % inhibit hyphenation in typewriter type \hyphenchar\ninett=-1 @@ -110,6 +134,7 @@ \font\ninesl=cmsl9 \font\eightsl=cmsl8 \font\sevensl=cmsl7 +\font\sixsl=cmsl6 \font\nineit=cmti9 \font\eightit=cmti8 @@ -137,11 +162,19 @@ \font\ninefrak=eufm9 \font\eightfrak=eufm8 \font\sevenfrak=eufm7 +\font\sixfrak=eufm6 \font\hv=phvr +\font\dings=pzdr +\font\dingssmall=pzdr at 8pt +\chardef\pen='062 +\chardef\leaf='247 +\chardef\fancystar='122 + +\newfam\ssfam +\newfam\ssbnfam \newfam\itbfam -\newfam\frakfam \newfam\msbmfam \newfam\msamfam @@ -183,26 +216,35 @@ \let\{=\LB % left brace in a string \let\}=\RB % right brace in a string }% + \def\tti{\fam\ttfam\tentti % switch to typewriter italic + \let\{=\LB % left brace in a string + \let\}=\RB % right brace in a string + }% \def\ttex{\tentex \let\{=\LB % left brace in a string \let\}=\RB % right brace in a string }% \def\ttl{\let\it\tentitlei\let\sl\tentitlei\tentitle}% - \def\ssf{\tenss}% + \def\ssf{\fam\ssfam\tenss}% + \textfont\ssfam=\tenss\scriptfont\ssfam=\sevenss + \def\ssfb{\fam\ssfam\tenssb}% + \def\ssfbn{\fam\ssbnfam\tenssb}% + \textfont\ssbnfam=\tenssn\scriptfont\ssfam=\sevenssn \textfont\ttfam=\tentt - \tt \ttglue=.5em plus.25em minus.15em + \fam\ttfam\tentt \ttglue=.5em plus.25em minus.15em \def\Bbb{\fam\msbmfam\tenmsbm}% \textfont\msbmfam=\tenmsbm\scriptfont\msbmfam=\sevenmsbm \scriptscriptfont\msbmfam=\fivemsbm \textfont\msamfam=\tenmsam\scriptfont\msamfam=\sevenmsam \scriptscriptfont\msamfam=\fivemsam - \textfont\frakfam=\tenfrak - \def\frak##1{{\fam\frakfam\tenfrak ##1}}% + \def\frak##1{{\tenfrak ##1}}% \normalbaselineskip=12pt \let\sc=\eightrm + \let\sci=\eightit \let\mc=\ninerm \let\cyr=\tencyr \let\big=\tenbig \setbox\strutbox=\hbox{\vrule height8.5pt depth3.5pt width0pt}% + \let\sscmd\sevenpoint \normalbaselines\rm} \def\ninepoint{\def\rm{\fam0\ninerm}% @@ -223,26 +265,36 @@ \let\{=\LB % left brace in a string \let\}=\RB % right brace in a string }% + \def\tti{\fam\ttfam\ninetti % switch to typewriter italic + \let\{=\LB % left brace in a string + \let\}=\RB % right brace in a string + }% \def\ttex{\ninetex \let\{=\LB % left brace in a string \let\}=\RB % right brace in a string }% \def\ttl{\let\it\ninetitleit\let\sl\ninetitleit\ninetitle}% - \def\ssf{\niness}% + \def\ssf{\fam\ssfam\niness}% + \textfont\ssfam=\niness\scriptfont\ssfam=\sixss + \def\ssfb{\fam\ssfam\ninessb}% + %no room for another font family + \def\ssfbn{\fam\ssbnfam\ninessn}% + \textfont\ssbnfam=\ninessn\scriptfont\ssbnfam=\sixssn \textfont\ttfam=\ninett - \tt \ttglue=.5em plus.25em minus.15em + \fam\ttfam\ninett \ttglue=.5em plus.25em minus.15em \def\Bbb{\fam\msbmfam\ninemsbm}% \textfont\msbmfam=\ninemsbm\scriptfont\msbmfam=\sixmsbm \scriptscriptfont\msbmfam=\fivemsbm \textfont\msamfam=\ninemsam\scriptfont\msamfam=\sixmsam \scriptscriptfont\msamfam=\fivemsam - \textfont\frakfam=\ninefrak - \def\frak##1{{\fam\frakfam\ninefrak ##1}}% + \def\frak##1{{\ninefrak ##1}}% \normalbaselineskip=11pt \let\sc=\sevenrm + \let\sci\sevenit \let\mc=\eightrm \let\cyr=\ninecyr \let\big=\ninebig \setbox\strutbox=\hbox{\vrule height8pt depth3pt width0pt}% + \let\sscmd\sixpoint \normalbaselines\rm} \def\eightpoint{\def\rm{\fam0\eightrm}% @@ -262,24 +314,34 @@ \let\{=\LB % left brace in a string \let\}=\RB % right brace in a string }% + \def\tti{\fam\ttfam\eighttti % switch to typewriter italic + \let\{=\LB % left brace in a string + \let\}=\RB % right brace in a string + }% \def\ttex{\eighttex \let\{=\LB % left brace in a string \let\}=\RB % right brace in a string }% \textfont\ttfam=\eighttt - \tt \ttglue=.5em plus.25em minus.15em + \fam\ttfam\eighttt \ttglue=.5em plus.25em minus.15em + \def\ssf{\fam\ssfam\eightss}% + \textfont\ssfam=\eightss\scriptfont\ssfam=\sixss + \def\ssfb{\fam\ssfam\eightssb}% + \def\ssfbn{\fam\ssbnfam\eightssb}% + \textfont\ssbnfam=\eightssn\scriptfont\ssbnfam=\sixssn \def\Bbb{\fam\msbmfam\eightmsbm}% \textfont\msbmfam=\eightmsbm\scriptfont\msbmfam=\sixmsbm \scriptscriptfont\msbmfam=\fivemsbm \textfont\msamfam=\eightmsam\scriptfont\msamfam=\sixmsam \scriptscriptfont\msamfam=\fivemsam - \textfont\frakfam=\eightfrak - \def\frak##1{{\fam\frakfam\eightfrak ##1}}% + \def\frak##1{{\eightfrak ##1}}% \normalbaselineskip=9pt \let\sc=\sixrm + \let\sci=\sixit \let\mc=\sevenrm \let\cyr=\eightcyr \let\big=\eightbig \setbox\strutbox=\hbox{\vrule height7pt depth2pt width0pt}% + \let\sscmd\sixpoint \normalbaselines\rm} \def\sevenpoint{\def\rm{\fam0\sevenrm}% @@ -298,21 +360,92 @@ \let\{=\LB % left brace in a string \let\}=\RB % right brace in a string }% + \def\tti{\fam\ttfam\seventti % switch to typewriter italic + \let\{=\LB % left brace in a string + \let\}=\RB % right brace in a string + }% \textfont\ttfam=\seventt - \tt \ttglue=.5em plus.25em minus.15em + \fam\ttfam\seventt \ttglue=.5em plus.25em minus.15em + \def\ssf{\fam\ssfam\sevenss}% + \textfont\ssfam=\sevenss\scriptfont\ssfam=\sixss + \def\ssfb{\fam\ssfam\sevenssb}% + \def\ssfbn{\fam\ssbnfam\sevenssb}% + \textfont\ssbnfam=\sevenssn\scriptfont\ssbnfam=\sixssn \def\Bbb{\fam\msbmfam\sevenmsbm}% \textfont\msbmfam=\sevenmsbm\scriptfont\msbmfam=\sixmsbm \scriptscriptfont\msbmfam=\fivemsbm \textfont\msamfam=\sevenmsam\scriptfont\msamfam=\sixmsam \scriptscriptfont\msamfam=\fivemsam - \textfont\frakfam=\sevenfrak - \def\frak##1{{\fam\frakfam\sevenfrak ##1}}% + \def\frak##1{{\sevenfrak ##1}}% \normalbaselineskip=8pt \let\sc=\sixrm + \let\sci=\sixit \let\mc=\sixrm \let\big=\sevenbig \setbox\strutbox=\hbox{\vrule height6pt depth2pt width0pt}% \normalbaselines\rm} +\def\sixpoint{\def\rm{\fam0\sixrm}% + \textfont0=\sixrm \scriptfont0=\fiverm \scriptscriptfont0=\fiverm + \textfont1=\sixi \scriptfont1=\fivei \scriptscriptfont1=\fivei + \textfont2=\sixsy \scriptfont2=\fivesy \scriptscriptfont2=\fivesy + \textfont3=\tenex \scriptfont3=\tenex \scriptscriptfont3=\tenex + \def\it{\fam\itfam\sixit}% + \def\itbold{\fam\itbfam\sixboldi}% + \textfont\itfam=\sixit + \def\sl{\fam\slfam\sixsl}% + \textfont\slfam=\sixsl + \def\bf{\fam\bffam\sixbf}% + \textfont\bffam=\sixbf \scriptfont\bffam=\fivebf\scriptscriptfont\bffam=\fivebf + \def\tt{\fam\ttfam\sixtt + \let\{=\LB % left brace in a string + \let\}=\RB % right brace in a string + }% + \def\tti{\fam\ttfam\sixtti % switch to typewriter italic + \let\{=\LB % left brace in a string + \let\}=\RB % right brace in a string + }% + \textfont\ttfam=\sixtt + \fam\ttfam\sixtt \ttglue=.5em plus.25em minus.15em + \def\ssf{\fam\ssfam\sixss}% + \textfont\ssfam=\sixss\scriptfont\ssfam=\fivess + \def\ssfb{\fam\ssfam\sixssb}% + \def\ssfbn{\fam\ssbnfam\sixssb}% + \textfont\ssbnfam=\sixssn\scriptfont\ssbnfam=\fivessn + \def\Bbb{\fam\msbmfam\sixmsbm}% + \textfont\msbmfam=\sixmsbm\scriptfont\msbmfam=\fivemsbm \scriptscriptfont\msbmfam=\fivemsbm + \textfont\msamfam=\sixmsam\scriptfont\msamfam=\fivemsam + \scriptscriptfont\msamfam=\fivemsam + \def\frak##1{{\sixfrak ##1}}% + \normalbaselineskip=8pt + \let\sc=\sixrm + \let\sci=\sixit + \let\mc=\sixrm + \let\big=\sixbig + \setbox\strutbox=\hbox{\vrule height5.5pt depth1.5pt width0pt}% + \normalbaselines\rm} + +\def\em{\let\tt\tti\let\sc\sci\it} + +% fonts for the chapter titles + +\font\cmhuge=cmssbx10 at .7in +\font\tthuge=cmtt10 at .7 in + +\font\cmmiddle=cmss10 at .3in +\font\ttmiddle=cmtt10 at .3in + +\def\hugetitle{% + \let\ssf\cmhuge + \let\tt\tthuge + \ssf +} + +\def\midtitle{% + \let\ssf\cmmiddle + \let\tt\ttmiddle + \ssf +} + % temporary registers \input trt1.sty @@ -416,244 +549,10 @@ \raise\ht\strutbox\vbox to 0pt{\vss\hbox to 0pt{\pdfdest name {#1} xyz}}% \fi} -% macros to typeset hex values in customized form (useful when typesetting embedded code) - -% the line translator: take a sequence of tokens and translate it into another sequence -% #1 is the sequence of tokens (will be expanded) to insert at the beginning -% #2 is the sequence of tokens (will be expanded) to insert before every token in the sequence -% #3 is the first sequence of tokens (will be expanded) to insert between tokens in the sequence -% #4 is the second sequence of tokens (will be expanded) to insert between tokens in the sequence -% #5 is the sequence of tokens (will be expanded) to insert at the end -% #6 is the command to execute after each token -% #7 is original sequence -% #8 is the resulting sequence - -\def\linetranslator#1#2#3#4#5#6:#7>#8{% - \def\ins@rt{#2}\def\insert@{#3}\def\@insert{#4}% - \def\@nd{#5}\def\c@mmand{#6}\let\t@kens#8% - \edef\next{\t@kens{\the\t@kens#1}}\next - \expandafter\linetr@nslator\the#7\end} - -\def\linetr@nslator#1#2{% - \ifx#1\end - \let\next\relax % no more tokens left - \else - \ifx#2\end % #1 is the last token - \edef\next{\t@kens{\the\t@kens\ins@rt#1\@nd}}\next - \else - \edef\next{\t@kens{\the\t@kens\ins@rt#1\insert@\@insert}}\next - \c@mmand - \fi - \let\next\linetr@nslator - \fi\next#2 -} - -% the mask translator: take a sequence of pairs {length:number}{contents} and translate it into another sequence -% #1 is the sequence of tokens (will be expanded) to insert at the beginning -% #2 is the sequence of tokens (will be expanded) to insert before every pair in the sequence -% #3 is the first sequence of tokens (will be expanded) to insert between pairs in the sequence -% #4 is the second sequence of tokens (will be expanded) to insert between pairs in the sequence -% #5 is the sequence of tokens (will be expanded) to insert at the end -% #6 is the command to execute after each pair -% #7 is original sequence -% #8 is the resulting sequence - -\def\masktranslator#1#2#3#4#5#6:#7>#8{% - \def\ins@rt{#2}\def\insert@{#3}\def\@insert{#4}% - \def\@nd{#5}\def\c@mmand{#6}\let\t@kens#8% - \edef\next{\t@kens{\the\t@kens#1}}\next - \m@sktranslator#7{"40000000}\relax\relax} - -\def\m@sktranslator#1#2#3{% - \ifnum#1<"40000000 % only happens when there are no pairs - \ifnum#3<"40000000 % not the last pair - \edef\next{\t@kens{\the\t@kens\ins@rt{#1}{#2}\insert@\@insert}}\next - \c@mmand - \let\next\m@sktranslator - \else - \edef\next{\t@kens{\the\t@kens\ins@rt{#1}{#2}\@nd}}\next - \let\next\m@sktr@nslator - \fi - \else - \let\next\m@sktr@nslator - \fi - \next{#3}% +\def\pdfpagelink#1{% reference the page number + \pdfstartlink attr {/Border [0 0 0]} goto page #1 {/XYZ null null null}\BlueGreen#1\Black\pdfendlink } -\def\m@sktr@nslator#1{} - -% binary converter - -\def\binary#1{% - \ifx#1\end - \let\next\relax - \else - \bin@ry#1\let\next\binary - \fi\next} - -\let\bits\toksa % storage for binary conversion bits -\newtoks\bytes % storage for the binary representation -\let\quotient\tempca -\let\oldquotient\tempcb - -\def\bin@ry#1{\tempcc=4 \quotient="#1 \oldquotient=\quotient -\loop \divide\quotient by2 \multiply\quotient by2 \advance\oldquotient by-\quotient - \advance\tempcc by\m@ne - \edef\next{\bits{\the\oldquotient\the\bits}}\next - \divide\quotient by2 \oldquotient=\quotient -\ifnum\tempcc > \z@ -\repeat -\edef\next{\bytes{\the\bytes\the\bits}}\next -\bits{}} - -% display macros: -% -% o registers - -\newtoks\digittable % the table representing the register -\newcount\columncount % counter for the current column - -% o fonts - -\font\fivessb=phvb at4pt - -% o generic control sequences - -\def\incrementcc{\advance\columncount by\@ne} -\def\decrementcc{\advance\columncount by\m@ne} - -% o mask highlighting - -% the strange looking definition of \m@skspan originates from \multispan in plain.tex: -% \newcount\mscount -% \def\multispan#1{\omit \mscount#1\relax -% \loop\ifnum\mscount>\@ne \sp@n\repeat} -% \def\sp@n{\span\omit\advance\mscount\m@ne} -% -% the number of `physical' columns to span is (2 * columns - 1) due to the fact that we -% have to span the gaps between columns as well. - -\def\m@skspan#1#2{% - \multispan{#1\advance\mscount by\mscount\advance\mscount by-1}{\vrule\highltcl{\leaders\hrule height 4pt\hfil}\vrule}% -} - -% o mask underlining - -\def\m@sksp@n#1#2{% - \multispan{#1\advance\mscount by\mscount\advance\mscount by-1}{\hrulefill}% -} - -% o mask legend typesetting - -\def\m@sklegend#1#2{% - \multispan{#1\advance\mscount by\mscount\advance\mscount by-1}{\hfil\lgndcl{\fivessb#2}\hfil}% -} - -% o displaying each digit - -\def\dgtdispl@y#1#2{% - \ifx#20% - \let\colorbg\lightcl\let\colord\darkcl - \else - \let\colorbg\darkcl\let\colord\lightcl - \fi - \vrule\colorbg{\vrule height4pt width 12.5pt}% - \llap{\raise.6pt\hbox{\colord{\fivessb#1}$\,$}}\vrule -} - -% o typesetting space between digits - -\def\c@lumnspacer#1{\tempca#1\tempcb\tempca\divide\tempca by8\multiply\tempca by8 - \ifnum\tempca=\tempcb - \middlediamond - \else - \tempca#1\tempcb\tempca\divide\tempca by4\multiply\tempca by4 - \ifnum\tempca=\tempcb - \middledot - \else - \hfil - \fi - \fi} - -% oo dimond to separate bytes - -\def\middlediamond{\setbox0=\hbox{$\scriptscriptstyle\diamond$}\tempda=4pt \advance\tempda by-\ht0 - \divide\tempda by2 \hss\raise\tempda\box0\hss}% - -% oo dot to separate nybbles - -\def\middledot{\setbox0=\hbox{.}\tempda=4pt \advance\tempda by-\ht0 - \divide\tempda by2 \hss\raise\tempda\box0\hss}% - -% o put it all together - -\let\stcr\cr % so that this can be used inside \tabalign which redef's \cr - -\def\regdisplay#1#2{{% - \binary#1\end - \linetranslator{}{\hrulefill\noexpand\eatone}{&$\,\,$}{&}{\stcr}{\incrementcc}:\bytes>\digittable - \linetranslator{}{\noexpand\dgtdispl@y{\the\columncount}}{&\noexpand\c@lumnspacer{\the\columncount}}{&}% - {\stcr}{\decrementcc}:\bytes>\digittable - \masktranslator{}{\noexpand\m@sksp@n}{&\hfil}{&}{\stcr}{\relax}:{#2}>\digittable - \masktranslator{}{\noexpand\m@skspan}{&\hfil}{&}{\stcr}{\relax}:{#2}>\digittable - \masktranslator{}{\noexpand\m@sksp@n}{&\hfil}{&}{\stcr}{\relax}:{#2}>\digittable - \expandafter\digittable\expandafter{\the\digittable\noalign{\vskip-3.8pt}}% - \masktranslator{}{\noexpand\m@sklegend}{&\hfil}{&}{\stcr}{\relax}:{#2}>\digittable - \vbox{\offinterlineskip - \halign{&##\stcr - \the\digittable - } - }% -}} - -% an alternate display - -\def\altmiddledot{\setbox0=\hbox{.}% - \tempda=\ht\thezero \advance\tempda by-\ht0 - \divide\tempda by2 \advance\tempda by -\dp\thezero - $\,$\raise\tempda\box0$\,$% -} - -\def\altmiddlediamond{\setbox0=\hbox{$\scriptscriptstyle\diamond$}% - \tempda=\ht\thezero \advance\tempda by-\ht0 - \divide\tempda by2 \advance\tempda by -\dp\thezero - \hss\raise\tempda\box0\hss -} - -\def\altdgtdispl@y#1#2{% - \ifx#20% - \let\colorbg\lightcl\let\colord\darkcl - \else - \let\colorbg\darkcl\let\colord\lightcl - \fi - \setbox0=\hbox{$\,$0$\,$}\tempda\ht0 - \advance\tempda by 2pt \ht0\tempda - \vrule\colorbg{\lower1pt\hbox{\vrule height\ht0 depth\dp0 width \wd0}}% - \llap{\colord{\raise.5pt\hbox{\fivessb#1$\,$}}}\vrule -} - -\def\altc@lumnspacer#1{\tempca#1\tempcb\tempca - \divide\tempca by4\multiply\tempca by4 - \ifnum\tempca=\tempcb - \ % - \else - \kern1pt% - \fi -} - -\def\bytedisplay#1{{% - \binary#1\end - \linetranslator{}{\hrulefill\noexpand\eatone}{&\hfil}{&}{\stcr}{\incrementcc}:\bytes>\digittable - \linetranslator{}{\noexpand\altdgtdispl@y{\the\columncount}}{&\noexpand\altc@lumnspacer{\the\columncount}}{&}% - {\stcr}{\decrementcc}:\bytes>\digittable - \linetranslator{}{\hrulefill\noexpand\eatone}{&\hfil}{&}{\stcr}{\incrementcc}:\bytes>\digittable - \lower\dp\thezero\vbox{\offinterlineskip - \halign{&##\stcr - \the\digittable - } - }% -}} - \quickcolordef{peach}{0 0.06 0.14 0} \quickcolordef{corn}{0 0.06 0.63 0.02} \quickcolordef{sandybrown}{0 0.33 0.61 0.04} @@ -664,54 +563,6 @@ \def\colorwhite#1{\grayset{1}#1\restorecolor} \def\colorgray#1{\grayset{.5}#1\restorecolor} -\newif\iffullcolorpalette -\fullcolorpalettetrue - -\iffullcolorpalette - \let\lightcl=\colorpeach - \let\shadedcl=\colorcorn - \let\highltcl=\colorgray - \let\lgndcl=\colorwhite -\else - \let\lightcl=\colorwhite - \let\shadedcl=\colorgray - \let\highltcl=\colorwhite - \let\lgndcl=\colorblack -% \let\colorlinkstart=\begingroup -% \let\colorlinkend=\endgroup -\fi - \let\darkcl=\colorblack - -% macros to typeset the hex numbers in `graphic' format - -\newtoks\registerlegend - -\def\registerdisplay#1\end{\edef\next{\the\registerlegend}% - \ifx\next\empty - \edef\next{\noexpand\bytedisplay{#1}}\next - \else - \edef\next{\noexpand\regdisplay{#1}{\the\registerlegend}}\next - \fi -} - -\newbox\thezero - -\setbox\thezero=\hbox{\lower1pt\hbox{\vbox{\offinterlineskip -\halign{#&$\,$#$\,$&#\cr -\noalign{\hrule} -\omit\vrule height1pt&&\omit\vrule height1pt\cr -\vrule&\phantom0&\vrule\cr -\omit\vrule height1pt&&\omit\vrule height1pt\cr -\noalign{\hrule} -}}}} - -\def\texbinary{\global\let\oldT\T - \global\def\T##1{{\let\end\relax\let\^\registerdisplay##1\end{\tt :}\let\^\hexify##1\end}}} - -\def\endtexbinary{\global\let\T\oldT} - -\def\hexify#1\end{\hbox{{\tt #1}$_{\scriptscriptstyle1\kern-.7pt6}$}} - % verbatim listing macros borrowed (with changes) from The TeXbook \newcount\democodelc @@ -801,31 +652,55 @@ % macros that provide a way to customize printing of reserved words -\newtoks\tempseq -\tempseq={RVD} \let\oldamp\& \let\oldoneletterid\| -\def\replaceunderscore#1{\let\next\replaceunderscore - \ifx#1\_\tempseq=\expandafter{\the\tempseq x}\else - \ifx#1\#\tempseq=\expandafter{\the\tempseq H}\else - \ifx#1\end\let\next\relax\else\tempseq=\expandafter{\the\tempseq #1}\fi - \fi - \fi\next} -\def\reservedid#1{{\replaceunderscore#1\end - \expandafter\let\expandafter\newseq\csname\the\tempseq\endcsname - \ifx\relax\newseq\oldamp{#1}\else\newseq\fi}} - -\def\reservedoneletterid#1{{% - \expandafter\let\expandafter\newseq\csname\the\tempseq\string#1\endcsname - \ifx\relax\newseq\oldoneletterid{#1}\else\newseq\fi}} +\let\oldslashslash\\ + +\def\replaceunderscore#1{% + \ifx#1\_% + \yybreak{x\replaceunderscore}% + \else + \ifx#1\#% + \yybreak@{H\replaceunderscore}% + \else + \ifx#1\end + \yybreak@@{}% + \else + \yybreak@@{\string#1\replaceunderscore}% + \fi + \fi + \yycontinue +} + +\def\reservedid#1{\expandafter\r@servedid\expandafter{\csname RVD\replaceunderscore#1\end\endcsname}{#1}} + +\def\r@servedid#1#2{\ifx#1\relax\yybreak{\oldamp{#2}}\else\yybreak{#1}\yycontinue} + +\def\reservedname#1{\expandafter\r@servedname\expandafter{\csname RVD\replaceunderscore#1\end\endcsname}{#1}} + +\def\r@servedname#1#2{\ifx#1\relax\yybreak{\oldslashslash{#2}}\else\yybreak{#1}\yycontinue} + +\def\reservedoneletterid#1{% + \expandafter\ifx\csname RVD\string#1\endcsname\relax + \yybreak{\oldoneletterid{#1}}% + \else + \yybreak{\csname RVD\string#1\endcsname}% + \yycontinue} \def\defreserved#1{% - \expandafter\def\csname\the\tempseq #1\endcsname + \expandafter\def\csname RVD\replaceunderscore#1\end\endcsname } \let\&\reservedid \let\|\reservedoneletterid +% better `hash' + +\let\oldhash\# +\def\#{\lower.5pt\hbox{\tt\oldhash}} + +\let\oldmathS\$ + % cweb macros adopted to making typesetting languages other than C possible: Makefile and linker scripts. \tempca=\catcode`\^^I% remember the old catcode @@ -843,6 +718,8 @@ \let\&=\AM % ampersand in a string \let\^=\CF % circumflex in a string \let\$=\oldmathS % dollar sign + \let\#=\oldhash % hash symbol: the new definition above would break alignment + \let\n\empty % the `end of line' inserted by the preprocessing script \def^^I{$\llcorner$&$\lrcorner$}% a tab is a tab \tabalign{}#1\cr}}}\endgroup} % verbatim string \catcode`\^^I=\tempca @@ -854,17 +731,12 @@ \def\R{\hbox{$^{\rm not}$}} \let\CM\lnot \def\MRL#1{\KK#1}\def\KK#1#2{\buildrel\;{\let\OR\lor\scriptscriptstyle#1}\over#2} -\def\C#1{\5\5\quad$\triangleright\,${\rm #1}$\,\triangleleft$} +\def\C#1{\5\5\quad\hbox{$\triangleright\,$}{\rm #1}\hbox{$\,\triangleleft$}} \let\Z=\leq \let\G=\geq \let\E== \def\tabC#1{\quad$\triangleright\,${\cmntfont#1}$\,\triangleleft$} -% better `hash' - -\let\oldhash\# -\def\#{\lower.5pt\hbox{\.{\oldhash}}} - \def\.#1{\leavevmode\hbox{\tt % typewriter type for strings \let\\=\BS % backslash in a string \let\{=\LB % left brace in a string @@ -880,263 +752,180 @@ % macros to change the appearance of section headers \outer\def\N#1#2#3.{% beginning of starred section - \ifacro{\toksF={}\makeoutlinetoks#3\outlinedone\outlinedone}\fi - \gdepth=#1\gtitle={#3}\MN{#2}% - \ifon\ifnum#1<\secpagedepth \vfil\eject % force page break if depth is small - \else\vfil\penalty-100\vfilneg\vskip\intersecskip\fi\fi - \message{*\secno} % progress report - \def\stripprefix##1>{}\def\gtitletoks{#3}% - \edef\gtitletoks{\expandafter\stripprefix\meaning\gtitletoks}% - \edef\next{\write\cont{%\noexpand\noexpand\noexpand\eatone{\noexpand\meaning\noexpand\ZZ}% - \noexpand\noexpand\noexpand % AS this is a (sort of) bug in cwebmac.tex - % as long as the index is output (i.e. ...\eject) - % before all the sections this is unnecessary - % uncomment the line after the brace to see what \ZZ - % expands to in case of weird errors - \ZZ{\gtitletoks}{#1}{\secno}% write to contents file - {\noexpand\the\pageno}{\the\toksE}}}\next % \ZZ{title}{depth}{sec}{page}{ss} - \ifpdftex\expandafter\xdef\csname curr#1\endcsname{\secno}% - \ifnum#1>0\countB=#1 \advance\countB by-1 - \advancenumber{chunk\the\countB.\expnumber{curr\the\countB}}\fi\fi - \ifpdf\special{pdf: outline #1 << /Title (\the\toksE) /Dest - [ @thispage /FitH @ypos ] >>}\fi - \ifon\startsection{\ttl#3.\ }\ignorespaces} % changed the font; AS + \ifacro{\toksF={}\makeoutlinetoks#3\outlinedone\outlinedone}\fi + \gdepth=#1\gtitle={#3}\MN{#2}% + \ifon\ifnum#1<\secpagedepth \vfil\eject % force page break if depth is small + \else\vfil\penalty-100\vfilneg\vskip\intersecskip\fi\fi + \message{*\secno} % progress report + \def\stripprefix##1>{}\def\gtitletoks{#3}% + \edef\gtitletoks{\expandafter\stripprefix\meaning\gtitletoks}% + \edef\next{\write\cont{%\noexpand\noexpand\noexpand\eatone{\noexpand\meaning\noexpand\ZZ}% + \noexpand\noexpand\noexpand % AS this is a (sort of) bug in cwebmac.tex + % as long as the index is output (i.e. ...\eject) + % before all the sections this is unnecessary + % uncomment the line after the brace to see what \ZZ + % expands to in case of weird errors + \ZZ{\gtitletoks}{#1}{\secno}% write to contents file + {\noexpand\the\pageno}{\the\toksE}}}\next % \ZZ{title}{depth}{sec}{page}{ss} + \ifpdftex\expandafter\xdef\csname curr#1\endcsname{\secno}% + \ifnum#1>0\countB=#1 \advance\countB by-1 + \advancenumber{chunk\the\countB.\expnumber{curr\the\countB}}\fi\fi + \ifpdf\special{pdf: outline #1 << /Title (\the\toksE) /Dest + [ @thispage /FitH @ypos ] >>}\fi + \ifon\startsection{\ttl#3.\ }\ignorespaces} % changed the font; AS \let\oldN\N \outer\def\textN#1#2#3.{% beginning of starred section in `text' mode - \ifacro{\toksF={}\makeoutlinetoks#3\outlinedone\outlinedone}\fi - \gdepth=#1\gtitle={#3}\MN{#2}% - \ifon - \ifnum#1<2 - \vfil\eject % force page break for chapters - \else - \vskip0pt plus 3.5\baselineskip\penalty-100\vskip0pt plus -3.5\baselineskip\vskip\intersecskip % no page break - \fi - \fi - \message{*\secno} % progress report - \def\stripprefix##1>{}\def\gtitletoks{#3}% - \edef\gtitletoks{\expandafter\stripprefix\meaning\gtitletoks}% - \edef\next{\write\cont{%\noexpand\noexpand\noexpand\eatone{\noexpand\meaning\noexpand\ZZ}% - \noexpand\noexpand\noexpand % AS this is a (sort of) bug in cwebmac.tex - % as long as the index is output (i.e. ...\eject) - % before all the sections this is unnecessary - % uncomment the line after the brace to see what \ZZ - % expands to in case of weird errors - \ZZ{\gtitletoks}{#1}{\secno}% write to contents file - {\noexpand\the\pageno}{\the\toksE}}}\next % \ZZ{title}{depth}{sec}{page}{ss} - \ifpdftex\expandafter\xdef\csname curr#1\endcsname{\secno}% - \ifnum#1>0\countB=#1 \advance\countB by-1 - \advancenumber{chunk\the\countB.\expnumber{curr\the\countB}}\fi\fi - \ifpdf\special{pdf: outline #1 << /Title (\the\toksE) /Dest - [ @thispage /FitH @ypos ] >>}\fi - \ifon\startsection{\ttl#3}\smallskip\noindent\ignorespaces} + \ifacro{\toksF={}\makeoutlinetoks#3\outlinedone\outlinedone}\fi + \gdepth=#1\gtitle={#3}\MN{#2}% + \ifon + \ifnum#1<2 + \vfil\eject % force page break for chapters + \else + \vskip0pt plus 3.5\baselineskip\penalty-100\vskip0pt plus -3.5\baselineskip\vskip\intersecskip % no page break + \fi + \fi + \message{*\secno} % progress report + \def\stripprefix##1>{}\def\gtitletoks{#3}% + \edef\gtitletoks{\expandafter\stripprefix\meaning\gtitletoks}% + \edef\next{\write\cont{%\noexpand\noexpand\noexpand\eatone{\noexpand\meaning\noexpand\ZZ}% + \noexpand\noexpand\noexpand % AS this is a (sort of) bug in cwebmac.tex + % as long as the index is output (i.e. ...\eject) + % before all the sections this is unnecessary + % uncomment the line after the brace to see what \ZZ + % expands to in case of weird errors + \ZZ{\gtitletoks}{#1}{\secno}% write to contents file + {\noexpand\the\pageno}{\the\toksE}}}\next % \ZZ{title}{depth}{sec}{page}{ss} + \ifpdftex\expandafter\xdef\csname curr#1\endcsname{\secno}% + \ifnum#1>0\countB=#1 \advance\countB by-1 + \advancenumber{chunk\the\countB.\expnumber{curr\the\countB}}\fi\fi + \ifpdf\special{pdf: outline #1 << /Title (\the\toksE) /Dest + [ @thispage /FitH @ypos ] >>}\fi + \ifon\startsection{\ttl#3}\smallskip\noindent\ignorespaces} + +\outer\def\chapterN#1#2#3.{% beginning of starred section in `book' mode + \ifacro{\toksF={}\makeoutlinetoks#3\outlinedone\outlinedone}\fi + \gdepth=#1\gtitle={#3}\MN{#2}% + \ifon + \ifnum#1<\tw@ + \vfil\eject % force page break for chapters and major subsections + \ifodd\pageno + \else + \null\vfill\eject + \fi + \else + \vskip0pt plus 3.5\baselineskip + \penalty-100 + \vskip0pt plus -3.5\baselineskip + \vskip\intersecskip % no forced page break + \fi + \fi + \message{*\secno} % progress report + \def\stripprefix##1>{}\def\gtitletoks{#3}% + \edef\gtitletoks{\expandafter\stripprefix\meaning\gtitletoks}% + \edef\next{\write\cont{%\noexpand\noexpand\noexpand\eatone{\noexpand\meaning\noexpand\ZZ}% + \noexpand\noexpand\noexpand % AS this is a (sort of) bug in cwebmac.tex + % as long as the index is output (i.e. ...\eject) + % before all the sections this is unnecessary + % uncomment the line after the brace to see what \ZZ + % expands to in case of weird errors + \ZZ{\gtitletoks}{#1}{\secno}% write to contents file + {\noexpand\the\pageno}{\the\toksE}}}\next % \ZZ{title}{depth}{sec}{page}{ss} + \ifpdftex\expandafter\xdef\csname curr#1\endcsname{\secno}% + \ifnum#1>0\countB=#1 \advance\countB by-1 + \advancenumber{chunk\the\countB.\expnumber{curr\the\countB}}\fi\fi + \ifpdf\special{pdf: outline #1 << /Title (\the\toksE) /Dest + [ @thispage /FitH @ypos ] >>}\fi + \ifon\stsecchap{#1}{#3}\ignorespaces +} + +\def\stsecchap#1#2{\rightskip=0pt % get out of C mode (cf. \B) + \sfcode`;=1500 \pretolerance 200 \hyphenpenalty 50 \exhyphenpenalty 50 +% + \ifnum#1>0 + \noindent{\let\*=\lapstar\llap{\tentitle\secstar\quad}}{\ttl #2}\smallskip\noindent% push it to the margins + \else + \null % sloppy but this works for the narrow case of this example + \global\chapterheadtrue + \vskip1.5in + \vbox{\tabskip=0pt plus 1 fil + \halign to\hsize{% + \hfil##\tabskip=0pt\cr + \cmhuge\secstar\cr + \noalign{\vskip 1pc}% + \cmmiddle#2\cr + }% + }% + \bigskip + \noindent + \fi +% + \ifpdftex\smash{\raise\baselineskip\hbox to0pt{% + \let\*=\empty\ifmakepdf\pdfdest num \secstar fith\fi}}% this space is a bug in the original cwebmac.tex; AS + \else\ifpdf\smash{\raise\baselineskip\hbox to0pt{% + \let\*=\empty\special{% + pdf: dest (\romannumeral\secstar) [ @thispage /FitH @ypos ]}}}\fi\fi} \outer\def\textM#1{\MN{#1}\ifon\vskip0pt plus 3\baselineskip\penalty-100\vskip0pt plus -3\baselineskip % no page break - \vskip\intersecskip\startsection\ignorespaces} + \vskip\intersecskip\startsection\ignorespaces} \def\MN#1{\par % common code for \M, \N - {\xdef\secstar{#1}\let\*=\empty\xdef\secno{#1}}% remove \* from section name - \ifx\secno\secstar \onmaybe \else\ontrue \fi - \mark{{\secno}{\the\gdepth}{\the\gtitle}}} % remove the annoying - % `paragraph' sign; AS + {\xdef\secstar{#1}\let\*=\empty\xdef\secno{#1}}% remove \* from section name + \ifx\secno\secstar \onmaybe \else\ontrue \fi + \mark{{\secno}{\the\gdepth}{\the\gtitle}}% remove the annoying `paragraph' sign; AS +} -% a new start section macro: fix the extra space bug and push the setion number to the margins +% a new start section macro: fix the extra space bug and push the section number to the margins \def\stseclap{\rightskip=0pt % get out of C mode (cf. \B) - \sfcode`;=1500 \pretolerance 200 \hyphenpenalty 50 \exhyphenpenalty 50 - \noindent{\let\*=\lapstar\llap{\tentitle\secstar\quad}}% push it to the margins - \ifpdftex\smash{\raise\baselineskip\hbox to0pt{% - \let\*=\empty\ifmakepdf\pdfdest num \secstar fith\fi}}% this space is a bug in the original cwebmac.tex; AS - \else\ifpdf\smash{\raise\baselineskip\hbox to0pt{% - \let\*=\empty\special{% - pdf: dest (\romannumeral\secstar) [ @thispage /FitH @ypos ]}}}\fi\fi} + \sfcode`;=1500 \pretolerance 200 \hyphenpenalty 50 \exhyphenpenalty 50 + \noindent{\let\*=\lapstar\llap{\tentitle\secstar\quad}}% push it to the margins + \ifpdftex\smash{\raise\baselineskip\hbox to0pt{% + \let\*=\empty\ifmakepdf\pdfdest num \secstar fith\fi}}% this space is a bug in the original cwebmac.tex; AS + \else\ifpdf\smash{\raise\baselineskip\hbox to0pt{% + \let\*=\empty\special{% + pdf: dest (\romannumeral\secstar) [ @thispage /FitH @ypos ]}}}\fi\fi} \let\startsection\stseclap +\newif\ifchapterhead + % make page and sectoin number hang in the margins; \quad is chosen to % be consistent with section appearance; the page numbers are printed % in old-style numerals; -\def\lheader{\headertrue\llap{\mainfont\oldstyle\the\pageno\tentitle\quad}\eightpoint\rm\grouptitle - \hfill\title\rlap{\tentitle\quad\tenpoint$^{\hbox{\sevenrm\topsecno}}_{\hbox{\sevenrm\botsecno}}$}} % top line on left-hand pages -\def\rheader{\headertrue -\llap{\tenpoint$^{\hbox{\sevenrm\topsecno}}_{\hbox{\sevenrm\botsecno}}$\tentitle\quad}% -\eightpoint\rm\title\hfill - \grouptitle\rlap{\tentitle\quad\mainfont\oldstyle\the\pageno}} % top line on right-hand pages +\def\lheader{% + \ifchapterhead + \hfil + \else + \termindexfalse\headertrue\llap{\mainfont\oldstyle\the\pageno\tentitle\quad}% + \eightpoint\rm\grouptitle\hfill\title + \rlap{\tentitle\quad\tenpoint$^{\hbox{\sevenrm\topsecno}}_{\hbox{\sevenrm\botsecno}}$}% + \fi +} % top line on left-hand pages + +\def\rheader{% + \ifchapterhead + \hfil + \else + \termindexfalse\headertrue\llap{\tenpoint$^{\hbox{\sevenrm\topsecno}}_{\hbox{\sevenrm\botsecno}}$\tentitle\quad}% + \eightpoint\rm\title\hfill\grouptitle + \rlap{\tentitle\quad\mainfont\oldstyle\the\pageno}% + \fi +} % top line on right-hand pages \def\botsecno{\expandafter\takeone\botmark} % the first section on the % next page -% from time to time, entries must be omitted from the index; -% the macros below implement a mechanism to do that - -\newif\ifisindexable - -\def\setindexable#1{% - \isindexabletrue - \def\next{#1}% - \expandafter\s@t@ndexable\unindexable.\end -} +\newwrite\exampletable -\def\s@t@ndexable#1#2\end{% - {% - \def\ifisindexable{#1}% - \ifx\ifisindexable\next - \yybreak{\aftergroup\isindexablefalse\aftergroup\eattoend}% - \else - \def\ifisindexable{#2}% - \ifx\ifisindexable\dotcontainer - \yybreak@{\aftergroup\eattoend}% - \else - \yybreak@{\aftergroup\s@t@ndexable}% - \fi - \yycontinue - }% - #2\end -} - -\def\inxmod{% - \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 - \message{Index:} - \medskip - \eightpoint\raggedright - \fnotesstart=2 - \fnotesspan=1 - \noofcolumns=3 - \icgap=5pt% - \linecount=3 - \setmcparams - \dsskip=0pt% - \adjskip=0pt plus 9pt% - \ifx\unindexable\UNDEFINED - \def\unindexable{{$\TeXx$}{$\TeXa$}{$\TeXb$}{$\TeXf$}{$\TeXao$}{$\TeXfo$}}% - \else - \expandafter\def\expandafter\unindexable\expandafter{\unindexable - {$\TeXx$}{$\TeXa$}{$\TeXb$}{$\TeXf$}{$\TeXao$}{$\TeXfo$}% - }% - \fi - \def\I##1, ##2.{% - {% - \setindexable{##1}% - \ifisindexable - \else - \aftergroup\eatone - \fi - }% - {% - \hangindent1em\noindent##1:\kern.5em - \ifacro\pdfnote##2.\else##2\fi.% - \par - }% - }% - % indexing macros for grammar terms - \def\termidstring##1{% processed name in italics - \numberstocharsandspaces##1\end - \let\optstrextra\optstrextraesc - \expandafter\nameproc\expandafter{\the\toksa}% - \def\idxentry{{\it\the\toksa}}% - }% - \def\termvstring##1{% processed name in typewriter style - \numberstocharsandspaces##1\end - \let\optstrextra\optstrextraesc - \expandafter\nameproc\expandafter{\the\toksa}% - \def\idxentry{{\tt\def\_{\char`\_}\the\toksa}}% - }% - \def\termttstring##1{% straightforward typewriter text - \numberstocharsandspaces##1\end - \def\idxentry{{\tt\the\toksa}}% - }% - \def\termostring##1{% options (e.g. \flex\ and \bison\) - \numberstocharsandspaces##1\end - \def\idxentry{{$\langle$\bf\the\toksa$\rangle$}}% - }% - \let\termhdrstring\termidstring - \def\termstring##1{% - \numberstocharsandspaces##1\end - \let\optstrextra\optstrextraesc - \expandafter\nameproc\expandafter{\the\toksa}% - \def\idxentry{{\tt"\the\toksa"}}% - }% - \def\texcsstring##1{% - \numberstocharsandspaces##1\end - \def\idxentry{% - \def\texnspace{index}% - \def\getcescape{% an \ seen is really an \, and will not go through C string processing - \def\next{escape}% - \action\next\in\currentstate - }% - \termindexfalse\expandafter\inlineTeXx\expandafter{\expandafter/\the\toksa}% - }% - }% - \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 - \expandafter\let\expandafter\acharswitch\csname acharswitch:index\endcsname - \def\texlexer{% 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 - \action\next\in\currentstate - }% - \def\indexseparator##1##2{% - \vskip.5\baselineskip - \centerline{\dinkus}% - \vskip.5\baselineskip - } - \def\GI##1##2##3##4.{% - {% - \def\hostparsernamespace{##1}% - \toksa{}##2{##3}% - \I{\idxentry}##4.% - }% - }% - % end indexing macros for grammar terms - \let\*=\lapstar - \def\[##1]{{\it##1}} % definitions - \def\(##1){$\underline{##1}$} % underlined index item - \def\(##1){{\bf ##1}} % 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$} % definitions in examples - \def\g##1g{{\bf ##1}$^\circ$} % an alternative to the above - \begindoublecols - \readindex - \otherlangindexseparator - \readgindex -} - -\def\otherlangindexseparator{% - \par - \vskip.5\baselineskip - \centerline{B{\sc ISON AND} \TeX\ {\sc INDEX}}% - \vskip.5\baselineskip - \par -} +\newif\ifsaveparseoutput +\newif\ifchecktable \def\finmod{% \enddoublecols \closeout\exampletable - \unsetfootnotes \parfillskip 0pt plus 1fil \def\grouptitle{NAMES OF THE SECTIONS} \let\topsecno=\nullsec @@ -1178,68 +967,122 @@ \centerline{\sc A LIST OF ALL SECTIONS} \penalty300 \medskip + \emergencystretch=10pt \readsections } -\newread\trygindex +% \Cee\ section macros -\def\readgindex{% - \openin\trygindex=\jobname.gdy - \ifeof\trygindex - \else - \closein\trygindex - \input \jobname.gdy - \fi -} +% stage one macros for `\B' sections: collecting tokens -% main section macro +% \B is always paired with \par (see CWEAVE section 213); unfortunately, this is +% where certainty ends; the output of \CWEAVE\ is woefully unstructured, to say the +% least; the ugly hack below appears to be the only way to typeset the \Cee\ sections +% in their own style (using the 9pt face as is the case below). \let\oldB\B -% stage one macros for `\B' sections: collecting tokens - -% \B is always paired with \par (see CWEAVE section 213) - \long\def\Bvbpp#1\par{% - \Bvbp@#1\X\X${}\E{}$\par + \Bvbp@#1\X\X$\E$\par +} + +\long\def\Bvbpp#1\par{% the \vb{\yyendgame}\vb... is inserted by brack.pl + \Bvbp@#1\cleanBtail\X\X$\E$\par } -\long\def\Bvbp@#1\X#2\X$#3\E#4$#5\par{% +\def\cleanBtail\X\X$\E${} + +\long\def\Bvbp@#1\X#2\X$#3\E#4$#5\par{% new version of the above, experimental \yystringempty{#5}% - {% - \Bvb@@#1\X#2\X$#3\E#4$\par - }{% - \Bvb@@#1\X#2\X${#3}\E{#4}$\begingroup + {% this is a \Cee\ section (@c or @p); it is tempting to assume that the suffix + % is \X\X$\E$\par and forego the invocation of \Bvb@@, however, this is not always + % the case as the first \X may come from a different section in the middle. + \oldB#1\X#2\X$#3\E#4$\par + }{% the logic here is not perfect but if this is still a \Cee\ section, + % inserting @t@> between @> and whatever follows that produces $...\E...$ + % will correct the misidentification (the result of which may be, at best, + % part of the section being typeset in a wrong face, or, worse \begingroup + % starting a group in a wrong place (such as in the middle of the math mode)) + \oldB#1\X#2\X${#3}\E{#4}$\begingroup % the braces around #3 and #4 are necessary + % to ensure proper spacing around \E in case + % #3 and #4 are empty \ninepoint + \Binputtoks{#5}\Btoksmathfalse #5\par\endgroup }% } -\long\def\Bvb@@#1\X\X$#2\E#3$\par{% - \oldB#1\par +\newtoks\Binputtoks + +\newif\ifBtoksmath % does the section start in math mode? + +\let\yyendgame\empty + +\let\postparse\empty % the `upper half' \preparse... macros will use the contents of \Binputtoks + +\newif\ifyyskipparse + +\let\B\Bvbpp + +% parser stack setup + +\def\fillpstack#1#2{% + \expandafter\def\csname currentparser[#1]\endcsname{#2}% } -\def\begingsec#1#2\endgsec{% - \ifmmode - \yybreak{{}${}\vbpp{}$#2\vb\endgsec{#1}{$#2}}%$ +\def\poppstack#1{% + \expandafter\ifx\csname currentparser[#1]\endcsname\relax + \yybreak{% unknown language, skip the section + \preparsetrivial + } \else - \yybreak{\vbpp{}#2\vb\endgsec{#1}{#2}}% + \yybreak{% + \expandafter\expandafter\expandafter + \p@ppstack\csname currentparser[#1]\endcsname\end{#1}% + }% \yycontinue } -\long\def\vbpp#1#2\vb#3#{% verbatim section preprocessor - \yystringempty{#3}{% - \vbp@{#1\stashed{#2}}% +\def\p@ppstack#1#2\end#3{% + \yystringempty{#2}{% + \fillpstack{#3}\relax#1% }{% - #3{#1\stashed{#2}}% + \fillpstack{#3}{#2}#1% }% } -\long\def\vbp@#1#2{% - \vbpp{#1#2}% +% section macros + +\def\lsectionbegin#1{% + \ifmmode + \yybreak{% + {}$% exit the group inside the math mode + \Btoksmathtrue + \poppstack{#1}\vb{}$% + }% finish the math mode and reinsert it as stash + \else + \yybreak{% + \poppstack{#1}% + }% + \yycontinue } -\let\B\Bvbpp +\def\skiptolsection#1\lsectionbegin#2{% + \ifBtoksmath + \yybreak{% + \lsectionbegin{#2}\vb{}${}% + }% + \else + \yybreak{% + \lsectionbegin{#2}% + }% + \yycontinue +} + +\def\removefinalvb#1\endparse{} + +\def\preparsetrivial#1\postparse{} % in case the section contains some dangerous + % terms like \insertraw{...} that must be skipped % URL typesetting @@ -1260,15 +1103,29 @@ % commonly used names -\def\CWEB{\.{CWEB}}\def\CTANGLE{\.{CTANGLE}}\def\CWEAVE{\.{CWEAVE}} +\def\CWEB{\.{CWEB}} +\def\CTANGLE{\.{CTANGLE}} +\def\CWEAVE{\.{CWEAVE}} +\def\WEB{\.{WEB}} +\def\Pascal{P{\sc ASCAL}} +\def\noweb{\.{noweb}} \def\splint{\.{SPLinT}} \def\POSIX{{\sc POSIX}} +\def\EAST{{\sc EAST}} +\def\WEST{{\sc WEST}} \def\ISO{{\mc ISO}} -\def\bison{\.{bison}} -\def\flex{\.{flex}} +\def\bison{\ifheader B{\sc ISON}\else\.{bison}\fi} +\def\flex{\ifheader F{\sc LEX}\else\.{flex}\fi} \def\lex{\.{lex}} +\def\yacc{\.{yacc}} \def\gcc{\.{gcc}} +\def\ld{\ifheader LD\else\.{ld}\fi} \def\GNU{{\sc GNU}} +\def\CEEPP/{{\mc C{\tt ++}\spacefactor1000}} +\def\Ceepp{\CEEPP/} +\def\mft{\.{mft}} +\def\MF{{\tt META}\-{\tt FONT}\spacefactor1000 } +\def\MP{{\tt META}\-{\tt POST}\spacefactor1000 } % from tugboat.cmn \newbox\TestBox \def\La{\tempca=\the\fam \leavevmode L% @@ -1289,84 +1146,31 @@ }% } -% debugging - -\def\shownethe#1{% - \edef\next{\the#1}% - \ifx\next\empty - \else - \showthe#1% - \fi -} - -\def\showem#1#2#3{\toksa{#1}\toksb{#2}\toksc{#3}{\newlinechar=`^^J% - \errmessage{% - arg. 1: \the\toksa^^J% - arg. 2: \the\toksb^^J% - arg. 3: \the\toksc% -}}} - % sugar \def\FOREVER{{\bf forever}} -% delay functions prettyprinting and other miscellanea; - -\def\delayhalfsec{\hbox{wait \kern-.5pt\raise1pt\hbox{$\scriptstyle1$}% -\kern-1pt/\kern-1pt\lower1pt\hbox{$\scriptstyle2$} sec, }} -\def\delayquartersec{\hbox{wait \kern-.5pt\raise1pt\hbox{$\scriptstyle1$}% -\kern-1pt/\kern-1pt\lower1pt\hbox{$\scriptstyle4$} sec, }} - -\def\delay#1sec{% -\hbox{\def\secmult{}wait -\getsecmult#1\end -\if\secmult u\def\secmodifier{ $\mu$\kern.05pt }\else -\if\secmult m\def\secmodifier{ m}\else -\if\secmult n\def\secmodifier{ n}\else - \secmult\def\secmodifier{ }% -\fi\fi\fi -\secmodifier sec$\rm\scriptstyle s$, } -} - -\def\getsecmult#1{% -\ifx#1\end\let\next\relax\else - \secmult\def\secmult{#1}\let\next\getsecmult -\fi\next -} - -% attribute prettyprinting; - -\long\def\parseattrib#1#2\end{\csname attrib#1\endcsname} - -\def\xxattributexx#1{\ifx(#1\let\next\xxattributex\else\let\next\xxattribute\fi\next#1} -\def\xxattributex((\\#1{% - \expandafter\let\expandafter\currentattrib\csname attrib#1\endcsname - \ifx\currentattrib\attribpacked - \strut\colorblack{% - \lower2pt\hbox{\vrule width \wd\thezero height - \ht\thezero depth - \dp\thezero}}\llap{\colorwhite{\hbox{$\scriptscriptstyle\bf 01\kern.5pt$}}}% - \let\next\eatparentheses - \fi - \ifx\currentattrib\attribnoinline - {\ \bf noinline\rm_a}% - \let\next\eatparentheses - \fi - \ifx\currentattrib\attribformat - {\ \bf format\rm_a}% - \let\next\eatarguments - \fi - \next -} - -\def\eatparentheses#1)){} -\def\eatarguments(\\#1,#2,#3))){(\hbox{\rm as }\.{#1})} - -\def\xxattribute#1{\.{\_\_attribute\_\_} (\sc GNU) #1} - -\let\attribnoinline=1 -\let\attribpacked=2 -\let\attribformat=3 +\ifacro + \ifpdftex + \input extras/texmf/macros/protcode.tex + \pdfprotrudechars=2 + \setprotcode\tenrm + \setprotcode\ninerm + \setprotcode\eightrm + \setprotcode\sevenrm + \setprotcode\sixrm + \setprotcode\tenit + \setprotcode\nineit + \setprotcode\eightit + \setprotcode\sevenit + \setprotcode\sixit + % do not stretch characters + %\pdfdjustspacing=2 + %\pdffontexpand\sevenrm 30 20 10 autoexpand + % TODO: use \pdfsavepos, \pdflastxpos, and \pdflastypos to + % save the position of index terms on the page + \fi +\fi \tenpoint -%\registerlegend{{8}{\noexpand\phantom{B}}} + diff --git a/support/splint/tex/noweb.sty b/support/splint/tex/noweb.sty new file mode 100644 index 0000000000..a0f2c7cf43 --- /dev/null +++ b/support/splint/tex/noweb.sty @@ -0,0 +1,399 @@ +% Copyright 2012-2020, Alexander Shibakov +% This file is part of SPLinT +% +% SPLinT is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% SPLinT is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with SPLinT. If not, see <http://www.gnu.org/licenses/>. + +\def\stseclap{\rightskip=0pt % get out of C mode (cf. \B) + \sfcode`;=1500 \pretolerance 200 \hyphenpenalty 50 \exhyphenpenalty 50 + \noindent{\let\*=\empty\llap{\tentitle\setsafesecno{\secno}\quad}}% push it to the margins + \putxref{\MNM}{}{}.% generate a location reference for noweb cross referencing style + \ifpdftex\smash{\raise\baselineskip\hbox to0pt{% + \let\*=\empty\ifmakepdf\pdfdest num \secstar fith\fi}}% this space is a bug in the original cwebmac.tex; AS + \else + \ifpdf + \smash{\raise\baselineskip + \hbox to0pt{% + \let\*=\empty\special{% + pdf: dest (\romannumeral\secstar) [ @thispage /FitH @ypos ]% + }% + }% + }% + \fi + \fi +} + +\def\stsecchap#1#2{\rightskip=0pt % get out of C mode (cf. \B) + \sfcode`;=1500 \pretolerance 200 \hyphenpenalty 50 \exhyphenpenalty 50 +% + \ifnum#1>\z@ % the `level' if this section is below that of a chapter + \noindent{\let\*=\empty\llap{\tentitle + \setsafesecno{\secno}\quad}}{\ttl #2}% push it to the margins + \putxref{\MNM}{}{}.% generate a location reference for noweb cross referencing style + \smallskip\noindent + \else + \setchaptertitle{\secno}{#2}% + \putxref{\MNM}{0}{}.% generate a chapter location reference for noweb cross referencing style + \fi +% + \ifpdftex\smash{\raise\baselineskip\hbox to0pt{% + \let\*=\empty\ifmakepdf\pdfdest num \secstar fith\fi}}% this space is a bug in the original cwebmac.tex; AS + \else\ifpdf\smash{\raise\baselineskip\hbox to0pt{% + \let\*=\empty\special{% + pdf: dest (\romannumeral\secstar) [ @thispage /FitH @ypos ]}}}\fi\fi} + +\def\setchaptertitle#1#2{% + \global\chapterheadtrue + \null + {\ninepoint\tempda=\baselineskip + \multiply\tempda by 17 + \vskip\tempda plus\baselineskip minus 2pt + }% + \vbox to 0pt{% + \vss + \tabskip=0pt plus 1 fil + \halign to\hsize{% + \hfil##\tabskip=0pt\cr + \hugetitle\setsafechapno{#1}\cr + \noalign{\vskip 1pc}% + \midtitle#2\cr + }% + }% + \prevdepth=0pt + \bigskip + \noindent{\let\*=\empty\llap{\tentitle\setsafesecno{\secno}\quad}}% +} + +\let\startsection\stseclap + +\expandafter\def\expandafter\oldB\expandafter{\oldB\global\csectionstarttrue\putxref{\BBB}{}{}.} + +\def\putxref#1#2.{% it is important that #2 contains at least two braced groups (as in {}{}) + % otherwise the parameter scanning mechanism will strip the outside braces + \ifxreflocal + {\edef\next{\write\xrefstream{\nx\nx\nx#1{\nx\the\nx\pageno}{\secno}#2\harmlesscomment}}\next}% + \fi +} + +\def\X#1:#2\X{\ifmmode\gdef\XX{\null$\null}\else\gdef\XX{}\fi %$% section name + \XX$\langle\,${\let\I=\ne#2\eightrm\kern.5em + \ifacro{\pdfnote#1.}\else#1\fi}$\,\rangle$\putpathindex{\secno}{#1}\XX\putxrefx{#1}{#2}} + +\def\putxrefx#1#2{% + \ifxreflocal + {\def\sname{#2}% + \def\stripprefix##1>{ }% + \let\*\empty + \edef\next{\write\xrefstream{\nx\nx\nx\XXX{\nx\the\nx\pageno}{\secno}{#1}\harmlesscomment + \expandafter\stripprefix\meaning\sname}}\next}% + \fi +} + +\newif\ifcsectionstart % does this section name appear at the beginning of a \Cee\ section? + +\def\putpathindex#1#2{% + \ifcsectionstart + \global\csectionstartfalse\strut + \vadjust{% + \setbox0=\hbox{\strut}% + \kern-\dp0 + \vbox to 0pt{ + \vss + \hbox to\pagewidth{% + \hfil\rlap{% + \let\*\empty + \kern1em \setpathlinks{#1}{#2}% + }% + }% + }% + \setbox0=\hbox{\strut}% + \kern\dp0 + }% + \fi +} + +\def\setpathlinks#1#2{% + \expandafter\ifx\csname xchain[#1][#2]down\endcsname\relax + \expandafter\ifx\csname xchain[#1][#2]up\endcsname\relax + \else + \setuplink{#1}{#2}{\hfil##\hfil}% + \fi + \else + \expandafter\ifx\csname xchain[#1][#2]up\endcsname\relax + \setdownlink{#1}{#2}{\hfil##\hfil}% + \else + \setuplink{#1}{#2}{##\hfil} + \setdownlink{#1}{#2}{\hfil##}% + \fi + \fi +} + +\def\setdownlink#1#2#3{% + {\setbox0\vtop{ + \sevenpoint\halign{#3\cr + \xref@nowebsection{\csname xchain[#1][#2]down\endcsname}\cr + \relax\ifacro + \pdflink{\csname xchain[#1][#2]down\endcsname}{\raise3.5pt\hbox{$\scriptscriptstyle\bigtriangledown$}}% + \else + \raise3.5pt\hbox{$\scriptscriptstyle\bigtriangledown$}% + \fi + \cr + } + }% + \dp0=0pt \box0}% +} + +\def\setuplink#1#2#3{% + {\setbox0\vbox{ + \sevenpoint\halign{#3\cr + \relax\ifacro + \pdflink{\csname xchain[#1][#2]up\endcsname}{\lower1.3pt\hbox{$\scriptscriptstyle\bigtriangleup$}}% + \else + \lower1.3pt\hbox{$\scriptscriptstyle\bigtriangleup$}% + \fi + \cr + \xref@nowebsection{\csname xchain[#1][#2]up\endcsname}\cr + } + }% + \box0}% +} + +\def\makenote{% + \addtokens\toksB{\noexpand\pdflink{\the\toksC}{\setsafesecno{\the\toksC}}}% + \toksC={}\global\countC=0 +} + +% redefine \pdflink; N.B.: the semantics of this command sequence have changed, since now +% #2 is not ignored (as it would have been if using pdftex); instead it becomes a typesetting +% template for the link + +\ifpdftex + \ifx\pdfannotlink\undefined\let\pdfannotlink\pdfstartlink\fi% for pdfTeX 0.14 + \def\pdflink#1#2{\hbox{\pdfannotlink height\ht\strutbox depth\dp\strutbox + attr{/Border [0 0 0]} goto num #1 \BlueGreen #2\Black\pdfendlink}} +\else\def\pdflink#1#2{\setbox0=\hbox{\special{pdf: bc [ \pdflinkcolor ]}{#2}% + \special{pdf: ec}}\special{pdf: ann width \thewidth height \theheight + depth \thedepth << /Type /Annot /Subtype /Link + /Border [0 0 0] /A << /S /GoTo /D (\romannumeral#1) >> >>}\box0\relax}\fi + +% while typesetting the table of contents, show the actual section numbers +% TODO: introduce section accounting for book style typesetting. + +\def\contentsline#1#2#3#4#5{\ifnum#2=0 \smallbreak\fi + \line{\consetup{#2}#1 + \rm\leaders\hbox to .5em{.\hfil}\hfil + \ \ifacro\pdflink{#3}{#3}\else#3\fi\hbox to3em{\hss#4}}} + +\newif\ifxreflocal % are we generating references in noweb style (as page no., position pairs)? + +\newread\trystream % generic stream to test for an existence of a file + +\def\readlxrefs{% see if the local reference file exists + \openin\trystream=\jobname.xxr + \ifeof\trystream + \else + \closein\trystream + \input \jobname.xxr + \fi +} + +\newif\ifcsecactive + +\def\BBB#1#2#3#4{% #1 is the page number + % #2 is the section number + \csecactivetrue +} + +\def\lxrcurrentpage{-1} + +\newcount\lxrcurrentindex +\newcount\chaptercount + +\lxrcurrentindex=\z@ + +\def\MNM#1#2#3#4{% #1 is the page number + % #2 is the section number + % #3 is the chapter flag or empty + % #4 is reserved + \ifnum#1=\lxrcurrentpage + \else + \lxrcurrentindex=\z@ + \def\lxrcurrentpage{#1}% + \fi + {% + \tomodalpha\lxrcurrentindex\next + \def\nnext{\expandafter\noexpand\csname lxref[#2]\endcsname}% + \yystringempty{#3}{% + \let\nnnext\empty + }{% + \global\advance\chaptercount\@ne + \def\nnnext{\the\chaptercount}% + }% + \edef\next{\def\nnext{{#1}{\next}{\nnnext}}}% + \expandafter + }\next + \advance\lxrcurrentindex\@ne +} + +\def\xref@nowebsection#1{% translate the \CWEB\ section number into a \noweb\ reference + \expandafter\xr@f@nowebsection\romannumeral-1\csname lxref[#1]\endcsname.% +} + +\def\xr@f@nowebsection#1#2#3.{% + {#1}{#2}% +} + +\def\xref@chapter#1{% translate the \CWEB\ section number into a chapter number + \expandafter\xr@f@chapter\romannumeral-1\csname lxref[#1]\endcsname.% +} + +\def\xr@f@chapter#1#2#3#4.{% + \yystringempty{#3}{{000}}{% + {#3}% + }% +} + +\def\setsafesecno#1{% + \expandafter\ifx\csname lxref[#1]\endcsname\relax + #1% + \else + \xref@nowebsection{#1}% + \fi +} + +\def\setsafechapno#1{% + \expandafter\ifx\csname lxref[#1]\endcsname\relax + #1% + \else + \xref@chapter{#1}% + \fi +} + +\def\tomodalpha#1#2{% + \tempca=#1 + \let#2\empty + \bloop + \tempcb=\tempca + \divide\tempca by 26 + \tempcc=\tempca + \multiply\tempcc by 26 + \advance\tempcb by -\tempcc + \advance\tempcb by `\a + \uccode`\.=\tempcb + \uppercase{\edef#2{.#2}}% + \advance\tempca\m@ne + \ifnum\tempca<\z@ + \else + \repeat +} + +\def\XXX#1#2#3{% + \ifcsecactive % previous command was \BBB (produced by the \B macro) +% \expandafter\def\csname lxref[][]\endcsname{}% + \csecactivefalse + \fi +} + +\def\SSS{\let\XXX\xxxchain} % reference separator + +\def\lxrefseparator{% + \write\xrefstream{\nx\SSS}% +} + +\def\xxxchain#1#2#3{% + \xxxch@in{}{}#3, .% +} + +\newif\iftracenowebchains + +\def\xxxch@in#1#2#3, #4.{% #1 is the chain head + % #2 is the chain previous + % #3 is the chain next + % #4 is the remaining chain + \yystringempty{#1}{% start the chain + \yystringempty{#3}{% + \errmessage{The reference chain (#3) is malformed.}% + }{% + \xxxch@in{#3}{}#4, .% + }% + }{% + \yystringempty{#2}{% potentially the second link + \yystringempty{#3}{% this is a one link chain + }{% this is a second link + \expandafter\def\csname xchain[#1][#1]down\endcsname{#3}% + \expandafter\def\csname xchain[#3][#1]up\endcsname{#1}% + \iftracenowebchains\message{s(#1.->#3 #3->#1.)}\fi + \xxxch@in{#1}{#3}#4, .% + }% + }{% this is the middle or the end of the chain + \yystringempty{#3}{% this is the end of the chain + }{% + \expandafter\def\csname xchain[#3][#1]up\endcsname{#2}% + \expandafter\def\csname xchain[#2][#1]down\endcsname{#3}% + \iftracenowebchains\message{m(#1)(#2->#3 #3->#2)}\fi + \xxxch@in{#1}{#3}#4, .% + }% + }% + }% +} + +% replace the default reference setting macros in gindex.sty; +% typeset references so that, for example, \(77){8, 9} becomes +% \(\pdflink{77}{8c}), \(\pdfpagelink{9}) provided section 77 +% is section 8c by noweb's reckoning. + +\def\consumeonexref#1#2{% #1 is the accumulated references + % #2 is the section number + \expandafter\ifx\csname lxref[#2]\endcsname\relax + \errmessage{Section #2 does not have a local index.}% + \else + \yybreak{\expandafter\c@nsumeonexref\romannumeral-1\xref@nowebsection{#2}{#2}{#1}}% + \yycontinue +} + +\def\c@nsumeonexref#1#2#3#4#5{% #1 is the page number of the beginning of the section + % #2 is the (\noweb) section number (within the page) where the term appears + % #3 is the (\CWEB) section number there the term appears + % #4 is the accumulated references + % #5 is a list of pages where this term appears + \c@nsume@nexref{#1}{#2}{#3}{#4}{}#5, \end +} + +\def\c@nsume@nexref#1#2#3#4#5#6, {% #1 is the page number of the beginning of the section + % #2 is the (\noweb) section number (within the page) where the term appears + % #3 is the (\CWEB) section number where the term appears + % #4 is a total list of processed references + % #5 is a local list of processed references + % #6 is a page number from the list + \ifnum#1=#6 % the term appears on the same page where the section begins + \yybreak{\c@nsume@nexr@f{#1}{#2}{#3}#4{#5}{\compoundlink{#3}{#1#2}}}% + \else + \yybreak{\c@nsume@nexr@f{#1}{#2}{#3}#4{#5}{\pagelink{#6}}}% + \yycontinue +} + +\def\c@nsume@nexr@f#1#2#3#4#5#6#7#8{% + \c@nsume@n@xr@f{#1}{#2}{#3}{{#4}{#5}{#6}}{#7, #5#8#4}% +} + +\def\c@nsume@n@xr@f#1#2#3#4#5#6\end{% no more page numbers + \yystringempty{#6}{% + \attachlocallist{#1}{#2}{#3}#4{#5}% + }{% + \c@nsume@nexref{#1}{#2}{#3}{#4}{#5}#6\end + }% +} + +\def\attachlocallist#1#2#3#4#5#6#7{% + \grabfinexrefs{#6#7}% +} diff --git a/support/splint/tex/stokenset.sty b/support/splint/tex/stokenset.sty index 7146fcf0c1..9382415f6c 100644 --- a/support/splint/tex/stokenset.sty +++ b/support/splint/tex/stokenset.sty @@ -1,4 +1,4 @@ -% Copyright 2012-2014, Alexander Shibakov +% Copyright 2012-2020, Alexander Shibakov % This file is part of SPLinT % % SPLinT is free software: you can redistribute it and/or modify @@ -14,10 +14,19 @@ % You should have received a copy of the GNU General Public License % along with SPLinT. If not, see <http://www.gnu.org/licenses/>. -\prettywordpair{OPTIONAL}{{\tt opt}}% -\prettywordpair{NO_ATTR}{{\tt na}}% -\prettywordpair{EXTENDED}{{\tt ext}}% -\prettywordpair{INTEGER}{{$[\,0\ldots9\,]\ast$}}% -\prettywordpair{IDENTIFIER}{{$[\,\hbox{\tt a}\ldots\hbox{\tt Z}\,0\ldots9\,]\ast$}}% -\prettywordpair{WILDCARD}{{{\tt *} {\rm or} {\tt ?}}}% -\prettywordpair{PERCENT_IDENTIFIER}{{\tt\%$[\,\hbox{\tt a}\ldots\hbox{\tt Z}\,0\ldots9\,]\ast$}}% +% token typesetting for the name parser; we forego setting up +% automatic token typesetting (see xxexpression example for how +% this can be done) since the token set is rather small + +\prettywordpairwvis{OPTIONAL}{{\tt opt}}{opt}% +\prettywordpairwvis{NO_ATTR}{{\tt na}}{na}% +\prettywordpairwvis{EXTENDED}{{\tt ext}}{ext}% +\prettywordpair{LT}{{\tt l}}% +\prettywordpair{RT}{{\tt r}}% +\prettywordpairwvis{$\ undefined}{{\tt\$undefined}}{$undefined} +\prettywordpairwvis{INTEGER}{{$[\,0\ldots9\,]\ast$}}{[0...9]}% +\prettywordpairwvis{IDENTIFIER}{{$[\,\hbox{\tt a}\ldots\hbox{\tt Z}\,0\ldots9\,]\ast$}}{[a...Z0...9]*}% +\prettywordpair{META_IDENTIFIER}{{\cyr\lqq{\rm meta identifier}\rqq}}% +\prettywordpairwvis{WILDCARD}{{{\tt *} {\rm or} {\tt ?}}}{* or ?}% +\prettywordpairwvis{C_ESCCHAR}{\hbox{{\sixpoint\.{\\}}$c$}}{\benignescape c}% +\prettywordpairwvis{PERCENT_IDENTIFIER}{{\tt\%$[\,\hbox{\tt a}\ldots\hbox{\tt Z}\,0\ldots9\,]\ast$}}{\%[a...Z0...9]*}% diff --git a/support/splint/tex/trt1.sty b/support/splint/tex/trt1.sty index e3e722c91f..7783e15767 100644 --- a/support/splint/tex/trt1.sty +++ b/support/splint/tex/trt1.sty @@ -1,4 +1,4 @@ -% Copyright 2014, Alexander Shibakov +% Copyright 2014-2020, Alexander Shibakov % This file is part of SPLinT % % SPLinT is free software: you can redistribute it and/or modify @@ -33,5 +33,7 @@ \newtoks\toksd \newtoks\tokse \newtoks\toksf +\newtoks\toksg +\newtoks\toksh \expandafter\def\csname loadtexruntime1\endcsname{\endinput} diff --git a/support/splint/tex/xarithm.sty b/support/splint/tex/xarithm.sty index 4d424a863c..d971092043 100644 --- a/support/splint/tex/xarithm.sty +++ b/support/splint/tex/xarithm.sty @@ -1,4 +1,4 @@ -% Copyright 2014, Alexander Shibakov +% Copyright 2014-2020, Alexander Shibakov % This file is part of SPLinT % % SPLinT is free software: you can redistribute it and/or modify diff --git a/support/splint/tex/yxunion.sty b/support/splint/tex/yxunion.sty index fb0d2460b3..4d03d83c78 100644 --- a/support/splint/tex/yxunion.sty +++ b/support/splint/tex/yxunion.sty @@ -1,4 +1,4 @@ -% Copyright 2012-2015, Alexander Shibakov +% Copyright 2012-2020, Alexander Shibakov % This file is part of SPLinT % % SPLinT is free software: you can redistribute it and/or modify diff --git a/support/splint/tex/yy.sty b/support/splint/tex/yy.sty index 22a7948e9d..96769a0fc5 100644 --- a/support/splint/tex/yy.sty +++ b/support/splint/tex/yy.sty @@ -1,4 +1,4 @@ -% Copyright 2012-2014, Alexander Shibakov +% Copyright 2012-2020, Alexander Shibakov % This file is part of SPLinT % % SPLinT is free software: you can redistribute it and/or modify @@ -27,14 +27,12 @@ \newwrite\tokendefs \let\nx\noexpand -\def\drvname{bo} - \input yycommon.sty % general routines for stack and array access \input yymisc.sty % helper macros (stack manipulation, table processing, value stack pointers) + % parser intitialization, optimization \input yyinput.sty % input functions \input yyparse.sty % parser machinery \input flex.sty % lexer functions -\input yyboth.sty % parser intitialization, optimization \ifnum\optimization>\tw@ \input yyfaststack.sty @@ -43,17 +41,31 @@ \input yystype.sty % scanner auxilary types and functions \input yyunion.sty % parser data structures +% modify the input routine to recognize \yyendgame; the somewhat verbose end of +% the section is necessary to gracefully handle parser failures: the \endparse +% control sequence must appear outside of any \vb block for \cleanupparse +% to do its job; the \yyinput reads \vb blocks in pairs so the closing \vb{} is +% necessary and is removed by \removefinalvb (see limbo.sty and brack.pl for +% details). + +\expandafter\def\expandafter\multicharswitch\expandafter +{\multicharswitch\yyendgame{\yyinput\yyeof\yyeof\endparseinput\removefinalvb}} + \def\indexpseudonamespace{[index]} % the main parser \let\parsernamespace\empty +% the bootstrapping parser needs the name of the file where token equivalences will appear + \def\modebootstrap{% - \edef\tokendeffile{\drvname.tok}% + \edef\tokendeffile{\jobname.tok}% so that the name of the token file can track the name of the parser \edef\bstrapparser{byytab.tex}% sets \bootstrapmodetrue \def\bootstraplexersetup{\let\yylexreturn\yylexreturnbootstrap}% only return tokens whose value is known at bootstrap \input yybootstrap.sty% + \def\PB##1{} + \def\inlineTeXx##1{} } \def\modenormal{% @@ -67,10 +79,7 @@ % \csname ##1\parsernamespace\the##2\endcsname %}% \input yyinit.sty% + \input yytexlex.sty% } -\ifx\modeactive\UNDEFINED - \def\modeactive{\modenormal} -\fi - -\modeactive +\input yydebug.sty diff --git a/support/splint/tex/yybootstrap.sty b/support/splint/tex/yybootstrap.sty index 185ad3b0a6..97ddb1a666 100644 --- a/support/splint/tex/yybootstrap.sty +++ b/support/splint/tex/yybootstrap.sty @@ -1,4 +1,4 @@ -% Copyright 2012-2014, Alexander Shibakov +% Copyright 2012-2020, Alexander Shibakov % This file is part of SPLinT % % SPLinT is free software: you can redistribute it and/or modify @@ -21,23 +21,36 @@ \immediate\openout\tokendefs=\tokendeffile \fi \genericparser - name: main, + name: bootstrap, ptables: \bstrapparser, ltables: cweb/ltab.tex, tokens: {}, asetup: \bootstraplexersetup, - dsetup: \newlexerstateextra, - rsetup: \noexpand\savefullstateextra, + dsetup: \newlexerstateextra\newparserstateextra, + rsetup: {}, optimization: \optimizeall;% -\tomainparser % this saves the current state +\tobootstrapparser % this saves the current state -\input yytexlex.sty +% stage two macros: parsing +% note that the bootstrap parser has no way of telling if the \%token declarations +% belong to the current parser or not (for example, the \flex\ parser has its own +% declarations); it is thus important to make sure that the \%token declarations in +% the file visible to the parser belong to a single parser (so the file read by the +% bootstrap parser does not have declarations sections for a a parser other than +% \bison's. -\let\unparse\eatone +\def\preparsebootstrap{% + \let\postparse\postparsebootstrap + \tobootstrapparser % this is not currently required since there are no namespace switching macros + % in the \TeX\ portion of the text; it is left here in case such macros are used in the future + \basicparserinit + \bisonparserinit + \bisonparserdatainit + \yyparse +} -\expandafter\def\csname parserstack[b]\endcsname#1#2{% - \parsevb{#1}% Stage two, start the parsing +\def\postparsebootstrap{% \ifyyparsefail % do nothing if parsing failed \yybreak{}% \else % Stage three, process the parsed table @@ -45,26 +58,32 @@ \yycontinue } -\expandafter\def\csname parserstack[]\endcsname#1#2{% - \parsevb{#1}% Stage two, start the parsing - \ifyyparsefail % do nothing if parsing failed - \yybreak{}% - \else % Stage three, process the parsed table - \yybreak{\initbootstrap\the\table}% - \yycontinue +\fillpstack{b}{% + \preparsebootstrap + \relax } -% stage two macros: parsing +% sections with no parser tag are assumed to be bison sections -\def\parsevb#1{% - %\ifchecktable {\toks0{#1}\errmessage{table before parsing: \the\toks0}}\fi - \tomainparser % this is not currently required since there are no namespace switching macros - % in the \TeX\ portion of the text; it is left here in case such macros are used in the future - \doparse{#1}% +\fillpstack{}{% + \preparsebootstrap + \relax } -\long\def\beginprod#1\endprod{% - \endgroup -} +% ignore in text production examples (there is no way to parse them anyway) + +\long\def\beginprod#1\endprod{} \let\begincprod\beginprod + +\def\nameproc#1\with#2{% + #2{}{}{}{}{}% pretend the name is empty +} + +\def\frexproc#1\with#2{% + #2{}{}{}% pretend the regex is empty +} + +\def\prodstyle#1{} + +\input yydebug.sty diff --git a/support/splint/tex/yyboth.sty b/support/splint/tex/yyboth.sty deleted file mode 100644 index f15fe006c2..0000000000 --- a/support/splint/tex/yyboth.sty +++ /dev/null @@ -1,181 +0,0 @@ -% Copyright 2012-2014, Alexander Shibakov -% This file is part of SPLinT -% -% SPLinT is free software: you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation, either version 3 of the License, or -% (at your option) any later version. -% -% SPLinT is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with SPLinT. If not, see <http://www.gnu.org/licenses/>. - -% parser environment - -\newif\ifyyskipparse -\newif\ifsaveparseoutput -\newif\ifchecktable -\newif\ifchecktrim - -\newwrite\exampletable - -\def\basicparserinit{% - \yytext{}% - \yytextpure{}% - \yytextseenpure{}% - \yytextseen{}% - \yybyte{}% - \yyfbyte{}\yysbyte{}% - \yystash{}% - \yystashseen{}% - \yyformat{}% - \yyformatseen{}% - \yyfutureyytext{}% - \yyinitstack\yystatestack - \yyfmark=\z@ - \yysmark=\z@ - \yyfmarklast=\z@ - \formatmarker=\z@ - \yysmarklast=\z@ - \stashmarker=\z@ - \yytextbackupfalse - \yyg@yyinit=\z@ - \yyg@yystart=\z@ - \YYATBOL=\@ne - \yyparsefailfalse - \YYEOBLASTMATCHtrue -} - -\def\parserinit{% - \basicparserinit - \yyinitstack\obstackforstring - \yyinitstack\obstackforstringraw - \percentpercentcount=\z@ - \lonesting=\z@ - \laststring{}\laststringraw{}% - \currentlaststring{}\currentlaststringraw{}% - \parserdatainit -} - -\def\parserdatainit{% - % make control sequences inserted by the parser non expandable to facilitate - % token list manipulation; currently nothing is done -} - -% optimization options - -\def\optimizeall{% - % lexer - \ifnum\optimization>\z@ - \optimize{yynxt}% - \optimize{yyaccept}% - \optimize{yydef}% - \optimize{yychk}% - \optimize{yybase}% - \optimize{yyec}% - \optimize{yymeta}% - \tracingstats=\@ne - \fi - % parser - \ifnum\optimization>\@ne - \optimize{yytranslate}% - \optimize{yyrone}% - \optimize{yyrtwo}% - \optimize{yyrthree}% - \optimize{yydefact}% - \optimize{yydefgoto}% - \optimize{yypact}% - \optimize{yypgoto}% - \optimize{yytable}% - \optimize{yycheck}% - \optimize{yyprhs}% - \optimize{yyrhs}% - \optimize{yytoknum}% - \optimize{yystos}% - \optimizetext{yytname}% - \fi -} - -\long\def\endgsec#1#2#3{% - \ifyyskipparse - \yybreak{\unparse{#3}}% - \else - \yybreak{\csname parserstack[#2]\endcsname{#1}{#3}}% - \yycontinue -} - -\let\endcprod\endgroup -\let\endmprod\endgroup -\let\endprod\endgroup - -\def\genericparser name: #1, ptables: #2, ltables: #3, tokens: #4, asetup: #5, dsetup: #6, rsetup: #7, optimization: #8;{% - % parser initialization - % - \expandafter\def\csname #1namespace\endcsname{[#1]}% - \savecs{local-namespace}\parsernamespace - \expandafter\let\expandafter\parsernamespace\csname #1namespace\endcsname - \pinittoks{}% - \input #2 % load main parser table - \settokens % set the values of all tokens - \yystringempty{#4}{}{% - \input #4 % use token equivalence table to set the values of non-string tokens - }% - #5% additional setups - % - \input #3 % load lexer tables - % - % at this point the macros inside the table files (\newtable, \constset, - % \yybigswitch, \stashswitch, \addname, \yydoactionswitch, \setflexstates, - % \stateset, \tokeneq) have set up the corresponding stuctures in - % the `parser namespace' (e.g. if the parser namespace is `main', - % \newtable{yyaccept} created a token register \yyaccept[main]), - % assigned the `generic' names to them (to continue - % the example above, \newtable does \let\yyaccept\yyaccept[main]) and - % recorded the corresponding commands in \pinittoks for future use. - % - % lexer state macros are namespace specific (just like token names) - % so they have to be set in each namespace. - % - \setflexstates - #8% possible optimization - % - % finally, we add the definitions for the variables used in running - % the lexer and the parser. - \newparserstate - \newlexerstate - #6% additional data setup (say, \newlexerstateextra) - % - % we record all the commands necessary to switch to the desired namespace - % in a convenient macro - \expandafter\edef\csname to#1parser\endcsname{% - \noexpand\savefullstate % save the state of the current parser - #7% any data that needs to be saved - % switch to the new namespace - \let\noexpand\parsernamespace\expandafter\noexpand\csname #1namespace\endcsname - \the\pinittoks % restore all the tables, tokens and constants, and stacks - \let\noexpand\getcurrentparser\expandafter\noexpand\csname to#1parser\endcsname - }% - \restorecs{local-namespace}\parsernamespace -} - -\def\genericprettytokens namespace: #1, tokens: #2, correction: #3, host: #4;{% - \savecs{local-namespace}{\parsernamespace\tokeneq}% - \yystringempty{#2}{}{% - \expandafter\let\expandafter\parsernamespace\csname #1namespace\endcsname - \def\tokeneq##1##2{\prettytoken{##1}}% - \let\tokenpp\prettytoken - \input #2 % /* re-use token equivalence table to set the typesetting of tokens */ - }% - \yystringempty{#3}{}{% - \expandafter\let\expandafter\parsernamespace\csname #1namespace\endcsname - \input #3 % input customized typesetting rules for tokens - }% - \yystringempty{#4}{}{% - \expandafter\let\expandafter\hostparsernamespace\csname #4namespace\endcsname - }% - \restorecs{local-namespace}{\parsernamespace\tokeneq}% -} diff --git a/support/splint/tex/yycommon.sty b/support/splint/tex/yycommon.sty index 5058fafe8a..a8144efaa4 100644 --- a/support/splint/tex/yycommon.sty +++ b/support/splint/tex/yycommon.sty @@ -1,4 +1,4 @@ -% Copyright 2012-2014, Alexander Shibakov +% Copyright 2012-2020, Alexander Shibakov % This file is part of SPLinT % % SPLinT is free software: you can redistribute it and/or modify @@ -38,9 +38,9 @@ % the following macro is a mild example of expansion tricks \def\yypopstack#1\by#2{% - \ifnum#2>\z@ - \yyp@pst@ck{#1}{#2}% - \fi + \ifnum#2>\z@ + \yyp@pst@ck{#1}{#2}% + \fi } \def\yyp@pstack#1{% @@ -53,8 +53,8 @@ \let.\expandafter \def\yyp@pst@ck#1#2{% - \let\sts\or - \iffalse{\fi...\def...#1...{...\sts.\ifcase\number\number.\xincrement.{\number#2} \yyp@pstack#1}\else}\fi + \let\sts\or + \iffalse{\fi...\def...#1...{...\sts.\ifcase\number\number.\xincrement.{\number#2} \yyp@pstack#1}\else}\fi } \catcode`\.=12 % other character @@ -64,17 +64,21 @@ \def\yypop#1\into#2{\def\sts{\consumeone{#2}}#1\stackend#1} \long\def\consumeone#1#2{% - #1{#2}\let\sts\scoopupstack + #1{#2}\let\sts\scoopupstack } % pushing stuff on a stack: \yypush{t o k e n s}\on\yyvs or \expandafter\yypush\number\yystate\on\yyss -\long\def\yypush#1\on#2{\toksa={#1}\expandafter\toksb\expandafter{#2}\edef#2{\noexpand\sts{\the\toksa}\the\toksb}} +\long\def\yypush#1\on#2{\expandafter\def\expandafter#2\expandafter{\romannumeral\yyp@sh{#2}{#1}}} + +\long\def\yyp@sh#1#2{\expandafter\yyp@@h\expandafter{#1}{#2}} + +\long\def\yyp@@h#1#2{0 \sts{#2}#1} % push register contents on a stack: #1 is a register, #2 is a stack (a control % sequence that expands to a `\sts{v a l u e}\sts...' list) -\def\yypushr#1\on#2{\expandafter\toksa\expandafter{#2}\edef#2{\noexpand\sts{\the#1}\the\toksa}} +\def\yypushr#1\on#2{\expandafter\yypush\expandafter{\the#1}\on#2} % the first parameter is the stack, the second is the location from the top (a nonnegative number), the third is % the control sequence that will hold the value; @@ -82,12 +86,12 @@ \def\yyreadstack#1\at#2\to#3{\edef\sts{\noexpand\skipandcount{\number#2}{\noexpand#3}}#1\stackfinish#1} \def\skipandcount#1#2#3{% - \ifnum#1=\z@ %we have got to the element we need - \def#2{#3}% - \yybreak\ignorestack - \else - \yybreak{\edef\sts{\noexpand\skipandcount{\xdecrement{#1}}{\noexpand#2}}}% - \yycontinue + \ifnum#1=\z@ %we have got to the element we need + \def#2{#3}% + \yybreak\ignorestack + \else + \yybreak{\edef\sts{\noexpand\skipandcount{\xdecrement{#1}}{\noexpand#2}}}% + \yycontinue } % same as above except read the value into a register @@ -95,12 +99,12 @@ \def\yyreadstackr#1\at#2\to#3{\edef\sts{\noexpand\skipandcountr{\number#2}{#3}}#1\stackfinish#1} \def\skipandcountr#1#2#3{% - \ifnum#1=\z@ %we have got to the element we need - #2#3% - \yybreak\ignorestack - \else - \yybreak{\edef\sts{\noexpand\skipandcountr{\xdecrement{#1}}{\noexpand#2}}}% - \yycontinue + \ifnum#1=\z@ %we have got to the element we need + #2#3% + \yybreak\ignorestack + \else + \yybreak{\edef\sts{\noexpand\skipandcountr{\xdecrement{#1}}{\noexpand#2}}}% + \yycontinue } \long\def\ignorestack#1\stackfinish#2{} @@ -108,53 +112,53 @@ \def\stackfinish#1{\def#1{0\message{:stack empty:}}} \def\yyreadvstack#1\upto#2{% assume that #2 > 0 - \edef\sts{\noexpand\splitstack{\number#2}{\expandafter\xincrement\expandafter{\number\toptoks}}}#1\stackend#1% + \edef\sts{\noexpand\splitstack{\number#2}{\expandafter\xincrement\expandafter{\number\toptoks}}}#1\stackend#1% } \long\def\splitstack#1#2#3{% - \expandafter\def\csname$'#1\endcsname{#3}% $ - \ifnum#2<\@cclvi % we have not reached the maximum allocated number of token registers - \expandafter\toksdef\csname$$'#1\endcsname=#2 - \toks#2{#3}% - \fi - \ifnum#1=\@ne %we have read the values - \let\sts\scoopupstack - \else - \edef\sts{\noexpand\splitstack{\xdecrement{#1}}{\xincrement{#2}}}% - \fi + \expandafter\def\csname$'#1\endcsname{#3}% $ + \ifnum#2<\@cclvi % we have not reached the maximum allocated number of token registers + \expandafter\toksdef\csname$$'#1\endcsname=#2 + \toks#2{#3}% + \fi + \ifnum#1=\@ne %we have read the values + \let\sts\scoopupstack + \else + \edef\sts{\noexpand\splitstack{\xdecrement{#1}}{\xincrement{#2}}}% + \fi } \def\yypeekvstack#1\upto#2{% assume #2 > 0 - \edef\sts{\noexpand\peelstack{\number#2}{\expandafter\xincrement\expandafter{\number\toptoks}}}#1\relax% + \edef\sts{\noexpand\peelstack{\number#2}{\expandafter\xincrement\expandafter{\number\toptoks}}}#1\relax% } \long\def\peelstack#1#2#3{% - \expandafter\def\csname$'#1\endcsname{#3}% $ - \ifnum#2<\@cclvi % we have not reached the maximum allocated number of token registers - \expandafter\toksdef\csname$$'#1\endcsname=#2 - \toks#2{#3}% - \fi - \ifnum#1=\@ne %we have read the values - \let\sts\eatone - \else - \edef\sts{\noexpand\peelstack{\xdecrement{#1}}{\xincrement{#2}}}% - \fi + \expandafter\def\csname$'#1\endcsname{#3}% $ + \ifnum#2<\@cclvi % we have not reached the maximum allocated number of token registers + \expandafter\toksdef\csname$$'#1\endcsname=#2 + \toks#2{#3}% + \fi + \ifnum#1=\@ne %we have read the values + \let\sts\eatone + \else + \edef\sts{\noexpand\peelstack{\xdecrement{#1}}{\xincrement{#2}}}% + \fi } % macros to support new printing routines \def\yypeeksstack#1\upto#2\withprefix#3{% assume #2 > 0 - \edef\sts{\noexpand\peelsstack{\number#2}}% - \expandafter\def\expandafter\sts\expandafter{\sts{#3}{}}#1\relax% + \edef\sts{\noexpand\peelsstack{\number#2}}% + \expandafter\def\expandafter\sts\expandafter{\sts{#3}{}}#1\relax% } \long\def\peelsstack#1#2#3#4{% - \ifnum#1=\@ne %we have read the values - #3\let\sts\eatone - \else - \edef\sts{\noexpand\peelsstack{\xdecrement{#1}}}% - \expandafter\def\expandafter\sts\expandafter{\sts{#2}{#2{#4}#3}}% - \fi + \ifnum#1=\@ne %we have read the values + #3\let\sts\eatone + \else + \edef\sts{\noexpand\peelsstack{\xdecrement{#1}}}% + \expandafter\def\expandafter\sts\expandafter{\sts{#2}{#2{#4}#3}}% + \fi } % token register access @@ -164,7 +168,11 @@ } \def\concatl#1#2{% store the concatenation result in the second sequence - #2\expandafter\expandafter\expandafter{\expandafter\the\expandafter#1\the#2}% + \expandafter\conc@tl\expandafter{\the#2}{#1}{#2}% +} + +\def\conc@tl#1#2#3{% + #3\expandafter{\the#2#1}% } \def\appendr#1#2{% @@ -179,12 +187,35 @@ \tokreturn{}{}{#1{\the#1}}% } +% appending to token registers without expansion + +\long\def\appendlnx#1#2{% + \expandafter\app@ndlnx\expandafter{\the#1}{#2}{#1}% +} + +\long\def\app@ndlnx#1#2#3{% + #3{#2#1}% +} + +% one can use #1\expandafter{\the#1#2} instead of \appendrnx below; +% this form (as well as the \appendlnx above) has the advantage of +% being useable with \romannumeral0 in case one merely wants to record +% the concatenation for future use + +\long\def\appendrnx#1#2{% + \expandafter\app@ndrnx\expandafter{\the#1}{#2}{#1}% +} + +\long\def\app@ndrnx#1#2#3{% + #3{#1#2}% +} + % the following macros are an expandable way to determine if a token register is empty; % while a number of different conditionals can be used, including plain \iffalse, % this choice seems to result in a shortest macro and the fewest number of \expandafter's; % an idea from % http://tex.stackexchange.com/questions/2936/test-whether-token-list-is-empty -% where it is attributed to Ulrich Diez can be generalized to make multiple tests inside braces +% where it is attributed to Ulrich Diez can be generalized to apply multiple tests inside braces % in a row; the macros from that discussion are quoted below; note, however, that these macros % lead to unbalanced braces inside alignments (see The \TeX book, Appendix~D, p.~385 for the % discussion of the `master counter' and the `balance counter' and their behavior when @@ -205,17 +236,17 @@ % non-brace while the parameter scanning mechanism of \TeX\ will try % to collect the smallest possible balanced input; the `excessive' % braces will disappear in the expansion of the `\if...' construct; -% the reason \if or other macros that expand their argumens are so well suited for this +% the reason \if or other macros that expand their arguments are so well suited for this % `chain expansion' mechanism is in the fact that the expansions for \string and \if... are launched % from the same point. \long\def\yytoksempty#1{% - \iffalse{{\fi - \if{\expandafter\yytoks@mpty\the#1}}}% - \yybreak\yyfirstoftwo - \else - \yybreak\yysecondoftwo - \yycontinue + \iffalse{{\fi + \if{\expandafter\yytoks@mpty\the#1}}}% + \yybreak\yyfirstoftwo + \else + \yybreak\yysecondoftwo + \yycontinue } % when the token list is empty, \TeX\ will try to expand \yybreak premaurely; @@ -225,12 +256,12 @@ % gleaned from `\TeX\ the program') \long\def\yystringempty#1{% - \iffalse{{\fi - \if{\yytoks@mpty#1}}}% - \yybreak\yyfirstoftwo - \else - \yybreak\yysecondoftwo - \yycontinue + \iffalse{{\fi + \if{\yytoks@mpty#1}}}% + \yybreak\yyfirstoftwo + \else + \yybreak\yysecondoftwo + \yycontinue } \catcode`\>=2 @@ -253,7 +284,7 @@ } % the macros below are a derivation of David Kastrup's magnificent string comparison -% macros below: +% macros: % \def\strequal#1{\number\strequalstart{}{}#1\relax} % \def\strequalstart#1#2#3{\if#3\relax\strequalstop\fi % \strequalstart{\if#3#1}{#2\fi}} @@ -261,7 +292,7 @@ % % use: \if\strequal{string}{string}... % -% they were adjusted to handle spaces in the strings and conform to a different +% they were adjusted to handle spaces inside the strings and to conform to a different % syntax, namely \yyifsamestring{string1}{string2}{true}{false} % the original macros use the fact that, say \if1\fi will expand to nothing and % that \number'13 expands to 11 whereas \number13 expands to 13; the elegance of @@ -269,7 +300,7 @@ \edef\yyifsamestring#1{\noexpand\yyifsamestr@ng{}{}#1 \noexpand\yyifsam@str@ng\space} \def\yyifsamestr@ng#1#2#3 {\ifx\yyifsam@str@ng#3\yyifsam@str@ng\fi - \yyifs@m@str@ng{#1}{#2}#3\space} + \yyifs@m@str@ng{#1}{#2}#3\space} \def\yyifs@m@str@ng#1#2#3{% \if#3\space @@ -299,12 +330,12 @@ % but then \yytoks@mpty could not be reused \long\def\yystartsinbrace#1{% - \iffalse{\fi - \if{\yytoks@mpty#1}}% - \yybreak\yysecondoftwo - \else - \yybreak\yyfirstoftwo - \yycontinue + \iffalse{\fi + \if{\yytoks@mpty#1}}% + \yybreak\yysecondoftwo + \else + \yybreak\yyfirstoftwo + \yycontinue } % a test to determine whether the argument is a given control sequence @@ -333,89 +364,86 @@ \long\def\yyfirstoftwo#1#2{#1} \long\def\yysecondoftwo#1#2{#2} +\long\def\yyfirstofthree#1#2#3{#1} \long\def\yysecondofthree#1#2#3{#2} \long\def\yythirdofthree#1#2#3{#3} -% arrays of integers are going to be represented by a string of tokens `element0 \or element1 \or ...' +\long\def\yypioneofthree#1#2#3{{#1}} +\long\def\yypitwoofthree#1#2#3{{#2}} +\long\def\yypithreeofthree#1#2#3{{#3}} + +% (unoptimized) arrays of integers are represented by a string of tokens `element0 \or element1 \or ...' % #2 is a register (otherwise the case and the integer from the array `coalesce'); % the following macro was designed to make something like -% \vara=\getelemof\yytable\at\yyn\relax possible so it has to expand to a number; +% \tempca=\getelemof\yytable\at\yyn\relax possible so it has to expand to a number; % incidentally, some care should be taken using the above asignment to make sure that % it is not followed by an expandable token (such as \if) as in this case the token might be -% expanded prematurely, as the assignment is looking for the first non-expandable token which +% expanded prematurely while the assignment is looking for the first non-expandable token which % is not part of the number; this is the reason for the \relax -\def\getelemof#1\at#2{% the original meaning of this macro - \ifcase\expandafter#2\the#1\else\fi +\def\getelemof#1\at#2{% #1 is the name of the token register containing the array, #2 is the index + \expandafter\get@l@mof\expandafter{\csname#1\endcsname}{#2}% } -\def\getelemof#1\at#2{% no longer limited to registers for #2 - \expandafter\get@lemof\expandafter{\the#1}{#2}% +\def\get@l@mof#1#2{% + \expandafter\get@lemof\expandafter{\the#1}{#2}% } \def\get@lemof#1#2{% - \ifcase#2 #1\else\fi + \ifcase#2 #1\else\fi } -\def\fastgetelemof#1\at#2{% - \csname #1\parsernamespace\number#2\endcsname -} - -\def\fgetelemof#1\at#2{% - \expandafter\ifx\csname optopt[#1]\parsernamespace\endcsname\relax - \expandafter\getelemof\csname #1\endcsname\at{#2}% - \else - \csname #1\parsernamespace\number#2\endcsname - \fi -} +\let\fgetelemof\getelemof % a nestable loop -\def\bloop#1\repeat{#1\bloop{#1}\repeat\fi} +\def\bloop#1\repeat{#1\bl@op{#1}\repeat\fi} + +\def\bl@op#1\repeat\fi{\fi#1\bl@op{#1}\repeat\fi} % optimization macros: currently, the level of optimization has to be consistent throughout the % document, i.e. \optimize macros have to be called on the same arrays after loading. % the reason is the yyfaststack.sty file that modifies the \newtable macro once for all the tables \def\optimize#1{% - \setoptopt{#1}% - \tempca\z@ - \bloop - \tempcb=\expandafter\ifcase\expandafter\tempca\the\csname#1\endcsname\else\@MM\fi\relax - \ifnum\tempcb<\@MM % - \expandafter\edef\csname #1\parsernamespace\the\tempca\endcsname{\the\tempcb}% - \advance\tempca\@ne - \repeat + \setoptopt{#1}% + \tempca\z@ + \bloop + \tempcb=\expandafter\ifcase\expandafter\tempca\the\csname#1\endcsname\else\@MM\fi\relax + \ifnum\tempcb<\@MM % + \expandafter\edef\csname #1\parsernamespace\the\tempca\endcsname{\the\tempcb}% + \advance\tempca\@ne + \repeat } \def\optimizetext#1{% optimizing text arrays - \setoptopt{#1}% - \tempca\z@ - \@ptimizetext{#1} + \setoptopt{#1}% + \tempca\z@ + \@ptimizetext{#1} } \def\@ptimizetext#1{% - \edef\next{\expandafter\ifcase\expandafter\tempca\the\csname#1\endcsname\else\end\fi}% - \ifx\next\endcontainer - \let\next\eatone - \else - \expandafter\edef\csname #1\parsernamespace\the\tempca\endcsname{\next}% - \advance\tempca\@ne - \let\next\@ptimizetext - \fi - \next{#1}% + \edef\next{\expandafter\ifcase\expandafter\tempca\the\csname#1\endcsname\else\end\fi}% + \ifx\next\endcontainer + \let\next\eatone + \else + \expandafter\edef\csname #1\parsernamespace\the\tempca\endcsname{\next}% + \advance\tempca\@ne + \let\next\@ptimizetext + \fi + \next{#1}% } \def\uoptimize#1{% same as the macro above but produces nonnegative constants as \mathchardef's - \setoptopt{#1}% - \tempca\z@ - \bloop - \tempcb=\expandafter\ifcase\expandafter\tempca\the\csname#1\endcsname\else\@MM\fi\relax - \ifnum\tempcb<\@MM % - \toksa\expandafter{\csname #1\parsernamespace\the\tempca\endcsname}% - \edef\next{\mathchardef\the\toksa=\the\tempcb\relax}\next - \advance\tempca\@ne - \repeat + \setoptopt{#1}% + \tempca\z@ + \bloop + \tempcb=\expandafter\ifcase\expandafter\tempca\the\csname#1\endcsname\else\@MM\fi\relax + \ifnum\tempcb<\@MM % + \toksa\expandafter{\csname #1\parsernamespace\the\tempca\endcsname}% + \edef\next{\mathchardef\the\toksa=\the\tempcb\relax}\next + \advance\tempca\@ne + \repeat } \def\setoptopt#1{% @@ -466,29 +494,29 @@ \newif\iftracedfa \def\taction#1\in#2{% - \begingroup - \edef\acstring{#1}% in case #1 is, say, \the\toksa, so we no longer have to keep track of it - \iftracedfa\derrmessage{acting on <\meaning\acstring>\space in (\string#2) \getstatename#2 }\fi - \toksa\expandafter{#2}\toksb\expandafter{\acstring}% - \edef\next{\toksa{\the\toksa\the\toksb{% - \iftracedfa\noexpand\derrmessage{default action: \noexpand\meaning\noexpand\default}\fi - \noexpand\default}}% - \def\noexpand\next####1\the\toksb####2####{\noexpand\grabaction}}\next - \expandafter\next\the\toksa\grabaction - \tokreturn{}{}{\the\toksa}% + \begingroup + \edef\acstring{#1}% in case #1 is, say, \the\toksa, so we no longer have to keep track of it + \iftracedfa\ferrmessage{acting on <\meaning\acstring>\space in (\string#2) \getstatename#2 }\fi + \toksa\expandafter{#2}\toksb\expandafter{\acstring}% + \edef\next{\toksa{\the\toksa\the\toksb{% + \iftracedfa\noexpand\ferrmessage{default action: \noexpand\meaning\noexpand\default}\fi + \noexpand\default}}% + \def\noexpand\next####1\the\toksb####2####{\noexpand\grabaction}}\next + \expandafter\next\the\toksa\grabaction + \tokreturn{}{}{\the\toksa}% } \def\tactionx#1\in#2{% exclusive version of the macro above (i.e. match the last action before the brace) - \begingroup - \edef\acstring{#1}% in case #1 is, say, \the\toksa, so we no longer have to keep track of it - \iftracedfa\errmessage{acting on <\meaning\acstring>\space in (\string#2) \getstatename#2 }\fi - \toksa\expandafter{#2}\toksb\expandafter{\acstring}% - \edef\next{\toksa{\the\toksa\the\toksb{% - \iftracedfa\noexpand\derrmessage{default action: \noexpand\meaning\noexpand\default}\fi - \noexpand\default}}% - \def\noexpand\next####1\the\toksb####{\noexpand\grabaction}}\next - \expandafter\next\the\toksa\grabaction - \tokreturn{}{}{\the\toksa}% + \begingroup + \edef\acstring{#1}% in case #1 is, say, \the\toksa, so we no longer have to keep track of it + \iftracedfa\errmessage{acting on <\meaning\acstring>\space in (\string#2) \getstatename#2 }\fi + \toksa\expandafter{#2}\toksb\expandafter{\acstring}% + \edef\next{\toksa{\the\toksa\the\toksb{% + \iftracedfa\noexpand\ferrmessage{default action: \noexpand\meaning\noexpand\default}\fi + \noexpand\default}}% + \def\noexpand\next####1\the\toksb####{\noexpand\grabaction}}\next + \expandafter\next\the\toksa\grabaction + \tokreturn{}{}{\the\toksa}% } \def\getstatename#1{\expandafter\g@tstatename#1.\raw} @@ -496,11 +524,11 @@ \def\g@tstatename#1#2\raw{\expandafter\eatone\string#1} \def\caction#1\in#2{% - \begingroup - \uccode`.=#1\relax - \uppercase{\toksa{\taction{.}\in}}% - \toksb{#2}\concat\toksa\toksb - \tokreturn{}{}{\the\toksa}% + \begingroup + \uccode`.=#1\relax + \uppercase{\toksa{\taction{.}\in}}% + \toksb{#2}\concat\toksa\toksb + \tokreturn{}{}{\the\toksa}% } \def\checkforcount#1{% a rough implementation of `type checking' for a parameter @@ -513,17 +541,182 @@ } \def\action#1\in#2{% - \begingroup - \checkforcount#1% - \toksb{{#1}\in{#2}}\concat\toksa\toksb - \tokreturn{}{}{\the\toksa}% + \begingroup + \checkforcount#1% + \toksb{{#1}\in{#2}}\concat\toksa\toksb + \tokreturn{}{}{\the\toksa}% }% \let\switchon\taction +\let\switchonwithtype\action % phase out \action, since it is a rather common name \let\default\relax \def\grabaction#1#2\grabaction{\toksa{#1}} +% switch manipulation macros: adding and replacing labels and actions +% the macros assume that the switch to be manipulated is well formed, otherwise +% no assumptions have been made; +% if the label is not present in the switch or the new label already exists, an +% error is returned +% the macros are not expandable but can be made such with some +% (rather significant) effort + +% #1 is the label at which to change +% #2 is the new label +% #3 is the name of the new switch +% #4 is the switch +% #5 is the operation to perform if #2 is present and #3 is not +\def\matchswitch#1#2#3#4#5{% + \expandafter\matchswitch@a\expandafter{#1}{#2}{#3}{#4}{#1}{\matchswitch@e}{#5}% +} + +% #1 is the expanded version of the switch +% #2 is the label at which to change +% #3 is the new label +% #4 is the name of the new switch +% #5 is the switch +% #6 is the test sequence to apply if #2 is present +% #7 is the operation to perform if #2 is present and #3 is not +\def\matchswitch@a#1#2#3#4#5#6#7{\matchswitch@b{#1}{#1}{#2}{#3}{#4}{#5}{#6}{#7}} + +% #1 is the expanded version of the switch +% #2 is the expanded version of the switch +% #3 is the label at which to change +% #4 is the new label +% #5 is the name of the new switch +% #6 is the switch +% #7 is the test sequence to apply if #3 is present +% #8 is the operation to perform if #3 is present and #4 is not +\def\matchswitch@b#1#2#3#4#5#6#7#8{% + \def#5##1#3{\matchswitch@c}% + \expandafter\expandafter\expandafter#5\expandafter\eatone\string{#1#3}{#2}{#3}{#4}{#5}{#6}{#7}{#8}% +} + +\def\matchswitch@c{% + \expandafter\expandafter\expandafter\matchswitch@d + \expandafter\expandafter\expandafter{\expandafter\eatone\string}% +} + +% #1 is the match result +% #2 is the expanded version of the switch +% #3 is the label at which to change +% #4 is the new label +% #5 is the name of the new switch +% #6 is the switch +% #7 is the test sequence to apply if #3 is present +% #8 is the operation to perform if #3 is present and #4 is not +\def\matchswitch@d#1#2#3#4#5#6#7#8{% + #7{#1}{#2}{#3}{#4}{#5}{#6}{#8}% +} + +% #1 is the match result +% #2 is the expanded version of the switch +% #3 is the label at which to change +% #4 is the new label +% #5 is the name of the new switch +% #6 is the switch +% #7 is the operation to perform if #3 is present and #4 is not +\def\matchswitch@e#1#2#3#4#5#6#7{% + \yystringempty{#1}{% label not present + \errhelp{Switch #6 contents: #2}% + \errmessage{label \nx#3 was not found in switch \nx#6}% + }{% + \yystringempty{#4}{% no new label, skip the next test + #7{#2}{#3}{#4}{#5}% + }{% + \matchswitch@a{#2}{#4}{#3}{#5}{#6}{\matchswitch@f}{#7}% + }% + }% +} + +\def\matchswitch@f#1#2#3#4#5#6#7{% + \yystringempty{#1}{% label not present + #7{#2}{#4}{#3}{#5}% + }{% + \errhelp{Switch #6 contents: #2}% + \errmessage{label \nx#3 already exists in switch \nx#6} + }% +} + +% add a label to an existing action + +\def\extendswitch#1\at#2\by#3\to#4{% + \matchswitch{#1}{#2}{#3}{#4}{\@xtendswitch}% +} + +\def\@xtendswitch#1#2#3#4{% + \def#4##1#2##2#3{\def#4{##1#2#3##2}}% + #4#1#3% +} + +% replace an existing label inside a switch + +\def\replaceswitch#1\at#2\by#3\to#4{% + \matchswitch{#1}{#2}{#3}{#4}{\r@placeswitch}% +} + +\def\r@placeswitch#1#2#3#4{% + \def#4##1#2##2#3{\def#4{##1#3##2}}% + #4#1#3% +} + +% replace an existing action inside a switch + +\def\replaceaction#1\at#2\by#3\to#4{% + \matchswitch{#1}{#2}{}{#4}{\r@placeaction{#3}}% +} + +% #1 holds the new action +% #2 is the expanded switch +% #3 is the label at which to make the replacement +% #4 is empty +% #5 is the name of the new switch +\def\r@placeaction#1#2#3#4#5{% + \r@placeaction@a{#2}{#3}{#5}{#1}% +} + +% #1 is the expanded switch +% #2 is the label at which to make the replacement +% #3 is the name of the new switch +% #4 is the new action +\def\r@placeaction@a#1#2#3#4{% + \def#3##1#2##2##{\expandafter\expandafter\expandafter + \r@placeaction@b\expandafter\expandafter\expandafter{\expandafter\eattwo\string}}% + \expandafter\expandafter\expandafter#3\expandafter\eatone\string{#1}{#2}{#3}{#1}{#4}% +} + +% #1 is the part of the switch after the action +% #2 is the label at which to make the replacement +% #3 is the name of the new switch +% #4 is the expanded switch +% #5 is the new action +\def\r@placeaction@b#1#2#3#4#5{% + \def#3##1#2##2##{\expandafter\expandafter\expandafter + \r@placeaction@c\expandafter\expandafter\expandafter{\expandafter\eatone\string}{##1}{##2}}% + \expandafter\expandafter\expandafter#3\expandafter\eattwo\string{#4.}{#2}{#3}{#1}{#5}% +} + +% #1 = {{before the label}{between the label and the action} after the action . } +\def\r@placeaction@c#1{% + \expandafter\yystringempty\expandafter{\r@placeaction@f#1}{% the remainder of the switch is gone + \expandafter\r@placeaction@d\r@placeaction@e#1% + }{% + \expandafter\r@placeaction@c\expandafter{\r@placeaction@e#1}% + } +} + +% #1 before the label +% #2 between the label and the action +% #3 is the label +% #4 is the name of the new switch +% #5 part of the switch after the action +% #6 is the new action +\def\r@placeaction@d#1#2#3#4#5#6{\def#4{#1#3#2#6#5}} + +\def\r@placeaction@e#1#2#3.{{#1}{#2}} + +\def\r@placeaction@f#1#2#3.{} + % grab the first token unless it is a space or a brace \def\getfirsttoken#1{% @@ -554,7 +747,8 @@ \long\def\yybreak@@@#1#2\yycontinue{\fi\fi\fi\fi#1} \long\def\yybreak@@@@#1#2\yycontinue{\fi\fi\fi\fi\fi#1} -% we intentionally leave \yycontinue undefined since it should not be expanded normally +% we intentionally leave \yycontinue defined as an \errmessage +% since it should not be expanded normally; % every conditional that uses \yybreak?{...} ... \yycontinue construct % must have an \else clause, i.e.\ a conditional such as % \if ab @@ -562,27 +756,21 @@ % \yycontinue % is a bad idea as it will result in an incomplete \iffalse %\let\yycontinue\fi +\def\yycontinue{\errmessage{\noexpand\yycontinue should never be expanded!}} +% this also makes \if...\yycontinue constructs unskippable; this can be remedied by +% adding a \fi before \yycontinue, which will not affect a properly constructed +% conditional % macros for taking care of extra tokens -\long\def\yyid#1{#1} -\long\def\yypione#1#2{#1} -\long\def\yypitwo#1#2{#2} +\long\def\yyid#1{#1} % this is misnamed since it changes #1 by stripping braces and spaces \long\def\yyswap#1#2{#2#1} \long\def\eatone#1{} \long\def\eattwo#1#2{} +\long\def\eatthree#1#2#3{} \long\def\eattoend#1\end{} +\long\def\eattospace#1 {} \input xarithm.sty -% temporaries - -\input trt1.sty - -% \tempcd used by \printrule and implicit rule name macros in yymisc.sty -% \tempce used by implicit rule name macros in yymisc.sty - -% \tokse and \toksf so far only used in the bison action for -% \codepropstype - \newif\ifbootstrapmode diff --git a/support/splint/tex/yydebug.sty b/support/splint/tex/yydebug.sty new file mode 100644 index 0000000000..0d763aecfa --- /dev/null +++ b/support/splint/tex/yydebug.sty @@ -0,0 +1,148 @@ +% Copyright 2012-2020, Alexander Shibakov +% This file is part of SPLinT +% +% SPLinT is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% SPLinT is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with SPLinT. If not, see <http://www.gnu.org/licenses/>. + +% handy debugging shortcuts + +\def\yydebugsetup{% initialize debugging (note that arbitrary commands + % can be also inserted by \insertraw{...} + \expandafter\def\expandafter\multicharswitch % allow execution of any code in the middle of input + \expandafter{\multicharswitch\yydebugbegin\yydebugend{\the\yybyte}}% +} + +\def\yydebuggenericstart{% generic command executed in the middle of input + \yydebugmost % turn on tracing + \yyinput % ... and continue +} + +\def\yydebuggenericfinish{% stop debugging + \yydebugnone % turn off tracing + \yyinput % ... and continue +} + +\let\yydebugbegin\yydebuggeneric +\let\yydebugend\yydebuggenericfinish + +\newif\ifcdebug % a temporary conditional + +\def\yydebugall{% turn all debugging options on + \yydebugmost + \checktabletrue + \saveparseoutputtrue +} + +\def\yydebugparse{% + \tracelookaheadtrue + \traceparseresultstrue + \traceparserstatestrue + \tracerulestrue + \tracestackstrue + \tracediscardedinputtrue +} + +\def\reporttokendisplay{% to make this skippable in bootstrap mode + \ifdisplaytokenraw\ferrmessage{tokens are typeset as is^^J}\fi +} + +\def\yydebugmost{% do not save or display the tables + \ifbootstrapmode + \ferrmessage{*** bootstrap mode is on ***^^J^^J}% + \else + \reporttokendisplay + \checktrimtrue + \parseverbosetrue + \checktrailingstashtrue + \fi + \ifbracketedvisible\ferrmessage{Symbolic term names are visible^^J}\fi + \iftermindex\else\ferrmessage{Indexing is turned off^^J}\fi + \ifshowlastaction\else\ferrmessage{Last action will not be shown}\fi + \ifxreflocal\else\ferrmessage{Cross references are generated in noweb style}\fi + \ifx\optimization\UNDEFINED + \else + \ferrmessage{Optimization level set at \number\optimization^^J}% + \fi + + \tracingonline=3 + \showboxbreadth=10000 + \showboxdepth=10000 +% + \yydebugparse + \traceactioncodetrue + \traceactionstrue + \tracebadcharstrue + \tracebadnamestrue + \tracedfatrue + \traceflexbufferstrue + \tracenamestrue + \tracestatestrue + \traceswitchlabelstrue + \tracetexpptrue + \tracetokennamestrue + \yyflexdebugtrue + \yyinputdebugtrue + \yytracereplacementstrue + \traceprettytokenstrue +} + +\def\yydebugnone{% turn all debugging options off + \checktablefalse + \ifbootstrapmode + \else + \checktrimfalse + \parseverbosefalse + \fi + \saveparseoutputfalse + \traceactioncodefalse + \traceactionsfalse + \tracebadcharsfalse + \tracebadnamesfalse + \tracedfafalse + \tracediscardedinputfalse + \traceflexbuffersfalse + \tracelookaheadfalse + \tracenamesfalse + \traceparseresultsfalse + \traceparserstatesfalse + \tracerulesfalse + \tracestacksfalse + \tracestatesfalse + \traceswitchlabelsfalse + \tracetexppfalse + \tracetokennamesfalse + \yyflexdebugfalse + \yyinputdebugfalse + \yytracereplacementsfalse + \cdebugfalse +} + +% miscellaneous shortcuts + +\def\shownethe#1{% + {% + \edef\next{\the#1}% + \ifx\next\empty + \else + \showthe#1% + \fi + }% +} + +\def\showem#1#2#3{\toksa{#1}\toksb{#2}\toksc{#3}{\newlinechar=`^^J% + \errmessage{% + arg. 1: \the\toksa^^J% + arg. 2: \the\toksb^^J% + arg. 3: \the\toksc% +}}} + diff --git a/support/splint/tex/yyfaststack.sty b/support/splint/tex/yyfaststack.sty index cc43c33115..9bf46b3d1e 100644 --- a/support/splint/tex/yyfaststack.sty +++ b/support/splint/tex/yyfaststack.sty @@ -1,4 +1,4 @@ -% Copyright 2012-2014, Alexander Shibakov +% Copyright 2012-2020, Alexander Shibakov % This file is part of SPLinT % % SPLinT is free software: you can redistribute it and/or modify @@ -14,23 +14,26 @@ % You should have received a copy of the GNU General Public License % along with SPLinT. If not, see <http://www.gnu.org/licenses/>. -% fast versions of stack access functions +% fast(er) versions of stack access functions \catcode`\@=11 -\def\yyinitstack#1{% #1 is the counter +\def\yyinitstack#1{% #1 is the name of the stack \csname \expandafter\eatone\string#1<count>\endcsname\m@ne } % stacks will be defined as pairs ( \s t a c k n a m e [n u m b e r], \s t a c k n a m e <count> ) -% where \s t a c k n a m e [n u m b e r] is a control sequence and \s t a c k n a m e <count> -% is a \count register +% where \s t a c k n a m e [n u m b e r] is an associative array of control sequences +% and \s t a c k n a m e <count> is a \count register % % note that in the implementaion below the stack grows `the wrong % way'; this is done for convenience, since there is no `memory read % with increment' operation, the `usual' (say, hardware) stack % implementations take advantage of, and our stack can grow -% unrestricted this way +% unrestricted this way; also note that while the array is namespace specific, +% the stack pointer is not, so special effort is required to preserve it + +\let\yyinitarray\yyinitstack % using the stack as an array only makes sense for the optimized version \def\getstackpointer#1{% expands to the value of the current top of the stack position \expandafter\the\csname \expandafter\eatone\string#1<count>\endcsname @@ -38,7 +41,15 @@ \def\gettopofstackcs#1{% expands to the control sequence (a member of the associative array) % that holds the value of the current element at the top of the stack - \csname \expandafter\eatone\string#1[\getstackpointer#1]\parsernamespace\endcsname + \csname \expandafter\eatone\string#1[\getstackpointer#1]\parsernamespace \endcsname +} + +\def\gettopofstackcsx#1{% a version of the above to be used with \romannumeral + 0\expandafter\noexpand\csname \expandafter\eatone\string#1[\getstackpointer#1]\parsernamespace \endcsname +} + +\def\gettopofstackcsxx#1{% to be used with \romannumeral, expands to the contents of the top stack element + 0\expandafter\expandafter\expandafter\space\csname \expandafter\eatone\string#1[\getstackpointer#1]\parsernamespace \endcsname } \def\getmidstackcs#1#2{% expands to the control sequence (a member of the associative array) @@ -46,6 +57,10 @@ \csname \expandafter\eatone\string#1[#2]\parsernamespace\endcsname } +\def\getmidstackcsx#1#2{% a version of the above to be used with \romannumeral, safe to use with \edef + 0\expandafter\noexpand\csname \expandafter\eatone\string#1[#2]\parsernamespace\endcsname +} + \def\movestackpointer#1\by#2{% \expandafter\advance\csname \expandafter\eatone\string#1<count>\endcsname#2% } @@ -56,8 +71,8 @@ % -\def\yypop#1\into#2{% - #2\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter{\gettopofstackcs#1}% +\def\yypop#1\into#2{% pops the stack #1, stores the top element in token register #2 + #2\expandafter{\romannumeral\gettopofstackcsxx#1}% \movestackpointer#1\by\m@ne } @@ -68,6 +83,11 @@ \expandafter\expandafter\expandafter\def\gettopofstackcs#2{#1}% } +\long\def\yypushx#1\on#2{% push with expand + \movestackpointer#2\by\@ne + \expandafter\expandafter\expandafter\edef\gettopofstackcs#2{#1}% +} + % push register contents on a stack: #1 is a register, #2 is a stack \def\yypushr#1\on#2{% @@ -199,6 +219,20 @@ \movestackpointer#1\by#2\relax } +% faster array access macros + +\def\fastgetelemof#1\at#2{% + \csname #1\parsernamespace\number#2\endcsname +} + +\def\fgetelemof#1\at#2{% this definition allows mixing optimized and unoptimized tables + \expandafter\ifx\csname optopt[#1]\parsernamespace\endcsname\relax + \getelemof{#1}\at{#2}% + \else + \csname #1\parsernamespace\number#2\endcsname + \fi +} + % new stack access macros that read the stack directly (to reduce namespace pollution) % these are here more as an example diff --git a/support/splint/tex/yyinit.sty b/support/splint/tex/yyinit.sty index 8d9b7d33c3..5091c05007 100644 --- a/support/splint/tex/yyinit.sty +++ b/support/splint/tex/yyinit.sty @@ -1,4 +1,4 @@ -% Copyright 2012-2014, Alexander Shibakov +% Copyright 2012-2020, Alexander Shibakov % This file is part of SPLinT % % SPLinT is free software: you can redistribute it and/or modify @@ -22,10 +22,10 @@ name: main, ptables: cweb/gyytab.tex, ltables: cweb/ltab.tex, - tokens: \drvname.tok, + tokens: bo.tok, asetup: {}, - dsetup: \newlexerstateextra, - rsetup: \noexpand\savefullstateextra, + dsetup: \newlexerstateextra\newparserstateextra, + rsetup: {}, optimization: \optimizeall;% % prologue parser @@ -34,12 +34,63 @@ name: prologue, ptables: cweb/dyytab.tex, ltables: cweb/ltab.tex, - tokens: \drvname.tok, + tokens: bo.tok, asetup: {}, - dsetup: \newlexerstateextra, - rsetup: \noexpand\savefullstateextra, + dsetup: \newlexerstateextra\newparserstateextra, + rsetup: {}, optimization: \optimizeall;% +% flex parser + +\genericparser + name: flex, + ptables: cweb/fiptab.tex, + ltables: cweb/filtab.tex, + tokens: fo.tok, + asetup: {}, + dsetup: {}, + rsetup: {}, + optimization: {};% optimized by the driver (--optimize-tables, --optimize-actions) + +% flex regex parser + +\genericparser + name: flexre, + ptables: cweb/reptab.tex, + ltables: cweb/filtab.tex, + tokens: fo.tok, + asetup: {}, + dsetup: {}, + rsetup: {}, + optimization: {};% optimized by the driver (--optimize-tables, --optimize-actions) + +% flex section 2 parser + +\genericparser + name: flextwo, + ptables: cweb/raptab.tex, + ltables: cweb/filtab.tex, + tokens: fo.tok, + asetup: {}, + dsetup: \newparserstateextra, + rsetup: {}, + optimization: {};% optimized by the driver (--optimize-tables, --optimize-actions) + +% flex section 1 parser + +\genericparser + name: flexone, + ptables: cweb/ddptab.tex, + ltables: cweb/filtab.tex, + tokens: fo.tok, + asetup: {}, + dsetup: {}, + rsetup: {}, + optimization: {};% optimized by the driver (--optimize-tables, --optimize-actions) + +\let\flexpseudonamespace\flexnamespace +\let\flexpseudorenamespace\flexrenamespace + % parser for term names: this is not really a great idea in itself but rather an % illustration of what is possible @@ -50,84 +101,299 @@ tokens: {}, asetup: {}, dsetup: {}, - rsetup: \noexpand\savefullstateextra, + rsetup: \let\returnexplicitspace\ignoreexplicitspace, % ignore spaces in names optimization: \optimizeall;% \tomainparser -\input yytexlex.sty +% stage two macros: parsing -\let\unparse\yyid +% \flex parser stack -\expandafter\def\csname parserstack[b]\endcsname#1#2{% - \parsevb{#1}% Stage two, start the parsing - \ifyyparsefail % revert to generic macros if parsing failed - \yybreak{\message{parsing failed ...}#2}% - \else % Stage three, process the parsed table - \yybreak{\typesetalltables}% - \yycontinue +% section 1 parser + +\def\flexoneparserinit{% + \yylessusedtrue + \floption@sensetrue } -\expandafter\def\csname parserstack[]\endcsname#1#2{% - \parsevb{#1}% Stage two, start the parsing - \ifyyparsefail % revert to generic macros if parsing failed - \yybreak{\message{parsing failed ...}#2}% - \else % Stage three, process the parsed table - \yybreak{\typesetalltables}% - \yycontinue +\def\flexoneparserdatainit{% + \table{}% } -% stage two macros: parsing +% regular expression parser -\newtoks\symstream +\def\flexreparserinit{% + \yyBEGIN{SECT2}% + \flin@ruletrue + \yylessusedtrue +} -\def\parsevb#1{% - \ifchecktable - \ifsaveparseoutput - {\toks0{#1}\newlinechar=`^^J\immediate\write\exampletable{^^J\harmlesscomment - table before parsing:^^J\the\toks0}}% - \else - {\toks0{#1}\errmessage{table before parsing: \the\toks0}}% - \fi - \fi +\def\flexreparserdatainit{% + \table{}% +} + +% section 2 parser + +\def\flexparserinit{% + \yyBEGIN{SECT2}% + \def\flbracelevel{0}% + \yylessusedtrue +} + +\def\flexparserdatainit{% + \table{}% +} + +% output parsed tables + +\long\def\displayoutputcode#1#2#3{% #1 is the output code (will be expanded by \write) + % #2 is the output stream + % #3 is the preamble (will be expanded by \write) + \immediate\write#2{#3#1}% +} + +\def\displayflextable#1{{% + \hidecslist\cwebstreamchars + \restorecslist{flexparser-debug}\yyflunion + \newlinechar=`^^J% + \expandafter\displayoutputcode\expandafter{\the\table}\exampletable + {^^J\harmlesscomment \parsernamespace::parsed table #1:^^J}% +}} + +\def\displaybisontable#1{{% + \hidecslist\cwebstreamchars + \restorecslist{parser-debug}\yyunion + \newlinechar=`^^J% + \expandafter\displayoutputcode\expandafter{\the\table}\exampletable + {^^J\harmlesscomment \parsernamespace::parsed table #1:^^J}% +}} + +% stage two parsing macros + +\def\preparsebisongrammar{% + \let\postparse\postparsebisongrammar \tomainparser - \doparse{#1}% + \displayrawtable % do this after the parse namespaces are setup + \basicparserinit + \bisonparserinit + \bisonparserdatainit + \yyparse +} + +\def\preparsebisonprologue{% + \let\postparse\postparsebisonprologue + \toprologueparser + \displayrawtable % do this after the namespaces are setup + \basicparserinit + \bisonparserinit + \bisonparserdatainit + \yyparse +} + +\def\preparseflexone{% + \let\postparse\postparseflexone + \toflexoneparser + \displayrawtable % do this after the namespaces are setup + \basicparserinit + \flexoneparserinit + \flexoneparserdatainit + \yyparse +} + +\def\preparseflextwo{% + \let\postparse\postparseflextwo + \toflextwoparser + \displayrawtable % do this after the namespaces are setup + \basicparserinit + \flexparserinit + \flexparserdatainit + \yyparse +} + +\def\preparsefallback#1{% + \let\postparse\relax + \message{#1}% +} + +% stage three, postprocessing and typesetting + +\newif\ifparseverbose + +\def\postparsegeneric#1{% \ifyyparsefail - \toprologueparser - \doparse{#1}% - \ifyyparsefail - \else - \ifsaveparseoutput{\newlinechar=`^^J\immediate\write\exampletable{^^J\harmlesscomment parsed table (prologue): - ^^J\the\table}}% - \fi - \fi + \yybreak{% + \ifparseverbose\ferrmessage{#1 parsing failed.}\fi + \parserreset + }% \else - \ifsaveparseoutput{\newlinechar=`^^J\immediate\write\exampletable{^^J\harmlesscomment parsed table (grammar): - ^^J\the\table}}% - \fi + \yybreak{% + \ifparseverbose\ferrmessage{#1 parsing successful.}\fi + \ifsaveparseoutput\displayparsedtable{#1}\fi + \typesetparsedtables + }% + \yycontinue +} + +\def\parserreset#1\par{% + \yyparsefailfalse % in case the next pass is a \relax + \let\postparse\empty % ... + \expandafter\skiptolsection\the\Binputtoks\par% start the next parsing pass, skip \6\hbox{} trash +} + +\def\postparsebisongrammar{% + \let\displayparsedtable\displaybisontable + \let\typesetparsedtables\typesetalltables + \postparsegeneric{(grammar)}% +} + +\def\postparsebisonprologue{% + \let\displayparsedtable\displaybisontable + \let\typesetparsedtables\typesetalltables + \postparsegeneric{(prologue)}% +} + +\def\postparseflexone{% + \let\displayparsedtable\displayflextable + \let\typesetparsedtables\typesetfsonetables + \postparsegeneric{(section 1)}% +} + +\def\postparseflextwo{% + \let\displayparsedtable\displayflextable + \let\typesetparsedtables\typesetfstwotables + \postparsegeneric{(section 2)}% +} + +\def\displayrawtable{% + \ifsaveparseoutput + {\newlinechar=`^^J\immediate\write\exampletable{^^J\harmlesscomment + table before parsing:^^J\the\Binputtoks}}% + \fi + \ifchecktable + \ferrmessage{table before parsing: \the\Binputtoks}% \fi } -% stage three macros: typesetting +\fillpstack{}{% + \preparsebisongrammar + \preparsebisonprologue + {\preparsefallback{**}}% + \relax % this \relax is necessary so that the braces above + % are not stripped by \poppstack +} + +\fillpstack{b}{% + \preparsebisongrammar + \preparsebisonprologue + {\preparsefallback{**}}% + \relax % this \relax is necessary so that the braces above + % are not stripped by \poppstack +} + +\fillpstack{fs1}{% + \preparseflexone + \preparseflextwo + {\preparsefallback{==}}% + \relax % this \relax is necessary so that the braces above + % are not stripped by \poppstack +} + +\fillpstack{fs2}{% + \preparseflextwo + {\preparsefallback{--}}% + \relax % this \relax is necessary so that the braces above + % are not stripped by \poppstack +} + +\fillpstack{t}{% + \relax +} + +% stage 3.5 macros: typesetting + +\newtoks\symstream \def\tlskip{\z@} \def\tfskip{\parindent} +\newif\ifchecktrailingstash + \def\typesetalltables{% \begingroup + \ifsaveparseoutput + {\newlinechar=`^^J\immediate\write\exampletable{^^J\harmlesscomment + stashed stream:^^J\the\yystash^^J^^J\harmlesscomment + format stream: ^^J\the\yyformat}}% + \fi + \ifchecktable + \ferrmessage{parsed table: \the\table^^J^^J% + stashed stream: \the\yystash^^J^^J% + format stream: \the\yyformat}% + \fi + \extractprodtableinfo + \symstream\table + \table{}% + \setprodtable + \the\symstream\relax + \postoks{}\pushothertables + \ifchecktable + \ferrmessage{table after processing: \the\table}% + \fi + \ifsaveparseoutput + {\newlinechar=`^^J\immediate\write\exampletable{^^J\harmlesscomment + processed table:^^J\the\table}}% + \fi + \parindent1em + \checkforpropertable\table + \tabskip\tfskip + \ruletableset + \ifchecktrailingstash + \ferrmessage{remaining stash: \the\yystash}% + \fi + \unwrapstash\yystash + \toksa\expandafter{\the\yystash}% + \cleanstash\stripstash\checkforccode + \ifchecktrailingstash + \ferrmessage{stash after cleaning: \the\toksa}% + \fi + \ifnum\wd0>\z@ + %\ifchecktable + % \showboxdepth=1000 + % \showboxbreadth=1000 + % \showbox0 + %\fi + % currently testing for nontrivial leftover stash involves packaging the stash material + % into a \vbox; as a result, the stash containing ${}{}$\hbox{} will have a nonzero length + % which is why the test below is necessary + \ifnum\ht0>\z@ + \indent\boxstash + \fi + \fi + \expandafter % export the value of the alignment + \endgroup + \expandafter\gaglue\the\gaglue\relax +} + +\def\typesetfstwotables{% + \begingroup \ifchecktable \ifsaveparseoutput {\newlinechar=`^^J\immediate\write\exampletable{^^J\harmlesscomment - stashed stream:^^J\the\yystash}}% + stashed stream:^^J\the\yystash^^J^^J\harmlesscomment + format stream: ^^J\the\yyformat}}% \else - \errmessage{parsed table: \the\table^^J^^Jstashed stream: \the\yystash}% + \errmessage{parsed table: \the\table^^J^^J% + stashed stream: \the\yystash^^J^^J% + format stream: \the\yyformat}% \fi \fi + \extractregextableinfo \symstream\table \table{}% - \setprodtable + \setregextable \the\symstream\relax - \postoks{}\pushothertables + \regextableset \ifchecktable \ifsaveparseoutput \else @@ -138,17 +404,76 @@ {\newlinechar=`^^J\immediate\write\exampletable{^^J\harmlesscomment processed table:^^J\the\table}}% \fi - \parindent1em - \checkforpropertable\table - \tabskip\tfskip - \ruletableset \ifchecktable - \message{remaining stash: \the\yystash}% + \ifchecktrim + \ferrmessage{remaining stash: \the\yystash}% + \fi + \fi + \unwrapstash\yystash + \toksa\expandafter{\the\yystash}% + \cleanstash\stripstash\checkforccode + \ifchecktable + \ifchecktrim + \ferrmessage{stash after cleaning: \the\toksa}% + \fi + \fi + \ifnum\wd0>\z@ + %\ifchecktable + % \showboxdepth=1000 + % \showboxbreadth=1000 + % \showbox0 + %\fi + % currently testing for nontrivial leftover stash involves packaging the stash material + % into a \vbox; as a result, the stash containing ${}{}$\hbox{} will have a nonzero length + % which is why the test below is necessary + \ifnum\ht0>\z@ + \indent\boxstash + \fi + \fi + \endgroup +} + +\def\typesetfsonetables{% + \begingroup + \ifchecktable + \ifsaveparseoutput + {\newlinechar=`^^J\immediate\write\exampletable{^^J\harmlesscomment + stashed stream:^^J\the\yystash^^J^^J\harmlesscomment + format stream: ^^J\the\yyformat}}% + \else + \errmessage{parsed table: \the\table^^J^^J% + stashed stream: \the\yystash^^J^^J% + format stream: \the\yyformat}% + \fi + \fi +% \extractregextableinfo + \symstream\table + \table{}% + \setregexdeftable + \the\symstream\relax + \regexdeftableset + \ifchecktable + \ifsaveparseoutput + \else + \errmessage{table after processing: \the\table}% + \fi + \fi + \ifsaveparseoutput + {\newlinechar=`^^J\immediate\write\exampletable{^^J\harmlesscomment + processed table:^^J\the\table}}% + \fi + \ifchecktable + \ifchecktrim + \ferrmessage{remaining stash: \the\yystash}% + \fi \fi - \toksa{}\the\yystash + \unwrapstash\yystash + \toksa\expandafter{\the\yystash}% \cleanstash\stripstash\checkforccode \ifchecktable - \message{stash after cleaning: \the\toksa}% + \ifchecktrim + \ferrmessage{stash after cleaning: \the\toksa}% + \fi \fi \ifnum\wd0>\z@ %\ifchecktable @@ -166,10 +491,16 @@ \endgroup } +\let\extractprodtableinfo\empty % we do not preprocess the productions table + +\let\extractregextableinfo\empty % we do not preprocess the regex table + % setting the rule table: cross-section alignment and other effects are applied here; % in order to produce the proper line skips before and after \unvbox, the rules followed by % \TeX\ while adding an \halign to a vertical list have to be reproduced explicitly +\newdimen\gaglue % the width of the action box of the last alignment + \def\ruletableset{% \par \vskip-\baselineskip @@ -186,12 +517,48 @@ } \expandafter }\expandafter - \unvbox\expandafter0\expandafter + \unvcopy\expandafter0\expandafter \prevdepth\the\prevdepth\relax + \setbox\z@=\vbox{\unvbox\z@ \setbox\z@=\lastbox % set the alignment dimension + \hbox{\unhbox\z@ \unskip\setbox\z@=\lastbox\expandafter}\expandafter}\expandafter\gaglue\the\wd\z@ } \def\setallterms#1{\setbox\z@=\hbox{\it#1}\ifsquashterms\hbox to0pt{\unhbox\z@\hss}\else\unhbox\z@\fi\hfil} +% typesetting the scanner automaton rules + +\def\regextableset{% + \par + \vskip-\baselineskip + \setbox0 \vbox\expandafter{\expandafter + \null\expandafter\prevdepth\the\prevdepth + \halign to\hsize + {##\hfil\tabskip0 pt plus1fil\ &\relax\tabskip\tlskip\toksa{}##\makestashbox\hfil\cr + \the\table + }% + \expandafter + }\expandafter + \unvbox\expandafter0\expandafter + \prevdepth\the\prevdepth\relax +} + +% typesetting named regular expression definitions + +\def\regexdeftableset{% + \par + \vskip-\baselineskip + \setbox0\vbox\expandafter{\expandafter + \null\expandafter\prevdepth\the\prevdepth + \halign to\hsize + {\hskip\parindent##\hfil\tabskip0 pt plus1fil\ &\relax\tabskip\tlskip\tt##\hfil\cr + \the\table + }% + \expandafter + }\expandafter + \unvbox\expandafter0\expandafter + \prevdepth\the\prevdepth\relax +} + % quick and dirty global alignment: the size of the last box (and those in between) % can be chosen automatically after one pass and read in for the final pass; % in the future this will be the default implementation; for now, the inelegant @@ -264,7 +631,8 @@ \tokdectoks\toksa \edef\next{\table{\the\table\noalign{% \tabskip\parindent - \nx\displaytokenrawtrue + %\nx\displaytokenrawtrue % this controls how tokens are displayed + % in the declarations: if true, the macro names will be shown \halign to\hsize{\the\tokdectoks}% }% }}\next @@ -384,10 +752,12 @@ % macros for processing \Cee\ mode material +\newif\ifchecktrim + %\long\def\buildstash#1{\toksa\expandafter{\the\toksa#1}} % = stashed \def\cleanstash{% - \ifchecktrim\errmessage{collected stash: \the\toksa}\fi + \ifchecktrim\ferrmessage{collected stash: \the\toksa}\fi \expandafter\cleanst@sh\the\toksa\packagebox} \def\cleanst@sh{\let\6\testsbox\setbox0=\vbox\bgroup} @@ -417,7 +787,7 @@ \def\packagebox{\egroup\ifnum\wd0>\z@\else\toksa{}\fi} \def\stripstash{% - \ifchecktrim\errmessage{before trimming: \the\toksa}\fi + \ifchecktrim\ferrmessage{before trimming: \the\toksa}\fi \def\6{}\expandafter\stripst@sh\expandafter\ignorespaces\the\toksa\6\str@pst@sh} \def\stripst@sh{\toksa{}\stripst@shi} @@ -451,7 +821,7 @@ \newif\iftrailingreturn \def\striptrim{% - \ifchecktable\errmessage{trimming: \the\toksb}\fi + \ifchecktrim\ferrmessage{trimming: \the\toksb}\fi \edef\next{\the\toksb}% \expandafter\striptr@m\the\toksb\relax\end } @@ -463,10 +833,10 @@ #3% \relax #4% ? \end{% -% \def\next{#4}% -% \ifx\next\empty % \toksc{#3#4}\showthe\toksc - \setbox\z@\vbox{#3#4}% +% + \setbox\z@\vbox{ + #3#4}% \ifnum\wd\z@=\z@ \expandafter\trimreturn\the\toksa\end \toksb{}% @@ -485,8 +855,8 @@ } \def\boxstash{% - \ifchecktrim\errmessage{stash contents: \the\toksa}\fi - $\vtop{\activateinlinec\tabskip\z@\halign{\strut\ignorespaces##\hfil\cr\the\toksa\crcr}}$} + \ifchecktrim\ferrmessage{stash contents: \the\toksa}\fi + $\vtop{\activateinlinec\tabskip\z@\halign{\strut\ignorespaces##\hfil\cr\relax\the\toksa\crcr}}$} \def\makestashbox{\cleanstash\stripstash\boxstash} @@ -533,12 +903,16 @@ \ifcat\noexpand\next0% \let\next\pr@dterm \else - \let\next\oldmathS + \if\noexpand\next[% + \let\next\pr@dterm + \else + \let\next\oldmathS + \fi \fi \fi \next } - + \def\pr@dterm#1{% \ifx#1\$% \def\next{\hbox{$\Upsilon$}}% @@ -550,44 +924,60 @@ \ifnum`#1>`0\relax \def\next{\seekno#1}% \else - \def\next{\hbox{$\Upsilon$}#1}% + \def\next{\hbox{$\Upsilon$}#1}% TODO: look for an identifier \fi \else - \def\next{\hbox{$\Upsilon$}#1}% + \def\next{\hbox{$\Upsilon$}#1}% TODO: look for an identifier \fi \fi \fi \next }% -\let\oldmathS\$ \let\$\prodterm +\defreserved\${\prodterm} \def\seekno{\afterassignment\printterm\tempca}% \def\seeksym#1]{% - \hbox{$\Upsilon\kern-1pt{}_{\rm#1}$}} + \hbox{$\Upsilon\kern-1pt{}_{\def\\##1{\hbox{\sscmd\prodstyle{##1}}}\rm#1}$}} + +\def\seeksym#1]{% a better version of the above + \hbox{$\ulcorner\def\\##1{##1}\let\.\\\let\|\\\let\ous\_\let\_\relax + \edef\next{#1}\let\_\ous + \hbox{\expandafter\prodstyle\expandafter{\next}}\urcorner$}} \def\printterm{\hbox{$\Upsilon\kern-1pt{}_{\number\tempca}$}}% +% typesetting examples of \bison\ productions and \flex\ input in text + \long\def\setproduction#1{% \def\termidxrank{5}% \def\headeridxrank{4}% \def\defidxrank{3}% \def\texcsidxrank{5}% + \textproductionsetup + \hbox{\strut}% + \Binputtoks{\lsectionbegin{b}#1\yyeof\yyeof\endparseinput\endparse\postparse}% + \the\Binputtoks\par% Stage two, start the parsing +} + +\def\textproductionsetup{% \ninepoint \let\returnexplicitspace\splitexplicitspace \let\acharswitch\texcharadjust \let\onecharswitch\texcsadjust + \let\extractprodtableinfo\empty % we do not preprocess the table \showlastactionfalse \let\actionfiller\empty - \parsevb{#1} % Stage two, start the parsing - \ifyyparsefail - {\toks0{#1}\errmessage{failed to parse: \the\toks0}}% - \else % Stage three, process the parsed table - \par\hbox{\strut}% - \typesetalltables - \fi + \let\postparsetext\postparsebproduction + \fillpstack{b}{% + \preparsebisongrammar + \preparsebisonprologue + {\preparsefallback{**}}% + \relax % this \relax is necessary so that the braces above + % are not stripped by \poppstack + }% } \def\splitexplicitspace{% @@ -605,7 +995,7 @@ \yybyte{\_}% \expandafter\yycp@\expandafter`\the\yybyte\relax \mkpurebyte - \yyreturn + \yyreturn } } @@ -636,8 +1026,9 @@ \long\def\b@ginprod#1\endprod{% \setproduction{#1}% + \expandafter \endgroup - \par + \expandafter\gaglue\the\gaglue\relax % export the alignment width } \def\beginmprod{% @@ -657,8 +1048,55 @@ \def\begincprod#1\endcprod{{\def\tlskip{0 pt plus1fill}\let\tfskip\tlskip\beginprod#1\endprod}} -% the next macro assumes that \gindex being defined implies that all the bookkeeping required -% for maintaining the index of grammar terms has been taken care of +% flex examples typesetting + +\long\def\setflex#1{% + \def\fstatedefidxrank{3}% + \def\fstateidxrank{4}% + \def\fregexidxrank{5}% + \textflexsetup + \hbox{\strut}% + \Binputtoks{\lsectionbegin{fs1}#1\yyeof\yyeof\endparseinput\endparse\postparse}% + \the\Binputtoks\par% Stage two, start the parsing, the \par is expected by the \parserreset +} + +\def\textflexsetup{% + \ninepoint + %\let\returnexplicitspace\splitexplicitspace + \let\acharswitch\texcharadjust + %\let\onecharswitch\texcsadjust + \let\extractprodtableinfo\empty % we do not preprocess the table + \let\postparsetext\postparsefsection + \fillpstack{fs1}{% + \preparseflexone % TODO + \preparseflextwo + {\preparsefallback{**}}% + \relax % this \relax is necessary so that the braces above + % are not stripped by \poppstack + }% +} + +\def\beginflex{% + \par + \begingroup + \catcode`\^^M=12 % + \catcode`\#=12 % + \b@ginflex% +} + +\long\def\b@ginflex#1\endflex{% + \setflex{#1}% + \expandafter + \endgroup + \expandafter\gaglue\the\gaglue\relax % export the alignment width, TODO: set \gaglue in \flex +} + + + +% the following macros assume that \gindex or \xrefstream having been defined implies +% that all the bookkeeping required for maintaining the custom index and local cross referencing +% has been taken care of; this way during the bootstrapping mode, index entries or cross references +% are not generated. \ifx\gindex\UNDEFINED \else @@ -666,6 +1104,10 @@ \immediate\openout\gindex=\jobname.gdx \fi +\let\endcprod\endgroup +\let\endmprod\endgroup +\let\endprod\endgroup + % stringing all the manuals together (disabled for now) %\newwrite\lastpageinfo diff --git a/support/splint/tex/yyinput.sty b/support/splint/tex/yyinput.sty index d424d299d8..0898410c51 100644 --- a/support/splint/tex/yyinput.sty +++ b/support/splint/tex/yyinput.sty @@ -1,4 +1,4 @@ -% Copyright 2012-2015, Alexander Shibakov +% Copyright 2012-2020, Alexander Shibakov % This file is part of SPLinT % % SPLinT is free software: you can redistribute it and/or modify @@ -14,7 +14,13 @@ % You should have received a copy of the GNU General Public License % along with SPLinT. If not, see <http://www.gnu.org/licenses/>. -\def\mkpurebyte{\uccode`\@=\yycp@\uppercase{\yybytepure{@}}\uccode`\@=`\@} +%\def\mkpurebyte{\uccode`\@=\yycp@\uppercase{\yybytepure{@}}\uccode`\@=`\@} + +% make all symbol characters category 12; most macros are indifferent to this +% however, if delimited macros are used to process the mathched text, the option +% makes it easier to write such macros; + +\def\mkpurebyte{\uccode`\.=\yycp@\uppercase{\yybytepure{.}}\uccode`\.=`\.} \def\yyinput{\futurelet\next\yyinp@t} % get the code of the next character ... @@ -57,7 +63,13 @@ \yycontinue } +% some \Cee\ escape characters; the rest are either silly (like \a and \b) or +% are already defined to have other important functions in \TeX\ (such as \v and \t) + \chardef\n=`\^^J +\chardef\r=`\^^M +\chardef\f=`\^^L +\chardef\HT=`\^^I % ASCII horizontal tab \chardef\charseq1 \chardef\charac2 \chardef\chargroup3 @@ -78,7 +90,7 @@ % automatically \yybyte{#1}% \ifyyinputdebug - \immediate\write16{read: \the\yybyte}% + \immediate\write16{read: \the\yybyte\space after: \the\yytext@seen}% \fi \ifx#1\ % a space token \yybreak\returnexplicitspace @@ -135,12 +147,24 @@ }% \def\multicharswitch{ + \raw\vb\raw {% + \vbunwrap + } + \raw\insertraw\raw {% + \insertrawnext + } \raw\stashed\raw {% \stashnext } \raw\format \formatlocal\raw {% \formatnext } + \raw\formatbegin\raw {% + \fmtbegin + } + \raw\formatp\raw {% + \fmtparam + } \raw\sflush\raw {% \sflushnext } @@ -158,6 +182,9 @@ \raw\fold \breakline\raw {% \expandafter\yyinput\expandafter\formatlocal\expandafter{\the\yybyte}% } + \raw\breakahead\raw {% + \expandafter\yyinput\expandafter\formatp\the\yybyte + } \raw\break\raw {% for testing purposes \yycp@=`\ % \yybytepure={ }% @@ -195,22 +222,64 @@ \setspecialcharsfrom\multicharswitch \setspecialcharsfrom\acharswitch +\def\insertrawnext#1{% insert a command + #1\yyinput +} + +\def\vbunwrap#1#2\vb{% + \yyinput#1\stashed{#2}\vb +} + \chardef\stashchar=`\ % \chardef\formatchar=`\ % \newcount\stashmarker \newcount\formatmarker -\def\stashnext#1{% +\def\stashnextwithspace#1{% \yybytepure{ }\yycp@\stashchar - \toksa{#1}% + \yybyte\expandafter{\the\yybyte{#1}}% \advance\stashmarker\@ne - \edef\next{\yysbyte{\noexpand\strm[\the\stashmarker]{\the\yybyte{\the\toksa}}.[\the\stashmarker]}}\next + \edef\next{\yysbyte{\noexpand\strm[\the\stashmarker]{\the\yybyte}.[\the\stashmarker]}}\next % the extra `.' is to avoid the stripping of braces by the parameter scanning mechanism of TeX - \yybyte\expandafter{\the\yybyte{#1}}% \yyreturn } +% the mechanism for stash processing making stash invisible + +\def\stashnextwithnothing#1{% + \advance\stashmarker\@ne + \yybyte\expandafter{\the\yybyte{#1}}\concat\yysubtext\yybyte + \appendr\yysbyte{\noexpand\strm[\the\stashmarker]{\the\yybyte}.[\the\stashmarker]}% + \ifyyinputdebug + \immediate\write16{stash byte: \the\yysbyte mid text: \the\yysubtext}% + \fi + % the extra `.' is to avoid the stripping of braces by the parameter scanning mechanism of TeX + \yyinput +} + +% while collecting the stash, the macro below packages the stash contents into a command sequence +% to add to the \yystash stream; the stash is presented to the lexer unpackaged though; this +% introduces a minor inefficiency while ensuring that exactly one level of packaging is present +% (otherwise the lexer may back up and repackage already packaged stash); the inefficiency only +% persists while the lexer scans the current token (and possibly backs up). + +\def\stashnextwithnothingnx#1{% + \advance\stashmarker\@ne + \yypush{#1}\on\astarray + \appendr\yysbyte{\noexpand\strm[\the\stashmarker]{\the\yybyte{% + \expandafter\noexpand\romannumeral\gettopofstackcsx\astarray}}.[\the\stashmarker]}% + \yybyte\expandafter{\the\yybyte{#1}}% do not package the input + \concat\yysubtext\yybyte + \ifyyinputdebug + \immediate\write16{stash byte: \the\yysbyte mid text: \the\yysubtext}% + \fi + % the extra `.' is to avoid the stripping of braces by the parameter scanning mechanism of TeX + \yyinput +} + +\let\stashnext\stashnextwithnothingnx + \def\formatnext#1{% \yybytepure{ }\yycp@\formatchar \toksa{#1}% @@ -221,6 +290,9 @@ \yyreturn } +\def\fmtbegin#1\fmtend{\formatnext{#1}} % multiparameter format sequences +\def\fmtparam#1#2{\formatnext{#1{#2}}} % single parameter format sequences + \chardef\boundarychar=`\ % % the following is a minimal setup of a parsing boundary @@ -237,22 +309,45 @@ \edef\next{\toksc{\the\yystash\the\yystashseen}}\next \yyfifolastidx\toksc\in\toksc \toksa{#1}\toksb{#2}% - \edef\next{\yysbyte{\noexpand\strm[\the\toksa]{\the\yybyte{\the\toksb}{\the\toksc}}.[\the\toksa]}}\next + \appendr\yysbyte{\noexpand\strm[\the\toksa]{\the\yybyte{{\nx\it flushing}: ``\the\toksb'', + {\nx\it last index}: $[\the\toksc]$. }}.[\the\toksa]}% % the extra `.' is to avoid the stripping of braces by the parameter scanning mechanism of TeX \yybyte\expandafter{\the\yybyte{#1}{#2}}% + \concat\yysubtext\yybyte + \ifyyinputdebug + \immediate\write16{stash byte: \the\yysbyte mid text: \the\yysubtext}% + \fi \yyreturn } +% the following implementation is marginally cleaner as it does not redefine \yyr@@dfifo +% it also makes it almost transparent that \yyreadfifo does not modify any token registers +% except for the two of its parameters +% TODO: replace \yyr@@dfifo with \yyr@adfifo + \def\yyreadfifo#1\to#2\in#3{% +%{% to reduce the side effects to the redefinition of the input and output + % token registers \def\yyr@adfifo##1\strm[#2]##2[#2]##3\end{% - \def\yyr@@dfifo{##3}% - \ifx\yyr@@dfifo\empty - #3{}% there is no such marker in the fifo - \else + \yystringempty{##3}{#3{}}% there is no such marker in the fifo + {% #3{##1\strm[#2]##2[#2]}% \def\yyr@@dfifo####1\strm[#2]####2[#2]\end{#1{####1}}% strip off the inserted string \yyr@@dfifo##3\end - \fi +% TODO: \def\yyr@dfifo####1\strm[#2].[#2]\end{#1{####1}}% strip off the inserted string +% \yyr@dfifo##3\end + }% + }% + \expandafter\yyr@adfifo\the#1\strm[#2].[#2]\end +%\edef\next{#1{\the#1}#3{\the#3}}\expandafter}\next +} + +\def\yytrimfifo#1\to#2\in#3{% just save the initial segment of #1 in #3 + \def\yyr@adfifo##1\strm[#2]##2[#2]##3\end{% + \yystringempty{##3}{#3{}}% there is no such marker in the fifo + {% + #3{##1\strm[#2]##2[#2]}% + }% }% \expandafter\yyr@adfifo\the#1\strm[#2].[#2]\end } diff --git a/support/splint/tex/yymisc.sty b/support/splint/tex/yymisc.sty index fcc38da96d..b961135b02 100644 --- a/support/splint/tex/yymisc.sty +++ b/support/splint/tex/yymisc.sty @@ -1,4 +1,4 @@ -% Copyright 2012-2014, Alexander Shibakov +% Copyright 2012-2020, Alexander Shibakov % This file is part of SPLinT % % SPLinT is free software: you can redistribute it and/or modify @@ -14,7 +14,7 @@ % You should have received a copy of the GNU General Public License % along with SPLinT. If not, see <http://www.gnu.org/licenses/>. -% `data structure access' macros': picking the n-th undelimited parameter +% `data structure access' macros: picking the n-th undelimited parameter % in a parameter list inside a token register % it is assumed that none of the arguments is \end, and that there are enough % parameters to pick the desired one @@ -88,6 +88,28 @@ \def\g@ttenth#1#2#3#4#5#6#7#8#9\end{\g@tsecond#9\end} +% removing the first element of a token register if it has more than one; + +\def\sansfirst#1{% + \expandafter\s@nsfirst\expandafter{\the#1}{#1}% +} + +\def\s@nsfirst#1#2{% + \expandafter\s@nsf@rst\expandafter{\eatone#1}{#2}% +} + +\def\s@nsf@rst#1#2{% + \yystringempty{#1}{}{% + #2{#1}% + }% +} + +% a version of the macro above that expands to the original argument with the first element removed + +\def\sansfirstx#1{% + \expandafter\yystringempty\expandafter{\eatone#1}{#1}{\eatone#1}% +} + % string replacement: all arguments are registers, nothing is expanded, no \next is defined % note that this is not a greedy replacement: this could be arranged with a more sophisticated macro % also note that the string being replaced cannot have any braces in it @@ -270,6 +292,18 @@ % in the interest of efficiency; the old version (that used a control sequence % as a `stop marker') was more prone to this bug. +% the next sequence is not merely a convenient abbreviation; it is useful if one +% wants to look at an `alternative' value stored for the sequence without restoring +% it to the curent namespace; it also sets up the naming convention for namespaces + +\def\restorecsname#1#2{% get the name of the sequence in storage + % note that #2 can be a string beginning with an arbitrary + % character as a placeholder for the escape character + '#1'[\expandafter\eatone\string#2]% +} + +% save macros listed in #2 in namespace #1 + \def\savecs#1#2{\s@vecs{#1}#2.} \def\s@vecs#1#2{% @@ -277,12 +311,22 @@ \yybreak{}% \else \yybreak{% - \expandafter\let\csname '#1'[\expandafter\eatone\string#2]\endcsname#2% + \expandafter\let\csname\restorecsname{#1}{#2}\endcsname#2% \s@vecs{#1}% }% \yycontinue } +% similar to the macro above but the list is a control sequence + +\def\savecslist#1#2{% + \expandafter\s@vecslist\expandafter{#2}{#1}% +} + +\def\s@vecslist#1#2{% + \savecs{#2}{#1}% +} + \def\restorecs#1#2{\r@storecs{#1}#2.} \def\r@storecs#1#2{% @@ -290,12 +334,20 @@ \yybreak{}% \else \yybreak{% - \expandafter\let\expandafter#2\csname '#1'[\expandafter\eatone\string#2]\endcsname + \expandafter\let\expandafter#2\csname\restorecsname{#1}{#2}\endcsname \r@storecs{#1}% }% \yycontinue } +\def\restorecslist#1#2{% + \expandafter\r@storecslist\expandafter{#2}{#1}% +} + +\def\r@storecslist#1#2{% + \restorecs{#2}{#1}% +} + \def\hidecs#1{\h@decs#1.} \def\h@decs#1{% @@ -309,51 +361,53 @@ \yycontinue } -\def\savehcs#1#2{\savecs{#1}{#2}\hidecs{#2}} - -\def\savecslist#1#2{% - \expandafter\s@vecslist\expandafter{#2}{#1}% -} +\def\hidecslist#1{\expandafter\hidecs\expandafter{#1}} -\def\s@vecslist#1#2{% - \savecs{#2}{#1}% -} +\def\savehcs#1#2{\savecs{#1}{#2}\hidecs{#2}} -\def\restorecslist#1#2{% - \expandafter\r@storecslist\expandafter{#2}{#1}% +\def\savehcslist#1#2{% + \expandafter\s@vehcslist\expandafter{#2}{#1}% } -\def\r@storecslist#1#2{% - \restorecs{#2}{#1}% +\def\s@vehcslist#1#2{% + \savehcs{#2}{#1}% } % a twist on the macros above: save control sequences with a postfix -\def\savecsx#1#2{\s@vecsx{#1}#2.} +\def\savecsx#1#2{\s@vecsx{#1}#2.} % there is no \savecsxlist macro -\def\s@vecsx#1#2{% +\def\s@vecsx#1#2{% #1 is the namespace, #2 is a control sequence without the postfix or prefix \ifx#2.% \yybreak{}% \else \yybreak{% - \expandafter\s@vecsxlet\expandafter#2\csname\expandafter\defprefix\expandafter\eatone\string#2\defpostfix\endcsname{#1}% + \expandafter\s@vecsxlet\csname\expandafter\defprefix\expandafter\eatone\string#2\defpostfix\endcsname#2{#1}% \s@vecsx{#1}% }% \yycontinue } -\def\s@vecsxlet#1#2{% - \expandafter\let\csname '#2'[\expandafter\defprefix\expandafter\eatone\string#1\defpostfix]\endcsname +\def\s@vecsxlet#1#2#3{% #1 is the control sequence augmented by prefix and postfix, + % #2 is the control sequence without prefix or postfix + % #3 is the namespace + \expandafter\let\expandafter#1\csname\restorecsxname{#3}{#2}\endcsname } \def\restorecsx#1#2{\r@storecsx{#1}#2.} +% see remarks about \restorecsname above + +\def\restorecsxname#1#2{% + '#1'[\expandafter\defprefix\expandafter\eatone\string#2\defpostfix]% +} + \def\r@storecsx#1#2{% \ifx#2.% \yybreak{}% \else \yybreak{% - \expandafter\r@storecsxlet\expandafter#2\csname '#1'[\expandafter\defprefix\expandafter\eatone\string#2\defpostfix]\endcsname + \expandafter\r@storecsxlet\expandafter#2\csname\restorecsxname{#1}{#2}\endcsname \r@storecsx{#1}% }% \yycontinue @@ -401,7 +455,7 @@ % in the appropriate namespace, this macro adds a % preamble, a postamble and a `this' type macro; this % will mostly be used with indexing \TeX\ control sequences - \tokse{\def\thisname{#1}\edef\thisnamex{\expandafter\eatone\string#1}}% + \toksf{\def\thisname{#1}\edef\thisnamex{\expandafter\eatone\string#1}}% \toksa\expandafter{% \csname\expandafter\defprefix\expandafter\eatone\string#1\defpostfix\endcsname}% \toksc\expandafter{\expandafter\def\the\toksa#2}% @@ -410,11 +464,11 @@ } \def\d@f@{% - \appendl\toksd{\the\tokse}% - \tokse\expandafter{\defypreamble}% - \appendl\toksd{\the\tokse}% - \tokse\expandafter{\defypostamble}% - \appendr\toksd{\the\tokse} + \tokse{\defypreamble}% + \concatl\tokse\toksd + \concatl\toksf\toksd + \tokse{\defypostamble}% + \concat\toksd\tokse \toksd\expandafter{\expandafter{\the\toksd}}% \concat\toksc\toksd \afterassignment\d@fy @@ -429,12 +483,14 @@ \def\defp#1#2#{% flexible dynamic type checking \toksa\expandafter\expandafter\expandafter{\yyuniontag#1}% - \expandafter\edef\yyuniontag{\the\toksa}% + \expandafter\edef\yyuniontag{\the\toksa}% add the sequence to the current union \def#1#2{\errmessage{unexpected type: \string#1 in namespace <\currentyyunionnamespace>}}% \savecs\parserstrictnamespace#1% \toksa{#2}% - \edef#1{\the\toksa}% + \edef#1{\the\toksa}% save the prototype \savecs\parserprototypesnamespace#1% + \let#1\relax + \savecs\parserdebugnamespace#1% save the debug sequence for outputting the AST \def#1#2% } @@ -478,6 +534,17 @@ {\catcode`\^^M=12 \aftergroup\def\aftergroup\eolletter\aftergroup{\aftergroup^^M\aftergroup}}% end of line, ... not really {\catcode`\|=0\catcode`\\=12 |aftergroup|def|aftergroup|benignescape|aftergroup{|aftergroup\|aftergroup}}% not an escape {\catcode`\#=12 \aftergroup\def\aftergroup\hashletter\aftergroup{\aftergroup#\aftergroup}}% not a parameter token +{\catcode`\~=12 \aftergroup\def\aftergroup\safetilde\aftergroup{\aftergroup~\aftergroup}}% inactive tie +{\catcode`\$=12 \aftergroup\def\aftergroup\safemath\aftergroup{\aftergroup$\aftergroup}}% not really a start math character + +\let\uscore\_ % the canonical underscore for the fonts that do not have the character + +% remove the brackets from the namespace string; +% the parameter is the control sequence that expands to the namespace string + +\def\stripbrackets#1{\expandafter\stripbr@ckets#1[]\end} + +\def\stripbr@ckets#1[#2]#3\end{\yystringempty{#3}{#1}{#1#2}} % token name input @@ -631,10 +698,11 @@ % tables \def\newtable@full#1{% - \toksa{\csname newtoks\endcsname}% - \expandafter\the\expandafter\toksa\csname #1\parsernamespace\endcsname - \edef\next{\let\csname #1\endcsname\csname #1\parsernamespace\endcsname}\next - \toksa\expandafter{\next}\concat\pinittoks\toksa + \expandafter\expandafter\csname newtoks\endcsname\csname #1\parsernamespace\endcsname + \expandafter\expandafter\expandafter\let\expandafter + \expandafter\csname #1\endcsname\csname #1\parsernamespace\endcsname + \appendr\pinittoks{\let\expandafter\noexpand\csname #1\endcsname + \expandafter\noexpand\csname #1\parsernamespace\endcsname}% \csname #1\parsernamespace\endcsname=% } @@ -645,72 +713,61 @@ \def\constset#1#2{% % a \mathchardef would be nicer but it cannot handle negative numbers \expandafter\def\csname #1\parsernamespace\endcsname{#2}% - \toksa\expandafter{\csname #1\endcsname}% - \toksb\expandafter{\csname #1\parsernamespace\endcsname}% - \edef\next{\let\the\toksa\the\toksb}\next - \toksa\expandafter{\next}\concat\pinittoks\toksa + \expandafter\expandafter\expandafter\let\expandafter + \expandafter\csname #1\endcsname\csname #1\parsernamespace\endcsname + \appendr\pinittoks{\let\expandafter\noexpand\csname #1\endcsname + \expandafter\noexpand\csname #1\parsernamespace\endcsname}% } \def\uconstset#1#2{% % a \mathchardef for positive constants \expandafter\mathchardef\csname #1\parsernamespace\endcsname=#2 % - \toksa\expandafter{\csname #1\endcsname}% - \toksb\expandafter{\csname #1\parsernamespace\endcsname}% - \edef\next{\let\the\toksa\the\toksb}\next - \toksa\expandafter{\next}\concat\pinittoks\toksa + \expandafter\expandafter\expandafter\let\expandafter + \expandafter\csname #1\endcsname\csname #1\parsernamespace\endcsname + \appendr\pinittoks{\let\expandafter\noexpand\csname #1\endcsname + \expandafter\noexpand\csname #1\parsernamespace\endcsname}% } \def\charset#1#2{% \expandafter\chardef\csname #1\parsernamespace\endcsname=#2\relax% - \toksa\expandafter{\csname #1\endcsname}% - \toksb\expandafter{\csname #1\parsernamespace\endcsname}% - \edef\next{\let\the\toksa\the\toksb}\next - \toksa\expandafter{\next}\concat\pinittoks\toksa -} - -% switch macro - -\def\stashswitch#1{% - \toksa\expandafter{\csname #1\endcsname}% - \toksb\expandafter{\csname #1\parsernamespace\endcsname}% - \edef\next{\let\the\toksb\the\toksa}\next - \edef\next{\let\the\toksa\the\toksb}% - \toksa\expandafter{\next}\concat\pinittoks\toksa + \expandafter\expandafter\expandafter\let\expandafter + \expandafter\csname #1\endcsname\csname #1\parsernamespace\endcsname + \appendr\pinittoks{\let\expandafter\noexpand\csname #1\endcsname + \expandafter\noexpand\csname #1\parsernamespace\endcsname}% } % parser and lexer state control -\def\settokreg#1{% - \toksa{\csname newtoks\endcsname}% - \expandafter\the\expandafter\toksa\csname #1\parsernamespace\endcsname - \edef\next{\let\csname #1\endcsname\csname #1\parsernamespace\endcsname}\next - \toksa\expandafter{\next}\concat\pinittoks\toksa +\def\settokreg#1{% do not create individual token registers for each parser namespace + \expandafter\ifx\csname #1\endcsname\relax + \expandafter\expandafter\csname newtoks\endcsname\csname #1\endcsname + \fi } -\def\setcntreg#1{% - \toksa{\csname newcount\endcsname}% - \expandafter\the\expandafter\toksa\csname #1\parsernamespace\endcsname - \edef\next{\let\csname #1\endcsname\csname #1\parsernamespace\endcsname}\next - \toksa\expandafter{\next}\concat\pinittoks\toksa +\def\setcntreg#1{% do not create individual count registers for each parser namespace + \expandafter\ifx\csname #1\endcsname\relax + \expandafter\expandafter\csname newcount\endcsname\csname #1\endcsname + \fi } \def\setnulstack#1{% - \toksa\expandafter{\csname #1\endcsname}% - \toksb\expandafter{\csname #1\parsernamespace\endcsname}% - \edef\next{\let\the\toksb\noexpand\empty}\next - \edef\next{\let\the\toksa\the\toksb}\next - \toksa\expandafter{\next}\concat\pinittoks\toksa - \setcntreg{#1<count>}% this is only needed for the accelerated stack + \expandafter\let\csname #1\parsernamespace\endcsname\empty % for the unoptimized stack + \appendr\pinittoks{\let\expandafter\noexpand\csname #1\endcsname + \expandafter\noexpand\csname #1\parsernamespace\endcsname}% + \setcntreg{#1<count>}% this is only (as well as the only action that is) needed for the accelerated stack } \def\setcurrentcs#1{% - \toksa\expandafter{\csname #1\endcsname}% - \toksb\expandafter{\csname #1\parsernamespace\endcsname}% - \edef\next{\let\the\toksb\the\toksa}\next - \edef\next{\toksa{\let\the\toksa\the\toksb}}\next - \concat\pinittoks\toksa + \expandafter\expandafter\expandafter\let\expandafter + \expandafter\csname #1\parsernamespace\endcsname\csname #1\endcsname + \appendr\pinittoks{\let\expandafter\noexpand\csname #1\endcsname + \expandafter\noexpand\csname #1\parsernamespace\endcsname}% } +% switch macro + +\let\stashswitch\setcurrentcs + \def\newparserstate{% \setcntreg{yytoken}% \setcntreg{yystate}% @@ -721,14 +778,18 @@ % \yyval and \yylval will be token registers \settokreg{yyval}% \settokreg{yylval}% + \setnulstack{astarray}% an array of AST nodes \setnulstack{yyssa}% \setnulstack{yyvsa}% } \def\newlexerstate{% + \settokreg{yytext@}% `dirty' buffer (contains stash and formatting) + \settokreg{yytext@seen}% read `dirty' buffer \settokreg{yytext}% \settokreg{yytextseen}% \settokreg{yybyte}% + \settokreg{yysubtext}% stash between characters \settokreg{yyfutureyytext}% token register used to save read text in eob macros % \settokreg{yytextpure}% % the registers that serve the same role @@ -760,32 +821,133 @@ % \setcntreg{yyfmark}% % the last marker in the current token \setcntreg{yyfmarklast}% + \setcntreg{yyfmark@accept}% \setcntreg{yysmark}% \setcntreg{yysmarklast}% + \setcntreg{yysmark@accept}% \setnulstack{yystatestack}% \setcurrentcs{setflexstates}% \setcurrentcs{ifyytextbackup}% this is purely to record the recovery command in \pinittoks } -\def\savestatelist#1{% this elaborate definition is needed to ensure that `throwaway token registers' like \toksa - % survive the namespace switch - \edef\next{\expandafter\expandafter\expandafter - \let\expandafter\expandafter\expandafter\noexpand\expandafter\expandafter\csname #1\parsernamespace\endcsname - \expandafter\noexpand\csname #1\endcsname}\next -} - -\def\savefullstate{% - \savestatelist{yyssa}% - \savestatelist{yyvsa}% - \savestatelist{yystatestack}% - \savestatelist{ifyytextbackup}% buffer -} - % use \pinittoks to compose a `parser restore' macro along with % \let\yyvsa\yyvsa[parser namespace] and \let\yyssa\yyssa[parser namespace]; % `parser save' macro only has to set up \yy?sa[parser namespace]'s; -% if a fully reentrant parser is required, use the macros above to save the contents of -% all the variables by redefining \settokreg and \setcntreg and saving \yy?sa stacks +% +% this mechanism creates parsers that (barely) survive namespace switches (such as when a local +% parser is used to extract information about the tokens) and does not result in a reentrant parser; +% if a fully reentrant parser is required, either use the macros above to save the contents of +% all the variables by redefining \settokreg and \setcntreg and saving \yy?sa stacks or, better still, +% take advantage of the grouping mechanism provided by \TeX; note that the grouping approach seems +% to be the only viable solution if the stack mechanism is `optimized' + +% optimization options + +\def\optimizeall{% + % lexer + \ifnum\optimization>\z@ + \optimize{yynxt}% + \optimize{yyaccept}% + \optimize{yydef}% + \optimize{yychk}% + \optimize{yybase}% + \optimize{yyec}% + \optimize{yymeta}% + \tracingstats=\@ne + \fi + % parser + \ifnum\optimization>\@ne + \optimize{yytranslate}% + \optimize{yyrone}% + \optimize{yyrtwo}% + \optimize{yyrthree}% + \optimize{yydefact}% + \optimize{yydefgoto}% + \optimize{yypact}% + \optimize{yypgoto}% + \optimize{yytable}% + \optimize{yycheck}% + \optimize{yyprhs}% + \optimize{yyrhs}% + \optimize{yytoknum}% + \optimize{yystos}% + \optimizetext{yytname}% + \fi +} + +% parser and lexer initialization, token prettyfying + +\def\genericparser name: #1, ptables: #2, ltables: #3, tokens: #4, asetup: #5, dsetup: #6, rsetup: #7, optimization: #8;{% + % parser initialization + % + \expandafter\def\csname #1namespace\endcsname{[#1]}% + \savecs{local-namespace}\parsernamespace + \expandafter\let\expandafter\parsernamespace\csname #1namespace\endcsname + \pinittoks{}% + \input #2 % load main parser table + \settokens % set the values of all tokens + \yystringempty{#4}{}{% + \input #4 % use token equivalence table to set the values of non-string tokens + }% + #5% (a)dditional setups + % + \input #3 % load lexer tables + % + % at this point the macros inside the table files (\newtable, \constset, + % \yybigswitch, \stashswitch, \addname, \yydoactionswitch, \setflexstates, + % \stateset, \tokeneq) have set up the corresponding stuctures in + % the `parser namespace' (e.g. if the parser namespace is `main', + % \newtable{yyaccept} created a token register \yyaccept[main]), + % assigned the `generic' names to them (to continue + % the example above, \newtable does \let\yyaccept\yyaccept[main]) and + % recorded the corresponding commands in \pinittoks for future use. + % + % lexer state macros are namespace specific (just like token names) + % so they have to be set in each namespace. + % + \setflexstates + #8% possible optimization + % + % finally, we add the definitions for the variables used in running + % the lexer and the parser. + \newparserstate + \newlexerstate + #6% additional (d)ata setup (say, \newlexerstateextra) + % + % we record all the commands necessary to switch to the desired namespace + % in a convenient macro + {% + \toks0{#7}% additional setup before switching namespaces + \edef\next{% + \the\toks0 % additional namespace setups + \let\noexpand\parsernamespace\expandafter\noexpand\csname #1namespace\endcsname + \the\pinittoks % restore all the tables, tokens and constants, and stacks + \let\noexpand\getcurrentparser\expandafter\noexpand\csname to#1parser\endcsname + }% + \toks0\expandafter{\next}% + \edef\next{\toks0{\def\expandafter\noexpand\csname to#1parser\endcsname{\the\toks0}}}\next + \expandafter + }\the\toks0 + \restorecs{local-namespace}\parsernamespace +} + +\def\genericprettytokens namespace: #1, tokens: #2, correction: #3, host: #4;{% + \savecs{local-namespace}{\parsernamespace\tokeneq}% + \yystringempty{#2}{}{% + \expandafter\let\expandafter\parsernamespace\csname #1namespace\endcsname + \def\tokeneq##1##2{\prettytoken{##1}}% + \let\tokenpp\prettytoken + \input #2 % /* re-use token equivalence table to set the typesetting of tokens */ + }% + \yystringempty{#3}{}{% + \expandafter\let\expandafter\parsernamespace\csname #1namespace\endcsname + \input #3 % input customized typesetting rules for tokens + }% + \yystringempty{#4}{}{% + \expandafter\let\expandafter\hostparsernamespace\csname #4namespace\endcsname + }% + \restorecs{local-namespace}{\parsernamespace\tokeneq}% +} % switch and dfa macros @@ -1186,7 +1348,7 @@ \def\setuprefs#1#2{% \expandafter\let\csname$[#1]\endcsname.% $o the \ifx ... \relax test makes sense ... \appendr\nameflagtoks{\noexpand\unsetsymname{#1}}% clean it up later - \toksa{}\expandafter\charstonumbers#1\end + \toksa{}\expandafter\charstonumbers#1\end \edef\next{\toksb{\space\space\noexpand\setsym{\the\toksa}{#2}\hc^^J\uu\uu\hc\hc\hc\uu#1 --> #2^^J}}\next \edef\next{\toksc{\space\space\noexpand\unsetsym{\the\toksa}\hc^^J\uu\uu\hc\hc\hc\uu#1 --> \relax^^J}}\next \concat\setsncommands\toksb @@ -1420,3 +1582,8 @@ \setsymcs{#1}{#2}% \setsymtr{#1}{#2}% } + +% message output + +\def\ferrmessage#1{{\newlinechar`\^^J\immediate\write16{\parsernamespace::#1^^J}}} + diff --git a/support/splint/tex/yynested.sty b/support/splint/tex/yynested.sty index db725abfc5..2a47c79593 100644 --- a/support/splint/tex/yynested.sty +++ b/support/splint/tex/yynested.sty @@ -1,4 +1,4 @@ -% Copyright 2012-2015, Alexander Shibakov +% Copyright 2012-2020, Alexander Shibakov % This file is part of SPLinT % % SPLinT is free software: you can redistribute it and/or modify @@ -24,21 +24,12 @@ \boundaryupper-\@M \boundarylower-\@M -\expandafter\def\expandafter\parserdatainit\expandafter{% - \parserdatainit +\expandafter\def\expandafter\bisonparserdatainit\expandafter{% + \bisonparserdatainit \boundaryupper-\@M \boundarylower-\@M } -% the next sequence is just a reminder of what would have to be done if -% reentrancy is required; the current state saving mechanism is intended for -% bare unoptimized parsers exclusively and does not handle any constant saving - -\expandafter\def\expandafter\savefullstateextra\expandafter{% - \savefullstateextra - % save \boundaryupper and \boundarylower -} - \def\inputboundarynext#1{% \yybytepure{ }\yycp@\boundarychar #1\getstackpointer\yyvsa\relax diff --git a/support/splint/tex/yyparse.sty b/support/splint/tex/yyparse.sty index ce5ab8b5e3..f6c6dadff8 100644 --- a/support/splint/tex/yyparse.sty +++ b/support/splint/tex/yyparse.sty @@ -1,4 +1,4 @@ -% Copyright 2012-2015, Alexander Shibakov +% Copyright 2012-2020, Alexander Shibakov % This file is part of SPLinT % % SPLinT is free software: you can redistribute it and/or modify @@ -37,14 +37,14 @@ \yypushr\yystate\on\yyssa {% \iftraceparserstates - \derrmessage{^^Jstate \the\yystate\iftracestacks, \fi}% + \ferrmessage{^^Jstate \the\yystate\iftracestacks, \fi}% \fi \iftracestacks \iftraceparserstates \else - \derrmessage{^^J}% + \ferrmessage{^^J}% \fi - \showstack\yyssa\derrmessage{state stack: \stackcs^^J}% + \showstack\yyssa\ferrmessage{state stack: \stackcs^^J}% \fi }% \yybreak\yybackup @@ -117,7 +117,7 @@ \yybreak@@@\yynewstate % new state will be shifted \else % ...if (yyn < 0) \iffalse % if (yytable_value_is_error(yyn)) - % \ifnum\yyn=\YYTABLEERROR\relax + % /* #define yytable_value_is_error(Yytable_value) YYID (0) */ \yybreak@@@@\yyerr \else \yyn=-\yyn @@ -137,7 +137,7 @@ \yyn=\fgetelemof{yydefact}\at\yystate\relax % yyn = yydefact[yystate] \iftraceactions - \derrmessage{default action^^J}% + \ferrmessage{default action^^J}% \fi \ifnum\yyn=\z@ \xskiptofi\yyerr @@ -149,16 +149,16 @@ \def\yyreduce{% \yylen=\fgetelemof{yyrtwo}\at\yyn\relax \iftracerules - \derrmessage{^^Jreducing (rule \the\yyn)}\printrule{\yyn}% + \ferrmessage{^^Jreducing (rule \the\yyn)}\printrule{\yyn}% \fi {% \iftracestacks \iftracerules \else - \derrmessage{^^J}% + \ferrmessage{^^J}% \fi \showstack\yyssa - \derrmessage{stack: \stackcs^^Jpopping \the\yylen^^J}% + \ferrmessage{stack: \stackcs^^Jpopping \the\yylen^^J}% \fi }% \yyilen=\fgetelemof{yyrthree}\at\yyn\relax @@ -218,14 +218,14 @@ \def\yypaccept{% \iftraceparseresults - \derrmessage{accepted^^J}% + \ferrmessage{accepted^^J}% \fi \finishparse } \def\yyerr{% \iftraceparseresults - \derrmessage{(parse) error^^J}% + \ferrmessage{(parse) error^^J}% \fi \cleanupparse } @@ -235,10 +235,12 @@ \let\yysymswitch\eatone \let\yysymcleanup\eatone +% parser specific output message: defines the current token name to output + \def\derrmessage#1{{% \newlinechar=`\^^J% \edef\tokname{\fgetelemof{yytname}\at\yytoken}% - \message{#1}% + \ferrmessage{#1}% }} % these macros reuse dedicated counters ... locally @@ -256,7 +258,7 @@ \else \edef\ruleline{\ruleline\space<empty>}% \fi - \message{ -->\ruleline}% + \ferrmessage{ -->\ruleline}% }} % print the rule without using yyprhs and yyrhs (necessary if using @@ -269,7 +271,7 @@ \else \edef\ruleline{\ruleline\space<empty>}% \fi - \message{ -->\ruleline}% + \ferrmessage{ -->\ruleline}% }} \def\appendtoruleline#1{% @@ -293,7 +295,7 @@ \long\def\cleanupparse#1\endparse{% \iftracediscardedinput - \immediate\write16{discarding the rest of the input}% + {\toksa{#1}\immediate\write16{discarding the rest of the input: \the\toksa}}% \fi \yyerror } @@ -317,3 +319,39 @@ % \yysymcleanup{\yyn}% removing symbol names from the namespace } + +% common parser initializations; note that some initializations (such as resetting the data +% and state stacks) are done at parser startup (see the definition of \yyparse) + +\def\basicparserinit{% + \yytext{}% + \yysubtext{}% + \yytext@{}% + \yytextpure{}% + \yytextseenpure{}% + \yytextseen{}% + \yytext@seen{}% + \yybyte{}% + \yyfbyte{}\yysbyte{}% + \yystash{}% + \yystashseen{}% + \yyformat{}% + \yyformatseen{}% + \yyfutureyytext{}% + \yyinitstack\astarray % flattened AST to (possibly) speed up the parser + \yyinitstack\yystatestack + \yyfmark=\z@ + \yysmark=\z@ + \yyfmarklast=\z@ + \yyfmark@accept=\z@ + \formatmarker=\z@ + \yysmarklast=\z@ + \yysmark@accept=\z@ + \stashmarker=\z@ + \yytextbackupfalse + \yyg@yyinit=\z@ + \yyg@yystart=\z@ + \YYATBOL=\@ne + \yyparsefailfalse + \YYEOBLASTMATCHtrue +} diff --git a/support/splint/tex/yypretty.sty b/support/splint/tex/yypretty.sty new file mode 100644 index 0000000000..aeb1179b32 --- /dev/null +++ b/support/splint/tex/yypretty.sty @@ -0,0 +1,25 @@ +% Copyright 2012-2020, Alexander Shibakov +% Copyright 2002-2014 Free Software Foundation, Inc. +% This file is part of SPLinT +% +% SPLinT is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% SPLinT is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with SPLinT. If not, see <http://www.gnu.org/licenses/>. + +% prettified token output for the common parts of \bison grammars; +% for these to be properly displayed, the name parser must produce +% the tokens in an appropriate namespace; they should also not be +% \bison\ names (otherwise \TeX\ will complain about `... name ... +% not exceptional ...') + +\prettywordpair{emptyrhs&}{$\circ$ {\rm(empty rhs)}}% +\prettywordpair{inline_action&}{$\diamond$ {\rm(inline action)}}% diff --git a/support/splint/tex/yystype.sty b/support/splint/tex/yystype.sty index e37b298590..8e4660fb6e 100644 --- a/support/splint/tex/yystype.sty +++ b/support/splint/tex/yystype.sty @@ -1,4 +1,4 @@ -% Copyright 2012-2014, Alexander Shibakov +% Copyright 2012-2020, Alexander Shibakov % This file is part of SPLinT % % SPLinT is free software: you can redistribute it and/or modify @@ -23,15 +23,10 @@ \setnulstack{obstackforstringraw}% } -\def\savefullstateextra{% - \savestatelist{obstackforstring}% - \savestatelist{obstackforstringraw}% -} - % lexer environment -\def\yycomplain#1{\immediate\write16{#1}} % lexer errors -\def\yypdeprecated#1{\errmessage{option: #1 is ignored}} % outdated options +\def\yycomplain#1{\ferrmessage{flex: #1}} % lexer errors +\def\yypdeprecated#1{\yywarn{option: #1 is ignored}} % outdated options \def\STRINGGROW{% \concat\currentlaststring\yytextpure @@ -63,3 +58,104 @@ \newtoks\laststringraw \newtoks\currentlaststring \newtoks\currentlaststringraw + +% common \bison parser initialization; the first macro initializes the lexer structures only +% while the second one deals exclusively with the data produced by the parser; logically, in a `real' +% \bison\ parser, the second set of initializations is applied to the |..._extra| local +% data for the parser (for a reentrant yyparse()); we put it here for convenience. + +\def\bisonparserinit{% + \yyinitstack\obstackforstring + \yyinitstack\obstackforstringraw + \percentpercentcount=\z@ + \lonesting=\z@ + \laststring{}\laststringraw{}% + \currentlaststring{}\currentlaststringraw{}% +} + +\def\bisonparserdatainit{% + \table{}\typestable{}\prectable{}\opttable{}% +} + +% macros for \flex\ lexer + +\newif\iffldidadef +\newif\ifflindented@code +\newif\iffloption@sense +\newif\iffllex@compat +\newif\ifflposix@compat +\newif\ifflin@rule +\newif\iffldoing@rule@action +\newif\ifflcontinued@action +\newif\ifflend@is@ws +\newif\ifflsf@skip@ws +\newif\ifflsf@case@ins +\newif\ifflsf@dot@all + +\newcount\fllinenum +\def\flinc@linenum{\advance\fllinenum\@ne} +\def\flinc#1{% + \expandafter\fl@nc\expandafter{\number#1}{#1}% +} +\def\fl@nc#1#2{% + \edef#2{\xincrement{#1}}% +} + +\def\fldec#1{% + \expandafter\fld@c\expandafter{\number#1}{#1}% +} +\def\fld@c#1#2{% + \edef#2{\xdecrement{#1}}% +} + +\def\yylessafter#1{}% put back the string starting at (after) #1 +\def\flsf@push{}% push the next parenthesis level +\def\flsf@pop{}% pop the nesting level + +\def\RETURNNAME{\yylexreturnsym{NAME}} +\def\RETURNCHAR{\yylexreturnsym{CHAR}} +\def\yyflexoptreturn#1{% + \edef\next{\yylval{{\iffloption@sense\else no\fi}{\the\yytextpure}{\the\yyfmark}{\the\yysmark}}}\next + \yylexreturnregular{#1}% +} + +% macros to process special character classes + +\def\makecclpair#1#2{% + \expandafter\def\csname xccl@#1\endcsname{\langle#2\rangle}% + \mak@cclpair#1.{#2}% +} + +\def\mak@cclpair CCE_#1.#2{% + \expandafter\def\csname xccl@CCE_NEG_#1\endcsname{\langle^\neg#2\rangle}% +} + +\makecclpair{CCE_ALPHA}{\alpha\beta} +\makecclpair{CCE_ALNUM}{\alpha n} +\makecclpair{CCE_BLANK}{\hbox{ }} +\makecclpair{CCE_GRAPH}{\hbox{\dingssmall\leaf}} +\makecclpair{CCE_DIGIT}{\hbox{\.{0..9}}} +\makecclpair{CCE_XDIGIT}{\hbox{\.{0..Z}}} +\makecclpair{CCE_SPACE}{\hbox{\.{\ }}} +\makecclpair{CCE_LOWER}{\hbox{\.{a..z}}} +\makecclpair{CCE_UPPER}{\hbox{\.{A..Z}}} +\makecclpair{CCE_PRINT}{\hbox{\dingssmall\pen}} +\makecclpair{CCE_PUNCT}{\hbox{\.{.}}} +\makecclpair{CCE_CNTRL}{\mapsto} + +\def\xcclreturn#1{% + \yyBEGIN{CCL}% + \yytextpure{#1}% substitute the token name for the actual text + % this is slightly dangerous, because of the `_' in the name + % for this to work, ftokenset.sty must be used + \yylexreturnsym{#1}% +} + +\chardef\flquotechar`\" + +\def\fllexsetup{% + \def\flbrace@depth{0}% + \def\flsectnum{0}% + \def\flnmstr{{}{}}% recorded name + \def\flnmdef{{}{}}% recorded definition +} diff --git a/support/splint/tex/yytexlex.sty b/support/splint/tex/yytexlex.sty index a7e7dc3250..7c149108d3 100644 --- a/support/splint/tex/yytexlex.sty +++ b/support/splint/tex/yytexlex.sty @@ -1,4 +1,4 @@ -% Copyright 2012-2015, Alexander Shibakov +% Copyright 2012-2020, Alexander Shibakov % This file is part of SPLinT % % SPLinT is free software: you can redistribute it and/or modify @@ -40,7 +40,7 @@ \appendyybyte} = {% - \appendr\texlinetoks{{}${}={}${}}% + \appendrnx\texlinetoks{{}${}={}${}}% \yygetchar } \{ @@ -62,12 +62,12 @@ \else \def\next{^^A}% \fi - \action\next\in\texdefaultstate + \switchon\next\in\texdefaultstate } ^^A % \yycp@==1 {% \edef\next{\noexpand\noexpand\the\yybyte}% - \action\next\in\texdefaultstate} + \switchon\next\in\texdefaultstate} \raw\hbox\raw {% \appendnext} @@ -151,14 +151,14 @@ \yycp@=`\\% \putother\yycp@\in\yybyte \def\next{escape}% - \action\next\in\currentstate} + \switchon\next\in\currentstate} } \def\texescdefault{% \let\currentstate\esccurrentstate \yycp@=`\ % \yybyte{\ }% - \action\yycp@\in\currentstate + \caction\yycp@\in\currentstate } \def\getcescape{% @@ -189,37 +189,42 @@ \fi \fi \fi - \action\next\in\currentstate + \switchonwithtype\next\in\currentstate } \def\outputtexcs{% - \expandafter\ifx\csname\the\yytext\defTpostfix\endcsname\relax - \putother{`\\}\in\toksa + \expandafter\ifx\csname\defprefix\the\yytext\defpostfix\endcsname\relax + %\putother{`\\}\in\toksa + \toksa{\hbox{\sixpoint\tt\char`\\}}% \concat\texlinetoks\toksa \concat\texlinetoks\yytext - \appendr\texlinetoks{\noexpand\hbox{$\noexpand\,$}}% + \appendrnx\texlinetoks{\hbox{$\,$}}% + \toksb{}% no visual key \else - \appendr\texlinetoks{\expandafter\expandafter\expandafter\noexpand\expandafter\csname\the\yytext xTeXmode\endcsname}% + \appendr\texlinetoks{\expandafter\noexpand\csname\defprefix\the\yytext\defpostfix\endcsname}% + \expandafter\ifx\csname\restorecsxname{index:visual}{.\the\yytext}\endcsname\relax + \toksb{}% no visual key + \else + \toksb\expandafter\expandafter\expandafter{\csname\restorecsxname{index:visual}{.\the\yytext}\endcsname}% + \fi \fi - \appendr\texidxtoks{% - \termindex{{\nx\nx\nx\texcsstring{\expandafter\charstonumberse\the\yytext\end}}{\texnspace}{\nx\the\pageno}{\secno}}% - }% + \appendr\texidxtoks{\gidxentryxb{\texcsstring}{\the\yytext}{\the\toksb}}% } -% the `calling conventions' for indexing \TeX\ control sequences are too different to use canned indexing macros -% (the second parameter is a register so it has to be expanded before the \charstonumberse processes it) -% we therefore invoke the macros by hand +% indexing of \TeX\ control sequences \def\texidxdomain{T} \def\texcsidxrank{2} +\def\texcstxtidxrank{5} -\def\writetexidxentry#1{\iftermindex\write\gindex{\nx\nx\expandafter\nx\csname\texidxdomain TI\endcsname\texcsidxrank#1}\fi} +\def\writetexidxentry#1{\indxe\gindex{{\secno}{{}{\texispace}}{\texidxdomain}{\texcsidxrank}#1}} +\def\writetextxtidxentry#1{\indxe\gindex{{\secno}{{}{\texispace}}{\texidxdomain}{\texcstxtidxrank}#1}} \def\appendyybyte{\concat\texlinetoks\yybyte\yygetchar} \def\appendnext#1{\toksa{#1}\concat\texlinetoks\toksa\yygetchar} -\def\defTpostfix{xTeXmode} +\def\defTpostfix{[xTeXmode]} \def\stripyybyte{% \expandafter\stripyyb@te\the\yybyte @@ -239,57 +244,69 @@ \newif\iftracetexpp \newtoks\textoks +% the most common way for a \TeX? macro to appear in in the input is being inserted by +% \CWEB\ itself; in this case \CWEB\ makes sure that the macro is expanded in math mode; +% this assumption is relied upon in the design of these macros, and violating it may +% result in sume rather puzzling error messages, resulting from the insertion of +% \ignorespaces outside of the current group; the warning macro below makes this +% dependence explicit. + +\def\TeXxwarn{% + \relax + \ifmmode + \else + \errhelp{Check stash collecting macros.}% + \errmessage{\nx\\TeXx macro is used outside of math mode.}% + \fi +} + \def\TeXx(#1)#2;{% TODO - \let\oldttdot\.\relaxcweb - \textoks{}\let\.\dotcollect + \TeXxwarn + {}$\let\oldttdot\.\relaxcweb + \let\.\dotcollect + \textoks{}% #1% \restorecweb\let\.\oldttdot - \expandafter\T@Xx\the\textoks} + \expandafter\T@Xx\the\textoks + {}${}\aftergroup\ignorespaces} \def\mypar{\par} \def\TeXb(#1)#2;{% TeX material begin - {}$% + \TeXxwarn + {}$\let\oldttdot\.\relaxcweb + \toksa{}\let\.\dotcollectb + \textoks{}% \let\oldsix\6% \let\6\ignorespaces \let\oldC\C \let\C\saveCcomments - \let\oldttdot\.\relaxcweb - \textoks{}\toksa{}\let\.\dotcollectb #1% \restorecweb\let\.\oldttdot \dotcollectstripquotes - ${}} + ${}\aftergroup\ignorespaces} \def\TeXa(#1)#2;{% TeX material add - {}$% - \let\oldttdot\.\relaxcweb + \TeXxwarn + {}$\let\oldttdot\.\relaxcweb \toksa{}\let\.\dotcollectb #1% \restorecweb\let\.\oldttdot \dotcollectstripquotes - ${}} + ${}\aftergroup\ignorespaces} \def\TeXf(#1)#2;{% TeX material add - {}$% - \let\oldttdot\.\relaxcweb + \TeXxwarn + {}$\let\oldttdot\.\relaxcweb \toksa{}\let\.\dotcollectb \textoks\expandafter{\the\textoks\hbox{\6}}% #1% \restorecweb\let\.\oldttdot \dotcollectstripquotes - ${}} - -\def\TeXo(#1)#2;{% TeX material output - \let\oldttdot\.\relaxcweb - \let\.\dotcollect - \let\6\oldsix - \let\C\oldC - #1% - \restorecweb\let\.\oldttdot - $\expandafter\T@Xx\expandafter"\the\textoks"$} + ${}\aftergroup\ignorespaces} \def\TeXao(#1)#2;{% TeX material output + \TeXxwarn {}$\let\oldttdot\.\relaxcweb \toksa{}\let\.\dotcollectb \let\6\oldsix @@ -297,9 +314,11 @@ #1% \restorecweb\let\.\oldttdot \dotcollectstripquotes - $\expandafter\T@Xx\expandafter"\the\textoks"${}${}} + \expandafter\T@Xx\expandafter + "\the\textoks"{}${}\aftergroup\ignorespaces} \def\TeXfo(#1)#2;{% TeX material output + \TeXxwarn {}$\let\oldttdot\.\relaxcweb \toksa{}\let\.\dotcollectb \textoks\expandafter{\the\textoks\hbox{\6}}% @@ -308,11 +327,14 @@ #1% \restorecweb\let\.\oldttdot \dotcollectstripquotes - $\expandafter\T@Xx\expandafter"\the\textoks"${}${}} + \expandafter\T@Xx\expandafter + "\the\textoks"{}${}\aftergroup\ignorespaces} \let\TeXxi\TeXx -\def\inlineTeXx#1{$\TeXxi(\.{"#1"});$} % for indexing macros - +\def\inlineTeXx#1{$\let\writetexidxentry\writetextxtidxentry\TeXxi(\.{"#1"});$} % for indexing macros +\def\TeXlit{\iffalse{\fi}{\setbox0\lastbox}\removewhitespace + \expandafter\.\expandafter{\iffalse}\fi} % to help with \CWEB's @t...@> cleanup + % e.g.\ |TeXao(@t\TeXlit"\hbox{\TeX\ stuff}"@>);| \def\dotcollect#1{\toksa{#1}\concat\textoks\toksa} \def\dotcollectb#1{\toksb{#1}\concat\toksa\toksb} \def\dotcollectstripquotes{\expandafter\d@tcollectstripquotes\the\toksa} @@ -322,7 +344,6 @@ \def\restorecweb{\restorecs{local-namespace}{\)}} \def\T@Xx"#1"{% - {}${}%$ \iffalse{\fi % alignment! \begingroup % tune up the standard input routines @@ -336,17 +357,17 @@ \texlinetoks{}\texidxtoks{}\bbalance\z@ \let\bbal\bbalempty \yytextbackupfalse + \let\defpostfix\defTpostfix\let\defprefix\empty \restorecsxlist\texnspace\alltexsymbols \let\termindex\writetexidxentry \yygetchar#1\end - \toksc{#1}% \iftracetexpp{\newlinechar=`^^J% - \errmessage{TeX_ input: \the\toksc^^JTeX_ first pass: \the\texlinetoks}}\fi + \toksc{#1}\ferrmessage{TeX_ input: \the\toksc^^JTeX_ first pass: \the\texlinetoks}}\fi \ifnum\bbalance=\z@ \else - \bbbalance + \bbbalance{#1}% \fi - \iftracetexpp\errmessage{TeX_ final pass: \the\texlinetoks}\fi + \iftracetexpp\ferrmessage{TeX_ final pass: \the\texlinetoks}\fi \concat\texlinetoks\texidxtoks \expandafter \endgroup @@ -356,24 +377,35 @@ % otherwise there is a risk that an output routine is called before % the group is complete and \yyreturn definition is wrong so \yyparse % will not be able to function - \expandafter\texlinetoks\expandafter{\the\texlinetoks}% - \let\bbal\bbalempty\bbalance\z@ - \restorecsxlist\texnspace\alltexsymbols - \let\termindex\writetexidxentry\tt\chardef\_=`\_\the\texlinetoks + \expandafter\T@Xpretypeset\the\texlinetoks \endgroup \iffalse}\fi - {}${}%$ +} + +\def\T@Xpretypeset{% + \let\bbal\bbalempty\bbalance\z@ + \let\defpostfix\defTpostfix\let\defprefix\empty + \restorecsxlist\texnspace\alltexsymbols + \tt\chardef\_=`\_% } \def\alltexsymbols{% - \space\toksa\toksb\toksc\tokse\toksf\the\ifx\ifnum\fi\else - \def\edef\let\empty\next\switchon\in\concat\appendr\default - \noexpand\emptyterm\print\relax\yy\inmath\omit\hfil\getfirst - \getsecond\getthird\getfourth\getfifth\nx\to\hspace\toksd\rhscont - \rhscnct\rhsbool\table\ifrhsfull\rhsfulltrue\rhsfullfalse - \yyval\tempca\tempcb\z@\@ne\tw@\m@ne\advance\ifcat\iftracebadchars - \bb\yylexreturnptr\yylexreturn\yylexreturnval\yylexreturnchar - \yylexreturntext\yylexnext + \space\toksa\toksb\toksc\toksd\tokse\toksf\toksg\toksh\the\ifx + \ifnum\fi\else\def\edef\let\empty\next\switchon\in\concat\appendr + \default\noexpand\emptyterm\print\relax\yy\inmath\omit\hfil\getfirst + \getsecond\getthird\getfourth\getfifth\nx\to\hspace\rhscont\rhscnct + \rhsbool\table\ifrhsfull\rhsfulltrue\rhsfullfalse\yyval\tempca + \tempcb\z@\@ne\tw@\m@ne\advance\ifcat\iftracebadchars\bb + \yylexreturnptr\yylexreturn\yylexreturnval\yylexreturnsym + \yylexreturnchar\yylexreturnxchar\yylexreturntext\yylexnext + \%\harmlesscomment\\\yyfatal\yywarn\yyBEGIN\yypushstate\yypopstate + \yyBEGINr\yylexstate\yypdeprecated +} + +% TODO: make this the mechanism for updating \alltexsymbols + +\def\extendcs#1\with#2{% + \expandafter\def\expandafter#1\expandafter{#1#2}% } \def\collectspaces#1{% @@ -394,23 +426,34 @@ \def\spacecontainer{\ } \def\texnspace{texline} +\def\texvspace{texvisline} +\def\texispace{index} \let\defpostfix\defTpostfix \let\defprefix\empty -\let\defypreamble\empty % for indexing macros -\def\defypostamble{ {\rm(\.{\\\thisnamex})}} - \let\settgroup\relax \defx\space{\hbox{$\,$\char`\ $\,$}}{texline} +\defy\space{\hbox{$\,$\char`\ $\,$}}{index} -\defx\hspace{\hbox{$\,$\char`\ $\,$}}{texline} +\defx\hspace{% somewhat precarious definition + \hbox{\char`\ }% + \def\setegroup{{}$\,${}}% + \def\setpgr@up{^{\hbox{\sscmd\the\toksa}}\,$}% + \def\setegr@up{\,$}% + \def\setpgroup{% + ${}_{\hbox{\sscmd\the\toksa}}% + \let\setpgroup\setpgr@up + \let\setegroup\setegr@up + \grabbalanced + }\grabbalanced +}{texline} \defy\hspace{\hbox{$\,$\char`\ $\,$}}{index} \defx\advance{% - $\mathop{\hbox{\bf add}}{}$% + $\mathop{\hbox{\bf add}}$% }{texline} \defy\advance{% @@ -425,6 +468,8 @@ $0_{\rm R}$% }{index} +\defx\z@{0_R}{index:visual} + \defx\@ne{% $\,1_{\rm R}\,$% }{texline} @@ -433,6 +478,8 @@ $1_{\rm R}$% }{index} +\defx\@ne{1_R}{index:visual} + \defx\tw@{% $\,2_{\rm R}\,$% }{texline} @@ -441,6 +488,8 @@ $2_{\rm R}$% }{index} +\defx\tw@{2_R}{index:visual} + \defx\m@ne{% $\,-1_{\rm R}\,$% }{texline} @@ -449,151 +498,208 @@ $-1_{\rm R}$% }{index} +\defx\m@ne{-1_R}{index:visual} + \defx\tempca{% - ${}t_a{}$% + $t_a$% }{texline} \defy\tempca{% $t_a$% }{index} +\defx\tempca{t_a}{index:visual} + \defx\tempcb{% - ${}t_b{}$% + $t_b$% }{texline} \defy\tempcb{% $t_b$% }{index} +\defx\tempcb{t_b}{index:visual} + \defx\toksa{% - {}${}v_a{}${}% + {}$v_a${}% \def\setegroup{}% \def\setpgroup{% $\leftarrow\langle\,\hbox{\the\toksa}% \if\next]% \else - \rangle% + \,\rangle% \fi $}\grabbalanced }{texline} +\defx\toksa{va}{index:visual} + \defy\toksa{% - ${}v_a{}$% + $v_a$% }{index} \defx\toksb{% - {}${}v_b{}${}% + {}$v_b${}% \def\setegroup{}% \def\setpgroup{% $\leftarrow\langle\,\hbox{\the\toksa}% \if\next]% \else - \rangle% + \,\rangle% \fi $}\grabbalanced }{texline} +\defx\toksb{vb}{index:visual} + \defy\toksb{% - ${}v_b{}$% + $v_b$% }{index} \defx\toksc{% - {}${}v_c{}${}% + {}$v_c${}% \def\setegroup{}% \def\setpgroup{% $\leftarrow\langle\,\hbox{\the\toksa}% \if\next]% \else - \rangle% + \,\rangle% \fi $}\grabbalanced }{texline} +\defx\toksc{vc}{index:visual} + \defy\toksc{% - ${}v_c{}$% + $v_c$% }{index} \defx\toksd{% - {}${}v_d{}${}% + {}$v_d${}% \def\setegroup{}% \def\setpgroup{% $\leftarrow\langle\,\hbox{\the\toksa}% \if\next]% \else - \rangle% + \,\rangle% \fi $}\grabbalanced }{texline} +\defx\toksd{vd}{index:visual} + \defy\toksd{% - ${}v_d{}$% + $v_d$% }{index} \defx\tokse{% - {}${}v_e{}${}% + {}$v_e${}% \def\setegroup{}% \def\setpgroup{% $\leftarrow\langle\,\hbox{\the\toksa}% \if\next]% \else - \rangle% + \,\rangle% \fi $}\grabbalanced }{texline} +\defx\tokse{ve}{index:visual} + \defy\tokse{% - ${}v_e{}$% + $v_e$% }{index} \defx\toksf{% - {}${}v_f{}${}% + {}$v_f${}% \def\setegroup{}% \def\setpgroup{% $\leftarrow\langle\,\hbox{\the\toksa}% \if\next]% \else - \rangle% + \,\rangle% \fi $}\grabbalanced }{texline} +\defx\toksf{vf}{index:visual} + \defy\toksf{$v_f$}{index} +\defx\toksg{% + {}$v_g${}% + \def\setegroup{}% + \def\setpgroup{% + $\leftarrow\langle\,\hbox{\the\toksa}% + \if\next]% + \else + \,\rangle% + \fi + $}\grabbalanced +}{texline} + +\defx\toksg{vg}{index:visual} + +\defy\toksg{$v_g$}{index} + +\defx\toksh{% + {}$v_h${}% + \def\setegroup{}% + \def\setpgroup{% + $\leftarrow\langle\,\hbox{\the\toksa}% + \if\next]% + \else + \,\rangle% + \fi + $}\grabbalanced +}{texline} + +\defx\toksh{vh}{index:visual} + +\defy\toksh{$v_h$}{index} + \defx\yyval{% - {}${}\Upsilon{}${}% + {}$\Upsilon${}% \def\setegroup{}% \def\setpgroup{% $\leftarrow\langle\,\the\toksa \if\next]% \else - \rangle% + \,\rangle% \fi $}\grabbalanced }{texline} \defy\yyval{% - ${}\Upsilon{}$% + $\Upsilon$% }{index} -\def\setflexreturn#1{% - \def\setegroup{{\bf return}#1}% +\defx\yyval{Y}{index:visual} + +\def\setcfreturn#1{% more flexible return statement + \def\setegroup{{}$\mathop{\hbox{#1}}${}}% + \let\settgroup\setegroup \def\setpgroup{% {% - \let\texidxdomain\bisonidxdomain - \tokse\toksa - \expandafter\nameproc\expandafter{\the\toksa}% + \let\termindex\writeidxentry % the indexed term is a \bison\ token + \toksc\toksa + \expandafter\nameproc\expandafter{\the\toksa}\with\parsebin \ifyyparsefail \edef\next{\toksa{\termmetastyle{% - \expandafter\gidxentry\expandafter{\expandafter\termvstring\expandafter}\expandafter{\the\toksa}% + \gidxentryxb{\termvstring}{\the\toksa}{}% \let\nx\idxfont\nx\empty\nx\tt\the\toksa\nx\/% }}}\next \else - \expandafter\settermstyle\expandafter{\the\tokse}% + \edef\next{\noexpand\settermstyle{\the\toksb}{\the\toksc}}\next \fi - {}$\mathop{\hbox{{\bf return}#1}}\hbox{\the\toksa}${}}% + {}$\mathop{\hbox{#1}}\hbox{\the\toksa}${}}% }\grabbalanced } +\def\setflexreturn#1{% + \setcfreturn{{\bf return}#1}% +} + \defx\yylexreturnptr{% \setflexreturn{$_p${}}% }{texline} @@ -602,14 +708,28 @@ {\bf return$_p$}% }{index} +\defx\yylexreturnptr{return_p}{index:visual} + +\defx\yylexreturnxchar{% + \setflexreturn{$_x${}}% +}{texline} + +\defy\yylexreturnxchar{% + \hbox{\bf return$_x$}% +}{index} + +\defx\yylexreturnxchar{return_x}{index:visual} + \defx\yylexreturnchar{% - {\bf return$_c$}% + \hbox{\bf return$_c$}% }{texline} \defy\yylexreturnchar{% - {\bf return$_c$}% + \hbox{\bf return$_c$}% }{index} +\defx\yylexreturnchar{return_c}{index:visual} + \defx\yylexnext{% {\bf continue}% }{texline} @@ -618,6 +738,8 @@ {\bf continue}% }{index} +\defx\yylexnext{continue}{index:visual} + \defx\yylexreturn{% \setflexreturn{$_l${}}% }{texline} @@ -626,6 +748,8 @@ {\bf return$_l$}% }{index} +\defx\yylexreturn{return_l}{index:visual} + \defx\yylexreturnval{% \setflexreturn{$_v${}}% }{texline} @@ -634,6 +758,18 @@ {\bf return$_v$}% }{index} +\defx\yylexreturnval{return_v}{index:visual} + +\defx\yylexreturnsym{% + \setflexreturn{$_{vp}${}}% +}{texline} + +\defy\yylexreturnsym{% + {\bf return$_{vp}$}% +}{index} + +\defx\yylexreturnsym{return_vp}{index:visual} + \defx\yylexreturntext{% {\bf return$_t$}% }{texline} @@ -642,10 +778,90 @@ {\bf return$_t$}% }{index} -\defx\table{{}${}\Omega{}${}}{texline} +\defx\yylexreturntext{return_t}{index:visual} + +\defx\xcclreturn{% + \setcfreturn{\bf set $\Upsilon$ {\rm and} return$^{\rm ccl}$}% +}{texline} + +\defy\xcclreturn{% + {\bf set $\Upsilon$ {\rm and} return$^{\rm ccl}$}% +}{index} + +\defx\xcclreturn{set U return^ccl}{index:visual} + +\defx\yyflexoptreturn{% + \setflexreturn{$^{\rm opt}$}% +}{texline} + +\defy\yyflexoptreturn{% + {\bf return$^{\rm opt}$}% +}{index} + +\defx\yyflexoptreturn{return^opt}{index:visual} + +\extendcs\alltexsymbols\with{\xcclreturn\yyflexoptreturn} + +\defx\yyfatal{% + {}$\mathop{\bf fatal}${}% + \def\setegroup{}% + \def\setpgroup{% + $\langle\,\hbox{\the\toksa}% + \if\next]% + \else + \,\rangle% + \fi$% + }\grabbalanced +}{texline} + +\defx\yyfatal{fatal}{index:visual} + +\defy\yyfatal{% + {\bf fatal}% +}{index} + +\defx\yywarn{% + {}$\mathop{\bf warn}${}% + \def\setegroup{}% + \def\setpgroup{% + $\langle\,\hbox{\the\toksa}% + \if\next]% + \else + \,\rangle% + \fi$% + }\grabbalanced +}{texline} + +\defx\yywarn{warn}{index:visual} + +\defy\yywarn{% + {\bf warn}% +}{index} + +\defx\yypdeprecated{% + {}$\mathop{\bf deprecated}${}% + \def\setegroup{}% + \def\setpgroup{% + $\langle\,\hbox{\the\toksa}% + \if\next]% + \else + \,\rangle% + \fi$% + }\grabbalanced +}{texline} + +\defx\yypdeprecated{deprecated}{index:visual} + +\defy\yypdeprecated{% + {\bf deprecated}% +}{index} + +\defx\table{{}$\Omega${}}{texline} \defy\table{$\Omega$}{index} +\defx\table{Omega}{index:visual} + \defx\relax{\hbox{$\circ$}}{texline} \defy\relax{\hbox{$\circ$}}{index} @@ -662,6 +878,8 @@ \lcenclose{$\cdot$}% }{index} +\defx\the{val}{index:visual} + \def\thecomaction{% \raw \toksaxTeXmode\toksbxTeXmode\tokscxTeXmode\toksdxTeXmode\toksexTeXmode\toksfxTeXmode \raw {% @@ -728,10 +946,18 @@ {\bf else$\;$}% }{texline} +\defy\else{% + {\bf else}% +}{index} + \defx\fi{% {\bf fi$\;$}% }{texline} +\defy\fi{% + {\bf fi}% +}{index} + \defx\def{% {\bf def$\;$}% }{texline} @@ -748,6 +974,8 @@ {\bf def$_{\rm x}$}% }{index} +\defx\edef{def_x}{index:visual} + \defx\let{% {\bf let$\;$}% }{texline} @@ -808,6 +1036,10 @@ ${}\mapsto{}$% }{texline} +\defy\to{% + $\mapsto$% +}{index} + \defx\emptyterm{% \hbox{$\ulcorner\ldots\urcorner$}% }{texline} @@ -840,6 +1072,8 @@ $\Upsilon\kern-1pt{}_{\rm?}$% }{index} +\defx\yy{Y_?}{index:visual} + \def\seeknots#1\bbal{% \let\setegroup\relax \ifnum#1>0\relax @@ -904,6 +1138,8 @@ ${}_{\rm?}\kern-2pt\Upsilon$% }{index} +\defx\bb{Y_??}{index:visual} + \defx\switchon{% \hbox{\bf switch$\;$}% \def\setpgroup{{$($}\the\toksa{$)$}$\,$}% @@ -948,7 +1184,7 @@ \defx\getfirst{% - {}${}\pi_1${}% + {}$\pi_1${}% \def\setegroup{\relax}% \def\setpgroup{% ${}(\hbox{\the\toksa}% @@ -960,14 +1196,16 @@ }{texline} \defy\getfirst{% - ${}\pi_1$% + $\pi_1$% }{index} +\defx\getfirst{pi_1}{index:visual} + \defx\getsecond{% - {}${}\pi_2${}% + {}$\pi_2${}% \def\setegroup{\relax}% \def\setpgroup{% - ${}(\hbox{\the\toksa}% + $(\hbox{\the\toksa}% \if\next]% \else )% @@ -976,11 +1214,13 @@ }{texline} \defy\getsecond{% - ${}\pi_2$% + $\pi_2$% }{index} +\defx\getsecond{pi_2}{index:visual} + \defx\getthird{% - {}${}\pi_3${}% + {}$\pi_3${}% \def\setegroup{\relax}% \def\setpgroup{% ${}(\hbox{\the\toksa}% @@ -992,14 +1232,16 @@ }{texline} \defy\getthird{% - ${}\pi_3$% + $\pi_3$% }{index} +\defx\getthird{pi_3}{index:visual} + \defx\getfourth{% - {}${}\pi_4${}% + {}$\pi_4${}% \def\setegroup{\relax}% \def\setpgroup{% - ${}(\hbox{\the\toksa}% + $(\hbox{\the\toksa}% \if\next]% \else )% @@ -1008,14 +1250,16 @@ }{texline} \defy\getfourth{% - ${}\pi_4$% + $\pi_4$% }{index} +\defx\getfourth{pi_4}{index:visual} + \defx\getfifth{% - {}${}\pi_5${}% + {}$\pi_5${}% \def\setegroup{\relax}% \def\setpgroup{% - ${}(\hbox{\the\toksa}% + $(\hbox{\the\toksa}% \if\next]% \else )% @@ -1024,11 +1268,13 @@ }{texline} \defy\getfifth{% - ${}\pi_5$% + $\pi_5$% }{index} +\defx\getfifth{pi_5}{index:visual} + \defx\rhscont{% - {}${}\pi_{\{\}}${}% + {}$\pi_{\{\}}${}% \def\setegroup{\relax}% \def\setpgroup{% ${}(\hbox{\the\toksa}% @@ -1040,11 +1286,13 @@ }{texline} \defy\rhscont{% - ${}\pi_{\{\}}$% + $\pi_{\{\}}$% }{index} +\defx\rhscont{pi_brace}{index:visual} + \defx\rhscnct{% - {}${}\pi_{\leftrightarrow}${}% + {}$\pi_{\leftrightarrow}${}% \def\setegroup{\relax}% \def\setpgroup{% ${}(\hbox{\the\toksa}% @@ -1056,11 +1304,13 @@ }{texline} \defy\rhscnct{% - ${}\pi_{\leftrightarrow}$% + $\pi_{\leftrightarrow}$% }{index} +\defx\rhscnct{pi_arrow}{index:visual} + \defx\rhsbool{% - {}${}\pi_{\vdash}${}% + {}$\pi_{\vdash}${}% \def\setegroup{\relax}% \def\setpgroup{% ${}(\hbox{\the\toksa}% @@ -1072,9 +1322,53 @@ }{texline} \defy\rhsbool{% - ${}\pi_{\vdash}$% + $\pi_{\vdash}$% +}{index} + +\defx\rhsbool{pi_implies}{index:visual} + +\defx\%{% + {\.{\harmlesscomment}}% +}{texline} + +\defy\%{% + {\.{\harmlesscomment}}\let\defypostamble\relax% }{index} +\defx\%{\%}{index:visual} + +\defx\harmlesscomment{% + {\.{\harmlesscomment}}% +}{texline} + +\defy\harmlesscomment{% + {\.{\harmlesscomment}}\let\defypostamble\relax% +}{index} + +\defx\harmlesscomment{\%}{index:visual} + +\defx\\{% + {\.{\\}}% +}{texline} + +\defy\\{% + {\.{\\}}\let\defypostamble\relax% +}{index} + +\defx\\{\\}{index:visual} + +\defx\lbchar{% + \.{\{}% +}{texline} + +\defy\lbchar{% + \.{\{}% +}{index} + +\expandafter\defx\expandafter\lbchar\expandafter{\lbchar lbchar}{index:visual} + +\extendcs\alltexsymbols\with\lbchar + \def\bbalempty[#1]#2{% \ifx#2]\relax \else @@ -1089,7 +1383,7 @@ \fi }% -\def\bbbalance{% +\def\bbbalance#1{% \ifnum\bbalance>0 \loop \advance\bbalance-1\relax @@ -1107,14 +1401,14 @@ \tempca-\bbalance \bbalance\tempca \texlinetoks{}\texidxtoks{}% - \expandafter\yygetchar\the\toksc\end + \yygetchar#1\end % \errmessage{\the\texlinetoks...\the\toksd...\the\bbalance}% - \appendl\texlinetoks{\the\toksd}% + \concatl\toksd\texlinetoks \fi } \def\grabbalanced{% - \futurelet\next\gr@bbalanced + \futurelet\next\gr@bbalanced } \def\gr@bbalanced{% @@ -1143,3 +1437,113 @@ \fi \next } + +\defx\yyBEGIN{% + \def\setegroup{{\bf enter}}% + \def\setpgroup{% + {% + \let\parsernamespace\flexpseudonamespace + \expandafter\nameproc\expandafter{\the\toksa}\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 + \edef\next{{}$\nx\mathop{\hbox{\nx\bf enter}}(\hbox{\the\toksd})${}% + \gidxentryxb{\termvstring}{\the\toksa}{\the\tokse}}\next + \let\termindex\eatone + }\grabbalanced +}{texline} + +\defy\yyBEGIN{% + {\bf enter}% +}{index} + +\defx\yyBEGIN{enter}{index:visual} + +\defx\yyBEGINr{% + {\bf enter$_x\,$}% +}{texline} + +\defy\yyBEGINr{% + {\bf enter$_x$}% +}{index} + +\defx\yyBEGINr{enter_x}{index:visual} + +\defx\yypushstate{% + \def\setegroup{{\bf push state}}% + \def\setpgroup{% + {% + \let\parsernamespace\flexpseudonamespace + \expandafter\nameproc\expandafter{\the\toksa}\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 + \edef\next{{}$\nx\mathop{\hbox{\nx\bf push state}}(\hbox{\the\toksd})\,${} + \gidxentryxb{\termvstring}{\the\toksa}{\the\tokse}}\next + \let\termindex\eatone + }\grabbalanced +}{texline} + +\defy\yypushstate{% + {\bf push state}% +}{index} + +\defx\yypushstate{push\_state}{index:visual} + +\defx\yypopstate{% + \def\setegroup{{\bf pop state}}% + \def\setpgroup{% + {% + \let\parsernamespace\flexpseudonamespace + \expandafter\nameproc\expandafter{\the\toksa}\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 + \edef\next{{}$\nx\mathop{\hbox{\nx\bf pop state}}(\hbox{\the\toksd})\,${} + \gidxentryxb{\termvstring}{\the\toksa}{\the\tokse}}\next + \let\termindex\eatone + }\grabbalanced +}{texline} + +\defy\yypopstate{% + {\bf pop state}% +}{index} + +\defx\yypopstate{pop state}{index:visual} + +\defx\yylexstate{% + \def\setegroup{{\bf state}}% + \def\setpgroup{% + {% + \let\parsernamespace\flexpseudonamespace + \expandafter\nameproc\expandafter{\the\toksa}\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 + \edef\next{{}$\nx\mathop{\hbox{\nx\bf state}}(\hbox{\the\toksd})\,${}% + \gidxentryxb{\termvstring}{\the\toksa}{\the\tokse}}\next + \let\termindex\eatone + }\grabbalanced +}{texline} + +\defy\yylexstate{% + {\bf state}% +}{index} + +\defx\yylexstate{state}{index:visual} diff --git a/support/splint/tex/yyunion.sty b/support/splint/tex/yyunion.sty index d9749a86b9..7f4937a4e3 100644 --- a/support/splint/tex/yyunion.sty +++ b/support/splint/tex/yyunion.sty @@ -1,4 +1,4 @@ -% Copyright 2012-2015, Alexander Shibakov +% Copyright 2012-2020, Alexander Shibakov % This file is part of SPLinT % % SPLinT is free software: you can redistribute it and/or modify @@ -21,6 +21,7 @@ \def\yyuniontag{\yyunion} \def\parserstrictnamespace{parser-strict} \def\parserprototypesnamespace{parser-strict:headers} +\def\parserdebugnamespace{parser-debug} \def\yyunion{\currentyyunionnamespace} \def\currentyyunionnamespace{generic} @@ -29,6 +30,11 @@ % 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 \long\def\stashed#1{} % stashed material (usually \Cee\ code) :: \stashed{tex_string} @@ -40,23 +46,24 @@ \long\def\strm[#1]#2.[#3]{} % a stream element :: \strm[digits]{\stashed|\format|\formatlocal}.[digits] -% types returned by the lexer (* marks the types that get removed by the parser in some cases) +% 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 -\def\midf#1#2{} % rule separator :: \midf{fptr}{sptr} -\defp\stringify#1#2#3#4{} % STRING :: \stringify{12string}{tex_string}{fptr}{sptr} -\defp\idit#1#2#3#4{} % ID :: \idit{12string}{tex_string}{fptr}{sptr} -\defp\tagit#1#2#3#4{} % TAG :: \tagit{12string}{tex_string}{fptr}{sptr} -\defp\charit#1#2#3#4{} % CHAR :: \charit{12string}{tex_string}{fptr}{sptr} \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\flexoptionpair#1#2{} % a flex option :: \flexoptoinpair{\idit}{\idit|\stringify} - -% types inserted by the parser - -% insidemost - \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} @@ -89,6 +96,7 @@ \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} @@ -96,7 +104,7 @@ \defp\precdecls#1#2#3#4#5{} % precedence declarations :: \precdecls{left|right|nonassoc|precedence}{\tagit}{[\idit\stringify\charit]+}{fptr}{sptr} \defp\flexsstatedecls#1#2#3{} % flex state declarations (nonexlusive) :: \flexsstatedecls{[\idit\stringify]+}{fptr}{sptr} \defp\flexxstatedecls#1#2#3{} % flex state declarations (exclusive) :: \flexxstatedecls{[\idit\stringify]+}{fptr}{sptr} -\defp\flexoptiondecls#1#2#3{} % flex state declarations :: \flexoptiondecls{[\flexoptionpair]+}{fptr}{sptr} +\defp\flexoptiondecls#1#2#3{} % flex options :: \flexoptiondecls{[\flexoptionpair]+}{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} @@ -133,17 +141,276 @@ \newtoks\yystashlocal \newtoks\yyformatlocal +% 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 -\def\doparse#1{% - \table{}\typestable{}\prectable{}\opttable{}% - \parserinit\yyparse#1\yyeof\yyeof\endparseinput\endparse +\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 macro +% 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<NUL>} +\tempcb=\uccode`. + +\bloop +\uccode`.=\tempca +\uppercase{\toksb\expandafter{.}}% +\toksa\expandafter\expandafter\expandafter{\expandafter\the\expandafter\toksa\expandafter\or\the\toksb}% +\advance\tempca by\@ne +\ifnum\tempca>"FF + \appendfitotoksa +\else +\repeat + +\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} + +\edef\next{\toksa{\def\noexpand\asciiprint##1{\the\toksa}}}\next +\the\toksa + +\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 +} + +% 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 +} + +\def\gatherstash#1#2\strm[#3]#4.[#5]{% #1 contains the stash gathered + \yystringempty{#3}{ #1}% + {% + \expandafter\g@therstash\expandafter{\romannumeral0\unstash#4}{#1}% + }% +} + +% stash processing wrapper macros + +\def\g@therstash#1#2{\gatherstash{#2#1}} + +\def\unstash#1#2{\expandafter\space#2}% #1 is \stashed or \sflush + +\def\yyreadstash#1\to#2\in#3\with#4{% + \yyreadfifo#1\to#2\in#3% + #4{#3}% + \setbox\z@=\vbox{ + \hsize\maxdimen\emergencystretch\maxdimen + \rightskip\z@ plus 1fill + \insertstash{#3}% + \ifmmode + {}$\aftergroup\yyr@adstash % $o that the box can be finished + \else + \aftergroup\eatthree + \fi + }{#1}{#2}{#3}% +} + +\def\yyr@adstash#1#2#3{% + #3\expandafter{\the#3{}$}% $ + \appendlnx#1{\strm[NaN]{\stashed{{}${}}}.[NaN]}% {}, in case \yystash ends with $ +} + +% the sequence below may be redefined so that the #2 parameter to \yyreadstash may be a list of +% token registers + +\def\insertstash#1{\the#1\relax} + +\def\readstash#1{\yyreadstash\yystash\to#1\in\yystashlocal\with\unpackstash} + +\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\unpackstash +} + +\def\unpackstash#1{#1\expandafter{\romannumeral0\expandafter\unp@ckstash\the#1\strm[].[]}} + +\def\unp@ckstash{\gatherstash{}} + +\def\unwrapstash#1{% to use where only the removal of \strm and \stashed is needed + #1\expandafter{\romannumeral0\expandafter\unwr@pstash\the#1\strm[].[]}% } -\long\def\strm[#1]#2.[#3]{#2} +\def\unwr@pstash{\gatherstash{}} + +% parser invocation + +\def\newparserstateextra{} + +\def\d@parse#1{\yyparse#1\yyeof\yyeof\endparseinput\endparse} + +\def\astarraylastcs{\expandafter\noexpand\romannumeral\gettopofstackcsx\astarray} + +\long\def\strm[#1]#2.[#3]{#2} % this is used with both the format and the stash streams; TODO: deprecate + \long\def\inmath#1{$#1$} -\long\def\stashed#1{\toksa\expandafter{\the\toksa#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 @@ -157,15 +424,6 @@ \let\termindex\eatone } -\def\headeridxrank{1} % index rank of lhs - -\def\writeidxhentry#1{\write\gindex{% - \nx\nx - \expandafter - \nx - \csname\bisonidxdomain TI\endcsname\headeridxrank#1}% -} - \def\prodhead@r#1#2{% \let\idit\prodhdridit #1\relax\concat\table\toksa\hrhss@p @@ -229,45 +487,32 @@ \let\stringify\termnamestringify \let\optstrextra\optstrextraesc \let\termindex\writeidxentry - #1\relax\concat\table\toksa + \termnam@{#1}{#2}% \let\termindex\eatone } -\def\bisonidxdomain{B} % marker fo the domain (section of the index) -\def\termidxrank{2} % rank (affects the order in which the entries are - % listed in the index and the listing style) - -\def\writeidxentry#1{\write\gindex{% - \nx\nx - \expandafter - \nx - \csname\bisonidxdomain TI\endcsname\termidxrank#1}% -} +\def\termnam@#1#2{\toksa{}\toksb{}\toksc{}#1\expandafter\termn@m@\expandafter{\the\toksa}{#2}} -\let\termindex\eatone +\def\termn@m@#1#2{\toksa{}\toksb{}\toksc{}#2\expandafter\t@rmn@m@\expandafter{\the\toksa}{#1}} -% 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 +% several versions of term typesetting -\def\gidxentry#1#2{% a generic index entry - \iftermindex - \termindex{% - {\nx\nx\nx#1{\charstonumberse#2\end}}% - {\hostparsernamespace}{\nx\the\pageno}{\secno}% - }% - \fi +\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$}}}% + \concat\table\toksa } -\def\tidxentry#1#2{% a text index entry - \iftermindex - \write\gindex{% - \nx\nx\expandafter\nx\csname\bisonidxdomain TI\endcsname\termidxrank - {\nx\nx\nx#1{\charstonumberse#2\end}}% - {\indexpseudonamespace}{\nx\the\pageno}{\secno}% - }% - \fi +\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 + }% + \concat\table\toksa } % @@ -278,77 +523,46 @@ \yyreadfifo\yyformat\to#3\in\yyformatlocal \restorecs{table-render}{\strm}% #5% accumulate all the directives - \edef\next{\the\bdirects}% - \ifx\next\empty - \else + \yytoksempty\bdirects{}{% \edef\next{\bdirects{% $\vtop{\halign{\nx\quad####\nx\hfil&####\nx\hfil\cr\the\bdirects}}$}}\next - \fi + }% \the\yyformatlocal \actbrac@s{#1}{#2}{#4}% } \def\actbrac@s#1#2#3{% - \yyreadfifo\yystash\to#3\in\yystashlocal - \unmathstash{#3}% - \edef\next{\toksa{\the\bdirects&\the\yystashlocal\cr}}\next + \readstash{#3}% + \appendr\table{\the\bdirects&\toksa{\the\yystashlocal}\cr}% \bdirects{}% - \concat\table\toksa -} - -\def\unmathstash#1{% - \setbox\z@=\vbox{ - \hsize\maxdimen\emergencystretch\maxdimen - \rightskip\z@ plus 1fill - \let\TeXx\relax\let\stashed\copystashed - \the\yystashlocal\relax - \ifmmode - {}$\aftergroup\unm@thstash % $o that the box can be finished - \else - \aftergroup\eatone - \fi}{#1}% -} - -\def\copystashed#1{#1} - -\def\unm@thstash#1{% - \toksa{\strm[NaN]{\stashed{{}$}}.[NaN]}% $o it cannot be matched if \yystashlocal is read again - \concat\yystashlocal\toksa - \toksa{\strm[#1]{\stashed{${}}}.[#1]}%$ - \appendl\yystash{\the\toksa}% } \def\bpredicate#1#2#3#4#5\bdend{% \yyreadfifo\yyformat\to#3\in\yyformatlocal \restorecs{table-render}{\strm}% #5% accumulate all the directives - \edef\next{\the\bdirects}% - \ifx\next\empty + \yytoksempty\bdirects{% \bdirects{\quad$\dashv\ \nx\vdash$}% - \else + }{% \edef\next{\bdirects{% $\vtop{\halign{\nx\quad####\nx\hfil&####\nx\hfil\cr$\dashv\ $&\omit\nx\hfil$\nx\vdash$\cr \the\bdirects}}$}}\next - \fi + }% \the\yyformatlocal \bpredicat@{#1}{#2}{#4}% } -\def\bpredicat@#1#2#3{% - \yyreadfifo\yystash\to#3\in\yystashlocal - \unmathstash{#3}% - \edef\next{\toksa{\the\bdirects&\the\yystashlocal\cr}}\next +\def\bpredicat@#1#2#3{% + \readstash{#3}% + \appendr\table{\the\bdirects&\toksa{\the\yystashlocal}\cr}% \bdirects{}% - \concat\table\toksa } \def\bdirective#1#2#3#4{% \savecslist{local-namespace}\yyunion \restorecslist{table-render:directives}\yyunion - \toksa{}% - #2% make a directive list - \edef\next{\toksa{$\nx\langle${\ntt #1} &\the\toksa$\nx\rangle$\cr}}\next - \concat\bdirects\toksa + \toksa{}#2% make a directive list + \appendr\bdirects{$\nx\langle${\ntt #1} &\the\toksa$\nx\rangle$\nx\cr}% \restorecslist{local-namespace}\yyunion } @@ -379,34 +593,43 @@ \let\currentrulecontext\empty -\def\emptyterm{% - \edef\next{\toksa{$\nx\circ$\tidxentry{\termidstring}{emptyrhs}}}\next - \concat\table\toksa -} +% 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\emptyterm{\appendr\table{$\nx\circ$\tidxentry{\termexception}{emptyrhs&}}} \def\termnameidit#1#2#3#4{% \yyreadfifot\yyformat\to#3\in\yyformatlocal\with\formatsort\relax \the\yyformatlocal - \nameproc{#2}% - \peekstash{#4}% - \settermstyle{#1}% + \nameproc{#2}\with\parsebin + \peekstash{#4}% does not clobber \toksa and \toksb + \expandafter\settermstyle\expandafter{\the\toksb}{#1}% } -\def\settermstyle#1{% - \edef\next{\toksa{\termmetastyle{% - \gidxentry{\termidstring}{#1}% - \let\nx\idxfont\nx\empty\nx\it\the\toksa\nx\/% - }}}\next -} - -\def\idxinline#1{% index the term in text - \edef\next{\tidxentry{\termidstring}{#1}}\next +\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}% + \nameproc{#2}\with\parsebin + \ifyyparsefail + \toksb{"#1"}\toksc{\termstring}% + \else + \toksc{\termidstring}% + \fi \edef\next{\toksa{{% - \gidxentry{\termstring}{#1}% + \expandafter\gidxentryxv\expandafter{\the\toksc}{#1}{\the\toksb}% \ntt\the\toksa }}}\next } @@ -418,31 +641,39 @@ \newif\ifinheader \def\prodhdridit#1#2#3#4{% - \setrulecontext{}% - \nameproc{#2}% - \expandafter\setrulecontext\expandafter{\the\toksc}% + \setrulecontext{}% TODO: ? + \nameproc{#2}\with\parsebin + \setrulecontext{#1}% \edef\next{\toksa{{% - \gidxentry{\termhdrstring}{#1}% + \gidxentryxv{\termidstring}{#1}{\the\toksb}% \nx\inheadertrue\let\nx\idxfont\nx\bf\nx\itbold\the\toksa\nx\/% }}}\next } \def\charit#1#2#3#4{% - \expandafter\ifx\csname'parser'\hostparsernamespace#1\endcsname\relax - \edef\next{\toksa{{\ntt #1}\gidxentry{\termvstring}{'#1'}}}% + \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'parser'\hostparsernamespace#1\endcsname{\currentrulecontext}\gidxentry{\termvstring}{'#1'}}}% + %\csname\prettynamecs\hostparsernamespace{#1}\endcsname{\currentrulecontext}\gidxentryxv{\termvstring}{'#1'}{\the\tokse}}}% + \csname\prettynamecs\hostparsernamespace{#1}\endcsname{\currentrulecontext}\gidxentryxv{\termidstring}{'#1'}{\the\tokse}}}% \fi \next } \def\anint#1#2#3{% - \toksa{#1}\concat\table\toksa + \appendrnx\table{#1}% } \def\hexint#1#2#3{% - \toksa\expandafter{\eattwo#1$_{16}$}\concat\table\toksa + \expandafter\appendrnx\expandafter\table\expandafter{\eattwo#1$_{16}$}% } \def\optoptsepnone{% @@ -451,22 +682,22 @@ \def\optoptsepsmall{% keep the alignment going but insert a small space \concat\opttable\postoks - \toksa{\noalign{\smallskip}}\concat\opttable\toksa + \appendrnx\opttable{\noalign{\smallskip}}% } \def\prodprodsepsmall{% \pushothertables - \toksa{\noalign{\penalty-150 \smallskip}}\concat\table\toksa + \appendrnx\table{\noalign{\penalty-150 \smallskip}}% } \def\prodprodsep{% \pushothertables - \toksa{\noalign{\medskip}}\concat\table\toksa + \appendrnx\table{\noalign{\medskip}}% } \def\prodprodseplarge{% \pushothertables - \toksa{\noalign{\bigskip}}\concat\table\toksa + \appendrnx\table{\noalign{\bigskip}}% } \def\separatorswitcheq{% @@ -532,28 +763,22 @@ \def\posmark#1#2{% % \yyreadfifo\yyformat\to#1\in\yyformatlocal -% no formattig for locations currently - \restorecs{table-render}{\strm}% +% no formatting for locations currently % \the\yyformatlocal \posm@rk{#2}% } \def\posm@rk#1{% - \yyreadfifo\yystash\to#1\in\yystashlocal - \edef\next{\the\yystashlocal}% - \ifx\next\empty - \postoks{}% - \else - \unmathstash{#1}% - % TODO: move this out - \toksa{}\the\yystashlocal\cleanstash\stripstash + \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 + \edef\next{\postoks{\noalign{\indent\toksa{\the\yystashlocal}\nx\makestashbox}}}\next \fi - \fi + }% } \def\codeoptionlist{% @@ -608,29 +833,13 @@ \def\pushothertables{% %token's - \edef\next{\the\tokdectoks}% - \ifx\next\empty - \else - \attachtokentable - \fi + \yytoksempty\tokdectoks{}{\attachtokentable}% %type's - \edef\next{\the\typestable}% - \ifx\next\empty - \else - \attachtypestable - \fi + \yytoksempty\typestable{}{\attachtypestable}% %precedence's - \edef\next{\the\prectable}% - \ifx\next\empty - \else - \attachprectable - \fi + \yytoksempty\prectable{}{\attachprectable}% % options - \edef\next{\the\opttable}% - \ifx\next\empty - \else - \attachoptionstable - \fi + \yytoksempty\opttable{}{\attachoptionstable}% \concat\table\postoks } % @@ -643,8 +852,7 @@ \savecslist{local-namespace}{\yyunion\termindex}% \restorecslist{table-render:token-declarations}\yyunion \let\termindex\writetokenidxentry - \displaytokenrawtrue - \let\currenttokentype\empty#1% + \let\currenttokentype\empty#1% \restorecslist{local-namespace}{\yyunion\termindex}% } @@ -652,31 +860,29 @@ \savecslist{local-namespace}{\yyunion\termindex}% \restorecslist{table-render:type-declarations}\yyunion \let\termindex\writetokenidxentry - \typesset{}% - #2\relax#1% - \edef\next{\typestable{\the\typestable\nx\onetype{\the\toksa}{\the\typesset}}}\next + \typesset{}#2\relax#1% + \appendr\typestable{\nx\onetype{\the\toksa}{\the\typesset}}% \restorecslist{local-namespace}{\yyunion\termindex}% } % \onetype is a typeseting macro defined elsewhere +% TODO: move these to the \flex\ section \def\flexsstatedecls#1#2#3{% \savecslist{local-namespace}{\yyunion\termindex}% \restorecslist{table-render:flex-state-declarations}\yyunion - \let\termindex\writetokenidxentry - \typesset{}% - #1\relax - \edef\next{\typestable{\the\typestable\nx\flexsstatelist{\the\typesset}}}\next + \let\termindex\writeidxfsdentry%\writetokenidxentry + \typesset{}#1\relax + \appendr\typestable{\nx\flexsstatelist{\the\typesset}}% \restorecslist{local-namespace}{\yyunion\termindex}% } \def\flexxstatedecls#1#2#3{% \savecslist{local-namespace}{\yyunion\termindex}% \restorecslist{table-render:flex-state-declarations}\yyunion - \let\termindex\writetokenidxentry - \typesset{}% - #1\relax - \edef\next{\typestable{\the\typestable\nx\flexxstatelist{\the\typesset}}}\next + \let\termindex\writeidxfsdentry%\writetokenidxentry + \typesset{}#1\relax + \appendr\typestable{\nx\flexxstatelist{\the\typesset}}% \restorecslist{local-namespace}{\yyunion\termindex}% } @@ -685,9 +891,8 @@ \def\flexoptiondecls#1#2#3{% \savecslist{local-namespace}{\yyunion\termindex}% \restorecslist{table-render:flex-option-definitions}\yyunion - \let\termindex\writetokenidxentry - \toksa{}% - #1\relax + \let\termindex\writeidxfsrnentry%\writetokenidxentry + \toksa{}#1\relax \restorecslist{local-namespace}{\yyunion\termindex}% } @@ -700,8 +905,8 @@ \restorecslist{table-render:prec-declarations}\yyunion \setrulecontext{*#1}% \let\termindex\writetokenidxentry - \typesset{}#3\toksa{}#2% - \edef\next{\prectable{\the\prectable\noexpand\oneprec{#1}{\the\toksa}{\the\typesset}}}\next + \typesset{}#3\toksa{}#2% + \appendr\prectable{\nx\oneprec{#1}{\the\toksa}{\the\typesset}}% \restorecslist{local-namespace}{\yyunion\termindex}% \setrulecontext{}% } @@ -712,52 +917,45 @@ \def\oneparametricoption#1#2#3#4{% \restorecs{table-render:token-declarations}{\braceit\stringify\idit\anint\hexint}% - \toksa{}\toksb{}\toksc{}% - #2% - \edef\next{\noexpand\oneparametricopti@n{#1}{\the\toksa}{\the\toksb}{\the\toksc}}\next + \toksa{}\toksb{}\toksc{}#2% + \edef\next{\nx\oneparametricopti@n{#1}{\the\toksa}{\the\toksb}{\the\toksc}}\next } \def\oneparametricopti@n#1#2#3#4{% - \edef\next{#2}% - \ifx\next\empty % there is no identifier - \def\next{#4}% - \ifx\next\empty % there is no digit + \yystringempty{#2}{% there is no identifier + \yystringempty{#4}{% there is no digit \edef\next{\toksa{{\ntt"\the\toksb"}}}\next - \else + }{% \edef\next{\toksa{{\nx\rm\the\toksc}}}\next - \fi - \else - \nameproc{#2}% - \fi % now \toksa contains the value of the parameter + }% + }{% + \nameproc{#2}\with\parsebin + }% now \toksa contains the value of the parameter \toksb{#1}% \let\termindex\writetokenidxentry - \edef\next{\toksa{\gidxentry{\termostring}{#1}$\nx\langle${\nx\bf\the\toksb}$\nx\rangle$&\the\toksa\nx\/\nx\cr}}\next + \appendr\opttable{\gidxentry{\termostring}{#1}{}$\nx\langle${\nx\bf\the\toksb}$\nx\rangle$&\the\toksa\nx\/\nx\cr}% \let\termindex\eatone - \concat\opttable\toksa } \def\paramdef#1#2#3#4{% \restorecs{table-render:token-declarations}\braceit \let\termindex\writetokenidxentry - \edef\next{\toksa{\gidxentry{\termostring}{#2}}}\next - \toksb\expandafter{\the\toksa$\langle${\bf #2}$\rangle$}\toksa{}% - #1% + \appendr\opttable{\gidxentry{\termostring}{#2}{}}% \let\termindex\eatone - \concat\toksb\toksa - \concat\opttable\toksb + \appendrnx\opttable{$\langle${\bf #2}$\rangle$}% + \toksa{}#1% + \concat\opttable\toksa } \def\optionflag#1#2#3#4{% - \def\next{#2}% - \ifx\next\empty - \toksb{}% - \else - \toksb{ {\rm(set as $\langle${\bf#2}$\rangle$)}}% - \fi \let\termindex\writetokenidxentry - \edef\next{\toksa{\gidxentry{\termostring}{#1}$\nx\langle${\nx\bf#1}$\nx\rangle$\nx\rlap{$\nx\,\star$}&\the\toksb\cr}}\next + \appendr\opttable{\gidxentry{\termostring}{#1}{}}% \let\termindex\eatone - \concat\opttable\toksa + \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{% @@ -768,21 +966,18 @@ } \def\codepropstyp@#1#2#3#4{% - \yyreadfifo\yystash\to#4\in\yystashlocal - \unmathstash{#4}% + \readstash{#4}% \restorecs{table-render:type-declarations}{\idit\stringify\hspace}% \let\termindex\writetokenidxentry - \typesset{}% - #2% collect all the symbols in \typesset - \edef\next{\toksa{\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}$}% - }}\next + \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 - \concat\opttable\toksa } \def\codeassoc#1#2#3#4#5#6#7{% @@ -793,20 +988,15 @@ } \def\codeass@c#1#2#3#4{% - \yyreadfifo\yystash\to#4\in\yystashlocal - \unmathstash{#4}% + \readstash{#4}% \let\idit\termnameidit \let\termindex\writetokenidxentry - \toksa{}% in case #1 is empty - #2% put the typeset form of the identifie in \toksa - \toksb\toksa - \edef\next{\toksa{\yystringempty{#1}{}{\gidxentry{\termostring}{#1}}% - $\nx\langle${\nx\bf #1}$\nx\rangle$\nx\quad{\the\toksb}&% - \toksa{}\the\yystashlocal - \nx\makestashbox - \nx\hfil\cr - }}\next - \concat\opttable\toksa + \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 } @@ -821,35 +1011,29 @@ \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{}% in case #2 is empty - #2% put the value in toksa - \toksc\toksa - \restorecslist{local-namespace}\yyunion + #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 - \edef\next{\toksa{$\nx\langle${\nx\bf define}$\nx\rangle$\nx\quad{\the\toksb}&% - \the\toksc\cr - }}\next - \concat\opttable\toksa + \appendr\opttable{$\nx\langle${\nx\bf define}$\nx\rangle$\nx\quad{\the\toksb}&\the\toksc\cr}% } \def\prologuecode#1#2#3#4#5{% similar to \actbrac@s - \yyreadfifo\yystash\to#5\in\yystashlocal - \unmathstash{#5}% - \restorecs{table-render}{\strm\stashed}% - \toksa{}\the\yystashlocal - \edef\next{\toksa{\omit\span\omit\nx\cdotfill\cr - \omit\span\omit\toksa{\the\toksa}\nx\makestashbox\nx\cr - \omit\span\omit\nx\cdotfill\cr}}\next - \concat\opttable\toksa + \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{% - \strm\stashed\rarhss@p\rrhss@p\prodhead@r\hrhss@p\arhss@p\actbrac@s\hspac@\codepropstyp@\vard@f\stopproduction - \termmetastyle\peekstash + \strm\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 @@ -868,10 +1052,16 @@ #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 @@ -881,45 +1071,44 @@ } \def\actbrac@s@flatten#1#2#3{% do everything but add the stash contents to the table - \yyreadfifo\yystash\to#3\in\yystashlocal - \unmathstash{#3}% - \yystashlastcontent\yystashlocal + \readstash{#3}% + \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\actbrac@s@fl@tten{% \ifx\actsep\arhssep - \edef\next{% - \toksa{$\nx\ \nx\diamond\nx\ $\tidxentry{\termidstring}{inline_action}}}\next - \concat\table\toksa + \appendr\table{$\nx\ \nx\diamond\nx\ $\tidxentry{\termexception}{inline_action&}}% \fi } \def\rrhss@p@flatten{% - \toksa{$\ \vert\ $}\concat\table\toksa + \appendrnx\table{$\ \vert\ $}% }% \def\stopproduction@flatten{% \ifshowlastaction - \toksa\yystashlastcontent + \yystashlastcontent\expandafter{\expandafter\toksa\expandafter{\the\yystashlastcontent}}% \else - \toksa{\actionfiller}% + \yystashlastcontent{\actionfiller}% \fi - \toksa\expandafter{\expandafter&\expandafter&\the\toksa\cr}\concat\table\toksa + \appendr\table{&&\the\yystashlastcontent\nx\cr}% } +% fold: resume normal display + \def\fold{% \restorecs{table-render}{\actbrac@s\rrhss@p\arhss@p\rarhss@p\stopproduction}% - \ifshowlastaction - \toksa\yystashlastcontent - \else - \toksa{\actionfiller}% - \fi - \toksa\expandafter{\expandafter&\expandafter&\the\toksa\cr}\concat\table\toksa + \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 @@ -928,10 +1117,10 @@ \def\prodhead@r@inline#1#2{% \let\idit\prodhdridit #1\relax + \concat\table\toksa \setbox\z@=\hbox{\strut\the\toksa\/$\,$\rm:\quad}% \tempda=\wd\z@\relax \advance\tempda-2em - \edef\next{\table{\the\table{\the\toksa}}}\next \hrhss@p } @@ -940,18 +1129,45 @@ \def\termspostformat{\ifsquashterms\aftergroup\noexpand\squashtermstrue\fi} \def\hrhss@p@inline{% - \edef\next{\toksa{&\termspostformat\hbox to \the\tempda{\hss}}}\next\concat\table\toksa + \appendr\table{&\termspostformat\hbox to \the\tempda{\hss}}% } +% breakline: break the production line + \def\breakline{% \let\hspac@\hspac@@breakline } \def\hspac@@breakline{% - \toksa{{$\,\hookleftarrow$}&\omit\hfil&\omit\hfil\cr\omit\hfil&\hbox to 2em{\hfil}}\concat\table\toksa + \appendrnx\table{{$\,\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{% + \appendrnx\table{{$\,\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 @@ -961,34 +1177,85 @@ \hrhss@p } -\def\hrhss@p@skipheader{\toksa{\omit\hbox to 2em{\hfil}&\termspostformat}\concat\table\toksa\restorecs{table-render}{\hrhss@p}} +\def\hrhss@p@skipheader{\appendrnx\table{\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 - \yyreadfifo\yystash\to#1\in\yystashlocal - \unmathstash{#1}% - \edef\next{\toksb{{% - \nx\restorecs{table-render}{\nx\stashed\nx\strm}% - \toksa{}\the\yystashlocal\nx\makestashbox}}}\next - \def\termmetastyle##1{\the\toksb}% + \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\strm\stopproduction}% \squashtermsfalse } -\def\prodstyle#1{% to typeset token names in text +\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 - \nameproc{#1}% - \settermstyle{#1}% + \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 @@ -1007,7 +1274,7 @@ } \def\hspace#1#2{% - \appendr\typesset{ }% + \appendrnx\typesset{ }% } \def\charit#1#2#3#4{% @@ -1044,11 +1311,8 @@ } \def\braceit#1#2#3{% similar to \actbrac@s - \yyreadfifo\yystash\to#3\in\yystashlocal - \unmathstash{#3}% - \restorecs{table-render}{\strm\stashed}% - \toksa{}\the\yystashlocal - \edef\next{\toksa{&\toksa{\the\toksa}\nx\makestashbox\nx\cr}}\next + \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{}{}{}{}) @@ -1056,42 +1320,42 @@ % #3 is the string value (\stringify{}{}{}{}) \toksa{}\toksb{}\toksc{}% #1#2#3\relax - \edef\next{\noexpand\onesymb@l{\the\toksa}{\the\toksc}{\the\toksb}}\next + \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 - \yystringempty{#3}{}{\nameproc{#3}\tokstoks\toksa}% - \yystringempty{#1}{}{\nameproc{#1}}% - \iftracetokennames\derrmessage{token: \the\toksa, string: \the\tokstoks}\fi + \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}% - \edef\next{% - \tokdectoks{\the\tokdectoks - \noexpand\toksdefline - {\the\toksa}% - {% - \yystringempty{#1}{}{\gidxentry{\termidstring}{#1}}% - \yystringempty{#3}{}{\gidxentry{\termstring}{#3}}% - }% - {\yytoksempty\toksb{auto}{\the\toksb}}% - {#2}% - {\the\tokstoks}% - }% - }\next + \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}% } -\def\defidxrank{0} % index rank of definitions - -\def\writetokenidxentry#1{\write\gindex{% - \nx\nx - \expandafter - \nx - \csname\bisonidxdomain TI\endcsname\defidxrank#1}% -} - \toyyunion{table-render:token-declarations} %precedence declarations @@ -1109,29 +1373,35 @@ } \def\charit#1#2#3#4{% - \expandafter\ifx\csname'parser'\hostparsernamespace#1\endcsname\relax - \edef\next{\toksa{{\ntt #1}\gidxentry{\termvstring}{'#1'}}}% + \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'parser'\hostparsernamespace#1\endcsname{\currentrulecontext}\gidxentry{\termvstring}{'#1'}}}% + %\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 } \def\anint#1#2#3{% - \edef\next{\toksa{${}=\hbox{\ntt#1}$}}\next - \concat\typesset\toksa + \appendrnx\typesset{${}=\hbox{\ntt#1}$}% } \def\hexint#1#2#3{% \toksa\expandafter{\eattwo#1}% - \edef\next{\toksa{${}=\hbox{\ntt\the\toksa}_{16}$}}\next - \concat\typesset\toksa + \appendr\typesset{${}=\hbox{\ntt\the\toksa}_{16}$}% } \def\hspace#1#2{% - \appendr\typesset{ }% + \appendrnx\typesset{ }% } \def\tagit#1#2#3#4{% @@ -1153,11 +1423,8 @@ \def\stringify#1#2#3#4{\toksa{#2}} \def\bracedvalue#1#2#3{% similar to \actbrac@s - \yyreadfifo\yystash\to#3\in\yystashlocal - \unmathstash{#3}% - \restorecs{table-render}{\strm\stashed}% - \toksa{}\the\yystashlocal - \edef\next{\toksa{\toksa{\the\toksa}\nx\makestashbox}}\next + \readstash{#3}% + \edef\next{\toksa{\toksa{\the\yystashlocal}\nx\makestashbox}}\next } \toyyunion{table-render:variable-definitions} @@ -1193,12 +1460,11 @@ \restorecslist{parser-strict}\yyunion \def\idit#1#2#3#4{% - \nameproc{#2}% - \edef\next{\toksa{{% - \gidxentry{\termttstring}{#1}% + \nameproc{#2}\with\parsebin + \appendr\typesset{{% + \gidxentryxv{\termttstring}{#1}{\the\toksb}% \ntt\the\toksa - }}}\next - \concat\typesset\toksa + }}% } \def\hspace#1#2{% @@ -1213,17 +1479,21 @@ \def\flexoptionpair#1#2{% #1% - \edef\next{#2}% - \ifx\next\empty % there is no rihgt hand side - \edef\next{\toksa{$\nx\langle${\ntt\the\toksa}$\nx\rangle_{\rm f}\,\star$&\cr}}\next - \else + \yystringempty{#2}{% there is no right hand side + \appendr\opttable{$\nx\langle${\ntt\the\toksa}$\nx\rangle_{\rm f}\,\star$&\cr}% + }{% \toksb\toksa\toksa{}#2% - \edef\next{\toksa{$\nx\langle${\ntt\the\toksb}$\nx\rangle_{\rm f}$&\nx\it\the\toksa\nx\/\nx\cr}}\next - \fi - \concat\opttable\toksa + \appendr\opttable{$\nx\langle${\ntt\the\toksb}$\nx\rangle_{\rm f}$&\nx\it\the\toksa\nx\/\nx\cr}% + }% } -\def\idit#1#2#3#4{\toksa{#2}} +\def\idit#1#2#3#4{% + \toksa{#2}% + \edef\next{\toksa{{% + \gidxentry{\termfsopstring}{#2}{}% + \ntt\the\toksa + }}}\next +} \def\stringify#1#2#3#4{\toksa{{\ntt@"#2"}}} @@ -1244,10 +1514,13 @@ \edef\next{\toksc{\numname:}\toksd{\noexpand\lhs{\the\lastlastname}{\the\lastname}}}\next } -\def\rrhssep#1#2{} -\def\arhssep#1#2{} -\def\rarhssep#1#2{} -\def\hspace#1#2{} +% the macros below are defined in `parser-prototypes' +%\def\rrhssep#1#2{} +%\def\arhssep#1#2{} +%\def\rarhssep#1#2{} +%\def\hspace#1#2{} +%\def\prodprodsep{} +%\def\onesymbol#1#2#3{} \def\rhs#1#2#3{% \concat\toksa\toksc @@ -1317,10 +1590,6 @@ \lastname{'#1'}% } -\def\prodprodsep{} - -\def\onesymbol#1#2#3{} - \def\anint#1#2#3{% \lastname{#1}% } @@ -1342,119 +1611,72 @@ \savecslist{symbols}\yyunion -% name parser macros +%% token typesetting macros -\def\idstr#1#2{% - \toksb{#1}% - \concat\toksa\toksb - \toksb{#2}% - \concat\toksc\toksb -} +\def\prettynamecs#1#2{'parser'#1#2} % naming convention for token typesetting alternatives -\def\chstr#1#2{% - \toksb{{\ntt@#1}}% - \concat\toksa\toksb - \toksb{#2}% - \concat\toksc\toksb +\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\sfxi#1#2{\toksb{\/${}_{\idxfont#1}$}\concat\toksa\toksb} - -\def\sfxn#1#2{\toksb{#1}\concat\toksa\toksb} +\def\prettywordpair@@#1#2{\setsafe{#1}\expandafter\def\csname\prettynamecs\parsernamespace\saferword\endcsname##1{#2}} -\def\dotsp{\futurelet\next\d@tsp} +\def\prettywordpair#1#2{\prettywordpair@@{#1}{{\ntt@#2}}} -\def\d@tsp{% - \ifx\next\sfxi - \else - \ifx\next\qual - \else - \toksb{.}\concat\toksa\toksb - \fi - \fi +\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\optstr#1#2{% - \toksb\expandafter{\eatone#1}% - \optstrextra - \concat\toksa\toksb - \toksb{#2}% - \concat\toksc\toksb +\def\prettywordpairwvis#1#2#3{% + \prettywordpair{#1}{#2}% + \expandafter\def\csname\viskeyref\parsernamespace{\saferword}\endcsname##1{#3}% } -\def\optstrextra{% - \edef\next{\toksb{{$\nx\ulcorner$\ntt\the\toksb$\nx\urcorner$}}}\next +\def\prettywordpair@wvis#1#2#3{% + \prettywordpair@{#1}{#2}% + \expandafter\def\csname\viskeyref\parsernamespace{\saferword}\endcsname##1{#3}% } -\def\optstrextraesc{% - \edef\next{\toksb{{$\nx\langle$\ntt\the\toksb$\nx\rangle$}}}\next +\def\prettywordpair@@wvis#1#2#3{% + \prettywordpair@@{#1}{#2}% + \expandafter\def\csname\viskeyref\parsernamespace{\saferword}\endcsname##1{#3}% } -\def\qual#1#2{\toksb{\/${}_{\rm#2}$}\concat\toksd\toksb} - -\let\idxfont\relax - -\savecs{nameparser}{\idstr\chstr\sfxi\sfxn\qual\optstr\dotsp\optstringextra\idxfont} +% a control sequence to reuse the token definition file for typesetting -\newtoks\namechars +\newif\iftraceprettytokens % display prettyfying control sequences -\newif\iftracebadnames -\newif\iftracenames - -\def\nameproc#1{% - \ifbootstrapmode - \toksa{}% +\def\tokeneqpretty#1#2{% + \setsafe{#1}\toksa{}\numberstocharsandspaces#2\end + \expandafter\nameproc\expandafter{\the\toksa}\with\parsebin + \ifyyparsefail + \toksc{{}$_{\rm m}${}}\toksd\toksa \else - \savecs{local-namespace}\getcurrentparser - \tosmallparser - \basicparserinit - \yyparse#1\yyeof\yyeof\endparseinput\endparse - \ifyyparsefail - \iftracebadnames - \ferrmessage{bad name: #1}% - \fi - \toksa{#1}\toksc{}% - \else - \toksa{}\toksb{}\toksc{}\toksd{}% - \iftracenames - \ferrmessage{parsed name: \the\namechars}% - \fi - \the\namechars\relax - \iftracenames - \ferrmessage{processed name: \the\toksa<identifier>, \the\toksb<suffices>, \the\toksc<hash name>, \the\toksd<options>}% - \fi - \expandafter\ifx\csname'parser'\hostparsernamespace\the\toksc \endcsname\relax - \else - \toksa\expandafter{\csname'parser'\hostparsernamespace\the\toksc \endcsname}% - \appendr\toksa{{\currentrulecontext}}% - \fi - \concat\toksa\toksd - \fi - \restorecs{local-namespace}\getcurrentparser - \getcurrentparser + \toksc{}\toksd\toksb % quotes should trigger the creation of a visible key \fi -} - -%% token typesetting macros - -\def\setsafe#1{\def\saferword{#1}\setspecialcharsfrom\saferword} -\def\prettyword#1{\setsafe{#1}\expandafter\edef\csname'parser'\parsernamespace\saferword\endcsname##1{{\ntt\lowercase{\saferword}}}} -\def\prettytoken#1{\setsafe{#1}\expandafter\edef\csname'parser'\parsernamespace\saferword\endcsname##1{{\ntt\saferword}}} -\def\prettytoken@#1{\toksa{}\numberstocharsandspaces#1\end\expandafter\edef - \csname'parser'\parsernamespace\the\toksa\endcsname##1{{\ntt\the\toksa}}% -} -\def\prettywordpair#1#2{\setsafe{#1}\expandafter\def\csname'parser'\parsernamespace\saferword\endcsname##1{{\ntt@#2}}} -\def\prettywordpair@#1#2{% - \setsafe{#1}\toksa{}\numberstocharsandspaces#2\end\expandafter\nameproc\expandafter{\the\toksa}% - \expandafter\edef\csname'parser'\parsernamespace\saferword\endcsname##1{% + \expandafter\edef\csname\prettynamecs\parsernamespace\saferword\endcsname##1{% \noexpand\ifdisplaytokenraw {\ntt\saferword}% \noexpand\else - {\ntt\def\noexpand\_{\char`\noexpand\_}\the\toksa}% + {\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 } -\def\prettywordpair@@#1#2{\setsafe{#1}\expandafter\def\csname'parser'\parsernamespace\saferword\endcsname##1{{#2}}} % the bootstrap macros @@ -1471,7 +1693,7 @@ \def\idit#1#2#3#4{\toksb{#1}} %\def\anint#1#2#3{\toksc{#1}}% this definition is not needed as all - %information is extracted from yytname + % 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 '{' @@ -1509,15 +1731,923 @@ \savecslist{bootstrap:flex-state-declarations}\yyunion -\def\charstonumberse#1\end{% - \yystringempty{#1}{}% - {\yystartsinspace{#1}{{\number`\ }\charstonumber@@#1\end}{\charstonumbers@#1\end}}% +% correct a few macros for debugging + +\restorecslist{parser-debug}\yyunion + +\defc\actbraces{% action braces :: \actbraces{tex_string}{\idit|<nothing>}{fptr}{sptr}directive*\bdend + \noexpand\actbraces{#1}{#2}{#3}{#4}#5\noexpand\bdend +} + +\defc\bpredicate{% predicate :: \bpredicate{tex_string}{<nothing>}{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|<nothing>}{\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\charstonumbers@#1{% - {\number`#1}\charstonumberse +\def\charstonumb@rsr@#1\end#2{% + \expandafter\charstonumbersr@swap\expandafter{\number`#2}{#1}% } -\def\charstonumber@@#1 {\charstonumberse} +\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; +% 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<identifier>, \the\toksb<suffices>, % + \the\toksc<hash name>, \the\toksd<options>, \the\tokse<visible key>}% + \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\frexproc#1\with#2{% + {% keeping all changes local + \iftracenames + \toksa{#1}\ferrmessage{original regex: \the\toksa}% + \fi + \toflexreparser + \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{% + \restorecslist{flexparser-sect2}\yyflunion +} + +\def\setregexdeftable{% + \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 not been implemented (see yyunion.sty).} +} + +\defc\flretrail{%#1#2#3% regular expression with a trailing context :: \flretrail{re}{{fptr}{sptr}}{re} + \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 + \hbox{\tt#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{\termvstring}{#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}% +} + +\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 \flsconslist (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 + \yytoksempty\table{}{\appendrnx\table{\noalign{\medskip}}}% + \concat\table\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 + #2% collect the state names (and the stash in between) + \readstashwredirect#3\toksf + \appendr\toksb{\nx\rm\toksa{\the\toksf}\nx\makestashbox}% +} + +\defc\flname{% #1#2#3#4% name :: \flname{name}{name12}{fptr}{sptr} + {% + \let\parsernamespace\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\writeidxfsentry + \readstashwredirect{}{#4}\toksf % do not touch \yystashlocal + \appendr\toksb{{\nx\rm\toksa{\the\toksf}\nx\makestashbox}% + \the\toksd\gidxentryxv{\termvstring}{#1}{\the\tokse}}% + \let\termindex\eatone +} + +\defc\flnamesep{%#1#2% separator between names :: \flnamesep{fptr}{sptr} + \toksb\expandafter{\the\toksb\ }% +} + +\newskip\rgindent + +\rgindent=\parindent + +\defc\flaction{%#1#2#3#4#5#6#7% \flex action :: \flaction{\flsconlist...}{\fl..rule ...}{fptr}{sptr}{fptr}{sptr}{formatting command} + \toksb{}#1% + \toksc{}#2% + #7% apply formatting + \readstash{#6}% read stash late, after \flsconlist and \fl...rule + \yytoksempty\toksb{% + \appendr\table{\hskip\the\rgindent\hbox{\nx\tt\nx\strut\the\toksc}}% + }{% + \appendr\table{% + \hskip\the\rgindent + \vbox{% + {\nx\sscmd\nx\expandafter}\nx\expandafter\baselineskip\nx\the\baselineskip + \halign{&####\hfil\cr + \hbox to\rgindent{\nx\sscmd\nx\tt\nx\strut\the\toksb\hss}\cr + \nx\tt\nx\strut\the\toksc\cr + }% + }% + }% + }% + \appendr\table{&\toksa{\relax\the\yystashlocal}\nx\cr}% +} + +\defc\flactionc{%#1#2#3#4#5#6#7% \flex continued action :: \flaction{\flsconlist...}{\fl..rule ...}{fptr}{sptr}{fptr}{sptr}{formatting command} + \toksb{}#1% + \toksc{}#2% + \readstash{#6}% read stash late, after \flsconlist and \fl...rule + #7% apply formatting + \yytoksempty\toksb{% + \appendr\table{\hskip\the\rgindent\hbox{\nx\tt\nx\strut\the\toksc}}% + }{% + \appendr\table{% + \hskip\the\rgindent + \vbox{% + {\nx\sscmd\nx\expandafter}\nx\expandafter\baselineskip\nx\the\baselineskip + \halign{&####\hfil\cr + \hbox to\rgindent{\nx\sscmd\nx\tt\nx\strut\the\toksb\hss}\cr + \nx\tt\nx\strut\the\toksc\cr + }% + }% + }% + }% + \appendr\table{&\toksa{{}$\nx\hookleftarrow$\relax\the\yystashlocal}\nx\cr}% in the event \cr has been redefined +} + +\def\inscomment#1{% + \def\astformat@flaction{% + \toksd{#1}% + \appendr\table{\noalign{\nx\smallskip\noindent\hskip\the\rgindent + $\nx\triangleright\;$\the\toksd\nx\smallskip}}% + }% +} + +\let\astformat@flaction\empty + +\toyyunion{flexparser-sect2} + +% \flex\ setion~1 typesetting +% currently, all \flex\state declarations are handled by an extended \bison\ parser +% to collect the state data; we thus only implement regular expression definitions; + +\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 + \appendr\table{{}$\nx\langle\hbox{\ntt\the\toksd}\nx\rangle${}% + \gidxentryxv{\termfsrestring}{#1}{\the\tokse}&\the\toksc\cr% TODO: make a special type processor for regex names + }% + \let\termindex\eatone +} + +\defc\flopt{%#1#2#3#4#5% \flex option :: \flopt{option}{text}{text12}{fptr}{sptr} + \csname flex@ption_#1\endcsname{#2}{#3}% +} + +\expandafter\def\csname flex@ption_deprecated\endcsname#1#2{% + \flex@opt@deprecated#2% +} + +\def\flex@opt@deprecated#1#2#3^^J{% + \let\termindex\writeidxfsrnentry + \appendr\table{$\langle${\nx\tt #2}$\rangle_{\rm f}$\gidxentryxv{\termfsopstring}{#2}{#2}% + \the\toksg&\number\flexgetnumber#3.\nx\cr}% + \let\termindex\empty +} + +\def\flexgetnumber#1{% + \ifnum`#1<"3A + \yybreak{% + \ifnum`#1>"2F + \yybreak{#1\flexgetnumber}% + \else + \yybreak{% + \ifnum`#1="20 + \yybreak{\flexgetnumber}% + \else + \yybreak{}% + \yycontinue + } + \yycontinue + }% + \else + \yybreak{}% + \yycontinue +} + +\toyyunion{flexparser-sect1} + +% correct a few sequences for debugging purposes + +\restorecslist{flexparser-debug}\yyflunion + +\defc\flnametok{%#1#2% named definition :: \flnametok{matched text}{formatting command}, the text is \{text\}\ * + \noexpand\flnametok{#1}{}% +} + +\defc\flparens{%#1#2#3#4% parenthesized regular expression :: \flparens{{fptr}{sptr}}{re}{{fptr}{sptr}}{formatting command} + \noexpand\flparens{#1}{#2}{#3}{}% +} + +\defc\flrule{%#1#2% full regular expression :: \flrule{re}{formatting command} + \noexpand\flrule{#1}{}% +} + +\defc\flbolrule{%#1#2% full regular expression at the beginning of the line :: \flbolrule{re}{formatting command} + \noexpand\flbolrule{#1}{}% +} + +\defc\flaction{%#1#2#3#4#5#6#7% \flex action :: \flaction{\flsconlist...}{\fl..rule ...}{fptr}{sptr}{fptr}{sptr}{formatting command} + \noexpand\flaction{#1}{#2}{#3}{#4}{#5}{#6}{}% +} + +\defc\flactionc{%#1#2#3#4#5#6#7% \flex continued action :: \flaction{\flsconlist...}{\fl..rule ...}{fptr}{sptr}{fptr}{sptr}{formatting command} + \noexpand\flactionc{#1}{#2}{#3}{#4}{#5}{#6}{}% +} -\def\charstonumbers#1\end{\edef\next{\toksa{\charstonumberse#1\end}}\next} +\toyyunion{flexparser-debug} diff --git a/support/splint/tex/yyxunion.sty b/support/splint/tex/yyxunion.sty deleted file mode 100644 index fb0d2460b3..0000000000 --- a/support/splint/tex/yyxunion.sty +++ /dev/null @@ -1,33 +0,0 @@ -% Copyright 2012-2015, Alexander Shibakov -% This file is part of SPLinT -% -% SPLinT is free software: you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation, either version 3 of the License, or -% (at your option) any later version. -% -% SPLinT is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with SPLinT. If not, see <http://www.gnu.org/licenses/>. - -% 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. - -\restorecslist{bootstrap}\yyunion % get the original bootstrap macros - -\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 |