From: OvermindDL1 <ove...@gm...> - 2010-07-30 03:47:39
|
On Thu, Jul 29, 2010 at 7:37 PM, Carl Barron <cba...@ro...> wrote: > > On Jul 29, 2010, at 9:18 PM, Joel de Guzman wrote: > >> On 7/29/2010 10:46 AM, Keith Rothman wrote: >>> I am trying to get both the attribute (in this case double) and the raw string >>> from a double_. >>> >>> I have something that works but it is "ugly" and uses grammar level state: >>> >>> #include<boost/config/warning_disable.hpp> >>> #include<boost/spirit/include/qi.hpp> >>> #include<boost/spirit/include/phoenix.hpp> >>> >>> #include<string> >>> >>> namespace client >>> { >>> >>> namespace qi = boost::spirit::qi; >>> struct double_str >>> { >>> double_str() {}; >>> template<typename T> >>> double_str(double d, const T& i) : d(d), str(i.begin(), i.end()) {}; >>> double d; >>> std::string str; >>> }; >>> >>> template<typename Iterator> >>> struct grammer : qi::grammar<Iterator, double_str()> >>> { >>> double tmp; >>> >>> grammer() : grammer::base_type(val, "val") >>> { >>> using qi::double_; >>> using qi::_val; >>> using qi::_1; >>> using qi::raw; >>> namespace phx = boost::phoenix; >>> >>> val = raw[double_[ phx::ref(tmp) = _1] ][ _val = phx::construct<double_str>( >>> phx::ref(tmp), _1 ) ]; >>> } >>> >>> qi::rule<Iterator, double_str()> val; >>> }; >>> } >>> >>> int main(int argc, char *argv[]) >>> { >>> client::grammer<std::string::const_iterator> gram; >>> std::string str("1e5"); >>> >>> std::string::const_iterator iter = str.begin(); >>> std::string::const_iterator end = str.end(); >>> >>> client::double_str ds; >>> >>> bool r = parse(iter, end, gram, ds); >>> } >>> >>> Is there a cleaner way (no grammar level variable, or less semantic actions)? >> >> I'd use the same approach, but I'll adapt the double_str to fusion instead >> and stuff the data directly. E.g. (using phoenix::at_c): >> >> val = raw[double_[at_c<0>(_val) = _1] ] >> [at_c<0>(_val) = construct<std::string>(begin(_1), end(_1))]; > > > > 1) op %= instead of op = eliminates the construction via phoenix. > now if you want the fusion sequeence <string,double> > 2) a simple start rule will produce it via attrib > > start = val >> attrib(phx::ref(tmp); > > > so I'd keep the grammar and do 1 and 2, Maybe even just this? typedef boost::fusion::vector<std::string,double> str_double; qi::rule<Iterator, str_double(), local<double> > val; val %= raw[double[_a = _1]] >> attr(_a); |