2017-01-22 11 views
1

ここでは、LL(k)パーサの相互左回帰問題に関するStackOverflowに関する多くの質問を読んでいます。私は、左再帰除去するために一般的なアルゴリズムを見つけました:ANTLR4相互左回帰文法

A : Aa | b ; 

はしかし、私は私の状況に適用する方法を見つけ出すことはできません

A : bR ; 
R : (aA)? ; 

になります。私は、など

left_exp: IDENT | exp DOT IDENT ; 
exp  : handful 
     | of 
     | other rules 
     | left_exp ; 

「他のルールの一握り」すべてが通常の再帰が含まれている、などexp : exp PLUS expを、持っているし、何の問題もありません。問題は、left_expexpが相互に再帰的であることです。

私はちょうどexpルールにIDENTexp DOT IDENTを追加することを考えたが、left_expが有効になり、他の有効なexpのルールが適用されないいくつかの状況では、あります。

EDIT

私も割り当てが続く左の発現のための呼び出しを次のルールを持っています。

assign_statement: left_exp (COLON IDENT)? EQUAL exp SEMI ; 

正規表現は、それがDOT IDENTが続いている場合にのみ、左式ですので、その後、割り当てが受け入れるだろうので、私はちょうど、私の表現の定義に

| IDENT 
| exp DOT IDENT 

を追加することができないようですこれらの2つのうちの1つだけではなく、左側の他の有効な式。

答えて

1

私は通常、適用のアプローチは、このように書きます:

A: Aa | b; 

は次のようになります。

A: b (a)*; 

または一般的には:(削除)左再帰を持つとすべてのALTが続く左再帰なしすべてのALT無制限の発生(クレーンオペレータを介して表現される)。例:

A: Aa | Ab | c | d | Ae; 

は次のようになる。

A:(C | D)(| B | E)*。

あなたはに常時交換することにより、容易にこれを確認することができます。

A: Aa | b; 
A: (Aa | b)a | b; 
A: Aaa | ba | b; 
A: (Aa | b)aa | ba | b; 
A: Aaaa | baa | ba | b; 

など

あなたの例では、しかし、あなたは(2つのルールを介した)間接的な左再帰を持っています。 ANTLRではこれを認めません。解決策は、left_expからexpまでaltsを移動し、上記のアルゴリズムIを適用することです。

+0

言語定義には左の式が必要な代入文があり、DOT IDENTが後に続く場合は式が左の式になるだけなので、2つを組み合わせることはできません。その情報を含めるように質問を更新します。 –

+0

私はあなたが何を理解しているかわかりませんが、パーサーは構文ツールです。あなたが意味するセマンティクスを理解していません。必要に応じて、解析後にそれらを強制する必要があります。パーザの観点からは、2つのaltsを独自のルールで分離するかどうかに違いはありません。しかし、ANTLRは、相互に左の再帰的ルールを解析することはできません。左回帰は、単一のルールでのみ発生する可能性があります。 –

+0

基本的に、 'l_exp'は代入の左側にあるもので、' exp'の識別子またはドット識別子のいずれかであり、 'l_exp'はそれ自体で有効な' exp'です。私は、代入の左側に整数リテラルである '6 = 12'のようなものを許さないようにしようとしていました。しかし、私はちょうどその過去のパーサーを許可し、後でそれを処理する必要があるかもしれないように聞こえる。 –