ANTLR
grammarPour la partie lexeur, on ne propage au parseur que les jetons A, B et C. En effet grâce à la directiveAnBn; // grammar rules file : anbn EOF ; anbn : A anbn B | /* vide */ ; // lexer rules A : 'a'; B : 'b'; C : 'c'; UNMATCH : . -> skip;
skip
, tout ce qui est reconnu par la règle lexicale UNMATCH est simplement
caché. On utilise en général cet artifice pour les commentaires ou les
espaces non significatifs.
AnBn.g4
et la compiler.
antlr4-grun
antlr4-grun
On le lance sur les machines du département avec
$ antlr4-grunqui est équivalent à :
$ java org.antlr.v4.runtime.misc.TestRig(pour peu que la variable
CLASSPATH
soit correctement configurée).
Pour le lancer, il suffit de préciser la grammaire, le
point d'entrée (l'axiome) ainsi que l'option -gui puis d'entrer le
texte à analyser et finir avec ctrl+D
(EOF).
$ antlr4-grun AnBn 'anbn' -gui aaaaabbbbb
aabb
aabbc
aacbb
aaabbb
aadabbb
grammar Calculette; start : expr EOF; expr : expr '*' expr | expr '+' expr | ENTIER ; // lexer NEWLINE : '\r'? '\n' -> skip; WS : (' '|'\t')+ -> skip ; ENTIER : ('0'..'9')+ ; UNMATCH : . -> skip ;
En pratique, ANTLR4 va autoriser cette grammaire et produire un analyseur.
antlr4-grun
sur l'exemple 4 + 5 * 6 + 4
On décide alors de modifier le choix de la règle expr
par:
expr : expr '+'expr | expr '*' expr | ENTIER ;
antlr4-grun
sur l'exemple 4 + 5 * 6 + 4
. Commenter.Nous allons profiter de la capacité d'ANTLR à utiliser des grammaires
attribuées afin de calculer la valeur des expressions.
On associe à chaque symbole un attribut synthétisé val
.
On manipule ces attributs dans les actions en préfixant les symboles par un dollar.
expr returns [ int val ] : a=expr '+' b=expr {$val = $a.val + $b.val;} | ... ;
@parser::members { private int evalexpr (int x, String op, int y) { if ( op.equals("*") ){ return x*y; } else if ( op.equals("+") ){ return x+y; } else { System.err.println("Opérateur arithmétique incorrect : '"+op+"'"); throw new IllegalArgumentException("Opérateur arithmétique incorrect : '"+op+"'"); } } }On notera qu'il est possible de récupérer le contenu d'un jeton (token) à l'aide de la méthode suivante:
expr returns [ int val ] : a=expr op=('*'|'/') b=expr {System.out.println($op.text);}On peut de manière similaire récupérer la valeur du jeton comme entier (si adapté) avec
.int
.
Pour déboguer on peut aussi accéder à la ligne et à la position (.line
et .pos
).
42 24+24-6 5*8+2*1 6*4/5+38 42+1+2+-3 5*8+2*-1/-1 (5*6*7*11 + 2)/11*5-1008 (5*6*7*11 + 2)/(11*5) (5*6*7*11 + 2)/11/5 (5*6*7*11 + 2)/(11/5)-1114