transform expressions - split grammar into *.hpp *_def.hpp and *.cpp

This commit is contained in:
artemp 2015-12-09 11:53:57 +00:00
parent b7a54e5166
commit f3b6955533
7 changed files with 176 additions and 70 deletions

View file

@ -49,7 +49,7 @@ BOOST_SPIRIT_DECLARE(expression_grammar_type);
namespace mapnik namespace mapnik
{ {
grammar::expression_grammar_type expression_grammar(); grammar::expression_grammar_type expression_grammar();
} }

View file

@ -304,7 +304,7 @@ namespace mapnik { namespace grammar {
auto const ustring = x3::rule<class ustring, std::string> {} = no_skip[alpha > *alnum]; auto const ustring = x3::rule<class ustring, std::string> {} = no_skip[alpha > *alnum];
// start // start
auto const expression_def = logical_expression; auto const expression_def = logical_expression;
auto const logical_expression_def = conditional_expression[do_assign] > auto const logical_expression_def = conditional_expression[do_assign] >
*(((lit("and") | lit("&&")) > conditional_expression[do_and]) *(((lit("and") | lit("&&")) > conditional_expression[do_and])
@ -416,10 +416,10 @@ namespace mapnik { namespace grammar {
namespace mapnik namespace mapnik
{ {
grammar::expression_grammar_type expression_grammar() grammar::expression_grammar_type expression_grammar()
{ {
return grammar::expression; return grammar::expression;
} }
} }
#endif // MAPNIK_EXPRESSIONS_GRAMMAR_X3_DEF_HPP #endif // MAPNIK_EXPRESSIONS_GRAMMAR_X3_DEF_HPP

View file

@ -0,0 +1,51 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2015 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
#ifndef MAPNIK_TRANSFORM_GRAMMAR_X3_HPP
#define MAPNIK_TRANSFORM_GRAMMAR_X3_HPP
#include <mapnik/transform_expression.hpp>
#pragma GCC diagnostic push
#include <mapnik/warning_ignore.hpp>
#include <boost/spirit/home/x3.hpp>
#pragma GCC diagnostic pop
namespace mapnik {
namespace x3 = boost::spirit::x3;
namespace grammar {
struct transform_expression_class; // top-most ID
using transform_expression_grammar_type = x3::rule<transform_expression_class, mapnik::transform_list>;
BOOST_SPIRIT_DECLARE(transform_expression_grammar_type);
}} // ns
namespace mapnik
{
grammar::transform_expression_grammar_type transform_expression_grammar();
}
#endif

View file

@ -24,6 +24,7 @@
#define MAPNIK_TRANSFORM_GRAMMAR_X3_DEF_HPP #define MAPNIK_TRANSFORM_GRAMMAR_X3_DEF_HPP
#include <mapnik/transform_expression.hpp> #include <mapnik/transform_expression.hpp>
#include <mapnik/transform_expression_grammar_x3.hpp>
#include <mapnik/expression_grammar_x3.hpp> #include <mapnik/expression_grammar_x3.hpp>
#pragma GCC diagnostic push #pragma GCC diagnostic push
@ -67,78 +68,92 @@ BOOST_FUSION_ADAPT_STRUCT(mapnik::skewY_node,
namespace mapnik { namespace grammar { namespace mapnik { namespace grammar {
namespace x3 = boost::spirit::x3; namespace x3 = boost::spirit::x3;
namespace ascii = boost::spirit::x3::ascii; namespace ascii = boost::spirit::x3::ascii;
// [http://www.w3.org/TR/SVG/coords.html#TransformAttribute] // [http://www.w3.org/TR/SVG/coords.html#TransformAttribute]
// The value of the transform attribute is a <transform-list>, which // The value of the transform attribute is a <transform-list>, which
// is defined as a list of transform definitions, which are applied in // is defined as a list of transform definitions, which are applied in
// the order provided. The individual transform definitions are // the order provided. The individual transform definitions are
// separated by whitespace and/or a comma. // separated by whitespace and/or a comma.
using x3::double_; using x3::double_;
using x3::no_skip; using x3::no_skip;
using x3::no_case; using x3::no_case;
using x3::lit; using x3::lit;
using x3::char_; using x3::char_;
x3::rule<class transform_list_class, mapnik::transform_list> transform_list_rule("transform list"); // starting rule
x3::rule<class transform_node_class, mapnik::transform_node> transform_node_rule("transform node"); transform_expression_grammar_type const transform("transform");
x3::rule<class matrix_node_class, mapnik::matrix_node> matrix("matrix node"); // rules
x3::rule<class translate_node_class, mapnik::translate_node> translate("translate node"); x3::rule<class transform_list_class, mapnik::transform_list> transform_list_rule("transform list");
x3::rule<class scale_node_class, mapnik::scale_node> scale("scale node"); x3::rule<class transform_node_class, mapnik::transform_node> transform_node_rule("transform node");
x3::rule<class rotate_node_class, mapnik::rotate_node> rotate("rotate node"); x3::rule<class matrix_node_class, mapnik::matrix_node> matrix("matrix node");
x3::rule<class skewX_node_class, mapnik::skewX_node> skewX("skew X node"); x3::rule<class translate_node_class, mapnik::translate_node> translate("translate node");
x3::rule<class skewY_node_class, mapnik::skewY_node> skewY("skew Y node"); x3::rule<class scale_node_class, mapnik::scale_node> scale("scale node");
x3::rule<class rotate_node_class, mapnik::rotate_node> rotate("rotate node");
x3::rule<class skewX_node_class, mapnik::skewX_node> skewX("skew X node");
x3::rule<class skewY_node_class, mapnik::skewY_node> skewY("skew Y node");
// Import the expression rule // Import the expression rule
namespace { auto const& expr = expression_grammar(); } namespace { auto const& expr = expression_grammar(); }
auto const transform_list_rule_def = transform_node_rule % no_skip[char_(", ")]; // start
auto const transform_def = transform_list_rule;
auto const transform_node_rule_def = matrix | translate | scale | rotate | skewX | skewY ; auto const transform_list_rule_def = transform_node_rule % no_skip[char_(", ")];
// matrix(<a> <b> <c> <d> <e> <f>) auto const transform_node_rule_def = matrix | translate | scale | rotate | skewX | skewY ;
auto const matrix_def = no_case[lit("matrix")]
> '(' > expr > ',' > expr > ',' > expr > ',' > expr > ',' > expr > ',' > expr > ')'
;
// translate(<tx> [<ty>]) // matrix(<a> <b> <c> <d> <e> <f>)
auto const translate_def = no_case[lit("translate")] auto const matrix_def = no_case[lit("matrix")]
> '(' > expr > -(',' > expr ) > ')' > '(' > expr > ',' > expr > ',' > expr > ',' > expr > ',' > expr > ',' > expr > ')'
; ;
// scale(<sx> [<sy>]) // translate(<tx> [<ty>])
auto const scale_def = no_case[lit("scale")] auto const translate_def = no_case[lit("translate")]
> '(' > expr > -(',' > expr ) > ')' > '(' > expr > -(',' > expr ) > ')'
; ;
// rotate(<rotate-angle> [<cx> <cy>]) // scale(<sx> [<sy>])
auto const rotate_def = no_case[lit("rotate")] auto const scale_def = no_case[lit("scale")]
> '(' > expr > -(',' > expr > ',' > expr) > ')' > '(' > expr > -(',' > expr ) > ')'
; ;
// skewX(<skew-angle>) // rotate(<rotate-angle> [<cx> <cy>])
auto const skewX_def = no_case[lit("skewX")] auto const rotate_def = no_case[lit("rotate")]
> '(' > expr > ')'; > '(' > expr > -(',' > expr > ',' > expr) > ')'
;
// skewY(<skew-angle>) // skewX(<skew-angle>)
auto const skewY_def = no_case[lit("skewY")] auto const skewX_def = no_case[lit("skewX")]
> '(' > expr > ')'; > '(' > expr > ')';
// skewY(<skew-angle>)
auto const skewY_def = no_case[lit("skewY")]
> '(' > expr > ')';
BOOST_SPIRIT_DEFINE ( BOOST_SPIRIT_DEFINE (
transform_list_rule, transform,
transform_node_rule, transform_list_rule,
matrix, transform_node_rule,
translate, matrix,
scale, translate,
rotate, scale,
skewX, rotate,
skewY skewX,
); skewY);
}} // }} // ns
#endif // ns namespace mapnik
{
grammar::transform_expression_grammar_type transform_expression_grammar()
{
return grammar::transform;
}
}
#endif

View file

@ -169,6 +169,7 @@ source = Split(
expression_string.cpp expression_string.cpp
expression.cpp expression.cpp
transform_expression.cpp transform_expression.cpp
transform_expression_grammar_x3.cpp
feature_kv_iterator.cpp feature_kv_iterator.cpp
feature_style_processor.cpp feature_style_processor.cpp
feature_type_style.cpp feature_type_style.cpp

View file

@ -21,8 +21,9 @@
*****************************************************************************/ *****************************************************************************/
#include <mapnik/parse_transform.hpp> #include <mapnik/parse_transform.hpp>
#include <mapnik/transform_expression_grammar_x3_def.hpp> #include <mapnik/transform_expression_grammar_x3.hpp>
#include <mapnik/expression_grammar_x3_config.hpp> // transcoder_tag
#include <mapnik/config_error.hpp>
// stl // stl
#include <string> #include <string>
#include <stdexcept> #include <stdexcept>
@ -38,11 +39,19 @@ transform_list_ptr parse_transform(std::string const& str, std::string const& en
mapnik::transcoder const tr(encoding); mapnik::transcoder const tr(encoding);
auto const parser = boost::spirit::x3::with<mapnik::grammar::transcoder_tag>(std::ref(tr)) auto const parser = boost::spirit::x3::with<mapnik::grammar::transcoder_tag>(std::ref(tr))
[ [
mapnik::grammar::transform_list_rule mapnik::transform_expression_grammar()
]; ];
// FIXME : try/catch! bool status = false;
bool r = boost::spirit::x3::phrase_parse(itr, end, parser, space, *trans_list); try
if (r && itr == end) {
status = boost::spirit::x3::phrase_parse(itr, end, parser, space, *trans_list);
}
catch (boost::spirit::x3::expectation_failure<std::string::const_iterator> const& ex)
{
throw config_error("Failed to parse transform expression: \"" + str + "\"");
}
if (status && itr == end)
{ {
return trans_list; return trans_list;
} }

View file

@ -0,0 +1,30 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2015 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
#include <mapnik/transform_expression_grammar_x3_def.hpp>
#include <mapnik/expression_grammar_x3_config.hpp>
namespace mapnik { namespace grammar {
BOOST_SPIRIT_INSTANTIATE(transform_expression_grammar_type, iterator_type, context_type);
}}