左再帰の削除で説明されているように、左再帰を削除するには 2 つの方法があります。
- いくつかの手順を使用して、元の文法を変更して左再帰を削除します
- 左再帰を持たないように文法を独自に書く
ANTLR で左再帰を削除する (持たない) ために、通常は何を使用しますか? パーサーに flex/bison を使用しましたが、ANTLR を使用する必要があります。ANTLR (または一般的な LL パーサー) の使用に関して私が懸念しているのは、左再帰の削除だけです。
- 実用的な意味で、ANTLR で左再帰を削除することはどれほど深刻ですか? これは ANTLR を使用する上での目玉ですか? それとも、ANTLR コミュニティでは誰も気にしていませんか?
- ANTLR の AST 生成のアイデアが気に入っています。AST をすばやく簡単に取得するという点で、(左再帰を削除する 2 つの方法のうち) どの方法が望ましいですか?
追加した
次の文法でいくつかの実験を行いました。
E -> E + T|T T -> T * F|F F -> INT | ( え )
左再帰を削除した後、次のものが得られます
E -> TE' E' -> null | +テ' T -> FT' T' -> null | *FT'
次の ANTLR 表現を思い付くことができました。比較的単純で簡単ですが、左再帰を持たない文法の方が適しているようです。
文法T; オプション { 言語=Python; } start は [値] を返します : e {$value = $e.value}; e は [値] を返します :てっぺん { $value = $t.value $ep.value != なしの場合: $value += $ep.value } ; ep は [値] を返します : {$値 = なし} | | '+' tr = ep { $value = $t.value $r.value != なしの場合: $value += $r.value } ; t は [値] を返します : f tp { $value = $f.value $tp.value != なしの場合: $value *= $tp.value } ; tp は [値] を返します : {$値 = なし} | | '*' fr = tp { $value = $f.value; $r.value != なしの場合: $value *= $r.value } ; f は [int 値] を返します : INT {$value = int($INT.text)} | | '(' e ')' {$value = $e.value} ; INT: '0'..'9'+; WS: (' '|'\n'|'\r')+ {$channel=HIDDEN;} ;