マクロツイーター

はてダから移行した記事の表示が崩れてますが、そのうちに直せればいいのに(えっ)

整数を読み飛ばす、続き(2)

「整数を読み飛ばす」話の更なる続き。

今回は e-TeX での完全な解決法(と思うもの)を述べるが、本命の方法の前にまた色々と試行を重ねることにする。

今までは TeX の「整数を読み込む」プリミティブを濫用することを考えたが、全く別の筋道を考える。自力でスキャンする、つまり「トークンを順番に読み込んで検査することで『整数を構成する部分』を見つける」ということはできないか。整数の表現方法の膨大な多様性から考えると絶望的に思える。とすると、「整数を読み込んで単に展開する」プリミティブである \number を使って以下のように解決できるのではないか。

  • 当該の「整数を表すトークン列」の前に「\number」を置く。
  • \number を置く。元々の整数の表現形式に関わらず 10 進表記でその整数が展開される。
  • その位置からスキャンを始めて、1 個以下のマイナス符号、続いて 10 進数字が続く部分を読み捨てる。

予想通り(?)、この方法は上手くいかない。例えば次のような場合を考えれば解る。


\year 12 3{4}5{\foo}

この場合、整数として読み込むべきものは \year のみである。ところが、\number を入れてそれを展開させた後の状態は次のようになる。\year に由来する数字と元々その後にあった数字を区別することはもはや不可能である。


201112 3{4}5{\foo}

その他にも困難がある。「展開」だけで処理しなければならないということは「\futurelet を使って直後が空白トークンやグループ({...})であるかを前もって調べる」という技法が使えず、(区切りなしの)1 引数を取るマクロを無検査で反復呼び出しするしかない(と思う)。ということは、「201112」まで読んで次の空白トークンで止まることすら無理で、結局 \foo まで読んでしまい、しかもその \foo を「戻す」時にそれが元々 { } で囲まれていたかが解らないことになりそうだ。

ところで、今の話からいうと、似たような問題でこの手法が使える場合があることが解る。

直後に続く「寸法」(dimen;伸縮なしの長さ)を読み飛ばすマクロ \gobbledimen を作れ。ただしその寸法は他の型(グルー等)からのキャスト(coerce)でなく、また「単位付き数値」(-99.9cc\tw@\p@ 等)でもないとする。

「単位付き数値」でない真の寸法は \the で展開することができる。そして、今度は、確実にスキャンを適切な場所で止めることができる。何故かというと、寸法を \the で展開した結果は必ず ...pt という文字列になり、終端を表すマーカー(カテゴリコード 12 の「pt」)が存在するからである。実際には 1 文字ずつ読み捨てる必要もなく区切り付引数のマクロが使える。((ここでは \xx@gobbledimen@a の定義自体の明快さのために敢えて行ったが、「小文字のカテゴリコードを変更する」ことはバグの原因になり易く避けられることが多い。例えば、「\catcode`t=12 \catcode`p=12」だともう正しく動かない。))


\def\gobbledimen{%
\expandafter\xx@gobbledimen@a\the
}
{\catcode`p=12 \catcode`t=12 % p と t のカテゴリコードを直接変更(手抜き)
\gdef\xx@gobbledimen@a#1pt{}% カテゴリコード12の「pt」までのトークンを捨てる
}
\edef\test{AB\gobbledimen\lastkern CD} % \test は「ABCD」になる

実は、この「寸法の場合」の話をしたのはちゃんとした理由があって、それは「e-TeX での解決法と大いに関係がある」からである。で、もう随分記事が長くなっているので、解決法はまた後日にする。

〈さらに続く〉