ANTLR语法不完整

时间:2011-12-09 05:21:30

标签: antlr

使用这个语法我可以找到指数,但我得到的答案是相反的顺序(例如:这是我得到的: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;};

2 个答案:

答案 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

你得到以下解析树:

enter image description here

答案 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