Analyse lexicale Généralités Expressions rationnelles Automates finis

Slides:



Advertisements
Présentations similaires
Premier programme en C :
Advertisements

Initiation à la programmation et algorithmique cours 4
Portée des variables VBA & Excel
Introduction à l’Algorithmique
Calculs de complexité d'algorithmes
Groupe IHM Isabelle BONDOUX Cédric CASTAGNE Samy FOUILLEUX
Cours n°2M2. IST-IE (S. Sidhom) UE 303 Promo. M2 IST-IE 2005/06 Conception dun système d'information multimédia Architecture trois-tiers : PHP/MySQL &
C.
Chap 1 Grammaires et dérivations.
Introduction : Compilation et Traduction
Automate asynchrone.
ESIEE Paris © Denis BUREAU I N Initiation à la programmation avec le langage Java.
IFT313 Introduction aux langages formels
Introduction à l'informatique linguistique
Principes de programmation (suite)
IFT313 Introduction aux langages formels
Points importants de la semaine Les commentaires. Les variables. Les instructions conditionnelles. Les instructions itératives (les boucles).
Conception et analyse des algorithmes
CPI/BTS 2 Programmation Web Introduction au PHP
OCaml - Les listes L3 MI.
Introduction : Compilation et Traduction
Partie 1 Etude de l'existant
Récursivité.
44 Contrôle du déroulement du programme. 4-2 Objectifs A la fin de ce cours, vous serez capables de : Utiliser les constructions de prise de décision.
Les éléments de base de l’algorithmique
II. Chaînage, SDD séquentielles
Les algorithmes: complexité et notation asymptotique
IFT451 Introduction aux langages formels Froduald Kabanza Département dinformatique Université de Sherbrooke planiart.usherbrooke.ca/kabanza/cours/ift313.
Algorithmique et Programmation
Etude de cas : buffer clavier
Expressions régulières et hash tables
Semaine #1 INF130 par Frédérick Henri.
Semaine #1 INF135 par Frédérick Henri.
Principes de programmation
Contrôle de types Les types en programmation Expressions de types Un contrôleur de types Equivalence de types Conversions de types Généricité.

IFT 6800 Atelier en Technologies d’information
LIFI-Java 2004 Séance du Jeudi 9 sept. Cours 1. La notion de langage Décrire une tâche à effectuer –programme Écrire à un haut niveau –facile pour lutilisateur.
Chapitre 9 Les sous-programmes.
Chapitre 3 Syntaxe et sémantique.
Analyse lexicale et syntaxique
Partie II Sémantique.
COURS DE PROGRAMMATION ORIENTEE OBJET :
Analyse lexicale Pr ZEGOUR DJAMEL EDDINE
Programmation logique Le Langage PROLOG
NORMALISATION DES LANGAGES DE PROGRAMMATION des Automates Programmables Industriels CEI Jean-Jacques DUMÉRY -1-
Rappel Modèle analyse-synthèse de la compilation
NORMALISATION DES LANGAGES DE PROGRAMMATION des Automates Programmables Industriels CEI
Types de données fondamentaux
Le langage C Structures de données
Expressions régulières et hash tables
1 Notations Asymptotiques Et Complexité Notations asymptotiques : 0 et  Complexité des algorithmes Exemples de calcul de complexité.
Paradigmes des Langages de Programmation
Algorithmique Les structures Rappel L'enchaînement séquentiel
LES PILES ET FILES.
Chapitre II Analyse Lexical.
Les adresses des fonctions
Les machines de Turing Lionel Blavy Sébastien Giraud Fabien Tricoire
Créer des packages.
Un survol du language C.
 Syntaxe du langage PHP
D.E ZEGOUR Ecole Supérieure d’Informatique. Problèmes de décision Concepts de base Expressions régulières Notation particulière pour exprimer certaines.
Le langage Z minimal Pr ZEGOUR DJAMEL EDDINE
Le langage Racket (Lisp)
Sémantique des instructions pour le langage Z minimal Pr ZEGOUR DJAMEL EDDINE Ecole Supérieure d’Informatique (ESI)
1 École des Mines de Saint-Etienne. 158, cours Fauriel Saint-Etienne Cedex 2. Tél Fax Jean-Jacques Girardot
ISBN Chapitre 10 L'implémentation des sous- programmes.
Chap 1 Grammaires et dérivations.
Philippe Gandy - 8 septembre 2015 Basé sur les notes de cours de Daniel Morin et Roch Leclerc.
Transcription de la présentation:

Analyse lexicale Généralités Expressions rationnelles Automates finis Analyseurs lexicaux

Rôle d'un analyseur lexical lexèmes analyseur lexical analyseur syntaxique code source ... table des symboles Séparer l'analyse lexicale de l'analyse syntaxique Réduire la complexité du compilateur et la complexité de conception de ces deux modules Augmenter la flexibilité du compilateur : portabilité, maintenabilité Augmenter l'efficacité du compilateur

Méthodes de construction Utiliser un générateur d'analyseurs lexicaux (Flex) Ecrire l'analyseur lexical dans un langage évolué

