bachotex2009-stephen-hicks-pearl1.tex
bachotex2009-stephen-hicks-pearl1.tex
—
TeX document,
2 KB (2248 bytes)
Zawartość pliku
%%% inlinedef: a general recursive token scanner with callbacks
% There have been several discussions about uses of \expandafter
% that border on the ridiculous, with as many as fifteen in a row
% found in actual TeX input files! Additionally, trying to expand
% past macro parameters #1 causes problems because there is no
% guarantee that #1 is a single token. It would instead be nice
% to insert something right before a single token we want to expand
% far in advance. A slightly more general problem is to scan tokens
% in the input stream while preserving spaces and grouping.
\let\xa\expandafter
\def\scan{\futurelet\foo\switch}
\def\switch{%
\let\next\normal
\ifcat\noexpand\foo\space \let\next\dospace\fi
\ifcat\noexpand\foo\bgroup \let\next\trygroup\fi
\ifcat\noexpand\foo\relax \try{&\meaning\foo}\fi
\next}
\def\try#1{\ifcsname #1\endcsname\xa\let\xa\next\csname #1\endcsname\fi}
\def\dospace{\toks0\xa{\the\toks\xa0 \space}\xa\scan\unspace}
\xa\def\xa\unspace\space{}
\long\def\trygroup#1#{%
\def\temp{#1}\xa\let\xa\next\ifx\temp\empty\recurse\else\normal\fi\next#1}
\long\def\recurse#1{%
\begingroup\toks0{}\scan#1\END{}\xa\endgroup\xa
\toks\xa0\xa\xa\xa{\xa\the\xa\toks\xa0\xa{\the\toks0}}\scan}
\long\def\normal#1{\toks0\xa{\the\toks0 #1}\scan}
\def\callback#1#2#{\def#1{\noexpand#1}\xa\def\csname&\meaning#1\endcsname#2}
% We can set up a few callbacks, e.g. \END to end scanning, and
% \EXPAND to expand the next token:
\callback\END#1{}
\callback\EXPAND#1{\expandafter\scan}
% And now we can get arbitrary tokens from the input stream into \toks0
% using
\def\baz{!}
\scan foo {bar \EXPAND\baz} \baz \END
\message{\the\toks0} % foo\space {bar\space !}\space \baz
% This can be made more general in several ways: if we don't check
% \ifcat\noexpand\foo\relax then we can execute callbacks on arbitrary
% tokens, including spaces and grouping symbols. Of course this slows
% things down quite a bit further, which brings me to the main
% disadvantage with this approach: it takes about 25 times as long
% than a simple string of \expandafter's, and is therefore not
% suitable for inner loops. But the code it allows us to write, as
% long as efficiency isn't important, is much more readable.
\end
Akcje Dokumentu
