2

I am working on creating a language with ANTLR, and started a base language with the expr.g example. I am using ANTLR 3. I am ready to work on more data types than ints, and after looking around, I found Bart Kiers' wonderful example for floats, here.

In his example, he has the expression return float, however, this means that it doesn't return int. I am confused on how to have a return rule allow for more than one return type? I was thinking I could make a combined "number" type that incorporated ints and floats and return that, but then of course I run into the issue that within Java I have to return an int or a float specifically. Do I have to have two versions of the expression code, one for each data type? I would think this isn't necessary, but I am stumped... I can imagine using optional rules for the expression (i.e. either float or int is valid in this expression), but the return type itself requires a specific type. I am sorry for repeating myself, but I hopefully am clear with what I am confused about.

Here is my grammar file

And the expression grammar section:

expr returns [int value]
    : e=mexpr {$value = $e.value;}
      ( PLUS e=mexpr {$value += $e.value;}
      | MINUS e=mexpr {$value -= $e.value;}
      )*
    ;

Compare to Bart's:

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

And of course our rules are using the appropriate datatypes (int for me, float for him)...

Community
  • 1
  • 1
Sym
  • 21
  • 3

1 Answers1

1

I don't really see the need to let a rule return both a double and int: if you ever need an int, simply cast the double.

That said, ANTLR rules can return more than one object (or primitive):

additionExp returns [double value, int i]

which you can set either in the incline code, { ... }, just like the $value, or set it in the @after{ ... } block:

additionExp returns [double value, int i]
@after{ $i = (int)$value; }
    :    m1=multiplyExp       {$value =  $m1.value;} 
         ( '+' m2=multiplyExp {$value += $m2.value;} 
         | '-' m2=multiplyExp {$value -= $m2.value;}
         )* 
    ;

In other rules, you simply reference either value or i from the additionExp rule, like this:

otherRule
 : a=additionExp { 
                   System.out.println("int a.i = " + $a.i);
                   System.out.println("double a.value = " + $a.value);
                 }
 ;
Bart Kiers
  • 166,582
  • 36
  • 299
  • 288
  • Thanks - I'll play around with both styles (returning more than one, or casting to int). I still don't quite grok it, but you only truly learn by doing :) – Sym Oct 12 '12 at 00:57
  • @Sym, I added a small example of how to use the extra attribute. – Bart Kiers Oct 12 '12 at 07:00