I. Introduction▲
JavaCC 21 est la continuation du travail sur le vénérable générateur de code JavaCC, initialement développé chez Sun Microsystems dans les années 90 et dont le code source fut libéré en 2003, sous une licence open source libérale. JavaCC 21 est la version la plus avancée de JavaCC en ce moment. Il y a beaucoup de nouvelles fonctionnalités et il est prévu d'en d'avoir plus prochainement. D'ailleurs, certains bogues de longue date ont été corrigés.
Le « 21 » de JavaCC 21 n'est pas un numéro de version. Cela fait simplement partie du nom du projet et cela signifie que c'est une version de JavaCC pour le 21e siècle.
L'objectif de ce tutoriel est de vous présenter les principales avancées de cette évolution majeure.
II. Support actualisé du Langage Java▲
JavaCC 21 supporte le langage Java jusqu'à version JDK 13. La grammaire Java que JavaCC 21 utilise en interne peut être utilisée dans vos propres projets sans aucune restriction. Des informations complémentaires peuvent être trouvées sur cette page.
III. Les prédicats syntactiques fonctionnent correctement▲
Avec JavaCC, une limitation de longue date est que les prédicats ne peuvent pas s'utiliser de façon récursive. Il s'agit d'un problème qui existe depuis de nombreuses années et qui n'avait jamais été résolu. Comme conséquence, l'outil a toujours été moins utile que ce qu'il aurait dû être, vu qu'un usage moindrement sophistiqué implique typiquement des lookaheads récursifs et, tout simplement, que cela ne fonctionnait pas. En JavaCC 21, cela fonctionne enfin. Des informations complémentaires peuvent être trouvées sur cette page.
IV. Une syntaxe simplifiée▲
Bien que la syntaxe originale fonctionne encore et sera toujours supportée dans le futur, JavaCC 21 offre une nouvelle syntaxe simplifiée qui est plus facile à écrire et à lire. Parfois, il s'agit d'une amélioration de lisibilité qui est absolument importante. Par exemple, où vous auriez écrit avant :
void
FooBar
(
) :
{}
{
Foo
(
) Bar
(
)
}
avec la nouvelle syntaxe simplifiée, vous pouvez maintenant écrire :
FooBar : Foo Bar ;
Les aspects plutôt lourds de la syntaxe LOOKAHEAD ont été simplifiés. Plus de détails peuvent être trouvés sur cette page. Encore une fois, la nouvelle syntaxe offre parfois des améliorations de clarté importante. Où vous auriez écrit avant :
LOOKAHEAD
(
Foo
(
) Bar
(
) Baz
(
)) Foo
(
) Bar
(
) Baz
(
)
Avec JavaCC 21, vous pouvez désormais écrire :
=>
Foo Bar Baz
Le nouveau signet jusqu'ici fournit aussi de grands gains en lisibilité et maintenabilité. Des informations complémentaires peuvent être trouvées sur cette page. Par exemple, où vous auriez écrit avant :
LOOKAHEAD(Foo() Bar()) Foo() Bar() Baz()
Vous pouvez écrire maintenant :
Foo Bar =>|| Baz
Ce nouvel élément syntactique =>|| s'appelle le signet jusqu'ici et il permet d'écrire, de manière très claire, que, si l'on voit l'exppansion Foo Bar Baz, alors on scanne en avant jusqu'à la fin de Bar.
V. Les prédicats Lookbehind▲
Lookbehind (regarder en arrière) est une nouvelle fonctionnalité en JavaCC 21 qui vous permet d'écrire des prédicats aux points de choix qui vérifient si l’on se trouve à un point donné dans un texte. Par exemple :
SCAN ...\Foo => Bar
Ce code veut dire qu'on entre la production Foo si on n'est pas déjà dans un Foo. (Autrement dit, Foo n'est pas une production rentrante.) Il s'agit d'une fonctionnalité très utile, déjà utilisée dans le développement interne. Cette fonctionnalité n'est pas présente dans d'autres outils similaires à JavaCC.
VI. Améliorations dans la construction d'arbres syntactiques▲
JavaCC 21 se base sur la notion que la construction d'un AST (Abstract Syntax Tree) est l'usage normal (ou typique) de ce genre d'outil. Bien que le package JavaCC original (20e siècle) avait une fonctionnalité pour construire les AST, le préprocesseur JJtree a des problèmes d'ergonomie de longue date.
Ce qui fait que JJTree est assez lourd à utiliser, c'est précisément qu'il s'agit d'un préprocesseur ! En JavaCC 21, toute cette fonctionnalité est tout simplement dans l'outil de base et le parseur généré construit un AST par défaut. La construction de l'arbre peut être arrêtée tout de même.
JavaCC 21 se sert de la même syntaxe pour les annotations de construction d'AST que JJTree.
JavaCC 21 a une déclaration INJECT qui vous permet d'injecter du code Java dans n'importe quel fichier généré. On peut ainsi éviter d'utiliser cet anti-pattern qui nécessite de modifier manuellement les fichiers générés.
VII. Meilleur code généré▲
JavaCC 21 génère généralement du code bien plus lisible. D'ailleurs, le code généré est bien plus récent. Considérons le champ Token.kind dans le fichier Token.java généré par l'outil original. Ce champ est un un entier (type primitif) et contrairement à de bonnes pratiques très connues il est publiquement accessible. Dans le fichier Token.java généré para JavaCC 21, la méthode Token.getType() renvoie un Enum (qui est type-safe) et tout le code du parseur généré qui utilisait des entiers pour représenter le type du Token, utilise maintenant des type-safe enums.
Le code généré par le JavaCC original ne donnait pratiquement aucune information au sujet de la provenance du code généré. Les parseurs générés par JavaCC 21 possèdent l'information ligne/colonne relative au fichier source de la grammaire JavaCC. Les parseurs injectent l’information dans la pile d'exécution de ParseException sur la ligne/colonne du fichier grammaire.
Si vous voulez faire une comparaison du code généré par le JavaCC original et celui généré par JavaCC 21, vous pouvez regarder ici.
Le code de JavaCC 21 lui-même est le fruit d'une importante refactorisation. La génération du code a été externalisée dans des templates FreeMarker. Pour se faire une idée de ce que cela veut dire dans la pratique, voici le template principal pour générer le code Java pour les productions grammaticales.
VIII. Diverses améliorations sur les possibilités d’utilisation▲
En général, les paramètres par défaut de JavaCC 21 sont plus sensés, ce qui fait que l'outil est bien plus facile à utiliser pour les débutants. Des informations complémentaires peuvent être trouvées sur cette page.
IX. JavaCC 21 est sous développement actif▲
Ceci, parmi tout, est peut-être le point plus important : le projet est à nouveau sous développement actif. Alors, les usagers peuvent s'attendre à de nouvelles fonctionnalités bientôt. Vu que la génération du code a été externalisée dans des templates, la possibilité de générer des parseurs dans d'autres langages ne devrait pas tarder. Un autre objectif qui devrait être assez proche, c'est de pouvoir générer des parseurs fault-tolerant qui peuvent construire un AST même quand l'entrée contient des erreurs.
Une façon de se tenir à jour avec le projet JavaCC 21 est de s'abonner à la liste d'informations).
L'usage est vraiment assez simple comme cela est décrit sur cette page. JavaCC 21 est invoqué depuis la ligne de commandes avec :
$ java -jar javacc-full.jar MyGrammar.javacc
Un ficher .jar récent est toujours disponible sur cette page : https://javacc.com/download/javacc-full.jar. D’une autre façon, on peut obtenir le dernier code source de Github et faire une construction manuelle :
$ git clone https://github.com/javacc21/javacc21.git
$ cd javacc21
$ ant jar test
X. Conclusion▲
Si vous vous intéressez à ce projet, n'hésitez pas à utiliser la discussion prévue à cet effet Commentez .
Cet article est une traduction de cette publication.
Nous tenons à remercier escartefigue pour sa relecture attentive de cet article et Mickael BARON pour la mise au gabarit.