2012-11-28 17 views
3

Dans ma grammaire Esprit Boost Je voudrais avoir une règle qui fait cela:Spirit peut stimuler les règles paramétrables

règle < ...> noCaseLit = NO_CASE [allumé ("KEYWORD")];

mais pour un mot-clé personnalisé afin que je puisse le faire:

... >> noCaseLit ("SomeSpecialKeyword") >> ... >> noCaseLit ("OtherSpecialKeyword1")

Est-ce possible avec les règles Boost Spirit et si oui, comment?

P.S. J'utilise la chose insensible à la casse comme un exemple, ce que je suis après est le paramétrage de la règle en général.

: Edits A travers le lien fourni par « sehe » dans les commentaires que j'ai pu se rapprocher de ce que je voulais, mais je ne suis pas encore tout à fait.

/* Defining the noCaseLit rule */ 
rule<Iterator, string(string)> noCaseLit = no_case[lit(_r1)]; 
/* Using the noCaseLit rule */ 
rule<...> someRule = ... >> noCaseLit(phx::val("SomeSpecialKeyword")) >> ... 

Je ne l'ai pas encore trouvé un moyen de convertir automatiquement la chaîne littérale à la valeur Phoenix afin que je puisse utiliser la règle comme ceci:

rule<...> someRule = ... >> noCaseLit("SomeSpecialKeyword") >> ... 
+1

double possible de [des parties communes Affacturage des règles de Spirit] (http://stackoverflow.com/questions/13388227/factoring-out-common-parts-of-spirit-rules) – sehe

+0

Thx sehe pour fournir ce lien, il m'a aidé à apprendre sur l'utilisation de l'attribut hérité. – Halt

Répondre

4

Le plus simple est de simplement créer une fonction qui renvoie votre règle/analyseur. Dans l'exemple près de la fin de this page vous pouvez trouver un moyen de déclarer la valeur de retour de votre fonction. (Le même here dans un exemple commenté).

#include <iostream> 
#include <string> 
#include <boost/spirit/include/qi.hpp> 

namespace ascii = boost::spirit::ascii; 
namespace qi = boost::spirit::qi; 

typedef boost::proto::result_of::deep_copy< 
      BOOST_TYPEOF(ascii::no_case[qi::lit(std::string())]) 
     >::type nocaselit_return_type; 

nocaselit_return_type nocaselit(const std::string& keyword) 
{ 
    return boost::proto::deep_copy(ascii::no_case[qi::lit(keyword)]); 
} 

//C++11 VERSION EASIER TO MODIFY (AND DOESN'T REQUIRE THE TYPEDEF) 
//auto nocaselit(const std::string& keyword) -> decltype(boost::proto::deep_copy(ascii::no_case[qi::lit(keyword)])) 
//{ 
// return boost::proto::deep_copy(ascii::no_case[qi::lit(keyword)]); 
//} 


int main() 
{ 
    std::string test1="MyKeYWoRD"; 
    std::string::const_iterator iter=test1.begin(); 
    std::string::const_iterator end=test1.end(); 
    if(qi::parse(iter,end,nocaselit("mYkEywOrd"))&& (iter==end)) 
     std::cout << "Parse 1 Successful" << std::endl; 
    else 
     std::cout << "Parse 2 Failed. Remaining: " << std::string(iter,end) << std::endl; 

    qi::rule<std::string::const_iterator,ascii::space_type> myrule = 
    *(
      (nocaselit("double") >> ':' >> qi::double_) 
     | (nocaselit("keyword") >> '-' >> *(qi::char_ - '.') >> '.') 
    ); 

    std::string test2=" DOUBLE : 3.5 KEYWORD-whatever.Double :2.5"; 
    iter=test2.begin(); 
    end=test2.end(); 
    if(qi::phrase_parse(iter,end,myrule,ascii::space)&& (iter==end)) 
     std::cout << "Parse 2 Successful" << std::endl; 
    else 
     std::cout << "Parse 2 Failed. Remaining: " << std::string(iter,end) << std::endl; 


    return 0; 
} 
+0

Thx pour cette solution. Vous allez dans une direction différente de celle de ma «moitié». Cela fonctionne et fait ce que j'étais après. – Halt

+0

+1 pour une autre réponse stupéfiante, montrant la compréhension de ce qui se passe _dans les_interfaces de l'Esprit. [Oh, et Vim 'g ~ iw' beaucoup? :)] – sehe

Questions connexes