Using Boost.Spirit with Boost.Units

Hi, I need to be able to construct expressions from a collection of basic units and prefixes. The expression is provided as a string and thus needs to be parsed first. I have been able to achieve without too much trouble. What I am having trouble with is constructing the appropriated expressions using the Boost.Units library. I'm still very new to these two boost libraries so any pointers on how to achieve what I'm after (is it possible?) would be very much appreciated. Please see my code below: ----------------------------------- #include <boost/spirit/include/phoenix.hpp> #include <boost/spirit/include/qi.hpp> #include <boost/units/systems/si.hpp> #include <boost/units/systems/si/prefixes.hpp> #include <boost/units/systems/cgs.hpp> #include <boost/units/systems/temperature/celsius.hpp> #include <boost/variant.hpp> #include <iostream> #include <string> using namespace boost::units; using namespace boost::units::si; // Most prefixes omitted for brevity. struct si_prefix_symbol_: boost::spirit::qi::symbols<char, int> { si_prefix_symbol_() { add ("k", 3) ("M", 6) ("G", 9) ("c", -2) ("m", -3) ; } } si_prefix_symbol; typedef boost::variant<quantity<cgs::mass>, quantity<length>, quantity<si::time>, quantity<absolute<si::temperature> >, quantity<absolute<celsius::temperature> >, double> variant_t; struct unit_symbol_: boost::spirit::qi::symbols<char, variant_t> { unit_symbol_() { add ("m", 1.0 * meter) ("g", 1.0 * cgs::gram) ("s", 1.0 * second) ("K", 1.0 * absolute<si::temperature>()) ("C", 1.0 * absolute<celsius::temperature>()) ; } } unit_symbol; template<class Iterator> struct unit_expression: boost::spirit::qi::grammar<Iterator, variant_t()> { unit_expression(): unit_expression::base_type(start) { using boost::spirit::int_; using boost::spirit::ascii::space; using boost::spirit::eps; using namespace boost::spirit::arg_names; start = eps[_val = 1.0] >> ( ( ( unit_symbol | si_prefix_symbol >> unit_symbol ) >> -( '^' >> int_ ) ) % space ) ; } boost::spirit::qi::rule<Iterator, variant_t()> start; }; int main() { std::string in("kg m^-2"); typedef std::string::const_iterator iterator_type; typedef unit_expression<iterator_type> unit_expression; iterator_type first = in.begin(); iterator_type last = in.end(); unit_expression unit_parser; variant_t result; bool r = parse(first, last, unit_parser, result); if(r && first == last) { std::cout << "success: " << result << std::endl; } else { std::cout << "parsing failed at: "; std::cout << std::string(first, last) << std::endl; } return 0; }
participants (1)
-
Vitaly Budovski