OMeta
Écrire un analyseur grammatical "à la main" est une tâche fastidieuse et source de nombreuses erreurs, typiquement pour implémenter une spécification de langage qui évolue constamment. C'est pour cette raison que des générateurs d'analyseurs grammaticaux sont souvent utilisés pour automatiser ce processus.
Un compilateur utilise non seulement un analyseur grammatical mais aussi un analyseur syntaxique, plusieurs traducteurs et enfin un générateur de code - chacun pouvant être issus de différents outils et même utiliser différents langages.
Alessandro Warth a créé le langage OMeta afin d'unifier tous ces outils, réduire la courbe d'apprentissage et faciliter l'expérimentation de langages. Ce langage a été créé dans le cadre d'une thèse de doctorat. Vous pouvez consulter cette thèse ici : http://www.vpri.org/pdf/tr2008003_experimenting.pdf.
OMeta est un langage de reconnaissance de modèle fondé sur une analyse grammaticale d'expression (PEG - Parsing Expression Grammar). Ce langage permet donc de supprimer la séparation entre l'analyseur grammatical et syntaxique.
De nombreux concepts et extensions sont apportées dans ce langage, mais nous n'allons pas les détailler ici.
Travailler avec OMeta peut être décomposé en 3 parties :
- Écrire une grammaire dans le langage OMeta.
- Configurer le compilateur OMeta et compiler la grammaire.
- Utiliser le résultat de la compilation afin d'analyser et traduire un flux d'entrée.
OMeta/JS
Étant un langage générique de description de grammaire, OMeta a été implémenté dans plusieurs langages hôte. Dans le cadre de notre projet, nous nous intéresserons à la librairie OMeta/JS qui, comme son nom l'indique, est l'implémentation JavaScript du langage OMeta.
Vous pouvez trouver cette librairie dans GitHub à l'adresse : https://github.com/alexwarth/ometa-js. Ce dépôt contient aussi un éditeur en ligne, mais dont nous allons nous passer dans cet article.
Les fichiers nécessaires à notre test sont :
- bs-js-compiler.js
- bs-ometa-compiler.js
- bs-ometa-js-compiler.js
- bs-ometa-optimizer.js
- lib.js
- ometa-base.js
- ometa-script-tag.js
- parser.js
Mise en place
Afin de se familiariser avec ce langage, nous allons tout d'abord créer un environnement de test pour nous aider dans la rédaction de notre grammaire.
Cette étape de rédaction se fera de façon incrémentale afin de mieux décomposer notre problème.
Expérimentations concernant la grammaire
Voici l'enveloppe de notre fichier HTML dans lequel nous allons stocker la grammaire de notre langage:
<html> <head></head> <body> <script type="text/x-ometa-js" id="ometadd"> ometa WSD { } </script> <script src="lib/ometa/lib.js"></script> <script src="lib/ometa/ometa-base.js"></script> <script src="lib/ometa/ometa-script-tag.js"></script> <script src="lib/ometa/parser.js"></script> <script src="lib/ometa/bs-js-compiler.js"></script> <script src="lib/ometa/bs-ometa-compiler.js"></script> <script src="lib/ometa/bs-ometa-js-compiler.js"></script> <script src="lib/ometa/bs-ometa-optimizer.js"></script> <script> document.addEventListener('DOMContentLoaded', function () { // Les différents tests seront ici }); </script> </body> </html>
Nous allons donc faire évoluer ce modèle jusqu'à obtenir la grammaire que nous souhaitons obtenir. Notez que l'interprétation automatique de la grammaire est réalisée dans le script "ometa-script-tag.js" dont le rôle est de parcourir la page HTML à la recherche de scripts de type "text/x-ometa-js". Nous pourrions faire autrement mais ce comportement nous convient pour l'instant.