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

前端 未结 1 1493
感情败类
感情败类 2020-12-11 06:12

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

1条回答
  •  遥遥无期
    2020-12-11 06:50

    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
    

    0 讨论(0)
提交回复
热议问题