diff --git a/include/mapnik/parse_path.hpp b/include/mapnik/parse_path.hpp index 7990e9fb5..66cf0ddfe 100644 --- a/include/mapnik/parse_path.hpp +++ b/include/mapnik/parse_path.hpp @@ -43,8 +43,13 @@ namespace mapnik { typedef boost::variant path_component; typedef std::vector path_expression; typedef boost::shared_ptr path_expression_ptr; +template struct path_expression_grammar; MAPNIK_DECL path_expression_ptr parse_path(std::string const & str); +MAPNIK_DECL bool parse_path_from_string(path_expression_ptr const& path, + std::string const & str, + path_expression_grammar const& g); + template struct path_processor diff --git a/include/mapnik/path_expression_grammar.hpp b/include/mapnik/path_expression_grammar.hpp index 5da749b11..9c11e29eb 100644 --- a/include/mapnik/path_expression_grammar.hpp +++ b/include/mapnik/path_expression_grammar.hpp @@ -60,6 +60,7 @@ namespace standard_wide = boost::spirit::standard_wide; using standard_wide::space_type; using standard_wide::space; +typedef boost::variant path_component; template struct path_expression_grammar : qi::grammar(), space_type> diff --git a/include/mapnik/xml_node.hpp b/include/mapnik/xml_node.hpp index 82c8ded0b..8d2858e46 100644 --- a/include/mapnik/xml_node.hpp +++ b/include/mapnik/xml_node.hpp @@ -119,6 +119,11 @@ public: std::string get_text() const; + xml_tree const& get_tree() const + { + return tree_; + } + template T get_value() const; private: diff --git a/include/mapnik/xml_tree.hpp b/include/mapnik/xml_tree.hpp index 27893d262..d5beb9614 100644 --- a/include/mapnik/xml_tree.hpp +++ b/include/mapnik/xml_tree.hpp @@ -25,6 +25,7 @@ //mapnik #include #include +#include // boost #include @@ -55,6 +56,7 @@ private: public: mapnik::css_color_grammar color_grammar; mapnik::expression_grammar expr_grammar; + path_expression_grammar path_expr_grammar; }; } //ns mapnik diff --git a/src/load_map.cpp b/src/load_map.cpp index 901098411..0db27b8c3 100644 --- a/src/load_map.cpp +++ b/src/load_map.cpp @@ -782,7 +782,13 @@ void map_parser::parse_point_symbolizer(rule & rule, xml_node const & sym) *file = ensure_relative_to_xml(file); - symbol.set_filename(parse_path(*file)); + path_expression_ptr expr(boost::make_shared()); + if (!parse_path_from_string(expr, *file, sym.get_tree().path_expr_grammar)) + { + throw mapnik::config_error("Failed to parse path_expression '" + *file + "'"); + } + + symbol.set_filename(expr); if (transform_wkt) { @@ -865,7 +871,13 @@ void map_parser::parse_markers_symbolizer(rule & rule, xml_node const& sym) } } - markers_symbolizer symbol(parse_path(filename)); + path_expression_ptr expr(boost::make_shared()); + if (!parse_path_from_string(expr, filename, sym.get_tree().path_expr_grammar)) + { + throw mapnik::config_error("Failed to parse path_expression '" + filename + "'"); + } + markers_symbolizer symbol(expr); + optional opacity = sym.get_opt_attr("opacity"); if (opacity) symbol.set_opacity(*opacity); @@ -961,8 +973,12 @@ void map_parser::parse_line_pattern_symbolizer(rule & rule, xml_node const & sym } file = ensure_relative_to_xml(file); - - line_pattern_symbolizer symbol(parse_path(file)); + path_expression_ptr expr(boost::make_shared()); + if (!parse_path_from_string(expr, file, sym.get_tree().path_expr_grammar)) + { + throw mapnik::config_error("Failed to parse path_expression '" + file + "'"); + } + line_pattern_symbolizer symbol(expr); parse_metawriter_in_symbolizer(symbol, sym); rule.append(symbol); @@ -1009,7 +1025,12 @@ void map_parser::parse_polygon_pattern_symbolizer(rule & rule, file = ensure_relative_to_xml(file); - polygon_pattern_symbolizer symbol(parse_path(file)); + path_expression_ptr expr(boost::make_shared()); + if (!parse_path_from_string(expr, file, sym.get_tree().path_expr_grammar)) + { + throw mapnik::config_error("Failed to parse path_expression '" + file + "'"); + } + polygon_pattern_symbolizer symbol(expr); // pattern alignment pattern_alignment_e p_alignment = sym.get_attr("alignment",LOCAL_ALIGNMENT); @@ -1159,7 +1180,12 @@ void map_parser::parse_shield_symbolizer(rule & rule, xml_node const& sym) } image_file = ensure_relative_to_xml(image_file); - shield_symbol.set_filename(parse_path(image_file)); + path_expression_ptr expr(boost::make_shared()); + if (!parse_path_from_string(expr, image_file, sym.get_tree().path_expr_grammar)) + { + throw mapnik::config_error("Failed to parse path_expression '" + image_file + "'"); + } + shield_symbol.set_filename(expr); } catch (image_reader_exception const & ex) { diff --git a/src/parse_path.cpp b/src/parse_path.cpp index 2c9fb9030..9e564653a 100644 --- a/src/parse_path.cpp +++ b/src/parse_path.cpp @@ -29,7 +29,7 @@ namespace mapnik { path_expression_ptr parse_path(std::string const & str) { - path_expression_ptr path = boost::make_shared() ; + path_expression_ptr path = boost::make_shared(); path_expression_grammar g; std::string::const_iterator itr = str.begin(); @@ -44,4 +44,15 @@ path_expression_ptr parse_path(std::string const & str) throw std::runtime_error("Failed to parse path expression"); } } + +bool parse_path_from_string(path_expression_ptr const& path, + std::string const & str, + path_expression_grammar const& g) +{ + std::string::const_iterator itr = str.begin(); + std::string::const_iterator end = str.end(); + bool r = qi::phrase_parse(itr, end, g, space, *path); + return (r && itr==end); +} + } diff --git a/src/xml_tree.cpp b/src/xml_tree.cpp index 26c3a3bf7..6ff31e7d9 100644 --- a/src/xml_tree.cpp +++ b/src/xml_tree.cpp @@ -171,7 +171,8 @@ xml_tree::xml_tree(std::string const& encoding) file_(), tr_(encoding), color_grammar(), - expr_grammar(tr_) + expr_grammar(tr_), + path_expr_grammar() { node_.set_processed(true); //root node is always processed }