조건문 디버깅을 위해 catcode를 사용하여 매크로를 개별 토큰/문자로 분할하시겠습니까?

조건문 디버깅을 위해 catcode를 사용하여 매크로를 개별 토큰/문자로 분할하시겠습니까?

다음에서 수정된 이 MWE를 고려하십시오.ifthenelse가 동일한 문자열 비교에 실패하면:

\documentclass{article}

\edef\test{german\relax}
\edef\curentry{\string german\relax}

\typeout{test: \meaning\test, curentry: \meaning\curentry}
\ifx\curentry\test
  \typeout{ equal}
\else
  \typeout{ unequal}
\fi

\begin{document}
\end{document}

이것을 로 컴파일하면 pdflatex test.tex터미널에 다음 출력이 표시됩니다.

test: macro:->german\relax , curentry: macro:->german\relax
 unequal

이제 링크된 게시물에서 그 이유를 설명합니다.

무슨 일이 일어나는지는 \string이 처음 보는 토큰(이 경우에는 g)에 적용된다는 것입니다. 두 결과를 비교해 보면 결과는 동일하지 않습니다. 하나는 글자가 아닌 글자가 하나 있고, 글자는 다섯 개이고, 두 번째는 글자가 여섯 개입니다.

그러나 매크로가 어떻게 정의되었는지 실제로 알지 못하는 패키지에서 일부 상황을 검사하려고 한다고 가정해 보겠습니다. 그래서 저는 매크로 중 하나를 \typeout선택 하기 로 결정했습니다 .\meaning똑같다내용이 인쇄되었지만 조건문은 여전히 ​​실패합니다. 이런 상황을 디버깅하려면 어떻게 해야 합니까?

즉, 제가 사용할 수 있는 일종의 기능이 있습니까?Latex에서 catcode 테이블을 생성합니까(터미널에 \typeout 사용)?)은 위의 매크로에 대해 다음과 같이 출력됩니다.

% \typeoutComponents{\test}
g (catcode 11)
e (catcode 11)
r (catcode 11)
m (catcode 11)
a (catcode 11)
n (catcode 11)
\relax (catcode ?)

% \typeoutComponents{\curentry}
g (catcode 12)
e (catcode 11)
r (catcode 11)
m (catcode 11)
a (catcode 11)
n (catcode 11)
\relax (catcode ?)

... "문자열"(매크로) 동일성이 실패하는 이유를 스스로 추론할 기회를 갖기 위해?

(그런데 하위 질문: 매크로/명령/토큰/제어 시퀀스(예: 로 시작하는 것 \)에 캣코드가 있을 수 있나요?)

답변1

이 명령은 \tl_analysis_show:N요청한 작업을 수행합니다.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\checktokenbytoken}{sm}
 {
  \IfBooleanTF{#1}
   {
    \tl_show_analysis:n { #2 }
   }
   {
    \tl_show_analysis:N #2
   }
 }
\ExplSyntaxOff

\edef\xgerman{\string german\relax}

\checktokenbytoken{\xgerman}
\checktokenbytoken*{german\relax}

터미널에서

The token list \xgerman contains the tokens:
>  g (the character g)
>  e (the letter e)
>  r (the letter r)
>  m (the letter m)
>  a (the letter a)
>  n (the letter n)
>  \relax (control sequence=\relax).
<recently read> }

l.19 \checktokenbytoken{\xgerman}

? 
The token list contains the tokens:
>  g (the letter g)
>  e (the letter e)
>  r (the letter r)
>  m (the letter m)
>  a (the letter a)
>  n (the letter n)
>  \relax (control sequence=\relax).
<recently read> }

l.20 \checktokenbytoken*{german\relax}

(TeX Live 2017 이전 릴리스의 경우 이 기능이 작동하려면 \usepackage{l3tl-analysis}추가가 필요하며 현재는 더 이상 사용되지 않습니다)\usepackage{xparse}\tl_show_analysis:N

답변2

내 솔루션에는 외부 패키지가 필요하지 않습니다. 이 \showcat\macro구현됩니다. 후에

\def\test{ger{$##m}a~n \relax \foo}
\edef\curentry{\string german \relax}

\showcat\test
\showcat\curentry

우리는 결과를 얻습니다:

\test -> 
  the letter g (catcode 11)   
  the letter e (catcode 11)
  the letter r (catcode 11)
  begin-group character { (catcode 1)
  math shift character $ (catcode 3)
  macro parameter character # (catcode 6)
  the letter m (catcode 11)
  end-group character } (catcode 2)
  the letter a (catcode 11)
  the token ~ (catcode 13)
  the letter n (catcode 11)
  blank space   (catcode 10)
  the token \relax (catcode 16)
  the token \foo (catcode 16)
\curentry -> 
  the character g (catcode 12)
  the letter e (catcode 11)
  the letter r (catcode 11)
  the letter m (catcode 11)
  the letter a (catcode 11)
  the letter n (catcode 11)
  blank space   (catcode 10)
  the token \relax (catcode 16)

구현은 다음과 같습니다.

\def\showcat#1{\immediate\write16{\string#1 -> }\expandafter\showcatA#1\showcatA}
\def\showcatA{\futurelet\tmp\showcatB}
\def\showcatB{\let\next=\showcatE
   \ifx\tmp\bgroup \let\next=\showcatC \fi
   \ifx\tmp\egroup \let\next=\showcatC \fi
   \expandafter\ifx\space\tmp \let\next=\showcatC \fi
   \ifx\tmp\showcatA \let\next=\showcatF \fi
   \next
}
\def\showcatC{\afterassignment\showcatD \let\tmp= }
\def\showcatD{\showcatE\tmp}

\def\showcatE#1{\edef\next{\string#1}%
   \immediate\write16{\space\space 
       \ifnum\showcatG<13 \meaningtmp \else the token \next
       \fi \space (catcode \showcatG)}%
   \showcatA
}
\def\meaningtmp{\meaning\tmp}
\def\showcatF#1{}
\def\showcatG{\showcatH\bgroup1\showcatH\egroup2\showcatH$3\showcatH&4%
   \showcatH##6\showcatH^7\showcatH_8\showcatH{ }{10}%
   \showcatH A{11}\showcatH/{12}\showcatH~{13}16}
\def\showcatH#1#2{\ifcat\noexpand\tmp\noexpand#1#2\expandafter\showcatI\fi}
\def\showcatI#116{}

물론 카테고리 0, 5, 9, 14, 15의 토큰은 매크로 본문에 절대 나타나지 않습니다. 그리고 제어 시퀀스(카테고리가 없는 토큰)는 테스트 \showcatG에서 의 간단한 사용을 위해 카테고리 16으로 표현됩니다 \ifnum.

관련 정보