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

INFO 2108 Syntaxe et sémantique des langages de programmation Pierre-Yves Schobbens Bureau 409 081/72 49 90 rue Grandgagnage 21 5000 Namur

Présentations similaires


Présentation au sujet: "INFO 2108 Syntaxe et sémantique des langages de programmation Pierre-Yves Schobbens Bureau 409 081/72 49 90 rue Grandgagnage 21 5000 Namur"— Transcription de la présentation:

1 INFO 2108 Syntaxe et sémantique des langages de programmation Pierre-Yves Schobbens Bureau 409 081/72 49 90 rue Grandgagnage 21 5000 Namur pierre-yves.schobbens@info.fundp.ac.be

2 Plan 0. Introduction 1. Analyse lexicale : Langages réguliers 2. Analyse syntaxique : Langages non contextuels 3. Analyse statique (p.ex. typage): Grammaires attribuées 4. Eléments de génération de code 5. Sémantique

3 Références Grune, Bal, Jacobs, Langendoen « Compilateurs », Dunod, 2002. Aho, Sethi, Ullman : « Compilateurs : principes, techniques et outils », InterEditions, 1998, BUMP # 1 412/037 R. Wilhem, D. Maurer : « Les compilateurs : théorie, construction, génération », Masson, 1994, BUMP # 1 412/030

4 Chapitre 0. Introduction

5 Types de langages Les techniques de ce cours sappliquent à: –des langages de programmation :Pascal, Ada, … –des langages de commande : JCL, Sh, Csh, … – des langages de description de données: SQL (DDL), XML,... – des langages de spécification : VDM, Z, Albert,... – des langages de formulaires : EDIFACT, CGI (WWW),... – des formats de messages (réseaux) –des langages de documents : EQN, HTML,

6 Paradigmes de langages de programmation 1. impératifs : Algol, Pascal, Ada, Fortran, Cobol, Modula, C axés sur laffectation 2. fonctionnels : Lisp, ML, Hope, Miranda, Haskell, FP basés sur lévaluation des expressions 3. logiques : Prolog, Gödel basés sur la preuve de formules 4. orientés objet : Simula, Smalltalk, C++, Eiffel, CLOS, Java basés sur lhéritage N.B. :Les paradigmes ne sont pas mutuellement exclusifs.

7 Exécution des langages 2 extrêmes 1. Les interpréteurs - lisent le programme au fur et à mesure les programmes peuvent être créés dynamiquement 2. Les compilateurs - traduisent lensemble du programme soit- en langage dune machine concrète 486, P6, Power ou- en langage dune machine abstraite SECD, WAM, JVM, P-MACHINE

8 Rôle dun compilateur compilateur Code source Code cible Code machine du compilateur compilateur dimplémentation Générateur de compilateur (Flex, Bison) Code dimplémentation du compilateur Spécification

9 Structure dun compilateur 1. analyse lexicale 2. crible 3. analyse syntaxique 4. analyse sémantique 5. optimisations 6. allocation mémoire 7. génération de code 8. optimisations propres à la cible avant arrière reconnaître les « mots » reconnaître les « phrases » vérifier les types, etc. élimination de code inutile, etc. choisir la place des variables instructions machine séquence plus efficaces D25

10 Ex. compilateurs GNU C ANSI 68000Pentium Power Ada 95 C++ Pascal Front-ends (1-4) partie avant Middle-end (5) Partie centrale Back-ends (6-9) partie arrière G6

11 Outils pour les langages Editeurs structurels : édition intelligente Analyseurs : p.ex. pour la rétro-ingénierie, Y2K Paragrapheurs : mettent en page D17

12 Chapitre 1 : Analyse Lexicale Rôle : retrouver les mots qui composent le texte

13 Place de lanalyse lexicale Analyseur lexical Texte source = caractères « mots » = lexèmes générateur danalyseur lexical Expressions régulières Automate fini D104-108

14 Plan 1. Langages et expressions régulières 2. automates finis : Kleene 2.1 non-déterministe 2.2 déterministe 2.3 minimal 3. Régulier ou pas?

15 Définitions : alphabet, ensemble de caractères (donné, fini) ex. : ASCII, EBCDIC, ISO-Latin-1, UniCode,... texte, mot, phrase : suite de caractères Langage : ensemble de phrases Note : convient pour les langages séquentiels (parlé, écrit) mais pas pour des langages graphiques : phrase vide. : concaténation (parfois le. est omis) D112

16 Propriétés x. = x =. xneutre x. (y. z) = (x. y). zassociativité Ces propriétés sont complètes D113

17 Ordres X est un préfixe de Y : Y commence par X –« 12 » est un préfixe de « 1234 » X est un suffixe de Y : Y finit par X –« 34 » est un suffixe de « 1234 » X est une sous-chaîne de Y : X sobtient par suppression dun suffixe et dun préfixe –« 23 » est une sous-chaîne de « 1234 » D113

18 Opérations sur les langages D114

19 Propriétés D117

20 Expressions régulières = les expressions écrites avec souvent omis aussi noté ou + Langage régulier = langage décrit par une expression régulière D115

21 Exemples dexpressions régulières 1. = 0 | (1| 2 | 3 | 4 | 6 | 7 | 8 | 9). (0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9)* une constante décimale de C est, soit un 0 seul, soit un chiffre significatif suivi dautant 0 1 nest pas une constante décimale en C, mais octale. 1 0 est une constante décimale. 2. = (0 | 1)*. 0 3. = (a | b |... | z). (a | b |... | z | 0 |... | 1)*

22 Abréviations } L n =L. L.... L où n est un naturel n n fois L + =L L* [a - z]=tous les caractères entre a et z dans le code ASCII = les lettres = a b... z L ? =L L [n-m] =L n L n+1... L m

23 2. Automates finis b a eb a e caractère courant mot à reconnaître état final ou accepteur q4q4 q3q3 q2q2 q1q1 q0q0 état initial état courant a c b a b D135

24 Définition Un automate fini (non-déterministe avec transitions vides) se compose de : D136

25 Fonctionnement Un automate accepte un mot m si on peut trouver un chemin c: –Qui commence dans létat initial –Qui finit dans un état final –Qui suit des transitions –La concaténation des étiquettes des transitions donne m Les mots acceptés forment le langage de lautomate L(A) D137

26 Exemple: constante naturelle décimale de C [1-9] 0 [0-9]

27 Exemple : multiples de 2 en notation binaire 0 0 1 Multiples de 2 en notation binaire : Ils se terminent toujours par 0. Ceci est facile à représenter par un automate non-déterministe

28 Exemple : identificateurs de Pascal a a z z 0 9 notation : [a-z] [a-z 0-9]

29 Exemple : Multiples de 7 rs a Principe: r est le reste par 7 du nombre lu (n) m = n * 10 + a donc s = (r * 10 + a) mod 7

30 Théorème de Kleene Un langage est régulier ssi cest le langage dun automate fini Preuve : La preuve est donnée par 2 algorithmes 1. qui construit un automate pour chaque expression régulière 2. qui construit une expression régulière pour chaque automate fini en gardant le même langage.

31 Expression automate cas de base début (a) Automate pour (b) Automate pour. début (c) Automate pour le caractère "a". début a

32 Expression automate: union Pour R 1 Pour R 2 début (a) Construction de lautomate dunion pour deux expressions régulières

33 Expression automate: concaténation Pour R 1 Pour R 2 début (b) Construction de lautomate de concaténation pour deux expressions régulières

34 Expression automate: répétition Pour R 1 début (c) Construction de lautomate de fermeture pour deux expressions régulières

35 Exemple : constante décimale de C 0 1 2 F 3 4 5 1 9... 0 9 0

36 Problèmes 1. Lautomate contient des -transitions 2. Il nest pas déterministe: moins efficace 3. Il y a beaucoup trop détats (80 dans lexemple)

37 Automate déterministe Un automate fini est déterministe, intuitivement sil ne peut se comporter que dune façon pour un mot donné : –Il na pas de transition- –Étant donné un état de départ et un caractère lu, il y a au plus 1 état darrivée Il est complet si, étant donné un état de départ et un caractère lu, il y a au moins un état darrivée D138

38 Idée de la déterminisation début 1 2... k S 1, S 2,..., S k Dans lautomate déterministe: Un seul chemin vers un état qui représente tous ceux où une copie peut être. début 1 2... k S1S1 S2S2 SnSn... Dans lautomate non déterministe: Plusieurs chemins étiquetés

39 Déterminisation On construit un nouvel automate A Note : on peut diminuer le nombre détats en ne considérant que les états accessibles. Notation : puisque est fonctionnelle pour les automates déterministes, on emploie une notation fonctionnelle - De même alphabet - nouvel état = ensemble danciens états -état initial = succs({q 0 }) = états accessibles de q 0 par des transitions vides - état final = état contenant un ancien état final - transition = ensemble des états où une copie peut arriver S,a) = succs( {q | p q, p S} ) D140 a

40 Exemple : constantes décimales de C Quelques ensembles fermés par 0 1 2 F 3 4 5 1 9... 0 9 État initial 0

41 Constantes décimales de C déterminisé 0 1 9 0 9 0 9 0 0 9

42 Exemple Reconnaître une suite de 1, 2, 3 où le dernier chiffre est apparu précédemment. Expression régulière : * (1 * 1 | 2 * 2 | 3 * 3), où Automate : 0 2 3 2 2 1 1 3 3 1 4 1,2,3

43 Exemple : déterminisation 3 0 2 1 3 0,1 1/2 0,2 0,3 0,1,4 0,1,2 0,1,3 0,2,4 0,2,3 0,3,4 2 1 2 3 1 2 1 2 3 3 2 1/2 3 3 1 1 2/3 1 1/3 2 3 1 3 0,1 2,4 0,1 2,3 0,1 3,4 0,2 3,4 1/3 2/3 1/2/3 2 1 0,1 2,3,4 Intuition : Les états marqués 1 (ou 2, 3) signifient «on a rencontré un 1 (ou 2,3)». Létat 4 signifie : on a rencontré un 2° caractère identique, donc on peut terminer.

44 Algorithme de minimisation retirer les états non accessibles compléter lautomate Idée : On met les états dans des classes différentes quand on voit quils ont un comportement différent. répéter pour chaque K, K := ( \ {K}) {{K i }} où {K i } est la partition de K la plus grosse tous les états de K i arrivent dans la même classe pour chaque caractère jusquà ce que ne change pas : partition couranteles états sont groupés en classes := {F, Q \ F}au départ, on crée deux classes: les finaux et les non-finaux Fusionner les états d une même classe Retirer létat mort

45 Exemple de minimisation « Constante décimale de C » 0 1 9 0 9 0 9 0 0 9 Non finaux Finaux Minimisation du nombre détats : partition des états

46 9 0 Exemple de minimisation « Constante décimale de C » 0 1 9 Fusion détats : partition des états

47 Kleene (2) automate fini expression régulière (1) 1° étape : automate fini jeu déquations pour chaque état on crée une équation : S 3 = a. S 4 b. S 5 S 3 représente lensemble des chaînes quon peut lire en partant de S 3. Note: ces équations ont plusieurs solutions, c'est la plus petite qui nous intéresse. S3S3 S4S4 S5S5 a b si S 3 est final

48 automate fini expression régulière (2) 2° étape : résolution des équations où S 3 napparaît pas dans les expressions x, y. S 3 = x y. S 3 ~> S 3 = y* x

49 Exemple 0-9 1-9 0 S0S0 S1S1 S2S2 1° étape: l automate est équivalent aux équations S 0 = 0. S 1 | (1 | 2 | … | 9). S 2 S 1 = S 2 = | (0 | 1 |... | 9). S 2

50 Exemple (2) 2° étape : résolution par triangulation 1) éliminer S 1 : S 0 = 0 | [1-9]. S 2 S 2 = | [0-9]. S 2 2) résoudre S 2 : S 2 = [0-9]*. 3) éliminer S 2 : S 0 = 0 | [1- 9]. [0-9]*

51 Complémentation On calcule un automate qui accepte le complément de A. Algorithme: 1.Déterminiser A; 2.Le compléter: 1.Ajouter un état mort; 2.Ajouter des transitions vers cet état (si car. manque). 3.Propriété: chaque chaîne amène dans un seul état. 3.Inverser les états finaux et non-finaux.

