Analyse lexicale et syntaxique

Slides:



Advertisements
Présentations similaires
Mais vous comprenez qu’il s’agit d’une « tromperie ».
Advertisements

ORTHOGRAM PM 3 ou 4 Ecrire: « a » ou « à » Référentiel page 6
LES NOMBRES PREMIERS ET COMPOSÉS
Ma surprise du Zoo.
[number 1-100].
Qualité du Premier Billot. 2 3 Défauts reliés à labattage.
Licence pro MPCQ : Cours
Distance inter-locuteur
Traitement sémantique et grammaire dattributs Pr ZEGOUR DJAMEL EDDINE Ecole Supérieure dInformatique (ESI)
Les numéros
Les identités remarquables
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 &
Introduction à la logique
LES TRIANGLES 1. Définitions 2. Constructions 3. Propriétés.
Ecriture simplifiée d'une somme de relatifs
Chap 1 Grammaires et dérivations.
Introduction : Compilation et Traduction
ESIEE Paris © Denis BUREAU I N Initiation à la programmation avec le langage Java.
User management pour les entreprises et les organisations Auteur / section: Gestion des accès.
IFT313 Introduction aux langages formels
ORTH 1 CE2 Je sais écrire sans erreur les pluriels des noms se terminant par s, x, z.
Mr: Lamloum Med LES NOMBRES PREMIERS ET COMPOSÉS Mr: Lamloum Med.
1 5 octobre 2011 / paw Présentation du 7 octobre 2011.
Introduction : Compilation et Traduction
1 Cours numéro 3 Graphes et informatique Définitions Exemple de modélisation Utilisation de ce document strictement réservée aux étudiants de l IFSIC.
Récursivité.
Analyse lexicale Généralités Expressions rationnelles Automates finis
Cours de physique générale I Ph 11
IFT451 Introduction aux langages formels Froduald Kabanza Département dinformatique Université de Sherbrooke planiart.usherbrooke.ca/kabanza/cours/ift313.
1 Guide de lenseignant-concepteur Vincent Riff 27 mai 2003.
GRAM 1 CE2 Je sais transformer une phrase affirmative en phrase négative.
IFT313 Introduction aux langages formels
Titre : Implémentation des éléments finis sous Matlab
Tableaux de distributions
Tableaux de distributions
Projet poker 1/56. Introduction Présentation de léquipe Cadre du projet Enjeux Choix du sujet 2.
F Copyright © Oracle Corporation, Tous droits réservés. Créer des programmes avec Procedure Builder.
LES NOMBRES PREMIERS ET COMPOSÉS
VOC 1 CE2 Je sais utiliser des mots de la vie quotidienne.
1 INETOP
IFT313 Introduction aux langages formels
IFT313 Introduction aux langages formels Froduald Kabanza Département dinformatique Université de Sherbrooke planiart.usherbrooke.ca/kabanza/cours/ift313.
IFT313 Introduction aux langages formels Froduald Kabanza Département dinformatique Université de Sherbrooke Automates à pile LR Notion de poignée.
RACINES CARREES Définition Développer avec la distributivité Produit 1
Représentation des systèmes dynamiques dans l’espace d’état
DUMP GAUCHE INTERFERENCES AVEC BOITIERS IFS D.G. – Le – 1/56.
1 CSI3525: Concepts des Languages de Programmation Notes # 3: Description Syntaxique des Languages.
La Distribution des Données
Traduction dirigée par la syntaxe
Applications des langages hors-contextes Les analyseurs syntactiques ascendants GNU Yacc et Bison.
Chapitre 3 Syntaxe et sémantique.
Expressions et affectations
Titre : Implémentation des éléments finis en Matlab
Partie II Sémantique.
Analyse lexicale Pr ZEGOUR DJAMEL EDDINE
1 INETOP
Résoudre une équation du 1er degré à une inconnue
Rappel Modèle analyse-synthèse de la compilation
Équipe 2626 Octobre 2011 Jean Lavoie ing. M.Sc.A.
MAGIE Réalisé par Mons. RITTER J-P Le 24 octobre 2004.
Mise en forme en Mathématiques
1 GPA435 Systèmes d’exploitation et programmation de système Copyright, 2000 © Tony Wong, Ph.D. Chapitre 8 Filtres UNIX.
Traitement de différentes préoccupations Le 28 octobre et 4 novembre 2010.
1/65 微距摄影 美丽的微距摄影 Encore une belle leçon de Macrophotographies venant du Soleil Levant Louis.
Paradigmes des Langages de Programmation
LES PILES ET FILES.
Exercice de vérification 1 p
Les Chiffres Prêts?
Abdelkader Heni FUNDP Syntaxe et sémantique Abdelkader Heni FUNDP
Chap 1 Grammaires et dérivations.
Transcription de la présentation:

