view Wnn/manual/3.libwnn/rk_lib/Intro @ 3:ed4bb01eb317

- suppress warnings. - partially fixed comparison between pointer and 0.
author Yoshiki Yazawa <yaz@cc.rim.or.jp>
date Thu, 13 Dec 2007 19:53:14 +0900
parents bbc77ca4def5
children
line wrap: on
line source

3.5     オートマトン(3J_T)

3.5.1 はじめに
 オートマトンは、かな漢字変換フロントエンドプロセッサ uum など (以後、単に
uum と呼ぶ) のローマ字かな変換を実現している機能で、変換内容を設定した
表 (変換表と呼ぶ) を変えることで任意の変換にすることができる。また、当
システムには、これと同一の機能を持ったオートマトンライブラリ (日本語入力
ライブラリ (libwnn) の romkan_ で始まる関数) があり、多種多様な変換プログ
ラムに応用できる。


3.5.2 機能  
 オートマトンは、変換表に従って直列に結ばれた3つの変換 (順に、前処理、
本処理、後処理と呼ぶ) を行い、その最終結果を出力する。3つの処理操作は、
それぞれの変換表に基づいて変換が行われる。また、オートマトンは、モード機
能を持つ。モードを切り替えることにより、3つの処理で使用する表の組み合
わせを動的に変更できる。このモードの設定、切り替えコードの設定も変換表
で行う。

 変換表が、テキストファイルであるため、表は容易に変更でき、しかも任意の変
換表に変更できる。また、1つの変換を行った後、次の変換を行うまでは、 BS
(バックスペース) により変換の1つ前の状態に戻すことができる。
    
 uum のローマ字かな変換では、本処理で「英大文字→ひらがな」の変換しか
行えないが、前処理で「英大文字→英大文字」、「英小文字→英大文字」の切り
替え、また後処理では「ひらがな→ひらがな」、「ひらがな→カタカナ」、「ひら
がな→半角カタカナ」の切り替えを行うことにより、ローマ字かな変換の入力・
出力の数種のケースに対処している。
 
			┌───オートマトン───┐		
			│      	          │
	  ┌───┐    │ ┌───前処理───┐ │
	  │入  力│  ―→ │ 小文字は大文字に │ │            
	  └───┘    │ │ 変換             │ │ 
	   英 (半角)    │ └─────────┘ │
	   大・小文字   │           ↓ 	  │ 
			│ ┌───本処理───┐ │
			│ │英大文字→ひらがな│ │            
			│ │の表に基づいて変換│ │ 
			│ └─────────┘ │
			│           ↓           │	 
			│ ┌───後処理───┐ │	
			│ │ ひらがなを必要に │ │    ┌───┐     
			│ │ 応じてカタカナや │ ―→  │出  力│ 
			│ │ 半角カナに変換   │ │    └───┘
			│ └─────────┘ │    
			└────────────┘

3.5.3 変換表
 オートマトンは、変換表として次の表を使用する。


		┌(1)モード定義表
		│                モード宣言・使用する対応表を指定する表。
		│                ファイル名は "mode" である。     


	変換表  ┤             
		│		┌ 前処理表 ... 前処理で使用する対応表。    
		│		│		'1'で始まるファイル名。
		│		│ 
		│		│
		└(2)対応表  ┤ 本処理表 ... 本処理で使用する対応表。
				│		'2'で始まるファイル名。


				└ 後処理表 ... 後処理で使用する対応表。
						'3'で始まるファイル名。
					     
					前処理・本処理・後処理でそれぞれ
					任意の数の対応表が使用できる。 


 モード定義表には、モードの宣言、各モードで使用する対応表の組み合わせ
とその決定規則を記述する。

 対応表には、入力コードと出力コードとの対応が記述される。対応表は、前・
本・後処理の3つに分かれ、それぞれ、任意の数の表を使用ができる。

 uum は、モード定義表を以下の順番で探す。

  1. uum のオプション -r による指定。

  2. uum 初期化ファイル uumrc の setrkfile エントリによる指定。

  3. ファイル名 /usr/local/lib/wnn/rk/mode


 表の記述方法のうち、

  …  	は、0回以上の繰り返し、
  … …	は、1回以上の繰り返し、
  [   ]	は、省略可能

