2012-03-03 10 views
3

ANTLR 3.4を使用してCコンパイラをビルドしようとしています。ANTLR文法エラー

ここに記載されている文法のフルセット、次のようにルールのレクサー使用し

program   : (vardeclaration | fundeclaration)*     ; 
vardeclaration : INT ID (OPENSQ NUM CLOSESQ)? SEMICOL ; 

fundeclaration : typespecifier ID OPENP params CLOSEP compoundstmt  ; 
typespecifier : INT | VOID           ; 
params   : VOID | paramlist          ; 
paramlist  : param (COMMA param)*         ; 
param   : INT ID (OPENSQ CLOSESQ)?   ; 

compoundstmt : OPENCUR vardeclaration* statement* CLOSECUR   ; 
statementlist : statement*           ; 

statement  : expressionstmt | compoundstmt | selectionstmt | iterationstmt | returnstmt; 
expressionstmt : (expression)? SEMICOL; 
selectionstmt : IF OPENP expression CLOSEP statement (options {greedy=true;}: ELSE statement)?; 
iterationstmt : WHILE OPENP expression CLOSEP statement; 
returnstmt  : RETURN (expression)? SEMICOL; 

expression  : (var EQUAL expression) | sampleexpression; 
var    : ID (OPENSQ expression CLOSESQ)? ; 

sampleexpression: addexpr ((LOREQ | LESS | GRTR | GOREQ | EQUAL | NTEQL) addexpr)?; 
addexpr   : mulexpr ((PLUS | MINUS) mulexpr)*; 
mulexpr   : factor ((MULTI | DIV ) factor)*; 

factor   : (OPENP expression CLOSEP) | var | call | NUM; 
call   : ID OPENP arglist? CLOSEP; 
arglist   : expression (COMMA expression)*; 

ELSE : 'else' ; 
IF  : 'if'  ; 
INT  : 'int'  ; 
RETURN : 'return' ; 
VOID : 'void' ; 
WHILE : 'while' ; 

PLUS : '+' ; 
MINUS : '-' ; 
MULTI : '*' ; 
DIV  : '/' ; 

LESS : '<' ; 
LOREQ : '<=' ; 
GRTR : '>' ; 
GOREQ : '>=' ; 

EQUAL : '==' ; 
NTEQL : '!=' ; 
ASSIGN : '=' ; 

SEMICOL : ';' ; 
COMMA : ',' ; 

OPENP : '(' ; 
CLOSEP : ')' ; 
OPENSQ : '[' ; 
CLOSESQ : ']' ; 
OPENCUR : '{' ; 
CLOSECUR: '}' ; 

SCOMMENT: '/*' ; 
ECOMMENT: '*/' ; 


ID : ('a'..'z' | 'A'..'Z')+/*(' ')*/ ; 
NUM : ('0'..'9')+ ; 
WS : (' ' | '\t' | '\n' | '\r')+ {$channel = HIDDEN;}; 
COMMENT: '/*' .* '*/' {$channel = HIDDEN;}; 

しかし、私はそれは私にエラーを与え、これを保存しようと、

error(211): /CMinusMinus/src/CMinusMinus/CMinusMinus.g:33:13: [fatal] rule expression has non-LL(*) decision due to recursive rule invocations reachable from alts 1,2. Resolve by left-factoring or using syntactic predicates or using backtrack=true option. 
|---> expression  : (var EQUAL expression) | sampleexpression; 

1 error 

この問題を解決するにはどうすればよいですか?

答えて

2

すでに言及したように、文法規則expressionはあいまいです。その規則の両方の選択肢が開始されます。つまり、varとなります。

パーサーに少し「助けてください」必要があります。構文解析にvarとそれに続くEQUALがある場合は、代替1を選択し、代替2を選択する必要があります。これは構文述語(以下の規則の(var EQUAL)=>部分)を使用して行うことができます。このQ & A述語について

expression 
: (var EQUAL)=> var EQUAL expression 
|    sampleexpression 
; 

より:What is a 'semantic predicate' in ANTLR?

1

問題はこれです:あなたはどちらかvarまたはsampleexpressionで始まる

expression  : (var EQUAL expression) | sampleexpression; 

。しかし、sampleexpressionは、

のように、varに減らすことができます。したがって、コンパイラのk-長の述語を見つける方法はありません。あなたがなどのエラーメッセージが提案することができます

が、これはあなたの問題を解決するかどうかを確認するためにbacktrack=trueを設定するが、それはASTにないつながるかもしれない - あなたが期待するparsetreesをしても、特別な入力条件に遅いかもしれません。 このような再帰を避けるために、文法をリファクタリングすることもできます。

+0

'バックトラック= true'には、指定されたエラーを削除します。しかし結果は間違っているようです。 backtrack = trueとはどういう意味ですか? – DarRay

+1

それはあいまいな文法を持っているので、期待通りの結果が得られないことが私の意図でした。バックトラックは可能な限り入力トークンを一致させようとします。もしそれが致命的な終わりに遭遇するならば、それは見つかった最後のあいまいな代替物に戻り、すべての可能なパスが試されるまでそこから再度試みます。 – stryba