52 Exemple de complémentation Automate déterministe complété : il y a une flèche pour chaque caractère de = [0-9] [0-9] [1-9] 0 S0S0 [0-9] Négation : on intervertit les états finaux [0-9] [1-9] 0 S0S0 [0-9] S3S3 S1S1 S2S2 S1S1 S2S2

53 Langages non réguliers Un langage est régulier ssi un programme peut le lire (de gauche à droite) en ne mémorisant quune information finie. Lemme de pompage: Une chaîne plus longue que le nombre détats de lautomate contient une boucle quon peut répéter. si k est le nombre détats une chaîne plus longue doit faire une boucle. y z x D119

54 Exemple Le langage {0 n 1 n } nest pas régulier : –Il faut retenir le nombre de 0, qui peut être grand : linformation nest pas finie. –Sil était régulier, on aurait un automate; Soit k son nombre détats. 0 k 1 k doit passer par une boucle : Si la boucle ne contient que des 0, on accepte des chaînes avec plus de 0 que de 1. Si la boucle ne contient que des 1, on accepte des chaînes avec plus de 1 que de 0. Si la boucle contient des 0 et 1, alors on accepte des chaînes où 0 suit 1.

55 Chapitre 2 : Analyse Syntaxique Rôle :Lanalyseur syntaxique retrouve la structure (arbre) grammaticale du programme.

56 Grammaire non contextuelle une grammaire a 4 éléments: lensemble des symboles terminaux V T lensemble des non-terminaux V N lensemble des productions P le symbole de départ S (non-terminal) finis

57 BNF : Exemple : Pascal Exemple Pour Pascal, on reprend : V T = les symboles reconnus lors de lanalyse lexicale : mots-clés. Ex. if, identificateurs. Ex. x,... V N = les catégories syntaxiques : Ex. :,, P = les productions de la grammaire Ex. : : : = if then else S = la catégorie des textes complets : Pour le langage C la catégorie nexiste pas, le symbole de départ (ce quon peut compiler) est.

58 Notations Terminaux: les minuscules, chiffres, symboles dopérateurs, symboles en gras Non-terminaux: majuscules: A,B,C,S ; entre Symboles: X, Y, Z Chaînes de terminaux: u,v,w Chaînes de symboles: D192 W254

59 Historique - Pourquoi « non contextuel » ? (context-free) Chomsky (en 1956) a choisi ce nom par contraste avec ses « grammaires contextuelles » (type 1) où on peut mettre des conditions pour lapplication dune règle. - BNF signifie « Backus Naur form », du nom de ses inventeurs (utilisé pour la définition d Algol 60, vers 1958).

60 Emploi dune grammaire Partir du symbole de départ (ou axiome) S; répéter : –employer une règle : remplacer le côté gauche par le côté droit jusquà ce quil ny ait plus que des symboles terminaux dans le texte.

61 Langage Chaque chaîne quon peut obtenir ainsi est une phrase de G. Lensemble des phrases est le langage de G noté L(G). Les étapes intermédiaires sont des proto-phrases de G.

62 Dérivations Une dérivation est une suite de pas de l algorithme précédent: S 1 2 3 w Si l algorithme peut passer de à en zéro, une ou plusieurs étapes, on dit que produit, noté *

63 Exemple : program tutu. : program tutu begin end. Comp : : : = begin end produit directement Comp * produit program tutu begin end.

64 Simplifications Un non-terminal est inaccessible sil ne fait partie daucune proto-phrase. Il est improductif sil ne produit aucune chaîne de terminaux. On peut retirer ces non-terminaux de la grammaire sans changer le langage : ils ne servent à rien.

65 Algorithme: Productif Algorithme qui donne les non-terminaux productifs. Au départ: aucun non-terminal nest marqué productif tous les terminaux sont productifs répéter parcourir les productions A ::= si tous les symboles du côté droit sont marqués productifs alors marquer le côté gauche A comme productif jusquà ce quun parcours ne marque rien de plus On enlève les non-terminaux improductifs et les productions où ils apparaissent.

66 Algorithme: Accessible Algorithme qui donne les non-terminaux accessibles. Au départ: seul le symbole de départ S est marqué accessible répéter parcourir les productions A ::= si le côté gauche A est marqué accessible alors marquer tous les non-terminaux du côté droit comme accessibles jusquà ce quun parcours ne marque rien de plus On enlève les non-terminaux inaccessibles et leurs règles. Exercice: Réécrivez ces deux algorithmes avec un temps d'exécution optimal (linéaire plutôt que quadratique).

67 Arbre de dérivation Idée : pour une phrase, il y a beaucoup de dérivations essentiellement identiques Déf. : Un arbre de dérivation pour u dans G est un arbre ordonné : –Dont les nœuds sont étiquetés par des non-terminaux – Dont les feuilles sont étiquetées par des terminaux (ou ) – Dont la racine est étiquetées par le symbole de départ – Chaque nœud correspond à une règle de production

68 Exemple darbre S : : = p id R ; D C.(1) D : : = (2) R : : = (F) | (3 | 4) F ::= id | id, F(5 | 6) C ::= b I e(7) I ::= (8) Dérivations gauche: S p id R ; D C. p id ; D C. p id ; C. p id ; b I e. p id ; b e. droite: S p id R ; D C. p id R ; D b I e. p id R ; D b e. p id R ; b e. p id ; b e. Arbre de dérivation : S p id R ; D C. b I e Grammaire S: programme R: paramètres du programme D: déclarations C: instruction composée (1)(1)(4)(4)(2)(2)(7)(7)(8)(8) (1)(1)(7)(7)(8)(8)(2)(2)(4)(4)

69 Ambiguité Déf. : une grammaire est ambiguë sil y a une phrase qui a plusieurs arbres de dérivation. A éviter quand on veut générer un analyseur. Peut être utile comme grammaire abstraite. Exemple dambiguïté : les « else pendants » du Pascal : : = if then else | if then if b then if c then x : = 5 else x : = 3 Autre exemple: la grammaire précédente est ambigüe

70 Ambiguité : exemple : expressions La grammaire suivante des expressions de Pascal avec +,* : E ::= E+E | E*E | (E) | id est ambiguë: par exemple, x+y+z a deux arbres d'analyse: E E E E E E x + y + z x + y + z On notera ces arbres (x+y)+z et x+(y+z).

71 Résolution des ambigüités Une ambigüité (x+y)+z vs. x+(y+z) est appellée une ambigüité d'associativité: on la résoud en choisissant le coté récursif (coté gauche en Pascal) E ::= E+F | F F ::= id | (E)

72 Résolution des ambigüités Une ambigüité (x+y)*z vs. x+(y*z) est appellée une ambigüité de précédence: on la résoud en ajoutant un nouveau non- terminal par niveau de précédence. Ici, terme T et facteur F: E ::= E+T | T T ::= T*F | F F ::= id | (E)

73 Résolution des ambigüités L'ambigüité du if then else peut aussi se résoudre en introduisant des non-terminaux: : qui a tous ses else : sinon. ::= | ::= if then else ::= if then | if then else

74 Automate à pile a caractère courant fenêtre de lecture (avance dun caractère)........ sommet = état courant pile a létat définit le sommet de la pile

75 Automates à pile Définition Un automate à pile se compose de : V T lalphabet dentrée (fini) Q les états (fini) q 0 létat initial Fles états finaux ou accepteurs caractère à trouver dans la fenêtre états à dépiler du sommet de la pile états à empiler sur la pile

76 Fonctionnement Lautomate démarre avec une pile vide, dans létat initial. Il suit les transitions (d, a, e) : –lire le caractère. –dépiler/empiler les éléments indiqués de la pile. Il accepte le texte sil arrive dans un état accepteur (final).

77 Déterminisme Un automate à pile est déterministe si : –il na pas de transitions. –si deux transitions lisent le même caractère, elle ne peuvent pas sappliquer sur la même pile : la pile consultée de lune ne peut pas être un préfixe de la pile consultée de lautre.

78 BNF Automates à piles Les états sont des items, càd des règles avec un « point de lecture » inséré. On utilise 3 types de transitions : –Expansions (expand) : si létat a le point devant un non-terminal B: A::= … B … on empile une règle pour celui-ci: B ::= … avec le point au début. –Réductions (reduce): si létat a le point en fin: B ::= …, on le dépile et on avance le point: A::= … B … –Lectures ou décalages (shift): si létat a le point devant un terminal: A::= … a …, on le lit et on avance le point A::= …a ….

79 BNF: état initial/final On ajoute un nouveau symbole de départ S létat de départ est S ::= S létat final est S ::= S

80 BNF = Automates à pile Il y a aussi une transformation des automates à pile vers les BNF. Un langage est donc non-contextuel ssi cest le langage dun automate à pile non- déterministe.

81 Non-déterminisme Lautomate obtenu est non-déterministe : plusieurs expansions sont possibles, laquelle choisir ? –Regarder les k symboles en entrée pour choisir la bonne production: analyseur descendants gauche LL(k) – Postposer la décision (comme pour les automates finis) analyseur ascendant droit (ex. yacc) LR(k)

82 Analyse descendante LL(k) Grammaire LL(k) : Le choix de la bonne expansion doit pouvoir se faire sur base des k prochains symboles à lire.

83 Cas simple Si pour chaque non-terminal chacune des productions commence par un symbole terminal différent alors la grammaire est simplement LL(1) Exemple : : = if then else fi while do od begin end le premier terminal permet de faire le bon choix.

84 LL(k): définition Pour chaque choix d'une production pour A, on peut faire ce choix sur base des k premiers caractères non encore lus: G est LL(k) ssi pour tout choix A ::=, A::= de G ( ), PREMIER( ) PREMIER( ) = pour tout qui peut suivre A dans une dérivation gauche: S g * wA

85 Algorithme : PREMIER PREMIER(A) donne les possibilités de début de A, tronqués à k caractères. Pour chaque non-terminal A, le tableau P[A] contient un sous-ensemble de PREMIER(A), initialement vide. tant que P change: pour chaque règle A ::= ajouter PREMIER( ) à P[A] PREMIER(X1…Xn) est la concaténation tronquée à k de PREMIER(X1) … PREMIER(Xn) PREMIER(X) = {X} si X est terminal PREMIER(X) = P[X] si X est non-terminal

