什么是代币?

什么是代币?

请原谅这样一个基本的问题,但我做了一些谷歌搜索,并浏览了这个网站,虽然有很多线程和在线资源涉及代币,我似乎找不到直接的解释什么是 token,特别是在 TeX、LaTeX 等的上下文中。也许 TeXbook 中对 token 有很好的解释,但我没有它的副本。

这个维基百科页面给了我一些想法:

标记是一串字符,根据规则分类为符号(例如,标识符、数字、逗号)。

但这对我来说有点太笼统了。根据维基百科的定义和这个 TeX.SE 线程那么,说 token 是“具有 catcode 的事物”是否正确?(即使是这样,作为一个答案似乎也不能完全令人满意:被赋予 catcode 的事物具有什么特征?)

如果能提供一些 TeX、LaTeX 等领域的标记的说明性示例和非示例,我们将不胜感激。

答案1

以下内容摘自电子书

当 TeX 从文件中读取一行文本或直接在终端上输入一行文本时,它会将该文本转换为“标记”列表。标记可以是 (a) 带有附加类别代码的单个字符,也可以是 (b) 控制序列。例如,如果纯 TeX 的常规约定有效,则文本将转换为包含{\hskip 36 pt}八个标记的列表:

{1 \hskip 312 612 10 p11 t11 }2

这里的下标是类别代码,如前所述:1 表示“组的开头”,12 表示“其他字符”,等等。 没有\hskip下标,因为它表示控制序列标记而不是字符标记。请注意,后面的空格\hskip不会进入标记列表,因为它跟在控制字后面。

如果您想彻底了解 TeX,那么理解标记列表的概念非常重要,通过将 TeX 视为活的有机体来学习这个概念会很方便。文件中的各行输入只能被 TeX 的“眼睛”和“嘴巴”看到;但在文本被吞噬之后,它会以标记列表的形式发送到 TeX 的“胃”,而实际排版的消化过程完全基于标记。就胃而言,输入以标记流的形式流入,有点像您的 TeX 手稿被全部输入到一行非常长的行中。

