9

C#ベースのプログラミング言語コンパイラを手動のレクサー/パーサーからAntlrに移行しています。

Antlrは、通常はほとんど機能するため、深刻な頭痛の種になっていますが、機能しない小さな部分があり、解決するのが非常に困難です。

私の頭痛のほとんどは、パーサーではなく、Antlrのレクサー部分が原因であることがわかりました。次にparser grammar X;、手動で記述したレクサーと、Antlrで生成されたパーサーを使用できる可能性があることに気づきました。

だから私はこのトピックに関するより多くのドキュメントを探しています。カスタムITokenStreamが機能する可能性があると思いますが、このトピックに関するオンラインドキュメントは事実上ないようです...

4

1 に答える 1

8

方法がわかりました。それは最善のアプローチではないかもしれませんが、確かに機能しているようです。

  1. Antlr パーサーはITokenStreamパラメーターを受け取ります
  2. Antlr レクサーはそれ自体がITokenSources
  3. ITokenSourceよりも大幅にシンプルなインターフェースです。ITokenStream
  4. ITokenSourceaを aに変換する最も簡単な方法は、パラメーターを受け取る aITokenStreamを使用することです。CommonSourceStreamITokenSource

したがって、次の 2 つのことだけを行う必要があります。

  1. 文法をパーサーのみに調整する
  2. ITokenSource を実装する

文法の調整は非常に簡単です。すべてのレクサー宣言を削除し、文法を として宣言するようにしてくださいparser grammar。便宜上、簡単な例をここに掲載します。

parser grammar mygrammar;

options
{
    language=CSharp2;
}

@parser::namespace { MyNamespace }

document:   (WORD {Console.WriteLine($WORD.text);} |
        NUMBER {Console.WriteLine($NUMBER.text);})*;

class mygrammarの代わりに次のファイルが出力されることに注意してくださいclass mygrammarParser

そこで、「偽の」レクサーを実装したいと思います。私は個人的に次の疑似コードを使用しました。

TokenQueue q = new TokenQueue();
//Do normal lexer stuff and output to q
CommonTokenStream cts = new CommonTokenStream(q);
mygrammar g = new mygrammar(cts);
g.document();

最後に、定義する必要がありますTokenQueueTokenQueue厳密には必要ありませんが、便宜上使用しました。lexer トークンを受け取るメソッドと、Antlr トークンを出力するメソッドが必要です。したがって、Antlr ネイティブ トークンを使用しない場合は、convert-to-Antlr-token メソッドを実装する必要があります。また、TokenQueue実装する必要がありますITokenSource

トークン変数を正しく設定することが非常に重要であることに注意してください。最初は、計算を間違えていたので、いくつか問題がありましたCharPositionInLine。これらの変数が正しく設定されていないと、パーサーが失敗する可能性があります。また、通常のチャネル (非表示ではない) は 0 です。

これはこれまでのところ私にとってはうまくいっているようです。他の人も同様に役立つことを願っています。フィードバックをお待ちしています。特に、この問題を解決するためのより良い方法を見つけた場合は、遠慮なく別の返信を投稿してください。

于 2010-12-11T01:48:29.033 に答える