JRubyでもtecsgenのテストケースが通るのを確認しました

raccのparser.rbへのとりあえずのパッチ作成に載せた試作パッチを、Linux(Fedora 7)とcgywin(1.5.25)上でJRubyで実行し、tecsgenの配布物に含まれるテストケースが通ることを確認しました。

Javaは、JDK 1.6 update14、JRubyは1.3.1を使用しました。

ただし、それぞれの箇所でいささか工夫が必要でした。

*Linux
tecsgenがCのヘッダファイルを読み込む(typedefで定義された型名や構造体タグ名を認識するため)時に、C処理系の独自の予約語が存在すると、tecsgenはそれを認識で来ません。
これによるパース失敗を避けるため、独自の予約語を読み込み前に削除しています。
具体的にはtecsgenの内部でCプリプロセッサ(あるいはC処理系のCプリプロセス処理機能)を呼び出し、空文字列に置換してから、ヘッダファイルを読み込みます。
具体的にはtecsgenのコマンドラインオプション-Dで空文字列に置き換える文字を指定します。
ただし、この指定が”-D__extension__”とされていたため、Linuxのgcc(4.1.3)では”1″に置き換えられて、コンパイルエラーになりました。
#cygwinではこの指定でも問題が起きませんでした。
#現在公開されているtecsgenは、主にcygwinで動作確認されています。

Linuxでは”-D__extension__=”とする必要がありました。

*cygwin
cygwinでJRubyを実行する場合、環境変数RUBYLIBへのパス名の設定方法に工夫が必要でした。
この工夫は、Rubyの場合は必要ありませんでした。

cygwinでフルパスで指定する場合、/cygdrive/c/のように
ドライブ名を/cygdrive/ドライブ名という指定をすることが
可能です。
しかし、この形式で指定した場合、rubyのスクリプトで
クラスFileのexpand_pathメソッドでフルパスに変換した
場合、
C:/cygdrive/c
と、先頭にドライブ名をつけたにも関わらず、/cygdrive/c
もつけたままであるため、存在しないパスになってしまいました。
これは、cygwinの標準のrubyとか、cygwin中から呼び出した
mswin32版rubyでは、経験しなかったことです。
どこが原因かまでは調べていませんが、cygwin上で、JRubyを
使ってtecsgen.rbを実行して、”ファイルが見つからない”
というようなエラーが発生した場合は、環境変数RUBYLIBの値を
確認してください。
もし、”/cygdrive/c”のような形式であれば、この部分をとり
さったパス名を指定してください。
以下をコマンドラインで実行してもよいと思います。

export RUBYLIB=`echo $PWD | sed ‘s/^\/cygdrive\/.//’`

raccのparser.rbとcparseの違い

さらに引き続き(raccのエラー回復モードは頑張りすぎ?tecsgen の Exerb版, Jruby 版の障害について)、raccのparser.rbとcparseの動作の違いを調べています.

昨日は、parser.rbがエラー回復モードで、定義された文法を満たすトークンの並びを得ようとして、(入力が終わっているのに)延々と次のトークンを得ようとして、無限ループに陥っているようだと書きました。
このことを指して「頑張りすぎ」と評していました。

そして、同じ不完全な内容の入力(不完全故に文法エラーになる)に対して、正常終了して文法エラーを報告するcparseは「頑張らない」ようにしているのではないかと予想していました.

今回、cparseを用いて、同じくtecsgen -yを指定してデバッグ表示させて見たところ、以外な結果になりました。

celltype tTaskMain {};

に対して、’}’を読み込むと文法エラーになります。
そしてエラー回復モードに入ります。

ここでcparseの場合、いったん読み込んだトークンを
捨てて、$endというトークンを読み込みます。
その次のトークンとして「}」を読み込みます。
後は、入力の通りにトークンを読み込みます。

エラー回復モードに入ったときに(入力には存在しない)仮想的なトークンを読み込んでいます。

この影響で、必要なトークンが不足しているために発生した文法エラーから回復することができていました。

先日以下の入力なら、parser.rbでも無限ループにはいらないと書きました.

celltype tTaskMain {}};

cparseの場合、エラー回復モード時に、あたかも上記のような入力がされていたかのように振る舞います。

$endが追加されるのは、他の文法エラーになる入力でも確かめてみました。

最初の私の予想(入力の終わりを特別扱いして、頑張らない)は外れていました。
cparseが採用しているエラー回復処理の方針は、どこかで聞いた覚えがあるのですが、思い出せません。またちょっとググってみても分かりませんでした。

(追記)
上の書き方ですと、parser.rbとcparse.soがまるっきりエラー回復モードのやりかたが違っているように受け取られるかも知れません。
しかし、rubyとC言語の違いはありますが、アルゴリズムとしては、(私が今まで調べて、理解した範囲では)どちらも同じに見えます。
動作の違いは、微妙な判定条件の違いとか、参照するテール(テーブルはそれぞれ用に作成されます)の内容の違いによるのではないかと感じています。