86 Exemple : sommes Une somme est une expression Pascal du genre : x+y+z+w en Pascal, les opérations se regroupent de gauche à droite : ((x+y)+z)+w La grammaire des sommes est donc: S ::= S+id | id | (S)où id est le terminal pour les identificateurs P[S] = après la 1ère production = {id} après la 2ème production = {id, ( } après la 3ème production, qui est la valeur finale. Donc cette grammaire nest pas LL(1). En général, une grammaire récursive à gauche nest pas LL(k)

87 Comment rendre une grammaire LL(1) ? éliminer la récursivité gauche factoriser les parties communes

88 Éliminer la récursivité gauche Une grammaire est récursive à gauche si un non-terminal A se dérive strictement en une proto-phrase commençant par A: A + A Une grammaire récursive à gauche nest jamais LL(k). A ::= A devient A, A ::= A| D201

89 Algorithme pre : G sans cycle A A, sans vide A post : G sans récursivité à gauche invariant : (A k ::= A l ), si k k : les règles déjà traitées commencent par des grands terminaux pour i := 1..n pour j := 1..i-1 remplacer Aj par sa définition dans Ai ::= Aj remplacer Ai ::= Ai par Ai ::= Ai, Ai ::= Ai|

90 Exemple Élimination de la récursivité gauche Grammaire dexpressions: E ::= E + T | T T ::= T * F | F F ::= ( E ) | id D202 Ordre: 1: E, 2: T, 3: F i=1 Ai::=Ai | E ::= T E E ::= +T E | i=2 Ai::=Ai | T ::= F T T ::= * F T | F ::= ( E ) | id Résultat

91 Exemple 2 Élimination de la récursivité gauche Grammaire : A ::= B b | C e B ::= A a | d C ::= A c | d D203 Ordre: 1: A, 2: B, 3: C i=2 Ai::=Aj B ::= B b a | C e a | d B::= CeaB|dB B::=baB| Ai::=Ai | C ::= B b c | C e c | d C ::= CeaBbc|dBbc|Cec|d C ::= dBbcC|dC C::=eaB bcC|ecC| calcul :Résultat A ::= B b | C e

92 Factorisation Idée : postposer le choix en regroupant les parties communes (facteurs) Exemple: I ::= if E then I | if E then I else I devient I ::= if E then I C C::= | else I

93 Exemple : PREMIER Pour la grammaire des expressions sans récursivité gauche: 0 : S ::= E3 : E ::= + E6 : T ::= * T 1 : E ::= T E4 : T ::= F T7 : F ::= (E) 2 : E ::= 5 : T ::= 8 : F ::= id k vaut 1. Les itérations de PREMIER sont listées en colonnes. On visite les productions en commençant par le fin (de 8 à 1). Par exemple, on peut lire dans la deuxième entrée de la première colonne, quaprès la visite des productions 8 puis 7, lensemble P du non-terminal F contient les symboles id et (. 8 : P[F] = {id}5 : P[T] = {*, }2 : P[E] = {+, } 7 : P[F] = {id, ( }4 : P[T] = {id, ( }1 : P[E] = {id, ( } 6 : P[T] = {*}3 : P[E] = {+}0 : P[S] = {id, ( } P ne donne pas le début des productions 5 et 2: il faut connaître le début de ce qui est derrière E et T, calculé par SUIVANT.

94 Suivant Quand PREMIER( ) est trop court, on regarde derrière avec SUIVANT(A) : ce qui peut suivre A. Algorithme : Le tableau des suivants est initialisé à vide SUIVANT[S] := {$} /* le marqueur de fin */ tant que SUIVANT change pour chaque règle A ::= B ajouter PREMIER( ). SUIVANT[A](tronqué à k) à SUIVANT[B] Si ceci élimine les conflits, on dit que la grammaire est fortement LL(k). Une grammaire LL(1) est fortement LL(1).

95 Exemple : SUIVANT Pour la grammaire des expressions sans récursivité gauche: 0 : S ::= E3 : E ::= + E6 : T ::= * T 1 : E ::= T E4 : T ::= F T7 : F ::= (E) 2 : E ::= 5 : T ::= 8 : F ::= id PREMIER ne suffit pas pour E, T On calcule SUIVANT: S: {$} 0: E: {$} 1: T: {+,$} E:{$} 4: F: {*,+,$} T:{+,$} 7: E: { ),$} 1: T: {+,),$} E:{ ),$} 4: F: {*,+,),$} T:{+,),$}

96 Analyseur descendant à pile Si la grammaire est LL(k) : à partir du non-terminal à développer (derrière le en sommet de pile) et des k caractères dentrée, on sait quelle règle appliquer. On le met dans une table. Lanalyseur fait : –une lecture si le est devant un terminal: On avance la fenêtre et le point dans l'item. –une réduction si le est en fin de d'item: On dépile l'item. –une expansion si le est devant un non-terminal: On empile l'item daprès la table.

97 Exemple table LL(1) pour expressions D215

98 Trace de lanalyse LL(1) dune expression Contenu de la pileChaîne d'entrée $ [S E] id * id $ $ [S E] [E TE'] id * id $ $ [S E] [E TE'] [T FT'] id * id $ $ [S E] [E TE'] [T FT'] [F id] id * id $ $ [S E] [E TE'] [T FT'] [F id] * id $ $ [S E] [E TE'] [T FT'] * id $ $ [S E] [E TE'] [T FT'] [T' *T] * id $ $ [S E] [E TE'] [T FT'] [T' *T] id $ $ [S E] [E TE'] [T FT'] [T' *T] [T FT'] id $ $ [S E] [E TE'] [T FT'] [T' *T] [T FT'] [F id] id $ $ [S E] [E TE'] [T FT'] [T' *T] [T FT'] [F id] $ $ [S E] [E TE'] [T FT'] [T' *T] [T FT'] $ $ [S E] [E TE'] [T FT'] [T' *T] [T FT'] [T' ] $ $ [S E] [E TE'] [T FT'] [T' *T] [T FT'] $ $ [S E] [E TE'] [T FT'] [T' *T] $ $ [S E] [E TE'] [T FT'] $ $ [S E] [E TE'] $ $ [S E] [E TE'] [E' ] $ $ [S E] [E TE'] $ $ [S E] $ $$ D216

99 Gestion de la pile On peut représenter les items en mettant les non-terminaux non encore lus en ordre inverse sur la pile. Lanalyseur fait : –une lecture si le sommet est un terminal: On avance la fenêtre et on dépile. –une expansion si le sommet est un non-terminal: On empile en ordre inverse la partie droite de la règle trouvée daprès la table. –les réductions deviennent implicites. D215

100 Analyseur récursif prédictif On peut employer la pile implicite de récursion : –le non-terminal de gauche = procédure appelée –règles = corps de la procédure –prédiction = test du fichier dentrée –point = adresse de retour

101 Exemple : expression procedure expr; begin if input^ in [ (, id ] then begin term; exprend; end else erreur end; E ::= T E choix par table LL(1) T E

102 Exemple: suite procedure exprend; begin if input^ = + then begin get; term; exprend; end else if eof or input^ = ) then else erreur end E ::= +TE | E + T E

103 Actions On peut insérer du code dans les règles de syntaxe, appelé « action » Ce code est exécuté lorsque l'analyseur exécute cette partie de la règle Souvent ces actions construisent un arbre danalyse abstrait

104 Arbre abstrait : exemple E T E F T id + E T E F T Arbre syntaxique concret de x + y, pour la grammaire des expressions sans récursion à gauche. + x y Arbre abstrait x + y

105 2.3 Analyse syntaxique ascendante Idée : On choisit la règle à appliquer après avoir lu le texte correspondant –larbre danalyse est construit de bas (feuilles) en haut (racine) –la dérivation correspondante est droite : le non-terminal le plus à droite est actif. –Le programme remonte dans la dérivation. Problème : comment garder trace des règles possibles ? D222

106 Exemple : Texte Ada if x + 1 > y then x := 1 else x := 2 end if ; > + x 1 y := x1 x2 * if then else := end if manche if then else end if...

107 Automate fini caractéristique Décrit le comportement du sommet de pile Sa déterminisation donne des ensembles de règles possibles Ses états finaux sont les réductions

