TeX 手稿 `\iftrue\expandafter a\else b\fi c\bye` 是如何处理?

TeX 手稿 `\iftrue\expandafter a\else b\fi c\bye` 是如何处理?

有人能告诉我,我对 TeX 引擎(如texpdftex)如何处理以下 TeX 手稿的理解是否正确吗?如果不正确,请纠正我?

\iftrue\expandafter a\else b\fi c\bye

困难在于理解如何\else扩展,以及在使用\fi该子句时是否保留在输入流中。\else

我对这种形式感兴趣是因为我在 TikZ 源代码中(在文件中<pgf installation dir>/frontendlayer/tikz/tikz.code.tex)遇到了类似的形式:

\def\tikz@endscope{%
    \iftikz@auto@end@path%
        \expandafter\tikz@finish\expandafter\egroup%
        \else\expandafter\tikz@@endscope%
    \fi%
}

TeX 引擎处理 TeX 手稿的方式如下

\iftrue\expandafter a\else b\fi c\bye
  1. 控制序列\iftrue从输入流中删除,并将内部标志推送到堆栈上,我将其称为堆栈if,表示我们处于true条件表达式的子句内。

  2. \expandafter展开如下:

    1. 控制序列\expandafter已从输入流中删除。

    2. 输入流开头的标记,即a,将从输入流中移除,并推送到我将调用的内部堆栈上堆栈expand after

    3. 输入流开头的标记,即\else,被扩展。那么, 是如何\else扩展的呢?根据 TeX Book(第 20 次印刷,1991 年,第 213 页):

      \else\or\fi扩展时,TEX 会读至任何应跳过的文本的末尾。

      因此 TeX 会跳过(即从输入流中删除)\else(包括\else)和第一个\fi(不包括 )之间的所有内容\fi。这样输入流将保留以下内容:

      \fi c\bye
      
    4. 弹出堆栈expand after并将其元素添加到输入流的开头。因此,在此步骤结束时,输入流由以下内容组成:

      a\fi c\bye
      
    5. 恢复正常 TeX 处理。

  3. 该信件a被写入 dvi 文件。

  4. 弹出\fi堆栈if(回想一下步骤 1)。if堆栈现在为空,因此 TeX 知道我们不再处于条件语句中。

  5. 该信件c被写入 dvi 文件。

  6. 引擎停止了。

最后,dvi 文件包含文本

交流电

答案1

您有一系列可扩展的命令。在这里,我将主要关注从“TeX 宏的观点”来看事情是如何发生的:TeX 程序中当然有细节,但我的理解是这不是重点。

首先,TeX 会进行扩展\iftrue,使条件计数器增加一,但不会执行任何其他操作。然后,TeX 会找到\expandafter跳过a(就像您所说的放入堆栈一样)并扩展\else。结果是 TeX 会寻找匹配的\fi,因此会检查但不扩展标记,直到找到一个为止,并丢弃沿途收集的材料。一旦找到\fi(或\let原始标记),条件计数器就会减少,并且\fi也会丢弃。在此阶段,a会重新插入,我们(实际上)有

ac\bye

这是按通常方式排版的。

条件扩展移除这很重要。这意味着与\expandafter条件相结合可以关闭“有效载荷”已展开。您可以在以下结构中看到

\iftrue\expandafter\show\else b\fi c\bye

你会得到

> the letter c.
l.1 \iftrue\expandafter \show\else b\fi c
                                         \bye

如果您希望插入任何带有参数的内容,这一点至关重要:否则您将不得不在各处应对杂散的条件结尾。

相关内容