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

C++ Discussion :

Boost Proto - Grammaire et Fonctions


Sujet :

C++

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    301
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 301
    Points : 345
    Points
    345
    Par défaut Boost Proto - Grammaire et Fonctions
    Bonjour à tous,

    J'essaie de me mettre à boost.proto mais j'ai un petit problème dès les premiers exemples du users'guide notamment celui où l'on cherche à faire un petit calculateur permettant d'écrire des trucs comme:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    auto const& f=_1*_1-_1;
    std::cout << f(3) << std::endl; //affiche "6"
    mais surtout des trucs comme:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    auto const& g= square(_1)-_1;
    std::cout << g(3) << std::endl; //affiche "6"
    Ce que j'arrive pas à faire c'est à valider par une grammaire le deuxième exemple.

    Voici l'exemple:
    tout d'abord les includes nécessaires:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <boost/mpl/int.hpp>
    #include <boost/proto/core.hpp>
    #include <boost/proto/context.hpp>
     
    namespace proto = boost::proto;
    ensuite la fonction square:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    // Define a square_fun function object
    struct square_fun
    {
        typedef double result_type;
     
        double operator()(double d) const
        {
            return std::pow(d, 2);
        }
    };
     
    // Define a lazy square() function for the calculator EDSL.
    template< typename Arg >
    typename proto::result_of::make_expr<
        proto::tag::function  // Tag type
      , square_fun        // First child (by value)
      , Arg const &           // Second child (by reference)
    >::type const
    square(Arg const &arg)
    {
        return proto::make_expr<proto::tag::function>(
            square_fun()    // First child (by value)
          , boost::ref(arg)   // Second child (by reference)
        );
    }
    ensuite la grammaire des expressions possibles:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    struct calculator_grammar
      : proto::or_<
            proto::plus< calculator_grammar, calculator_grammar >
          , proto::minus< calculator_grammar, calculator_grammar >
          , proto::minus< double, calculator_grammar >
          , proto::multiplies< calculator_grammar, calculator_grammar >
          , proto::divides< calculator_grammar, calculator_grammar >
          , proto::terminal< proto::_ >
          //ici je ne sais pas quoi mettre pour valider les expressions à base de square
        >
    {};
    et enfin le reste du code avec le contexte, le domaine et le calculateur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    struct calculator_context : proto::callable_context< calculator_context const >
    {
        // Values to replace the placeholders
        std::vector<double> args;
     
        // Define the result type of the calculator.
        // (This makes the calculator_context "callable".)
        typedef double result_type;
     
        // Handle the placeholders:
        template<int I>
        double operator()(proto::tag::terminal, boost::mpl::int_<I>) const
        {
            return this->args[I];
        }
    };
     
    // Forward-declare an expression wrapper
    template<typename Expr>
    struct calculator;
     
    // Define a calculator domain. Expression within
    // the calculator domain will be wrapped in the
    // calculator<> expression wrapper.
    struct calculator_domain
      : proto::domain< proto::generator<calculator>/*, calculator_grammar*/ >
    {};
     
     
    // Define a calculator expression wrapper. It behaves just like
    // the expression it wraps, but with an extra operator() member
    // function that evaluates the expression.    
    template<typename Expr>
    struct calculator
      : proto::extends<Expr, calculator<Expr>, calculator_domain>
    {
        typedef
            proto::extends<Expr, calculator<Expr>, calculator_domain>
        base_type;
     
        calculator(Expr const &expr = Expr())
          : base_type(expr)
        {}
     
        typedef double result_type;
     
        // Overload operator() to invoke proto::eval() with
        // our calculator_context.
        double operator()(double a1) const
        {
            calculator_context ctx;
            ctx.args.push_back(a1);
            return proto::eval(*this, ctx);
        }
    };
     
    // Define the Protofied placeholder terminals
    calculator<proto::terminal<boost::mpl::int_<0> >::type> const _1;
     
    int main()
    {
    	auto const& f = _1*_1 - _1;
    	std::cout << f(3) << std::endl;
     
    	auto const& g = square(_1) - _1;
    	std::cout << g(3) << std::endl;
            return 0;
    }
    Le truc c'est que si j'active ma grammaire mon exemple avec f compile mais pas celui avec g (normal ça respecte pas ma grammaire). Donc voilà, comment je peux ajouter square(calculator_grammar) à ma grammaire?

  2. #2
    Membre régulier
    Homme Profil pro
    Ingénieur
    Inscrit en
    Octobre 2006
    Messages
    48
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur
    Secteur : Transports

    Informations forums :
    Inscription : Octobre 2006
    Messages : 48
    Points : 97
    Points
    97
    Par défaut
    Bonjour,

    Je suis très loin d'être un expert de boost::proto mais en tout cas ce code compile sous gcc 4.7.1 avec boost 1.53.0 en mode -std=c++11.

    Tout cela semble fonctionner, quel est le problème?

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    301
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 301
    Points : 345
    Points
    345
    Par défaut
    C'est vrai que c'est pas très clair (le problème c'est qu'il y a pas mal de code). En fait pour associer une grammaire à un domaine, c'est sur les lignes suivantes que ça se passe:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    struct calculator_domain
      : proto::domain< proto::generator<calculator>/*, calculator_grammar*/ >
    {};
    Si on enlève les commentaires, la grammaire calculator_grammar est associée au domaine calculator_domain et c'est là que ça compilera pas car ma grammaire ne défini pas square(_1) comme une syntaxe correcte.

    PS: je teste sous visual 2012 avec boost 1.53

  4. #4
    Membre régulier
    Homme Profil pro
    Ingénieur
    Inscrit en
    Octobre 2006
    Messages
    48
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur
    Secteur : Transports

    Informations forums :
    Inscription : Octobre 2006
    Messages : 48
    Points : 97
    Points
    97
    Par défaut
    Effectivement, je viens de m'apercevoir que la grammaire n'était pas utilisée

    Après quelques essais erreurs (et une lecture attentive de l'imprésionnant log d'erreur), j'en suis venu à la conclusion qu'ajouter le noeud suivant à la grammaire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    , proto::function< calculator_grammar >
    ne fonctionnait pas et que :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    , proto::function< calculator_grammar, calculator_grammar >
    fonctionnait miraculeusement.

    <Hypothèse fumeuse>Je suppose que le premier argument template de proto::function est la "grammaire de retour" de la fonction tandis que les argmuments suivants correspondent à la grammaire des paramètres (ici 1 seul paramètre est validé par la grammaire).</Hypothèse fumeuse>

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    301
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 301
    Points : 345
    Points
    345
    Par défaut
    Parfait! Merci beaucoup iNaKoll ça règle parfaitement mon problème!

  6. #6
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    proto::function< proto::terminal< proto::_ >, calculator_grammar >
    C'est le plus simple : ton appel ressemble à a(b), c'est ce qu'indique le proto::function. a doit être un terminal et b une expression valide selon ta grammaire.

    Cependant on peut faire beaucoup mieux en définissant des règles de grammaire plus complexe qui vont permettre une arité plus grande et souple.

    Je n'utilise pas assez régulièrement proto pour te donner la grammaire comme ca, mais en fouillant la doc sur les partie concernant spécifiquement les grammaires, tu devrais trouver ton bonheur.

  7. #7
    Membre chevronné
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    Citation Envoyé par iNaKoll Voir le message
    <Hypothèse fumeuse>Je suppose que le premier argument template de proto::function est la "grammaire de retour" de la fonction tandis que les argmuments suivants correspondent à la grammaire des paramètres (ici 1 seul paramètre est validé par la grammaire).</Hypothèse fumeuse>
    non, proto::function attend N grammaires qui sont la grammaire de l'appelant et les N-1 grammaires de ces arguments.

    x(y)

    match function< grammar_x, grammar_y >

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Boost Spirit: Grammaire pour les équations en math
    Par darkman19320 dans le forum C++
    Réponses: 3
    Dernier message: 17/04/2012, 18h30
  2. Débuts avec boost::proto
    Par Kaluza dans le forum Boost
    Réponses: 1
    Dernier message: 04/11/2011, 20h21
  3. Réponses: 8
    Dernier message: 14/10/2011, 11h06
  4. [boost::multi_array]accés au fonction membres des objets stocké.
    Par dillinger91 dans le forum Bibliothèques
    Réponses: 0
    Dernier message: 31/12/2008, 20h11
  5. [Boost.Function] Appeler une fonction "externe"
    Par poukill dans le forum Boost
    Réponses: 17
    Dernier message: 29/08/2007, 16h04

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