108 Automate fini caractéristique Déf. : Lautomate fini caractéristique est donné par états = items(G) alphabet = les symboles (terminaux ou non) état initial = litem de départ: [S ::= S] états finaux = les états où on réduit: [A ::= ] transitions = lecture : on déplace le point après le symbole lu ([A ::= X X, [A ::= X où X V N V T expansion: si le point est devant un non-terminal, on choisit une de ses productions: ([A ::= B

109 Exemple : expression S0S0 S1S1 S2S2 S5S5 S3S3

110 Préfixe viable = la partie déjà analysée du texte = létat de la pile dun analyseur ascendant (avant le point) def: un préfixe dune proto-phrase droite qui ne sétend pas au-delà du manche le plus à droite

111 Item valide Intuitivement, un item valide donne un état possible de lanalyseur quand il a lu un préfixe. Def. : A::= est valide pour le préfixe viable ssi il y a une dérivation droite S d * A w d * w

112 Déterminisation de lautomate fini caractéristique En appliquant la déterminisation, on obtient un automate déterministe où létat atteint en suivant un préfixe viable est lensemble de ses items valides. Cet état peut être impropre ou conflictuel, s'il contient: –Une lecture (shift), càd un item où le point est devant un terminal –Et une réduction, càd un item où le point est en fin ou - deux réductions (conflit R/R) Dans ce cas, lautomate à pile associé est non déterministe, et la grammaire n'est pas LR(0).

113 Construction directe On peut spécialiser la déterminisation pour lautomate caractéristique de façon à ne pas le construire: on fait les deux étapes ensemble. D252 W342

114 Fermeture fonction Fermeture (s : ensemble ditems) : ensemble ditems ; (* fermeture par les successeurs, ici les expansions *) var q : ensemble ditems ; début q := s ; tant que [X Y ] q et Y P et [Y ] q /* il y a une expansion qui n'est pas encore dans q */ ajouter [Y ] à q retourne (q) fin ; s est appelé le noyau de q; il détermine q. D252 W342

115 Successeurs fonction Transition(s : ensemble ditems, Y : V N V N ) : ensemble ditems; (* donne le noyau de létat atteint par la lecture de Y *) retourne ( { [X Y ] | [X Y ] s } ) Le noyau du successeur par une transition étiquetée Y contient les items de létat de départ qui avaient le point devant Y, où on a avancé le point. D253 W343

116 Construction des états Q := { Fermeture({[S' ::= S]})}/* l'ensemble des états part de l'item initial */ := /* les transitions sont initialement vides */ pour chaque état q de Q, symbole X apparaissant derrière le point dans q faire q := Fermeture(Transition(q,X)) ; si q' non vide alors si q n'est pas dans Q alors on l'ajoute à Q on ajoute la transition de q vers q' lisant X dans D253 W343

117 Exemple : expressions S4S4 S 11 S5S5 S3S3 S2S2 S0S0 S1S1 S8S8 S9S9 +T E T F id ( ( T F F ( S6S6 E + ) S7S7 S 10 * * id F ( Lautomate LR(0) donne : D254 W339 Les états S 1, S 2, S 9 sont impropres : ils contiennent des conflits LR(0) : cette grammaire nest pas LR(0).

118 Exemple : expressions : états LR(0) Les états S 1, S 2, S 9 sont impropres : ils contiennent des conflits LR(0) : cette grammaire nest pas LR(0).

119 Exemple La grammaire: S ::= C | D C ::= a C | b D ::= a D | e nest pas LL(k) : on ne peut pas choisir entre C et D car il peut y avoir des a dabord dans les deux cas. Elle est LR(0) car on peut choisir après lecture. Son automate déterministe caractéristique ne contient pas de conflits LR(0). q 0 = {[S ::= S], [S::= C], [C::= aC], [C::= b], [S::= D], [D::= aD], [D::= e]} q 1 = {[C::= aC], [C::= aC], [C::= b], [D::= aD], [D::= aD], [D::= e]} q 2 = {[C::= b]} q 3 = {[D::= e]} q 4 = {[S::= C]} q 5 = {[C::= aC]} q 6 = {[S::= D]} q 7 = {[D::= aD]} q 7 = {[S::= S]} q0q0 q1q1 a e b C D S C b e D q5q5 q8q8 q6q6 q4q4 q3q3 q2q2 q7q7

120 SLR Pour résoudre les conflits LR(0), on regarde SUIVANT(A), où A est le côté gauche de la règle à réduire. D256 W352

121 Exemple : expressions SLR(1) Les états conflictuels LR(0) S 1 : le conflit entre réduire S, SUIVANT(S) = { $ } et lire +, est résolu. S 2 : le conflit entre réduire E, SUIVANT(E) = { $, +, ) } et lire *, est résolu. S 9 : idem. Cette grammaire est donc SLR(1). D237 W353

122 Exemple : Affectations en C S : : = L = R | R L : : = *R | id R : : = L L = partie gauche (donne ladresse) R : expression ; une expression est une instruction en C * : déréférenciation (prendre le contenu de ladresse) D257

123 Exemple : Affectations en C : automate SLR(1) [S S] [S L = R] [S R] [L * R] [L id] [R L] S3S3 S R [S S ] [S R ] S2S2 L [S L = R] [R L ] [S L = R] [R L] [L * = R] [L id] = S6S6 R S9S9 [S L = R ] [L id ] id S5S5 S4S4 * * L L R S7S7 S8S8 * [R L ] [L *R ] [L * R] [R L] [L *R] [L id] S 2 est conflictuel : SUIVANT(R) contient =. Cette grammaire nest pas SLR(1). id D258

124 Items LR(k) canonique On ajoute aux items une chaîne de longueur k (la prévision de litem), qui indique le texte qui peut suivre cet item: [A, u] La prévision est propagée par les transitions. Une nouvelle prévision est calculée avec PREMIER pour les expansions. On crée plus détats quavec les autres techniques (LR(0), SLR(1), LALR(1) ). D260 W350

125 Fermeture fonction Fermeture(I); répéter pour chaque item LR(k) [A B, u] de I et chaque chaîne v de PREMIER( u) pour chaque règle B ajouter [B, v] à I jusquà stabilisation D261 W350

126 Exemple : expressions : états LR(1) S4S4 S 11 S5S5 S3S3 S2S2 S0S0 S1S1 S8S8 S9S9 +T E T F id ( F ( S6S6 E ) S7S7 S 10 * * id F ( S 15 S 19 S 12 S 18 S 17 S 13 ( T F F E id ) S 16 S 21 * * id F ( S 20 +T id ( S 14 T F + Lautomate LR(0) est doublé : prévision avec $ (fin) ou avec )

127 Exemple : expressions : états LR(1) S 0 = Fermeture(Début) S 6 = Fermeture( S 1, +)) ={[S E,{$}]{[E E + T, {$, +} ], [E E+T,{$, +}],[T T * F, {$, +, *}], [E T, {$, +}],[T F, {$, +, *} ], [T T * F, {$, +, *}],[F (E), {$, +, *}], [T F, {$, +, *}],[F id, {$, +, *}] } [F (E), {$, +, *}], [F id, {$, +, *}] }S 9 = Fermeture(Succ( S 6, T)) {[E E + T, {$, +}], S 1 = Fermeture(Succ(S 0,E)) [T T * F, {$, +, *}] } {[S E, {$}], [E E + T, {$, +}] } S 2 = Fermeture(Succ(S 1,T)) {[E T, {$, +}], [T T * F, {$, +, *}] } = = S 4 = [E E+T,{), +}], [E T, {), +}], [T T * F, {), +, *} [T F, {), +, *}], [F (E), {), +, *}], [F id, {), +, *}] } { [F ( E), {$, +, *}], Notation: Les prévisions des items LR(1) qui ont le même item sans prévision sont regroupés.

128 LALR on garde les états LR(0) les prévisions sont la fusion des prévisions LR ayant le même cœur (état LR(0) ) Pour calculer les prévisions de [B ] : –trouver les origines de la règle : expansions [B ] –trouver les sources de lexpansion [A B, u] –calculer ce qui se trouve derrière B: PREMIER( u) –faire lunion –en cas de boucle: répéter jusquà stabilisation D270 W

129 Exemple : affectations en C [S S, {$} ] [S L = R] [S R, {$} ] [L * R] [L id] [R L, {$} ] S3S3 S R [S S ] [S R ] S2S2 L [S L = R] [R L, {$} ] [S L = R] [R L] [L * = R] [L id] = S6S6 R S9S9 [S L = R ] [L id ] id S5S5 S4S4 * * L L R S7S7 S8S8 * [R L ] [L *R ] [L * R] [R L] [L *R] [L id] id S0S0 Le conflit en S 2 est résolu Cette grammaire est LALR(1).

130 Exemple : expressions Etats impropres (conflit décaler/réduire) ( ( ( Derrière, en mauve: les ensembles de prévision LALR(1)

131 Grammaires ambiguës Une grammaire ambiguë peut être plus naturelle Elle provoque toujours des conflits Les conflits peuvent être résolus par des règles de précédence et dassociativité, sans augmenter le nombre détats D277 W368

132 Exemple : expressions La grammaire la plus naturelle est : E ::= E + E | E * E | ( E ) | id qui est ambiguë, mais peut servir de grammaire abstraite. En donnant des règles dassociativité: %left + %left * et de précédence données par lordre décriture, on résout les conflits Shift/Reduce: Si le dernier terminal de la règle à réduire est plus fort que celui la fenêtre, on réduit; sinon on lit. Si cest le même, on emploie lassociativité: on réduit pour %left Enfin, Yacc et Bison décalent de préférence. Pour les conflits réduire/réduire, ils préfèrent la règle écrite en premier.

133 Exemple : if then else En Pascal, on a : ::= if E then I else I | if E then I cette grammaire est ambiguë, mais sera analysée correctement grâce à la préférence au décalage.

134 Langages contextuels Certains langages ne peuvent pas être traités avec les grammaires non-contextuelles. Méthodes: –1. un langage est non-contextuel ssi il peut être reconnu par un programme dont la seule structure de données infinie est une pile.

135 Lemme de pompage –2. Si un langage est non-contextuel, alors il a une longueur k : toute chaîne plus longue que k se décompose en 5 parties u v w x y, et les parties v et x peuvent être répétées le même nombre de fois: u v n w x n y fait aussi partie du langage. Les parties v w x ensemble ont une longueur de k au plus. En pratique on lemploie dans lautre sens : on trouve une série de phrases (une pour chaque k) dans le langage et, quelle que soit la décomposition, le lemme nous obligerait à inclure aussi des phrases incorrectes : on sait alors que le langage ne peut être décrit par une grammaire BNF. S A A u v w x y

136 Exemple {a n b n c n } nest pas non-contextuel: on peut empiler pour chaque a, puis dépiler pour chaque b mais alors on ne sait plus compter les c.

137 Exemple {a n b n c n } nest pas non-contextuel: si l'était, a k b k c k se décomposerait en u v w x y v w x est de longueur k au plus donc il ne peut contenir à la fois des a, des b, et des c donc en répétant v et x, on n'a plus assez du caractère manquant: impossible.

138 Sémantique statique Rôle : Vérifier les propriétés contextuelles statiques, principalement la cohérence des types D Ch.5-6 W Ch. 9

139 Syntaxe abstraite La sémantique statique travaille sur les arbres de syntaxe abstraite. if2 grt plusassign id (x) iconst (1) id (y) id (z) iconst (1) id (z) iconst (2) Exemple : Arbre de syntaxe abstraite

140 CondStat Ifstat E T F id (x) E F iconst (1) +if E compop (>) ETFETF id (y) then E id (z) E T F iconst (1) := Ass else Stat E id (z) E T F iconst (2) := Ass fi Arbre de syntaxe concrète pour le même exemple

141 Sémantique statique 1. un exemple : le typage 2. une technique de spécification : les grammaires attribuées

142 1. Typage Portée Systèmes de types –équivalence –coercition –polymorphisme –surcharge D Ch. 6 W388

143 Portée Les types se déduisent des déclarations Les déclarations sont valides dans leur portée Elles peuvent être cachées par dautres déclarations Chaque langage a ses règles de portée / visibilité.

144 Portée : exemple de Pascal En Pascal, la portée dune déclaration est le bloc dans lequel elle se trouve Il ne peut y avoir quune déclaration de ce nom dans un bloc Une nouvelle déclaration du même nom dans un bloc imbriqué cache la déclaration extérieure Les paramètres sont traités comme des variables locales

145 Portée : exemple dAda La portée dune déclaration commence à la déclaration et se termine à la fin du bloc Si le bloc est un package, elle comprend de plus les packages qui importent celui-ci Une nouvelle déclaration ne cache un nom que si le type est le même

146 Portée : implémentation Pour chaque bloc on crée une table de symboles Chaque table a un lien vers le bloc englobant Chaque déclaration ajoute une entrée dans le bloc (souvent avec des infos: type, taille, déplacement dans le bloc dactivation, etc.) Chaque occurrence didentificateur est recherchée dans la liste des blocs en appliquant les règles du langage.

147 Expressions de types expressions de type : typiquement : –des types de base : booléen, entier, réel, … –des noms de types –des constructeurs de type : tableaux records (structures, enregistrement) fonctions pointeurs D381

148 Règles de typage Chaque langage a ses règles Parfois les règles demandent une vérification dynamique (à lexécution) Un système de typage est sain si toutes les valeurs utilisées à lexécution sont du type calculé statiquement Un langage est typé si le typage impose des conditions sur les programmes. D383

149 Exemple : Pascal le typage de Pascal nest pas sain : –on nest pas obligé de vérifier que les indices de tableaux restent dans les bornes prévues –les variants peuvent être modifiés sans contrôle –les valeurs initiales ne sont pas nécessairement du bon type

150 Exemple de règles Si a est un tableau, alors dans indexation sur a, les expressions des indices doivent avoir le même type de base que le type dindices apparaissant dans la déclaration de a. –exemple: vara : array[1..10] of integer; i : -10.. 0 ; i := a[i] (* correct car le type de base est integer, mais pas recommandé *)

151 Equivalence des types Quand 2 types sont ils égaux ? 2 grandes familles : équivalence par nom : ils doivent avoir la même déclaration (Pascal, Ada) équivalence structurelle : on calcule sils se ramènent à la même structure (C, Algol68, ML) D389

152 Equivalence par nom ex. : Pascal, Ada 1) varx : record a, b : integer end y : record a, b : integer end les types de x, y sont différents (dépend de limplémentation en Pascal74) 2) typer = record a, b : integer end varx : r ; y : r ; les types de x, y sont équivalents 3) varx, y : record a, b : integer end les types de x, y sont équivalents en Pascal, mais différents en Ada

153 Equivalence structurelle deux types sont équivalents si leur structure est la même (intuitivement, sils admettent les mêmes valeurs) vérification en parcourant la structure des types si cycles possibles, attention à la terminaison D390

154 Algorithme structure globale : partition des nœuds du graphe, notée t1 == t2 (les types déjà prouvés équivalents) equiv(t1, t2) si t1 == t2 alors renvoyer vrai sinon si constructeur(t1) <> constructeur(t2) alors renvoyer faux sinon si pour tout i, equiv (fils(i,t1),fils(i,t2))) alors union(t1, t2); renvoyer vrai

155 Particularités de typage surcharge coercition polymorphisme

156 Surcharge (ou « polymorphisme ad hoc ») Un identificateur est surchargé sil peut avoir des significations différentes suivant son type. Exemple en Pascal, en ML, … + : real x real real + : int x int int en Ada : lutilisateur peut surcharger lui-même, par exemple : function "*" (x, y : Matrix) return Matrix ;

157 Résolution de la surcharge + 3 f p int int x int int real x real real real int char char real int A la fin de lalgorithme, chaque fonction doit avoir un seul type sinon : ambiguïté de type Soit vis(k) lensemble des définitions de k visibles, avec leurs types Ex. : vis(« + ») = { int x int int, real x real real } Lalgorithme élimine les types dabord en montant dans larbre puis en descendant. La contrainte est que les arguments doivent avoir le type attendu par la fonction. Ex. : vis(« p ») = { int, real} vis(« f ») = { real real, int int, char char} 3 + f(p) D400 W390

158 Coercition Def : Conversion implicite entre types (insérée par le compilateur) Exemple : En Pascal, un entier peut être employé à la place dun réel dans une expression mais PAS à gauche de := ex. : var r : real ; i : integer ; begin r := i i := r x interdit Notation : typedestnote une coercition vers typedest (notation Ada) Exemple : Dans tous les langages à objets : une variable peut être « coercée » vers tous les types dont son type statique hérite. D396

159 Les coercitions introduisent de nombreuses ambiguïtés, surtout combinées aux surcharges : Exemple : coercition integer real notée real / : integer x integer integer ; / : real x real real ; r := 3/2 peut se comprendre : r := real (3/2) valeur 1. ou r := real (3) / real (2) valeur 1.5 en Pascal : on utilise 2 noms pour la division: / et div. Les langages non-O.O. modernes interdisent les coercitions.

160 Résolution de la coercition Pour résoudre les ambiguïtés de coercition, on se donne des règles de préférence, p.ex.: –préférer une coercition unique à une suite de coercitions –préférer les coercitions le plus haut dans larbre Sil ny a pas de surcharge: insérer des coercitions lorsque nécessaire Avec surcharge : on étend lensemble des typages avec un ordre partiel de préférence Pour Pascal, une passe ascendante suffit.

161 Exemple : Pascal si les 2 opérandes sont entiers : résultat entier si les 2 opérandes sont réels : résultat réel si un opérande est entier, le coercer en réel. exemple: 3+2+5*4.1 = real(3+2) +( real(5) * 4.1 )

162 Polymorphisme (paramétrique) Une définition est polymorphique si elle peut sappliquer de la même façon à tout type. Exemple en ML head : a list a renvoie le 1er élément dune liste où a est une variable qui représente n'importe quel type en Pascal : nil : a Différence par rapport à la surcharge lopérateur a une seule définition : son comportement est uniforme lensemble des types est potentiellement infini. D402 W391

163 Résolution du polymorphisme Pour chaque occurrence dune fonction polymorphe, on introduit une copie de son type avec de nouvelles variables de type Pour chaque variable (de type inconnu), on introduit une nouvelle variable de type. La portée des variables est locale à une ligne. Les variables de type peuvent recevoir des valeurs particulières dans une substitution On résout les contraintes par unification, en calculant la substitution qui permet de les satisfaire. Il y a un résultat le plus général, le type principal. D409 W394

164 Exemple 1 (en ML) On peut écrire une fonction « longueur » qui marche sur des listes de nimporte quel type (impossible en Pascal) fun longueur( [] )= 0 | longueur (x :: l) = longueur(l) +1 où: [] est la liste vide, de type a list : liste de nimporte quel type. : : est le constructeur de liste: (x :: l) est la liste obtenue en mettant x devant l. Il est de type b x b list b list, càd que x doit avoir le même type que les éléments de l. Les types de longueur, x, l sont inconnus a priori. On introduit donc de nouvelles variables to, tx, tl pour leur type. Les contraintes sont: to = (a list) int pour la 1ère ligne to = (b list) int pour la 2ème ligne. On en déduit a = b par unification. D412

165 Exemple 2 (ML) fun append ( [ ] ) (l2) = l2 append (x :: r) (l2) = x :: (append r l2) Contraintes : ta= a list (tl2 e1) tl2= e1 :: : b x b list b list tr= b list tx= b ta= b list (tl3 e2 ) tx= c ta= tr (tl3 c list) e2= c list ta =a list (a list a list) taa listtl2 txtrtl3 ! tx list W395

166 2. Grammaires attribuées basées sur une grammaire BNF on ajoute à chaque nœud de larbre des attributs (p.ex. : type, table de symboles, code, valeur). Ce sont des champs supplémentaires les attributs sont calculés par des règles dattribution associées aux règles de la grammaire

167 Attributs synthétisés et hérités Attribut synthétisé : remonte dans larbre (calculé daprès les attributs de ses fils) Attribut hérité : descend dans larbre (calculé daprès les attributs de son père et/ou de ses frères) Attributs lexicaux (synthétisés) : pour les terminaux, calculés par lanalyseur lexical (p.ex. la valeur dune constante)

168 Exemple : calculatrice Règle de grammaireRègle dattribution S ::= E val : attribut synthétisé de E, T, F, nombre E ::= E 1 +TE.val = E 1.val + T.val E ::= TE.val = T.val T ::= T 1 *FT.val = T 1.val * F.val T ::= FT.val = F.val F ::= ( E ) F.val = E.val F ::= nombreF.val = nombre.val

169 Pour l exemple suivant, il nous faut un type abstrait « table de symboles » : ajout (table, id, def) : table - crée une erreur si id est déjà dans table - dans cet exemple, def est le type de la variable ; on peut mettre d autres infos dans la table (le déplacement, etc.) t 1 + t 2 : tableles défs de t 2 écrasent les défs de t 1 vide : table rech(table, id) : defretrouve la déf courante de id. La table sera synthétisée par les déclarations et héritées par les instructions.

170 Exemple : types dans les déclarations typeh: attribut hérité de L tab: attribut synthétisé de L: table de symboles (nom, type) Règles de grammaireRègles d'attribution D ::= L : TypeL.typeh = Type L ::= id, L 1 L 1.typeh = L.typeh L.tab = ajout(L 1.tab, id.entrée, L.typeh) | idL.tab = ajout(vide, id.entrée, L.typeh) D316

171 Graphe de dépendances Sur un arbre attribué, on ajoute une flèche si un attribut est employé pour calculer un autre Les flèches changent au max. d1 niveau Lordre du calcul doit suivre les flèches Sil y a un cycle, le calcul nest pas possible

172 Exemple : Graphe de dépendances x, y, z : bool; D typeh L tab : T id, typeh L tab bool id, typeh L tab id

173 Exemple : typage Pascal E 0.type = if E 1.type = int and E 2.type = int then int else real | (E 1 ) E 0. type = E 1. type Calcul du type dune expression numérique en Pascal (avec surcharge à la place de coercition) dans la grammaire abstraite type : attribut synthétisé de E : {int, real} Règles de grammaireRègles dattribution E 0 ::= E 1 op E 2 op peut être +, -, *

174 Exemple : arbre abstrait Les grammaires attribuées peuvent aussi servir à calculer larbre abstrait comme attribut de larbre concret. cons(e,g,d) construit un nœud darbre à 2 fils, g et d. a est un attribut synthétisé représentant l'arbre abstrait Règles de grammaireRègles dattribution E ::= E 1 +T E.a = cons(+, E 1.a, T.a) E ::= TE.a = T.a T ::= ( E )T.a = E.a T ::= idT.a = id Pour un DAG, cons renvoie le nœud (si) existant

175 Ordres dévaluation des attributs ordre fixe : donné a priori (p.ex. suit la méthode danalyse syntaxique : LL ou LR) ordre statique : daprès la grammaire attribuée, on précalcule un ordre ordre dynamique : le graphe de dépendance est construit avec larbre; les attributs sont évalués dans un ordre compatible avec le graphe

176 Ordre fixe : grammaire S- attribuées Une grammaire est S-attribuée si elle ne contient que des attributs synthétisés Implémenté dans les analyseurs ascendants (Yacc, Bison, …) Syntaxe: ex: E : E '+' E { $$ = $1 + $3 } ; –lévaluation de lattribut synthétisé $$ se fait dans laction de réduction –$i désigne lattribut du ième symbole D326

177 Grammaires S-attribuées : Implémentation Lanalyseur LR conserve une pile des non- terminaux déjà réduits Il leur associe leur attribut synthétisé Lors de la réduction, les $i sont trouvés en sommet de pile, utilisés pour calculer $$, et remplacés par $$. D328

178 Exemple : calculatrice Règle de grammaireAction dattribution(Yacc) S : E ; E : E + E{ $$ = $1+$3 } | E * E{ $$ = $1*$3 } | ( E ) { $$ = $2} ; F : nombre { $$ = $1} ;

179 Exemple : calculatrice - pile Dans cet exemple, la pile des attributs se comporte comme une pile dévaluation postfixe. D329

180 Ordre fixe : grammaires L- attribuées Une grammaire est L-attribuée si on peut évaluer les attributs lors d'un parcours en profondeur de gauche à droite de larbre danalyse càd: un attribut hérité ne dépend que dattribut hérités plus à gauche ou du père peut simplémenter dans LL(1), LALR(1), etc. D330 W434

181 Exemple : expression LL(1) val : attribut synthétisé h : attribut hérité de E': valeur de l'expression à gauche Règles BNFAttribution E ::= T E'E'.h = T.val E.val = E'.val E' ::= - T E' 1 E' 1.h = E'.h - T.val E'.val = E' 1.val | E'.val = E'.h T ::= nbT.val = nb.val

182 Ex dévaluation dune expression arbre attribué pour lexpression 9 - 5 - 3 E.val=1 T.val = 9 nb.val = 9 E.h = 9 T.val = 5 nb.val = 5 E.h = 4 T.val = 3 nb.val = 3 E.h = 1 val =1

183 L-Attributs dans LL(1) récursif On ajoute les attributs hérités comme paramètres d'entrée de la procédure du non- terminal, les attributs synthétisés comme paramètres de sortie On ajoute des variables locales pour les attributs apparaissant dans une règle du non-terminal D340

184 Exemple : expressions LL(1) Règle LL(1)attribution E' ::= E'.val = E'.h | - T E' 1 E' 1.h = E'.h - T.val E'.val = E' 1.val procedure reste(h: integer; var val: integer); var tval, e1val : integer; begin if eof then val := h else if input^ = - then begin get; (* lit - *) terme(h, tval); reste(h-tval, e1val); val := e1val end else error end

185 L-attributs dans LR On ajoute des actions à lendroit où les attributs doivent être calculés les actions dans un règle (mais pas à la fin) seront traduites par des marqueurs : des non-terminaux à définition vide, avec une action en fin. On accède aux attributs des non-terminaux précédents en remontant la pile ($0, $-1, etc.) D342

186 Exemple : marqueur Une règle S : {$$ = 5} B ; est traduite par S : M B; M : {$$ = 5}; Dans B la valeur de M est accessible comme $0 (cest lélément précédent sur la pile).

187 Ex: table de symboles pour C BNFAttribution insérée dans la règle BNF D ::= T { L.typeh = T.type } L T ::= int { T.type = entier } L ::= {L 1.typeh = L.typeh } L 1, id {L.tab = Ajout(id.nom, L.typeh, L 1.tab) } | id {L.tab = Ajout(id.nom, L.typeh, L 1.tab) } D : déclaration L : liste didentificateurs T : type (se place avant en C) D344

188 Ex: Table de symboles (Bison) D: T {$$=$1} L{$$ = $3 }; T : int{$$ = integer() }; L: L ',' id{$$ = add($3, $ 0, $1)} | id{$$ = add($1, $ 0, empty() ) }; Dans cet exemple laction {$$=$1}nest pas nécessaire: On peut utiliser lattribut synthétisé type pour lattribut hérité typeh

189 Ex: mise en page de formule EQN est un programme de mise en page de formules mathématiques (dites "boîtes") les indices doivent être plus bas et dans une fonte plus petite. P.ex. le texte dentrée E sub 1.a est mis en page comme E 1.a. Les boîtes servent à l'espacement. sub s'associe à droite: E sub i sub j = E sub (i sub j) D23, D333, D347

190 Ex: mise en page de formule tc: attribut hérité: taille des caractères ht: attribut synthétisé: hauteur totale de la boîte D334 S ::= B B ::= B 1 B 2 B ::= B 1 sub B 2 B ::= texte B.tc = 10au départ, taille 10 points S.ht = B.ht B 1.tc = B.tc B 2.tc = B.tc B.ht = max(B 1.ht, B 2.ht) B 1.tc = B.tc B 2.tc = Rétrécir(B.tc)plus petit pour l'indice B.ht = Déplacer(B 1.ht, B 2.ht)p.ex B 1.ht + B 2.ht/2 B.ht = texte.htn B.tchtn: hauteur des lettres

191 Même exemple en Bison %left ' ' %right sub % S : {$$ = 10 } B {$$ = $2}; B : B ' '{$$ = $0} B {$$ = max($1, $4)} | B sub {$$ = Rétrécir($0)} B {$$ = Déplacer($1,$4)} | texte {$$ = $1 * $0}; Avant chaque B, une action met tc dans $$ pour qu'il soit disponible dans B comme $0. On peut omettre {$$=$0} avant le premier B d'une règle pour B. S.ht B.ht B.tc

192 Utiliser les attributs synthétisés Ex: types dans les déclarations (Pascal) La règle D ::= L : T fait que le type nest pas disponible dans L ::= id, L Solution (peu naturelle): mettre le type dans la liste: D ::= id R R ::=, id R | : T T ::= integer |... D350 D id, id : integer R R T

193 Ex: types dans les déclarations (Pascal) D ::= id L D.tab = Ajout(id.nom, L.type, L.tab) L ::=, id L 1 L.type = L 1.type L.tab = Ajout(id.nom, L 1.type, L 1.tab) L::= : T L.type = T.type L.tab = vide Tous les attributs sont synthétisés.

194 Ordre statique Pour certaines grammaires attribuées (l- ordonnées, fortement non-circulaires) on peut calculer un ordre de visite de larbre à partir de la grammaire. Utilisé dans les systèmes FNC-2, GAG, etc.

195 Ordre dynamique Si les conditions précédentes ne sont pas vérifiées, on peut toujours construire larbre danalyse, son graphe de dépendances, et le trier pour faire le parcours. En pratique, cette technique est coûteuse. Utilisé p.ex. dans le système Elegant

196 Génération de Code pour langages impératifs Chap. 2 et 7 à 10 du Dragon s book

197 Plan Expressions Instructions Allocation mémoire –procédures imbriquées

198 1. Expressions sans partage : Pile –Allocation de registres –Réordonnancement avec partage : DAG –utilisation avec pipelines

199 Pile dexpressions Les expressions peuvent se calculer avec une pile en notation postfixe (appelée aussi Polonaise inversée) (p. ex. calculette Hewlett-Packard) Exemple : ((3 * 5) + (7 * 4)) / (3 + 5) Postfixe : 3 5 * 7 4 * + 3 5 + / Parenthèses inutiles chiffres empiler opération prendre les données sur la pile les remplacer par le résultat Ce principe est employé dans les langages à pile PostScript et FORTH, et dans les machines abstraites: P-machine (Pascal), JVM (Java) 5 3 * } 4 7 * 15 } 5 3 * 43 } 8 43 / 28 15 } + } 5

200 Registres Types de registres courants: universels spécialisés: réels flottants données adresses base index PC: program counter (prochaine instruction) CC: codes de conditions Les processeurs RISC ont de nombreux registres universels

201 Allocation de registres D613 W565 Technique simplifiée pour les arbres : 1. réorganisation des calculs 2. allocation des registres par simulation de pile

202 Réordonnancement Idée : on évalue dabord lexpression qui emploie le plus de registres car 1 registre sert pour le résultat. Exemple : + t 1 t 2 4 reg 3 reg } + calcul de t1 ; calcul de t2 ; addition

203 Calcul du meilleur ordre calculer récursivement le nombre de registres optimal : r (t 1 op t 2 ) =max (r 1, r 2 )si r 1 r 2 r 1 + 1si r 1 = r 2 oùr 1 = r(t 1 ) r 2 = r(t 2 ) Le cas de base dépend du type dinstructions de la machine. Pour une architecture load/store, il faut 1 registre. {

204 Exemple 3 2 2 2 abc de 111 11 _ + + _ (a + b) - (c - (d + e)) requiert 3 registres sur une machine load/store

205 type abstrait Pile empiler(P, E)ajoute E sur P dépiler(P)enlève le sommet de P et le renvoie échanger(P)échange le sommet et celui en dessous sommet(P)renvoie le sommet sans changer la pile sommet2(P) renvoie lélément en dessous du sommet

206 Algorithme dallocation pilereg : pile statique de registres libres pilereg nest jamais vide Le sommet de pilereg contiendra le résultat pilereg doit être remis dans létat initial Une pile de temporaires est employée lorsqu il n y a plus assez de registres (> r)

207 Algorithme : cas de base la variable est chargée dans le registre : ProdCode(n) : si n est une feuille (une variable dadresse var): émettre( lw sommet(pilereg), 0(var) ) Note: diffère de D617 car prévu pour une machine load/store (p.ex. MIPS) D617

208 Algorithme : cas 3 sil est plus avantageux de respecter lordre : r1 r2, r>r2 ProdCode(n1); R := dépiler(pilereg); ProdCode(n2); émettre(op, R, R, sommet(pilereg)) ; empiler(pilereg, R);

209 Algorithme : cas 2 sil est plus avantageux dinverser lordre càd si r2 r1, r>r1: ProdCode(n2); R := dépiler(pilereg); ProdCode(n1); émettre( op, R, sommet(pilereg), R); empiler(pilereg, R);

210 Algorithme : cas 4 si les deux sous-termes utilisent plus de registres quil ny en a: r1, r2 r ProdCode(n1); T := dépiler(piletemp); émettre(sw sommet(pilereg), T ); // stocke le résultat en T ProdCode(n2); émettre(lw sommet2(pilereg), T ) ; // charge T émettre(op sommet(pilereg), sommet2(pilereg), sommet(pilereg) ); empiler(piletemp, T)

211 Exemple pour (a + b) - (c - (d + e)) avec 2 registres : lw R1, a lw R2, b add R1, R1, R2 sw R1,T// T := a+b lw R1, d lw R2, e add R1,R1,R2// R1 = d+e lw R2, c sub R1, R2, R1// R1 = c-(d+e) lw R2, T sub R1, R2, R1// R1 = (a+b)-(c-(d+e)) 3 2 2 2 abc de 111 11 _ + + _

212 Bloc de base le graphe de flot de contrôle (ou ordinogramme) donne les successions possibles dinstructions un bloc de base est une suite dinstructions sans branchements entrants ni sortants. D579 W563 B ex: while B do S S

213 Partage de calculs : DAG représente les calculs dun bloc de base les sous-expressions communes sont partagées forme: graphe acyclique : –les feuilles sont des variables ou des constantes –les nœuds sont des opérateurs –les nœuds sont étiquetés par les variables affectées D598 W575

214 Exemple : DAG c := a[i]+1; b := 1-a[i]; b c - + 1 [ ] 1 a i

215 Registres pour DAG En cas de partage, la technique en pile nest pas toujours optimale On divise le DAG en arbres en coupant aux nœuds partagés D619 b c - + 1 [ ] 1 a i t b c [ ] - + a i 1 t t 1

216 Pipelines Dans les processeurs à pipeline, le résultat nest disponible quaprès un délai Il faut insérer des instructions indépendantes Algorithme glouton: – tri topologique du DAG –choix dune instruction parmi les minimales –calcul des collisions Augmente lemploi des registres W580

217 Algorithme pour pipelines Simplification : le délai est 1 cycle. Candidats := minimaux(DAG); Collisions := {instruction précédente }; répéter b := ChoixHeuristique(Candidat \ enCollision(Candidats, Collisions ); si b = erreur alors insérer NOP; Collisions := vide; sinon enlever b de Candidats; Collisions := {b}; ajouter dans candidats les nœuds dont b était le seul prédécesseur jusquà Candidats vide

218 2. Instructions 2.1 conditionnelles 2.2 boucles 2.3 case

219 Instructions conditionnelles La plupart des machines ont un jeu dinstructions qui contient : exemple : MIPS un goto absoluj q :goto q un goto conditionnelbeq $rs $rt q :if $rs = $rt then goto PC+q un goto calculéjr $r :goto $r change le PC (program counter), le registre qui contient l adresse de la prochaine instruction.

220 Instructions conditionnelles code D (e) beq $r, $zero code(st 1 ) j code(st 2 ) if e then st 1 else st 2 code D (e) beq $r, $zero code(st) if e then st (a) deux branches(b) une seule branche Instructions traduisant les instructions conditionnelles

221 Boucles code D (e) beq $r, $zero code(st) j while e do st repeat st until e (a) boucle while(b) boucle repeat code D (e) beq $r, $zero Génération de code pour les boucles

222 Instruction case case e of 0 : st 0 ; 1 : st 1 ;. k : st k end code D e... jr $t1 code D st 0 j exit code D st 1 j exit code D st k j Lk...... j L2 j L1 j...... Laisse la valeur du sélecteur dans un registre $re Branchement indexé vers la fin de la Table des branchements Branchement vers la fin de linstruction Table des branchements q : exit : L0: Lk :

223 3. Allocation de mémoire les variables ont deux emplois différents : –à gauche de « := », cest une adresse –à droite de « := », cest la valeur stockée à cette adresse le langage source admet-il: –la récursivité ? si oui: nouvelles variables à créer –limbrication de procédures ? si oui : retrouver les liens

224 Allocation La mémoire est habituellement divisée en: –code : lecture seule –constantes : lecture seule –variables globales : adresse statique –pile : pour les variables locales de procédures récursives –tas : pour les autres variables dynamiques

225 Tableaux En Pascal les dimensions dun tableau sont statiques Les extensions de Pascalont des tableaux Algol-68taille dynamique Ada C } var : array [l 1.. u 1,..., l k.. u k ] of la ième dimension d i = u i - l i + 1 (si u i > l i ) Rangement par ligne: le dernier indice varie dabord: a[1,1] a[1,2] a[1,3] a[2,1] a[2,2] a[2,3] par colonne le premier indice varie dabord: a[1,1] a[2,1] a[1,2] a[2,2] a[1,3] a[2,3]

226 Tableaux : indices Pour accéder à un élément a[e,f,g] on calcule ladresse a+ (e-l 1 )* d 2 *d 3 + (f-l 2 )*d 3 + (g-l 3 ) en Pascal seuls e,f,g sont dynamiques on peut précalculer la partie statique Le schéma de Horner limite les multiplications : e* d 2 *d 3 + f *d 3 + g = (e* d 2 + f) *d 3 + g

227 Records En Pascal tous les types ont une taille statique pour chaque champ on a un déplacement relatif Ex.record a : array [1.. 5, 1.. 5] of boolean1 byte par bool. x : integer1 byte par int. y : real1 byte par real end p.ex. 0 25 26 27 Les machines ont souvent des contraintes dalignement : p.ex. un réel doit avoir une adresse multiple de 4 on doit laisser du remplissage ou réordonner les champs Traduction d un accès à un champ code G (v.c i ) = code G (v) ; # laisse l adresse de v dans un registre $t add $t, (c i ), $t #laisse l adresse du champ dans $t. # (c i ) est le déplacement de c i

228 Pointeurs Les cases créées par new ne peuvent pas être allouées sur la pile car elles vivent plus longtemps que la procédure qui les a créées. On réserve une zone spéciale, le TAS. La gestion du tas - comment récupérer la place lors dun dispose ? - risque de fragmenter la mémoire si plusieurs tailles p.ex. : organisation en pools où toutes les cases ont la même taille. PILETAS SP D438 W25

229 Procédures récursives Chaque appel à une procédure récursive doit avoir de nouvelles variables locales Lallocation est LIFO, donc en pile Les instances de procédures sont donc stockées dans une pile. Souvent un registre SP pointe vers le sommet de la pile.

230 D433 Pile de contrôle L exécution des procédures (récursives) est imbriquée représentable par une pile Le contenu de la pile représente une branche de l arbre d activation. La pile contient des blocs d activation. Le registre FP (frame pointer) point sur le bloc courant, sommet de la pile. Chaque bloc contient: des temporaires (pour l évaluation d expressions). les variables locales; l état des registres à restaurer, en particulier: l adresse de retour est la valeur du PC (program counter) le lien d accès ou prédécesseur statique (si imbrication) le lien de contrôle ou prédécesseur statique (valeur du FP) pointe vers le bloc appelant les arguments la valeur de retour (pour une fonction)

231 Protocole d appel Répartit les rôles de l appelant et de l appelé. Par exemple: 1. l appelant crée le bloc d activation 2. l appelant évalue les arguments et les met dans les registres ($a) ou dans le bloc 3. l appelant calcule le lien d accès en suivant le sien. 3. l appelant sauve le PC et saute au début de l appelé 4. l appelé alloue et initialise les variables locales 5. l appelé commence son exécution (qui calcule la valeur de retour) Au retour: 1. l appelé restaure les registres, en dernier le PC (saut de retour) D446-449

232 Accès aux noms non locaux Algol, Pascal, Ada, ont des procédures imbriquées Ils emploient la portée statique : les variables sont recherchées dans le texte englobant la portée dune variable est le sous-programme où elle est déclarée On emploie la déclaration la plus locale D453

233 Procédures Distinguer limbrication statique du texte des procédures dynamique des appels de procédure une variable a une distance dimbrication statique : procédure p var x : integer procedure q... x... end 1 niveau dimbrication statique L imbrication de procédures n existe pas en C, FORTRAN, Java,...

234 proc p(a) var b; var c proc q var a var q proc r var b b a c. a b q proc s var a. a q a q 0 1 2 0 0 1 1 0 Les flèches montrent pour chaque utilisation de variable, la définition associée Les nombres indiquent la distance dimbrication des occurrences de variables.

235 Prédécesseurs statiques Le lien daccès (ou prédécesseur statique) pointe vers lactivation la plus récente de la procédure englobante program h ; var i : integer ; proc p var a proc r var i : real i := i/2 ; a := 5 if i > 0 then i := i - 1 ; p else r fi i := 2 ; p ; p end. h p p p r p r Liens daccès Figure : Un programme et son arbre d activation (ou dappels). Les crochets donnent l imbrication des procédures.

236 Accès non local Chaque occurrence de variable est identifiée par sa différence dimbrication d et son déplacement o Pour trouver son adresse, on suit d liens daccès (donne le bloc dactivation de sa déclaration) et on ajoute o. D461

237 Mise à jour Lors dun appel, le nouveau lien daccès est obtenu en suivant d liens daccès de lappelant.

238 Exemples proc p proc q q proc r proc p q proc q p proc r proc q proc p q p q * p q d = 0 (a) d = 1 (b) d = 2 (c) * p q MP SP r * q q MP SP r * p *

239 Passage de paramètres Diffère dun langage à lautre Principaux types : –par valeur –par référence (ou par variable) –par copie (in out) –par nom D467

240 Passage par valeur Le paramètre est comme une variable locale Lappelant évalue la valeur de largument et le place comme valeur initiale du paramètre

241 Passage par référence Ladresse de largument est passée. En Pascal: noté par var

242 Exemple procedure Troquer(var x, y : integer); var t : integer; begin t := x; x := y; y := t end; Naurait aucun effet en passage par valeur !

243 Passage par copie Utilisé p.ex. en Ada (mode in out) La valeur de largument est copiée dans le paramètre ; au retour la valeur du paramètre est copiée dans largument Même effet que le passage par référence sauf en cas de synonymie. D470

244 Exemple program ValeurResultat(output); var a : integer; procedure Hasardeuse(var x:integer); begin x:=2 ; a := 0 end; begin a:=1; Hasardeuse(a) ; writeln(a) end. a=0 si passage par référence, a=2 si passage par copie. D471

245 Passage par nom Remplacement textuel du paramètre par largument (comme pour une macro) Utilisé seulement en Algol-60. D471

246 Exemple procedure Troquer(x,y:integer); var t:integer; begin t := x; x := y; y := t end; Troquer(i, t[i] ) met i dans t[t[i]] !

247 Passage de fonctions en paramètre Pour les langages à portée statique (p.ex. Pascal): On doit passer ladresse de début du code et le lien daccès

248 Exemple : fonction en paramètre Program HP proc p(fune h) h proc q func f p(g) p(f) func g q HP q p f q p f g p (a) Un programme avec fonction en paramètre (b) situation de la pile après appel de p(f) et (en pointillé) après appel de h (c) situation de la pile après appel de p(g) et (en pointillé) après appel de h

249 Sémantique dénotationnelle Idée : Le sens dun programme est un objet mathématique (souvent, une fonction)

250 Quest-ce que cest ? La sémantique donne le sens dun langage Pour un langage de programmation, elle permet de prévoir le comportement du programme Pour un langage séquentiel, on suppose que le seul comportement observable est le résultat final.

251 A quoi ca sert ? La sémantique permet de: –décider ce que doit faire un programme dans des cas complexes –calculer si des programmes sont équivalents, ce qui permet à un compilateur de remplacer lun par lautre. –dériver la plupart des analyses de programmes –construire des compilateurs fiables

252 Types de sémantique Sémantique opérationnelle : décrit comment un programme peut sexécuter Sémantique dénotationnelle : donne un objet (p.ex. une fonction des données vers les résultats) comme sens dun programme Sémantique axiomatique : donne des règles pour raisonner sur les programmes

253 Liens entre types de sémantique les 3 types de sémantique ont leur utilité: –la sémantique opérationnelle facilite la construction de compilateurs –la sémantique dénotationnelle donne les concepts du langage –la sémantique axiomatique est la plus utile pour les programmeurs On peut passer de lune à lautre en démontrant leur équivalence.

254 Notation lambda ( ) But : une notation pour les fonctions Ex. : la fonction qui met au carré (sqr en Pascal) x. x * x est une déclaration de paramètre qui suit les règles de visibilité : x. x + sqr (( x. x + x) (x + 2)) On peut simplifier grâce aux règles : : ( x. E) (A) se simplifie en E [A x] E où toutes les occurrences libres de x sont remplacées par A : ( x. E(x)) se simplifie en E, si E na aucune occurrence libre de x

255 Exemple de simplification x. x + sqr (( x. x + x) (x + 2)) portée : x. x + ( x. x * x) (( x. x + x) (x + 2)) Il y a deux endroit où sapplique : 1, 2 1 x. x + (( x. x + x) (x + 2)) * ( x. x + x) (x + 2) 3 x. x + (( x + 2) + (x + 2)) * ( x. x + x) (x + 2)) 4 x. x + (((x+ 2) + (x + 2)) * ((x + 2) + (x + 2))) = x. 4x 2 + 9x + 16 si on emploie les simplifications arithmétiques. On pourrait aussi appliquer les règles dans un autre ordre : on arrive au même résultat (Théorème de Church-Rosser) Ex. : 2 x. x + ( x. x * x) (x+2 + x+2) 1 x. x + (x+2 + x+2) * (x+2 + x+2) 12 def. 34 4 1

256 Domaines sémantiques Quel objet mathématique représente le sens dun programme ? Ceci dépend du langage considéré, et du sens quon lui accorde. Ex. : Pour Pascal, on convient habituellement que : - il devrait être déterministe (OK si on évite les effets de bord dans les fonctions) - on ne considère que les états initiaux et finaux des fichiers le sens est une fonction des états initiaux vers les états finaux. Ex. : Pour les langages concurrents (Ada, LOTOS, CSP, CCS,...) les opérations intermédiaires visibles comptent aussi : le sens est un objet plus compliqué (p.ex. des arbres)

257 Compositionnalité On veut donner un sens à chaque partie de façon à ce que le sens dun composé se déduise du sens de ses composants. Avantages : Si deux composants ont le même sens, on peut toujours remplacer lun par lautre (p.ex. compilateur optimisant) La définition de la sémantique suivra la structure de la syntaxe.

258 Exemple : séquence en Pascal Le sens d'une instruction S, noté [[ S ]], est une fonction de l'état initial vers l'état final Alors le sens d'une séquence est la composition fonctionnelle du sens de ses composants: [[ S 1 ; S 2 ]] = x. [[S 2 ]] ([[ S 1 ]] (x)) = [[ S 2 ]] ° [[ S 1 ]]

259 Non-terminaison Certains programmes bouclent pour certaines données Ex. : la fonction factorielle pour les nombres négatifs pour représenter cela, on ajoute une valeur spéciale « bouclage » ou « bottom » à lensemble des résultats. Comme ce résultat peut être largument dun autre appel, il faut aussi lajouter dans les données.

260 Strict Si un paramètre est nécessaire pour évaluer une fonction, dès que l'évaluation du paramètre ne termine pas, l'appel de fonction ne termine pas non plus. Def. : une fonction F est stricte dans son ième argument si F(x 1,, …, x i-1,, x i+1,...) =

261 Exemple: Pascal Presque toutes les fonctions de la sémantique de Pascal sont strictes, parce qu'on évalue tous les paramètres avant un appel. Exception: les instructions de contrôle p.ex. if ne nécessite pas d'évaluer une des deux parties.

262 Etat On représente ici l'état d'un programme par une fonction des variables vers leur valeur Pour Pascal, il faudrait aussi représenter les instances actives de procédures et leur variables locales

263 Sémantique des instructions Pascal [[ S 1 ; S 2 ]] = [[ S 2 ]] ° [[ S 1 ]] [[ skip ]] = x. x [[ if E then S 1 else S 2 ]] = x. if ([[ E ]] (x) = true) then [[ S 1 ]] (x) else [[ S 2 ]] (x) [[ V := E ]] = x. i. if i = V then [[ E ]] (x) else x(i) [[ while E do S ]] = x. if ([[ E ]] (x) = true) then [[while E do S]] ° [[ S ]](x) else x

264 Récursivité la définition du while est récursive, mais pas bien fondée. Comment calculer son sens ? Ce doit être une solution de: W = x. if [[ E ]] (x) then W ° [[ S ]](x) else x. Cette équation peut avoir plusieurs solutions, mais une seule est intuitive. Les solutions sont appellées points fixes de: F = W. x. if [[ E ]] (x) then W ° [[ S ]](x) else x.

265 Ordre dinformation Pour comparer les solutions et choisir la plus naturelle, on définit un ordre partiel X Y se lit « Y contient au moins linfo de X » ou « X approxime Y »

266 Bouclage Considérons le programme f(x) = f(x)+1 Cette équation na pas de solution dans les nombres Le programme boucle à lexécution On ajoute une valeur spéciale qui représente le fait quun programme boucle. = +1 est alors la seule solution.

267 Ordre partiel Un ordre partiel est une relation: Réflexive: X X Transitive: X Y et Y Z implique X Z Antisymétrique: X Y et Y X implique X=Y

268 Supremum Un majorant de Y est un élément b plus grand que tous ceux d'Y: b Maj(Y) = y Y, y b Un majorant plus petit que les autres est le supremum de Y s=sup(Y) ssi s Maj(Y) et m Maj(Y), s m

269 Chaîne Une chaîne est une suite croissante (x i ) i N telle que x i x i+1

270 Domaine Un domaine ou ordre partiel complet (CPO) est un ensemble X muni d'un ordre partiel X contient un minorant Toute chaîne de X a un supremum Intuition: Un programme qui boucle ne fournit aucune info: X On peut représenter linfo accumulée par un programme par le supremum de ses calculs partiels

271 CPO plat Pour les valeurs classiques, on ajoute juste en dessous: x y ssi x = ou x =y Z Par exemple: les entiers avec, noté Z, est obtenu ainsi. -4-3-2-101234 Exercice: est-ce bien un CPO?

272 CPO Union disjointe Si on a deux CPOs A, B on forme le type union disjointe de A et B en rajoutant encore un en-dessous: A+B B A Indique une valeur inconnue de A+B Indique une valeur inconnue de B AB

273 Ordre ponctuel Pour les fonctions, on emploie lordre ponctuel: f D C g ssi x D, f(x) C g(x) Lélément minimum est la fonction qui renvoie toujours : D C = x. C

274 Fonction monotone Une application entre CPOs est monotone si elle préserve l'ordre : Si x y alors f(x) f(y)

275 Théorème de Tarski Si F est une application monotone dun CPO dans lui-même, elle a un plus petit point fixe, noté fix(F).

276 Continuité pour lordre Une fonction f est continue si elle préserve les suprémums: Pour toute chaîne C: f(sup (C) ) =sup(f (C)) Attention cette continuité nest pas celle de la topologie usuelle sur les nombres rééls! Avec cette déf, toute fonction continue est monotone.

277 Théorème de Scott Si f est une application continue dun CPO dans lui-même, son plus petit point fixe peut se calculer en itérant f à partir de, f( ), f(f( )), f(f(f( ))), … et en prenant le supremum fix(f) = sup i (f i ( )) où f i (x) note f(f(…f(x)))

278 Preuve 1.Ce supremum est un point fixe = f 0 ( ) f( ) puisque CPO f i ( ) f i+1 ( ) par monotonie (f i ( )) i N est une chaîne, donc a un supremum s = sup i (f i ( )) f(s) =f(sup i (f i ( ))) = sup i (f(f i ( ))) = s

279 Preuve (2) Il est le plus petit: Soit v un autre point fixe v puisque CPO f i ( ) f i (v) = v par monotonie càd v majorant s v def. supremum

280 Continuité Pour appliquer le théorème de Scott, il faut que la fonction soit « continue » En pratique: toute fonction écrite en ML, Pascal, … est continue. Schéma de preuve: Les fonctions de base sont continues La composition préserve la continuité Un point fixe dune fonctionnelle continue est continu.

281 Exemple Quel est le sens de la fonction récursive ML: fun f(b) = if b then 3 else 2*f(b) f : bool int Cest le plus petit point fixe de H: H f b = if b then 3 else 2*f(b) On le calcule par la chaîne: H = b. if b then 3 else H(H ) = b. if b then 3 else Donc, i>0, H i = b. if b then 3 else = fix H = [[f]]

282 Règles de simplification Si f est stricte: f(if b then T else E) = if b then f(T) else f(E)

283 Exemple de point fixe Quel est le sens de f n = n+(if n=0 then 0 else f(f(n-1)) R: le plus petit point fixe de H f n = n+(if n=0 then 0 else f(f(n-1)) H 0 = H 1 n = n+(if n=0 then 0 else ) = if n=0 then 0 else H 2 n = n+(if n=0 then 0 else H 1 (if n-1=0 then 0 else )) = n+(if n=0 then 0 else if n=1 then 0 else ) = if n=0 then 0 else if n=1 then 1 else …

284 Exemple de point fixe H 3 n = H(H 2 ) n = n+(if n=0 then 0 else H 2 (H 2 (n-1)) = n+(if n=0 then 0 else H 2 (if n-1=0 then 0 else if n-1=1 then 1 else )) = if n=0 then n+0 else if n=1 then n+ H 2 0 else if n=2 then n+ H 2 1 else = if n=0 then 0 else if n=1 then 1 else if n=2 then 2+ H 2 1 else = if n=0 then 0 else if n=1 then 1 else if n=2 then 3 else

285 Exemple de point fixe H 4 n = H(H 3 ) n = n+(if n=0 then 0 else H 3 (H 3 (n-1)) = n+(if n=0 then 0 else H 3 (if n-1=0 then 0 else if n-1=1 then 1 else if n-1=2 then 3 else )) = if n=0 then 0 else if n=1 then n+ H 3 0 else if n=2 then n+ H 3 1 else if n=3 then n+ H 3 3 else = if n=0 then 0 else if n=1 then 1 else if n=2 then 3 else if n=3 then else = if n=0 then 0 else if n=1 then 1 else if n=2 then 3 else = H 3 n : le point fixe est atteint

286 Exemple de point fixe limite H h n = if n=1 then 1 else h(n-1)+1 H = n. if n=1 then 1 else H 2 = n. if n=1 then 1 else if n=2 then 2 else H i = n. if 0<n i then n else Preuve par induction: cas 0: H i = n. cas i+1: H(H i ) = n. if n =1 then 1 else if 0<n-1 i then (n-1)+1 else n. if 0<n i+1 then n else Limite: sup H i = n. if 0<n then n else

287 Interprétation Abstraite Linterprétation abstraite est une technique pour calculer des propriétés dun programme. En principe ces propriétés se déduisent de la sémantique du programme, mais celle-ci est trop coûteuse à calculer. On ne calcule donc que les propriétés qui nous intéressent; Le plus souvent ceci amène à faire des approximations. La sémantique sert à trouver et prouver ces approximations. W447

288 Interprétation Abstraite: cadre 1. Une sémantique dénotationnelle compositionnelle [[. ]] : programme Domaine standard A Chaque construction f du langage a sa sémantique f A 2. On veut construire une sémantique abstraite compositionnelle qui retient les propriétés à calculer Abs : programme Domaine abstrait B avec une relation «est représenté par » entre les deux domaines : - compatible : si a b, alors f A (a) f B (b) N - continue : si sup i (a i ) = a, sup i (b i ) = b, i N a i b i, alors a b W470

289 Exemple: Signe On veut que le compilateur calcule, si possible, le signe des expressions entières Z Domaine standard = Z Domaine abstrait = {0, p, n, ?} 0 représente 0: 0 p représente les nombres positifs: z p ssi z>0 n représente les nombres négatifs: z n ssi z<0 ? représente tout le domaine abstrait: z n0p?n0p?

290 Exemple: Signe: fonctions abstraites On construit les meilleures approximations des 4 opérations: *p0 n? pp0 n ? 00000 n n0p? ??0?? +p0n? ppp?? 0p0n? n nn? ????? p0n ? p?pp? 0n0p? n nn?? ????? /p0 n ? pperr n ? 00err00 n n errp? ??err?? est continue (les chaînes sont finies).

291 Exemple: Signe: point fixe i := 1; f := 1; while i<v do begin f := i*f; i := i+1; end Le compilateur utilise des états abstraits Si v est positif à lentrée de ce programme, il calcule que f et v seront positifs à la sortie. Avant la boucle: Après la boucle, par point fixe: ifv ppp ifv ppp

292 Dautres applications de linterprétation abstraite Linterprétation abstraite permet au compilateur de calculer des réponses approchées à des questions comme: Des variables sont-elles synonymes ? Des structures de pointeurs ont-elles des cellules partagées ? Une fonction est-elle stricte ? Une fonction a-t-elle des effets de bord ? Une variable a-t-elle un effet sur une autre ? Combien de temps prend un programme ? Calculs sur les grammaires (voir plus loin)

293 Sémantique des grammaires non contextuelles Le sens dun non-terminal X dans une grammaire G = (S, V N, V T, P) est lensemble des textes corrects pour X, càd {w V T * | X * w }. Les règles d'une grammaire sont récursives: la théorie du point fixe convient donc pour leur donner un sens. Si on suppose qu'on a donné un sens à chaque non-terminal (càd on a une fonction de V N P (V T *) ) alors on peut l'utiliser dans les règles de la grammaire pour calculer un nouveau sens. Le plus petit point fixe donne la sémantique de chaque non-terminal. La sémantique du symbole initial donne le langage de la grammaire.L'ordre utilisé est l'ordre sur les vecteurs d'ensembles: A 1 (X) A 2 (X) ssi X V N, A 1 (X) A 2 (X)

294 Continuité Toutes les grammaires définissent une fonction "continue" pour l'inclusion. En effet, le supremum pour l'inclusion est simplement l'union (infinie). Les grammaires BNF sont écrites avec les 4 opérateurs: union,. suivi de, a symbole terminal, chaîne vide. On peut montrer qu'ils sont continus, p.ex.: Donc ( i L i ).M = {x.y | i. x L i et y M} = i ( L i.M) Donc le langage peut se calculer par point fixe.

295 Exemple La grammaire P A ::= a A c | B B ::= b B | C C ::= | C = {A=, B=, C= } [[P]] = {A=, B=, C= } [[P]] 2 = {A=, B=, C= } [[P]] 3 = {A=, B= {,b}, C= } [[P]] 4 = {A= {ac,,b}, B= {,b,bb}, C= } On généralise: [[P]] n = { A = {a i b j c i | i+j n-3}, B = { b j | j n-2}, C= si n=0, C= sinon } On fait la preuve par induction Puis le passage à la limite: fix [[P]] = { A = {a i b j c i }, B = { b j }, C= }

296 Interprétation abstraite de grammaires Le calcul des k premiers symboles terminaux (voir chap.2) est une interprétation abstraite. L'opérateur. (suivi de) est donc abstrait en une concaténation bornée à k symboles. Les autres sont inchangés. Le domaine abstrait des langages bornés à k caractères a des chaînes finies, donc le calcul du point fixe converge finiment.

297 Sémantique opérationnelle Sémantique opérationnelle = on donne le sens du programme en donnant un ensemble dexécutions possibles. + Avantages : + intuition claire + facilité de construire un interpréteur + traitement du non-déterminisme Inconvénients fréquents : non compositionnel : on ne peut pas donner de sens à certaines parties peu abstrait : difficile de prouver que 2 programmes sont équivalents. difficile de construire un compilateur optimisant.

298 Sémantique Opérationnelle Structurée On évite les inconvients habituels en ajoutant: –Compositionalité : On donne des règles dinférences qui donnent les exécutions possible s en fonction de celles des composants. –Abstraction : On ajoute des règles de similarités disant quelles exécutions sont équivalentes.

299 Système de déduction Une règle dinférence est de la forme : prémisses conclusion « Si on a prouvé F 1... F n on peut déduire F 0 ». (Ici les F i décriront des exécutions possibles) Sil ny a pas de prémisses, on lappelle un axiome. Une règle peut contenir des méta-variables càd des variables qui représentent nimporte quel texte dune catégorie syntaxique donnée. On lappelle alors un schéma de règle. Une preuve est un arbre fini composé de règles dinférences ; elle a une conclusion à la racine, appelée théorème. La théorie dun système de déduction est lensemble des théorèmes.

300 Exemple : un système de déduction pour la syntaxe Les formules sont de la forme T : V N (le texte T dérive de V N ). Chaque règle non contextuelle, par exemple S ::= if E then S1 else S2 peut se traduire en une règle dinférence : E : expression S1 : instruction S2 : instruction if E then S1 else S2 : instruction

301 Exemple : déduction syntaxique Une preuve dans ce système est un arbre syntaxique : Les règles dinférences peuvent aussi vérifier des conditions de contexte, p.ex. les types :

302 Sémantique Opérationnelle Structurée : Définition Les formules qui nous intéressent: e 1 e 2 « dans létat e 1 par un pas dexécution on arrive dans létat e 2 »

303 Etats Les états doivent contenir linformation nécessaire à lexécution : –la valeur des variables –le point dexécution dans le programme (ici, on le représente par la partie du programme restant à exécuter) –létat de la pile de récursion –etc.

304 Exemple : expressions Pascal on ne traite dabord que des expressions sans variables et sans effet de bord, donc la mémoire nest pas (encore) nécessaire.

305 Règles de congruence : on peut simplifier n importe quelle sous-expression en Pascal : où f est un opérateur ou un appel de fonction de calcul : pour chaque opérateur Pascal, on donne des règles pour calculer la valeur du résultat à partir de la valeur des arguments –par exemple : not true false not false true

306 Exemple 7 + (4 * 5) 7 + 20 27 le premier pas est la règle de congruence pour le 2ème argument; sa prémisse est justifiée par la règle de calcul pour *. le second pas est le calcul de +.

307 Expressions avec mémoire Un état a maintenant 2 composantes: –lexpression à évaluer; –létat de la mémoire : une fonction Identificateur Valeur de congruence : on peut simplifier une sous-expression de calcul : (not true, m) (false, m) (not false, m) (true, m) de recherche de valeur en mémoire: (id, m) (m(id), m)

308 Exemple : expression congruence recherche congruence calcul * congruence recherche congruence calcul * congruence calcul +

309 Instructions affectation : –dabord évaluer lexpression –ensuite modifier létat pour la variable avec la constante ainsi calculée conditionnelle : –dabord évaluer lexpression –ensuite évaluer la branche choisie (2 cas) boucle : –créer une copie de lexpression –lévaluer (en gardant l expression du while pour les itérations) séquence : –évaluer la première instruction –lorsquelle se termine exécuter la 2ème instruction

310 Instructions Affectation :1. (e, m) (e, m ) congruence (id := e, m) (id := e, m ) calcul := 2.(id := n, m) (skip, update (id, n, m)) instruction vide Conditionnelle :1. (e, m) (e, m) (if e then S 1 else S 2 m) (if e then S 2 else S 2 m) 2.1 (if true then S 1 else S 2, m) (S 1, m) 2.2 (if false then S 1 else S 2, m) (S 2, m) abréviation (if e then S 1, m) (if e then S 1 else skip, m) Boucle :(while e do S, m) (if e then begin S ; while e do S end, m) Séquence : (S 1, m) (S 1, m) (S 1 ; S 2, m) (skip ; S, m) (S, m) e : expr id : identificateur n : const

311 Système de transitions Les règles de la SOS définissent une machine à états infinis, quon appelle aussi un système de transitions. On peut aussi la voir comme un graphe.

312 Questions importantes 1. Il y a-t-il plusieurs suites de flèches partant dun même état ? (déterminisme) 2. Certaines de ces suites sont-elles infinies ? (terminaison) 3. Aboutissent-elles toutes au même état ? (confluence) 4. Quelle forme ont les états finals ? Les état finals corrects ? Déf. : C final = il ny a pas de C : C C (forme normale) 5. Les flèches préservent-elles les types ?

313 Equivalence sémantique La SOS détaille les calculs, donc peu de programmes sont équivalents Deux programmes P,Q sont équivalents ssi: –ils mènen t aux mêmes états finaux –ils bouclent dans les mêmes circonstances : p *q signifie quun chemin dexécution mène de p à q. p signifie quun chemin dexécution infini part de p.

314 Exemple if e then S 1 else S 2 if not(e) then S 2 else S 1 1.Si (e, m) * (true, m) alors1) (if e then S 1 else S 2, m) * (if true then S1 else S2, m) (S 1, m) 2) (e, m) * (true, m) (not(e), m) * (not(true), m) * (false, m) (if not(e) then S 2 else S 1, m) (if false then S 2 else S 1, m) (S 1, m) 2. si (e, m) * (false, m) : preuve symétrique congruence 2.1 congruence calcul not congruence 2.2.

315 Sémantique dénotationnelle Donne pour chaque partie de programme, un objet qui est son sens: p.ex. un programme déterministe séquentiel dénote une fonction Compositionnelle si le sens dun programme dépend du sens de ses parties mais pas de leur forme. Abstraite si le sens ne conserve que linformation quon peut observer.

316 Compositionalité Si S1, S2 sont deux instructions dont le sens de chacune est une fonction des états de mémoire (de départ) vers les états de mémoire darrivée : f1, f2, alors la sequence S1; S2 a comme sens la fonction f1(f2(i)) pour tout état de départ i.

317 Sémantique axiomatique Donne des règles pour construire des programmes Les règles peuvent être démontrées à partir d une autre sémantique (p.ex. opérationnelle) Notation : {pre} P {post} signifie que si P démarre dans un état de mémoire satisfaisant pre, alors il se termine dans un état de mémoire satisfaisant post. pre post

318 Exemple de règles règle pour laffectation: { post [e/x] } x := e {post } la règle est valide si x ne peut être accédée que par ce nom (pas de synonymie) règle pour le if: { pre et b} t {post } { pre et non b} e {post } { pre } if b then t else e {post }


Télécharger ppt "INFO 2108 Syntaxe et sémantique des langages de programmation Pierre-Yves Schobbens Bureau 409 081/72 49 90 rue Grandgagnage 21 5000 Namur"

Présentations similaires


Annonces Google