J'aimerais commencer avec ANTLR, mais après avoir passé quelques heures à passer en revue les exemples sur le site antlr.org , je ne parviens toujours pas à comprendre clairement le processus de grammaire vers Java.
Y a-t-il un exemple simple, quelque chose comme une calculatrice à quatre opérations implémentée avec ANTLR passant par la définition de l'analyseur et jusqu'au code source Java?
Réponses:
Remarque : cette réponse est pour ANTLR3 ! Si vous recherchez un exemple ANTLR4 , cette Q&R montre comment créer un analyseur d'expression simple et un évaluateur à l'aide d' ANTLR4 .
Vous créez d'abord une grammaire. Vous trouverez ci-dessous une petite grammaire que vous pouvez utiliser pour évaluer les expressions construites à l'aide des 4 opérateurs mathématiques de base: +, -, * et /. Vous pouvez également grouper des expressions à l'aide de parenthèses.
Notez que cette grammaire est juste très basique: elle ne gère pas les opérateurs unaires (le moins dans: -1 + 9) ou les décimales comme .99 (sans numéro de tête), pour ne nommer que deux défauts. Ceci est juste un exemple sur lequel vous pouvez travailler.
Voici le contenu du fichier de grammaire Exp.g :
(Les règles de l'analyseur commencent par une lettre minuscule et les règles de lexer commencent par une lettre majuscule)
Après avoir créé la grammaire, vous voudrez en générer un analyseur et un lexeur. Téléchargez le pot ANTLR et stockez-le dans le même répertoire que votre fichier de grammaire.
Exécutez la commande suivante sur votre shell / invite de commande:
Il ne devrait pas produire de message d'erreur et les fichiers ExpLexer.java , ExpParser.java et Exp.tokens doivent maintenant être générés.
Pour voir si tout fonctionne correctement, créez cette classe de test:
et compilez-le:
puis exécutez-le:
Si tout se passe bien, rien n'est imprimé sur la console. Cela signifie que l'analyseur n'a trouvé aucune erreur. Lorsque vous passez
"12*(5-6)"
à"12*(5-6"
, puis recompilez et exécutez-le, il devrait être imprimé ce qui suit:Bon, maintenant nous voulons ajouter un peu de code Java à la grammaire pour que l'analyseur fasse réellement quelque chose d'utile. L'ajout de code peut être fait en plaçant
{
et à l'}
intérieur de votre grammaire avec du code Java simple à l'intérieur.Mais d'abord: toutes les règles de l'analyseur dans le fichier de grammaire doivent renvoyer une valeur double primitive. Vous pouvez le faire en ajoutant
returns [double value]
après chaque règle:ce qui nécessite peu d'explications: chaque règle devrait renvoyer une valeur double. Maintenant, pour "interagir" avec la valeur de retour
double value
(qui n'est PAS à l'intérieur d'un bloc de code Java ordinaire{...}
) à l'intérieur d'un bloc de code, vous devrez ajouter un signe dollar devantvalue
:Voici la grammaire mais maintenant avec le code Java ajouté:
et puisque notre
eval
règle retourne maintenant un double, changez votre ANTLRDemo.java en ceci:Encore une fois (générez) un nouveau lexer et analyseur à partir de votre grammaire (1), compilez toutes les classes (2) et exécutez ANTLRDemo (3):
et vous verrez maintenant le résultat de l'expression
12*(5-6)
imprimé sur votre console!Encore une fois: ceci est une très brève explication. Je vous encourage à parcourir le wiki ANTLR et à lire quelques tutoriels et / ou jouer un peu avec ce que je viens de poster.
Bonne chance!
ÉDITER:
Cette publication montre comment étendre l'exemple ci-dessus afin de
Map<String, Double>
pouvoir fournir un qui contient des variables dans l'expression fournie.Pour que ce code fonctionne avec une version actuelle d'Antlr (juin 2014), j'ai dû apporter quelques modifications.
ANTLRStringStream
nécessaire pour devenirANTLRInputStream
, la valeur renvoyée devait passer deparser.eval()
àparser.eval().value
, et je devais supprimer laWS
clause à la fin, car les valeurs d'attribut telles que$channel
ne sont plus autorisées à apparaître dans les actions de lexer.la source
parser.eval()
? Ce n'est pas clair ICI ou sur le Wiki ANTLR3!eval
est une règle d'analyse qui renvoie adouble
. Il existe donc uneeval()
méthode que vous pouvez invoquer sur une instance d'unExpParser
, comme je l'ai démontré dans leANTLRDemo.main(...)
. Après avoir généré un lexer / analyseur, ouvrez simplement le fichierExpParser.java
et vous verrez qu'il existe uneeval()
méthode renvoyant adouble
.Le méga tutoriel ANTLR de Gabriele Tomassetti est très utile
Il contient des exemples de grammaire, des exemples de visiteurs dans différents langages (Java, JavaScript, C # et Python) et bien d'autres choses. Hautement recommandé.
EDIT: autres articles utiles de Gabriele Tomassetti sur ANTLR
la source
Pour Antlr 4, le processus de génération de code java est ci-dessous: -
Mettez à jour le nom de votre bocal dans classpath en conséquence.
la source
Sur https://github.com/BITPlan/com.bitplan.antlr, vous trouverez une bibliothèque java ANTLR avec quelques classes d'aide utiles et quelques exemples complets. Il est prêt à être utilisé avec maven et si vous aimez l'éclipse et le maven.
https://github.com/BITPlan/com.bitplan.antlr/blob/master/src/main/antlr4/com/bitplan/exp/Exp.g4
est un langage d'expression simple qui peut multiplier et ajouter des opérations. https://github.com/BITPlan/com.bitplan.antlr/blob/master/src/test/java/com/bitplan/antlr/TestExpParser.java a les tests unitaires correspondants pour cela.
https://github.com/BITPlan/com.bitplan.antlr/blob/master/src/main/antlr4/com/bitplan/iri/IRIParser.g4 est un analyseur IRI qui a été divisé en trois parties:
https://github.com/BITPlan/com.bitplan.antlr/blob/master/src/test/java/com/bitplan/antlr/TestIRIParser.java a les tests unitaires pour cela.
Personnellement, j'ai trouvé que c'était la partie la plus délicate pour réussir. Voir http://wiki.bitplan.com/index.php/ANTLR_maven_plugin
https://github.com/BITPlan/com.bitplan.antlr/tree/master/src/main/antlr4/com/bitplan/expr
contient trois autres exemples qui ont été créés pour un problème de performances d'ANTLR4 dans une version antérieure. En attendant, ce problème a été résolu comme le montre le cas de test https://github.com/BITPlan/com.bitplan.antlr/blob/master/src/test/java/com/bitplan/antlr/TestIssue994.java .
la source
la version 4.7.1 était légèrement différente: pour l'importation:
pour le segment principal - notez les CharStreams:
la source