Analyse lexicale et syntaxique Chapitre 4 Analyse lexicale et syntaxique

Chapitre 4: Sujets Introduction Analyse lexicale Analyse syntaxique Méthode descendante Méthode ascendante Copyright © 2007 Addison-Wesley. All rights reserved.

Introduction 3 principales méthodes pour implémenter un langage de programmation: compilation interprétation méthode hybride Dans tous les cas, il est nécessaire de se référer au code source pour détecter les erreurs de syntaxe. Pratiquement toutes les méthodes d'analyse de la syntaxe reposent sur une description formelle de la syntaxe du langage (grammaire hors-contexte) Copyright © 2007 Addison-Wesley. All rights reserved.

Analyse syntaxique Deux parties: Au niveau inférieur il y a l'analyseur lexical (automates finis) Au niveau supérieur il y a l'analyseur syntaxique ou parseur (automates à pile) Copyright © 2007 Addison-Wesley. All rights reserved.

Décrire la syntaxe à l'aide de grammaires Procure une description claire et concise Le parseur peut être construit à partir de la grammaire La séparation des analyses lexicale et syntaxique facilite la maintenance car modulaire Copyright © 2007 Addison-Wesley. All rights reserved.

Avantages de la séparation Simplicité – méthodes moins complexes peuvent être utilisées pour l'analyse lexicale; simplifie le parseur Efficacité- séparation permet l'optimisation de l'analyseur lexical. Portabilité – l'analyseur lexical dépend souvent de la plateforme (lecture de fichiers) alors que l'analyseur syntaxique est toujours portable. Copyright © 2007 Addison-Wesley. All rights reserved.

Analyse lexicale Agit comme interface pour l'analyseur syntaxique Identifie les parties du programme source correspondant aux lexèmes Un lexème est un mot correspondant à une catégorie de mots (token) Par exemple, la variable somme est un lexème appartenant au token identificateur Copyright © 2007 Addison-Wesley. All rights reserved.

Analyse lexicale (suite) L'analyseur syntaxique appelle l'analyseur lexical lorsqu'il a besoin d'un autre token 3 approches pour construire un analyseur lexical: Écrire une description formelle des tokens (expressions régulière) et utiliser un outil logiciel (ex. lex) pour transformer ces descriptions en un analyseur lexical. Concevoir un diagramme d'état pour décrire les tokens et implémenter ce diagramme sous forme de programme. Concevoir un diagramme d'état pour décrire les tokens et implémenter ce diagramme à l'aide d'une table. Copyright © 2007 Addison-Wesley. All rights reserved.

Construire un analyseur lexical Par exemple, si on veut lire trois types de tokens: identificateurs: lettre suivie de lettres ou de chiffres. mots clefs: suite de lettres entiers littéraux: chiffre suivit de chiffres Approche naïve: Une transition pour chaque état et chaque caractère – trop gros! Copyright © 2007 Addison-Wesley. All rights reserved.

Construire un analyseur lexical (suite) Plusieurs transition peuvent être combinées pour simplifier le diagramme Une seule classe de caractères pour toutes les lettres majuscules et minuscule (LETTER) Une seule classe de caractères pour tous les chiffres (DIGIT) Copyright © 2007 Addison-Wesley. All rights reserved.

Construire un analyseur lexical (suite) Plutôt que d'avoir des états distincts pour les mots réservés, on traite ceux-ci de la même manière que les identificateurs On consulte une table pour déterminer si un lexème est un mot clef Copyright © 2007 Addison-Wesley. All rights reserved.

Diagramme d'état Copyright © 2007 Addison-Wesley. All rights reserved.

Construire un analyseur lexical (suite) Variables globales et utilitaires: char nextChar: contient le dernier caractère lu int charClass: LETTER (0), DIGIT (1), UNKNOWN (-1) char lexeme[100]: chaîne de caractère getChar() – lit le prochain caractère et le place dans nextChar. Met la classe du caractère dans charClass. addChar() – Ajoute nextChar à la fin de lexeme int lookup(char*) – détermine si lexeme est un mot clef Copyright © 2007 Addison-Wesley. All rights reserved.

Implémentation int lex() { getChar(); switch (charClass) { case LETTER: addChar(); while (charClass == LETTER || charClass == DIGIT) { } return lookup(lexeme); break; … Copyright © 2007 Addison-Wesley. All rights reserved.

Implémentation … case DIGIT: addChar(); getChar(); while (charClass == DIGIT) { } return INT_LIT; break; } /* End of switch */ } /* End of function lex */ Copyright © 2007 Addison-Wesley. All rights reserved.

