texjporg / tex-jp-build

Minimum source repository to build Japanese TeX processing tools
23 stars 6 forks source link

[npTeX] 欧文トークンに似せたCJKトークン #150

Open t-tk opened 2 years ago

t-tk commented 2 years ago

upTeXにcatcodeが15以下でかつCJKのトークンを追加で導入しよう、という提案です。 [upTeX] JIS-encoded TFM https://github.com/texjporg/tex-jp-build/issues/149 とは別に扱った方がよさそうなので issue を立てます。

背景はこちら。 https://github.com/texjporg/tex-jp-build/issues/149#issuecomment-1279731866

現状の LaTeX3 では regression test(大量に用意されたテストファイル入力 .lvt に対するログ .tlg を比較)の仕組みが (u)pTeX に対しては機能していません。

pTeX では高位ビットが現れるテストファイルの入力中断処理が仕込まれている upTeX では regression-test.cfg で最初から \disablecjktoken している その理由は恐らく

(u)pTeX が「和文(CJK)文字トークン」という独特の物が存在し,また文字コードが中途半端に 0--255 ではないこと(e.g.「あ」できるのに「\catcodeあ」できない) が理解されないためだと思われます。和文(CJK)文字トークンの catcode が 16〜18(19) であることも考慮されておらず「カテゴリーコードは 16 進 1 桁」を前提にしたインタフェースが構築されています(https://github.com/h20y6m/plexpl3/issues/3)。

で、私の提案はこちら https://github.com/texjporg/tex-jp-build/issues/149#issuecomment-1279757248

思いつきですが、その対策として例えばupTeXの仕様の追加で 「catcodeが11で文字コードがある値(例えば0x2E00以上)より大きい場合は漢字トークンとみなす」 「catcodeが12で文字コードがある値より大きい場合はCJK記号トークンとみなす」 のようなものを用意し、それらに対しては 「あ」できて「\catcodeあ」できてしかもCJKトークンである という風にするのはいかがでしょうか?

で @aminophen さんのリプライ https://github.com/texjporg/tex-jp-build/issues/149#issuecomment-1279778635

この特定の値については https://github.com/texjporg/tex-jp-build/issues/135 からだと思いますが,あちらは「OFM に定義された最大の文字コード」だから良かったものの,今回のようなものには使えないように思います。(例えば 0xB7 (U+00B7) は uptex-fonts でも和文扱いを想定した中黒です)

t-tk commented 2 years ago

今回の私の提案は、「本格的に kcatcode 16以上をすべてcatcode15以下に移し替えよう」という前提ではありません。 upTeX では、0x80..0xFF の間で欧文と和文(CJK文字)を区別する必要があって、開発初期の頃からの悩みのタネでした。15以下のcatcodeで0xFF以下のcharcodeではどうしても欧文と区別がつかないので拡張する必要がありました。(U+00B7が話題になったのは時期的には後の話ですが、本質的にはupTeXの一番最初からある問題です。) で、今回の提案は、「LaTeX3 の regression test」のような場でも(u)pTeXの立場を深く理解してもらうまでいかなくとも、せめてtest caseに混ぜてもらえる程度には欧文TeXに近づけよう、というものです。 従来のkcatcode16以上の動作は、機能として重複したままそのまま維持したいです。 私の提案の中の「特定の値」は実は0x2E00である必要はなく、0x0100以上でも0x2000でもいいです。 0x2E00の境界は、dvipsの「OFM→JFM の縦組みの読み替えをするか?」の判定に使いましたが、今回はもっと小さい値でも構いません。

「catcodeが11で文字コード 0x4E00はU+4E00で漢字の「一」でして、それをLaTeX3で処理したいです。」という風にしてそれをLaTeX3の開発チームに理解してもらえればよいです。 特定の値は0x2000でもよくて、 「catcodeが12で文字コード 0x2603はU+2603で「☃」でして、それをLaTeX3で処理したいです。」という風にしてそれをLaTeX3の開発チームに理解してもらう、という風でもいいです。 U+1FFF以下は、CJK以外の国々の言語の普通の文字(U+00B7のようなごく少数の例外を除く)が集まっていて、U+2000..206F が "General Punctuation"なので特定の値は0x2000でも妥当な感じがします。

aminophen commented 2 years ago

issue の分割と検討をありがとうございます。

まず『LaTeX3 をサポートするうえで (u)pTeX にとって最低限必要なのは何か』を把握する必要があると思います。

t-tk commented 2 years ago

今はブレインストーミング的なフェーズだと思うので、外れかもしれないことを言うかもしれません。

\disablecjktoken 既定化」とのことですが、理解出来ていません。 latexの中身について全然知らないのですが、 現状の uplatex.ltx を見ると latex.ltx, plcore.ltx, uplcore.ltx の順番に読んでいます。 冒頭で \disablecjktoken 既定でも latex.ltxplcore.ltx の間に \enablecjktoken を入れれば問題ないようにすることが出来そうに見えます。 それもダメということでしょうか? \enablecjktoken, \disablecjktoken はあくまでupTeXエンジンの入り口でCJKトークンに変換するかしないかを決めているだけだったはずで、既にCJKトークンになったものを無効化するとかいう風にはしなかったはずです。 (u)pTeX の特徴的な仕様を考えてみます。

  1. kcatcode 16,17,18,19 を持つ。
  2. charcode 0x0100..0xFFFFFF が可能。
  3. 和文用tfm(jfm)を使うが欧文tfmとは全く別である。
  4. 和文フォントと欧文フォントは個別に管理され、カレントフォントは欧文フォントと和文フォントの組である。
  5. 和文フォントあるいは和文-欧文間に関わる組版規則がいろいろあって(u)pTeXエンジンがまかなっている。
  6. kcatcode や cjktoken 化の設定の仕様いろいろ。(ブロック毎のkcatcodeとか\enablecjktokenとか)
  7. その他。

(u)pTeX が欧文TeXからかけ離れている点はいろいろあると思いますが、LaTeX3開発で障害になるのはどれでしょうか。 kcatcode の取る値はまだupTeXと非互換になってもダメージが小さいように見えます。 charcode の範囲は luaLaTeX, XeLaTeX でも可能なのだから欧米の開発者からも理解されるような気がします。 それ以外は(u)pTeX互換から離れようとした場合にかなりダメージが大きいように思います。 (u)pTeX から離れて luaTeX-ja に完全移行という選択肢もあると思います。 kcatcodeを振る際の仕様とかは、欧文TeXと違いすぎるものの欧文TeXと関わりのある基本的機能ではないのでLaTeX3開発とは関係が薄いようにも思います。 (u)pTeX と luaTeX-ja の間になるであろう「upTeX 非互換だが LaTeX3開発に同期しやすい新CJK-TeX」の仕様とは?

ごく少数の例だとしても「その文字を CJK トークン扱いさせたい状況においてそれを実現できる手段」

現状 \kchar でどんなcharcodeでもCJKトークンになるようにしてあったような記憶があります。

仮に和文(CJK)/欧文の区別を維持できるとして,その境界を特定の文字コード値とするのは,後々その値を変えたくなるような禍根を残さないものとしたい

その閾値を決めるプリミティヴを導入すれば済む話のように思います。都合に合わせ設定し直せばよいです。 というか、そもそも、cjktoken化の範囲は現状(ブロック毎に)コントロールできるようになっているので、現状のupTeXの仕様不足という話でないように見えます。 「LaTeX3 の regression test」が \disablecjktoken になっていることも本質でないように見えます。 「LaTeX3の開発中のブランチのものが cjktoken を有効にしたとたん動かなくなる事態が起きるが、そのことに気づいてもらえない」という問題なのだ、と感じます。

t-tk commented 2 years ago

もう一つ。 「和文(CJK)文字トークンの廃止」でも和文の組版品質を pTeX と同等以上に、ということを目指しているのが luaTeX-ja なのだと思っていました。 luaTeX-ja のようなアプローチでは無くて、 (u)pTeX に存在する仕様でかつそれを捨ててもよくて、それでも和文の組版が維持できる、とかイメージが浮かびません。

h20y6m commented 2 years ago

全然追いつけていないのですが

(u)pTeX が欧文TeXからかけ離れている点はいろいろあると思いますが、LaTeX3開発で障害になるのはどれでしょうか。

現状どうしたらいいのかわからないのは

でしょうか。

それから欧文については8-bitエンジンだけど和文文字トークンという異質なものが入ってくるという点でしょうか。

LaTeXでは(u)pTeXは8-bitエンジンとして扱われていて、8-bitエンジンではUTF-8でエンコードされたトークン列を前提としています。この前提のもとコードポイント単位での処理は、先頭のトークンを取得して何バイトのUTF-8バイトなのか判断してそのバイト数分のトークンを1文字として処理しています。 例えば ^^e6^^97^^a5 の場合先頭のトークンの文字コードは 0xE6 で3バイトのUTF-8バイト列なので後続の2トークンを追加で取得して3バイトを1文字として処理します。 ここで和文文字が入るとこの処理が破綻します。例えば 日本語 だと先頭のトークンの文字コードは 0x65E5 なので……となって「UTF-8の先頭バイトとして不正なのでエラー」とか「0xF0 以上なので4バイトなので追加で3トークン読んでこの場合は足りないので終端マーカーを巻き込んでよくわからないエラーがでたり無限ループしたり」とかが起こります。

あとupTeXの場合は0x80--0xFFの範囲に和文文字があるためUTF-8の2バイト以上を構成するはずの文字コードを持ったトークンがUTF-8バイト列の中に単独で現れるといったことが起こります。

aminophen commented 2 years ago

冒頭で \disablecjktoken 既定でも latex.ltx と plcore.ltx の間に \enablecjktoken を入れれば問題ないようにすることが出来そうに見えます。それもダメということでしょうか?

latex.ltx だけを \disablecjktoken で読むだけでは足りなくて「ユーザが書く LaTeX ソースの中身に現れる和文文字トークンが悪さをする可能性がある」ということです。さらに別の問題は「ptexenc による ^^-記法 への変換」が regex の ^ による文字除外シンタックスと衝突しうるということです。

現状 \kchar でどんなcharcodeでもCJKトークンになるようにしてあったような記憶があります。

それは CJK ノードの生成であって,CJK トークンを生成しているのではありません。「CJK ノードが存在すること」は LaTeX3 と一切衝突せず,TeX 入力を解釈するうえで「CJK トークンが存在すること」が課題になっています。

h-kitagawa commented 2 years ago

CJK トークンを生成

e-upTeX なら,\Uchar, \Ucharcat でできます:

\disablecjktoken
\expandafter\expandafter\let\expandafter\A\Uchar"3042\relax
\message{\meaning\A}
\bye

極端なことを言えば,「和文文字ノード」(aminophen さんの言葉だと「CJK ノード」)があれば,「和文文字トークン」がなくても

だけでもなんとかなりうると思います.

いくつか着地点は思いつくのですが,文章化できるほどには考えをまとめる時間がありません……(後で書きます).

t-tk commented 2 years ago

あまりよく分かっていませんが 「一見欧文トークンに見えるもの」から「CJKノード」が生成できれば目的(LaTeX3と衝突せずCJKの組版ができる)ということでしょうか。 issueのタイトルを変更してみました。もっと適切な言い方があればどなたかお願いします。

aminophen commented 2 years ago

「一見欧文トークンに見えるもの」から「CJKノード」が生成できれば目的(LaTeX3と衝突せずCJKの組版ができる)ということでしょうか。

端的に書いていただいてありがとうございます。私の理解と合っています。

t-tk commented 2 years ago

雑感です。

こういう話を聞くとCJKノードが内部バッファでもUTF-8のバイトの並びでなければならない、という状況は理解します。 upTeXの最初の頃2007年の状況では、T1 や T2A などの8bit欧文と和文の混在は想定していましたが LaTeX がこれほどまでUTF-8化することは想像できませんでした。 upTeXはpTeXの和文をUnicodeのCJKに置き換えるのが根幹にあり、CJKを内部バッファでUTF-8の並びにすることは全く頭にありませんでした。

全く別のソフトですが、Unicode化したときの内部バッファは、upbibtex, bibtexuはUTF-8, upmendexはUTF-16でして、それを採用した事情もさまざまです。 LaTeXのUTF-8化が進んだ場合、upTeXでは、CJKがUTF-32改で欧文がUTF-8の二階建て構造となり、見通しが良くない状況に陥ることは理解できます。

luaLaTeX, XeLaTeX のCJKは内部バッファでUTF-8になっているのでしょうか?

h-kitagawa commented 2 years ago

luaLaTeX, XeLaTeX のCJKは内部バッファでUTF-8になっているのでしょうか?

LuaTeX は内部バッファが UTF-8 です (tex/textoken.c, utils/unistring.c).

XeTeX は,ビルド時に作られる xetexd.h を見ると EXTERN UnicodeScalar * buffer ; とあるので,内部バッファは Unicode 値のようです.

t-tk commented 2 years ago

ありがとうございます。

XeTeX は,ビルド時に作られる xetexd.h を見ると EXTERN UnicodeScalar * buffer ; とあるので,内部バッファは Unicode 値のようです.

XeLaTeXでは https://github.com/h20y6m/plexpl3/issues/2 の問題は発生しないのでしょうか?

h20y6m commented 2 years ago

極端なことを言えば,「和文文字ノード」(aminophen さんの言葉だと「CJK ノード」)があれば,「和文文字トークン」がなくても

和文文字の UTF-8 バイト列,例えば ^^e3^^81^^82 から,きちんと和文文字ノード「あ」が作られる

これは欧文文字トークンは8-bit ASCIIのまま和文文字トークンをなくしてしまうということでしょうか? たしかに「和文文字トークン」がなくても「和文文字ノード」があれば日本語組版は可能そうではありますが……。

これだと「和文文字1文字=1トークン」の前提が使えなくなるのでつらいですね……。 jsclassesなどでやっている \futurelet で段落はじめの『「』の位置調整のようなものも簡単にはできなくなりますし。

(それに今のLaTeXは8-bitエンジンの場合0x80--0xFFの範囲の文字はカテゴリコード13になっているのでそのままではソースに「あ」とかいても展開されて「^^e3^^81^^82」というトークン列が残らないという問題も……)

個人的には(可能かどうかは置いておいて)和文文字トークンをなくすなら欧文文字トークンはUnicodeになってほしいです。

こういう話を聞くとCJKノードが内部バッファでもUTF-8のバイトの並びでなければならない、という状況は理解します。

「内部バッファ」がUTF-8かどうかというのはあまり重要ではないと思います。 それよりはTeX言語から見た「文字トークン」がどのような文字コードを持っているかだと思います。

pdfTeXでは文字トークンは0x00--0xFFの文字コードを持ちます。 現在のLaTeXはこの文字トークンがUTF-8の規則に従って並んでいる前提でUnicodeに関する処理をします。 pdfTeX自身がこれらをUTF-8として処理しているわけではないはずです。

UnicodeエンジンのXeTeXとLuaTeXの場合文字ト-クンはU+0000--U+10FFFFの文字コードを持ちます。 エンジンレベルで全てのUnicodeコードポイントがASCIIの範囲と違いがないので特別な処理は必要ありません。

upTeXの場合欧文文字トークンについてはpdfTeXと同様の処理が必要になります。 和文文字トークンについてはUnicodeの範囲の文字コードを持ちますがUnicodeエンジンとは異なる性質を持ちます。 和文と欧文で処理を切り替える必要があるので複雑になります。

XeLaTeXでは h20y6m/plexpl3#2 の問題は発生しないのでしょうか?

発生するのはupTeXのみです。

例えば文字コード0xB1をもつトークンは pdfTeXとpTeXでは ^^b1 のみ、XeTeXとLuaTeXでは ±^^b1± は同一のトークン)のみですが、 upTeXでは ^^b1±^^b1± は異なるトークン)の2種類があり文字コードだけでは区別できません。

