3

I would like to realize a "branch" in ANTLR3.

I figured using

branch[boolean is_a]
    : ({ $is_a}? => a)
    | ({!$is_a}? => b);

would do the trick, but I get the compiling errors "cannot find symbol" and "illegal start of type", because in the in the generated source i.e. DFA45.specialStateTransition(...) does not have a parameter is_a.

I tried omitting the =>¹, and/or omitting the $ of $is_a.

The FIRST sets of a and b are not disjoint.

In fact b is of type ((C) => c) | a.

¹) as I don't understand the difference between {...}? => ... and {...}? ...

Bart Kiers
  • 166,582
  • 36
  • 299
  • 288
Kijewski
  • 25,517
  • 12
  • 101
  • 143

1 Answers1

4

I'm not 100% sure why you get that error: I'd need to see your entire grammar for that. Anyway, there is no need to check for both is_a and !is_a. And both $is_a and is_a are valid.

Let's say you're parsing a list of numbers, and every 4th number, you want to handle through a different "branch". A grammar for that would look like:

grammar T;

parse
@init{int n = 1;}
  :  (number[n\%4 == 0] {n++;})+ EOF
  ;


number [boolean multipleOf4]
  :  {multipleOf4}?=> Int {System.out.println("branch A -> " + $Int.text);}
  |                   Int {System.out.println("branch B :: " + $Int.text);}
  ;

Int
  :  '0'..'9'+
  ;

Space
  :  (' ' | '\t' | '\r' | '\n') {skip();}
  ;

(note that the % is a reserved character inside ANTLR grammars (not inside String literals and comments though), so it needs escaping with a backslash)

And can be tested with the class:

import org.antlr.runtime.*;

public class Main {
    public static void main(String[] args) throws Exception {
        ANTLRStringStream in = new ANTLRStringStream("11 22 33 44 55 66 77 88 99");
        TLexer lexer = new TLexer(in);
        CommonTokenStream tokens = new CommonTokenStream(lexer);
        TParser parser = new TParser(tokens);
        parser.parse();
    }
}

Now generate a parser/lexer (A), compile all source files (B) and run the main class (C):

java -cp antlr-3.2.jar org.antlr.Tool T.g // A
javac -cp antlr-3.2.jar *.java            // B
java -cp .:antlr-3.2.jar Main             // C

(on Windows, run it by doing java -cp .;antlr-3.2.jar Main)

which produces the following output:

branch B :: 11
branch B :: 22
branch B :: 33
branch A -> 44
branch B :: 55
branch B :: 66
branch B :: 77
branch A -> 88
branch B :: 99

So, yes, you needed a "gated semantic predicate" ({boolean}?=>) in this case, not a "validating semantic predicate" ({boolean}?). The difference between the two predicates is explained in this previous SO Q&A: What is a 'semantic predicate' in ANTLR?

Community
  • 1
  • 1
Bart Kiers
  • 166,582
  • 36
  • 299
  • 288
  • @Kay, if you want, you could post the grammar you're working on and I'll have a look later on. Perhaps you can't post it in its entire form (work), but in that case, I won't be able to help (nor can someone else, is my guess). – Bart Kiers Feb 11 '11 at 13:05
  • It seems the language has to be "difficult enough" to render the problem. The generated code contains a `alt45 = dfa45.predict(input);` line in the `branch(boolean is_a)` method. DFA45.predict in turn uses is_a to predicate the next branch, but the variable is not passed along. Now I use `b {if(!is_b) throw new FailedPredicateException(...);}` which works fine for me. Thank you for the "What is a 'semantic predicate' in ANTLR" link! – Kijewski Feb 11 '11 at 13:12