Skip to content

Instantly share code, notes, and snippets.

@gordonwoodhull
Last active August 29, 2015 14:22
Show Gist options
  • Save gordonwoodhull/dcbb332eea06dd3279b9 to your computer and use it in GitHub Desktop.
Save gordonwoodhull/dcbb332eea06dd3279b9 to your computer and use it in GitHub Desktop.
Parse graphviz graph description at C++ compile time using metaparse! (incomplete)
#define MPLLIBS_LIMIT_SEQUENCE_SIZE 7
#define MPLLIBS_LIMIT_STRING_SIZE 256
#include <mpllibs/metaparse/string.hpp>
#include <mpllibs/metaparse/keyword.hpp>
#include <mpllibs/metaparse/token.hpp>
#include <mpllibs/metaparse/lit_c.hpp>
#include <mpllibs/metaparse/any.hpp>
#include <mpllibs/metaparse/alphanum.hpp>
#include <mpllibs/metaparse/sequence.hpp>
#include <mpllibs/metaparse/one_of.hpp>
#include <mpllibs/metaparse/empty.hpp>
#include <mpllibs/metaparse/build_parser.hpp>
#include <mpllibs/metaparse/entire_input.hpp>
#include <mpllibs/metaparse/foldr1.hpp>
#include <mpllibs/metaparse/foldlp.hpp>
#include <mpllibs/metaparse/return_.hpp>
#include <mpllibs/metaparse/transform.hpp>
#include <mpllibs/metaparse/middle_of.hpp>
#include <mpllibs/metaparse/last_of.hpp>
#include <boost/mpl/lambda.hpp>
#include <boost/mpl/push_front.hpp>
#include <boost/mpl/at.hpp>
using namespace mpllibs::metaparse;
namespace mpl = boost::mpl;
template<typename Parser, typename Default = void> using opt = one_of<Parser, return_<Default>>;
using graph_token = token<keyword<MPLLIBS_STRING("graph")>>;
using lbrace_token = token<lit_c<'{'>>;
using rbrace_token = token<lit_c<'}'>>;
using semi_token = token<lit_c<';'>>;
using lbracket_token = token<lit_c<'['>>;
using rbracket_token = token<lit_c<']'>>;
using comma_token = token<lit_c<','>>;
using equals_token = token<lit_c<'='>>;
// from grammar.hpp
typedef
token<
foldr1<
one_of<alphanum, lit_c<'_'> >,
string<>,
boost::mpl::lambda<
boost::mpl::push_front<boost::mpl::_1, boost::mpl::_2>
>::type
>
>
name_token;
using ID = name_token;
template<typename Name, typename Value>
struct attr_decl {
typedef attr_decl type; // why?;
};
template<typename AttrDecl>
struct declare_attr {
typedef attr_decl<typename mpl::at_c<AttrDecl, 0>::type, typename mpl::at_c<AttrDecl, 2>::type> type;
};
using attr = transform<
sequence<ID, equals_token, ID>,
mpl::quote1<declare_attr>
>;
using a_list = foldlp<
last_of<one_of<comma_token, semi_token>, attr>,
transform<attr, mpl::quote1<mpl::vector1>>,
mpl::quote2<mpl::push_back>
>;
using attr_list = middle_of<lbracket_token, a_list, rbracket_token>;
template<typename ID, typename Attrs>
struct node_decl {
typedef node_decl type; // why?
};
template<typename NodeDecl>
struct declare_node {
typedef node_decl<typename mpl::at_c<NodeDecl, 0>::type, typename mpl::at_c<NodeDecl, 1>::type> type;
};
using node_stmt = transform<
sequence<ID, opt<attr_list, mpl::vector<>>>,
mpl::quote1<declare_node>
>;
using arrow_token = token<keyword<MPLLIBS_STRING("->")>>;
template<typename Tail, typename Head, typename Attrs>
struct edge_decl {
typedef edge_decl type; //why?
};
template<typename EdgeDecl>
struct declare_edge {
typedef edge_decl<typename mpl::at_c<EdgeDecl, 0>::type,
typename mpl::at_c<EdgeDecl, 2>::type,
typename mpl::at_c<EdgeDecl, 3>::type> type;
};
using edge_stmt = transform<
sequence<ID, arrow_token, ID, opt<attr_list, mpl::vector<>>>,
mpl::quote1<declare_edge>
>;
using stmt = one_of<edge_stmt, node_stmt>; // not one_of<node_stmt, edge_stmt>;
using stmt_list = foldlp<
last_of<opt<semi_token>, stmt>, // not sequence<opt<semi_token>, stmt>
transform<stmt, mpl::quote1<mpl::vector1>>,
mpl::quote2<mpl::push_back>
>;
template<typename GraphDecl>
struct declare_graph :
mpl::pair<typename mpl::at_c<GraphDecl, 1>::type, typename mpl::at_c<GraphDecl, 3>::type>
{};
using graph_parser = build_parser<
entire_input<
transform<
sequence<
graph_token, opt<ID, string<>>, lbrace_token,
stmt_list,
rbrace_token
>,
mpl::quote1<declare_graph>
>
>>;
#define PRINT(T) static_assert(T::dummy_type, "hello there")
#include "gvparse.hpp"
#include "test.hpp"
using test1 = graph_parser::apply<MPLLIBS_STRING("graph g { A [x=y]; B->C [y=z, w=a]; D->E; F; G->H }")>::type;
PRINT(test1);
#include "gvparse.hpp"
#include "test.hpp"
using test1 = graph_parser::apply<MPLLIBS_STRING("graph g { A [x=y]; \
B->C [y=z, w=a]; \
D->E; \
F; \
G->H [a=b, b=c, c=d, d=e, e=f, f=g] \
}")>::type;
PRINT(test1);
#include "gvparse.hpp"
#include "test.hpp"
using test1 = graph_parser::apply<MPLLIBS_STRING("graph g { A [x=y]; \
B->C [y=z, w=a]; \
D->E; \
F; \
G->H [a=b, b=c, c=d, d=e, e=f, f=g]; \
I->J; \
J->K; \
K->L; \
L->M; \
M->N [g=h, h=i, i=j, j=k, k=l]; \
N->O; \
O->P [l=m; m=n; n=o; o=p]; \
P->Q; \
Q->R \
}")>::type;
PRINT(test1);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment