#ifndef BOOST_METAPARSE_V1_GRAMMAR_HPP #define BOOST_METAPARSE_V1_GRAMMAR_HPP // Copyright Abel Sinkovics (abel@sinkovics.hu) 2012. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include <boost/metaparse/v1/repeated.hpp> #include <boost/metaparse/v1/repeated1.hpp> #include <boost/metaparse/v1/sequence.hpp> #include <boost/metaparse/v1/one_of.hpp> #include <boost/metaparse/v1/transform.hpp> #include <boost/metaparse/v1/lit.hpp> #include <boost/metaparse/v1/lit_c.hpp> #include <boost/metaparse/v1/token.hpp> #include <boost/metaparse/v1/keyword.hpp> #include <boost/metaparse/v1/middle_of.hpp> #include <boost/metaparse/v1/last_of.hpp> #include <boost/metaparse/v1/always.hpp> #include <boost/metaparse/v1/one_char_except_c.hpp> #include <boost/metaparse/v1/foldr1.hpp> #include <boost/metaparse/v1/foldl_start_with_parser.hpp> #include <boost/metaparse/v1/alphanum.hpp> #include <boost/metaparse/v1/build_parser.hpp> #include <boost/metaparse/v1/entire_input.hpp> #include <boost/metaparse/v1/string.hpp> #include <boost/metaparse/v1/impl/front_inserter.hpp> #include <boost/mpl/at.hpp> #include <boost/mpl/map.hpp> #include <boost/mpl/eval_if.hpp> #include <boost/mpl/has_key.hpp> #include <boost/mpl/lambda.hpp> #include <boost/mpl/front.hpp> #include <boost/mpl/back.hpp> #include <boost/mpl/pair.hpp> #include <boost/mpl/insert.hpp> /* * The grammar * * rule_definition ::= name_token define_token expression * expression ::= seq_expression (or_token seq_expression)* * seq_expression ::= repeated_expression+ * repeated_expression ::= name_expression (repeated_token | repeated1_token)* * name_expression ::= char_token | name_token | bracket_expression * bracket_expression ::= open_bracket_token expression close_bracket_token */ namespace boost { namespace metaparse { namespace v1 { namespace grammar_util { template <char Op, class FState> struct repeated_apply_impl { typedef repeated_apply_impl type; template <class G> struct apply : repeated<typename FState::template apply<G>::type> {}; }; template <class FState> struct repeated_apply_impl<'+', FState> { typedef repeated_apply_impl type; template <class G> struct apply : repeated1<typename FState::template apply<G>::type> {}; }; struct build_repeated { typedef build_repeated type; template <class FState, class T> struct apply : repeated_apply_impl<T::type::value, FState> {}; }; struct build_sequence { typedef build_sequence type; template <class FState, class FP> struct apply_impl { typedef apply_impl type; template <class G> struct apply : sequence< typename FState::template apply<G>::type, typename FP::template apply<G>::type > {}; }; template <class FState, class FP> struct apply : apply_impl<FState, FP> {}; }; struct build_selection { typedef build_selection type; template <class FState, class FP> struct apply_impl { typedef apply_impl type; template <class G> struct apply : one_of< typename FState::template apply<G>::type, typename FP::template apply<G>::type > {}; }; template <class FState, class FP> struct apply : apply_impl<FState, FP> {}; }; template <class G, class Name> struct get_parser { typedef typename boost::mpl::at<typename G::rules, Name>::type ::template apply<G> p; template <class Actions> struct impl : transform<typename p::type, typename Actions::type> {}; typedef typename boost::mpl::eval_if< typename boost::mpl::has_key<typename G::actions, Name>::type, impl<boost::mpl::at<typename G::actions, Name> >, p >::type type; }; struct build_name { typedef build_name type; template <class Name> struct apply_impl { typedef apply_impl type; template <class G> struct apply : get_parser<G, Name> {}; }; template <class Name> struct apply : apply_impl<Name> {}; }; struct build_char { typedef build_char type; template <class C> struct apply_impl { typedef apply_impl type; template <class G> struct apply : lit<C> {}; }; template <class C> struct apply : apply_impl<C> {}; }; typedef token<lit_c<'*'> > repeated_token; typedef token<lit_c<'+'> > repeated1_token; typedef token<lit_c<'|'> > or_token; typedef token<lit_c<'('> > open_bracket_token; typedef token<lit_c<')'> > close_bracket_token; typedef token<keyword<string<':',':','='> > > define_token; typedef middle_of< lit_c<'\''>, one_of< last_of< lit_c<'\\'>, one_of< always<lit_c<'n'>, boost::mpl::char_<'\n'> >, always<lit_c<'r'>, boost::mpl::char_<'\r'> >, always<lit_c<'t'>, boost::mpl::char_<'\t'> >, lit_c<'\\'>, lit_c<'\''> > >, one_char_except_c<'\''> >, token<lit_c<'\''> > > char_token; typedef token< foldr1< one_of<alphanum, lit_c<'_'> >, string<>, impl::front_inserter > > name_token; struct expression; typedef middle_of<open_bracket_token, expression, close_bracket_token> bracket_expression; typedef one_of< transform<char_token, build_char>, transform<name_token, build_name>, bracket_expression > name_expression; typedef foldl_start_with_parser< one_of<repeated_token, repeated1_token>, name_expression, build_repeated > repeated_expression; typedef foldl_start_with_parser< repeated_expression, repeated_expression, build_sequence > seq_expression; struct expression : foldl_start_with_parser< last_of<or_token, seq_expression>, seq_expression, build_selection > {}; typedef sequence<name_token, define_token, expression> rule_definition; typedef build_parser<entire_input<rule_definition> > parser_parser; template <class P> struct build_native_parser { typedef build_native_parser type; template <class G> struct apply { typedef P type; }; }; template <class S> struct build_parsed_parser { typedef typename parser_parser::apply<S>::type p; typedef typename boost::mpl::front<p>::type name; typedef typename boost::mpl::back<p>::type exp; struct the_parser { typedef the_parser type; template <class G> struct apply : exp::template apply<G> {}; }; typedef boost::mpl::pair<name, the_parser> type; }; typedef build_parser<name_token> name_parser; template <class S> struct rebuild : name_parser::template apply<S> {}; struct no_action; template <class G, class P, class F> struct add_rule; template <class G, class Name, class P> struct add_import; template <class Start, class Rules, class Actions> struct grammar_builder { typedef grammar_builder type; typedef Rules rules; typedef Actions actions; // Make it a parser template <class S, class Pos> struct apply : get_parser< grammar_builder, typename rebuild<Start>::type >::type::template apply<S, Pos> {}; template <class Name, class P> struct import : add_import<grammar_builder, typename rebuild<Name>::type, P> {}; template <class Def, class Action = no_action> struct rule : add_rule<grammar_builder, build_parsed_parser<Def>, Action> {}; }; template <class Start, class Rules, class Actions, class P> struct add_rule<grammar_builder<Start, Rules, Actions>, P, no_action> : grammar_builder< Start, typename boost::mpl::insert<Rules, typename P::type>::type, Actions > {}; template <class Start, class Rules, class Actions, class P, class F> struct add_rule<grammar_builder<Start, Rules, Actions>, P, F> : grammar_builder< Start, typename boost::mpl::insert<Rules, typename P::type>::type, typename boost::mpl::insert< Actions, boost::mpl::pair< typename P::name, typename boost::mpl::lambda<F>::type > > ::type > {}; template <class Start, class Rules, class Actions, class Name, class P> struct add_import<grammar_builder<Start, Rules, Actions>, Name, P> : grammar_builder< Start, typename boost::mpl::insert< Rules, boost::mpl::pair<Name, build_native_parser<P> > >::type, Actions > {}; } template <class Start = string<'S'> > struct grammar : grammar_util::grammar_builder< Start, boost::mpl::map<>, boost::mpl::map<> > {}; } } } #endif