2017-01-11 6 views
2

私は簡単なプログラミング言語のANTLR文法を作成しようとしています。ANTLR if-else ambiguity errors

文場合、それはC-等を有している:

program 
    : statement* EOF 
    ; 

statement 
    : block                 # blockStatement 
    | SEMI                 # emptyStatement 
    | assignment               # assignmentStatement 
    | declaration               # variableDeclarationStatement 
    | 'if' parExpression ifBody=statement ('else' elseBody=statement)?  # ifStatement 
    .......... 
    ; 

block 
    : '{' statement* '}' 
    ; 

expression 
    : literal               # literalExpression 
    | Identifier              # variableReference 
    .......... 
    ; 

parExpression : '(' expression ')'; 

assignment : Identifier assignmentOp expression SEMI; 

SEMI : ';'; 

Identifier : (LETTER | '_') (LETTER | DIGIT | '_')* ; 

正常に動作するようですが、私はDiagnosticErrorListenerを実行したとき、私はこの

if (flag1) 
    x = 42; 
else if (flag2) 
    x = 43; 
else 
    x = 44; 
ようなコードのためのエラー

reportAttemptingFullContext d=1 (statement), input='else', Line 3:0 
reportContextSensitivity d=1 (statement), input='else', Line 3:0 
reportAttemptingFullContext d=1 (statement), input='else', Line 5:0 
reportContextSensitivity d=1 (statement), input='else', Line 5:0 

を取得

ここで何が間違っているのか分かりませんが、 if (a) if (b) ... else ...)、この文法はあいまいである可能性があります。

どのように修正する必要がありますか?

+0

なぜJavaタグですか? – GhostCat

+1

私はあなたが気にする必要はないと信じています。ここで報告されるのは、パーザがそれ自体であいまいさを解決しようとしたものです。通常の解析実行で期待通りの結果が得られた場合、文法はうまくいくようです。 –

答えて

4

これはと呼ばれ、その他はという問題があります。あなたは他の句に、オプションの試合をしたので

 if (flag1) 
     if (flag2) x=2; 
     else x=3; // belongs to if (flag2) 

 if (flag1) 
     if (flag2) x=2; 
     else x=3; // belongs to if (flag1) 

: はテキストの解析:

 if (flag1) 
     if (flag2) x=2; 
      else x=3; 

次の2つの方法をあなたの文法を一致させることができます。これは、文法規則があいまいな一致を提供することを意味します。これはANTLRから得ている苦情です。

あなたが望むのは、最も近い非閉じif文にelseを強制的に一致させることです。これはほとんどのプログラミング言語のif ... elseの解釈です。

あなたはルールを解析するステートメントを変更する必要があります。

statement 
    : non_if_statement 
    | if_statement 
; 

if_statement 
    : 'if' parExpression 
     ifBody= (non_if_statement 'else' elseBody=statement 
        | if_statement) 
; 

non_if_statement 
    :block                 
    | SEMI 
    | assignment 
    | declaration 
    .......... 
; 

これは書くのは少し厄介ですが、動作するはずです。

多くのパーサージェネレータでは、トークンに遭遇すると「強制的にシフト」することができます。元の文法でelseキーワードをシフトすると、同じ効果が得られます。私はANTLRのためにそれを言う方法を、実際にあなたができるかどうかわからない。

[Lischkeはエラーを無視すると、元の文法で正しい結果が得られる可能性があります。私は彼が正しいと思う。パーサジェネレータは、それが受け入れたものと二つの解釈のいずれかを選択することを余儀なくされているからです]このセマンティック述語は、この警告を回避するためにANTLRで使用することができるように

+0

ありがとうございます。 コード例では、if(flag1)if(flag2)...(最初の 'if'の後に' x = 1; 'なし)を意味しましたか? – AlexP11223

+0

Ooops、はい、x = 1;ちょうど午前2時のグリッチです。パッチを当てました。 –