を、それぞれ表わす。

3.5.4 モード定義表
 モード定義表には、モード宣言、各モードで使用する対応表の組み合わせと
その決定規則、モード表示文字列が記述される。
 モード定義表は、次の (1),(2),(3),(4) で構成される。ただし、行の先頭
または空白文字 (タブを含む) に続き、しかもエスケープされていない;から
行末までの文は、注釈文として扱われる。

 (1) 特殊文字

   特殊文字としては、以下に示すものがある。

	@HOME		環境変数 HOME を表わす。
	@MODEDIR	モード定義表の存在するディレクトリを表わす。
	@LIBDIR		標準設定がしてある変換表が存在するディレクトリ
			(/usr/local/lib/wnn/)

	~user		user がユーザ名ならば、そのユーザのログインディ
			レクトリ名を表わす。user の指定がなければ、自分
			のログイン・ディレクトリ名を表わす。

 (2) モード宣言

   モード宣言の書式は、次のとおり。

	(defmode  モード名 [初期状態])

	・モード名は、英数字からなる文字である。
	・初期状態は、on または off を指定する。 省略時は、off である。
	・モード宣言は、そのモードを使用する前に行う。

 (3) 対応表のサーチ指定

   対応表のサーチ指定の書式は、次のとおり。

	(search ディレクトリ名 … … )

	・モード定義表で指定された対応表がモード定義表と同じディレクトリに
	 ない場合、探しにいくディレクトリ名を指定する。

	・ディレクトリ名は、空白で区切って複数指定できる。

	・search は、対応表の指定より前に指定されていなければならない。

	(path ディレクトリ名 … … )
	      
	・対応表をサーチするために既に格納されているディレクトリ名を削除し、
	 引数に指定されたディレクトリ名を格納する。

	・ディレクトリ名は、空白で区切って複数指定できる。

	・search は、対応表の指定より前に指定されていなければならない。
	      
 (4) 対応表とモード表示文字列の指定

   指定方法は、次の3つがある。

	[1] 対応表のファイル名またはモード表示文字列 … … 

	[2] (if   条件式  対応表の指定またはモード表示文字列 … )

	[3] (when  条件式  対応表の指定またはモード表示文字列 … )

   対応表は '1'、'2'、'3' のどれかで始まるファイル名を指定する。
  パスによる指定もできる。
   モード表示文字列は、そのときのモードを表す " " で囲んだ文字列
    である。

	(a) " "  		変換が ON のときのモード表示文字列を表わす。 

	(b) (on_dispmode " ")	変換が ON のときのモード表示文字列を表わす。 

	(c) (off_dispmode " ")	変換が OFF のときのモード表示文字列を表わす。 

	(d) (on_unchg)		変換が ON のときのモード表示文字列をモード
				チェンジする前と同じモード表示文字列を表わす。
 
	(e) (off_unchg)		変換が OFF のときのモード表示文字列をモード
				チェンジする前と同じモード表示文字列を表わす。

   uum では、この文字列がモード表示に使用される。

   オートマトン・ライブラリは romkan_dispmode() によって、この文字列
    を取り出すことができる。ただし、モード定義表にあるモード時のモード表
    示文字列が複数あるように記述されている場合、最後のものだけが有効であ
    る。

   [2]、[3] は、条件によって選択する対応表を変えたいときに使用する。
  [2] の if 文 は、その条件式の結果が真ならば、その if 文内の指定を参照
    し、if 文の次の指定は参照しない。条件式が偽ならば、すぐ if 文を抜け出し
    て if 文の次の指定を参照する。

   [3] の when 文は、その条件式の結果が真ならば、その文内の指定を参照
    し、偽ならば参照しない。しかし、if 文と異なり、条件式の真偽にかかわらず
    when 文の次の指定を参照する。

   なお、[2]、[3] の対応表を指定する場合には、[2] または [3] を再
    帰的に定義できる。


   条件式には次の内1つを記述する。

	モード名		モードの状態が on のとき真
	(and  条件式  条件式)	2つの条件式が真のとき真
	(or   条件式  条件式)	どちらかの条件式が真のとき真
	(not  条件式)		条件式が偽のとき真
	(false)			常に偽
	(true)			常に真
   
   例えば、( モード定義に (defmode  kana) と (defmode  romajikana) が
    あるとき) (and  kana  romajikana)は、双方のモードが on のとき真になる。

   また例えば、(ここでは、条件式を○◎●で表し、変換表の名前をABC…
    で表すという規則のもとに)

	      (when ○ A (if ◎ B ) C ) (if ● D ) E
   
  と書かれていたする。そして、条件式○◎●共に成り立っているとす
   る。この並びを最初から見ていく。まず、(when ○ A (if ◎ B) C)と
   ある 。ここでは○は成り立つので、「A (if ◎ B) C」という並びを見る。
   はじめに、表Aを選択する。

     次に、(if ◎ B )がきて、しかも◎が成り立つので、表Bを選択する。こ
   の文はif文で、しかも条件式が成り立っているので、現在注目している並び
   「A(if ◎ B)C」のうち残りの部分は見なくてよい。これで、「A(if ◎ B)
   C」という並びを見終えたことになるが、この並びを含んでいたものは、when
   文なので、さらに「(when ○ A (if ◎ B )C) (if ● D) E」という並び
   の、残りの部分を見にいく。

    次に書かれているのは、(if ● D)である。●が成り立つので、表Dを選択す
   るが、if文なので、「(when ○ A (if ◎ B ) C ) (if ● D ) E」と
   いう並びのうち、残りの部分は見なくてよい。こうして、表A、B、Dが選
   択される。
 


   次に、uum が使用するモード定義表を例として示す。

   このモード定義表では、3のモードが定義されている。その後の 2A
   _CTRL から最後までが使用する対応表とモード表示文字列の指定である。
   モードが変わるごとに、この表を見て、上記のようにして使用する表の選択を
   行う。

	  (defmode romkan)
	  (defmode katakana)
	  (defmode zenkaku)

	  2A_CTRL
	  (if romkan
		  1B_TOUPPER
		  2B_ROMKANA 2B_JIS
		  (if (not katakana) "[あr]")
		  (if zenkaku 3B_KATAKANA "[アr]")
		  3B_HANKATA "[アイr]")

	  2B_DAKUTEN
	  (if (not katakana)
		  1B_ZENHIRA
		  (if zenkaku 3B_ZENKAKU "[あ ]")
		  "[Aあ]")
	  (if zenkaku
		  1B_ZENKATA
		  3B_ZENKAKU
		  "[ア ]")
	  "[アイA]"
								
   初期状態は、romkan、katakana、zenkaku のモード全てが off である。
   このとき表は、始めに 2A_CTRL を選択する。romkan が off なので、次
   の if文は参照しない。そして、2B_DAKUTEN を選択する。次の if文の条
   件式 (not katakana) は、katakanaが off ので真となる。そこで if文内
   を参照し、1B_ZENHIRA を選択する。次に if文内の if文を参照する。この
   if文では zenkaku が off になっているため条件式が偽となる。したがって、
   この if 文は参照しない。
   次に、モード表示文字列 "[Aあ]" を選択する。そして、残りの変換表並び
  は見ない。

