Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In ANTLR, is there a shortcut notation for expressing alternation of all the permutations of some set of rules?

In ANTLR I want to define a rule like this:

rule : ( a b c | a c b | b a c | b c a | c a b | c b a );

But in my case I have 10 rules instead of three, that I want to permute so it gets very impractical. Is there any way of expressing this in ANTLR without having to write all the permutations?

like image 774
Paralife Avatar asked Jul 30 '11 15:07

Paralife


1 Answers

I would just match any a, b or c once or more:

rule
 : ( a | b | c )+
 ;

and then, after parsing, traversing the parse tree and checking if a, b and c all matched exactly once.

But Yes, it is possible in the grammar itself by using predicates where needed.

A demo:

grammar Permutation;

parse
  :  permutation[5] {System.out.println("parsed: " + $permutation.text);} EOF
  ;

permutation[final int n]
@init{
  java.util.Set set = new java.util.HashSet();
  int counter = n;
}
  :  (
       {counter > 0}?=> token   // keep matching a `token` as long as `counter > 0`
       {                        //
         set.add($token.text);  // add the contents of `token` to `set`
         counter--;             // decrease `counter`
       }                        //
     )+ 
     {set.size() == n}?         // if `set.size() != n`, an exception is thrown
  ;

token
  :  A
  |  B
  |  C
  |  D
  |  E
  ;

A : 'A';
B : 'B';
C : 'C';
D : 'D';
E : 'E';

Space : ' ' {skip();};

The demo grammar above uses 2 different types of predicates: 1) a gated semantic predicate i to make sure that the permutation rule matches no more than the parameter final int n tokens, and 2) a validating semantic predicate i to ensure that the set holds exactly the final int n elements to ensure that it's a proper permutation of the 5 tokens.

More info about semantic predicates can be found here: What is a 'semantic predicate' in ANTLR?

You can test the grammar with the following class:

import org.antlr.runtime.*;

public class Main {
  public static void main(String[] args) throws Exception {
    PermutationLexer lexer = new PermutationLexer(new ANTLRStringStream(args[0]));
    PermutationParser parser = new PermutationParser(new CommonTokenStream(lexer));
    parser.parse();
  }
}
java -cp antlr-3.3.jar org.antlr.Tool Permutation.g 
javac -cp antlr-3.3.jar *.java

java -cp .:antlr-3.3.jar Main "A B C D E"
parsed: ABCDE

java -cp .:antlr-3.3.jar Main "B D C E A"
parsed: BDCEA

java -cp .:antlr-3.3.jar Main "A B C D B"
line 1:9 rule permutation failed predicate: {set.size() == n}?
parsed: null
like image 155
Bart Kiers Avatar answered Nov 15 '22 10:11

Bart Kiers