2012/12/15

TeX がむかついたので実装したけど挫折してる話

いきなり私見ですが、「TeX むかつく」という声の大半は、「インストールが苦痛」または「マクロが意味不明で思い通りならない」に分類できるんじゃないでしょうか。 でもまあ、便利なインストーラ付属の分かりやすいLaTeX2eの入門書が改訂を重ねて書店で売ってたりするのだし、これらは普通の用途においては解決策がある問題ということにしておきましょう。

インストールの壁をクリアして、ちょっと凝ったページの出力もできるようになると、 基本的な組版機能に不足はないし、数式にいたってはほぼ唯一無二だし、自作マクロでちょっとした自動化さえできるわけで、 「とにかくTeXむかつく」という心境から、「いっけん意味不明な制約やなぞの挙動には目をつぶるとして TeX しかないな」という心境に至る人も多いはずです。 わたし自身も、組版に関しては、だいたいそういう心境です。残念ながら TeX しかない。

しかし、それでも TeX には実際むかつくことがある! それは、「TeX がドキュメントシステムに向いてない」ことです。「自由すぎる」ともいえます。

ドキュメントというのは、木構造になっているべきです。 キーワードやフォント指定用語などのインライン要素から構成される章、節、段落、図、数式といったブロック要素が、根っこで一つのドキュメントへと束ねられてるようなイメージです。 散文一般とドキュメントに区別があるとしたら、この木構造が必須か否かという点かもしれません。 ドキュメントは、なんらかの木構造と一対一対応がないと、最悪、読み手によって意味が変わってしまいます。 小説ならそれでいいんですが、たとえばジェット機の整備マニュアルなんかだと、それではまずい。 だから、まっとうなドキュメントには木構造が求められるわけです。XMLとかSGMLが重宝されるゆえんです。

だからドキュメントをシステマチックに扱うには、木構造を反映できるファイル形式が不可欠です。 さらに、ドキュメントを木として編集するための仕組みもあればうれしいでしょう。

TeX がドキュメントシステムに向いてないと思うのは、この木構造の観点が欠落しているからです。 もちろん、書き手が注意して執筆することで、 TeX を使って木構造のドキュメントを作ることはできます。 しかし、 TeX で執筆された原稿を扱う汎用の仕組みを作ろうとすると、構文解析すら無理ゲーなことに気づきます。 ドキュメントシステムの処理系を作ろうとしたら、原稿から木を作ってそれを内部表現として扱うと思うのですが、 TeX の場合、原稿を書くための基本的な構文も内臓のマクロ言語によって提供されているため、原稿から木を作りたいだけなのに、原理的にはこのマクロ言語の処理系を書かないと完全なものにならない。そこで実践では「サポートする TeX の構文」を決めうちすることで TeX マクロ言語処理系を実装する手間は省くことになってしまい、だから世の中には「汎用の LaTeX→XML コンバーター」のような仕組みが見当たらないのです。

ないから作った

ないなら作ればいいというわけで、TeXマクロ言語の処理系を Gauche で実装してみたことがありました。TeX-modoki といいます(その後「tef」に改名)。基本的なマクロの展開が扱えます。久しぶりにソース見たら \afterassignment\aftergroup も未実装だったけど、奇数個の \expandafter の塊くらいはまじめに処理できます。

tex-modoki$ cat sample/expandafter-test.tex
\def\A#1#2#3{#1#2#3a}\def\B#1#2{#1#2b}\def\C#1{#1c}\def\D{d}

\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\A
\expandafter\expandafter\expandafter\B\expandafter\C\D

tex-modoki$ gosh -I. main.scm -o text sample/expandafter-test.tex
 dcba

トークンのカテゴリコードもまじめに扱ってるので、それ相応の判定結果が得られます。

