2017-11-15 6 views
0

私は同じ単語にマッチする複数のレクサールールを持つantlr文法を持っています。レキシング中に解決することはできませんが、文法ではあいまいになります。Antlrのあいまいなレクサールール

例:

conversion: NUMBER UNIT CONVERT UNIT; 
NUMBER: [0-9]+; 
UNIT: 'in' | 'meters' | ......; 
CONVERT: 'in'; 

入力:1 in in meters

語レクサールールUNITCONVERTに一致する "で"。

文法ファイルを読み込み可能にしながら、これをどのように解決できますか?

答えて

1

あなたの質問の情報に基づいて、最良の解決策が何であるかを言うのは難しいです。例えば、あなたのレクサールールであるかどうかわかりません。まったく曖昧です。

私のantlrの経験では、レクサールールは一般的に意味的意味を持ちません。何らかの正規表現にマッチするテキストだけです。だから、VARIABLEMETHOD_NAMEなどの代わりに、私はIDENTIFIERを持っていて、より高いレベルでそれを把握しています。言い換えれば

、あなたが文法規則でUNITCONVERTを交換する、または単に単一のルールを持っていることからいずれかの恩恵を受ける可能性があることを(少しから私はあなたの質問から収集することができます)ようだ:

conversion: NUMBER TEXT TEXT TEXT 

とANTLRリスナー/ tree-walker/etcのテキスト値を検証します。レクサールールであなたの質問を更新するための

EDIT

感謝。今すぐ明らかになったなぜそれが失敗している - BernardKが指摘するように、antlrは常に最初に一致するレクサールールを選択します。つまり、2つのあいまいなレクサールールのうちの2番目のルールが一致することは不可能であり、提案されたデザインは実行不可能になります。

私の意見では、レクサールールはユニット検証のようなことを行う正しいレイヤーではありません。彼らはコンテンツではなく構造で優れています。解析木を評価することは、antlr文法を変えようとするよりはるかに実用的です。

最後に、IDトークンの値を既知のユニットのセットに対して検証するなど、パースルールに組み込みアクションを使用することもできます。それはうまくいくかもしれませんが、あなたの文法の再利用可能性を破壊します。

+0

例にレクサールールを追加して、より明確にしました。レクサールールのすべてのテキストをキャッチし、訪問者で手動で解析すると、Antlrを使用する目的が無効になります。レクサーの規則を文法規則に移すと、文法は読みにくくなります。 ... ' – Toast

1

入力が2つのレクサールールに一致すると、ANTLRは最長または最初のどちらかを選択します。disambiguateを参照してください。あなたの文法では、inは決してCONVERTUNITとして解釈され、3つのUNITトークンがあるので、ルール

conversion: NUMBER UNIT CONVERT UNIT; 

は動作しないことができます。

$ grun Question question -tokens -diagnostics input.txt 
[@0,0:0='1',<NUMBER>,1:0] 
[@1,1:1=' ',<WS>,channel=1,1:1] 
[@2,2:3='in',<UNIT>,1:2] 
[@3,4:4=' ',<WS>,channel=1,1:4] 
[@4,5:6='in',<UNIT>,1:5] 
[@5,7:7=' ',<WS>,channel=1,1:7] 
[@6,8:13='meters',<UNIT>,1:8] 
[@7,14:14='\n',<NL>,1:14] 
[@8,15:14='<EOF>',<EOF>,2:0] 
Question last update 0159 
line 1:5 missing 'in' at 'in' 
line 1:8 mismatched input 'meters' expecting <EOF> 

何ができるかが唯一持っていることですIDまたはTEXTトークンと、このように、ラベルとそれらを区別する:

grammar Question; 

question 
@init {System.out.println("Question last update 0132");} 
    : conversion NL EOF 
    ; 

conversion 
    : NUMBER unit1=ID convert=ID unit2=ID 
     {System.out.println("Quantity " + $NUMBER.text + " " + $unit1.text + 
     " to convert " + $convert.text + " " + $unit2.text);} 
    ; 

ID  : LETTER (LETTER | DIGIT | '_')* ; // or TEXT : LETTER+ ;  
NUMBER : DIGIT+ ; 

NL  : [\r\n] ; 
WS  : [ \t] -> channel(HIDDEN) ; // -> skip ; 

fragment LETTER : [a-zA-Z] ; 
fragment DIGIT : [0-9] ; 

実行:

$ grun Question question -tokens -diagnostics input.txt 
[@0,0:0='1',<NUMBER>,1:0] 
[@1,1:1=' ',<WS>,channel=1,1:1] 
[@2,2:3='in',<ID>,1:2] 
[@3,4:4=' ',<WS>,channel=1,1:4] 
[@4,5:6='in',<ID>,1:5] 
[@5,7:7=' ',<WS>,channel=1,1:7] 
[@6,8:13='meters',<ID>,1:8] 
[@7,14:14='\n',<NL>,1:14] 
[@8,15:14='<EOF>',<EOF>,2:0] 
Question last update 0132 
Quantity 1 in to convert in meters 

ラベルは訪問者にルールのコンテキストから入手可能ですので、同じタイプのトークンを区別することは容易です。

関連する問題