TeX用のプリプロセッサを作ってみた

TeXのnewcommand, renewcommandのスコープがどうも納得できなくて、同じことを思った人が過去にいないはずがないのですでにどっかで公開されてるんじゃないかと思ったのだけど、すぐに見つけられなくて作るほうが早そうだったのでプリプロセッサを作ってしまった。


(注: \Gaussと\invは\newcommandされてる)

使ってみて思ったこと

  • 文字列のreplaceで置き換えているので\Sとか定義すると\Sigmaの前半にマッチしてしまう。
    • プログラミング言語だとトークンに刻んであるから短い変数名を使っても「ぴったり一致する短い名前」としかコンフリクトしないから、スコープを限定すれば1文字変数を使ってもまあ実害がない。でも文字列マッチだと短い名前はその文字列を含む名前を全てシャドーしてしまう。きちんとトークンに刻んでから、完全一致のみで置き換えるべき
  • 引数を取るマクロが欲しい!
    • →これを文字列マッチなんかでやるとカッコのネストで破滅することが眼に見えているのでちゃんとパースする必要がある
  • 今、根元のスコープから順に置換していってるけど、これは適切なの?
    • →置換したものがさらに置換されるケースを考えて、一番近くにあるルールが一番最後に適用されるのが正しいと考えてこの設計にしたが…
      • A: そもそも置換したものをさらに置換するとかすると理解が難しくなるからやめようよ案。変数の解決だって内側から見ていって見つかったらそこで終了じゃないか。(名前の解決だよ派)
      • B: ユースケース「外側で\x→\bm xが定義されていて、内側でphix→\bm \phi(\x)を定義する」を考えると、内側から順に適用するべきだ案。さもないと外側で定義したルールを再利用したルールを作る際に\bm xをもう一度書く必要が出てきてしまう(関数の適用なんだから近い側から順次適用が必要だよ派)
      • !B: それはルール定義のタイミングでルールの本体にその時点で定義されているルールを適用すればいいんだよ派
      • C: (当初の案) ユースケース「外側でEx→\mathbb{E}(x)を定義して、内側の文脈でxが\hat{x}に変わったらx→\hat{x}で『継承&オーバーライド』したい」を考えて外側から…
      • !C: それは引数を取るマクロで解決すべき問題。
    • Bが正解なのかなぁ

このプロトタイプは1ポモドーロで作れたけど、特に「解決の順番」はちゃんと考えないと破滅を引き起こしそうですな。あとパーサ。そこを考えてしっかりつくり直すと時間かかるかもなぁ。この目的ですでに誰か作ってある程度のユーザに使われてバグが潰されたものがあるなら、これはポイっと捨ててそっちに乗り換えた方がいいと思う。あるんじゃないのかなー。ないのかなー。



肝心のソースコードを貼り付けるの忘れてた。

https://gist.github.com/916838