Langages et Documents Traitements des textes « sources » Langages de Programmation Documents Structurés Paul Franchi SI - 4 2014-15 1 Quelques dates 1957-68 1968 1969 1972 1974 1975 1979-83 1980 1981 1982 1984 1985 1983-86 1987 1989 1990 1991 1993 1995 19951996 2004 2008 2010 2010 Fortran, Cobol, Lisp, Algol, APL, PL/I, Basic Pascal, Simula, Algol 68 Multics Unix B C, Prolog, Lex, Yacc DOS, TeX Scheme Green (DoD) => Ada Smalltalk, Modula 2 MS-DOS PostScript, LaTeX Lisa => Mac & Souris Windows C++ Perl, SQL ANSI C, Modula 3 Mosaic + HTML Unix Linux, Python PDF Java, Windows AltaVista, MSN, Yahoo, etc. SGML XML, JavaScript iTunes, iPod Google = 100 Gigas$ iPod x 275 Millions Apple = 225 Giga$ > Microsoft Transparent 3 Langages de Programmation Analyse lexicale Traitements « source to source » Documents Structurés Modèles SGML, DTD, DOM Langages HTML, XML, CSS Transformations XSLT Navigateurs Editeurs & Outils Transparent 4 Compilation Analyses Lexicale, Syntaxique, et Sémantique Chapitres 1 & 2 Paul Franchi SI deuxième année 2014-15 5 Sommaire 1. Introduction à la compilation 2. Analyse lexicale 3. Rappels sur les langages formels 4. Analyse syntaxique non déterministe 5. Analyse syntaxique descendante 6. Analyse syntaxique ascendante 7. Traduction dirigée par la syntaxe 8. Générateurs LR() 9. Sémantique statique des L.P. 10. Traitements «source to source» Transparent 6 Chapitre 1 Introduction à la Compilation Historique Schéma conceptuel Phases et passes Structures et langages intermédiaires Méta-compilation 7 Conception: modèle Analyse et Synthèse Traduire un programme source dans un langage cible analyse le programme conformément à la définition du langage source produit d’éventuels messages d’erreurs synthétise un code équivalent au programme source dans le langage cible Schéma fonctionnel Source Compilateur Partie Avant Cible Partie Arrière Messages d’erreurs Transparent 8 Phases & Passes Une phase est une étape conceptuelle du processus de compilation Une passe regroupe des traitements nécessitant un parcours complet du source (ou de la représentation associée) Source A. lexicale A. syntaxique S y m b o l e s A. sémantique G. code intermédiaire Optimiseur de code E r r e u r s G. de code Cible Transparent 9 Phase lexicale : fonctionnalités Traiter le texte source à l’entrée découpe le texte en unités lexicales conformément à la définition lexicale du langage compilé élimine (éventuellement) certaines unités inutiles Schéma fonctionnel Erreurs. Lexèmes Source Anal. Lex Arbres Anal. Synt. requête Table Symbôles. Identificateurs Source instrumenté. Transparent 10 Phase lexicale : pourquoi la séparer de la phase syntaxique ? Avantages: Conception modulaire de l’architecture logicielle Indépendance phases/passes Performances des analyseurs en temps en mémoire Evolutivité du compilateur vis à vis du langage source Autres applications hors compilation: Traitement de texte et des documents Codage des données sécurité compression Recherche de motifs KMP Programmation spécialisée Transparent 11 Phase syntaxique Fonctions Déterminer l’appartenance à un langage Produire un arbre (de dérivation) et d’éventuels messages d’erreurs Analyse descendante récursive multipasse de gauche à droite construction de l’arbre avec ou sans backtracking complexité : O(|règles||source|) Analyse (déterministe) descendante une seule passe de gauche à droite construction de l’arbre en descendant à partir de la racine meilleure complexité : O(|source|) Analyse (déterministe) ascendante une seule passe de gauche à droite construction de l’arbre en montant à partir des feuilles meilleure complexité : O(|source|) Transparent 12 Phase sémantique statique Actions sémantiques synchronisées par A.S. compilation en une seule passe Attributs synthétisés seulement Actions sémantiques dirigées par la syntaxe compilation multipasse Attributs synthétisés et hérités Sémantique statique portée, visibilité, typage décompilation transformations au niveau du source Transparent 13 Compilation et Théories Référence de langages Définition formelle non ambiguë Systèmes générateurs Expressions régulières Grammaires Reconnaissance des programmes Déterminisme Performance (complexité) Classes de langages Automates finis Automates à pile Langages hors contexte Sémantique Spécifications exécutables & Générateurs Optimisation Langages à contexte Graphes Systèmes logiques Transparent 14 Métacompilation « compiler-compiler » Grammaire lexicale de L Lexical Grammaire syntaxique de L Parser Définitions & actions sémantiques L -> Trans lator G E N E R A T O R C O M P I L A T E U R L -> Transparent 15 Archicture des compilateurs: Evolution et autres applications Documents XML, DOM, XSLT Communication par une API intermédiaire Source Compilateur Edition Cible Décompilation Partie Avant Cible Transformations Compilateur Cible Partie Arrière Cible Transparent 16 Chapitre 2 Analyse lexicale 2.1 les bases théoriques de l’implémentation 2.2 lex: un méta_générateur lexical 2.3 lex: des exemples de base 17 Analyse lexicale : le découpage d’un source Java class Pile { // lexicalement correct public int hauteur () { if vide() return 0; return 1+ this.depile().hauteur() } } #11: Pile <class> < id,11> <{> <public> <int> < id,13> <(> <)> <{> < if> < id,1> <(> <)> <return> <ce,0> <:> <return> <ce,1> <op,+> <this> <.> < id,2> <(> <)> <.> < id,13> <(> <)> <}> <}> Transparent 19 Section 2.1 les bases théoriques de l’implémentation Expressions régulières Grammaires régulières Langages rationnels Automates finis Déterminisme 20 Analyse lexicale : les outils de l ’implémentation Les outils théoriques: Langages réguliers: Expressions régulières lexèmes (« tokens ») Grammaires régulières symboles terminaux Automates finis: déterministes non déterministes transducteurs Les outils logiciels Les générateurs lexicaux : lex, flex, javalex, … grep, egrep, fgrep, ... sed, awk, ... Langages de programmation Grafcet, Esterel Perl, Python, Java, JavaScript, Php. Langages de Documents XPath, XSL, DTD, XSD Transparent 21 Langages Rationnels (Réguliers) Grammaires régulières (linéaires) Expressions étendues(lex) Expressions régulières Automates finis indéterministes Automates finis déterministes Transparent 22 Implémentation des Générateurs d'Analyse Lexicale Source format général /*exp ek exemple actions */ a abb a*b+ ak; ; ; ; AFND 0 a 1 2 a 3 b 4 5 b 6 b 7 8 b AFD 0137 a b 247 58 b 68 a b 7 b b 8 b Transparent 23 Section 2.2 lex: un méta-générateur lexical 24 lex : un générateur lexical lex est un méta-compilateur pour grammaires lexicales Table Transitions AF(N)D [ section de définitions ] %% [ section des règles: ExpReg Actions ] [ %% code de l ’utilisateur ] Analyseur (N)D Sorties analyseur lexical en C: lex.yy.c une fonction de découpage: yylex() Utilisation sous unix source.lex lex lex.yy.c cc a.out Transparent 25 Définition des Expressions régulières Alphabets: codes ISO, ASCII, etc Expressions régulières forme de Kleene via des méta-opérateurs (concaténation, le est omis ) | (alternative) (répétition) () exemple: les identificateurs C Id = (a|b|..|z|A|..|Z|_) (a|b|..|z|A|..|Z|_|0|..|9) Expressions régulières étendues méta-opérateurs [] - + ? "" \ ^ exemples les entiers: [0-9]+ les identificateurs C: [a-zA-Z_] [a-zA-Z0-9_] les chaînes de caractères sans " : \" [^"] \" les commentaires lignes Java: "/ /" Transparent 26 Les caractères de lex Les caractères terminaux tous les caractères, sauf les spéciaux l ’espace est significatif les spéciaux doivent être protégés par " " ou \ Les caractères spéciaux (méta-) e? e* e+ ef e|f e{n,m} (e) {D} e/f ^e e$ <E>e . \c "abc" [abc] [^abc] [a-c] Forme de Kleene 0 ou 1 fois l’exp e 0 ou n fois l’exp e 1 ou n fois l’exp e l'exp e f l'exp e ou l'exp f l'exp e répétée entre n et m fois l'exp e l'exp obtenue par substitution de D Contexte sensitivité l'exp e si suivie de l'exp f exp e en début de ligne exp e en fin de ligne L'exp e si dans l'état E Caractères tout caractère sauf \n le caractère c , même spécial la chaine de caractères abc le caractère a ou b ou c un des caractères sauf a, b, c le caractère a ou b ou c Transparent 27 Méta-langage et syntaxe de Lex /* Section Définitions (optionnelle)*/ Définitions lex /* optionnelles */ /* à substituer dans les règles Lex */ %{ /* obligatoirement en début de ligne */ Définitions en langage C ou C++ /* seront insérées telles quelles dans le code généré par Lex*/ %} /* obligatoirement en début de ligne */ Définitions lex /* optionnelles */ /* à substituer dans les règles Lex */ /* Section Règles ci-dessous: attention: commentaires ligne possibles seulement après les actions */ %% expressions lex {instructions C} /* … */ %% /* Section Code utilisateur (optionnelle)*/ Code C de l ’utilisateur & main() /*à insérer dans le code généré par lex*/ /* retour chariot obligatoire à la fin du flot d'entrée*/ Transparent 28 Exécution (simplifiée) d'un analyseur Lex public Flot scan() { // this est un flot d'entrée Flot FSortie: new Flot(); CC=CD= debut(); while( !EOF() && ulex(CD,CC).rec() ) {CC++;} if ( !EOF() || ulex(CD,CC-1).rec() ) if (CD==CC) { FSortie.app(CC); CD=++CC;} else {exec(ulex(CD,CC-1).regle()); CD=CC;} return FSortie; } Lexème le + long possible CCCCCCCCCCCCCCCCCCCCC CD CC E1 -> A1 Transparent 29 Format (non convivial!) de Lex Espaces ou tabulations ni en début de ligne, ni dans les expressions obligatoire entre expressions et actions commentaires dans les blocs {} seulement en fin de ligne dans les Règles Substitution des { } attention aux priorités après substitution Passage à la ligne impossible sauf | pour "factoriser" des règles Erreurs classiques exp; [public|private] ["class"] [^"class"] ALPHA ID ({L}|{C} ) {L} ( {ALPHA} ) * Transparent 30 Lex: variables, fonctions et macros Analyseur lexical yylex() – la fonction d’analyse yywrap() – après l'analyse du texte en entrée Le « token » en cours char *yytext int yyleng Etats ou contexte gauche %START %s %x BEGIN Transparent 31 Lex: modifier le fonctionnement Modifier le découpage yymore() – concatène les tokens successifs yyless(int n) – retour arrière de yyleng - n REJECT – ressaye les autres reconnaissances possibles par les autres règles Entrées/Sorties de caratères input() – lit le prochain caractère output(char c) – écrit c unput(char c) – met c dans le flot d’entrée ECHO – écrit le token courant Transparent 32 Lex & flex: compléments (1) Sur les Etats INITIAL ou 0 <*> – tous les états, y compris 0 <A,B,C> – «start conditions» multiples <A> { Exp1 R1 ; Expn Rn ; } – règles multiples YY_START – l’état courant YYSTATE Avec une (la) pile des états %option stack – accès à la pile des états yy_push_state(s), _pop_ => BEGIN yy_top_state() # de YY_START <<EOF>> <<EOF>> – règle spéciale sur fin de fichier yyterminate() – fin d’analyse yyin=fopen(*fliste, «r») – chang. de fichier Transparent 33 Exécution d'un analyseur Lex Lexème le + long possible CCCCCCCCCCCCCCCCCCCCC CD REJECT yyless() yymore() yyterminate() CC E1 -> A1 état valide BEGIN yy_pop_ yy_top_ yy_push_ YY_USER_ "désarmées" état invalide Transparent 34 Lex & flex: compléments (2) échappements caractères \176 \x7E // le caractère ~ en Octal // le caractère ~ en Hexa options de "pattern matching" i et -i – sensibilité à la casse x et -x – ignore les blancs et commentaires s et -s – . avec ou sans \n classes caractères [:digit:] – comme 0-9 [:alnum:] – comme 0-9a-zA-Z [[:digit:][:alpha:]] – comme [0-9a-zA-Z] [[:^digit:]] – comme [^0-9] Transparent 35 Lex & flex: compléments (3) La ligne courante %option yylineno – gestion de la ligne courante Sur les règles de l’analyseur yy_act – le numéro de la règle activée YY_NUM_RULES – le nombre total de règles Routines Utilisateur YY_USER_INIT – à faire avant l’analyse YY_USER_ACTION -- à faire à chaque règle Fichiers *yyin – FILE en entrée *yyout – FILE en sortie yyrestart (FILE *new_file) – FILE Transparent 36 Section 2.3 Lex: des exemples de base Identificateurs, mots clés, commentaires, chaînes de caractères, des L.P. 38 lex : les identificateurs Ada Expression étendue: [a-zA-Z](_?[a-zA-Z0-9])* Source lex /* définitions lex*/ LET [a-zA-Z] CHIF [0-9] ALPNUM ({LET}|{CHIF}) %% /* règle sans action*/ {LET}(_?{ALPNUM})* ; %% Transparent 39 lex : les identificateurs Java Expression étendue: [a-zA-Z_$ ] [a-zA-Z0-9_$] * Source lex /* définitions */ LET [a-zA-Z_$] CHIF [0-9] ALPNUM ({LET}|{CHIF}) %% /* règle sans action*/ {LET}({ALPNUM}) * ; %% Transparent 40 lex : les chaînes de caractères en Ada Expression ambigüe: ". " => accepte tous les caractères sur une ligne, y compris donc plusieurs " avant le " le plus à droite => ambiguïté: " chaine1 " ++ " chaine2 " ++ " chaine3 " Expression correcte %% /* règle sans action*/ \" ( [^ " \n ] | \" \" ) \" ; %% Transparent 41 lex : les chaînes de caractères en C et Java Expression ambigüe: ". " => accepte tous les caractères sur une ligne, y compris donc plusieurs " avant le " le plus à droite => ambiguïté: " chaine1 " ++ " chaine2 " ++ " chaine3 " Expression correcte %% /* règle sans action*/ %% Transparent 42 lex : mots clés, entiers, identificateurs C Source lex CHIF [0-9] ENTSIG ("-"|"+")?{CHIF} + IDENT [a-zA-Z_][a-zA-Z_0-9] MC1 auto | extern | static | typedef | register MC2 short | int | long | char | float | double MC3 if | else | do | while | for | case | switch MC4 default | return | break | continue | goto MC {MC1} | {MC2} | {MC3} | {MC4} %% {ENTSIG} {printf("%d\n", atoi(yytext)) ;} {IDENT} {printf("%s\n", yytext) ;} {MC} {printf( "mclé: %s\n", yytext) ;} [ \t\n]+ ; /* caractères ignorés */ . {fprintf(stderr, "car. invalide: %s\n", yytext) ;} %% Transparent 44 lex : les commentaires en C forme /* */ Expression ambiguë: " / " . "/ " => accepte tous les caractères dans le commentaire, y compris donc plusieurs / avant le / le plus à droite => ambiguïté: /com1/ ++ /com2/ ++ /com3/ Expression Régulière Lex Source lex (avec un état exclusif) %x COM %% ? ? Transparent 45 lex : les commentaires en C forme /* */ Expression ambiguë: " / " . "/ " => accepte tous les caractères dans le commentaire, y compris donc plusieurs / avant le / le plus à droite => ambiguïté: /com1/ ++ /com2/ ++ /com3/ Expression correcte Source lex(avec un état inclusif) %s COM %% ? ? ? Transparent 47 Unités lexicales imbriquées en lex Reconnaissance imbriquées ou non ? Mots réservés et identificateurs Mots réservés dans/hors les commentaires Mots réservés dans/hors les chaînes Chaînes dans/hors les commentaires etc. Reconnus ou pas ? MC if | else | do | while | for | case | switch %s COM /* ou %x ? */ %% {MC} {printf( "mclé: %s\n", yytext) ;} ? %% Transparent 49 lex : supprimer les espaces sauf dans les chaînes (1) Avec un état exclusif %x CHA %% ? ? Attention: les règles 2, 3 et 4 ne sont activables que dans l'état <CHA> dans l'état <CHA>, le lexeme \" est reconnu par la règle 4 et non pas 1 les règles 1, 5 et 6 ne sont pas activées dans l'état <CHA> hors de l'état <CHA>, " " est reconnu par la règle 5 et non pas 6 Transparent 51 lex : supprimer les espaces sauf dans les chaînes (2) Avec un état inclusif %s CHA %% ? Attention: la règle 1 n'est activable que dans l'état <0> les règles 2, 3 et 4 ne sont activables que dans l'état <CHA> dans l'état <CHA>, le lexeme \" est reconnu par la règle 4 et non pas 1 les règles 5 et 6 sont activables dans tous les états un lexeme " " est reconnu par la règle 2 dans l'état <CHA> et par la régle 5 sinon Transparent 53 lex : compter les éléments d’un texte Source lex %{ static int nbCar = 0, nbMot = 0, nbLig = 0; %} MOT EOL %% {MOT} {EOL} . [^ \t\n]+ \n {nbMot++; nbCar +=yyleng;} {nbLig++; nbCar ++;} nbCar ++; %% main() { yylex(); printf(« %d %d %d\n », nbLig, nbMot, nbCar); } Transparent 55 Section 2.4 Traitement lexical des Textes par Expressions régulières awk, grep, find, emacs, etc. Java Python Perl JavaScript 56 Expressions grep -E -P e? e* e+ ef e|f e{n} e{n,m} e{n,} (e) ^e e$ \<e e\> . \c "abc" [abc] [^abc] [a-c] \i 0 ou 1 fois l’exp e 0 ou n fois l’exp e 1 ou n fois l’exp e l'exp e f l'exp e ou l'exp f l'exp e répétée n fois l'exp e répétée entre n et m fois l'exp e répétée n fois ou plus l'exp e ou le groupe e exp e en début de ligne, exp e en fin de ligne. exp e en début de mot exp e en fin de mot tout caractère sauf \n le caractère c , même spécial la chaine abc le caractère a ou b ou c un des caractères sauf a, b, c le caractère a ou b ou c répéter le ième groupe( ) reconnu Transparent 57 Java Le Paquetage Java.util.regex Expressions régulières String expreg java.util.regex.Pattern Pattern p = Pattern.compile(expreg) java.util.regex.Matcher Matcher m = p.matcher( ) m.find() m.group() Transparent 58 Python Le Module re expreg = re.compile(' … ') m = expreg .match(… ) if m m.group( …) Transparent 59 Expressions Perl (1) e? e* e+ ef e|f e{n} e{n,m} e{n,} (e) ^e e$ \Ae e\Z . \c "abc" [abc] [^abc] \d \D \w \W [a-c] \i $i 0 ou 1 fois l’exp e 0 ou n fois l’exp e 1 ou n fois l’exp e l'exp e f l'exp e ou l'exp f l'exp e répétée n fois l'exp e répétée entre n et m fois l'exp e répétée n fois ou plus l'exp e ou le groupe e exp e en début de ligne, exp e en fin de ligne. exp e en début de mot exp e en fin de mot tout caractère sauf \n le caractère c , même spécial la chaine de caractères abc le caractère a ou b ou c un des caractères sauf a, b, c caractère chiffre ou non caractère alphanum ou non le caractère a ou b ou c le ième groupe( ) reconnu Transparent 60 Expressions Perl (2) Les Opérateurs sur Exp. Reg. pattern matching (m) /[0-9]/ m$[0-9]$ substitution(s) s+new+old+ s/0/1/ character translation (tr ou y) tr/A-Z/a-z/ pattern binding (~) $nom =~/Paul/ $nom !~/Paul/ $liste =~ s/Paul/Pierre/g $liste =~ tr/A-Z/a-z/ Transparent 61 JavaScript 1.5 et + (ECMAScript) Les expressions (Ecmascript v3, Perl 5 ) la classe RegExp var motif=/finADroite$/i; var motif=new RegExp("finADroite$", i); méthodes match() substr() replace() split() Modes i g (ignorer la casse) (global, donc toutes les occurrences) Répétition non avide (not "greedy") ?? +? *? Groupe seulement (non numéroté) (? : Transparent 62 Un modèle d'architecture partie avant partie arrière 63