同じ文字コードで和文と欧文が重なっているupTeX特有の問題です。

h-kitagawa commented 2 years ago

どうすればいいのか私の中でいまいち見えてきません. 個人的には「文字トークン自体に和文欧文と区別をつける必要は(必ずしも)ない」と思っていますが,0x80--0xFF の件を考えると悩ましいです[^1].

以下は適当に思いついた一つの案です.

[^1]: LuaTeX では \attribute の仕組みがあり,コード範囲による和文・欧文の区別以外にも「このノードだけ欧文文字ノード」「このノードだけ和文文字ノード」が比較的楽に実現できるという事情があります.

[^2]: 18 (other_kchar) と 16, 17, 19 との性格の違い.

[^3]: \lccode等の値は 0x100 以降も許すか?

t-tk commented 2 years ago

JIS X 0208で和文(全角)でかつUnicodeでU+00FF以下の文字コードが欧文の0x80..0xFFの文字コードが重なっているところが課題ということですね。upTeXの最初の頃と悩みが変わっていない。 「新upTeX」(そろそろ名前を付けた方が議論しやすいように思います。何かいい名前募集中)の文字コードを

のようにすれば、欧文と和文の文字コードの重なりが解消され、現状の upTeXとの差分は小さくて済みます。 あるいは、U+00FF以下で欧文とJIS X 0208が重なっている8文字とU+00B7の中黒だけ例外的にUnicodeではない内部コードに移してしまう方法もあると思います。

