Algorithmique et Programmation Fonctionnelle (APF) Algorithmique et Programmation Fonctionnelle (APF) RICM3 Cours 5 : Analyse syntaxique et flots Benjamin Wack Polytech 2014 - 2015 1 / 32 Algorithmique et Programmation Fonctionnelle (APF) La dernière fois I Preuves I Évaluation 2 / 32 Algorithmique et Programmation Fonctionnelle (APF) Plan Type unit Langages (cf Cours de Michael Périn) Analyse syntaxique Flots Écriture d’un analyseur (parser) 3 / 32 Algorithmique et Programmation Fonctionnelle (APF) Type unit Plan Type unit Langages (cf Cours de Michael Périn) Analyse syntaxique Flots Écriture d’un analyseur (parser) 4 / 32 Algorithmique et Programmation Fonctionnelle (APF) Type unit Type unit : définition Un type somme avec un seul constructeur noté () 5 / 32 Algorithmique et Programmation Fonctionnelle (APF) Type unit Type unit : définition Un type somme avec un seul constructeur noté () Il apparaît dans le type des : I Modifications de tableaux t.(2) <- 5 I Entrées / Sorties print_int : int -> read_int : unit -> I Affichages graphiques unit int 5 / 32 Algorithmique et Programmation Fonctionnelle (APF) Type unit Type unit : définition Un type somme avec un seul constructeur noté () Il apparaît dans le type des : I Modifications de tableaux t.(2) <- 5 I Entrées / Sorties print_int : int -> read_int : unit -> I Affichages graphiques I unit int De manière générale toute instruction qui « modifie » sans « calculer » : effet de bord Pourquoi ? 5 / 32 Algorithmique et Programmation Fonctionnelle (APF) Type unit Type unit : utilité Quand le calcul est effectué, qu’a-t-on appris ? I Information 1 : valeur du résultat I Information 2 : le calcul est terminé 6 / 32 Algorithmique et Programmation Fonctionnelle (APF) Type unit Type unit : utilité Quand le calcul est effectué, qu’a-t-on appris ? I Information 1 : valeur du résultat I Information 2 : le calcul est terminé Avant le calcul que sait-on ? I Le type du résultat donc, pour un type somme : les différentes valeurs possibles 6 / 32 Algorithmique et Programmation Fonctionnelle (APF) Type unit Type unit : utilité Quand le calcul est effectué, qu’a-t-on appris ? I Information 1 : valeur du résultat I Information 2 : le calcul est terminé Avant le calcul que sait-on ? I Le type du résultat donc, pour un type somme : les différentes valeurs possibles Cas du type unit I La valeur du résultat est connue d’avance ! I Ce qu’on apprend : “la calcul est fini” 6 / 32 Algorithmique et Programmation Fonctionnelle (APF) Langages (cf Cours de Michael Périn) Plan Type unit Langages (cf Cours de Michael Périn) Analyse syntaxique Flots Écriture d’un analyseur (parser) 7 / 32 Algorithmique et Programmation Fonctionnelle (APF) Langages (cf Cours de Michael Périn) Définitions Soit un ensemble T I mot = séquence (éventuellement vide) d’éléments de T I T ∗ = ensemble des mots sur T Représentation 1. T ∗ = 2. T ∗ S n∈N T n, avec T n = [1..n] → T = T list La concaténation sur T ∗ est : I notée par juxtaposition I associative (ab)c= a(bc) 8 / 32 Algorithmique et Programmation Fonctionnelle (APF) Langages (cf Cours de Michael Périn) Définitions I I I I Langage sur T = sous-ensemble de T ∗ . Lexème = unité lexicale ou mot. Analyse lexicale : Découpage d’une suite de T en mots. Analyse syntaxique : Organisation des lexèmes en phrase. 9 / 32 Algorithmique et Programmation Fonctionnelle (APF) Langages (cf Cours de Michael Périn) Définitions I I I I Langage sur T = sous-ensemble de T ∗ . Lexème = unité lexicale ou mot. Analyse lexicale : Découpage d’une suite de T en mots. Analyse syntaxique : Organisation des lexèmes en phrase. Exemples : I Langue naturelle I I Tl = {0 a0 , 0 b0 , . . . 0 z0 , 0 A0 . . . 0 Z0 , 0 0 } Les lexèmes légaux sont : les mots du dictionnaire. L’analyse syntaxique vérifie qu’il y a un sujet, un verbe... 9 / 32 Algorithmique et Programmation Fonctionnelle (APF) Langages (cf Cours de Michael Périn) Définitions I I I I Langage sur T = sous-ensemble de T ∗ . Lexème = unité lexicale ou mot. Analyse lexicale : Découpage d’une suite de T en mots. Analyse syntaxique : Organisation des lexèmes en phrase. Exemples : I Langue naturelle I I I Tl = {0 a0 , 0 b0 , . . . 0 z0 , 0 A0 . . . 0 Z0 , 0 0 } Les lexèmes légaux sont : les mots du dictionnaire. L’analyse syntaxique vérifie qu’il y a un sujet, un verbe... Expressions algébriques Ts = {+, ∗, (, ), Ent (n), Id (i) } I I Les lexèmes sont directement les symboles de Ts : pas d’analyse lexicale Analyse syntaxique : bon parenthésage, opérateurs infixes... 9 / 32 Algorithmique et Programmation Fonctionnelle (APF) Langages (cf Cours de Michael Périn) Vocabulaires I Vocabulaire terminal : T = {a, b, c, . . . } I Mots sur T notés u, v, w, . . . I Vocabulaire non-terminal : N = {A, B, C . . . }, chaque élément de N désigne un langage sur T I Extension à N ∗ et à (T ∪ N )∗ de la concaténation sur T UV = {uv | u ∈ U ∧ v ∈ V } ∗ : Exemples : I E = ensemble des expressions I T = ensemble des termes 10 / 32 Algorithmique et Programmation Fonctionnelle (APF) Langages (cf Cours de Michael Périn) Langages Soit T = {1, 2, . . . , 9, +} et N = {E} Règles I E : := E + E I E : := n Grammaire = ensemble exhaustif de règles 11 / 32 Algorithmique et Programmation Fonctionnelle (APF) Langages (cf Cours de Michael Périn) Problème de la reconnaissance Étant donné un mot u, et un non terminal N définissant un langage N déterminer si u ∈ N . 12 / 32 Algorithmique et Programmation Fonctionnelle (APF) Langages (cf Cours de Michael Périn) Problème de la reconnaissance Étant donné un mot u, et un non terminal N définissant un langage N déterminer si u ∈ N . Au passage : calculer une forme structurée du mot reconnu 12 / 32 Algorithmique et Programmation Fonctionnelle (APF) Langages (cf Cours de Michael Périn) Exemple (criticable) Soit la grammaire suivante I E : := T + T I E : := T I T : := n I T : := ( E ) Remarque : cette gramaire est limitée 13 / 32 Algorithmique et Programmation Fonctionnelle (APF) Langages (cf Cours de Michael Périn) Exemple (criticable) Soit la grammaire suivante I E : := T + T I E : := T I T : := n I T : := ( E ) Remarque : cette gramaire est limitée 3 + 5 + 1 ne fait pas partie du langage défini par E 13 / 32 Algorithmique et Programmation Fonctionnelle (APF) Langages (cf Cours de Michael Périn) Arbre syntaxique 5 + ((7 + 3) + 2) E T ’+’ 5 T ’(’ ’)’ E T ’(’ ’+’ T E ’)’ 2 T ’+’ T 7 3 14 / 32 Algorithmique et Programmation Fonctionnelle (APF) Langages (cf Cours de Michael Périn) Arbre abstrait 5 + ((7 + 3) + 2) Add Add Ent Add Ent Ent Ent 2 5 7 3 15 / 32 Algorithmique et Programmation Fonctionnelle (APF) Analyse syntaxique Plan Type unit Langages (cf Cours de Michael Périn) Analyse syntaxique Flots Écriture d’un analyseur (parser) 16 / 32 Algorithmique et Programmation Fonctionnelle (APF) Analyse syntaxique Décomposition naïve systématique par essais-erreurs Pour une règle S ::= S1 S2 . . . Sn I Décomposer x de toutes les manières possibles sous la forme d’une concaténation x = x1 x2 . . . xn I I I pour chaque i, déterminer si xi ∈ Si si échec, essayer une autre décomposition Si pas de solution, essayer une autre règle pour S 17 / 32 Algorithmique et Programmation Fonctionnelle (APF) Analyse syntaxique Décomposition naïve systématique par essais-erreurs Pour une règle S ::= S1 S2 . . . Sn I Décomposer x de toutes les manières possibles sous la forme d’une concaténation x = x1 x2 . . . xn I I I pour chaque i, déterminer si xi ∈ Si si échec, essayer une autre décomposition Si pas de solution, essayer une autre règle pour S C’est inefficace 17 / 32 Algorithmique et Programmation Fonctionnelle (APF) Analyse syntaxique Analyse descendante récursive À chaque mot u on fait correspondre la fonction (partielle) pu qui consomme u en préfixe d’un mot x : pu (x) = y ssi x = uy À chaque non-terminal N on fait correspondre une fonction (partielle) pN qui consomme un élément de N en préfixe d’un mot x : pN (x) = y ssi ∃u ∈ N , x = uy Exemple : pour une règle U ::= a V b T W on a : pU (x) = pW (pT (pb (pV (pa (x))))) 18 / 32 Algorithmique et Programmation Fonctionnelle (APF) Analyse syntaxique Analyse descendante récursive sur des listes 19 / 32 Algorithmique et Programmation Fonctionnelle (APF) Analyse syntaxique Choix de la règle Plusieurs règles pour un non terminal Précautions I pas de récursion gauche, même cachée (interdire U := Ua) I ne pas commencer par Cas simple : chaque règle commence par un terminal on filtre sur le premier élément débutant le mot analysé Cas plus général I solution 1 : étudier la grammaire, calculer premier(U ) I solution 2 : try membre droit règle 1 with Echec → membres droits règles suivantes I solution 3 (Ocaml) : flots (streams) 20 / 32 Algorithmique et Programmation Fonctionnelle (APF) Flots Plan Type unit Langages (cf Cours de Michael Périn) Analyse syntaxique Flots Écriture d’un analyseur (parser) 21 / 32 Algorithmique et Programmation Fonctionnelle (APF) Flots Flots (Stream) Structure séquentielle polymorphe paresseuse I séquentielle polymorphe : comme les listes I paresseuse : construite à mesure des demandes de consommation (activation d’un filtrage) I consommée (détruite) à mesure qu’elle est analysée Intérêts I éviter la construction d’une grosse structure de données intermédiaire I I typiquement : fichier vu comme flot de caractères. . . transformé en flot de lexèmes I facilités d’expression : parser I ⇒ utilisation idéale dans les analyseurs récursifs descendants Exemple : Pascal -> Caml, compilation, etc ... 22 / 32 Algorithmique et Programmation Fonctionnelle (APF) Flots Consommation Idée : consommer peu de mémoire en ne travaillant que sur une fenêtre glissante de la donnée à analyser. Avantages et inconvénients I Bonne discipline de programmation forcée par l’utilisation des flots I Impossibilité de revenir en arrière Comment faire ? I Utiliser des arguments supplémentaires pour conserver les données issues du passé I Conception de la grammaire : partager les préfixes communs 23 / 32 Algorithmique et Programmation Fonctionnelle (APF) Flots Flots : construction Extension syntaxique requise : #load "dynlink.cma" ; ; #load "camlp4o.cma" ; ; Constructeurs I Stream.from, Stream.of_string, Stream.of_channel I [< ... >] avec éléments précédés de ’ Ne pas mélanger ces 2 constructeurs # let flux_int_19 =[<’1; ’9>];; val flux_int_19 : int Stream.t = <abstr> # let flux_char_ab =[<’’a’; ’’b’>];; val flux_char_ab : char Stream.t = <abstr> # let flux_char_ab_cd = [< flux_char_ab; flux_char_cd>];; # let flux_char_1934 = Stream.of_string "1934";; 24 / 32 Algorithmique et Programmation Fonctionnelle (APF) Flots Flots : production paresseuse # let rec nat_stream n = [< ’n ; nat_stream (n+1) >] ;; val nat_stream : int -> int Stream.t = <fun> # let nat = nat_stream 0 ;; val nat : int Stream.t = <abstr> 25 / 32 Algorithmique et Programmation Fonctionnelle (APF) Flots Utilisation (analyse) d’un flot : avec “consommation” 26 / 32 Algorithmique et Programmation Fonctionnelle (APF) Flots Utilisation (analyse) d’un flot : avec “consommation” Récupération du premier élément d’un flot # let next = parser [< ’x >] -> x ;; Exemple : # # - next nat;; : int = 0 next nat;; : int = 1 26 / 32 Algorithmique et Programmation Fonctionnelle (APF) Écriture d’un analyseur (parser) Plan Type unit Langages (cf Cours de Michael Périn) Analyse syntaxique Flots Écriture d’un analyseur (parser) 27 / 32 Algorithmique et Programmation Fonctionnelle (APF) Écriture d’un analyseur (parser) Utilisation (analyse) d’un flot Le motif de filtrage concerne le début du flot 28 / 32 Algorithmique et Programmation Fonctionnelle (APF) Écriture d’un analyseur (parser) Utilisation (analyse) d’un flot Le motif de filtrage concerne le début du flot Un motif peut contenir des constantes (précédées de ’) 28 / 32 Algorithmique et Programmation Fonctionnelle (APF) Écriture d’un analyseur (parser) Utilisation (analyse) d’un flot Le motif de filtrage concerne le début du flot Un motif peut contenir des constantes (précédées de ’) Un motif peut mentionner d’autres analyseurs de flot Notation : résultat = analyseur (comme si on avait un let, omis par souci de concision) 28 / 32 Algorithmique et Programmation Fonctionnelle (APF) Écriture d’un analyseur (parser) Utilisation (analyse) d’un flot Le motif de filtrage concerne le début du flot Un motif peut contenir des constantes (précédées de ’) Un motif peut mentionner d’autres analyseurs de flot Notation : résultat = analyseur (comme si on avait un let, omis par souci de concision) On peut choisir entre plusieurs motifs 28 / 32 Algorithmique et Programmation Fonctionnelle (APF) Écriture d’un analyseur (parser) Utilisation (analyse) d’un flot Le motif de filtrage concerne le début du flot Un motif peut contenir des constantes (précédées de ’) Un motif peut mentionner d’autres analyseurs de flot Notation : résultat = analyseur (comme si on avait un let, omis par souci de concision) On peut choisir entre plusieurs motifs Un motif peut contenir une séquence de motifs séparés par ’ ;’ (consommés en tête du flot analysé) 28 / 32 Algorithmique et Programmation Fonctionnelle (APF) Écriture d’un analyseur (parser) Utilisation (analyse) d’un flot Le motif de filtrage concerne le début du flot Un motif peut contenir des constantes (précédées de ’) Un motif peut mentionner d’autres analyseurs de flot Notation : résultat = analyseur (comme si on avait un let, omis par souci de concision) On peut choisir entre plusieurs motifs Un motif peut contenir une séquence de motifs séparés par ’ ;’ (consommés en tête du flot analysé) Cas du motif vide [< >] : toujours accepté 28 / 32 Algorithmique et Programmation Fonctionnelle (APF) Écriture d’un analyseur (parser) Grammaire correspondant à un analyseur de flot Une fonction d’analyse correspond à un non-terminal : consommation de ce non-terminal en début de flot 29 / 32 Algorithmique et Programmation Fonctionnelle (APF) Écriture d’un analyseur (parser) Grammaire correspondant à un analyseur de flot Une fonction d’analyse correspond à un non-terminal : consommation de ce non-terminal en début de flot Le motif de filtrage à l’intérieur de [< ... >] correspond au membre droit d’une règle 29 / 32 Algorithmique et Programmation Fonctionnelle (APF) Écriture d’un analyseur (parser) Grammaire correspondant à un analyseur de flot Une fonction d’analyse correspond à un non-terminal : consommation de ce non-terminal en début de flot Le motif de filtrage à l’intérieur de [< ... >] correspond au membre droit d’une règle Même idée que pour l’analyse de listes, avec les différences suivantes I on ne s’encombre pas avec la liste (le flot) en cours d’analyse, il est implicitemment présent I plus grande facilité pour exprimer les choix (inutile de calculer le premier terminal qui pilote le choix) I effet de bord : on ne revient pas sur un terminal consommé 29 / 32 Algorithmique et Programmation Fonctionnelle (APF) Écriture d’un analyseur (parser) Nécessité de factoriser I E : := T + T I E : := T En I E : := T SE I SE : := + T I SE : := Sinon second motif jamais essayé. 30 / 32 Algorithmique et Programmation Fonctionnelle (APF) Écriture d’un analyseur (parser) Exercice sur une grammaire ambigue Exemple de grammaire I S := E $ I E := E + E I E := id Ambigue car 31 / 32 Algorithmique et Programmation Fonctionnelle (APF) Écriture d’un analyseur (parser) Exercice sur une grammaire ambigue Exemple de grammaire I S := E $ I E := E + E I E := id Ambigue car E + id + id = id + id + id = id + id + E 31 / 32 Algorithmique et Programmation Fonctionnelle (APF) Écriture d’un analyseur (parser) Exercice sur une grammaire ambigue Exemple de grammaire I S := E $ I E := E + E I E := id Ambigue car E + id + id = id + id + id = id + id + E Désambigüer la grammaire 31 / 32 Algorithmique et Programmation Fonctionnelle (APF) Écriture d’un analyseur (parser) Exercice sur une grammaire ambigue Exemple de grammaire I S := E $ I E := E + E I E := id Ambigue car E + id + id = id + id + id = id + id + E Désambigüer la grammaire I S := E $ I E := T I E := T + E I T := id 31 / 32 Algorithmique et Programmation Fonctionnelle (APF) Écriture d’un analyseur (parser) La prochaine fois I Flots : suite et fin I Exceptions I Récursivité terminale 32 / 32