您应该记住有关 TeX 标记的两个主要事项:(1) 控制序列被视为不再由符号序列组成的单个对象。因此,在用标记替换长控制序列名称后,TeX 处理长控制序列名称并不比短控制序列名称更难。此外,标记列表内的控制序列后面的空格不会被忽略;忽略空格规则仅适用于输入文件中字符串被标记期间。(2) 一旦将类别代码附加到字符标记,该附加就是永久性的。例如,如果字符{突然被声明为类别 12 而不是类别 1,TeX 标记列表中已有的字符{1仍将保留为类别 1;只有新创建的列表才会包含{12 个标记。换句话说,单个字符在从文件中读取后会立即获得固定的解释,具体取决于读取时它们的类别。控制序列则不同,因为它们可以随时更改其解释。TeX 的消化过程始终确切地知道字符标记表示什么,因为类别代码出现在标记本身中;但是当消化过程遇到控制序列标记时,它们必须查找该控制序列的当前定义才能弄清楚它的含义。

有关这些类别代码的列表(作为参考),请参阅类别代码是什么?

答案2

Wikipedia 页面给出的描述适用于 C 等语言,但不适用于 TeX。但原理是相似的:TeX 输入字节序列并将其转换为可以操作的对象,这些对象称为代币

TeXbook 第 7 章和 TeX by Topic 第 2 章中描述了具体的规则。让我试着对这个过程做一个简短的描述。

  1. TeX 每次读取一条记录(大致是输入文件中的一行)并丢弃记录结束终止符以及该记录结束符之前的所有空格(ASCII 代码为 32 的字符);然后附加其内部定义的记录结束字节(对应于的字节\endlinechar,通常为 13,与“回车符”相同)。

    为了简单起见,我假设并且\endlinechar=13字节 13 的类别代码是 5。

  2. 经过这一规范化步骤后,它会继续逐字节处理行。它会根据最后解释的规则,为每个字节(如果您愿意,也可以是字符)关联一个类别代码,即从 0 到 15 的数字。

  3. 首先,行首的类别代码为 10 的字节将被忽略。如果只剩下记录结尾,TeX 会在其主标记列表中插入标记\par,否则(如果它没有读取第一个输入行)它会插入一个空格标记(一对 (32,10),见下文)。TeX 处于“跳过空白状态”。

  4. 当 TeX 发现类别代码不同于 10 和 5 的字节时,它会进入一个新状态,即正常状态:每个类别代码不同于 0、9、14 或 15 的字节都会变成字符标记,因此是一对 (charcode, catcode),用于后续处理。catcode 为 9 或 15 的字节将被忽略(后一种情况下会发出错误消息),而类别代码为 14 的字节会导致 TeX 忽略它以及行上剩余的所有内容,包括记录结束字节。

  5. 当它发现类别代码为 0 的字节时,通常\,TeX 会进入一个新状态,在其中形成一个象征性标记如果后面的字节\的类别代码不同于 11,则形成以该字节为名称的标记(例如:\1\%等等)并恢复先前的正常状态。

  6. 如果以下字节\有类别代码 11(通常是一个字母),TeX 就会开始形成控制字:它会一直进行下去,直到找到类别代码不同于 11 的字节。这样存储的字节构成了此控制字的名称,该控制字成为符号标记,TeX 则返回到跳过空白状态。

因此,标记可以是 (charcode, catcode) 对,也可以是符号标记。请注意,此过程不会考虑这些标记的含义,这些含义将在后面的阶段进行检查。

需要知道的是什么时候这种情况会发生。实际上,TeX 对输入的处理是标记化和宏扩展的组合。每当 TeX 需要操作某个标记时,它就会查看输入。例如,如果为 TeX 提供了一个符号标记,那么可扩展(宏或原始),它读取并标记输入,直到找到这个可扩展标记的参数。

这就是为什么\verb不能在另一个命令的参数中。假设我们\mbox{\verb|{ab}|}的输入中有。TeX 找到符号标记\mbox并识别出它是可扩展的(因为它是一个用 定义的宏\def),并且它需要一个参数

\def\mbox#1{\leavevmode\hbox{#1}}

因此,TeX 读取输入以获取另一个标记,该标记恰好是{(准确地说是 ( {,1) 对),因此它知道必须读取匹配部分}才能确定参数。在此过程中,标记按上述方式形成,因此参数是以下标记序列

\verb |12 {1 a11 b11 }2 |12

这会破坏\verb破坏暂时改变字节的类别代码,这现在是不可能的,因为它们已经被存储为标记。

相反,当\verb|{ab}|不在命令的参数中时,\verb以延迟的方式操作。

  1. \verb参数,分隔符;它的第一个操作是打开一个组并将\bgroup的类别代码|(在此示例中)更改为 2,以便它将匹配插入的\bgroup并撤消所有类别代码的分配(包括将的类别代码更改|为 2)。

  2. 它将除 之外的所有非字母类别代码更改为 12 |,这样它们就可以打印了(当然,这不是完全的事实,但很接近事实),并让 TeX 继续进行标记化:不会形成符号标记,因为在此设置下没有字节具有类别代码 0。当|找到最后一个时,它会关闭组,撤消类别代码分配,然后 TeX 将返回其正常操作。

类别代码分配规则

TeX 维护着catcode 向量,即一个有 256 个槽的数组,编号从 0 到 255;每个槽包含一个 0-15 范围内的整数。当 TeX 从输入文件中读取一个字符时(我们处于上面第一个列表中的第二步),它知道它的 ASCII 代码,因此它会在 catcode 向量中查找并为该字符分配相应的类别代码。可以通过以下方式修改此向量中的条目

\catcode <integer> = <4 bit integer>

当使用能够理解完整 Unicode 范围的 XeTeX 或 LuaTeX 时,此向量会得到适当扩展;但是,可能的类别代码仍然有 16 个:

  • 0 表示“转义”;通常只有一个字符具有此代码,即反斜杠\,但在某些情况下需要暂时使用另一个

  • 1 表示“组的开始”,通常{;这样的字符启动一个组或者限定一个参数;

  • 2 表示“组结束”,通常}

  • 3 表示“数学转换”,通常$

  • 4 表示“制表”,通常&

  • 5 表示“行尾”;通常我们有\catcode\endlinechar=5,请参阅上文了解此类别代码的作用,这对于空行等同于结束一个段落这一众所周知的特征起着决定性作用;

  • 6 表示“参数”,通常#;显然它是宏定义中使用的参数;

  • 7 表示“上标”,通常为^;它还有另一种用法,例如 等组合^^M,但解释起来太长(可以在 TeX by Topic 或 TeXbook 中找到);

  • 8 表示“下标”,通常_

  • 9 表示“忽略”;通常字节 0 有此类别代码;

  • 10 表示“空格”;通常字节 32 和 10(空格和制表符)共享此类别代码;

  • 11 表示“字母”;可打印的字母有此代码;

  • 12 表示“其他可打印字符”;例如标点符号;

  • 13 表示“活跃”;另一个需要详细解释的功能;~通常是活跃的,这样的字符表现得像一个宏,需要适当定义;

  • 14 表示“注释”;通常%;参见上面的第 4 步了解其作用;

  • 15 表示“无效”;通常字节 127 有此代码。

为什么是第 9 和第 15 类?三十多年前,TeX 还在开发中,一些操作系统使用固定长度记录;这种用法来自穿孔卡。这些记录使用字节 0 填充。字节 127 可能表示“不计算这个,这是错误设置的”,但它也用于与电传打字机通信,表示退格。

直到 2019 年,大多数 TeX 实现中行尾的制表符也被丢弃,但现在不再如此,TeX 的行为与原始实现相同。

答案3

根据 TeX 书,该计划第 289 条:

@* \[20] Token lists.
A \TeX\ token is either a character or a control sequence, and it is
@^token@>
represented internally in one of two ways: (1)~A character whose ASCII
code number is |c| and whose command code is |m| is represented as the
number $2^8m+c$; the command code is in the range |1<=m<=14|. (2)~A control
sequence whose |eqtb| address is |p| is represented as the number
|cs_token_flag+p|. Here |cs_token_flag=@t$2^{12}-1$@>| is larger than
$2^8m+c$, yet it is small enough that |cs_token_flag+p< max_halfword|;
thus, a token fits comfortably in a halfword.

A token |t| represents a |left_brace| command if and only if
|t<left_brace_limit|; it represents a |right_brace| command if and only if
we have |left_brace_limit<=t<right_brace_limit|; and it represents a |match| or
|end_match| command if and only if |match_token<=t<=end_match_token|.
The following definitions take care of these token-oriented constants
and a few others.

答案4

如果我错了,请纠正我。这个答案可能不如上面的答案正确。

标记是一种已被翻译成 tex 语言的符号(如果你愿意的话可以称之为字符),但它仍然只是一个符号。

文本块中的每个字符(字母、数字等)都被视为一个符号,但整个控制序列(例如 \newpage)也被视为 Tex 中的一个符号。所以我的定义是“标记:Tex 中的符号”。

文件中的符号被转换为标记列表,然后 Tex 对这些标记进行操作并输出 pdf。

相关内容