XeTeXとLuaTeXでは ^^b1 は常に ± なのですね。 upTeXでは「欧文は pdfTeXと同じ」という仮定でしたが、その仮定をやめて、XeTeXとLuaTeXと同じように新upTeXでは「 ^^b1 は常に ± 」、0xFF以下の和文と欧文の区別は何らかの別の手段で実現する、という風な方法はないでしょうか?


JIS X 0208に加え中韓フォント対応で入れた中黒 U+00B7 も入れてリスト化しておきます。備忘録として。

区点 JIS SJIS EUC UTF8 UTF16 name
01-13 212D 814C A1AD C2B4 00B4 ´ Acute Accent
01-15 212F 814E A1AF C2A8 00A8 ¨ Diaeresis
01-62 215E 817D A1DE C2B1 00B1 ± Plus-Minus Sign
01-63 215F 817E A1DF C397 00D7 × Multiplication Sign
01-64 2160 8180 A1E0 C3B7 00F7 ÷ Division Sign
01-75 216B 818B A1EB C2B0 00B0 ° Degree Sign
01-88 2178 8198 A1F8 C2A7 00A7 § Section Sign
02-89 2279 81F7 A2F9 C2B6 00B6 Pilcrow Sign
---- C2B7 00B7 · Middle Dot
aminophen commented 2 years ago

