IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
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

Caml Discussion :

Ocamllex : renvoyer plusieurs tokens


Sujet :

Caml

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé
    Profil pro
    Inscrit en
    Février 2008
    Messages
    141
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 141
    Par défaut [Résolu] Ocamllex : renvoyer plusieurs tokens
    Bonjour,

    Je n'ai pas trouvé comment résoudre le problème suivant : j'aurais besoin, sur une règle de ocamllex, de renvoyer plusieurs tokens à la suite.

    Je m'explique : je suis en train d'écrire un parser pour Delphi, et en Delphi :
    - " 1. " désigne une valeur de type "float"
    - " [1..2] " désigne une valeur de type "ensemble d'entier"

    Ce qui veut dire que quand on lit sur l'entrée du lexer les caractères "1.", il faut encore lire un caractère pour savoir si la suite du code est "1.." - et dans ce cas, le caractère 1 représente l'entier 1 suivi de l'opérateur ".." - ou si "1." est une valeur réelle à virgule flottante.

    Je vois le principe à suivre, mais je n'ai pas compris comment je pouvais le coder avec ocamllex :

    1- émettre 2 tokens à la suite :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    let digit = ['0'-'9']
     
    rule monLexer = parse
      | (digit+ as inum) ".." { (INT inum); RANGE } (* Comment dois-je modiifer mon code pour pouvoir émettre 2 tokens à la suite, sans manger de caractère supplémentaire de l'input? *)
      | digit+ '.' digit* as ifloat { FLOAT ifloat }
    2 - remettre les caractères lus dans le lexbuf :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    rule monLexer = parse
      | (digit+ as inum) ".." { reload_in_lexbuf lexbuf "..";  (* Je n'ai pas trouvé de telle fonction dans la doc, ni dans lexing.mli. 
                                                                  cf yyless en lex *)
                                (INT inum) }
      | digit+ '.' digit* as ifloat { FLOAT ifloat }
    J'espère que ma question est compréhensible.
    Merci d'avance pour vos (nombreuses ) réponses.

  2. #2
    Membre Expert
    Avatar de SpiceGuid
    Homme Profil pro
    Inscrit en
    Juin 2007
    Messages
    1 704
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2007
    Messages : 1 704
    Par défaut
    Si tu es en train d'écrire un parseur pour Delphi tu as tout autant intérêt à étendre mon parseur pour Turbo Pascal

    Avec mon lexeur :
    • tu reconnais '..' à l'aide de lex.granted_poly ".."
    • tu reconnais '.' à l'aide de lex.granted_mono '.'

  3. #3
    Membre émérite
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    832
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 832
    Par défaut
    Mais tes lexers, ils sont beurk :-'

    LeGEC > ce genre de considérations subtiles ira mieux dans ton _parseur_ (si tu utilises ocamlyacc par exemple ce sera facile à faire). Au niveau du lexer tu dois juste découper ton entrée en tokens et éviter les subtilités. Je te conseille de garder seulement les entiers et un token Dot pour '.', le parseur reconnaîtra les siens :
    | INT DOT INT { Float (float_of_string (Printf.sprintf "%d.%d" $1 $3)) (* paresseux, l'autre *) }
    | CROCH INT DOT DOT INT HCORC { Interval $2 $5 }

  4. #4
    alex_pi
    Invité(e)
    Par défaut
    Citation Envoyé par SpiceGuid Voir le message
    Si tu es en train d'écrire un parseur pour Delphi tu as tout autant intérêt à étendre mon parseur pour Turbo Pascal

    Avec mon lexeur :
    • tu reconnais '..' à l'aide de lex.granted_poly ".."
    • tu reconnais '.' à l'aide de lex.granted_mono '.'
    Bon, autant pour ton histoire de bootstrap, je veux bien comprendre que tu te tapes un truc bas niveau à la main, mais là, quand tu parses un *autre* langage, pourquoi tu voudrais que les gens utilisent un truc aussi bas niveau ?

    Citation Envoyé par bluestorm Voir le message
    LeGEC > ce genre de considérations subtiles ira mieux dans ton _parseur_ (si tu utilises ocamlyacc par exemple ce sera facile à faire). Au niveau du lexer tu dois juste découper ton entrée en tokens et éviter les subtilités. Je te conseille de garder seulement les entiers et un token Dot pour '.', le parseur reconnaîtra les siens :
    | INT DOT INT { Float (float_of_string (Printf.sprintf "%d.%d" $1 $3)) (* paresseux, l'autre *) }
    | CROCH INT DOT DOT INT HCORC { Interval $2 $5 }
    Et même que si tu utilises Menhir, tu peux écrire des choses comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    | CROCH binf = INT DOT DOT bsup = INT HCORC {Interval binf bsuf}
    qui je trouve est encore plus clair (Oui, je preche pour l'utilisation de menhir )

  5. #5
    Membre Expert
    Avatar de SpiceGuid
    Homme Profil pro
    Inscrit en
    Juin 2007
    Messages
    1 704
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2007
    Messages : 1 704
    Par défaut
    Décidément il n'y en aura pas un pour (re-)lire ma documentation

    Ça n'est tout simplement pas possible que mes lexeurs soient beurk puisqu'il n'y a pas de lexeurs, il n'y a qu'un module Lex codé une fois pour toutes, quelque soit le *autre* langage.

    @LeGEC
    Par contre, comme mon lexeur est universel, il n'a pas de gestion des commentaires donc si tu choisi cette option tu devras le modifier toi-même pour qu'il avale (* tes commentaires *).

  6. #6
    alex_pi
    Invité(e)
    Par défaut
    Citation Envoyé par SpiceGuid Voir le message
    Décidément il n'y en aura pas un pour (re-)lire ma documentation
    Alors pour info, je l'ai relu, et honnêtement, je trouve ça horrible. Plusieurs raison:
    C'est un code monstrueusement impératif. Par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
        ( match lex with
        | l when lex.granted_word "const" -> ()
        | l when lex.granted_word "var" -> ()
        | l when lex.granted_word "in" -> ()
        | l when lex.granted_word "out" -> ()
        | l -> ()
        ) ;
    moi je dis non quoi...

    Si j'utilise un langage fonctionnel, c'est parce que j'aime simplement écrire ce que je pense. Si je pense "Quand j'ai un crochet, un entier, deux points, un entier, un crochet, alors les deux entiers représentent les bornes d'un ensembles d'entier", je veux écrire un code qui signifie ça. Et je pense que le code menhir que j'ai écris plus haut est très proche de ça. Le paquet de lex.granted ou que sais-je est quand même vachement moins proche de ce que je "pense".

    Si j'utilise un langage fortement typé, ce n'est pas juste pour me prendre des messages d'erreur imbitables dans la gueule, c'est parce que j'aime être prévenu statiquement qu'il y a un problème dans ce que j'écris. Un outil comme ocamlyacc ou menhir me prévient quand il y a un conflit dans la grammaire que j'écris. Le tiens, non. Je dois juste ne jamais me tromper. Quitte à ne jamais se tromper, autant coder en C, ça ira plus vite hein.

    Bref, même après lecture, je pense sincèrement que ton approche est monstrueusement bas niveau et n'apporte rien (allez, "pas grand chose") par rapport à un outil comme ocamlyacc ou menhir. Je ne vois donc aucune raison de l'utiliser.

  7. #7
    Membre éprouvé
    Profil pro
    Inscrit en
    Février 2008
    Messages
    141
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 141
    Par défaut
    < Je me permet de réinsérer un encart publicitaire concernant mon message original au milieu de cette discussion... >

    La raison pour laquelle je souhaiterais faire ceci pendant le lexing :

    la syntaxe exacte de de delphi pour les floats (enfin... celle que j'ai comprise en essayant de compiler 2 bêtes lignes de code) est la suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    mondouble := 1.0; // ok, car il n'y a pas d'espaces autour du .
    mondouble := 2 . 3; // ne marche pas, ni 2. 3, ni 2 .3
    Ce qui veut dire qu'à cause de cette règle à la con, mon lexer ne peut pas faire sauter tranquillement les espaces... et je dois donc rajouter des tokens "WhiteSpace" dans ma grammaire (pour pouvoir dire que "INT DOT INT" est un float, mais "INT WS DOT WS INT" n'en est pas un, et je n'imagine pas ce que ça donnerait pour les autres règles...), et ça ne m'avait pas l'air très joli.

    Alors je m'étais dit, autant faire ce micro parsing dans le lexer - je suis d'accord, ce n'est pas dans l'esprit du lexing, mais bon, ça lèverait des ambiguïtés plus tôt, et ça allègerait d'autant la grammaire...

    D'où ma question : est-ce que c'est techniquement possible avec ocamllex de dire "remet les deux caractères que tu viens de lire dans le lexbuf" ? Je n'ai pas vu de fonction convaincante dans le module Lexing, mais je n'ai peut-être pas tout lu. Est-ce qu'il suffit de modifier la position courante?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    lexbuf.cur_pos <- {lexbuf.cur_pos where pos := pos -2} (* ou un truc du genre *)
    <fin de l'encart publicitaire>

Discussions similaires

  1. comment renvoyer plusieurs variables
    Par pyrene dans le forum Macros et VBA Excel
    Réponses: 37
    Dernier message: 05/06/2008, 11h50
  2. [WD 9] Renvoyer plusieurs valeurs
    Par jo_la_pasteque dans le forum WinDev
    Réponses: 13
    Dernier message: 10/04/2008, 15h05
  3. Renvoyer plusieur champs depuis une fonction
    Par djorfe dans le forum Langage
    Réponses: 2
    Dernier message: 29/02/2008, 09h54
  4. Réponses: 8
    Dernier message: 06/04/2006, 18h45
  5. Faire un update avec une ss requete renvoyant plusieur row
    Par djodjo dans le forum Langage SQL
    Réponses: 6
    Dernier message: 02/09/2005, 15h51

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