2011-12-09 39 views
1

使用這個語法我可以找到指數,但我得到的答案是相反的順序(例如:這是我得到的:2^2^3 = 64這就是我應該得到的:2^2^3 = 2^8 = 256))ANTLR語法不完整

grammar SDD1 
; 

options { 
    language = Java; 
} 
// header for parser related java 
@header { 
    package com.compiler.tutorial; 
} 

// header for lexer related java 
@lexer::header { 
    package com.compiler.tutorial; 

} 

evaluator returns[int result] 
    : expression EOF {$result = $expression.result;} 
    ; 

expression returns[int result] 
    : op1=mult {$result = $op1.result;} 
    ('+' op2=mult {$result = $result + $op2.result;} 
    | '-' op2=mult {$result = $result - $op2.result;} 
    )* 
    ; 

mult returns [int result] 
    : op1 = exponent {$result = $op1.result;} 
    ( '*' op2=exponent {$result = $result * $op2.result;} 
    | '/' op2=exponent {$result = $result/$op2.result;} 

)* 
    ; 

exponent returns [int result] 
    : op1=factor {$result = $op1.result;} 
    ('^' op2=factor {$result = (int) Math.pow($result,$op2.result);} 
    )* 
    ; 



factor returns [int result] 
    : NUMBER {$result = Integer.parseInt($NUMBER.text); 
       System.out.println ("Number= " + $result);}| 
     IDENT {$result = 0;}| 
     '(' expression ')' {$result = $expression.result;} 
    ; 


fragment LETTER: 'a'..'z' | 'A'..'Z'; 
fragment DIGIT: '0'..'9'; 
IDENT: LETTER(LETTER | DIGIT)*; 
NUMBER: DIGIT+; 
WS: (' ' | '\t' | '\n' | '\r' | '\f')+ {$channel=HIDDEN;}; 
+0

2^2^3 = 64本身正確的,如果你喜歡評價(2^2)^ 3 = 64 ..........也許這是因爲你的語法是不完全遞歸,因爲它應該是(最右邊的表達式應該先評估???) – Umer

+0

請不要用「緊急」標記您的問題。 –

回答

2

對於初學者來說,2(23)是256,而不是512 - 有沒有(非奇異)的關聯性,這將使您從表達512: - )

但是,如果您想從指數運算符的從右到左的關聯性,您需要修改exponent規則以使其成爲gre伊迪。換句話說,允許它將exponent作爲次操作數(優先),而不僅僅是當前的factor

這樣,2^2^3的確會評價爲2(23)而不是(22)3

道歉,我不知道究竟如何實現與ANTLR,我在這裏展示我的年齡,但我這人非常的lex/yacc的人:-)

this PDF似乎做你想做的事情(參見幻燈片35)。基本上,你定義你的項目受到冪Ifactor你的情況),而指數E變爲:

E = I^E 
    | I 
+0

我的要求是這樣的,如果假設2^4^2第一個指數4^2應該做的結果是16,然後2^16應該完成。這是我的要求,請幫助 – gooner4

+0

@pranith,我明白你在做什麼,我只需要花一些時間從'yacc'翻譯 - 查看更新。 – paxdiablo

+0

@paxdiablo是正確的...你的規則 exponent returns [int result] :op1 = factor {$ result = $ op1.result;} ('^'op2 = factor {$ result =(int)Math.pow ($ result,$ op2。結果);} )* ; 應該分頭到兩個規則(類似於EXP:OP1「^」 extEXP;和extEXP:OP2 | EXP)我沒有ANTLR精確測試,但問題是,你寫了一個平坦的語法,避免貪婪的方法。 – Umer

3

你的問題是,^運算符是右結合。用你現在的語法,它被定義爲左聯合。像+, - 或*這樣的運算符是左結合的,這在ANTLR語法中是自然表達的。爲了表達正確的關聯性,你需要遞歸規則。我改變你語法不沾花括號內的行動,以便它提供了正確的分析樹:

grammar SDD1 
; 

options { 
    language = Java; 
} 
// header for parser related java 
@header { 
    package com.compiler.tutorial; 
} 

// header for lexer related java 
@lexer::header { 
    package com.compiler.tutorial; 

} 

evaluator returns[int result] 
    : expression EOF {$result = $expression.result;} 
    ; 

expression returns[int result] 
    : op1=mult {$result = $op1.result;} 
    ('+' op2=mult {$result = $result + $op2.result;} 
    | '-' op2=mult {$result = $result - $op2.result;} 
    )* 
    ; 

mult returns [int result] 
    : op1 = exponent {$result = $op1.result;} 
    ( '*' op2=exponent {$result = $result * $op2.result;} 
    | '/' op2=exponent {$result = $result/$op2.result;} 

)* 
    ; 

exponent returns [int result] 
    : atom ('^' exponent)? 
    ; 



atom returns [int result] 
    : NUMBER {$result = Integer.parseInt($NUMBER.text); 
       System.out.println ("Number= " + $result);}| 
     IDENT {$result = 0;}| 
     '(' expression ')' {$result = $expression.result;} 
    ; 



fragment LETTER: 'a'..'z' | 'A'..'Z'; 
fragment DIGIT: '0'..'9'; 
IDENT: LETTER(LETTER | DIGIT)*; 
NUMBER: DIGIT+; 
WS: (' ' | '\t' | '\n' | '\r' | '\f')+ {$channel=HIDDEN;}; 

(請注意,我添加的主要規則:

exponent returns [int result] 
    : atom ('^' exponent)? 
    ; 

沒有*的背後右大括號,但)

所以對於輸入:

2^3^4^5 

你會得到如下解析TRE E:

enter image description here