This shows you the differences between two versions of the page.
alf:laboratoare:03_fr_java [2023/03/17 08:55] alexandra.negoita02 created |
alf:laboratoare:03_fr_java [2023/04/03 17:37] (current) alexandra.negoita02 [Lexer en ANTLR4] |
||
---|---|---|---|
Line 14: | Line 14: | ||
==== Configuration ==== | ==== Configuration ==== | ||
- | L'outil nécessaire pour générer du code TypeScript à partir d'ANTLR4 est écrit en Java. Pour utiliser pleinement la cible ANTLR4 TypeScript (y compris la possibilité de régénérer le code à partir d'un fichier après les modifications), un environnement d'exécution Java (JRE) doit être installé sur la machine du développeur. Le code généré lui-même utilise plusieurs fonctionnalités nouvelles de TypeScript 2.0. | + | 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. |
=== Installation globale === | === Installation globale === | ||
- | - Installer une version de [[https://www.java.com/en/|Java]] 1.6+ (on recommande 1.8+). Vous pouvez vérifier l'installation à l'aide de la commande suivante: {{ :alf:laboratoare:java-version.PNG?400&nolink }} | + | - Télécharger le runtime complet d'ANTLR4 pour Java depuis ce [[https://github.com/antlr/website-antlr4/tree/gh-pages/download|lien]]. Le fichier ''.jar'' doivent etre sauvegardé dans un dossier spécial que vous devrez créer sur votre ordinateur, **C:\Javalib**. {{ :alf:laboratoare:download-anltr-4.11.1.png?550&nolink }} |
- | - Télécharger le runtime complet d'antlr4 pour Java, ainsi que l'archive pour JavaScript depuis ce [[https://www.antlr.org/download/|lien]]. Le fichier ''.jar'' et le dossier decompressé pour JavaScript doivent etre sauvegardés dans un dossier spécial que vous devrez créer sur votre ordinateur, **C:\Javalib**. {{ :alf:laboratoare:runtime.JPG?550&nolink }} | + | - Ajouter ''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 [[https://support.shotgunsoftware.com/hc/en-us/articles/114094235653-Setting-global-environment-variables-on-Windows|ici]]. {{ :alf:laboratoare:antlr-classpath.png?450&nolink }} |
- | - Ajouter ''antlr-4.9-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 [[https://support.shotgunsoftware.com/hc/en-us/articles/114094235653-Setting-global-environment-variables-on-Windows|ici]]. {{ :alf:laboratoare:set-system-var.PNG?450&nolink }} | + | |
- Créer 2 fichiers [[https://www.computerhope.com/jargon/b/batchfil.htm|batch]]. | - Créer 2 fichiers [[https://www.computerhope.com/jargon/b/batchfil.htm|batch]]. | ||
- Le fichier ''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 %**. | - Le fichier ''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 %**. | ||
- | - Le fichier ''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 %***. {{ :alf:laboratoare:batch-files.PNG?550&nolink }} | + | - Le fichier ''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 %***. {{ :alf:laboratoare:antlr-bat-files.png?550&nolink }} {{ :alf:laboratoare:antlr-javalib-structure.png?400&nolink }} |
- | - Ajouter le dossier **C:\Javalib** a la variable d'environnement PATH. {{ :alf:laboratoare:set-javalib-path.PNG?500&nolink }} | + | - Ajouter le dossier **C:\Javalib** a la variable d'environnement PATH. {{ :alf:laboratoare:antlr-path-envvar.png?500&nolink }} |
- | - Vérifier l'installation en tapant ''antlr4'' dans le Command Prompt. {{ :alf:laboratoare:check-antlr4.PNG?400&nolink }} | + | - Vérifier l'installation en tapant ''antlr4'' dans le Command Prompt. {{ :alf:laboratoare:antlr-cmd-test.png?400&nolink }} |
<note important> | <note important> | ||
Line 31: | Line 30: | ||
</note> | </note> | ||
- | === Installation pour TypeScript === | + | === Installation dans Intelij === |
- | - Créer un nouveau projet en Visual Studio Code et initialisez le fichier **package.json** avec la commande ''npm init''. | + | - Telecharger le plugin ANTLR4 pour Intelij depuis ce [[https://plugins.jetbrains.com/plugin/7358-antlr-v4|lien]]. Redémarrer le programme Intelij apres l'installation. {{ :alf:laboratoare:download-antlr-intelij-plugin.png?400&nolink }} |
- | - Installer ''antlr4ts'' en tant que dépendance d'exécution (runtime dependency) depuis le Terminal de VSCode. <code bash>npm install antlr4ts --save</code> | + | - Créer un nouveau projet en Intelij et assurez-vous que c'est un project type 'Maven'. {{ :alf:laboratoare:antlr-intelij-project.png?400&nolink }} |
- | - Installer ''antlr4ts-cli'' en tant que dépendance de développement depuis le Terminal de VSCode.<code bash>npm install antlr4ts-cli --save-dev</code> | + | - Entrez dans 'File > Settings' et assurez-vous que le plugin 'ANTLR v4' est active. {{ :alf:laboratoare:antlr-plugin-enables.png?400&nolink }} |
- | - Installer [[https://marketplace.visualstudio.com/items?itemName=mike-lischke.vscode-antlr4|l'extension d'ANTLR4]] depuis le navigateur web ou directement du MarketPlace de Visual Studio Code. {{ :alf:laboratoare:antlr4-extension.JPG?550&nolink }} | + | - Dans le fichier 'pom.xml', ecrivez les lignes suivantes, pour ajouter l'archive ANTLR dans notre projet. <code> |
- | - Redemarrer Visual Studio Code | + | <dependencies> |
- | - Ajouter un nouveau //script// dans le fichier **package.json** avec le contenu <code javascript>"scripts": { | + | <dependency> |
- | // ... | + | <groupId>org.antlr</groupId> |
- | "antlr4ts": "antlr4ts -visitor path/to/Alf.g4" | + | <artifactId>antlr4-runtime</artifactId> |
- | }</code> {{ :alf:laboratoare:packagejson.JPG?400&nolink }} | + | <version>4.11.1</version> |
- | - Configurer le fichier **tsconfig.json**. <code json>{ | + | </dependency> |
- | "compilerOptions": { | + | </dependencies> |
- | "target": "es2016", | + | </code> {{ :alf:laboratoare:antlr-xml.png?400&nolink }} |
- | "module": "commonjs", | + | - On doit aussi ajouter le fichier '.jar' dans le project, pour etre reconnu par Intelij. Entrez dans 'File > Project Structure', appuyez sur le menu 'Modules' et puis sur le boutton '+', et ajouter le fichier '.jar' qui est dans le directoire 'C:\Javalib'. Puis, appuyez sur 'Apply' et 'OK'. {{ :alf:laboratoare:antlr-dependencies.png?400&nolink }} |
- | "strict": true, | + | - Le resulat sera: {{ :alf:laboratoare:antlr-dependencies2.png?400&nolink }} |
- | "esModuleInterop": true, | + | |
- | "skipLibCheck": true, | + | |
- | "forceConsistentCasingInFileNames": true, | + | |
- | "lib": ["es2016"], | + | |
- | "moduleResolution": "node" | + | |
- | } | + | |
- | }</code> | + | |
- | - Télécharger les dépendences suivantes: <code bash>npm install --save-dev @types/node | + | |
- | npm install --save-dev typescript</code> | + | |
- | + | ||
- | <note important> | + | |
- | Vous pouvez lire plus de détails sur la configuration d'ANTLR4 pour TypeScript [[https://github.com/tunnelvisionlabs/antlr4ts|ici]]. | + | |
- | </note> | + | |
===== Lexer ===== | ===== Lexer ===== | ||
Line 73: | Line 59: | ||
==== Rappel - Expressions régulières ==== | ==== Rappel - Expressions régulières ==== | ||
- | === Mathematique === | ||
^ Character ^ Description ^ Exemple ^ | ^ Character ^ Description ^ Exemple ^ | ||
| * | Zéro ou plusieurs fois | a*, (ab)* | | | * | Zéro ou plusieurs fois | a*, (ab)* | | ||
Line 86: | Line 71: | ||
| ( ) | groupe | (abc)+ | | | ( ) | groupe | (abc)+ | | ||
| %% | %% | Ou | a %%|%% b, (ab) %%|%% (ba) | | | %% | %% | Ou | a %%|%% b, (ab) %%|%% (ba) | | ||
- | |||
- | |||
- | === JavaScript === | ||
- | ^ Character ^ Description ^ Exemple ^ | ||
| {n} | n fois | a{3} | | | {n} | n fois | a{3} | | ||
| {n,m} | minimum n, maximum m | a{3,7} | | | {n,m} | minimum n, maximum m | a{3,7} | | ||
Line 100: | Line 81: | ||
| ( ) | group | a(ab)a | | | ( ) | group | a(ab)a | | ||
- | Pour déclarer des expressions régulières, on a 2 possibilités: | + | ==== Lexer en ANTLR4 ==== |
- | <code javascript> | + | 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: |
- | + | <code> | |
- | // making a new RexExp object the standard way | + | grammar alf; |
- | let regex = new RegExp ("[0-9]+"); | + | |
- | + | ||
- | // making a new RegEx object using a shortcut | + | |
- | let regex: RegExp = /[0-9]+/; | + | |
+ | main: 'Hello ' NAME '!'; | ||
+ | NAME: ([A-Za-z]+); | ||
</code> | </code> | ||
+ | {{ :alf:laboratoare:antlr-alf-g4.png?400&nolink }} | ||
+ | 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. | ||
+ | {{ :alf:laboratoare:antlr-tree-preview.png?400&nolink }} | ||
- | ==== Lexer en ANTLR4 ==== | + | Pour utiliser la grammaire dans un programme, on doit premierement configurer ou sont generees les fichiers necessaires pour l'analyse ANTLR. |
- | Ayant créé le projet TypeScript + ANTLR précédent, on va y ajouter un fichier **Alf.g4** avec le contenu suivant: | + | - Creer un nouveau directoire 'alfLanguage', et marquer le 'Generated Sources Root'. Ce type de directoire signifie qu'il a seulement des fichiers read-only, qui peuvent etre importeed dans Main. {{ :alf:laboratoare:antlr-generated-sources-root.png?400&nolink }} |
- | + | - Clic-droit sur le fichier de grammaire 'alf.g4' et appuyez sur 'Configure ANTLR...'. Le directoire pour output va etre 'alfLanguage', et le paquet qui va contenir tous les fichiers gennerees va etre 'com.alf.parser'. {{ :alf:laboratoare:antlr-configure.png?400&nolink }} | |
- | <code> | + | - Clic-droit sur le fichier de grammaire 'alf.g4' et appuyez sur 'Generate ANTLR Recognizer'. On peut voir maintenant le directoire alfLanguage populee avec plusieurs fichiers: |
- | grammar Alf; | + | |
- | + | ||
- | prog:; | + | |
- | + | ||
- | NEWLINE : ([\r\n]+); | + | |
- | INT : ([0-9]+); | + | |
- | </code> | + | |
- | On peut observer la définition de 2 tokens différents (à l'aide des expressions régulières), //NEWLINE// et //INT// pour les nouvelles lignes, respectivement les numéros entiers. | + | |
- | + | ||
- | Après avoir créé ce fichier, on va exécuter la commande ''npm run antlr4ts'', qui va générer plusieurs fichiers //.ts//, ainsi que les fichiers ''.js'' nécessaires: | + | |
* **Lexer**: les règles de lexer sont destinées à créer des objets token correspondants | * **Lexer**: les règles de lexer sont destinées à créer des objets token correspondants | ||
* **Parser**: les règles de parser sont responsables pour l'analyse du langage | * **Parser**: les règles de parser sont responsables pour l'analyse du langage | ||
* **Listener**: fournit des méthodes appelées indépendamment par un objet walker fourni par ANTLR | * **Listener**: fournit des méthodes appelées indépendamment par un objet walker fourni par ANTLR | ||
* **Visitor**: contient des méthodes qui doivent accompagner (walk) leurs enfants avec des appels de visite explicites | * **Visitor**: contient des méthodes qui doivent accompagner (walk) leurs enfants avec des appels de visite explicites | ||
+ | {{ :alf:laboratoare:antlr-generated.png?400&nolink }} | ||
- | L'étape suivante suppose la création d'un fichier **main.ts** où l'on doit écrire la structure du programme et gestionner le fichier d'entrée: | + | 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: |
- | <code javascript> | + | <code java> |
- | import { CharStreams, CodePointCharStream, CommonTokenStream } from 'antlr4ts'; | + | package org.example; |
- | import { AlfLexer } from './AlfLexer'; | + | |
- | import { AlfParser, ProgContext } from './AlfParser'; | + | |
- | // Create the lexer and parser | + | // Import generated files |
- | let input: string = "10\n20"; | + | import com.alf.parser.alfLexer; |
- | let inputStream: CodePointCharStream = CharStreams.fromString(input); | + | import com.alf.parser.alfParser; |
- | let lexer: AlfLexer = new AlfLexer(inputStream); | + | import org.antlr.v4.runtime.CharStreams; |
- | let tokenStream: CommonTokenStream = new CommonTokenStream(lexer); | + | import org.antlr.v4.runtime.CommonTokenStream; |
- | let parser: AlfParser = new AlfParser(tokenStream); | + | |
- | // Parse the input, where `prog` is whatever entry point you defined | + | public class Main { |
- | let tree:ProgContext = parser.prog(); | + | public static void main(String[] args) { |
- | </code> | + | // Create lexer from input string |
+ | alfLexer lexer = new alfLexer(CharStreams.fromString("Hello ALF!")); | ||
- | <note warning> | + | // Create parser |
- | **ATTENTION!** Après chaque modification dans le fichier //main.js//, vous devez exécuter les commandes suivantes dans le Terminal de Visual Studio Code: | + | alfParser parser = new alfParser(new CommonTokenStream(lexer)); |
- | * ''npx tsc'' - pour exécuter le compilateur TypeScript | + | |
- | * ''node main.js'' - pour exécuter le fichier principal JavaScript généré | + | |
- | </note> | + | |
+ | // 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); | ||
- | <note important> | + | // Now we can get each token from the input we introduced |
- | Après chaque modification apportée à la grammaire (fichier ''Alf.g4''), vous devez exécuter la commande suivante pour enregistrer les changements: <code bash> | + | String name = tree.NAME().getText(); |
- | npm run antlr4ts | + | System.out.println("Name intoduced: " + name); |
+ | } | ||
+ | } | ||
</code> | </code> | ||
+ | {{ :alf:laboratoare:antlr-run.png?400&nolink }} | ||
+ | |||
+ | <note important> | ||
+ | Après chaque modification apportée à la grammaire (fichier ''alf.g4''), vous devez generer de nouveau les fichiers de ANTLR, avec clic-droit sur le fichier de grammaire > ''Generate ANTLR Recognizer'' | ||
</note> | </note> | ||
===== Exercices ===== | ===== Exercices ===== | ||
- | - Traitez le tableau ci-dessous a l'aide des **expressions régulières** de sorte que chaque livre devienne un objet de type Book, avec les suivantes propriétés: //titre// (string), //ISBN// (number), et //date de publication// (string). **(1p)** <code javascript> let books_array: string[] = [ | + | - **(Sans ANTLR)** Traitez le tableau ci-dessous a l'aide des **expressions régulières** de sorte que chaque livre devienne un objet de type Book, avec les suivantes propriétés: //titre// (string), //ISBN// (number), et //date de publication// (string). **(1p)** <code java> String[] books_array = {"Engineering a Compiler,9780120884780,7th February 2011", |
- | 'Engineering a Compiler,9780120884780,7th February 2011', | + | "Modern Operating Systems 4,9780133591620,21st March 2014", |
- | 'Modern Operating Systems 4,9780133591620,21st March 2014', | + | "Computer Networks,9332518742,9th January 2010"};</code> |
- | 'Computer Networks,9332518742,9th January 2010' | + | - Installez ANTLR4 globalement, en suivant les étapes du laboratoire. **(1p)** |
- | ];</code> | + | - Créez le programme complet présenté dans le tutoriel de ce TP (fichiers de configuration, fichier Alf.g4, fichier Main.java) et assurez-vous que son exécution est réalisée sans d'erreurs. Faites input string "Hello <votre nom>!"**(1p)** |
- | - Installez ANTLR4 globalement, ainsi que la version pour TypeScript. Attachez une capture d'écran avec l'exécution de la commande ''antlr4'' dans votre Command Prompt et une autre avec le résultat de la commande ''npm run antlr4ts'' dans le Terminal de Visual Studio Code. **(1p)** | + | |
- | - Créez le programme complet présenté dans le tutoriel de ce TP (fichiers de configuration, fichier Alf.g4, fichier main.ts) et assurez-vous que son exécution est réalisée sans d'erreurs. **(1p)** | + | |
- Affichez la liste des tokens: **(1p)** | - Affichez la liste des tokens: **(1p)** | ||
- | - A l'aide des fonctions pour les strings, traitez le fichier ''Alf.tokens'' créé automatiquement par ANTLR et générez un dictionnaire qui ait comme clés l'indice de vos tokens et comme valeurs leur nom. **(0.5p)** <code bash>{ '1': 'NEWLINE', '2': 'INT' }</code> | + | - A l'aide des fonctions pour les strings, traitez le fichier ''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)** <code bash>{1='Hello ', 2='!', 3=NAME}</code> |
- Parcourez et affichez la liste des tokens (pour chaque token, affichez son nom et sa valeur comme dans l'exemple. **Indice**: Pour pouvoir afficher la liste des tokens, vous devrez inspecter la classe //BufferedTokenStream// et choisir une méthode qui retourne cette liste. Vous aurez aussi besoin de la fonction **nextToken()** pour parcourir le buffer de données. **(0.5)** <code bash>[{ '10': 'INT', '\n': 'NEWLINE', '20': 'INT' }</code> | - Parcourez et affichez la liste des tokens (pour chaque token, affichez son nom et sa valeur comme dans l'exemple. **Indice**: Pour pouvoir afficher la liste des tokens, vous devrez inspecter la classe //BufferedTokenStream// et choisir une méthode qui retourne cette liste. Vous aurez aussi besoin de la fonction **nextToken()** pour parcourir le buffer de données. **(0.5)** <code bash>[{ '10': 'INT', '\n': 'NEWLINE', '20': 'INT' }</code> | ||
- | - Ajoutez a votre fichier ''Alf.g4'' des expressions régulières pour les jetons suivants: WORD - tout texte contenant uniquement des lettres 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)** | + | - Ajoutez a votre fichier ''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)** |
- Utilisez votre lexer pour analyser les jetons du fichier [[https://github.com/UPB-FILS-ALF/TP/blob/main/TP3/text_and_numbers.txt|text_and_numbers.txt]]. Pour chaque ligne de ce fichier affichez le texte du jeton, le type, et la ligne du fichier ou il a été trouvé. **(1p)** | - Utilisez votre lexer pour analyser les jetons du fichier [[https://github.com/UPB-FILS-ALF/TP/blob/main/TP3/text_and_numbers.txt|text_and_numbers.txt]]. Pour chaque ligne de ce fichier affichez le texte du jeton, le type, et la ligne du fichier ou il a été trouvé. **(1p)** | ||
- Ecrivez un lexer qui reconnaît un sous-ensemble du langage Python. Pour chaque point de cet exercice, utilisez comme exemple une chaîne quelconque correspondant au langage Python, pour voir si votre programme peut: **(3p)** | - Ecrivez un lexer qui reconnaît un sous-ensemble du langage Python. Pour chaque point de cet exercice, utilisez comme exemple une chaîne quelconque correspondant au langage Python, pour voir si votre programme peut: **(3p)** |