Lecture du code source (1/2) On utilise un tampon de lecture cyclique en deux moitiés Anticiper = lire quelques caractères d'avance pour décider la valeur du lexème en cours ... a = 4 * i + 1 fin debut Une anticipation de quelques caractères suffit Un langage où il n'y avait pas de limite à la taille de l'anticipation : PL/1 DECLARE ( ARG1, ARG2, ... , ARGn ) Il faut attendre la fin de l'expression pour savoir si DECLARE est un mot-clé ou un nom de tableau

Lecture du code source (2/2) ... a = 4 * i + 1 fin debut si fin atteint la fin de la première moitié alors { charger la deuxième moitié fin := fin + 1 } sinon si fin atteint la fin de la deuxième moitié alors { charger la première moitié fin := 0 } sinon fin := fin + 1

Mots et langages formels Un mot sur un alphabet A est une suite finie de symboles pris dans A A peut être l'ensemble des caractères, dans ce cas les lexèmes sont des mots alphabet mots code ASCII { 0, 1 } caractères analyse lexicale lexèmes analyse syntaxique programmes Le mot vide est noté ε, sa longueur est 0 Un langage formel est un ensemble de mots

Expressions rationnelles On forme des expressions à partir des symboles (éléments de l'alphabet) et de ε en utilisant - l'union notée | (ou +) - la concaténation (pas de symbole) - l'itération notée * On utilise souvent des opérations supplémentaires (abréviations) : + pour l'itération au moins une fois ? pour l'option . pour tout l'alphabet [...] pour une union de symboles Priorités entre opérateurs : itération, concaténation, union

Expressions rationnelles Identificateurs en C lettre = A | B | ... | Z | a | b | ... | z chiffre = 0 | 1 | ... | 9 id = (lettre | _) (lettre | _ | chiffre)* Nombres sans signe en C chiffres = chiffre chiffre* frac = . chiffres exp = (E | e) (+ | - | ε) chiffres | ε num = (chiffres (frac | . | ε) | frac) exp Les mêmes avec les abréviations chiffre = 0 | 1 | ... | 9 chiffres = chiffre+ frac = . chiffres exp = ((E | e) (+ | -) ? chiffres)? num = (chiffres (frac | .)? | frac) exp

Lexèmes Définition des espaces blancs delim = \b | \t | \n ws = delim* On dit habituellement lexème pour "catégorie de lexèmes" : expression lexème attribut ws - if else id pointeur num valeur etc. expression lexème attribut < relop lt <= le == eq != ne > gt >= ge

Automates finis Les analyseurs lexicaux utilisent des graphes appelés automates finis - les sommets sont appelés états - les transitions sont orientées et étiquetées - certains états sont finaux et comportent une action lettre | _ | chiffre 11 12 autre 13 return(gettoken(), install) lettre _ Identificateurs en C

Automates finis 1 2 3 4 5 6 7 8 9 10 Opérateurs de comparaison autre 1 autre 2 return(relop, lt) < = 3 return(relop, le) > autre 4 5 return(relop, gt) = 6 = return(relop, ge) = 7 8 return(relop, eq) ! 9 = 10 return(relop, ne) Opérateurs de comparaison

Automates finis chiffre chiffre 14 15 E | e chiffre + | - chiffre autre 16 17 18 19 chiffre . . chiffre E | e 20 21 chiffre chiffre 22 23 autre chiffre 24 chiffre . . autre 25 26 chiffre Nombres sans signe en C

Implémentation en C Un programme C qui reconnaît dans le début d'une chaîne de caractères un des lexèmes définis par les automates /* Recherche de l'état initial du prochain automate */ int state = 0, start = 0 ; int lexical_value ; int fail() { forward = token_debut ; switch(start) { case 0 : start = 11 ; break ; case 11 : start = 14 ; break ; case 14 : start = 22 ; break ; case 22 : recover() ; break ; default : /* erreur */ } return start ; }

token nexttoken() { while (1) { switch(state) { case 0 : c = nextchar() ; if (c==blank||c==tab||c==newline) { state = 0 ; debut ++ ; } else if (c == '<') state = 1 ; else if (c == '>') state = 4 ; else if (c == '=') state = 7 ; else if (c == '!') state = 9 ; else state = fail() ; break ; /* ... cas 1 - 10 ... */ case 11 : c = nextchar() ; if (isletter(c)||c=='_') state = 12 ;

case 12 : c = nextchar() ; if (isletter(c)||c=='_') state = 12 ; else if (isdigit(c)) state = 12 ; else state = 13 ; break ; case 13 : retract(1) ; install_id() ; return(gettoken()) ; /* ... cas 14-26 ... */ }

Automates déterministes Un automate fini est déterministe si : - il possède au plus un état initial - de chaque état part au plus une flèche étiquetée par un symbole donné Exemple d'automate non déterministe : a a | b 1 2 a Exemple d'automate déterministe : a b a 1 2 b

Automates déterministes Un automate déterministe représentant un ensemble de mots peut être utilisé commodément pour reconnaître l'un des mots dans une chaîne de caractères : il suffit de partir de l'état initial, de suivre les flèches et de voir si l'état dans lequel on arrive est final. Tout automate fini est équivalent à un automate fini déterministe : il existe un automate fini déterministe qui reconnaît le même langage.

Déterminisation Algorithme : on part d'un automate fini A = (Q, I, F, ). On construit l'automate déterministe D ayant 1. comme états les parties de Q 2. comme état initial I 3. comme états finaux les parties de Q contenant au moins un élément de F 4. comme transitions les (U, a, V) si V est l'ensemble des états atteignables depuis U par une transition étiquetée a Complexité : si A a n états, D a au plus 2n états.

Exemple 1 2 3 Un automate non déterministe 1 1 2 1 3 a | b 1 a 2 b 3 Un automate non déterministe b a 1 a 1 2 b 1 3 a b Le résultat de l'algorithme

Généralisation On peut admettre des transitions d'étiquette  (transitions spontanées). Pour être déterministe, un automate ne doit pas contenir de transitions spontanées. Pour déterminiser, on adapte l'algorithme précédent : - à l'étape 2 on prend l'ensemble des états atteignables depuis I par un chemin de transitions spontanées ; - à l'étape 3, V est l'ensemble des états atteignables depuis U par un chemin étiqueté a

La construction récursive On peut construire un automate fini équivalent à une expression rationnelle : il reconnaît le même langage. L'automate construit est tel que : - il a un seul état initial i - il a un seul état final f  i - aucune transition n'entre dans i - aucune transition ne sort de f. Pour  et a, on prend:   a

union     concaténation   itération    

Utilisation de Flex 4 étapes : spécification Flex flex lex.yy.c compilateur C caractères (code source) a.out lexèmes ... 4 étapes : - créer sous éditeur une spécification Flex (expressions rationnelles) - traiter cette spécification par la commande flex - compiler le programme source C obtenu - exécuter le programme exécutable obtenu

Spécifications Flex Un programme Flex est fait de trois parties : déclarations %% règles de traduction fonctions auxiliaires en C Les règles de traduction sont de la forme p1 { action1 } p2 { action2 } ... pn { actionn } où chaque pi est une expression rationnelle et chaque action une suite d'instructions en C.

Exemple %{ /* Partie en langage C : définitions de constantes, déclarations de variables globales, commentaires... */ %} delim [ \t\n] letter [a-zA-Z] %% {delim}* { /* pas d'action */ } if { return IF ; } then { return THEN ; } else { return ELSE ; } {letter}({letter}|[0-9])* { yyval = install_id() ; return ID ; } ([0-9]+(\.[0-9]*)?|\.[0-9]+)((E|e)(\+|-)?[0-9]+)? { yyval = install_num() ; return NUMBER ; }

Exemple "<" { yyval = LT ; return RELOP ; } "<=" { yyval = LE ; return RELOP ; } %% install_id() { /* fonction installant dans la table des symboles le lexème vers lequel pointe yytext et dont la longueur est yylength. Renvoie un pointeur sur l'entrée dans la table */ } install_num() { /* fonction calculant la valeur du lexème */

Spécifications Flex Les commentaires /* ... */ ne peuvent être insérés que dans une portion en C : - dans la partie déclaration, seulement entre %{ et %} ; - dans la partie règles, seulement dans les actions ; - dans la partie fonctions auxiliaires, n'importe où. Dans les règles pi { actioni } les expressions rationnelles pi ne peuvent pas contenir d'espaces blancs (ou alors dé-spécialisés). Dans la partie règles, si une règle commence par un espace blanc, elle est interprétée comme du langage C et est insérée dans lex.yy.c au début de la fonction qui renvoie le prochain lexème (utilisable pour déclarer des variables locales).

Segmentation du code source par l'analyseur lexical (1/3) L'analyseur lexical produit par Flex - commence à chercher les lexèmes au début du code source ; - après chaque lexème reconnu, recommence à chercher les lexèmes juste après Exemple : si piraté est reconnu, raté n'est pas reconnu Si aucun lexème n'est reconnu à partir d'un point du code source l'analyseur affiche le premier caractère sur la sortie standard et recommence à chercher à partir du caractère suivant

Segmentation du code source par l'analyseur lexical (2/3) Si plusieurs lexèmes sont reconnus à partir d'un point du code source (conflit) 1. Deux lexèmes de longueurs différentes C'est le plus long qui gagne Exemple : [a-zA-Z_] [a-zA-Z_0-9]*

Segmentation du code source par l'analyseur lexical (3/3) 2. Deux lexèmes de même longueur Ils commencent au même point et terminent au même point : s'il y a conflit, c'est qu'ils sont issus de deux règles différentes. C'est la règle qui apparaît la première dans la spécification Flex qui gagne Exemple : conflit entre [a-zA-Z_] [a-zA-Z_0-9]* et while Mettre l'exception avant la règle En dehors de ce cas, l'ordre des règles ne joue pas