L'analyseur syntaxique Objectifs: Trouver toutes les erreurs de syntaxe et envoyer un message approprié. Produire l'arbre syntaxique ou, du moins, l'information nécessaire pour le construire. Copyright © 2007 Addison-Wesley. All rights reserved.

L'analyseur syntaxique (suite) Deux catégories d'analyseurs syntaxiques: Descendant – produit l'arbre syntaxique en commençant par la racine Ascendant – commence par les feuilles Dans les deux cas on utilise une grammaire hors-contexte comme description du langage. Copyright © 2007 Addison-Wesley. All rights reserved.

L'analyseur syntaxique (suite) Complexité À partir de toute grammaire non ambiguë, il est possible de construire un analyseur syntaxique fonctionnant en temps O(n3), où n est la taille de l'entrée. On utilise plutôt un type restreint de grammaire permettant d'effectuer l'analyse syntaxique en temps O(n) Copyright © 2007 Addison-Wesley. All rights reserved.

L'analyseur syntaxique (suite) Parseurs descendants On commence avec le symbole de départ et on détermine la séquence de règles nécessaires pour dériver l'entrée (suite de token) <départ>    entrée Algorithme LL: Left-to-right scan (lecture de l'entrée de gauche à droite) Leftmost derivation (dérivation par la gauche) Copyright © 2007 Addison-Wesley. All rights reserved.

L'analyseur syntaxique (suite) Parseurs ascendants On commence avec l'entrée et on applique à rebours les règles de la grammaire afin d'obtenir la symbole de départ. entrée    <départ> Algorithme LR: Left-to-right scan Rightmost derivation Copyright © 2007 Addison-Wesley. All rights reserved.

Analyseur récursif-descendant (LL) Un sous-programme pour chaque non-terminal Les sous-programmes sont mutuellement récursifs Les grammaires hors-contextes étendues sont appropriées pour ce type d'analyseur syntaxique car elles minimisent le nombre de sous- programmes. On suppose l'existence d'un analyseur lexical lex, qui met le prochain token dans la variable globale nextToken Copyright © 2007 Addison-Wesley. All rights reserved.

Analyseur récursif-descendant (suite) Exemple: <expr>  <term> {(+ | -) <term>} <term>  <factor> {(* | /) <factor>} <factor>  id | ( <expr> ) Copyright © 2007 Addison-Wesley. All rights reserved.

Analyseur récursif-descendant (suite) // // Sous-programme pour le non-terminal expr void expr() {    term(); // Sous-programme pour le non-terminal term   while (nextToken == PLUS_CODE || nextToken == MINUS_CODE){     lex();     term();   } } Copyright © 2007 Addison-Wesley. All rights reserved.

Analyseur récursif-descendant (suite) // // Sous-programme pour le non-terminal term void term() {    factor(); // Sous-programme pour le non-terminal factor   while (nextToken == MULT_CODE || nextToken == DIV_CODE){     lex();     factor();   } } Copyright © 2007 Addison-Wesley. All rights reserved.

Analyseur récursif-descendant (suite) void factor() { if (nextToken) == ID_CODE) lex(); else if (nextToken == LEFT_PAREN_CODE) { expr(); if (nextToken == RIGHT_PAREN_CODE) else error(); } else error(); Copyright © 2007 Addison-Wesley. All rights reserved.

Analyseur récursif-descendant (suite) Grammaires LL Forme particulière Le problème de la récursion à gauche: A → Ab ou A → Bb B → Ac De telles grammaires ne peuvent pas être utilisée par un analyseur syntaxique descendant On peut cependant toujours remplacer une telle grammaire par une autre n'ayant pas ce problème  Copyright © 2007 Addison-Wesley. All rights reserved.

Analyseur récursif-descendant (suite) Autre problème: Deux règles: A→α et A→β tels que α génère aα' et β génère aβ' Comment choisir entre ces deux règles? La grammaire doit être modifiée mais cela n'est pas toujours possible Copyright © 2007 Addison-Wesley. All rights reserved.

Analyseurs ascendants Forme sententielle droite: On développe le non- terminal le plus à droite en premier Exemple: E → E + T | T T → T * F | F F → (E) | id E ⇒ E+T ⇒ E+T*F ⇒ E+T*id ⇒ E+F*id ⇒ E+id*id ⇒ F+id*id ⇒ id+id*id On veut partir de id+id*id et remonter vers E Copyright © 2007 Addison-Wesley. All rights reserved.

Analyseurs ascendants (suite) Handle: segment d'une forme sententielle (dérivée par la droite) correspondant à la partie à droite de la dernière règle utilisée Exemple: E ⇒ E+T ⇒ E+F ⇒ E+id ⇒ E+T+id E+T est le handle de E+T+id Remarque: Si la grammaire est non-ambiguë alors le handle est unique Problème: Comment trouver le handle? Copyright © 2007 Addison-Wesley. All rights reserved.

Analyseurs ascendants (suite) Les algorithmes Shift-Reduce: Utilisent une pile Déplacement (Shift): Action de placer le prochain token sur le dessus de la pile Reduction: Action de remplacer le handle sur le dessus de la pile par la partie de gauche (non- terminal) de la règle correspondante Copyright © 2007 Addison-Wesley. All rights reserved.

Analyseurs ascendants (suite) Parseurs LR Type particulier d'analyseurs ascendants conçus par D. Knuth en 1965 Ils fonctionnent pour pratiquement toutes les grammaires décrivant des langages de programmation Ils peuvent détecter les erreurs de syntaxe aussitôt que possible. Plus généraux que les parseurs LL Copyright © 2007 Addison-Wesley. All rights reserved.

Analyseurs ascendants (suite) Un parseur LR est un automate fini augmenté d'une pile Une configuration de la machine a la forme: (S0 X1 S1 X2 S2 … Xm Sm, aiai+1…an$) aiai+1…an : Partie de l'entrée qui reste à lire Si : États de la machine Xi : Symboles de la grammaire Copyright © 2007 Addison-Wesley. All rights reserved.

Structure d'un parseur LR Copyright © 2007 Addison-Wesley. All rights reserved.

Analyseurs ascendants (suite) Le comportement d'un parseur LR est indiqué par deux tables: la table ACTION (lignes=états, colonnes=terminaux) la table GOTO (lignes=états, colonnes=non-terminaux) La table ACTION indique si un déplacement ou une réduction doit avoir lieu étant donné l'état courant et le prochain token (terminal) La table GOTO indique quel état placer sur le dessus de la pile après qu'une réduction ait eu lieu. Copyright © 2007 Addison-Wesley. All rights reserved.

Analyseurs ascendants (suite) Configuration initiale: (S0, a1…an$) Configuration courante: (S0X1S1X2S2…XmSm, aiai+1…an$) Comportement du parseur: Si ACTION[Sm, ai] = Shift S, la prochaine configuration sera: (S0X1S1X2S2…XmSmaiS, ai+1…an$) Si ACTION[Sm, ai] = Reduce A   et que S = GOTO[Sm-r, A], où r = ||, alors la prochaine configuration sera: (S0X1S1X2S2…Xm-rSm-rAS, aiai+1…an$) Copyright © 2007 Addison-Wesley. All rights reserved.

Analyseurs ascendants (suite) Comportement du parseur (suite): Si ACTION[Sm, ai] = Accept, alors l'analyse est complété et aucune erreur n'a été trouvée. Si ACTION[Sm, ai] = Error, alors le parseur appelle un utilitaire de gestion des erreurs. Copyright © 2007 Addison-Wesley. All rights reserved.

Analyseurs ascendants (suite) Exemple: E → E + T E → T T → T * F T → F F → ( E ) F → id Les tables ACTION et GOTO sont habituellement construite à l'aide d'un programme telle que yacc ou bison Copyright © 2007 Addison-Wesley. All rights reserved.

Les tables ACTION et GOTO Copyright © 2007 Addison-Wesley. All rights reserved.

Analyseurs ascendants (suite) Pile Entrée Action id + id * id $ Shift 5 0 id 5 + id * id $ Reduce 6 (GOTO[0,F]) 0 F 3 Reduce 4 (GOTO[0,T]) 0 T 2 Reduce 2 (GOTO[0,E]) 0 E 1 Shift 6 0 E 1 + 6 id * id $ 0 E 1 + 6 id 5 * id $ Reduce 6 (GOTO[6,F]) 0 E 1 + 6 F 3 Reduce 4 (GOTO[6,T]) 0 E 1 + 6 T 9 Shift 7 0 E 1 + 6 T 9 * 7 id $ 0 E 1 + 6 T 9 * 7 id 5 $ Reduce 6 (GOTO[7,F]) 0 E 1 + 6 T 9 * 7 F 10 Reduce 3 (GOTO[6,T]) Reduce 1 (GOTO[0,E]) Accept E → E + T E → T T → T * F T → F F → ( E ) F → id Copyright © 2007 Addison-Wesley. All rights reserved.

Comprendre les tables: les items (1) T → 0T0 (2) T → 1 Items: S → _T$ T → _0T0 T → _1 S → T_$ T → 0_T0 T → 1_ S → T$_ T → 0T_0 T → 0T0_ Items complets: S → T$_ T → 1_

Signification des items S→_T$ Un item de la forme A→α_β indique que l'on est en train de traiter la règle A→αβ alors que α est sur les dessus de la pile Un item complet de la forme A→γ_ indique que γ est sur le dessus de la pile et qu'on peut le remplacer par A (réduction) T S→T_$ $ S→T$_ T→0_T0 T T→0T_0 T T→0T0_ T→0_T0 T T→0T_0 T→0T0_ T 1 T→1_

Signification des items (suite) S→_T$ Analyse du mot 00100$ Shifts (3 fois) Reduce Shift Reduce 1, T→1_ 0, T→0_T0 S, S→_T$ T, T→0T_0 0, T→0_T0 S, S→_T$ 0, T→0T0_ T, T→0T_0 0, T→0_T0 S, S→_T$ T, T→0T_0 0, T→0_T0 S, S→_T$ T S→T_$ $ S→T$_ T→0_T0 T T→0T_0 T T→0T0_ Shift Reduce Shift Reduce T→0_T0 T T→0T_0 T→0T0_ T 0, T→0T0_ T, T→0T_0 0, T→0_T0 S, S→_T$ T, S→T_$ S, S→_T$ $, S→T$_ T, S→T_$ S, S→_T$ S, accept S, S→_T$ 1 T→1_

Automate fini S→_T$ 2 T→0_T0 4 T→0T_0 5 T→0T0_ T T 1 1 Cet automate sert à décrire toutes les formes sententielles ne contenant pas de handle. Chaque état correspond à un item Seules les formes sententielles conduisant à un item complet possèdent un handle. 1 S→T_$ 3 T→1_ $ <accept> S→T$_ 0) S → T$ 1) T → 0T0 2) T → 1

