This shows you the differences between two versions of the page.
alf:laboratoare:03_fr_java [2023/03/19 17:04] alexandra.negoita02 |
alf:laboratoare:03_fr_java [2023/04/03 17:37] (current) alexandra.negoita02 [Lexer en ANTLR4] |
||
---|---|---|---|
Line 18: | Line 18: | ||
=== Installation globale === | === Installation globale === | ||
- | - 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:runtime.JPG?550&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 }} |
- | - 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:set-system-var.PNG?450&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 }} |
- 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 31: | ||
=== Installation dans Intelij === | === Installation dans Intelij === | ||
- | - Telecharger le plugin ANTLR4 pour Intelij depuis ce [[http://example.com|lien]]. Redémarrer le programme Intelij apres l'installation. | + | - 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 }} |
- | - Créer un nouveau projet en Intelij et assurez-vous que c'est un project type 'Maven'. | + | - 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 }} |
- | - Entrez dans 'File > Settings' et assurez-vous que le plugin 'ANTLR v4' est active. | + | - Entrez dans 'File > Settings' et assurez-vous que le plugin 'ANTLR v4' est active. {{ :alf:laboratoare:antlr-plugin-enables.png?400&nolink }} |
- | - Dans le fichier 'pom.xml', ecrivez les lignes suivantes, pour ajouter l'archive ANTLR dans notre projet. | + | - Dans le fichier 'pom.xml', ecrivez les lignes suivantes, pour ajouter l'archive ANTLR dans notre projet. <code> |
- | - 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'. | + | <dependencies> |
- | - Redemarrer Visual Studio Code | + | <dependency> |
- | - Ajouter un nouveau //script// dans le fichier **package.json** avec le contenu <code javascript>"scripts": { | + | <groupId>org.antlr</groupId> |
- | // ... | + | <artifactId>antlr4-runtime</artifactId> |
- | "antlr4ts": "antlr4ts -visitor path/to/Alf.g4" | + | <version>4.11.1</version> |
- | }</code> {{ :alf:laboratoare:packagejson.JPG?400&nolink }} | + | </dependency> |
- | - Configurer le fichier **tsconfig.json**. <code json>{ | + | </dependencies> |
- | "compilerOptions": { | + | </code> {{ :alf:laboratoare:antlr-xml.png?400&nolink }} |
- | "target": "es2016", | + | - 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 }} |
- | "module": "commonjs", | + | - Le resulat sera: {{ :alf:laboratoare:antlr-dependencies2.png?400&nolink }} |
- | "strict": true, | + | |
- | "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)** |