Skip to content

Instantly share code, notes, and snippets.

@akihiroy
Created September 3, 2010 07:14
Show Gist options
  • Save akihiroy/563539 to your computer and use it in GitHub Desktop.
Save akihiroy/563539 to your computer and use it in GitHub Desktop.
#include <string>
#include <vector>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
struct point {
float x;
float y;
};
BOOST_FUSION_ADAPT_STRUCT(
point,
(float, x)
(float, y)
)
enum path_cmd_type {
path_cmd_type_move,
path_cmd_type_closepath,
path_cmd_type_line,
path_cmd_type_cubicbezier,
path_cmd_type_quadraticbezier
};
struct path_cmd
{
path_cmd_type type;
point v1;
point v2;
point v3;
path_cmd() {}
path_cmd(path_cmd_type t, const point& vv1) : type(t), v1(vv1) {}
};
BOOST_FUSION_ADAPT_STRUCT(
path_cmd,
(path_cmd_type, type)
(point, v1)
(point, v2)
(point, v3)
)
typedef std::vector<path_cmd> path_data;
using boost::spirit::qi::rule;
using boost::spirit::qi::standard_wide::space_type;
template<class Iterator>
struct path_data_parser : boost::spirit::qi::grammar<Iterator, path_data(), space_type>
{
path_data_parser() : base_type(start)
{
using namespace boost::spirit::qi;
using namespace boost::phoenix;
start = *moveto_drawto_command_group[insert(_val, end(_val), begin(_1), end(_1))];
moveto_drawto_command_group = moveto[insert(_val, end(_val), begin(_1), end(_1))] >> *drawto_command[insert(_val, end(_val), begin(_1), end(_1))];
drawto_command = closepath[push_back(_val, _1)] | lineto[_val = _1] | curveto[_val = _1] | quadratic_bezier_curveto[_val = _1];
moveto = (lit('M') | lit('m')) >> moveto_argument_sequence[_val = _1];
moveto_argument_sequence = coordinate[push_back(_val, construct<path_cmd>(path_cmd_type_move, _1))] >> *(-lit(',') >> lineto_argument_sequence[insert(_val, end(_val), begin(_1), end(_1))]);
closepath = (lit('Z') | lit('z'))[at_c<0>(_val) = path_cmd_type_closepath];
lineto = (lit('L') | lit('l')) >> lineto_argument_sequence[_val = _1];
lineto_argument_sequence = coordinate[push_back(_val, construct<path_cmd>(path_cmd_type_line, _1))] >> *(-lit(',') >> lineto_argument_sequence[insert(_val, end(_val), begin(_1), end(_1))]);
curveto = (lit('C') | lit('c')) >> curveto_argument_sequence[_val = _1];
curveto_argument_sequence = curveto_argument[push_back(_val, _1)] >> *(-lit(',') >> curveto_argument_sequence[insert(_val, end(_val), begin(_1), end(_1))]);
curveto_argument = coordinate[_val = construct<path_cmd>(path_cmd_type_cubicbezier, _1)] >> -lit(',') >> coordinate[at_c<2>(_val) = _1] >> -lit(',') >> coordinate[at_c<3>(_val) = _1];
quadratic_bezier_curveto = (lit('Q') | lit('q')) >> quadratic_bezier_curveto_argument_sequence[_val = _1];
quadratic_bezier_curveto_argument_sequence = quadratic_bezier_curveto_argument[push_back(_val, _1)] >> *(-lit(',') >> quadratic_bezier_curveto_argument_sequence[insert(_val, end(_val), begin(_1), end(_1))]);
quadratic_bezier_curveto_argument = coordinate[_val = construct<path_cmd>(path_cmd_type_quadraticbezier, _1)] >> -lit(',') >> coordinate[at_c<2>(_val) = _1];
coordinate %= float_ >> -lit(',') >> float_;
}
rule<Iterator, path_data(), space_type> start;
rule<Iterator, path_data(), space_type> moveto_drawto_command_group;
rule<Iterator, path_data(), space_type> drawto_command;
rule<Iterator, path_data(), space_type> moveto;
rule<Iterator, path_data(), space_type> moveto_argument_sequence;
rule<Iterator, path_cmd(), space_type> closepath;
rule<Iterator, path_data(), space_type> lineto;
rule<Iterator, path_data(), space_type> lineto_argument_sequence;
rule<Iterator, path_data(), space_type> curveto;
rule<Iterator, path_data(), space_type> curveto_argument_sequence;
rule<Iterator, path_cmd(), space_type> curveto_argument;
rule<Iterator, path_data(), space_type> quadratic_bezier_curveto;
rule<Iterator, path_data(), space_type> quadratic_bezier_curveto_argument_sequence;
rule<Iterator, path_cmd(), space_type> quadratic_bezier_curveto_argument;
rule<Iterator, point(), space_type> coordinate;
};
int main()
{
std::wstring str_path_data(L"M 10 10 L 20 20z");
path_data data;
path_data_parser<std::wstring::const_iterator> g;
std::wstring::iterator it = str_path_data.begin();
bool res = boost::spirit::qi::phrase_parse(it, str_path_data.end(), g, boost::spirit::standard_wide::space, data);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment