左再帰の削除で説明されているように、左再帰を削除するには 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;} ;