Question

sorry for my english. Learning rules antlr, I turned the curve calculator, please tell me where I can not properly written.

  • > If I write: 2+(2*2) my calculator displays: 4.
  • >If I write: 2+pi my calculator displays: line 1:2 no viable alternative at input 'pi' line 1:4 no viable alternative at input ''4.0
  • > If I write: cos 2 my calculator displays: line 1:0 no viable alternative at input 'cos' 0.9092974268256817

And the same type of errors ...I ask your help

Here's what I got:

grammar rulle;

options {
  language = Java;
}

rule returns [double value]
    : exp=additionExp { $value = $exp.value; }
    ; 

additionExp returns [double value]
    :    m1=involutExp      {$value = $m1.value;}
         ( '+' m2=involutExp  {$value += $m1.value;}
         | '-' m2=involutExp  {$value -= $m2.value;}
         )* 
    ; 

involutExp returns [double value]
    : i1=radicalExp {$value = $i1.value;} 
        ( '^' i1=radicalExp {$value = Math.pow($value, $i1.value);}
        )*
    ;

radicalExp returns [double value]
    : r1=matchSinCosExp {$value = $r1.value;}
        ( '!' r1=matchSinCosExp{$value = Math.pow($value, 1.0/$r1.value);}
        )*
    ;

matchSinCosExp returns [double value]
    : m1=piExp {$value = $m1.value;}
        ('sin' m1=piExp {$value = Math.sin($m1.value);}
        |'cos' m1=piExp {$value = Math.sin($m1.value);}
        )*
    ;

piExp returns [double value]
    : p1=multiplyExp {$value = $p1.value;}
        ('pi' p1=multiplyExp {$value = ($p1.value-$p1.value)+Math.PI;} 
        )*
    ;

multiplyExp returns [double value]
    :    a1=atomExp     {$value = $a1.value;}
         ( '*' a2=atomExp {$value *= $a2.value;}
         | '/' a2=atomExp {$value /= $a2.value;}
         )* 
    ;


atomExp returns [double value]
    :    n=Number           {$value = Double.parseDouble($n.text);}
    |    '(' exp=additionExp ')' {$value = $exp.value;}
    ;

Number
    :    ('0'..'9')+ ('.' ('0'..'9')+)?
    ;

WS  
    :   (' ' | '\t' | '\r'| '\n') {$channel=HIDDEN;}
    ;
Was it helpful?

Solution

Multiple problems appear in this rule:

piExp returns [double value]
    : p1=multiplyExp {$value = $p1.value;}
        ('pi' p1=multiplyExp {$value = ($p1.value-$p1.value)+Math.PI;} 
        )*
    ;

The way this rule is structured, to get the value π you need to use an expression like 3pi4, i.e. pi is written as a binary operator instead of a primary expression. The values 3 and 4 are effectively ignored because both are assigned to the label p1 (as opposed to separate labels p1 and p2 like you have in other rules), thus the expression ($p1.value-$p1.value)+Math.PI simplifies to (0)+Math.PI which is just Math.PI.

You should correct this in the following way:

  1. Remove the rule piExp.
  2. Replace references to piExp in matchSinCosExp with references to multiplyExp.
  3. Create a new rule primaryExp:

    primaryExp returns [double value]
      : Number    {$value = Double.parseDouble($Number.text);}
      | 'pi'      {$value = Math.PI;}
      ;
    
  4. Alter your atomExp rule to reference primaryExp instead of just Number:

    atomExp returns [double value]
      : primaryExp              {$value = $primaryExp.value;}
      | '(' exp=additionExp ')' {$value = $exp.value;}
      ;
    
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top