raccのエラー回復モードは頑張りすぎ?

昨日の続きで、TECSジェネレータでの文法定義と、CDLファイルでのエラーになる書き方を調べています。

今回も途中報告です。

前回に書いたerror-7.cdlは、以下の文法の記述に誤りがある場合のテスト-ケースでした.

文法定義

celltype
: CELLTYPE celltype_name ‘{‘ celltype_statement_list ‘}’ ‘;’

error-7.cdlの内容

celltype TaskMain {
/* attributeの定義が空でならsyntax error */
/*    attr {

x = 0;

};
*/
};

これはコメントを無視すると、以下と同等です。

celltyope TaskMain {};

文法定義と比較すると、celltype_statement_listという要素が不足しているため、文法エラーとなります。

実際、raccの生成したパーザはこの文法エラーを認識して、on_error()を呼び出しています.

ここで、on_error()とは、raccを用いてパーザを作成する人が、エラー処理を行うために自由に定義できるメソッドです。

on_error()でパース自体を中止することもできます。

また中止せずに、raccが生成したパーザにエラー回復モードで処理を続行させることができます。

エラー回復モードは、文法エラーが見つかった箇所を、エラーだとは認識しつつも、そこに正しい記述があったものとみなして、パース処理をつづけることです。

今回の文法定義の場合を例にとると、celltype_statement_listが存在するべきところに、「}」があったため、エラーとなります.

この後エラー回復モードで処理を続けようとして、「}」をcelltype_statement_listだとみなします。

文法では、この後に「}」と「;」がこの順番に記述されていなければなりません。

しかし、入力としては「;」しか存在しません。

raccは入力の終わりを$endというトークンとして扱います。

しかし、これが来ても、文法エラーが解消されません.パーザは次の入力を求めますが、実際の入力は終わっているので、$endしか渡してもらえません.

結局ここで無限ループが発生してしまいます。

実は、同じエラー内容でも以下の場合は、パーザは文法エラーを報告し、正常に終了します.

(文法としてはエラーになるが、正常終了する場合の記述)

celltyope TaskMain {}};

最初の「}」が来た時点でエラーと判断されますが、エラー回復モードになっても「}」、「;」と続くため、celltypeの文法定義に合致し、エラー回復モードは終了します。その後入力の終わり$endが来て、パーザは正常終了します。

エラー回復モードが(期待するより)頑張りすぎているのかもしれません.

ただし、入力の終わりがきたら必ず打ち切るようにするには、入力の終わりを特別扱いし、どんな状態であっても終了するルーチンをつくるか、どの状態からでも入力の終わりが来たら終了する状態遷移テーブルを作成する必要があると思います。

後、raccが手本にしたyaccの仕様がどうだったのか、確認したほうがいいかな。

raccの動作が、yaccの仕様の通りであれば、on_error()で対処するのがbetterだと思います.

raccのエラー回復モードは頑張りすぎ?” への1件のコメント

  1. ピンバック: raccのparser.rbとcparseの違い « northern-cross blog

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です