18 #ifndef UNIT_CONVERTER_TEMPLATE_HH_ 19 #define UNIT_CONVERTER_TEMPLATE_HH_ 22 #include <boost/bind.hpp> 23 #include <boost/function.hpp> 24 #include <boost/version.hpp> 27 #if BOOST_VERSION >= 103800 28 #include <boost/spirit/include/classic_core.hpp> 29 #include <boost/spirit/include/classic_confix.hpp> 30 #include <boost/spirit/include/classic_escape_char.hpp> 31 #include <boost/spirit/include/classic_multi_pass.hpp> 32 #include <boost/spirit/include/classic_position_iterator.hpp> 33 #define spirit_namespace boost::spirit::classic 35 #include <boost/spirit/core.hpp> 36 #include <boost/spirit/utility/confix.hpp> 37 #include <boost/spirit/utility/escape_char.hpp> 38 #include <boost/spirit/iterator/multi_pass.hpp> 39 #include <boost/spirit/iterator/position_iterator.hpp> 40 #define spirit_namespace boost::spirit 47 const spirit_namespace::int_parser < boost::int64_t >
int64_p = spirit_namespace::int_parser < boost::int64_t >();
48 const spirit_namespace::uint_parser< boost::uint64_t >
uint64_p = spirit_namespace::uint_parser< boost::uint64_t >();
72 template<
class Iter_type >
86 std::string key =
get_str(begin, end);
121 std::stringstream ss;
122 ss <<
"Value of exponent '" <<
get_str( begin, end ) <<
"' is not integer";
123 THROW( ExcInvalidUnit() << EI_UnitError(ss.str()) );
129 std::stringstream ss;
131 ss <<
"Missing declaration of shortcut '.." <<
get_str( begin-4, end+4 ) <<
"..'";
133 ss <<
"Invalid shortcut of unit '" <<
get_str( begin, end ) <<
"'";
135 THROW( ExcInvalidUnit() << EI_UnitError(ss.str()) );
141 std::stringstream ss;
142 ss <<
"Invalid expression '" <<
get_str( begin, end ) <<
"', missing '='";
143 THROW( ExcInvalidUnit() << EI_UnitError(ss.str()) );
160 formula_it !=
it->second.factors_.end(); ++formula_it)
162 if (formula_it->factor_ ==
it->first) {
163 std::stringstream ss;
164 ss <<
"Cyclic declaration of unit '" <<
it->first <<
"'";
165 THROW( ExcInvalidUnit() << EI_UnitError(ss.str()) );
169 std::stringstream ss;
170 ss <<
"Shortcut '" << formula_it->factor_ <<
"' is in conflict with predefined unit";
171 THROW( ExcInvalidUnit() << EI_UnitError(ss.str()) );
173 formula_it->basic_ =
false;
176 std::stringstream ss;
177 ss <<
"Unit '" << formula_it->factor_ <<
"' is not defined";
178 THROW( ExcInvalidUnit() << EI_UnitError(ss.str()) );
192 inline std::string
get_str( std::string::const_iterator begin, std::string::const_iterator end )
const 194 return std::string( begin, end );
209 template<
class Iter_type >
210 class UnitSIGrammer :
public spirit_namespace::grammar< UnitSIGrammer< Iter_type > >
218 : actions_( semantic_actions )
224 template<
typename ScannerT >
236 typedef boost::function< void( Iter_type, Iter_type ) > Str_action;
237 typedef boost::function< void( double ) > Real_action;
238 typedef boost::function< void( boost::int64_t ) > Int_action;
240 Str_action
new_shortcut ( boost::bind( &Semantic_actions_t::new_shortcut, &
self.actions_, _1, _2 ) );
241 Str_action
new_mult_factor ( boost::bind( &Semantic_actions_t::new_mult_factor, &
self.actions_, _1, _2 ) );
242 Str_action
new_div_factor ( boost::bind( &Semantic_actions_t::new_div_factor, &
self.actions_, _1, _2 ) );
243 Real_action
new_multipl ( boost::bind( &Semantic_actions_t::new_multipl, &
self.actions_, _1 ) );
244 Int_action
new_exp ( boost::bind( &Semantic_actions_t::new_exp, &
self.actions_, _1 ) );
245 Str_action
throw_exp_not_int ( boost::bind( &Semantic_actions_t::throw_exp_not_int, &
self.actions_, _1, _2 ) );
246 Str_action
throw_not_equating ( boost::bind( &Semantic_actions_t::throw_not_equating, &
self.actions_, _1, _2 ) );
247 Str_action
throw_not_shortcut ( boost::bind( &Semantic_actions_t::throw_not_shortcut, &
self.actions_, _1, _2 ) );
252 = formula_ >> *( ch_p(
';') >> *space_p >> constant_ )
257 >> *( (ch_p(
'*') >> formula_factor_[ new_mult_factor ] >> !( ch_p(
'^') >> exp_ ) )
258 | (ch_p(
'/') >> formula_factor_[
new_div_factor ] >> !( ch_p(
'^') >> exp_ ) )
264 | ( alpha_p >> *( anychar_p - ch_p(
';') - ch_p(
'*') - ch_p(
'/') - ch_p(
'=') - ch_p(
'^') - space_p ) )
270 >> ch_p(
'=') >> *space_p >> constant_value_ )
271 | constant_err_[ throw_not_equating ]
275 = !(constant_multiplicator_ >> ch_p(
'*'))
280 = +( anychar_p - ch_p(
';') )
283 constant_multiplicator_
294 = +( anychar_p - ch_p(
';') - ch_p(
'*') - ch_p(
'/') - space_p )
298 = *( anychar_p - ch_p(
';') - ch_p(
'*') - ch_p(
'/') - ch_p(
';') - ch_p(
'^') )
302 = *( alnum_p | ch_p(
'_') )
303 >> ( anychar_p - alnum_p - ch_p(
'_') - ch_p(
';') - ch_p(
'*') - ch_p(
'/') - ch_p(
'=') - ch_p(
'^') - space_p )
304 >> *( alnum_p | ch_p(
'_') )
309 spirit_namespace::rule< ScannerT >
unit_, formula_, formula_factor_, exp_, exp_err_, constant_,
310 constant_value_, constant_err_, constant_multiplicator_, shortcut_err_, forbidden_char_;
312 const spirit_namespace::rule< ScannerT >&
start()
const {
return unit_; }
int factor_idx_
index to actual item of subvector of factors of unit_data_
UnitsMap units_map_
Define all base and derived units given by their symbol.
void throw_not_shortcut(Iter_type begin, Iter_type end)
Throw exception if shortcut of factor is not in correct format.
void throw_not_equating(Iter_type begin, Iter_type end)
Throw exception if sign '=' missing in definition.
std::string get_str(std::string::const_iterator begin, std::string::const_iterator end) const
void check_unit_data()
Check unit_data_ object.
Definition of unit grammar.
Semantic_actions_t & actions_
Semantic_actions & operator=(const Semantic_actions &)
void new_shortcut(Iter_type begin, Iter_type end)
Add new definition of formula.
void new_multipl(double d)
Add multipicative coeficient of unit.
const spirit_namespace::uint_parser< boost::uint64_t > uint64_p
Class manages parsing of user defined field unit.
void new_mult_factor(Iter_type begin, Iter_type end)
Add new factor of unit (factor is multiplying)
UnitData unit_data_
Full parsed data.
Semantic_actions< Iter_type > Semantic_actions_t
void new_exp(boost::int64_t i)
Compute exponent to actual factor of unit.
const spirit_namespace::rule< ScannerT > & start() const
const spirit_namespace::int_parser< boost::int64_t > int64_p
void throw_exp_not_int(Iter_type begin, Iter_type end)
Throw exception if exponent is not in correct format.
definition(const UnitSIGrammer &self)
spirit_namespace::rule< ScannerT > unit_
std::string unit_data_key_
key of actual item of unit_data_
UnitData unit_data() const
Store structure given by parser.
UnitSIGrammer(Semantic_actions_t &semantic_actions)
Constructor.
void new_div_factor(Iter_type begin, Iter_type end)
Add new factor of unit (factor is dividing)
static const BasicFactors basic_factors
Define all base and derived units given by their symbol.
Semantic_actions()
Constructor.
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.