diff options
Diffstat (limited to 'support/splint/tex/yymisc.sty')
-rw-r--r-- | support/splint/tex/yymisc.sty | 355 |
1 files changed, 261 insertions, 94 deletions
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}}} + |