1

So my rule is

/* Addition and subtraction have the lowest precedence. */
additionExp returns [double value]
    :    m1=multiplyExp       {$value = $m1.value;} 
         ( op=AddOp m2=multiplyExp )* {
                                       if($op != null){ // test if matched
                                         if($op.text == "+" ){
                                           $value += $m2.value;
                                         }else{
                                           $value -= $m2.value;
                                         }                                         
                                        }
                                       }
    ;

AddOp : '+' | '-' ;

My test ist 3 + 4 but op.text always returns NULL and never a char.

Does anyone know how I can test for the value of AddOp?

In the example from ANTLR4 Actions and Attributes it should work:

stat: ID '=' INT ';'
   {
    if ( !$block::symbols.contains($ID.text) ) {
      System.err.println("undefined variable: "+$ID.text);
    }
   }
   | block
   ;
RedX
  • 14,749
  • 1
  • 53
  • 76
  • There are quite a bit of things incorrect, AFAIK. Does the ANTLR Tool accept your grammar? I think it should produce errors for the `additionExp` tool since actions/embedded-code must be placed at the end of an alternative. Also, `$op != null` would also trigger an error, no? And lastly you're comparing strings using `==` (`$op.text == "+"`), which is incorrect (see: http://stackoverflow.com/questions/767372/java-string-equals-versus). – Bart Kiers Jan 09 '14 at 11:06
  • @BartKiers It works fine as you can see also from the posted example. But you were right on the string comparison. I need `.equals` and not `==`. – RedX Jan 09 '14 at 12:10
  • you'd be surprised how many times people post some snippet that does not reflect their actual code. B.t.w., I just noticed you placed your embedded code outside the `( ... )*`. That should be inside of it. – Bart Kiers Jan 09 '14 at 12:33
  • @BartKiers I don't exactly see what you mean? Which embedded code? – RedX Jan 09 '14 at 12:54
  • Everything between `{` and `}` is embedded code. You have `( ... )* {/* code */}`, while it should be `( ... {/* code */} )*`. But I don't know if ANTLR4 accepts this: in ANTLR4, I think you can only use embedded code at the end of an alternative, not inside the parenthesis. In ANTLR4, the practice is to put as little target specific code as possible inside the grammar: listeners and/or visitors should be used for evaluation. – Bart Kiers Jan 09 '14 at 12:57
  • @BartKiers You are right about listeners and visitors. I just started and was wondering why it did not work (but it is working now, as posted). I am currently reading the `The Definite ANTLR4 Reference` and using listeners is the next step. Thank you tho. If you post an answer about the `.equal` I will mark it as an answer. – RedX Jan 09 '14 at 13:20
  • @BartKiers The restriction on action placement only applies to lexer rules. – Sam Harwell Jan 09 '14 at 13:25

1 Answers1

1

Are you sure $op.text is always null? Your comparison appears to check for $op.text=="+" rather than checking for null.

  1. I always start these answers with a suggestion that you migrate all of your action code to listeners and/or visitors when using ANTLR 4. It will clean up your grammar and greatly simplify long-term maintenance of your code.

  2. This is probably the primary problem here: Comparing String objects in Java should be performed using equals: "+".equals($op.text). Notice that I used this ordering to guarantee that you never get a NullPointerException, even if $op.text is null.

  3. I recommend removing the op= label and referencing $AddOp instead.

    1. When you switch to using listeners and visitors, removing the explicit label will marginally reduce the size of the parse tree.

    2. (Only relevant to advanced users) In some edge cases involving syntax errors, labels may not be assigned while the object still exists in the parse tree. In particular, this can happen when a label is assigned to a rule reference (your op label is assigned to a token reference), and an error appears within the labeled rule. If you reference the context object via the automatically generated methods in the listener/visitor, the instances will be available even when the labels weren't assigned, improving your ability to report details of some errors.

Sam Harwell
  • 97,721
  • 20
  • 209
  • 280