何かいい名前募集中

安直ですが jpTeX に一票です。

t-tk commented 2 years ago

@h-kitagawa さんの案:

を多少変更した案はどうでしょう:

aminophen commented 2 years ago

まだついていけてないのですが… \catcode の話「全 Unicode 範囲について,…」は,「何バイトが1個の文字トークンになるか」とも合わせて考える必要がありますよね。

新しい仕様では???

従来の upTeX での \kcatcode の切替に「Unicode 文字を直書きしてバッククオートで値取得」を使うと文字トークンの区切り変化に対応できず,16進数の値を指定するほうが安全でした。同様に,\prebreakpenalty 指定などで多用される「バッククオートによる文字コード取得」や LaTeX の \@tfor でも,どこまでが1文字トークンになるかが影響します。

h-kitagawa commented 2 years ago

「何バイトが1個の文字トークンになるか」

upTeX の \kcatcode=15 をここで活かすという手もありますね. たとえば,内部バッファから U+xyzw(≧U+0080)の UTF-8 バイト列をトークン化する際に

とするとか[^1].ただその場合

従来の upTeX での \kcatcode の切替に「Unicode 文字を直書きしてバッククオートで値取得」を使うと文字トークンの区切り変化に対応できず

の問題は残ることになります.

「見た目 1 文字(Unicode 1 文字) = 1 トークン」がもちろんスッキリしているのですが,「実際に欧文 Unicode フォントを使うことはできない」のが新たな火種になったら困るなあ,という思いもあります.

