expressions - implement unary and binary function expression nodes

(sample functions: exp, pow, sin, cos, min, max, tan, atan)
This commit is contained in:
artemp 2014-08-25 14:17:18 +01:00
parent 48c23f27dc
commit 4adb0abb64
7 changed files with 134 additions and 29 deletions

View file

@ -126,9 +126,17 @@ struct evaluate_expression : util::static_visitor<T>
#endif
}
value_type operator() (function_call const& fun) const
value_type operator() (unary_function_call const& call) const
{
return value_type(123);// FIXME
value_type arg = util::apply_visitor(*this, call.arg);
return call.fun(arg);
}
value_type operator() (binary_function_call const& call) const
{
value_type arg1 = util::apply_visitor(*this, call.arg1);
value_type arg2 = util::apply_visitor(*this, call.arg2);
return call.fun(arg1, arg2);
}
template <typename ValueType>
@ -217,11 +225,18 @@ struct evaluate_expression<T, boost::none_t> : util::static_visitor<T>
#endif
}
value_type operator() (function_call const& fun) const
value_type operator() (unary_function_call const& call) const
{
return value_type(123);// FIXME
value_type arg = util::apply_visitor(*this, call.arg);
return call.fun(arg);
}
value_type operator() (binary_function_call const& call) const
{
value_type arg1 = util::apply_visitor(*this, call.arg1);
value_type arg2 = util::apply_visitor(*this, call.arg2);
return call.fun(arg1, arg2);
}
template <typename ValueType>
value_type operator() (ValueType const& val) const

View file

@ -149,9 +149,17 @@ struct evaluate : util::static_visitor<T1>
#endif
}
value_type operator() (function_call const& fun) const
value_type operator() (unary_function_call const& call) const
{
return value_integer(123);// FIXME
value_type arg = util::apply_visitor(*this, call.arg);
return call.fun(arg);
}
value_type operator() (binary_function_call const& call) const
{
value_type arg1 = util::apply_visitor(*this, call.arg1);
value_type arg2 = util::apply_visitor(*this, call.arg2);
return call.fun(arg1, arg2);
}
feature_type const& feature_;

View file

@ -39,8 +39,15 @@
// stl
#include <functional>
BOOST_FUSION_ADAPT_STRUCT(mapnik::function_call,
(mapnik::function_impl, fun)(mapnik::function_call::arguments_type, arguments))
BOOST_FUSION_ADAPT_STRUCT(mapnik::unary_function_call,
(mapnik::unary_function_impl, fun)
(mapnik::unary_function_call::argument_type, arg))
BOOST_FUSION_ADAPT_STRUCT(mapnik::binary_function_call,
(mapnik::binary_function_impl, fun)
(mapnik::binary_function_call::argument_type, arg1)
(mapnik::binary_function_call::argument_type, arg2))
namespace mapnik
{
@ -122,16 +129,68 @@ inline value_type exp_impl (value_type const& val)
{
return std::exp(val.to_double());
}
struct function_types : qi::symbols<char, function_impl>
// sin
inline value_type sin_impl (value_type const& val)
{
function_types()
return std::sin(val.to_double());
}
// cos
inline value_type cos_impl (value_type const& val)
{
return std::cos(val.to_double());
}
// tan
inline value_type tan_impl (value_type const& val)
{
return std::tan(val.to_double());
}
// atan
inline value_type atan_impl (value_type const& val)
{
return std::atan(val.to_double());
}
struct unary_function_types : qi::symbols<char, unary_function_impl>
{
unary_function_types()
{
add
("exp", unary_function_impl { &exp_impl })
("sin", unary_function_impl(sin_impl))
("cos", unary_function_impl(cos_impl))
("tan", unary_function_impl(tan_impl))
("atan", unary_function_impl(atan_impl))
("exp", unary_function_impl(exp_impl))
;
}
};
// binary functions
// min
inline value_type min_impl(value_type const& arg1, value_type const& arg2)
{
return std::min(arg1.to_double(), arg2.to_double());
}
// max
inline value_type max_impl(value_type const& arg1, value_type const& arg2)
{
return std::max(arg1.to_double(), arg2.to_double());
}
// pow
inline value_type pow_impl(value_type const& arg1, value_type const& arg2)
{
return std::pow(arg1.to_double(), arg2.to_double());
}
struct binary_function_types : qi::symbols<char, binary_function_impl>
{
binary_function_types()
{
add
("min", binary_function_impl(min_impl))
("max", binary_function_impl(max_impl))
("pow", binary_function_impl(pow_impl))
;
}
};
template <typename T>
@ -168,7 +227,8 @@ struct expression_grammar : qi::grammar<Iterator, expr_node(), space_type>
rule_type unary_expr;
rule_type not_expr;
rule_type primary_expr;
qi::rule<Iterator, function_call() , space_type> function_expr;
qi::rule<Iterator, unary_function_call() , space_type> unary_function_expr;
qi::rule<Iterator, binary_function_call() , space_type> binary_function_expr;
qi::rule<Iterator, std::string() > regex_match_expr;
qi::rule<Iterator, expr_node(expr_node), qi::locals<std::string,std::string>, space_type> regex_replace_expr;
qi::rule<Iterator, std::string() , space_type> attr;
@ -179,7 +239,8 @@ struct expression_grammar : qi::grammar<Iterator, expr_node(), space_type>
qi::symbols<char const, char const> unesc_char;
qi::rule<Iterator, char() > quote_char;
geometry_types geom_type;
function_types func_type;
unary_function_types unary_func_type;
binary_function_types binary_func_type;
};
} // namespace

