そこで、ANTLR を使用して Java でコンパイラを作成していますが、コンパイラがエラーをどのように処理するかについて少し戸惑っています。
デフォルトの動作は、エラー メッセージを出力してから、トークンの挿入などによって、エラーから回復して解析を続行しようとするようです。原則としてこれが好きです。これは、(最良の場合) ユーザーが複数の構文エラーを犯した場合、エラーごとに 1 つのメッセージを受け取ることを意味しますが、次のエラーを検出するために再コンパイルを強制するのではなく、すべてのエラーについて言及します。私の目的には、デフォルトのエラーメッセージで問題ありません。すべてのトークンの読み取りが完了すると、問題が発生します。
もちろん、ANTLR のツリー コンストラクターを使用して抽象構文ツリーを構築しています。ユーザーがすべてのエラーを確認できるように、構文エラーが発生しても解析を続行するのは良いことですが、解析が完了したら、例外を取得するか、入力が構文的に有効でないことを示す何らかの兆候を取得したいと考えています。そうすれば、コンパイルを停止して、ユーザーに「申し訳ありませんが、構文エラーを修正してから再試行してください」と伝えることができます。私が望んでいないのは、ユーザーが言おうとしていたと思われる内容に基づいて不完全な AST を吐き出し、何か問題が発生したことを示すことなくコンパイルの次のフェーズに進むことです (エラーメッセージ以外)。コンソールに表示され、表示されません)。しかし、デフォルトでは、まさにそれを行います。
The Definitive ANTLR Referencemismatch
は、構文エラーが検出されるとすぐに解析を停止する手法を提供します: メソッドとメソッドをオーバーライドしてsrecoverFromMismatchedSet
をスローし、同じことを行うアクションをRecognitionException
追加します。@rulecatch
これは解析エラーから回復する利点を失っているように見えますが、もっと重要なのは、部分的にしか機能しないことです。必要なトークンが欠落している場合 (たとえば、二項演算子の一方の側にしか式がない場合)、期待どおりに例外がスローされますが、余分なトークンが追加された場合、ANTLR はそこに属すると思われるトークンを挿入します。コンソール メッセージを除いて、構文エラーを示さない AST を生成し、陽気な方法で続行します。(さらに悪いことに、挿入されたトークンはEOF
であったため、ファイルの残りの部分は解析されませんでした。)
たとえば、フィールドのようなものをパーサーに追加し、メソッドをオーバーライドしてアクションを追加することで、これを修正できると確信しています。これにより、isValid
解析の最後にエラーが発生した場合に例外がスローされます。しかし、より良い方法はありますか?私がやろうとしていることは、ANTLR ユーザーの間では珍しいことだとは想像できません。