2010-12-10 11 views
8

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

Antlrは、通常、のほとんどがの作品ですが、私は厳しい頭痛を抱いていますが、解決しなければならない非常に苦痛を伴う小さな部分があります。

私の頭痛の大部分は、パーサーではなく、Antlrのレクサー部分が原因であることがわかりました。それから私はparser grammar X;に気づいて、おそらく私は手書きのレクサーとAntlrで生成されたパーサを持つことができたことに気付きました。

このトピックに関する詳細なドキュメントを探しています。カスタムITokenStreamはうまくいくと思いますが、このトピックに関するオンライン文書は事実上存在しないようです...

+0

私がお勧めするのは、既存のものから学ぶことができるということです。しかし、私はAntlrを使用するNHibernateしか見つけることができず、使い方は限られています。 : –

+0

* "しかし、小さな部分があり、解決できないほど痛い" * - 奇妙なことに、言語の字句部分は通常実装が簡単です。 –

+0

@Bart Kiers私はレンジや他のいくつかの機能(例えば、3.toString()や3.0.toString()など)をFAQにリストされている方法とは異なる方法で実装するのに問題があります。信じられないほど簡単に手動で作成されたレクサーで解決することができます。 – luiscubal

答えて

7

私は方法を見つけました。それは最良のアプローチではないかもしれませんが、確かに動作しているようです。

  1. ANTLRパーサはITokenStreamパラメータ
  2. ANTLRのレクサーは、それ自体あるITokenSource
  3. ITokenSourceITokenStreamITokenSourceを変換する最も簡単な方法は、CommonSourceStreamを使用することですITokenStream
  4. よりも大幅に簡素インタフェースである受け取りますITokenSourceパラメータを受信する。

は、だから今我々は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(); 

は最後に、我々はTokenQueueを定義する必要があります。 TokenQueueは厳密には必要ではありませんが、便宜のために使用しました。 これには、レクサートークンを受け取るメソッドと、Antlrトークンを出力するメソッドが必要です。したがって、Antlrネイティブトークンを使用しない場合は、Antlr-to-token変換メソッドを実装する必要があります。 また、TokenQueueITokenSourceを実装する必要があります。

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

これはこれまで私のために働いていたようです。私は他の人にも便利だと思っています。 私はフィードバックを受けています。特に、この問題を解決するためのよりよい方法が見つかった場合は、別の返信を自由に投稿してください。

+0

素晴らしい仕事ですが、どうやって.tokensファイルを扱いましたか?私はPyres lexersを使う以外は同様のことをしようとしています – Naveen

+0

@Naveen私は.tokensファイルに対して何もしないことを覚えていません。 – luiscubal

+0

私はあなたの方法もPythonで動作するようになっています。他の人はjflexとstaxで一緒に使っています。私はgithubの簡単な例を投稿しました:https://github.com/tinku99/antlr-pygments – Naveen