[^1]: そうすると,\kcatcode より \tokenmode"xyzw=0(1 バイト 1 トークン), 1("xyzw という一つの(和文)文字トークン)としたほうが単純化できる?

t-tk commented 2 years ago

名前の案について、upTeX/upLaTeXを命名したときはあまり強く意識していなかったのですが、pTeX/pLaTeXとまとめて言いたいときに (u)pTeX/(u)pLaTeX と書けるようになっていた点は結果的に便利でした。 なので、今回も ?pTeX/?pLaTeX のような形が便利だろう、と思います。 長すぎるのも好ましくないので ? は出来れば1文字がいいです。 それと、今回の新しいものはe-TeXが必ず含まれる、でいいですよね。

jpTeX は一つの有力候補だと私も思いますが、Japan を強く連想させすぎないか、気になります。CKの人もできれば招き入れたいと思います。 ブレストを兼ねてもう少し挙げてみます。

私としては、この中では apTeX が割と好みです。

aminophen commented 2 years ago

aptex は ptex-ng の別名として既にあるんですよね…。(make すると aptex が ptex-ng のコピーとして生成する)

aminophen commented 2 years ago

他も書いてみます。


個人的には,今回のフォーク目的が「日本で愛されてきた (u)pLaTeX の系譜を終了させないこと」だと思っているので,新たに CK の人を取り込む発想には乗りにくいです。確かに取り込めたほうがモチベーションにはなるのですが…。

t-tk commented 2 years ago

「日本で愛されてきた (u)pLaTeX の系譜を終了させないこと」

なるほど。それは腑に落ちます。

h-kitagawa commented 2 years ago

CKの人もできれば招き入れたい

もちろんそれができればよいのですが,もし彼らが XeLaTeX, LuaLaTeX をすでにメインにしているのであれば,pTeX 系統に入ってくる可能性は少ないと思います.

実際の CK の状況は知らないのですが,ちょっと検索したところ

が出てきました.

h-kitagawa commented 2 years ago

名称すら決まっていない段階ですが,新エンジン用にディレクトリだけ作ったものをhttps://github.com/h-kitagawa/texlive-source/tree/kitagawa_zptex_concept に置きました.バイナリができることだけ確認しています.

aminophen commented 2 years ago

change file は現状だとたくさんありすぎて管理しきれないので,日本語化関連を zptex-base.ch というファイルにまとめています.XeTeX のように zptex.web としてまとめるのも一つの手?

そうですね,まとめる方向に +1 です。過去の #32 とも絡みますが整理したいです。

t-tk commented 2 years ago

名称案追加です。

個人的には結構 +1 です。→ 過去にありました。没です。 spanish TeX で spTeX: http://es.tldp.org/CervanTeX/CervanTeX/FAQ/FAQ-CervanTeX/FAQ-CervanTeX-10.html

中国語: ctex のチームがおそらくxeCJK & XeTeX推し 韓国語: ko.tex が pdfLaTeX/XeLaTeX/LuaLaTeX に対応 とのことですが、確かにそのように見えます。 将来CJKのチームが開発リソースをある程度でも共通化する未来は見えませんね…

aminophen commented 2 years ago

新エンジン用にディレクトリだけ作ったもの https://github.com/h-kitagawa/texlive-source/tree/kitagawa_zptex_concept

https://github.com/aminophen/texlive-source/commit/48876e0d64b45adc501d6c2941df9ae19ac2666d で #149 の変更にも追随。さてここから仕様をどうするか…。

aminophen commented 2 years ago

@h-kitagawa さんの案:

  • C≦15 and C≠11, 12 and 0x100≦X のトークンは「ノードを作らない(欧文)文字トークン」である

これは「0x100≦X のアクティブ文字 (C=13)」とかも含まれると思いますが,それを例えば \string した時に仕様からはみ出しそうです。(C=12 and 0x100≦X になる?)

aminophen commented 2 years ago

仕様選定の取っ掛かりは @h20y6m さんのコメントにしようと思います。

和文文字トークンのカテゴリコードとして何を返すべきか

こちらは上の仕様案「和文文字コード 0x100≦X からも \catcode の読出できるようにする」で(個別に \catcode, \kcatcode を指定可能に…であれ,機械的に11,12に読み替える…であれ)どうにかなりそうですが

0x80--0xFFの範囲で欧文と和文が区別できない

これは upTeX 開発当初からの問題と同じで

欧文については8-bitエンジンだけど和文文字トークンという異質なものが入ってくる