3.5.5 対応表
 対応表には、前・本・後処理のそれぞれが行う変換データ (入力コードと出
力コードとの対応) が記述される。

 前・後処理は、本処理の補助という位置付けがなされている。このことから、
前・後処理の対応表には次の制限が課せられる。

前処理表  下記の (2) の記述ができない。
	  また、(1) の入力コード・出力コードには、それぞれ評価すると文
	    字になる式が1つだけ書ける。バッファ残りには書けない。

後処理表  上記の (2) の記述ができない。
	  また、(1) の入力コードには、評価すると文字になる式が1つだけ
	    書ける。バッファ残りには書けない。

 対応表の行のうち、ある行は次の (1)−(3) のうち1つか、または空行である。
この繰り返しで対応表が構成される。

	(1)    入力コード     [出力コード     [バッファ残り]]

	(2)    入力コード     機能

	(3)    変数宣言    

 これらを2行に渡って記述してはならない。また、改行または空白文字(タ
ブを含む) に続き、しかもエスケープされていない ; から行末までの文は、注
釈文として扱われる。
 出力コードの省略、およびバッファ残りの省略はヌルストリングの文として
扱われる。
 入力コード、出力コード、およびバッファ残りに記述できるのは、「評価する
と文字になる式」と「評価すると文字列になる式」を空白なしに並べたもので
ある。
 ここで、評価すると文字式または文字列になる式とは、その式によって文字
