使用这个语法我可以找到指数,但我得到的答案是相反的顺序(例如:这是我得到的:2 ^ 2 ^ 3 = 64这是我应该得到的:2 ^ 2 ^ 3 = 2 ^ 8 = 256))
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 :(得分: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
你得到以下解析树:
答案 1 :(得分:2)
对于初学者来说,2(23)
是256,而不是512 - no (非奇异)关联性将从该表达式中获得512: - )
但是,如果您希望指数运算符具有从右到左的关联性,则需要修改exponent
规则以使其变得贪婪。换句话说,允许它将exponent
作为辅助操作数(优先选择),而不仅仅是当前的factor
。
这样,2 ^ 2 ^ 3确实会评估为2(23)
而不是(22)3
。
道歉,我不知道完全如何使用ANTLR实现这一点,我在这里展示了我的年龄,但我非常喜欢lex / yacc: - )
但this PDF似乎就是你所追求的(见幻灯片35)。基本上,您根据求幂I
(在您的情况下为factor
)定义您的项目,并且指数E
变为:
E = I ^ E
| I