4

ANTLR4 を使用していくつかの言語用の小さな IDE を開発しており、レクサーが一致しない場合に誤った文字に下線を引く必要があります。このような場合、組み込みorg.antlr.v4.runtime.ANTLRErrorListener実装は次のようなメッセージを stderr に出力します。

line 35:25 token recognition error at: 'foo\n'

エラーの行と列に関する情報がどのように取得されるか (syntaxErrorコールバックに引数として渡される) を理解するのに問題はありませんが、コールバック内の文字列を取得するにはどうすればよい'foo\n'ですか?

パーサーがエラーの原因である場合、問題のあるトークンをsyntaxErrorコールバックの 2 番目の引数として渡すため、誤った入力の開始オフセットと停止オフセットに関する情報を抽出するのは簡単になり、これは参考書でも説明されています。しかし、ソースがレクサーの場合はどうでしょうか? この場合、コールバックの 2 番目の引数は null です。おそらく、レクサーがトークンの形成に失敗したためです。

下線の量を知るには一致しない文字の長さが必要ですが、リスナーの実装をデバッグしているときに、提供されたコールバック引数のどこにもこの情報を見つけることができませんでした (文字列操作を介して提供されたエラーメッセージから抽出することを除いて)。違う)。文字列は明らかに何らかの形で取得される可能性がありますが、'foo\n'何が欠けていますか?

間違った場所を見ている可能性があり、エラーメッセージが形成されるDefaultErrorStrategyを拡張することを検討する必要があると思います。

4

1 に答える 1

17

構文エラーが発生しないようにレクサーを作成する必要があります。ANTLR 4 では、レクサーの最後のルールとして以下を追加するだけで、これを簡単に実行できます。

ErrorChar : . ;

これにより、エラーがレクサーからパーサーに移動されます。

場合によっては、追加の手順を実行して、ユーザーが IDE でコードを編集する際に役立つようにすることができます。たとえば、言語が次の形式の二重引用符で囲まれた文字列をサポートしているとします。これは複数行にまたがることはできません。

StringLiteral : '"' ~[\r\n"]* '"';

次のルールのペアを使用して、IDE でのエラー報告を改善できます。

StringLiteral : '"' ~[\r\n"]* '"';
UnterminatedStringLiteral : '"' ~[\r\n"]*;

その後、メソッドをオーバーライドして、特別な方法でemit()を処理できます。UnterminatedStringLiteralその結果、ユーザーには適切なエラー メッセージが表示され、パーサーStringLiteralには通常適切に処理できる単一のトークンが表示されます。

@Override
public Token emit() {
    switch (getType()) {
    case UnterminatedStringLiteral:
        setType(StringLiteral);
        Token result = super.emit();
        // you'll need to define this method
        reportError(result, "Unterminated string literal");
        return result;
    default:
        return super.emit();
    }
}
于 2013-09-14T02:43:52.600 に答える