Algorithmique et Programmation Fonctionnelle (APF)

publicité
Algorithmique et Programmation Fonctionnelle (APF)
Algorithmique et Programmation Fonctionnelle
(APF)
RICM3
Cours 6 : Flots
Jean-François Monin
Polytech
2013 - 2014
1/5
Algorithmique et Programmation Fonctionnelle (APF)
La dernière fois
I
Type unit, effets de bord
I
Analyse syntaxique sur des listes
2/5
Algorithmique et Programmation Fonctionnelle (APF)
Plan
Fonction d’ordre supérieur
3/5
Algorithmique et Programmation Fonctionnelle (APF)
Flots
Plan
Fonction d’ordre supérieur
4/5
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 ...
5/5
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
6/5
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
[< ... >]
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";;
7/5
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>
8/5
Algorithmique et Programmation Fonctionnelle (APF)
Flots
Utilisation (analyse) d’un flot : avec “consommation”
9/5
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 s = match s with parser
[< ’x >] -> x ;;
Exemple :
#
#
-
next nat;;
: int = 0
next nat;;
: int = 1
9/5
Algorithmique et Programmation Fonctionnelle (APF)
Flots
Utilisation (analyse) d’un flot
Le motif de filtrage concerne le début du flot
10 / 5
Algorithmique et Programmation Fonctionnelle (APF)
Flots
Utilisation (analyse) d’un flot
Le motif de filtrage concerne le début du flot
Un motif peut contenir des constantes
10 / 5
Algorithmique et Programmation Fonctionnelle (APF)
Flots
Utilisation (analyse) d’un flot
Le motif de filtrage concerne le début du flot
Un motif peut contenir des constantes
Un motif peut mentionner d’autres analyseurs de flot
Notation : résultat = analyseur
(comme si on avait un let, omis par souci de concision)
10 / 5
Algorithmique et Programmation Fonctionnelle (APF)
Flots
Utilisation (analyse) d’un flot
Le motif de filtrage concerne le début du flot
Un motif peut contenir des constantes
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
10 / 5
Algorithmique et Programmation Fonctionnelle (APF)
Flots
Utilisation (analyse) d’un flot
Le motif de filtrage concerne le début du flot
Un motif peut contenir des constantes
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é)
10 / 5
Algorithmique et Programmation Fonctionnelle (APF)
Flots
Utilisation (analyse) d’un flot
Le motif de filtrage concerne le début du flot
Un motif peut contenir des constantes
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é
10 / 5
Algorithmique et Programmation Fonctionnelle (APF)
Flots
Grammaire correspondant à un analyseur de flot
Une fonction d’analyse correspond à un non-terminal :
consommation de ce non-terminal en début de flot
11 / 5
Algorithmique et Programmation Fonctionnelle (APF)
Flots
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 flitrage à l’intérieur de [< ... >]
correspond au membre droit d’une règle
11 / 5
Algorithmique et Programmation Fonctionnelle (APF)
Flots
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 flitrage à 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é
11 / 5
Algorithmique et Programmation Fonctionnelle (APF)
Flots
Flots : profondeur de parenthèses
let rec profond = parser
[< ’’(’; n=profond ; ’’)’; >] -> n+1
| [<>] -> 0;;
let tata = Stream.of_string "(((())))" ;;
let qq = profond tata;;
12 / 5
Algorithmique et Programmation Fonctionnelle (APF)
Flots
Flots : profondeur de parenthèses
let rec profond = parser
[< ’’(’; n=profond ; ’’)’; >] -> n+1
| [<>] -> 0;;
let tata = Stream.of_string "(((())))" ;;
let qq = profond tata;;
Avec accumulateur
12 / 5
Algorithmique et Programmation Fonctionnelle (APF)
Flots
Flots : profondeur de parenthèses
let rec profond = parser
[< ’’(’; n=profond ; ’’)’; >] -> n+1
| [<>] -> 0;;
let tata = Stream.of_string "(((())))" ;;
let qq = profond tata;;
Avec accumulateur
let rec profond_a n = parser
| [<’’(’; p = profond_a (n+1); ’’)’;>] -> p
| [<>] -> n
12 / 5
Algorithmique et Programmation Fonctionnelle (APF)
Flots
Construction d’un flot à partir d’un flot en entrée
Étant donné un flux de caractères s, construire un flot identique à
s mais sans ses voyelles
13 / 5
Algorithmique et Programmation Fonctionnelle (APF)
Flots
Construction d’un flot à partir d’un flot en entrée
Étant donné un flux de caractères s, construire un flot identique à
s mais sans ses voyelles
let rec otervoy s = match flux with parser
| [< ’ (’a’|’e’|’i’|’o’|’u’|’y’) >] -> otervoy s
| [<’x>] -> [<’x; otervoy s>]
13 / 5
Algorithmique et Programmation Fonctionnelle (APF)
Flots
Flot de parenthèses
Grammaire
I
P := (P)
I
P := a
Écrire une fonction qui enleve les parenthèses de ce flot.
solution
14 / 5
Algorithmique et Programmation Fonctionnelle (APF)
Flots
Flot de parenthèses
Grammaire
I
P := (P)
I
P := a
Écrire une fonction qui enleve les parenthèses de ce flot.
solution
let rec oterparenth flux = match flux with parser
[< ”(’ ; s= oterparenth ; ”)’ ; >] -> s
| [< ’ x >] -> [<’x ; oterparenth flux>] ; ;
14 / 5
Algorithmique et Programmation Fonctionnelle (APF)
Flots
Flot de caractères → flot de lexèmes
let rec next_tok = parser
| [<’ 0 0 ; tk = next_tok >] → tk
| [<’ 0 +0 >] → Some (Tplus)
| [<’ 0 00 ..0 90 as c ; >] → Some (Tent (horner (valchiffre c)))
.
| ..
| [< >] → None
let lex s = Stream.from (fun _ → next_tok s)
avec les bons types.
15 / 5
Algorithmique et Programmation Fonctionnelle (APF)
Flots
Exemple
Considèrons la grammaire suivante :
S ::= P S | a
P ::= ( S ) | x
16 / 5
Algorithmique et Programmation Fonctionnelle (APF)
Flots
Exemple
Considèrons la grammaire suivante :
S ::= P S | a
P ::= ( S ) | x
let rec a_S = parser
| [< ok1 = a_P ; ok2 = a_S >] → ()
| [< ’ 0 a 0 >] → ()
and a_P = parser
| [< ’ 0 (0 ; ok = a_S ; ’ 0 )0 >] → ()
| [< ’ 0 x 0 >] → ()
D’une manière générale, les fonctions comme a_P rendent un
résultat, par exemple (),
16 / 5
Algorithmique et Programmation Fonctionnelle (APF)
Flots
Compilation
Utiliser l’option -pp de ocamlc pour créer le .cmo
ocamlc -pp "camlp4o pa extend.cmo" -I +camlp4 -c fichier.ml
puis on compile avec
ocamlc fichier.cmo -o nom executable.
Documentation
http:
//caml.inria.fr/pub/oldcamlsite/camlp4/index.html
17 / 5
Algorithmique et Programmation Fonctionnelle (APF)
Fonction d’ordre supérieur
Plan
Fonction d’ordre supérieur
18 / 5
Algorithmique et Programmation Fonctionnelle (APF)
Fonction d’ordre supérieur
fold *
Ecrire une fonction qui calcule le résultat d’une fonction appliquée
successivement à l’ensemble des termes d’une liste.
19 / 5
Algorithmique et Programmation Fonctionnelle (APF)
Fonction d’ordre supérieur
fold *
Ecrire une fonction qui calcule le résultat d’une fonction appliquée
successivement à l’ensemble des termes d’une liste.
Solution
19 / 5
Algorithmique et Programmation Fonctionnelle (APF)
Fonction d’ordre supérieur
fold *
Ecrire une fonction qui calcule le résultat d’une fonction appliquée
successivement à l’ensemble des termes d’une liste.
Solution
let rec fold f accu = function
| [ ] -> accu
| a : : l -> fold f (f accu a ) l ; ;
let
let
let
let
plus x y = x+y ; ;
addition = fold plus 0 ; ;
fois x y = x * y ; ;
multiplication = fold fois 1 ; ;
19 / 5
Algorithmique et Programmation Fonctionnelle (APF)
Fonction d’ordre supérieur
fold *
Ecrire une fonction qui calcule le résultat d’une fonction appliquée
successivement à l’ensemble des termes d’une liste.
Solution
let rec fold f accu = function
| [ ] -> accu
| a : : l -> fold f (f accu a ) l ; ;
let
let
let
let
plus x y = x+y ; ;
addition = fold plus 0 ; ;
fois x y = x * y ; ;
multiplication = fold fois 1 ; ;
Prédéfinie : List.fold_right et List.fold_left
19 / 5
Téléchargement