TeX 何时执行 \catcode=`\... 赋值?

TeX 何时执行 \catcode=`\... 赋值?

TeX 总是扫描输入并将其转换为一些标记,然后根据该命令的最新定义扩展一些标记......stomach -> lists -> page

但是 TeX 何时执行 catcode 分配?它一看到它就执行吗?

例如

1. \catcode`\%=12
2. %
3. \catcode`\%=14
4. \def\foo{\catcode`\%=12%}
5. \bye

这将是错误的,因为 TeX 不会扩展要定义的宏。第 4 行中的最后一个 % 只是一个注释符号,而不是带有 catcode 12 的百分号。但是,TeX 是否会在查看时立即执行第 1 行和第 3 行(这是否意味着 TeX 不会将第 1 行和第 3 行转换为标记?)

另一个例子(我尝试完成这个宏,但是失败了)

\def\foo{hello, world}
{\catcode`\^=13
 \gdef^{\relax\ifmmode\def\next{\catcode`\^=7 ^}\else\let\next\foo\fi\next}}

{\catcode`\^=13
 ^$a^2$}
\bye

我认为我应该在它后面加上hello, worlda square因为first ^应该扩展

^ ->\relax\ifmmode\def\next{\catcode`\^=7 ^}\else\let\next\foo\fi\next
  ->\relax\let\next\foo\next
  ->\relax\next
  ->\relax h e l l o , w o r l d

所以,我应该成对得到hello, world.the second ^$ ... $

$a^2$ ->$a\relax\ifmmode\def\next{\catcode`\^=7 ^}\else\let\next\foo\fi\next2$
      ->$a\relax\def\next{\catcode`\^=7 ^}\next2$
      ->$a\relax\catcode`\^=7 ^2$
      ->$a^2$ % the catcode of ^ is 7 now

所以我想我应该得到a square

但这是错误的,我犯了错误。我不知道为什么 :-(

答案1

\catcode`@=11一旦 TeX 在使用标记时遇到命令(而不是进行扩展),就会执行该命令。

基本上,TeX 会处理试图使用它的标记列表。当它找到一个可扩展的标记时,它会执行扩展,并继续执行,直到找到一个不可扩展的标记。在这种情况下,它会将其(连同其参数,可能需要进行一些扩展)发送到“胃”进行执行。

我们来举几个例子。

  1. \catcode`@=11
    由于\catcode不可扩展,TeX 将其连同参数一起发送到胃并执行分配。@从此时起吸收的所有字符都将具有类别代码 11。

  2. \def\at{`@}\catcode\at=11
    宏定义被发送到胃;然后\catcode不可扩展,并且 TeX 确定其参数;由于\catcode需要查看数字,因此\at被扩展并最终\catcode`@=11将被发送到胃并像以前一样执行。

  3. \def\foo{\catcode`@=11 }
    这里的\def标记是不可扩展的,因此直到右括号为止的所有内容都被发送到胃部;分配\catcode不是执行,因为它位于宏的替换文本中。

在 LaTeX 内核中我们发现

448 \def\obeyspaces{\catcode`\ \active}
449 {\obeyspaces\global\let =\space}

(行号用于查找代码)。这是什么意思?LaTeX 需要为活动空间提供定义,因为这个标记 (32,13)​​ 可能会潜入一些延迟写入。在第 448 行中,\obeyspaces定义了宏来激活空间。在第 449 行中,打开一个组,\obeyspaces发出,使空间处于活动状态,活动空间收到定义。组的结尾将撤消类别代码分配。请注意,即使的定义\space

\def\space{ }

当 TeX 扩展活动空间时,它会反过来扩展,\space产生一个普通的\space类别代码 10 的空间,因为当空间具有该类别代码时,的替换文本已被吸收。


现在让我们看看您的示例。

1  \catcode`\%=12
2  %
3  \catcode`\%=14
4  \def\foo{\catcode`\%=12%}
5  \bye

第 1 行中的赋值会立即执行,因此%第 2 行中的只是打印。然后执行第 3 行中的赋值,TeX 转到第 4 行。第二行%的类别代码为 14,因此它是注释,定义不完整。

1  \def\foo{hello, world}
2  {\catcode`\^=13
3   \gdef^{\relax\ifmmode\def\next{\catcode`\^=7 ^}\else\let\next\foo\fi\next}}
4
5  {\catcode`\^=13
6   ^$a^2$}
7  \bye

您正在尝试定义活动的^。第 2 行打开的组将恢复类别代码分配。但是^后面\catcode`\^=7的类别代码是 13,而不是 7,因为如前所述,\catcode正在定义的宏的替换文本中的指令是不是已执行。

您只需要有一个类别代码为 7 的脱字符,如上\obeyspace例所示:

\def\foo{hello, world}
\def\normalhat{^}
{\catcode`\^=13
 \gdef^{\relax\ifmmode\let\next\normalhat\else\let\next\foo\fi\next}}

{\catcode`\^=13
 ^ $a^2$}
\bye

输出将是

你好世界A2

相关内容