Dear Boosters, The following code is one of my first attempts to use Spirit/Qi. For my education, I have tried 2 techniques to parse the simple "aaa=131;" string. The first one (Block A) compiles and seems to output the expected result. The second (B) does not compile with a huge massively templatized backtrace that I don't understand. What is the difference between using online rules and rule objects ? Is there a syntax error somewhere ? I'm afraid the documentation and example are rather terse about the syntax to be used here when coupling Qi and Phoenix... Many thanks for your help. best regards frc -- <pre> #include <iostream> #include <string> #include <vector> // - Boost/Spirit #include <boost/spirit/include/qi.hpp> #include <boost/spirit/include/phoenix_core.hpp> #include <boost/spirit/include/phoenix_operator.hpp> int main( int argc_, char * argv_[]) { int error_code = EXIT_SUCCESS; using boost::spirit::qi::double_; using boost::spirit::qi::string; using boost::spirit::qi::lit; using boost::spirit::qi::lexeme; using boost::spirit::qi::phrase_parse; using boost::spirit::qi::_1; using boost::spirit::qi::as_string; using boost::spirit::ascii::space; using boost::spirit::ascii::char_; using boost::phoenix::ref; { // Block A /// This compiles: std::string s = "aaa=131;"; std::cout << "s: '" << s << "'" << std::endl; std::string::iterator strbegin = s.begin(); std::vector<char> vkey; std::vector<char> vvalue; bool r = phrase_parse( strbegin, s.end(), (+(char_ - '='))[boost::phoenix::ref(vkey) = boost::spirit::qi::_1 ] >> '=' >> *space >> lexeme[+(char_ - ';')][boost::phoenix::ref(vvalue) = boost::spirit::qi::_1 ], space ); if (r) { std::string key(vkey.begin(), vkey.end()); std::string value(vvalue.begin(), vvalue.end()); std::cout << "key : '" << key << "'" << std::endl; std::cout << "value : '" << value << "'" << std::endl; } } { /// Block B /// This doesn't: std::string s = "aaa=131;"; std::cout << "s: '" << s << "'" << std::endl; std::string::iterator strbegin = s.begin(); std::vector<char> vkey; std::vector<char> vvalue; boost::spirit::qi::rule<std::string::iterator> key_rule = +(char_ - '='); boost::spirit::qi::rule<std::string::iterator> value_rule = lexeme[+(char_ - ';')]; bool r = phrase_parse( strbegin, s.end(), key_rule[boost::phoenix::ref(vkey) = boost::spirit::qi::_1 ] >> '=' >> *space >> value_rule[boost::phoenix::ref(vvalue) = boost::spirit::qi::_1 ], space ); if (r) { std::string key(vkey.begin(), vkey.end()); std::string value(vvalue.begin(), vvalue.end()); std::cout << "key : '" << key << "'" << std::endl; std::cout << "value : '" << value << "'" << std::endl; } } return error_code; } </pre> -- François Mauger
2013/12/12 Francois Mauger <mauger@lpccaen.in2p3.fr>
Dear Boosters,
The following code is one of my first attempts to use Spirit/Qi. For my education, I have tried 2 techniques to parse the simple "aaa=131;" string. The first one (Block A) compiles and seems to output the expected result. The second (B) does not compile with a huge massively templatized backtrace that I don't understand. What is the difference between using online rules and rule objects ? Is there a syntax error somewhere ? I'm afraid the documentation and example are rather terse about the syntax to be used here when coupling Qi and Phoenix...
[snip]
boost::spirit::qi::rule<std::string::iterator> key_rule = +(char_ - '='); boost::spirit::qi::rule<std::string::iterator> value_rule = lexeme[+(char_ - ';')];
bool r = phrase_parse( strbegin, s.end(), key_rule[boost::phoenix::ref(vkey) = boost::spirit::qi::_1 ] // <----HERE >> '=' >> *space >> value_rule[boost::phoenix::ref(vvalue) = boost::spirit::qi::_1 ], // <----HERE space );
The problem is (at least what I see): your key_rule/value_rule have no attribute, so qi::_1 eventually evaluates to nothing (i.e. unused_type). To give them attr, for example: boost::spirit::qi::rule<std::string::iterator, std::vector<char>()> key_rule; And I'd suggest using attr propagation instead of the explicit semantic action if possible. HTH
On 12/12/2013 15:24, TONGARI J wrote: Hi TJ,
Thanks for this fast answer.
The problem is (at least what I see): your key_rule/value_rule have no attribute, so qi::_1 eventually evaluates to nothing (i.e. unused_type). To give them attr, for example:
boost::spirit::qi::rule<std::__string::iterator, std::vector<char>()> key_rule;
I have added to second template attribute for rules and it works ! <pre> boost::spirit::qi::rule<std::string::iterator, std::vector<char>()> key_rule = +(char_ - '='); boost::spirit::qi::rule<std::string::iterator, std::vector<char>()> value_rule = lexeme[+(char_ - ';')]; bool r = phrase_parse( strbegin, s.end(), key_rule[boost::phoenix::ref(vkey) = boost::spirit::qi::_1 ] >> '=' >> *space >> value_rule[boost::phoenix::ref(vvalue) = boost::spirit::qi::_1 ], space ); </pre> However I don't understand the "()" after the "std::vector<char>". what does it mean ? Does it refer to the std::vector constructor ? Also I have implemented the following to play directly with std::strings and not use temporary vectors of char anymore: <pre> boost::spirit::qi::rule<std::string::iterator, std::string()> key_rule = as_string[+(char_ - '=')]; boost::spirit::qi::rule<std::string::iterator, std::string()> value_rule = as_string[lexeme[+(char_ - ';')]]; std::string key; std::string value; bool r = phrase_parse( strbegin, s.end(), key_rule[boost::phoenix::ref(key) = boost::spirit::qi::_1 ] >> '=' >> *space >> value_rule[boost::phoenix::ref(value) = boost::spirit::qi::_1 ], space ); </pre> Guess what... it works... obviously. Many thanks for the fix.
And I'd suggest using attr propagation instead of the explicit semantic action if possible.
Thanks you for the suggestion but I'm afraid I don't understand that much what you speak about !!! ;-| I just had a quick look at this article: http://boost-spirit.com/home/articles/attribute_handling/attribute-propagati... but I need more time to allow this science to percolate in my brain (if possible!). Do you mean I should discard "...[boost::phoenix::ref(...) = ...]" stuff in my rules and use a "sink" data structure (some kind of fusion "container") <pre> Foo bar; bool r = phrase_parse( strbegin, s.end(), my_rule, bar); </pre> where Foo could be a sort of tuple aggregating more basic attributes ? Maybe can you show me an URL where I will find some "simple" code snippet... I'm ready to RTFM but first I should find it (at least the right one... there are so many confusing informations about Spirit for a newbie). Thanks. Best frc -- François Mauger
On 12/12/2013 10:47 AM, Francois Mauger wrote:
On 12/12/2013 15:24, TONGARI J wrote: Hi TJ,
<snip>
However I don't understand the "()" after the "std::vector<char>". what does it mean ? Does it refer to the std::vector constructor ?
It is function declaration syntax. It is specifying a function that returns a std::vector<char> and takes no parameters. Qi uses this syntax to specify what the rule will synthesize (produce or return) and the inherited parameters (arguments to the rule). <snip>
Do you mean I should discard "...[boost::phoenix::ref(...) = ...]" stuff in my rules and use a "sink" data structure (some kind of fusion "container") <pre> Foo bar; bool r = phrase_parse( strbegin, s.end(), my_rule, bar); </pre> where Foo could be a sort of tuple aggregating more basic attributes ?
Attribute parsing is the way to go. Avoid semantic actions as much as possible. Parse into a data structure and then post process that structure if needed. Foo might be a tuple or it might be some complex, recursive data structure... it will depend on what you are parsing.
Maybe can you show me an URL where I will find some "simple" code snippet... I'm ready to RTFM but first I should find it (at least the right one... there are so many confusing informations about Spirit for a newbie).
Perhaps this will help some. slides: http://ciere.com/boostcon10/index.html video: <http://wipkip.nikhef.nl/events/BoostCon/2010/Boostcon-MichaelCaisseUsingSpiritV2QiAndKarma799.mov> hth - michael -- Michael Caisse ciere consulting ciere.com
Hi
On 12/12/2013 20:13, Michael Caisse wrote: On 12/12/2013 10:47 AM, Francois Mauger wrote:
On 12/12/2013 15:24, TONGARI J wrote:
However I don't understand the "()" after the "std::vector<char>". what does it mean ? Does it refer to the std::vector constructor ?
It is function declaration syntax. It is specifying a function that returns a std::vector<char> and takes no parameters. Qi uses this syntax to specify what the rule will synthesize (produce or return) and the inherited parameters (arguments to the rule).
ok. now that's clearer (while the syntax is rather obfuscating)
Attribute parsing is the way to go. Avoid semantic actions as much as possible. Parse into a data structure and then post process that structure if needed. Foo might be a tuple or it might be some complex, recursive data structure... it will depend on what you are parsing.
well, this will be my approach after this first discovery round. I like it because post-processing will give me more freedom to manipulate the sink object.
Perhaps this will help some.
I know this (good) tutorial (yours... congratulation!). unfortunately I was really confused by the example with BOOST_FUSION_ADAPT_CLASS_NAMED in a first attempt to bind one of my class with Spirit/Qi/karma. I cannot find this macro in Boost 1.53. But see: <pre> $ tail -3 boost/version.hpp #define BOOST_LIB_VERSION "1_53" #endif $ tail -3 boost/fusion/include/adapt_assoc_class.hpp #include <boost/fusion/adapted/class/adapt_assoc_class.hpp> #endif $ ls boost/fusion/adapted/class/adapt_assoc_class.hpp ls: cannot access boost/fusion/adapted/class/adapt_assoc_class.hpp: No such file or directory </pre> Seems something is broken or badly cleaned in new versions of Boost. Then I found some *_AST_* macros. But it is too early for me to fight with it. I have found almost no simple examples to use it. Now I realize that AST probably refers to Abstract Syntax Tree and a probably a new underlying technique used in Spirit... Many thanks for your help. frc -- François Mauger Groupe "Interactions Fondamentales et Nature du Neutrino" NEMO-3/SuperNEMO Collaboration LPC Caen-CNRS/IN2P3-UCBN-ENSICAEN Département de Physique -- Université de Caen Basse-Normandie Adresse/address: Laboratoire de Physique Corpusculaire de Caen (UMR 6534) ENSICAEN 6, Boulevard du Marechal Juin 14050 CAEN Cedex FRANCE Courriel/e-mail: mauger@lpccaen.in2p3.fr Tél./phone: 02 31 45 25 12 / (+33) 2 31 45 25 12 Fax: 02 31 45 25 49 / (+33) 2 31 45 25 49
participants (3)
-
Francois Mauger
-
Michael Caisse
-
TONGARI J