Construction des tables à partir de l'automate ACTION GOTO 1 $ T S2 S3 accept 2 4 3 R2 S5 5 R1

Autre exemple Ajoutons 3 règles à la grammaire précédente: (0) S → T$ (1) T → 0T0 (2) T → 1 (3) T → 0V (4) V → 2V (5) V →2 Note: Ceci n'est pas une grammaire LL mais c'est une grammaire LR

Automate fini non-déterministe S→_T$ 2 T→0_T0 4 T→0T_0 5 T→0T0_ T T 1 1 1 S→T_$ 3 T→1_ 7 V→2_ 2 $ 2 9 V→2V_ 6 T→0_V 8 V→2_V <accept> S→T$_ V 2 10 T→0V_ V 2

Automate fini déterministe 4 T→0T_0 5 T→0T0_ S→_T$ 2 T→0_T0 T 1 On peut toujours transformer un automate fini non-déterministe en un automate fini déterministe équivalent. Chaque état correspond à un ensemble d'items. 1 1 S→T_$ 3 T→1_ T $ 2,6 T→0_T0 T→0_V <accept> S→T$_ 9 V→2V_ 7,8 V→2_ V→2_V V 10 T→0V_ 2 V 2

Les conflits Il existe deux types de conflits possibles lors de la construction des tables à partir de l'automate: Shift-Reduce Reduce-Reduce