これは「欧文文字は1バイト1トークン」「和文文字は見た目の1文字で1トークン」で最初から解釈が分岐してしまう現在の仕様では解決困難なように思います。

じゃあどちらに寄せるのがいいかと考えると,(u)pTeX の資産を考えると「和文文字トークンを完全に廃止してしまう」のは \futurelet とか \prebreakpenalty などのバッククオートによる文字コード取得や LaTeX の \@tfor などを捨てることになるので,LuaTeX や XeTeX のように「見た目の1文字で1トークン」に寄せることで UTF-8 前提の 8-bit エンジン用のコードを使わないことにする方が自然だと思います。

どちらでも構いませんが,先の「0x80--0xFFの範囲で欧文と和文が区別できない」の根源は

「1文字1トークン」の和文文字を UTF-8 → Unicode 値に変換したときに 0x80--0xFF の文字コードになりうるのに,その行き先に「1バイト1トークン」の欧文文字トークンも存在すること

だと思うので,一律に「1文字1トークン」とすれば全て良い方向にむかうのではないでしょうか。

[edit] 内部バッファを UTF-8 にするか Unicode にするかとは無関係だったので修正

aminophen commented 2 years ago

クリーンな設計を一から立てるなら,こんなのはいかがでしょうか。

少し冗長な感じもしますが,和欧文の区別・\catcode・\kcatcode という3つの属性が独立していればスッキリしますが,メモリを食いそうなので可能かどうかは検討していません。

h-kitagawa commented 2 years ago

和欧文の区別・\catcode・\kcatcode という3つの属性が独立していればスッキリしますが,メモリを食いそうなので可能かどうかは検討していません。

1 memory_word は 8 バイトなので,素直に全部をテーブルに格納するとして 3*(2^16*17)*8 = 25.5*2^20 バイトを食うことになります. アクティブ文字とかも考えるともうちょっと増えると思います. ただ,「現在の計算機環境ならば問題ではないだろう,XeTeX も同じように全文字テーブルに格納しているし」と思います(富豪的プログラミングに毒されすぎでしょうか?).

ちなみに,e-TeX でレジスタを拡張した際は

[TODO] 文字コード X ≧ 0x100 の欧文文字トークンをどうするか? → 欧文 TFM で未定義なので「ノードを作らない」と定めるか,OFM を使うか,別途 \usepackage[utf8]{inputenc} 並みに 8-bit な TFM の欧文フォントを使える仕組みか,何かしらの用意が必要。