あるいは文字列に置き換わる、そのような式のことである。



 評価すると文字になる式には、次のものがある。

 (1) 文字表記

   文字表記を下記に示す(「評価すると文字列になる式」の文字表記とは異な
    る)。

   文字	「(」「)」「'」「"」「\」「;」「 」を除く。

   '文字'	この式でいう文字から「'」「\」「^」は除かれる。

   '^文字'	コントロール文字を表す。文字は ASCIIコード 32〜126 の文
		字または英小文字。
		「^?」は、DELコードを表わす。

   '\文字'	「\」の次の文字を表す。この式でいう文字からは数字と
		odx は除かれる。
		'\n','\t','\b','\r','\f' はC言語のエスケープ符号列と同
		じ。'\e','\E' は ESCコードを表わす。

   '\8進コード … …'	その8進コードを持つ文字を表す。

   '\o8進コード … …'	その8進コードを持つ文字を表す。

   '\d10進コード … …'	その10進コードを持つ文字を表す。

   '\x16進コード … …'	その16進コードを持つ文字を表す。

 (2) (関数名  評価すると文字になる式)  

    関数名			機  能

   toupper		引数が ASCII 英小文字ならば大文字に変える。
				(toupper  a) → A 

   tolower		引数が ASCII 英大文字ならば小文字に変える。
				(tolower  A) → a  

   toupdown		引数が ASCII 英小(大)文字ならば大(小)文字に変える。  
				(toupdown  a) → A 
				(toupdown  A) → a 

   tozenalpha	引数が ASCII 文字ならば対応する全角文字に変える。
				(tozenalpha  A) → A

   tohira		引数が全角カタカナならばひらがなに変える。
				(tohira  ア) → あ

   tokata		引数がひらがなならば全角カタカナに変える。
				(tokata  あ) → ア

   tozenhira		引数が半角カタカナならばひらがなに変える。
				(tozenhira  ア) → あ

   tozenkata		引数が半角カタカナならば全角カタカナに変える。
				(tozenkata  ア) → ア

   value		引数の文字コードを実際の数値にする。
				(value  0) → '\x0'
				(value  A) → '\xA'
				(value  F) → '\xf'

 (3) (関数名  評価すると文字になる式  評価すると文字になる式)

   関数名			機  能

	+		引数の和を値にする。 

	-		引数の差を値にする。

	*		引数の積を値にする。

	/		引数の商を値にする。
				(+  あ  '\d256' ) → ア
				(+  0  (value 3)) → 3

 (4) (変数名)

  関数名、機能、宣言名 (defvar) といずれも一致しない英字で始まる英
 数字からなる文字列。(変数の項参照。)
 ただし、'_' も英字とみなす。


 評価すると文字列になる式には、次のものがある。

 (1) "文字表記 … "

   文字表記を下記に示す(「評価すると文字になる式」の文字表記とは異な
    る)。

   文字	「"」「^」「\」を除く。

   ^文字	コントロール文字を表す。文字は ASCII コード 32〜126 の文
		字または英小文字。「^?」は、DELコードを表わす。

   \文字	文字は数字と odx を除く。
		'\n','\t','\b','\r','\f' はC言語のエスケープ符号列と同
		じ。'\e','\E' は ESCコードを表わす。

   \8進コード  … …[;]	その8進コードを持つ文字を表す。
				後に数字が続く場合「;」が必要。     

   \o8進コード … …[;]	その8進コードを持つ文字を表す。
				後に数字が続く場合「;」が必要。     

   \d10進コード … …[;]	その10進コードを持つ文字を表す。
				後に数字が続く場合「;」が必要。     

   \x16進コード … …[;]	その16進コードを持つ文字を表す。
				後に数字が続く場合「;」が必要。     

   "" (文字表記の省略)はヌルストリングを表す。

 (2) (関数名  評価すると文字列になる式)

	関数名                機  能
   tohankata		引数が全角ひらがな・全角カタカナならば半角カ
			タカナに変える。
				(tohankata  が) → ガ

   last=		最後にマッチした文字列の最後の文字と関数の引数
			(評価すると文字になる式) が一致するか。一致す
			るなら (last= 評価すると文字になる式) は空文字
			列になる。
				 (last=  A) 〜    あ

			 ただし、last= は、入力コードにのみ記述できる。

   todigit		第一引数で与えられたコードを第二引数のコードの
			進法の数に変換する。

   dakuadd		引数の後ろに濁点を付ける。

   handakuadd	引数の後ろに半濁点を付ける。 


 (3) (関数名  モード名)

   モード名はモード定義表で宣言されたものではなくてはならない。

	関数名		機  能

   if	引数であるモードが on なら(if  モード名)は空文字
		列になる。 
			(if  katakana)VU     ヴ

   unless	引数であるモードが off なら(unless  モード名) は
		空文字列になる。 
			(unless  katakana)VU     ぶ

   on	引数であるモードを on にする。
			(on  katakana)

   off	引数であるモードを off にする。
			(off  katakana)

   switch	引数であるモードが on なら off に、 off なら on に
		する。
			(switch  katakana) 

   ただし、if,unless は、入力コードにのみ記述できる。
   また、on,off,switch は、本処理表の出力コードにのみ記述できる。


 (4) (関数名)

   本処理表の出力コードにのみ記述できる。

	関数名                機  能

   allon                 全てのモードを on にする。

   alloff                全てのモードを off にする。



 機  能

  機能には下記の2つがあり、それぞれ単独で用いられる。

  (error) 	入力コードの部分のコードが入力されたらエラーとみなす。

  (restart)	前回のモード定義表を改めて読み込んで変換の再設定を行
		う。
		新しい変換表にエラーがあればエラーメッセージを表示し
		た後、元の変換表の設定に戻す。



 変数宣言

	(defvar   変数表記   (list 文字表記 … … ))
	(defvar   変数表記   (all))

  評価すると文字になる式として使用する変数とその変域の定義を行う。
  宣言は、上記の方法で行う。
  変数表記は、変数名 または (変数名 … … ) である。
  文字表記は、「評価すると文字になる式」の文字表記と同じ。
  list は、その引数の文字を変域とする。
  all は、全ての文字を変域とする。
  変数の項参照。




 関数の使用上の注意

  関数は評価すると文字または文字列になる式であるため、
	(toupper (tolower Y))
 と書ける。しかし、次のように評価すると文字列になる関数は他の関数の引
  数にできない。
	(toupper (tohankata か))