Conflits Shift-Reduce Configuration initiale: (S0, 000$) Shift: (S0 0 S1, 00$) Shift ou Reduce ? Bison choisit toujours le Shift dans ce cas. Remarque: Le mot ne sera donc pas accepté alors qu'il devrait l'être.

Conflits Reduce-Reduce S → 0 S 0 S → T T → S 0 T → 1 Configuration initiale: (S0, 010$) Shift: (S0 0 S1, 10$) Shift: (S0 0 S1 1 S2, 0$) Reduce: (S0 0 S1 T S3, 0$) Reduce: (S0 0 S1 S S3, 0$) Shift: (S0 0 S1 S S3 0 S4, $) Réduce: on utilise la règle 1 ou 3 ? Yacc choisit toujours la première des règles dans ce cas. Remarque: La grammaire n'est pas ambiguë.

Résumé L'analyse syntaxique est une partie essentielle de L'implémentation d'un langage Un analyseur lexical traduit une séquence de caractère (le programme source) en une séquence de tokens (et de lexèmes) Un parseur récursif-descendant est un parseur LL implémenté en écrivant le code directement à partir de la grammaire du langage Un parseur LR est l'approche la plus commune pour implémenter les analyseurs syntaxiques ascendants; c'est approche utilisé par Yacc. Copyright © 2007 Addison-Wesley. All rights reserved.