tex-modoki$ cat sample/ifcat-test.tex
\catcode`[=13 \catcode`]=13
\def[{*}

\ifcat[* yes \else no \fi % yes

\ifcat\noexpand[\noexpand] yes \else no \fi % yes

\ifcat\noexpand[* yes \else no \fi % no

tex-modoki$ gosh -I. main.scm sample/ifcat-test.tex
 yes   yes  no

未実装の機能が多いので制限だらけですが、簡単な整数計算のマクロなら実行できるっぽいです。「スヤァTeX」に登場する、修正ユリウス通日を求めるマクロも、少し修正は必要ですが実行できました(できるように今朝ちょっと実装を追加した)。「\relax」の変わりに「( ˘ω˘ )スヤァ…」を使うには(ry

tex-modoki$ gosh -I. main.scm -o text sample/julian.tex
   56286

tex-modoki$ cat sample/julian.tex
\input sample/plain % tex-modoki 用に修正した plain TeX マクロを指定

\newcount\xx@cnta
\newcount\xx@cntb
\newcount\xx@year   % 4桁の整数の格納に mathchar を使わない!
\newcount\xx@month  % 2桁の整数の格納に char を使わない!

\def\julian#1{%     % LaTeXじゃないので newcommand を def に
  \edef\xx@tmpa{#1}%
  \expandafter\xx@julian@a\xx@tmpa///\relax
}
\def\xx@julian@a#1/#2/#3/#4\relax{%
  \xx@cnta=#1\relax
  \xx@cntb=#2\relax
  \ifnum\xx@cnta<1 \xx@cnta=\@ne \fi  % 条件式の \@ne を 1 に
  \ifnum\xx@cntb<1 \xx@cntb=\@ne \fi  % 条件式の \@ne を 1 に
  \ifnum\xx@cntb<3\relax
    \advance\xx@cntb by 12\relax
    \advance\xx@cnta by -1\relax
  \fi
  \xx@year=\xx@cnta
  \xx@month=\xx@cntb
  \multiply\xx@cnta by 1461\relax
  \divide\xx@cnta by 4\relax
  \xx@cntb=\xx@year
  \divide\xx@cntb by 100\relax  
  \advance\xx@cnta by -\xx@cntb
  \divide\xx@cntb by 4\relax
  \advance\xx@cnta by \xx@cntb
  \xx@cntb=\xx@month
  \advance\xx@cntb by -2\relax
  \multiply\xx@cntb by 520\relax
  \divide\xx@cntb by 17\relax
  \advance\xx@cnta by \xx@cntb
  \advance\xx@cnta by #3\relax
  \advance\xx@cnta by -678912
  \edef\thejulian{\number\xx@cnta}%
}

\julian{2012/12/25}
\thejulian

というわけでこの記事も TeX & LaTeX Advent Calendar 2012 の15日目に向けて書きました。12日ぶり2回目。

TeX の数式を HTML で出力

さらに副産物として、「素TeXで書いた数式の HTML 出力」ができます! もともと TeX の組版機能を実装するつもりはなく、その力もないのですが、TeX の数式を木構造へと変換できるところまでいったので HTML+CSS でも出力できるようにしてみました。

出力例はこんな感じで、残念なとこもあるけど、まあ見られるかなというレベル。

tex-modoki-1

ソースは、こちらのような、単純な TeX ファイルです。 しかし、 LaTeX はもとより、ごく基本的な TeX の標準マクロさえないので、手元にある LaTeX の数式を変換しても内部表現を吐き出すだけだと思います。

結局挫折

けっこうがんばってここまで作ってたのですが、今では開発をほぼ中止しています。なぜなら、TeX では字句解析時の文脈もマクロからいじれてしまう(ヘンタイ!)という事実に後から気が付いたので、完全なものにするにはゼロから作り直す必要があるからです。TeX むかつく!

数式変換機能の線でもうちょっとがんばって開発を続けようかなと思ったこともありましたが、 LaTeX や ams の膨大な遺産を前に挫折! やっぱり TeX むかつく!

No comments :