La présentation est en train de télécharger. S'il vous plaît, attendez

La présentation est en train de télécharger. S'il vous plaît, attendez

ISBN 0-321-49362-1 Chapitre 4 Analyse lexicale et syntaxique.

Présentations similaires


Présentation au sujet: "ISBN 0-321-49362-1 Chapitre 4 Analyse lexicale et syntaxique."— Transcription de la présentation:

1 ISBN Chapitre 4 Analyse lexicale et syntaxique

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

3 Copyright © 2007 Addison-Wesley. All rights reserved.1-3 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)

4 Copyright © 2007 Addison-Wesley. All rights reserved.1-4 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)

5 Copyright © 2007 Addison-Wesley. All rights reserved.1-5 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

6 Copyright © 2007 Addison-Wesley. All rights reserved.1-6 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.

7 Copyright © 2007 Addison-Wesley. All rights reserved.1-7 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

8 Copyright © 2007 Addison-Wesley. All rights reserved.1-8 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.

9 Copyright © 2007 Addison-Wesley. All rights reserved.1-9 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!

10 Copyright © 2007 Addison-Wesley. All rights reserved.1-10 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)

11 Copyright © 2007 Addison-Wesley. All rights reserved.1-11 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

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

13 Copyright © 2007 Addison-Wesley. All rights reserved.1-13 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

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

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

16 Copyright © 2007 Addison-Wesley. All rights reserved.1-16 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.

17 Copyright © 2007 Addison-Wesley. All rights reserved.1-17 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.

18 Copyright © 2007 Addison-Wesley. All rights reserved.1-18 L'analyseur syntaxique (suite) Complexité –À partir de toute grammaire non ambiguë, il est possible de construire un analyseur syntaxique fonctionnant en temps O(n 3 ), 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)

19 Copyright © 2007 Addison-Wesley. All rights reserved.1-19 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) entrée Algorithme LL: –Left-to-right scan (lecture de l'entrée de gauche à droite) –Leftmost derivation (dérivation par la gauche)

20 Copyright © 2007 Addison-Wesley. All rights reserved.1-20 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 Algorithme LR: Left-to-right scan Rightmost derivation

21 Copyright © 2007 Addison-Wesley. All rights reserved.1-21 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

22 Copyright © 2007 Addison-Wesley. All rights reserved.1-22 Analyseur récursif-descendant (suite) Exemple: {(+ | -) } {(* | /) } id | ( )

23 Copyright © 2007 Addison-Wesley. All rights reserved.1-23 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(); }

24 Copyright © 2007 Addison-Wesley. All rights reserved.1-24 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(); }

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

26 Copyright © 2007 Addison-Wesley. All rights reserved.1-26 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

27 Copyright © 2007 Addison-Wesley. All rights reserved.1-27 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

28 Copyright © 2007 Addison-Wesley. All rights reserved.1-28 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

29 Copyright © 2007 Addison-Wesley. All rights reserved.1-29 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?

30 Copyright © 2007 Addison-Wesley. All rights reserved.1-30 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

31 Copyright © 2007 Addison-Wesley. All rights reserved.1-31 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

32 Copyright © 2007 Addison-Wesley. All rights reserved.1-32 Analyseurs ascendants (suite) Un parseur LR est un automate fini augmenté d'une pile Une configuration de la machine a la forme: (S 0 X 1 S 1 X 2 S 2 … X m S m, a i a i+1 …a n $) 1.a i a i+1 …a n : Partie de l'entrée qui reste à lire 2.S i : États de la machine 3.X i : Symboles de la grammaire

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

34 Copyright © 2007 Addison-Wesley. All rights reserved.1-34 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.

35 Copyright © 2007 Addison-Wesley. All rights reserved.1-35 Analyseurs ascendants (suite) Configuration initiale: (S 0, a 1 …a n $) Configuration courante: (S 0 X 1 S 1 X 2 S 2 …X m S m, a i a i+1 …a n $) Comportement du parseur: –Si ACTION[S m, a i ] = Shift S, la prochaine configuration sera: (S 0 X 1 S 1 X 2 S 2 …X m S m a i S, a i+1 …a n $) –Si ACTION[S m, a i ] = Reduce A et que S = GOTO[S m-r, A], où r = | |, alors la prochaine configuration sera: (S 0 X 1 S 1 X 2 S 2 …X m-r S m-r AS, a i a i+1 …a n $)

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

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

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

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

40 1-40 Comprendre les tables: les items (0)S T$ (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 0T0_ T 1_

41 1-41 T ST_$ Signification des items 0T0 0T0 S S_T$ $ ST$_ T T0T_0 T T0T_0 0 T0T0_ 1 T1_ 0 T0T0_ 0 T0_T0 0 T0_T0 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)

42 1-42 T ST_$ Signification des items (suite) 0T0 0T0 S S_T$ $ ST$_ T T0T_0 T T0T_0 0 T0T0_ 1 T1_ 0 T0T0_ 0 T0_T0 0 T0_T0 1, T1_ 0, T0_T0 S, S_T$ S, accept S, S_T$ $, ST$_ T, ST_$ S, S_T$ T, ST_$ S, S_T$ 0, T0T0_ T, T0T_0 0, T0_T0 S, S_T$ T, T0T_0 0, T0_T0 S, S_T$ 0, T0T0_ T, T0T_0 0, T0_T0 S, S_T$ T, T0T_0 0, T0_T0 S, S_T$ Shifts (3 fois) Reduce Shift Reduce Shift Reduce ShiftReduce Analyse du mot 00100$

43 1-43 Automate fini 0 S_T$ 1 ST_$ ST$_ 4 T0T_0 2 T0_T0 5 T0T0_ 3 T1_ 0 0 T 0 T $ 1 1 0) S T$ 1) T 0T0 2) T 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.

44 1-44 Construction des tables à partir de l'automate ACTIONGOTO 01$T 0S2S31 1accept 2S2S34 3R2 4S5 5R1

45 1-45 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

46 1-46 Automate fini non-déterministe 0 S_T$ 1 ST_$ ST$_ 4 T0T_0 2 T0_T0 5 T0T0_ 3 T1_ 0 0 T 0 T $ T0_V 8 V2_V 7 V2_ 9 V2V_ V T0V_ V

47 1-47 Automate fini déterministe 0 S_T$ 1 ST_$ ST$_ 4 T0T_0 2 T0_T0 5 T0T0_ 3 T1_ 0 0 T $ 1 1 2,6 T0_T0 T0_V 7,8 V2_ V2_V 9 V2V_ 2 2 V 0 0 T 10 T0V_ V On peut toujours transformer un automate fini non-déterministe en un automate fini déterministe équivalent. Chaque état correspond à un ensemble d'items.

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

49 1-49 Conflits Shift-Reduce S 0 S 0 | 0 –Configuration initiale: (S 0, 000$) –Shift: (S 0 0 S 1, 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.

50 1-50 Conflits Reduce-Reduce 1.S 0 S 0 2.S T 3.T S 0 4.T 1 –Configuration initiale: (S 0, 010$) –Shift: (S 0 0 S 1, 10$) –Shift: (S 0 0 S 1 1 S 2, 0$) –Reduce: (S 0 0 S 1 T S 3, 0$) –Reduce: (S 0 0 S 1 S S 3, 0$) –Shift: (S 0 0 S 1 S S 3 0 S 4, $) –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ë.

51 Copyright © 2007 Addison-Wesley. All rights reserved.1-51 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.


Télécharger ppt "ISBN 0-321-49362-1 Chapitre 4 Analyse lexicale et syntaxique."

Présentations similaires


Annonces Google