方法がわかりました。それは最善のアプローチではないかもしれませんが、確かに機能しているようです。
- Antlr パーサーは
ITokenStream
パラメーターを受け取ります
- Antlr レクサーはそれ自体が
ITokenSource
s
ITokenSource
よりも大幅にシンプルなインターフェースです。ITokenStream
ITokenSource
aを aに変換する最も簡単な方法は、パラメーターを受け取る aITokenStream
を使用することです。CommonSourceStream
ITokenSource
したがって、次の 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();
最後に、定義する必要がありますTokenQueue
。TokenQueue
厳密には必要ありませんが、便宜上使用しました。lexer トークンを受け取るメソッドと、Antlr トークンを出力するメソッドが必要です。したがって、Antlr ネイティブ トークンを使用しない場合は、convert-to-Antlr-token メソッドを実装する必要があります。また、TokenQueue
実装する必要がありますITokenSource
。
トークン変数を正しく設定することが非常に重要であることに注意してください。最初は、計算を間違えていたので、いくつか問題がありましたCharPositionInLine
。これらの変数が正しく設定されていないと、パーサーが失敗する可能性があります。また、通常のチャネル (非表示ではない) は 0 です。
これはこれまでのところ私にとってはうまくいっているようです。他の人も同様に役立つことを願っています。フィードバックをお待ちしています。特に、この問題を解決するためのより良い方法を見つけた場合は、遠慮なく別の返信を投稿してください。