这么简单的文字让我困惑
\def\say#1{The argument is #1, I see it}
\say{\catcode`{=12 \bf Hello}
\bye
当 TeX 编译失败并报告
Runaway argument?
{\catcode `{=12 \bf Hello}
! Forbidden control sequence found while scanning use of \say.
<inserted text>
\par
<to be read again>
\bye
l.3 \bye
我猜 TeX{
在读取时会将 catcode 1 放入标记列表中,\catcode`{
因此会产生不平衡的参数。为此,我稍微更改了命令,只是}
在末尾添加了一个额外的命令:
\say{\catcode`{=12 \bf Hello}}
现在出现了一个新错误:
! Too many }'s.
<argument> \catcode `{=12 \bf Hello}
\say #1->The argument is #1
, I see it
l.2 \say{\catcode`{=12 \bf Hello}}
如您所见,它也不起作用。但如果考虑 token 列表,后面有两个{
catcode 1 的左括号和两个}
catcode 2 的右括号,因此列表似乎是平衡的(可能)。显然 TeX 不这么认为。
最后,当我匹配时\catcode`{=12
,\catcode`}=12
它成功运行:
\say{\catcode`{=12 \bf Hello\catcode`}=12}
这可能意味着 TeX 首先收集\catcode`{=12 \bf Hello\catcode`}=12
作为参数\say
,然后分析标记列表。
{
那么会发生什么?在这里扮演什么角色\catcode`{
? TeX 如何判断参数是否平衡?
答案1
和
\def\say#1{The argument is #1, I see it}
代码
\say{\catcode`{=12 \bf Hello}
\bye
是非法的,因为{
尚未收到类别代码 12,因此 TeX 寻找匹配}
但未找到。当遇到 时\bye
,这在宏参数中是非法的,TeX 会停止并显示有关“禁止控制序列”的错误。
如果你添加一个右括号
\say{\catcode`{=12 \bf Hello}}
那么参数就被正确平衡了。现在 TeX 将进行宏替换,输入流将变成
The argument is \catcode`{=12 \bf Hello}, I see it
在哪里有不平衡的}
。
正如 Ulrike 所建议的,
\say{\catcode`\{=12 \bf Hello}
不会产生任何错误。字母常量由一个反引号(类别代码 12)和一个字符或一个字符控制序列组成。
例如,为了更改%
您的类别代码必须说
\catcode`\%=12
以避免 TeX 将其%
视为注释字符。一些字符必须在此上下文中始终可以进行转义:
- 类别代码为 0 的字符
- 类别代码为 5 的字符
- 类别代码为 9 的字符
- 类别代码为 14 的字符
- 类别代码为 15 的字符
所有其他人能逃脱,一些必须取决于您所在的位置。例如,#
如果您正在编写定义,则应该进行转义
\def\foo{\catcode`#=12 }
行不通,但是
\def\foo{\catcode`\#=12 }
会。⟨平衡文本⟩ 中的括号也类似。
练习:猜猜你会从中得到什么
\edef\foo{\catcode`\^^M=12 }
\foo
\showthe\catcode`\^^M