3.5.6 変数
 変数は同一パターンの変換が何通りもある場合に効果を発揮する。
例えば、

	┌─────────────────────────┐
	│  (defvar   a1   (list  K S T H Y R W G Z D B P)) │
	│  (a1)(a1)  っ   (a1)                             │
	└─────────────────────────┘

 上の2行は次の記述と同じ変換がされる。
 これはローマ字かな変換における促音処理である。

	┌─────────┐
	│  KK    っ    K   │
	│  SS    っ    S   │     
	│  TT    っ    T   │    
	│  ・    ・    ・  │  
	│  ・    ・    ・  │ 
	│  (   中  略   )  │
	│  PP    っ    P   │ 
	└─────────┘  
   
 変数は、変数宣言 (defvar) で行った変域の文字を値とする。


変数使用上の注意事項

  (1) 使用する変数はその表の中において defvar で定義しなければならな
      い。

  (2) 変数の定義はその表の中全体で有効である。
      1つの表でa1という変数を定義し、別な表でa1という変数を別様に定義し
      てもかまわない。
      この2つのa1は別の変数として扱われる。
      そのとき、逆に1つの表の中で同名の変数を2度 defvar することはできな
      い。

  (3) 対応表の1行の中では、同名の変数は常に同じ値をもつ。

	(defvar  a1  (list  A  B))
	(a1)(tolower (a1))   3

   この場合、「Aa」,「Bb」という文字列が「3」に変換される。
     「Ab」,「Ba」は変換されない。

  (4) 入力コードと表の入力コード部とのマッチングは左から行われる。このため、
      表の入力コード部を左から見ていったとき、ある変数が特定の文字にマッチ
      される前に関数の引数として現れてはいけない。

	(defvar  a1  (list  a  b))
	(toupper (a1))(a1)   3

      この場合「Aa」と入力すると「3」に変換してくれそうに思えるが、実際に
      は左からマッチさせようとして、「A」と (toupper (a1)) のマッチングを試
      みても、まだ値を持たない変数a1が toupper の引数になっているので許さ
      れない。
      このような設定は、表読み込み時にチェックされる。

  (5) 変数を出力コード部やバッファ残り部に書く場合も、入力コード部に現れる
   (つまり、入力コードとのマッチングで何らかの値を代入される) 変数でな
      ければならない。

	(defvar  a1  (list  K  S))
	(defvar  a2  (list  a))
	(a1)(a1)   (a2)    (a1) 

      この場合、入力コード部でマッチングが行われない変数 a2 が出力コード部
      に現れているので規則違反である。