View file

@ -150,7 +150,10 @@ expression_grammar<Iterator>::expression_grammar(std::string const& encoding)
)
;
function_expr = func_type >> lit('(') >> expr >> lit(')')
unary_function_expr = unary_func_type > lit('(') > expr > lit(')')
;
binary_function_expr = binary_func_type > lit('(') > expr > lit(',') > expr > lit(')')
;
unary_expr = primary_expr [_val = _1]
@ -169,6 +172,8 @@ expression_grammar<Iterator>::expression_grammar(std::string const& encoding)
| attr [_val = construct<mapnik::attribute>( _1 ) ]
| global_attr [_val = construct<mapnik::global_attribute>( _1 )]
| lit("not") >> expr [_val = !_1]
| unary_function_expr [_val = _1]
| binary_function_expr [_val = _1]
| '(' >> expr [_val = _1 ] >> ')'
| ustring[_val = unicode_(_1)] // if we get here then try parsing as unquoted string
;

View file

@ -36,6 +36,7 @@
#include <boost/regex.hpp>
#endif
#include <boost/variant.hpp>
#include <functional>
namespace mapnik
@ -125,23 +126,32 @@ struct regex_replace_node
};
#endif
using nullary_function_impl = std::function<value_type()>;
using unary_function_impl = std::function<value_type(value_type const&)>;
using binary_function_impl = std::function<value_type(value_type const&, value_type const&)>;
typedef util::variant<nullary_function_impl, unary_function_impl, binary_function_impl> function_impl;
struct function_call
struct unary_function_call
{
using arguments_type = std::vector<expr_node>;
function_call(function_impl fun, arguments_type const& arguments)
: fun(fun), arguments(arguments) { }
using argument_type = expr_node;
unary_function_call() = default;
unary_function_call(unary_function_impl fun, argument_type const& arg)
: fun(fun), arg(arg) {}
function_impl fun;
arguments_type arguments;
unary_function_impl fun;
argument_type arg;
};
inline expr_node& operator- (expr_node& expr)
struct binary_function_call
{
using argument_type = expr_node;
binary_function_call() = default;
binary_function_call(binary_function_impl fun, argument_type const& arg1, argument_type const& arg2)
: fun(fun), arg1(arg1), arg2(arg2) {}
binary_function_impl fun;
argument_type arg1;
argument_type arg2;
};
inline expr_node & operator- (expr_node& expr)
{
return expr = unary_node<tags::negate>(expr);
}

View file

@ -163,7 +163,8 @@ struct regex_replace_node;
struct attribute;
struct global_attribute;
struct geometry_type_attribute;
struct function_call;
struct unary_function_call;
struct binary_function_call;
using expr_node = util::variant<
value_null,
@ -191,7 +192,8 @@ util::recursive_wrapper<binary_node<tags::logical_and> >,
util::recursive_wrapper<binary_node<tags::logical_or> >,
util::recursive_wrapper<regex_match_node>,
util::recursive_wrapper<regex_replace_node>,
util::recursive_wrapper<function_call>
util::recursive_wrapper<unary_function_call>,
util::recursive_wrapper<binary_function_call>
>;
}

View file

@ -128,9 +128,13 @@ struct expression_string : util::static_visitor<void>
str_ +="')";
}
void operator() (function_call const& fun) const
void operator() (unary_function_call const& call) const
{
str_ += "fun()";// FIXME
str_ += "fun(arg)";// FIXME
}
void operator() (binary_function_call const& call) const
{
str_ += "fun(arg1,arg2)";// FIXME
}
private:
std::string & str_;