Ce TP est destiné à vous présenter le fonctionnement d'un lexer, son but étant de diviser un texte dans des parties identifiables, appelées jetons (tokens), comme dans l'exemple suivant.
En informatique, on va réaliser cette division à l'aide de l'outil ANTLR, spécialement créé pour traiter les textes structurés.
ANTLR (ANother Tool for Language Recognition) est un générateur d'analyseurs pour lire, traiter, exécuter ou traduire du texte structuré ou des fichiers binaires. Il est largement utilisé pour créer des langages, des outils et des frameworks. À partir d'une description de langage formel, ANTLR génère un analyseur pour ce langage qui peut automatiquement créer des arbres d'analyse, dont on va discuter dans les cours et les TPs suivants. ANTLR génère également automatiquement des arborescences qu'on peut utiliser pour visiter les nœuds de ces arbres afin d'exécuter du code spécifique à l'application.
L'outil nécessaire pour générer du code à partir d'ANTLR4 est écrit en Java. Donc, on a besoin seulement de l'archive ANTLR4 et d'un plug-in specialise pour Intelij.
.jar
doivent etre sauvegardé dans un dossier spécial que vous devrez créer sur votre ordinateur, C:\Javalib. antlr-4.11.1-complete.jar
à la variable d'environnement CLASSPATH (aussi pour les variables de systeme que pour celles de votre utilisateur). Vous pouvez lire plus sur les variables d'environnement ici. antlr4.bat
permet d'utiliser antlr4 dans la ligne de commande depuis n'importe quel fichier. Il doit contenir la commande java org.antlr.v4.Tool %.grun.bat
est utilisé pour tester le fichier d'entrée et pour afficher l'arbre d'analyse sous des formes différentes. Il doit contenir la commande java org.antlr.v4.runtime.misc.TestRig %*. antlr4
dans le Command Prompt.
<dependencies> <dependency> <groupId>org.antlr</groupId> <artifactId>antlr4-runtime</artifactId> <version>4.11.1</version> </dependency> </dependencies>
En informatique, l'analyse lexicale, le lexing ou la tokenisation est le processus de conversion d'une séquence de caractères (comme dans un programme informatique) en une séquence de jetons (chaînes avec une signification attribuée et donc identifiée). Un programme qui effectue une analyse lexicale peut être appelé un lexer.
Un lexer est généralement combiné avec un parser, qui analysent ensemble la syntaxe des langages de programmation, des pages Web, etc. Dans ce chapitre, nous approfondirons uniquement les principes de construction d'un lexer, et nous discuterons des autres composants dans les TPs suivants.
Vous pouvez construire un lexer de deux façons:
Character | Description | Exemple |
---|---|---|
* | Zéro ou plusieurs fois | a*, (ab)* |
+ | Une ou plusieurs fois | a+, (ab)+ |
? | Zéro ou une fois | a?, (ab)? |
^ | début de string | ^ab* |
$ | fin de string | b*a$ |
. | tout symbole | . |
[ ] | Ensemble | [abc] |
\s | Espace blanc | a\sb |
[^ ] | ensemble complémentaire | [^abc] |
( ) | groupe | (abc)+ |
| | Ou | a | b, (ab) | (ba) |
{n} | n fois | a{3} |
{n,m} | minimum n, maximum m | a{3,7} |
\w | alphanumérique et _ | \w |
\t | TAB | a\ta* |
\n | fin de ligne | a\nb |
\r | retour chariot | a\rb |
a(?!b) | a seulement si non suivi par b | a(?!b) |
a(?=b) | a seulement si suivi par b | a(?=b) |
( ) | group | a(ab)a |
Maintenant, nous devons ecrire le premier fichier '.g4', qui va acontenir toutes les regles de grammaire que nouv voulons avoir dans notre programme. Faisez un nouveau fichier 'alf.g4', qui va avoir les lignes suivantes:
grammar alf; main: 'Hello ' NAME '!'; NAME: ([A-Za-z]+);
On peut observer la définition d'un token (à l'aide des expressions régulières), NAME pour identifier le nom introduit.
Après avoir créé ce fichier, on peut voir l'arbre generee par ANTLR, dans le menu 'ANTLR Preview'. En gauche, vous pouvez ecrire le texte qui va etre analyse, et en droit est l'arbre avec tokens.
Pour utiliser la grammaire dans un programme, on doit premierement configurer ou sont generees les fichiers necessaires pour l'analyse ANTLR.
L'étape suivante suppose la création de Main.java, où l'on doit écrire la structure du programme et gestionner le fichier d'entrée:
package org.example; // Import generated files import com.alf.parser.alfLexer; import com.alf.parser.alfParser; import org.antlr.v4.runtime.CharStreams; import org.antlr.v4.runtime.CommonTokenStream; public class Main { public static void main(String[] args) { // Create lexer from input string alfLexer lexer = new alfLexer(CharStreams.fromString("Hello ALF!")); // Create parser alfParser parser = new alfParser(new CommonTokenStream(lexer)); // Parse the input, where `main` is the entry point you defined in the grammar file alfParser.MainContext tree = parser.main(); System.out.println("Tokens: " + tree.children); // Now we can get each token from the input we introduced String name = tree.NAME().getText(); System.out.println("Name intoduced: " + name); } }
alf.g4
), vous devez generer de nouveau les fichiers de ANTLR, avec clic-droit sur le fichier de grammaire > Generate ANTLR Recognizer
String[] books_array = {"Engineering a Compiler,9780120884780,7th February 2011", "Modern Operating Systems 4,9780133591620,21st March 2014", "Computer Networks,9332518742,9th January 2010"};
Alf.tokens
créé automatiquement par ANTLR et générez un HashMap qui ait comme clés l'indice de vos tokens et comme valeurs leur nom. (0.5p) {1='Hello ', 2='!', 3=NAME}
[{ '10': 'INT', '\n': 'NEWLINE', '20': 'INT' }
Alf.g4
des expressions régulières pour les jetons suivants: NUMBER - tout texte contenant uniquement des chiffres et PONCTUATION - différents signes de ponctuation. Utilisez le lexer créé dans l'exercice précédent pour afficher la liste des tokens pour le texte: Bonjour! Le TP d'ALF est de 8 a 10. (1p)program.py
. Ecrivez chaque type de jeton, le texte qui lui correspond et la ligne où il a été trouvé. (1p)