jlreq.cls話……というよりはTeXマクロな話.jlreq.clsの中で次のようなマクロを用意している.
\jlreq@ifendmark{<トークン列>}{<実行1>}{<実行2>}
これは<トークン列>が\jlreq@endmarkならば<実行1>を,そうでなければ<実行2>になるfully expandableなマクロ.ただし,<トークン列>は\jlreq@endmarkのみか\jlreq@endmarkを全く含まないと仮定する.
使うのは次のような時.\cmd{{A}{B}…}みたいなマクロを作りたい時に,まず\def\cmd#1{\cmdA#1\jlreq@endmark}として,一引数ごとに解釈していく\cmdAを定義することで実装する.\cmdA内では#1が\jlreq@endmarkであるか否かの判定をすることになる.
最初は何も考えずに,マクロとか使わず直に
\ifx\jlreq@endmark#1\relax……\else……\fi
と書いていた.#1が\jlreq@endmarkと等しければ明らかによく,そうでなければ#1の最初のトークンが\jlreq@endmarkと一致せずに読み飛ばされる,というわけである.#1の二つ目以降のトークンは読み飛ばし対象となる.
大概これで良いのだが,#1が\iftrue\fiとかで破綻する.\ifx\jlreq@endmark\iftrue\fi\relax\else\fiとなってしまい,\ifxにより\iftrueが食われてしまう.その結果,\fiが\if***より一つ大きくなって破綻する.
実際に使っていてこれで破綻してしまった(先頭に\if***が来る引数を与えなくてはならなくなった)ので,今のでは次のように書いている.
\long\def\jlreq@helper@ifendmark@getfirsttoken#1#2\jlreq@endmark{#1}
\long\def\jlreq@ifendmark#1{%
\expandafter\ifx\jlreq@helper@ifendmark@getfirsttoken#1\jlreq@endmark\jlreq@endmark\@empty
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi}
これは次の例で破綻する:\jlreq@ifendmark{{AA}}.\jlreq@helper@ifendmark@getfirsttokenとかいうマクロで一つ目のトークンだけ取り出した気になっているが,これは一つ目のトークンを取り出すとは限らないわけである.まぁ,jlreq.cls内ではこれで困ることはないのだが.
というわけで,改めてこんな風に手元でしてみた.
\long\def\jlreq@ifendmark#1{%
\expandafter\expandafter\expandafter\ifx\jlreq@ifendmark@#1{}\jlreq@endmark\jlreq@endmark
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi}
\long\def\jlreq@ifendmark@#1#{\jlreq@ifendmark@@#1\@empty\jlreq@endmark}
\long\def\jlreq@ifendmark@@#1#2\jlreq@endmark#3\jlreq@endmark{#1}
つまり,まずグルーピングの始まる{の前までを取得し,更にその一つ目のトークン(これは{}によるグルーピングを含まないはず)をとって比較する.{の前が空っぽだと面倒なので,\@emptyを挟んでいる.すると,\jlreq@ifendmark#1{}\jlrqe@endmarkを二回展開すると,
#1における{の前までが空ならば\@emptyに,- そうでなければ
{の前までの一つ目のトークン(つまり#1の一つ目のトークン)に
\jlreq@endmarkと比較すれば良い.これならば大丈夫だと思うのだが.
ちなみに
\def\jlreq@ifendmark#1#2#3{\ifx**** #2\else #3\fi}
ではなく\@firstoftwoや\@secondoftwoは(TeXあるあるだけど)#2や#3の\if***\fiが対応がとれていなくても大丈夫にするため.上の定義ならば,#2や#3の部分が解釈される時には\ifxによる読み飛ばしは完了している.
記述の中で \jlreq@ifendmark と \jlreq@endmark がゴッチャになってませんか?
返信削除あれ?どこですか?
返信削除あ,最初の方ですね,ありがとうございます.
返信削除