3.5.7    変換の方式
 まず、入力されるコードを文字単位にまとめる (2バイトコードの文字も
1文字として扱う)。これを入力コードという。これは、前・本・後の3処理を経
て最終出力となる。前処理では、入力コード1つに対して出力コード1つが対
応付けられる。この出力コードが本処理コードの入力コードになる。

 前処理表のうち現在使用されている表の入力コードの部分を上から順に見て
いく。最初に実際の入力コードと合致したところで、その行の出力コードの部
分に書かれてあるものが出力される。ただし、表が複数選択されているときは、
モード定義表で先に参照されたものから見ていく。また、実際の入力コードと
合致するものが表にないとき (表が1つも選択されない時も含む) は、入力コ
ードがそのまま出力される。これは、本処理、後処理においても同様である。

 本処理では、入力コードが表の入力コードの部分と合致する可能性がある (入
力コードの部分の先頭から何文字かは一致している状態) 限り、入力コードは、
バッファに追加される。バッファに入力コードが追加されるごとに、本処理表
の入力コードの部分を上から順に見ていってバッファと比較される。ここで、
バッファの内容が表の入力コードの部分の最長のものと合致する可能性 (入力
コードに部分の先頭から何文字かは一致している状態) があれば、変換未確定
という判断のもとに、変換を行わずに次の入力コードを待つ。

 ただし、画面処理などの都合上、バッファ内のコードは未確定文字として出
力される。他に入力エラー、モード変更などを知らせるコードも出力される。

 これらの出力コードは本来の出力コードとは区別され、後処理は行われない。
(詳細は、ライブラリの romkan_getc(3J_T) を参照)

 バッファの内容が表の入力コードの部分の最長のものと合致したら (同じ長
さのものがあれば先に見つかったものと合致する)、その出力コードが出力され
る。バッファ残りの部分がなければバッファ内の合致した部分が消され、あれ
ば、バッファ内の合致した部分と入れ替わり、以上の操作が繰り返される。

 表に合致する可能性のあるものが見つからなかった場合、バッファの先頭の
1文字がそのまま出力される。合致したものの出力コードの部分がモードの状
態を変える関数 (on,off,switch など) である場合、使用される対応表がモー
ド定義表の記述にしたがって変更される。これらのモードを変える関数は、モ
ードの状態 (on, off) に関係なく、絶えず使用される表に記述しておく方が良
い。また、機能の (restart) の入力コードの部分に合致した場合は、モード定
義表そのものの再読み込みが行われる。ただし、そのモード定義表は前回と同
じファイルである。この機能を使うことで、オートマトンの使用中に修正した
変換表 (モード定義表を含む) を、オートマトンを終えずにその変換内容を変
えることができる。

 後処理では、1つの入力コードに対して1つ以上の出力コードが最終出力と
して出力される。出力コードが1つ以上出力されることを除いて前処理と同じ
である。

 下記の例では、「Ls」または「LS」が入力されたとき「ls -la 改行」が出力
される。


	前処理表
	      ┌──────────────┐
	      │  (defvar   a1   (list s))  │
	      │  (a1)      (toupper (a1))  │
	      └──────────────┘  

	本処理表
	      ┌──────────────┐
	      │   LS        "LS -la\n"     │     
	      └──────────────┘  

	後処理表
	      ┌──────────────┐
	      │   (defvar   a1   (all))    │
	      │   (a1)      (tolower (a1)) │               
	      └──────────────┘