Boost spirit 2.x: how to deal with keywords and identifiers?

Hmmm just declare your rule to be: the > operator say that your keyword MUST be followed by an ident //instead of just may (if I understood spirit right the >> operator will //make the parser consider other rules if it fail which might or not be //what you want. Ident_decl = keyword_table_ > ident Expending on your exemple you should have something like this at the end: struct my_keywords : boost::spirit::qi::symbols { my_keywords() { add ("void", TYPE_VOID) ("string", TYPE_STRING) ("float", TYPE_FLOAT) ("int", TYPE_INT) ("bool", TYPE_BOOL) //TODO: add others ; } } keywords_table class ident_decl_node { //this will enable fusion_adapt_struct to access your private members template friend struct boost::fusion::extension::struct_member; int type; std::string ident; }; BOOST_FUSION_ADAPT_STRUCT( ident_decl_node, (int, type) (std::string, ident) ) struct MyErrorHandler { template struct result { typedef void type; }; template void operator()(Iterator first, Iterator last, Iterator error_pos, std::string const& what) const { using boost::phoenix::construct; std::string error_msg = "Error! Expecting "; error_msg += what; // what failed?

Error_msg += " here: \""; error_msg += std::string(error_pos, last); // iterators to error-pos, end error_msg += "\""; //put a breakpoint here if you don't have std::cout for the console or change //this line for something else. Std::cout ScriptNodes; template struct NodeGrammar: public grammar { using boost::spirit::arg_names; //edit1 NodeGrammar: NodeGrammar::base_type(start) { //I had problem if I didn't add the eps rule (which do nothing) so you might //want to leave it start %= ident_decl | some_other_node_decl >> eps; ident_decl %= keyword_table > ident; //I'm not sure if the %= operator will work correctly on this, you might have to do //the push_back manually but I think it should work ident %= rawlexeme((alpha | char_('_')) >> *(alnum | char_('_'))) - keywords_table_; on_error(start, error_handler(_1, _2, _3, _4)); //edit1 } my_keywords keyword_table_; boost::spirit::qi::rule start; boost::spirit::qi::rule ident_decl; boost::spirit::qi::rule ident_decl; boost::spirit::qi::rule ident; boost::phoenix::function error_handler; //edit1 } Also I don't know which version you use but I used the one in boost 1.40 and it seems there is a bug when using operator %= followed by only one argument (the parser would not parse correctly this rule). Ex: ident_decl %= ident do this instead ident_decl %= ident > eps which should be equivalent Hope this helped.

Hmmm just declare your rule to be: //the > operator say that your keyword MUST be followed by an ident //instead of just may (if I understood spirit right the >> operator will //make the parser consider other rules if it fail which might or not be //what you want. Ident_decl = keyword_table_ > ident; Expending on your exemple you should have something like this at the end: struct my_keywords : boost::spirit::qi::symbols { my_keywords() { add ("void", TYPE_VOID) ("string", TYPE_STRING) ("float", TYPE_FLOAT) ("int", TYPE_INT) ("bool", TYPE_BOOL) //TODO: add others ; } } keywords_table_; //... class ident_decl_node { //this will enable fusion_adapt_struct to access your private members template friend struct boost::fusion::extension::struct_member; int type; std::string ident; }; BOOST_FUSION_ADAPT_STRUCT( ident_decl_node, (int, type) (std::string, ident) ) //... struct MyErrorHandler { template struct result { typedef void type; }; template void operator()(Iterator first, Iterator last, Iterator error_pos, std::string const& what) const { using boost::phoenix::construct; std::string error_msg = "Error! Expecting "; error_msg += what; // what failed?

Error_msg += " here: \""; error_msg += std::string(error_pos, last); // iterators to error-pos, end error_msg += "\""; //put a breakpoint here if you don't have std::cout for the console or change //this line for something else. Std::cout ScriptNodes; template struct NodeGrammar: public grammar { using boost::spirit::arg_names; //edit1 NodeGrammar: NodeGrammar::base_type(start) { //I had problem if I didn't add the eps rule (which do nothing) so you might //want to leave it start %= ident_decl | some_other_node_decl >> eps; ident_decl %= keyword_table > ident; //I'm not sure if the %= operator will work correctly on this, you might have to do //the push_back manually but I think it should work ident %= rawlexeme((alpha | char_('_')) >> *(alnum | char_('_'))) - keywords_table_; on_error(start, error_handler(_1, _2, _3, _4)); //edit1 } my_keywords keyword_table_; boost::spirit::qi::rule start; boost::spirit::qi::rule ident_decl; boost::spirit::qi::rule ident_decl; boost::spirit::qi::rule ident; boost::phoenix::function error_handler; //edit1 }; Also I don't know which version you use but I used the one in boost 1.40 and it seems there is a bug when using operator %= followed by only one argument (the parser would not parse correctly this rule). Ex: ident_decl %= ident; do this instead ident_decl %= ident > eps; which should be equivalent.

Hope this helped.

Thanks for try, but it doesn't work for me. I have many errors, such as: error: no matching function for call to 'boost::fusion::vector_data1, Freefoil::Private::ident_decl_node&>::vector_data1(int&)'| boost/fusion/container/vector/detail/vector_n. Hpp – varnie Oct 28 '09 at 13:48 wow!

I've solved it! Your note about adding ">> eps" to the end of rule was a cause of problem! In any case, the rule: start %= ident_decl; compiles fine.

Good, now I have a toy compilable grammar. Thank you! – varnie Oct 28 '09 at 14:11 Hmm weird, >> eps should not do anything.

I had problem at runtime if I didn't had >> eps when working with operator %=. Watch it if your program assert at runtime saying something about intrusive_ptr ptr == NULL. But you don't use the same version as I so I don't know.

Cheers for solving your problem varnie! – n1ckp Oct 28 '09 at 14:30.

I've been using boost spirit classic in the past and now i'm trying to stick to the newer one, boost spirit 2.x. Could someone be so kind to point me in how to deal with keywords? Say, I want to distinguish between "foo" and "int" where "foo" is identifier and "int" is just a keyword.

I want to protect my grammar from incorrect parsing, say, "intfoo". How to write it correctly, stating that "void", "float", etc are keywords? Thanks in advance.

I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.

Related Questions