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, world
,a 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 会处理试图使用它的标记列表。当它找到一个可扩展的标记时,它会执行扩展,并继续执行,直到找到一个不可扩展的标记。在这种情况下,它会将其(连同其参数,可能需要进行一些扩展)发送到“胃”进行执行。
我们来举几个例子。
\catcode`@=11
由于\catcode
不可扩展,TeX 将其连同参数一起发送到胃并执行分配。@
从此时起吸收的所有字符都将具有类别代码 11。\def\at{`@}\catcode\at=11
宏定义被发送到胃;然后\catcode
不可扩展,并且 TeX 确定其参数;由于\catcode
需要查看数字,因此\at
被扩展并最终\catcode`@=11
将被发送到胃并像以前一样执行。\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