\afterassignment 如何工作?

\afterassignment 如何工作?

我在另一个问题中发现了以下代码:

\def\scan#1{\scanA#1*}
\def\scanA{\futurelet\next\scanB}
\def\scanB{\expandafter\ifx\next\space \expandafter\scanC \else \expandafter\scanE \fi}
\def\scanC{\afterassignment\scanD \let\next= }
\def\scanD{\scanE{ }}
\def\scanE#1{\ifx*#1\else \dosomething{#1} \expandafter\scanA \fi}

其效果是将像 这样的字符串转换ABC\dosomething{A}\dosomething{B}\dosomething{C}

\let\dosomething=\uppercase,则\scan{Hello World!}HELLO WORLD!

我理解当\ifx\next\spacein \scanBgets时false它会扩展为\scanE,它将下一个未读标记捕获为它的参数并\dosomething

但是,当得到 时true,它会扩展为\scanC\scanD扩展为\scanE{ },以便我们可以处理空格。但是为什么下一个\scanA会跳过空格,以及和如何\afterassignment工作\let\next=

===== OrthoPole 更新 =====

我想我自己已经了解了这个过程。

\ifx获取时true,流看起来像\futurelet·\next·\scanB·_·..._代表空格标记),并且它扩展为\afterassignment·\scanD·\let·\next·=·_·_·...。我们看到\let允许可选的空格标记,因此后面的第一个空格=将被省略,并将\next被分配第二个空格。在此分配之后,\scanD将被扩展。由于 后面的两个空格=被 吸收\let,我们得到\scanD·...

答案1

\afterassignment\cs\cs在执行下一个分配后立即重新插入到输入流中。

什么被视为赋值?设置寄存器的值(但对于盒子寄存器来说,情况略微复杂);执行\.def代表.无,gx等等char;执行\let

你的情况是最后一个。现在的语法\let

\let <cs><optional spaces><optional =><one optional space>

在你的情况下,这<optional spaces>部分并不有趣,因为你总是有\let\scanD。更有趣的是<one optional space>。在这种情况下,TeX 会代币跟随的扩展=,正如所见证的

\let\x=\space\message{abc}

abc在控制台上打印并\x使其与相同\space

正在做

\def\scanC{\afterassignment\scanD \let\next}

如果后面的标记\scanC=,则会失败,因为它将被视为\let指令的一部分,这是不想要的。但也有

\def\scanC{\afterassignment\scanD \let\next=}

如果后面的标记\scanC是显式的空格标记,则会失败,因为它将被视为<one optional space>

您希望分配给\next下一个标记,因此您需要

\def\scanC{\afterassignment\scanD \let\next= }

相关内容