TRONコードと ruby 1.9 M17n

 

ソースコードは troncode.trans.txt です。

ネタを使いまわしした ruby 1.9 でオレオレ文字コードを使う法 も参考になるかもしれません。

 

岸本 誠
BTRON Club 会員発表資料

 

はじめに

文字コードに関する基礎知識

文字とは何か?

この問題には踏み込まない(余談だが現在策定中の Ruby の標準仕様では「手続き」という概念が現れるがその定義はしていない)

符号化文字集合(CCS)、文字符号化方式(CES)、エンコーディング

符号化文字集合(Coded Character Set)

文字符号化方式(Character Encoding Scheme)

例にあげた EUC に「日本語」が付いてないところに注意。

エンコーディング(「コードセット」とも)

ruby 1.9 ではエンコーディングと呼んでいる。文献によっては [塩崎2003]「コードセット」と呼んでいる。(Unicode では文字符号化方式との区別がないなど混乱がある)

まとめ

TRONコードの特徴

Ruby

@1to100pen 氏による超漢字版もある(1.6ですが)
( http://hpcgi2.nifty.com/1to100pen/wiki/wiki.cgi?p=Btron )

 

バージョン 1.9 では eval が VM モデルに一新され、また、これまで、基本的にバイト列でしかなかった文字列オブジェクトが CSI 方式で多言語に対応した。

M17n

M17n (Multilingualization) = 多言語化。国際化 (Internationalization, I18n) の 部分集合。この <文字><文字数><文字> という略語法は DEC 発、というトリビアがある。

Ruby の M17n

参考資料

文字クラス、も検討されたが、どうせバイト列を持たなきゃならないので、だったら文字列でよい、ということになった。(参. CHISE プロジェクト)

 

ということになっているのだが

Encoding.default_internal を設定すると、ファイルから読み込んでデフォルトでこのエンコードに変換する、という設定ができる。

本来はアプリケーションのプログラマが考慮のうえ設定するはずのものだが、Ruby on Rails は require(ロード)するとこれを勝手に UTF-8 に設定してしまう!

(参考 http://route477.net/d/?date=20110119

TRONコード対応の実際

エンコーディングの追加については「サポートの要望を出すのが原則」となっている。しかし、しかるべき関数を呼び出す拡張ライブラリを作れば登録できてしまう。

ステートフル

ダミーエンコーディング

以下のようなスクリプトが動く。

require "troncode"
open("sample.tad", "rb:TADTextBE") {|file|
        s = file.read
}

ステートレス化

Encode

構造体

static OnigEncodingType stateless_TADTextBE = {
    &stateless_TADTextBE_mbc_enc_len,
    "stateless-TADTextBE",  /* name */
    4,  /* max byte length */
    4,  /* min byte length */
    &stateless_TADTextBE_is_mbc_newline,
    &stateless_TADTextBE_mbc_to_code,
    &stateless_TADTextBE_code_to_mbclen,
    &stateless_TADTextBE_code_to_mbc,
    &stateless_TADTextBE_mbc_case_fold,
    &stateless_TADTextBE_apply_all_case_fold,
    &stateless_TADTextBE_get_case_fold_codes_by_str,
    &stateless_TADTextBE_property_name_to_ctype,
    &stateless_TADTextBE_is_code_ctype,
    &stateless_TADTextBE_get_ctype_code_range,
    &stateless_TADTextBE_left_adjust_char_head,
    &stateless_TADTextBE_is_allowed_reverse_match
};

登録

rb_enc_register("stateless-TADTextBE", &stateless_TADTextBE);

トランスコード

以下、通常の TRONコードから、ステートレスTRONコードに変換するトランスコードを作るプログラム(抜粋)

<%
  map = {
    "00{00-20}" => :func_so,  # Control
    "{21-7e}{21-7e}" => :func_so,  # A Zone
    "{80-fd}{21-7e}" => :func_so,  # B Zone
    "{21-7e}{80-fd}" => :func_so,  # C Zone
    "{80-fd}{80-fd}" => :func_so,  # D Zone
    "fe{21-7e,80-fd}" => :func_so,  # Script/Language Change
    "fefe" => :func_si,  # Script/Language Escape
  }
  transcode_generate_node(ActionMap.parse(map), "TADTextBE_decoder")

  map = {
    "{00,fe}{21-7e,80-fd}" => :func_so,  # Script/Language Change
  }
  transcode_generate_node(ActionMap.parse(map), "TADTextBE_decoder_lang_escape")
%>

<%= transcode_generated_code %>

static const rb_transcoder
rb_TADTextBE_decoder = {
    "TADTextBE", "stateless-TADTextBE", TADTextBE_decoder,
    TRANSCODE_TABLE_INFO,
    2, /* input_unit_length */
    4, /* max_input */
    4, /* max_output */
    incompat_converter, /* asciicompat_type */
    2, tadtext_init, tadtext_init, /* state_size, state_init, state_fini */
    NULL, &fun_si_TADTextBE_decoder, NULL, &fun_so_TADTextBE_decoder
};

構造体 rb_transcoder は今のところソースツリーの中にしかない(インストールされない)ヘッダファイルの中にあるので、コンパイルするにはソースツリーからコピーする必要がある。テンプレートから C コードを生成する ruby スクリプトもソースツリー中にある。

ASCII コンパチブル

現在のところ、意図的に、トランスコーダーは変換元と変換先の少なくとも片方が ASCII コンパチブルとされている(前出の TRONコードのトランスコーダーはそうなっていないものを無理矢理作っている)。内部的に 2 段階の変換になるエンコーディング変換は透過的にできるので、asciicompat-TRON と、fixed-TRON の 2 種類の内部エンコーディングを作ったうえでまとめて変換する、ということは問題なくできる(はずである)。

その他問題点など

まとめ

文献まとめ