さらに引き続き(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言語の違いはありますが、アルゴリズムとしては、(私が今まで調べて、理解した範囲では)どちらも同じに見えます。
動作の違いは、微妙な判定条件の違いとか、参照するテール(テーブルはそれぞれ用に作成されます)の内容の違いによるのではないかと感じています。
“raccのparser.rbとcparseの違い” への1件の返信