3 votes

ANTLR3 : Paramètres et prédicats sémantiques ("cannot find symbol", "illegal start of type")

Je voudrais réaliser une "branche" dans ANTLR3.

Je me suis dit qu'en utilisant

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

ferait l'affaire, mais je reçois les erreurs de compilation "cannot find symbol" et "illegal start of type", parce que dans la source générée, à savoir DFA45.specialStateTransition(...) n'a pas de paramètre is_a .

J'ai essayé d'omettre le => ¹, et/ou en omettant le $ de $is_a .

Les PREMIÈRES séries de a y b ne sont pas disjoints.

En effet b est de type ((C) => c) | a .

¹) car je ne comprends pas la différence entre {...}? => ... y {...}? ...

4voto

Bart Kiers Points 79069

Je ne suis pas sûr à 100% pourquoi vous obtenez cette erreur : Il faudrait que je voie toute votre grammaire pour le savoir. Quoi qu'il en soit, il n'est pas nécessaire de vérifier les deux éléments suivants is_a et !is_a . Et les deux $is_a y is_a sont valables.

Imaginons que vous analysiez une liste de nombres, et que tous les 4 nombres, vous souhaitiez passer par une "branche" différente. Une grammaire pour cela ressemblerait à :

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

(notez que le % est un caractère réservé dans les grammaires ANTLR (mais pas dans les chaînes de caractères et les commentaires), il faut donc l'échapper avec une barre oblique inversée.)

Et peut être testé avec la classe :

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

Maintenant, générez un analyseur/lexeur (A), compilez tous les fichiers sources (B) et exécutez la classe principale (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

(sous Windows, exécutez-le en faisant java -cp .;antlr-3.2.jar Main )

qui produit le résultat suivant :

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

Donc, oui, vous aviez besoin d'un "prédicat sémantique gated" ( {boolean}?=> ) dans ce cas, et non un "Validation du prédicat sémantique" ( {boolean}? ). La différence entre les deux prédicats est expliquée dans ce précédent Q&R de SO : Qu'est-ce qu'un "prédicat sémantique" dans ANTLR ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X