如何获取 token 的 catcode?

如何获取 token 的 catcode?

为了调试复杂的宏,我想打印出令牌的 catcode。理想情况下,我希望有一个宏\getcatcode,例如,\getcatcode{a}它将扩展为10。如何做到这一点?

我发现了很多关于如何设置/更改 catcode 的信息,但没有关于如何读取它们的信息。

答案1

\catcode一起使用\the来获取 token 的 catcode :

\the\catcode`a

注意:`将下一个字符转换为所需的 ASCII 数字\catcode

作为自定义宏:

\newcommand{\getcatcode}[1]{\the\catcode`#1}

特殊字符必须用反斜杠转义,例如%必须写为\%#\#。以同样的方式书写普通字母也没有坏处,例如\getcatcode\a也一样好用。

答案2

正如 TeXbook 练习中所解释的那样,你也可以写

\newcommand{\printcatcode}[1]{%
   \ifcase\catcode`#1\relax
      escape\or
      beginning of group\or
      end of group\or
      math shift\or
      tab\or
      end of line\or
      parameter\or
      superscript\or
      subscript\or
      ignored\or
      space\or
      letter\or
      otherchar\or
      active\or
      comment\or
      ignored\fi}

 The category code is `\printcatcode\%'

需要指出的是, TeX 中的任何“代码表”都可以用于访问该值(\catcode,,,,,,)。\lccode\uccode\mathcode\delcode\sfcode

答案3

Martin 和 egreg 提供的解决方案打印当前的字符的 catcode。我理解最初的问题是如何打印字符的 catcode令牌,即可能在过去已被扫描过的,当时不同的 catcode 有效。考虑一下:

\catcode`\@=11
\newcommand{\x}{@}
\catcode`\@=12
\newcommand{\y}{@}

\newcommand{\printcatcode}[1]{
  \def\aux##1{
     \message{The catcode of the ##1 in \noexpand#1 is \getcatcode{##1}.^^J}
  }
  \expandafter\aux#1
}

\printcatcode{\x}
\printcatcode{\y}

显然,@宏中存储的 s\x具有\y两个不同的 catcode。但是,使用 Martin 的宏,我们得到:

The catcode of the @ in \x  is 12.
The catcode of the @ in \y  is 12.

这是因为 Martin 的宏打印的是标记所代表的字符的“当前” catcode,而不是实际存储在标记中的 catcode。

以下是一个比较好的解决办法:

\begingroup%
  % locally ensure that characters have their expected catcodes
  \catcode`\$=3%
  \catcode`\&=4%
  \catcode`\#=6%
  \catcode`\^=7%
  \catcode`\_=8%
  \catcode`\ =10%
  \catcode`\a=11%
  \catcode`\+=12%
  \catcode`\~=13%
  \gdef\getcatcode#1{%
    \ifcat\noexpand#1$3\else%
    \ifcat\noexpand#1&4\else%
    \ifcat\noexpand#1##6\else%
    \ifcat\noexpand#1^7\else%
    \ifcat\noexpand#1_8\else%
    \ifcat\noexpand#1 10\else%
    \ifcat\noexpand#1a11\else%
    \ifcat\noexpand#1+12\else%
    \ifcat\noexpand#1\noexpand~13\else%
    \ifcat\noexpand#1\relax16\else%
      unknown%
    \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi%
  }
\endgroup

这样,我们就得到了预期的答案:

The catcode of the @ in \x  is 11.
The catcode of the @ in \y  is 12.

代码有点别扭,我想知道是否有更优雅的解决方案。我无法测试 catcodes 0、1、2、5、9、14 和 15,但我不确定在输入被标记后是否真的会出现这样的 catcodes。

相关内容