Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

  1. #1
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    juin 2016
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : juin 2016
    Messages : 5
    Points : 2
    Points
    2

    Par défaut Pattern Matching in Mincaml

    Bonjour à tous,

    Tout d'abord je tiens à m'excuser si je ne suis pas dans la bonne catégorie.
    Dans l'un de mes cours portant sur l'usage de Ocaml / Mincaml il m'est demandé de réaliser un "Unparser" qui prend un Abstract Syntaxt Tree (AST) et renvoie le programme en Ocaml correspondant (si possible bien indenté mais pour l'instant je n'y suis pas encore).

    J'ai pour exemple cette string:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    "let rec fib n = if n < 2 then 1 else fib (n - 1) + fib (n - 1) in print(fib 5)"
    qui me donne comme AST ceci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    LetRec
     ({name = ("fib", Var {contents = None});
       args = [("n", Var {contents = None})];
       body =
        If (Not (LE (Syntax.Int 2, Syntax.Var "n")), Syntax.Int 1,
         Add (App (Syntax.Var "fib", [Sub (Syntax.Var "n", Syntax.Int 1)]),
          App (Syntax.Var "fib", [Sub (Syntax.Var "n", Syntax.Int 1)])))},
     App (Syntax.Var "print", [App (Syntax.Var "fib", [Syntax.Int 5])]))
    Mon souci est le suivant. Je n'arrive pas à trouver comment réaliser mon pattern matching pour "découper" cet AST de telle sorte que j'obtienne une string "LetRec" ^ "reste de l'AST". Les pattern matching usuels sur des listes ne s'appliquent pas ici puisque mon AST est de type Syntax.t et je ne trouve pas de solution à mon souci. Le but étant ensuite d'appeler récursivement mon unparser sur le reste de l'AST.

    Si quelqu'un a un conseil pour m'aider à avancer, je lui en serais plus que reconnaissant !

  2. #2
    Nouveau membre du Club
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    novembre 2013
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : novembre 2013
    Messages : 26
    Points : 34
    Points
    34

    Par défaut

    Hello,

    Le constructeur LetRec prend comme paramètre un couple :
    - le premier élément du couple est une structure avec 3 attributs : name, args et body (un AST).
    - le deuxième élément du couple est un AST.

    Connaissant cette structure de données, tu dois maintenant être capable d'aller chercher l'info dont tu as besoin au bon endroit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    let afficher_programme programme =
      match programme with
        | LetRec (fonction, appel) -> ... (* tu peux accéder aux différents éléments du programme ici *)
        | (* autres constructeurs ici *)

  3. #3
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    juin 2016
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : juin 2016
    Messages : 5
    Points : 2
    Points
    2

    Par défaut

    Hello,

    Merci bien pour ce message, cela me semble déjà plus clair ! j'ai toutefois un autre problème xD (j'ai beau essayer de me débrouiller comme je peux Ocaml n'est vraiment pas mon point fort)
    Une fois récupéré fonction et appel, auxquels j'applique récursivement la fonction d'unparsing, je n'arrive pas à appliquer le pattern matching à la fonction comprenant "name, args, body". Je suppose que mon souci est juste un problème de syntaxe? mais j'ai beau tenter différentes écritures dans mon pattern matching, impossible d'enlever mon message d'erreur... :/

  4. #4
    Nouveau membre du Club
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    novembre 2013
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : novembre 2013
    Messages : 26
    Points : 34
    Points
    34

    Par défaut

    Tu ne peux pas appliquer la même fonction à programme, fonction et appel, ils n'ont pas le même type...
    Par contre, tu peux écrire une deuxième fonction (récursive, celle-ci) qui affiche un AST, et que tu appelleras dans afficher_programme.

    name et args contiennent des chaînes de caractères, que tu peux directement afficher.

  5. #5
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    juin 2016
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : juin 2016
    Messages : 5
    Points : 2
    Points
    2

    Par défaut

    Pardon je m'étais mal exprimé. En fait mon souci survient avant d'appeler récursivement l'unparsing. Je n'arrive pas à "séparer" les différents éléments de la fonction dans un pattern matching (name, args, body). Et mon souci provient probablement d'une mauvaise syntaxe mais je n'arrive pas à trouver de documentation à propos de Syntax.fundef...

  6. #6
    Nouveau membre du Club
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    novembre 2013
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : novembre 2013
    Messages : 26
    Points : 34
    Points
    34

    Par défaut

    Tu ne connais pas les types records ?
    Il te suffit juste d'écrire fonction.name, fonction.args et fonction.body pour accéder aux attributs

  7. #7
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    juin 2016
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : juin 2016
    Messages : 5
    Points : 2
    Points
    2

    Par défaut

    Oh... Moi qui cherchait compliqué... Non je ne connaissais pas, mais je suis vraiment nouveau sur Ocaml et le cours va relativement vite pour passer sur ce genre de détails ^^

    J'arrive à voir la lumière au bout du tunnel désormais, par contre j'ai une question concernant le type de name et args. Mincaml ne me dit pas que ce sont des chaînes de caractères mais qu'ils sont respectivement Id.t * Type.t et (Id.t * Type.t) ?

  8. #8
    Nouveau membre du Club
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    novembre 2013
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : novembre 2013
    Messages : 26
    Points : 34
    Points
    34

    Par défaut

    Ça veut simplement dire qu'il y a une définition de type dans un module.
    Le type t est donc disponible à l'utilisateur via l'interface .mli :

    ld.mli (interface) :
    Son implémentation est par contre cachée dans le .ml :

    ld.ml (implémentation) :
    Une fonction d'affichage (dans le genre ld.t -> unit) est-elle disponible ?

  9. #9
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    juin 2016
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : juin 2016
    Messages : 5
    Points : 2
    Points
    2

    Par défaut

    Une fonction d'affichage (dans le genre ld.t -> unit) est-elle disponible ?
    Hmm je ne vois pas trop de quoi vous voulez parler quand vous parlez d'une telle fonction. J'ai pourtant je pense réussi à contourner mon problème, même si la solution n'est probablement pas très élégante:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    let print_func func =
    	let name = match func.name with (a,b) -> a in 
    		let args = match func.args with a -> (match List.hd(a) with (x,y) -> x) in
    			name ^ " " ^ args ^ " = " ^ unparse func.body;;
    Combiné à mon unparser, j'obtiens bien la ligne "let rec fib n = if n < 2 then 1 else fib (n - 1) + fib (n - 1) in print(fib 5)" quand je l'applique à "ast fib_p" cité plus haut. Je n'ai pas encore terminé puisqu'il me reste les derniers types à insérer mais je pense néanmoins avoir bien avancé (et mieux compris toutes ces histoires de pattern matching, types, etc..)

    Merci encore pour toute cette aide !

  10. #10
    Nouveau membre du Club
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    novembre 2013
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : novembre 2013
    Messages : 26
    Points : 34
    Points
    34

    Par défaut

    Mh ça veut dire que l'implémentation de ld.t n'est pas cachée. Oublie ce que j'ai dit.
    Ton code marche plus ou moins, mais on l'écrirait plutôt comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    let print_func func =
      let (func_name, _) = func.name in 
      let args = List.fold_left (fun arg_list (arg_name, _) -> arg_list ^ " " ^ arg_name) "" func.args in
      func_name ^ " " ^ args ^ " = " ^ unparse func.body
    ;;
    (pas testé)

    Quelques commentaires :
    - pour récupérer les valeurs d'un tuple, on peut écrire let (a, b) = func.name in
    - on a besoin d'afficher toute la liste des arguments, pas seulement le premier comme tu le fais. J'utilise un List.fold_left pour concaténer les noms de tous les arguments de la liste. Tu peux jeter un oeil à la doc pour plus de détails

Discussions similaires

  1. Pattern Matching sur une InputStream?
    Par Phoxtrot dans le forum Général Java
    Réponses: 2
    Dernier message: 19/05/2008, 15h36
  2. Use of uninitialized value in pattern match (m//)
    Par Vladkergan dans le forum Langage
    Réponses: 4
    Dernier message: 13/01/2008, 20h25
  3. pattern matching (image processing)
    Par anatore dans le forum Traitement d'images
    Réponses: 8
    Dernier message: 15/10/2007, 17h01
  4. Use of uninitialized value in pattern match(m//)
    Par hayaet dans le forum Langage
    Réponses: 1
    Dernier message: 08/10/2007, 12h45
  5. [Regex] Pattern matching
    Par jeRame dans le forum java.util
    Réponses: 1
    Dernier message: 26/06/2007, 15h28

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo