В ANTLR, есть ли сокращенная запись для выражения чередования всех перестановок некоторого набора правил? - PullRequest
4 голосов
/ 30 июля 2011

В ANTLR я хочу определить правило следующим образом:

rule: (abc | acb | bac | bca | cab | cba);

Но в моем случае у меня есть 10 правилвместо трех, которые я хочу переставить, так что это становится очень непрактичным.Есть ли способ выразить это в ANTLR без необходимости писать все перестановки?

1 Ответ

7 голосов
/ 30 июля 2011

Я бы просто сопоставил любой a, b или c один или несколько раз:

rule
 : ( a | b | c )+
 ;

, а затем, после анализа, обходит дерево разбора и проверяет, совпадают ли a, b и c все ровно один раз.

Но да, это возможно в самой грамматике, используя предикаты, где это необходимо.

Демонстрация:

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();};

Приведенная выше демонстрационная грамматика использует 2 различных типа предикатов: 1) a стробированный семантический предикат i , чтобы убедиться, что правило permutation не соответствует no больше, чем параметр final int n токенов и 2) a проверки семантического предиката i , чтобы гарантировать, что set содержит ровно final int n элементов для убедитесь, что это правильная перестановка из 5 токенов.

Более подробную информацию о семантических предикатах можно найти здесь: Что такое «семантический предикат» в ANTLR?

Вы можете проверить грамматику с помощью следующего класса:

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
...