Cup et JFlex Introduction Téléchargement • CUP http://www2.cs.tum.edu/projects/cup/java‐cup‐11b.jar • Jflex + Documentation http://jflex.de/jflex‐1.5.1.zip Documentation en ligne • Cup http://www2.cs.tum.edu/projects/cup/manual.html • JFlex http://jflex.de/manual.html Compilation java ‐jar java‐cup‐11b.jar parse0.cup Résultat: sym.java: la table des symboles contenant les terminaux parser.java CUP Structure d’un fichier CUP Un fichier CUP (extension: .cup) est composé de quatre sections qui doivent être dans l’ordre suivant: • déclarations préliminaires (section non obligatoire) • Code utilisateur (section non obligatoire) • Définition des terminaux et des non terminaux. • Précédence et associativité des terminaux. (non obligatoire) • La grammaire. 1. La première section peut contenir: • le nom du package de la classe parser.java (classe générée par CUP). • Imports de packages java. • Exemple : package lir; import java_cup.runtime.*; 2. Code utilisateur Cette peut contenir du code java qui sera inclus dans le parseur, parser code {: Le contenu sera inclus dans la classe parse. :}; 3. Déclaration de terminaux Syntaxe : terminal [Type] T1[,T2…] ; non terminal [Type] n1[,n2…]; 4. Précédence et associativité des terminaux precedence left T1[, T2...]; precedence right T1[, T2...]; precedence nonassoc T1[, T2...]; 5. La grammaire par défaut l’axiome est le non terminal de la partie gauche de la première production. La directive « start with N ;» permet de définir l’axiome. la grammaire est définie par une liste de productions, exemple d’une production instruction ::= affectation | affichage ; on peut aussi exécuter des actions sémantiques écrites en Java si la production est utilisée, exemple: expression ::= expression:e1 ADD expression:e2 {: RESULT = new Integer(e1.intValue() + e2.intValue()); :} RESULT désigne toujours le non terminal de la partie gauche. • Exécution: java ‐jar chemin/java‐cup‐11b.jar lir.cup. • Résultat: • parser.java: implémentation du parseur • sym.java: contient les constantes qui représentent les terminaux. Actions sémantiques • Une action sémantique est exprimée entre les délimiteurs {: et :} • Exemple expr:e1 PLUS expr:e2 {: RESULT = new Integer(e1.intValue() + e2.intValue()); :} Le premier non terminal est étiquetté par e1 et le deuxième par e2. Le non terminal de la partie gauche d’une production est toujours étiquetté par RESULT. Chaque symbole dans une production est représenté par un objet de type Symobl (dans la pile d’analyse ). Une étiquette fait référence à un objet dont la référence est stocké dans le champ value de la classe Symbol Pour chaque étiquette par exemple e1, deux autres variables sont accessibles dans l’action sémantique (e1left et e1right qui sont du même type que e1) • init with {: scanner.init(); :}; Le code contenu dans l'action de la clause "init with" de la spécification sera exécuté avant que les jetons ne soient demandés • le token sera demandé l'aide du code de la clause "scan with« Le Scanner • Le scanner doit retourner des objets de type Symbol, la valeur est stockée dans l’attribut value et le type doit être identique à celui présent dans la déclaration du fichier cup. • Les symboles déclarés sans type de données ont la valeur null dans l’attribut value. • Le code contenu dans l'action de la clause "init with" de la spécification sera exécuté avant que les jetons soient demandés JFlex Installation C:\jflex-1.5.1\ +--bin\ (start scripts) +--doc\ (FAQ and manual) +--examples\ +--byaccj\ (calculator example for BYacc/J) +--cup\ (calculator example for cup) +--interpreter\ (interpreter example for cup) +--java\ (Java lexer specification) +--simple-maven\ (example scanner built with maven) +--standalone-maven\ (a simple standalone scanner, built with maven) +--lib\ (precompiled classes, skeleton files) +--src\ +--main\ +--cup\ (JFlex parser spec) +--java\ +--java_cup\ +--runtime\ (source code of cup runtime classes) +--jflex\ (source code of JFlex) +--gui\ (source code of JFlex UI classes) +--jflex\ (JFlex scanner spec) +--resources\ (messages and default skeleton file) +--test\ (unit tests) m Modifier le fichier bin/jflex.bat (JAVA_HOME doit être déjà définie) • JFLEX_HOME=c:\JFLEX Exécution • jflex <options> <inputfiles> • java ‐jar jflex‐1.5.1.jar <options> <inputfiles> Un fichier Jflex est composé de 3 sections: Code de l’utilisateur %% Options et déclarations de macros %% Règles lexicales Code utilisateur Le contenu de cette section sera recopié dans le fichier généré par Jflex avant la déclaration de la classe. Essentiellement, le code écrit ici contiendra des imports de packages. Options et déclarations 1. Options Les options permettent de passer des arguments à l’outil JFlex. %class Lexeur: demande à JFlex de nommer le fichier produit “Lexeur.java”. %public, %final, %abstract, %implements interface1 : demande à JFlex de déclarer la classe produite avec l’option correspondante. %cup: permet d’intégrer JFlex avec Cup. %line %column: permet de compter les lignes et les colonnes dans les variables yyline et yycolumn respectivement. 2. Déclarations Les déclarations d’abréviations permettent de simplifier la définition des unités lexicales. Options Mode de compatibilité CUP %cup %implements java_cup.runtime.Scanner %function next_token %type java_cup.runtime.Symbol %eofval{ return new java_cup.runtime.Symbol(<CUPSYM>.EOF); %eofval} %eofclose /* Fermer le flux si EOF atteinte. Par défaut CUPSYM est sym, peut être modifié par %cupsym