diff --git a/include/mapnik/expression_evaluator.hpp b/include/mapnik/expression_evaluator.hpp index b2155f9da..a4d199012 100644 --- a/include/mapnik/expression_evaluator.hpp +++ b/include/mapnik/expression_evaluator.hpp @@ -73,6 +73,12 @@ struct evaluate : boost::static_visitor template value_type operator() (unary_node const& x) const + { + typename make_op::type func; + return func(boost::apply_visitor(*this, x.expr)); + } + + value_type operator() (unary_node const& x) const { return ! (boost::apply_visitor(evaluate(feature_),x.expr).to_bool()); } diff --git a/include/mapnik/expression_grammar.hpp b/include/mapnik/expression_grammar.hpp index c62b537cf..c74b70d47 100644 --- a/include/mapnik/expression_grammar.hpp +++ b/include/mapnik/expression_grammar.hpp @@ -198,21 +198,26 @@ struct expression_grammar : qi::grammar | ( (lit('>') | lit("gt") ) >> additive_expr [ _val > _1 ]) ) ; + additive_expr = multiplicative_expr [_val = _1] >> * ( '+' >> multiplicative_expr[_val += _1] | '-' >> multiplicative_expr[_val -= _1] ) ; - multiplicative_expr = primary_expr [_val = _1] - >> *( '*' >> primary_expr [_val *= _1] - | '/' >> primary_expr [_val /= _1] - | '%' >> primary_expr [_val %= _1] + multiplicative_expr = unary_expr [_val = _1] + >> *( '*' >> unary_expr [_val *= _1] + | '/' >> unary_expr [_val /= _1] + | '%' >> unary_expr [_val %= _1] | regex_match_expr[_val = regex_match_(_val, _1)] | regex_replace_expr(_val) [_val = _1] ) ; + unary_expr = primary_expr [_val = _1] + | '+' >> primary_expr [_val = _1] + | '-' >> primary_expr [_val = -_1] + ; primary_expr = strict_double [_val = _1] | int_ [_val = _1] @@ -256,6 +261,7 @@ struct expression_grammar : qi::grammar rule_type logical_expr; rule_type additive_expr; rule_type multiplicative_expr; + rule_type unary_expr; rule_type not_expr; rule_type primary_expr; qi::rule regex_match_expr; diff --git a/include/mapnik/expression_node.hpp b/include/mapnik/expression_node.hpp index 97608ec3b..a123297c5 100644 --- a/include/mapnik/expression_node.hpp +++ b/include/mapnik/expression_node.hpp @@ -40,6 +40,14 @@ namespace mapnik { namespace tags { +struct negate +{ + static const char* str() + { + return "-"; + } +}; + struct plus { static const char* str() @@ -166,6 +174,7 @@ typedef mapnik::value value_type; typedef boost::variant < value_type, attribute, +boost::recursive_wrapper >, boost::recursive_wrapper >, boost::recursive_wrapper >, boost::recursive_wrapper >, @@ -185,6 +194,7 @@ boost::recursive_wrapper > expr_node; template struct make_op; +template <> struct make_op { typedef std::negate type;}; template <> struct make_op { typedef std::plus type;}; template <> struct make_op { typedef std::minus type;}; template <> struct make_op { typedef std::multiplies type;}; @@ -289,6 +299,11 @@ struct function_call // ops +inline expr_node& operator- (expr_node& expr) +{ + return expr = unary_node(expr); +} + inline expr_node & operator += ( expr_node &left ,const expr_node &right) { return left = binary_node(left,right); diff --git a/include/mapnik/value.hpp b/include/mapnik/value.hpp index ab892d63f..06b1bdc30 100644 --- a/include/mapnik/value.hpp +++ b/include/mapnik/value.hpp @@ -524,6 +524,29 @@ struct mod: public boost::static_visitor } }; +template +struct negate : public boost::static_visitor +{ + typedef V value_type; + + template + value_type operator() (T val) const + { + return -val; + } + + value_type operator() (value_null const& val) const + { + return val; + } + + value_type operator() (UnicodeString const& ustr) const + { + UnicodeString inplace(ustr); + return inplace.reverse(); + } +}; + struct to_bool : public boost::static_visitor { bool operator() (bool val) const @@ -763,6 +786,11 @@ public: return boost::apply_visitor(impl::less_or_equal(),base_,other.base_); } + value operator- () const + { + return boost::apply_visitor(impl::negate(), base_); + } + value_base const& base() const { return base_;