% \subsection{List list of tokens} % % Two-dimensional arrays of tokens, or lists of lists of tokens. % % % Format of the list: % % \begin{verbatim} % {...tokens1...}{...tokens2...}...{...tokensN...} % \end{verbatim} % % Token manipulation should not belong to the ``cals'' package, % and the macros from this section have the prefix |llt@| % instead of |cals@|. Probably it is better to use some CTAN % package, but initially the llt-code was small and simple, so % I did not want dependencies, and now I do not want to replace % working code with something new. % % In comments to these functions, a parameter of type \textit{token list} % is a macro which will be expanded once to get the tokens, and % \textit{list list} is a macro which stores the two-dimensional array. % % An example of use: % \begin{verbatim} % \def\aaa{aaa} % \def\bbb{bbb} % \def\ccc{ccc} % \def\lst{} % empty list % \llt@cons\bbb\lst % \lst -> "{bbb}" % \llt@snoc\lst\ccc % \lst -> "{bbb}{ccc}" % \llt@cons\aaa\lst % \lst -> "{aaa}{bbb}{ccc}" % \llt@decons\lst % \llt@car -> "aaa", \lst -> "{bbb}{ccc}" % \llt@rot\lst % \llt@car -> "bbb", \lst -> "{ccc}{bbb}" % \end{verbatim} % % % % \begin{macro}{\llt@cons} % Prepends the token list \#1 to the list list \#2. % Corrupts the token registers 0 and~2. % \begin{macrocode} \def\llt@cons#1#2{% \toks0=\expandafter{#1}% \toks2=\expandafter{#2}% \edef#2{\noexpand{\the\toks0}\the\toks2 }% } % \end{macrocode} % \end{macro} % % \begin{macro}{\llt@snoc} % Appends the token list \#2 to the list list \#1 (note the order % of parameters). % Macro corrupts the token registers 0 and 2. % % \begin{macrocode} \def\llt@snoc#1#2{% \toks0=\expandafter{#1}% \toks2=\expandafter{#2}% \edef#1{\the\toks0 \noexpand{\the\toks2}}% } % \end{macrocode} % \end{macro} % % \begin{macro}{\llt@car} % A token list, set as a side-effect of the list deconstruction % and rotation functions. % \end{macro} % % \begin{macro}{\llt@decons} % List deconstruction. The first item is removed from the list list \#1 % and its tokens are put to the token list |\llt@car|. % Corrupts the token register 0. % Undefined behaviour if the list list has no items. % % The actual work happens on the |\expandafter| line. % It's hard to explain, let me show the macro expansion, % I hope it's self-explaining. % % \begin{verbatim} % \expandafter\llt@decons@open\lst} --> % \llt@decons@open{aaa}{bbb}{ccc}{ddd}} --> % \def\llt@car{aaa} \toks0=\llt@opengroup {bbb}{ccc}{ddd}} --> % \def\llt@car{aaa} \toks0={{bbb}{ccc}{ddd}} % \end{verbatim} % % Why I use |\let\llt@opengroup={| inside the definition? % Only to balance the number of opening and closing brackets. % Otherwise TeX will not compile the definition. % % Initially I tried to use the following helper: % % \begin{verbatim} % \def\decons@helper#1#2\relax{% % \def\llt@car{#1}% % \def\list{#2}} % \end{verbatim} % % If a call is |\decons@helper{aaa}{bbb}{ccc}\relax| then % all is ok, the helper gets: \#1 is |aaa| and \#2 is % |{bbb}{ccc}|. % % Unfortunately, if the list has two items and the call is % |\decons@helper{aaa}{bbb}}\relax|, then the helper gets: % \#1 is |aaa| and \#2 is |bbb| instead of |{bbb}|. % The grouping tokens are lost, and we can't detect it. % % \begin{macrocode} \def\llt@decons@open#1{% \def\llt@car{#1}% \toks0=\llt@opengroup } \def\llt@decons#1{% \let\llt@opengroup={% \expandafter\llt@decons@open#1}% \edef#1{\the\toks0}% } % \end{macrocode} % \end{macro} % % \begin{macro}{\llt@rot} % Rotates the list list \#1. The first item becomes the last. Also, % its tokens are saved to token list |\llt@car|. % The second item becomes the first item, the third the second etc. % Corrupts the token registers 0 and 2. % % \begin{macrocode} \def\llt@rot#1{% \ifx#1\empty \let\llt@car=\relax \else \llt@decons#1% \llt@snoc#1\llt@car% \fi } % \end{macrocode} % \end{macro} % % \begin{macro}{\llt@desnoc} % Very unefficient list deconstruction. The last item is removed % from the list list \#1 % and its tokens are put to the token % list |\llt@car|. Corrupts the token registers 0 and 2. % Undefined behaviour if the list list has no items. % % |\llt@desnocII| is used to hide |\if| from the loop. % \begin{macrocode} \def\llt@desnocII#1{ \ifx\empty#1% \let\llt@tmp=n% \else \llt@snoc{\llt@newlist}{\llt@car}% \let\llt@tmp=y% \fi } \def\llt@desnoc#1{% \def\llt@newlist{}% \loop \llt@decons{#1}% \llt@desnocII{#1}% \if y\llt@tmp \repeat \let#1=\llt@newlist} % \end{macrocode} % \end{macro}