これにどれくらいの手間がかかるか,で全体の方針も決まってきそうな気がします. LaTeX では \DeclareUnicodeCharacter{00F6}{\"o} のように Unicode 値→出力命令へのマッピングが定義されているようなので,「\DeclareUnicodeCharacter の定義を書き換え,対象になっている文字をアクティブ化する」とかでなんとかならないでしょうか?

→(edit) アクティブ化だと\Gödel みたいな制御綴が書けないですね(実際,(pdf)latex だめ).「1 文字 1 トークン」という方針だとサポートされる方が自然な気がしますが,何か良い方法はないでしょうか? \tonoderecipe"xyzw={<token list>} みたいなものを導入する?

aminophen commented 2 years ago

素直に全部をテーブルに格納するとして 3*(2^16*17)*8 = 25.5*2^20 バイトを食う

upTeX では uptex-base/01uptex_doc_utf8.txt によると

として文字トークンを表現しているようですので,新仕様案についても

というのを想定していましたが, テーブルへの格納が必要なのでしょうか。

[TODO] 文字コード X ≧ 0x100 の欧文文字トークンをどうするか?

これにどれくらいの手間がかかるか アクティブ化だと \Gödel みたいな制御綴が書けないですね...(中略)...「1 文字 1 トークン」という方針だとサポートされる方が自然な気がします

そうですね。アクティブ化に頼らずに何らかの方法で「Unicode 値→出力命令へのマッピング」を定義できるようにしたいので,ご提示の \tonoderecipe"xyzw={<token list>} のようなものがあれば良さそうです。(実装が大変かどうかはよく分からない…。多分 WEB 言語層よりも TeX マクロ層の方が大変そう)

t-tk commented 2 years ago

仮称のzptexのzを借りてzcatcodeを導入すれば 「和欧文の区別・\catcode・\kcatcode という3つの属性」は「zcatcode一つ」から引き出せると思います。

upTeX 英文字 欧文記号 漢字 かな CJK記号 ハングル
catcode 11 12 NA NA NA NA
kcatcode NA NA 16 17 18 19
max 0xFF 0xFF 0xFFFFFF 0xFFFFFF 0xFFFFFF 0xFFFFFF
バイト列 UTF-8 UTF-8 UTF32改 UTF32改 UTF32改 UTF32改
たたき台として例えば: zpTeX 英文字 欧文記号 漢字 かな CJK記号 ハングル
zcatcode 11 12 16 17 18 19
is_cjk F F T T T T
catcode 11 12 11 11 12 11
kcatcode NA NA 16 17 18 19
max 0xFFFFFF 0xFFFFFF 0xFFFFFF 0xFFFFFF 0xFFFFFF 0xFFFFFF
バイト列 UTF32改 UTF32改 UTF32改 UTF32改 UTF32改 UTF32改
aminophen commented 2 years ago

一応「クリーンな設計」について補足しておきますと,この設計は「3 つの特性が独立である」というところが重要な点です。例えば「\kcatcode 18 → \catcode 12」のような制限や読替は一切行わず,また N/A という未定義値も残さないのが好ましいと思っています。

これにより issue のタイトルである「欧文トークンに似せた CJK トークン」を突き詰め,見かけ上は文字トークンを欧文と同様のコードで扱えるようにする(実際には CJK トークンかもしれないが,全く意識する必要がなくなる)ことができないか? と考えています。

[edit] このように CJK トークンを隠しても,海外からも

だけは見えてしまうのが避けられないと思っています。


実装については

「和欧文の区別・\catcode・\kcatcode という3つの属性」は「zcatcode一つ」から引き出せる

そういうのでも良いですね。(zcatcode というものが

の計7bitを格納するものという想定)

h-kitagawa commented 2 years ago

テーブルへの格納が必要なのでしょうか。

個々の Unicode 文字ごとに \catcode,\kcatcode, \is_cjk 情報を格納する部分,ちょうど pTeX で言うところの

@ Region 4 of |eqtb| contains the local quantities defined here. The
bulk of this region is taken up by five tables that are indexed by eight-bit
characters;
...
@d cat_code_base=auto_xspacing_code+1
  {table of 256 command codes (the ``catcodes'')}
@d kcat_code_base=cat_code_base+256
  {table of 256 command codes for the wchar's catcodes }

にあたる部分の話をしていました.

各トークンでは和文・欧文の区別が固定なので,upTeX と同じ 29 bit 表現

で良いと思います(@aminophen さんの 31 bit 案だと,文字トークン以外を表すことができなくなりそう).

aminophen commented 2 years ago

個々の Unicode 文字ごとに \catcode,\kcatcode, \is_cjk 情報を格納する部分

理解しました。確かに…。

各トークンでは和文・欧文の区別が固定

それはそうなのですが「最初に CJK トークンかどうかを判定しないと \catcode を読書できない」という状態が続いてしまうと LaTeX3 開発者が扱いづらそうです。欧文トークンに似せるためには「トークンにも 3 つの独立な属性情報を読書可能」でないと駄目ではないか,と思っています。31bit 使ってはいけないということであれば,文字コードを 24bit (上限U+FFFFFF) ではなく 21bit (上限U+10FFFF) にすれば少し節約できます。

t-tk commented 2 years ago

このように CJK トークンを隠しても,海外からも

  • 和文文字トークン (kcatcode=16,17,18) 直後の改行は空白にならない
  • 和文記号 (kcatcode=18) 一文字のコントロールシンボルの文字列化では空白が補われない (#37)

だけは見えてしまうのが避けられないと思っています。

少なくともこの前者は流石にこちら(CJ)の事情を説明して容認してもらいたいと私は思います。

入力と出力で改行と空白の関係で期待しているものが反対側の例ですが、改行と空白の入れ方がCJでは欧文と違うんだ、と国際的なオープンソースの開発で認知された例だと思う例を挙げます。 groffでは 1.21 で、入力でベタ打ちのCJK文字が続いた場合にも、出力に改行を入れられるような設定が導入されています。 ( Kは分かち書きをするので必須とは言えないですが ) 以下、ChangeLogより


o The new class request assigns a short name to a set of characters which can be referred to in the cflags request. This is especially useful to control line-breaking and hyphenation rules in CJK languages.

o Three new values for the cflags request have been added, which are needed for proper CJK support.

128  prohibit before but allow break after character
256  prohibit after but allow break before character
512  allow break before and after character
t-tk commented 2 years ago

「欧文トークンに似せる」というのが、どの位似ている必要があるのか、あるいはLaTeX3の開発の立場で、「見かけは欧文と似ていて大体欧文と同じような動きをするがわずかに動作が違うもの」がどこまで許容できるのか、ぴんと来ません。 少々違う程度に収まっておくようにすることで、CJKあるいはzpTeX拡張を壊さずにLaTeX3の開発を進めてもらえないものだろうか、と思います。

CJの改行は違うんだよ、と英語で解説している文書を、上記のgroff以外でもどこかで読んだことがあったような記憶があります。説得の材料になるかもしれないので探してみます。

aminophen commented 2 years ago

和文文字トークン (kcatcode=16,17,18) 直後の改行は空白にならない 和文記号 (kcatcode=18) 一文字のコントロールシンボルの文字列化では空白が補われない

私も上記 2 点くらいなら,違いが許容されると思っています。(しかも都合がよいことに LaTeX3 では \ExplSyntaxOn していて,この状況では空白トークンは読み飛ばされます)

「欧文トークンに似せる」というのが、どの位似ている必要があるのか

今の理解としては「見かけ上は文字トークンを欧文と同様のコードで扱えるようにする」(実際には CJK トークンかもしれないが,全く意識せずに自由な値の \catcode を設定でき,設定したとおりの値を読出せる)程度でよいのではないかと考えています。

t-tk commented 2 years ago

ちょっと探してみましたが、cjk linebreak でググるだけで英語の解説がぞろぞろ引っかかりますね。 流石にこれは有名な話で「分かってください」と言えると思います。

https://developer.mozilla.org/en-US/docs/Web/CSS/line-break https://support.ptc.com/help/arbortext/r8.1.0.0/en/index.html#page/admin/admin/help10034.html https://tex.stackexchange.com/questions/8659/linebreaks-for-cjk-languages

t-tk commented 2 years ago

「upTeX と同じ 29 bit 表現」のところですが、確か上限は適当に決めたので拡張するのは難しくなかったと記憶しています。 omegaのソースを眺めながらuptex-m.chのこのあたりを適当に触った覚えがあります。

@d cs_token_flag=@"1FFFFFFF {amount added to the |eqtb| location in a
  token that stands for a control sequence; is a multiple of~@@"1000000, less~1}

それと、upTeXの文字コード値の上限を Unicodeの上限 U+10FFFF より大きい 0xFFFFFF にした理由は、将来的に 0x110000 以上を Unicode互換ではない upTeX の内部コードとして使うつもりでした。 現状 OTFパッケージの vf の文字コードの一時利用先として使っています。 それ以外に、IVSの漢字や、合成でしか表せない濁点・半濁点付き仮名など(Unicodeでは複数のコードポイントの合成文字として定義されていて一つのコードポイントで表せない文字)をupTeXで組む際に、内部コードとして使いたいと思っていました、が実現には至っていません。

aminophen commented 2 years ago

上の「クリーンな設計」の実装の取っ掛かり部分です。

h-kitagawa commented 2 years ago

最初に CJK トークンかどうかを判定しないと \catcode を読書できない」という状態が続いてしまうと LaTeX3 開発者が扱いづらそうです。欧文トークンに似せるためには「トークンにも 3 つの独立な属性情報を読書可能」でないと駄目ではないか,と思っています。

やっと意図がわかりました……\kcatcode と \catcode が連動しないからなのですね.

ただ,「catcode=11, kcatcode=18」「catcode=12, kcatcode=16」のような状況がいまいち自然なものには思えてきません.\kcatcode のしがらみを無視して良いなら

とかする手はあるかもしれません.

aminophen commented 2 years ago

\kcatcode と \catcode が連動しないからなのですね

はい。伝わりづらかったようですみません…。

「catcode=11, kcatcode=18」のような状況がいまいち自然なものには思えてきません.

確かにいまいちですが,\string や \meaning の仕様設計で迷いました。従来の upTeX では「和文文字を \string しても kcatcode は変わらず元のまま」「欧文文字の catcode は 12 に変わる」なので。

※ \string と同じ convert 系の文字列生成命令は \kansuji にも当てはまるので「\kansuji トリックによる和文文字生成」という古いコードに影響することを懸念。

aminophen commented 2 years ago

upTeXの文字コード値の上限を Unicodeの上限 U+10FFFF より大きい 0xFFFFFF にした理由

知りませんでした。なるほど,ありがとうございます。

現状 OTFパッケージの vf の文字コードの一時利用先として使っています。

これは「文字コード上限 U+10FFFF に落とすと,OTF パッケージは使えなくなる(改修が必要)」ということを仰っていますか?

aminophen commented 2 years ago

クリーンな設計 実装の取っ掛かり部分

連動or独立の件でほかに迷っているところとしては「\catcode を設定した場合に,それを別途 \iscjk=0 にしないと欧文扱いにならない」という状態でよいか?です。例えば が和文扱いの時に \catcode`あ=13 で値書込できて \catcode`あ を読出せたとして,直後に と書いてもまだ欧文扱いにはなっていないのは非直感的。

h-kitagawa commented 2 years ago

(朝で時間がないので箇条書きで書きます)

[^1]: 上のコメント で「『catcode=11, kcatcode=18』『catcode=12, kcatcode=16』のような状況がいまいち自然なものには思えてきません」と書いたのはこういう違和感に起因しています.

aminophen commented 2 years ago

欧文文字トークンに \kcatcode の情報が必要な理由

h-kitagawa commented 2 years ago

欧文文字トークンに \kcatcode の情報が必要な理由

eqtb テーブルに格納された属性の kcatcode は……

これは理解しますが,「欧文文字トークン」自体に必要な理由にはなっていないと思います(もちろん実装を単純化するために欧文・和文問わず \catcode, \kcatcode 情報を持っておくというのは合理的ですが).

upTeX では和文文字ノードにも kcatcode が付与されて \jcharwidowpenalty 決定に使われる

これは理解していませんでした,ありがとうございます.