TeX 不使用哪些标记作为未限定的参数(除非嵌套在类别代码 1 的显式字符标记和类别代码 2 的显式字符标记之间)?
在 TeXbook 练习 20.4 之前的倒数第二个危险弯道段落中,你会发现这样的句子:
在输入 '
\def\row#1#2{...}
' 之后,你可以在参数之间添加空格(例如 '\row x n
'),因为 TeX 不使用单个空格作为无限参数。
在 TeXbook 练习 20.5 之前的 double dangeorus bend 段落中,你会发现以下句子:
你可能会问,TeX 如何确定一个参数在何处结束。答案是:[...]未限定的参数紧接着⟨参数文本⟩通过参数标记,或者它出现在参数文本的最末尾;在这种情况下,相应的参数是下一个非空白标记,除非该标记是“
{
”,此时参数将是{...}
后面的整个组。
在 TeXbook 中,我确实没有找到“单个空格”和“非空白标记”这两个术语的精确定义。
请枚举 TeX 不用作非限定参数的所有标记(除非嵌套在类别代码 1 的显式字符标记和类别代码 2 的显式字符标记之间)。
现在我发现 TeX 不使用类别代码 10 和字符代码 32 的显式字符标记作为未限定的参数 - 您需要关注 TeX 对的\macro
第二个参数所采取的方式:
\def\macro#1#2{\def\macrob{Arg 1:(#1) Arg 2:(#2)}}
\macro A B
\show\macrob
\bye
类别代码 10 和字符代码 32 的隐式字符标记用作未限定的宏参数:
\def\macro#1#2{\def\macrob{Arg 1:(#1) Arg 2:(#2)}}
\catcode`\X=13
\uppercase{\let\space= } %
\uppercase{\letX= } %
\macro A\space B
\show\macrob
\macro AXB
\show\macrob
\bye
显式的有趣空格被用作未限定的宏参数:
\def\macro#1#2{\def\macrob{Arg 1:(#1) Arg 2:(#2)}}
\uccode`\ =`\a
\uppercase{\macro A B}%
\show\macrob
\bye
隐式滑稽空格被用作未限定的宏参数:
\def\macro#1#2{\def\macrob{Arg 1:(#1) Arg 2:(#2)}}
\def\letcs#1#2{\let#1= #2}%
\catcode`\X=13
\uccode`\ =`\a
\uppercase{\letcs\space{ }}%
\uppercase{\letcsX{ }}%
\macro A\space B
\show\macrob
\macro AXB
\show\macrob
\bye
类别代码 12 和字符代码 32 的隐式/显式字符标记用作未限定的宏参数:
\def\macro#1#2{\def\macrob{Arg 1:(#1) Arg 2:(#2)}}
\catcode`\ =12\relax%
\let\space= %
\macro{A} {B}%
\show\macrob
\macro{A}\space{B}%
\show\macrob
\bye
控制空格用作未限定的宏参数:
\def\macro#1#2{\def\macrob{Arg 1:(#1) Arg 2:(#2)}}
\macro A\ B
\show\macrob
\bye
因此我测试了一些情况,但测试边缘情况既不能对术语“单个空格”做出精确定义,也不能对术语“非空白标记”做出精确定义。;-)
换句话说:我不知道 TeX 不将哪些标记用作未限定的参数(除非嵌套在类别代码 1 的字符标记和类别代码 2 的字符标记之间)。
似乎数量⟨太空代币⟩不等于“单个空格”/“非空白标记”:
TeXbook 在第 24 章“垂直模式摘要”中说道:
数量⟨太空代币⟩,用于语法⟨可选空格⟩上面的 代表显式或隐式空间。换句话说,它表示类别 10 的字符标记,或者表示当前含义已通过
\let
或等于此类标记的控制序列或活动字符\futurelet
。
提到的“控制序列或活动字符”,可归入⟨太空代币⟩,将被用作未分隔的宏参数 - 上面的例子显示了这一点 - 而“单个空格”/“非空白标记”不被用作未分隔的宏参数。
可能“单个空格”/“非空白标记”是⟨太空代币⟩?
如果是的话——具体是哪个子集?
答案1
TeXbook 的风格通常是说一些正确的事情,但不是完全的事实。
没有“单一空间”的正式定义,因为没有必要。
事实上,如果你尝试
\begingroup\def\\{\global\let\spacetoken= }\\ \endgroup
\def\foo#1#2{(First is #1)(Second is #2)}
\foo AB
\foo A B
\edef\two{\space\space}
\expandafter\foo\expandafter A\two B
\foo A\spacetoken B
\bye
你会得到三个实例
(第一为 A)(第二为 B)
最后一行将生成
(第一个是 A)(第二个是 )B
这个技巧是在和\expandafter
之间插入多个空格。所以你看下一个练习是“更正确的”:TeX 跳过任何A
B
明确的寻找未限定参数时,空格标记。
最后一个例子表明隐式空格标记不会被跳过。代码中的第一行是从练习 24.6 中借用的,用于创建\spacetoken
隐式空格标记,因为不能简单地像 中那样执行\let\bgroup={
。如果你添加,\show\spacetoken
你会得到
> \spacetoken=blank space .
但这是不是在寻找未限定的参数时被忽略。
显式空格标记是类别代码为 10 的字符标记(正常设置下为空格或制表符;但如果您对此感兴趣,请参阅后面的更多详细信息)。正常设置下,这可能由输入中的空格或制表符生成,或者由在对输入进行标记时分配类别代码 10 的任何字符生成。
但是,有一个问题。总是有一个问题!
必须考虑到 TeX 会吸收类别代码为 10 的字符,并根据其原始字符代码为其分配字符代码 32。因此制表符与空格没有区别,因为它们是一旦完成标记化,情况也是一样。
那么,问题是什么
\uccode` =`x \uppercase{\foo A B}
不忽略有趣的空间?事实上,它不同于
\catcode`*=10 \foo A*B
忽略星号,因为它的类别代码为 10。
事实上,类别代码为 10 的角色是规范化字符代码为 32在标记化过程中。但是,当\uppercase
应用时,标记化已经执行,并且空格具有字符代码 32。但是之后\uppercase
字符变为x
10,它不再有效并且不能被忽略,因为它没有字符代码 32。
因此,只忽略字符代码 32 和类别代码 10 的字符的答案是正确的,但如果不考虑规范化,则会产生误导。
答案2
tex.web 有
begin if cur_tok=space_token then
跳过被忽略的space_token
标记
@d space_token=@'5040 {$2^8\cdot|spacer|+|" "|$}
答案3
在“寻找”未限定参数的开头时,TeX 只会跳过字符代码 32 和类别 10(空格)的显式字符标记序列。
数量⟨太空代币⟩确实不等于您引用的 TeXbook 段落意义上的“单个空格”/“非空白标记”:
数量⟨一个可选空格⟩定义为:
⟨一个可选空格⟩→⟨太空代币⟩|⟨空的⟩
无论何处⟨一个可选空格⟩是允许的,这也可以是一个隐式的空间标记。
例如,参见
\lowercase{\let\sptoken = } %
\edef\result{\number1234 }
\show\result
\edef\result{\number1234\sptoken}
\show\result
\let\result\sptoken\sptoken=\sptoken\TeX
\bye
(这里\lowercase
只是删除了括号。这样,您将在“=”后面获得两个字符代码为 32 的显式空格标记。第一个将被丢弃,因为使用\let
-assignments 时,“=”后面的一个空格是可选的。第二个将不会被丢弃,但将成为其含义被分配给的标记\sptoken
。)
\sptoken
是隐式空格标记。
它在 TeX\number
求值期间被丢弃,就像显式空格标记一样。
它也像任何其他空格标记一样被丢弃⟨可选空间⟩在执行第二个\let
赋值时。但是 TeX在“寻找”未限定参数的开头时
不会跳过。\sptoken
所以这个例子证明了数量⟨太空代币⟩并不等于您所引用的 TeXbook 段落意义上的“单个空格”/“非空白标记”。
顺便一提:
您的问题集中在 TeX 在寻找未限定参数的开头时如何处理标记。
您的问题涉及标记化已经完成的处理阶段。
不过,值得一提的是与 .tex-input 标记过程相关的一个事实:
如果在对 .tex 输入进行标记的过程中,TeX 遇到类别代码为 10(空格)的字符,而读取设备处于状态 M(行中间),则 TeX 会将类别 10(空格)和字符代码 32 的明确字符标记附加到标记流中。也就是说,无论所讨论的输入字符的代码点有多少个数字,生成的标记都将具有字符代码 32。
例如,水平制表符(水平制表符在 ASCII 中的代码点编号为 9)通常也分配有类别代码 10。因此,对水平制表符进行标记通常会产生类别 10(空格)和字符代码 32 的明确字符标记。即,TeX 在“寻找”未定界参数的开头时跳过的那个标记。