1[#grammar] 2[section grammar] 3 4[h1 Synopsis] 5 6 template <class StartSymbol = BOOST_METAPARSE_STRING("S")> 7 struct grammar 8 { 9 template <class S, class Pos> 10 struct apply; 11 12 template <class Name, class P> 13 struct import; 14 15 template <class S, class Action = /* unspecified */> 16 struct rule; 17 }; 18 19[h1 Description] 20 21[note 22Note that using this adds a significant overhead to your builds. When someone 23uses your parser, the compiler will have to build your grammar parser, use it 24to parse your grammar and build your parser and then it can parse the input 25the user would like to parse with your parser. You might consider using the 26parser combinators the library provides. 27] 28 29Parser combinator for constructing parsers based on an embedded DSL similar to 30EBNF. It can be used the following way: 31 32 grammar<> 33 // definitions 34 35where a definition can be a rule or an import command. 36 37Rules look like on of the following: 38 39 ::rule<BOOST_METAPARSE_STRING("name ::= def")> 40 ::rule<BOOST_METAPARSE_STRING("name ::= def"), semantic_action> 41 42`name` consists of letters, digits and the `_` character. It is the name of 43the symbol being defined. `def` describes the rule. It can be 44 45* the name of a symbol 46* a terminal, which is a character between single quotes. `\` can be used for 47 escaping. The following are accepted: `\n`, `\r`, `\t`, `\\`, `\'` 48* a sequence of definitions 49* a definition followed by the `*` character, which means repetition accepting 50 0 match 51* a definition followed by the `+` character, which means repetition expecting 52 at least one match 53* a definition in brackets 54 55Rules take an optional `semantic_action` argument. It is a placeholder 56expression taking one argument. When this is given, this is used to transform 57the result of the rule. 58 59Imports can be used to turn an arbitrary parser into a symbol available for the 60rules. Import definitions look like the following: 61 62 ::import<BOOST_METAPARSE_STRING("name"), parser> 63 64`name` is the name of the symbol, `parser` is the parser to bind the name to. 65 66The start symbol of the grammar is specified by the template argument of the 67`grammar` template. This is optional, the default value is `S`. 68 69Note that the current implementation "inlines" the referenced symbols while 70parsing the grammar and recursion is not supported because of this. 71 72[h1 Header] 73 74 #include <boost/metaparse/grammar.hpp> 75 76[h1 Example] 77 78 #define BOOST_METAPARSE_LIMIT_STRING_SIZE 64 79 80 #include <boost/metaparse/grammar.hpp> 81 #include <boost/metaparse/token.hpp> 82 #include <boost/metaparse/int_.hpp> 83 #include <boost/metaparse/entire_input.hpp> 84 #include <boost/metaparse/build_parser.hpp> 85 #include <boost/metaparse/string.hpp> 86 87 #include <boost/mpl/front.hpp> 88 #include <boost/mpl/back.hpp> 89 #include <boost/mpl/plus.hpp> 90 #include <boost/mpl/fold.hpp> 91 #include <boost/mpl/lambda.hpp> 92 93 using boost::metaparse::token; 94 using boost::metaparse::int_; 95 using boost::metaparse::build_parser; 96 using boost::metaparse::entire_input; 97 using boost::metaparse::grammar; 98 99 using boost::mpl::front; 100 using boost::mpl::back; 101 using boost::mpl::plus; 102 using boost::mpl::fold; 103 using boost::mpl::lambda; 104 using boost::mpl::_1; 105 using boost::mpl::_2; 106 107 template <class A, class B> 108 struct lazy_plus : boost::mpl::plus<typename A::type, typename B::type> {}; 109 110 template <class Sequence, class State, class ForwardOp> 111 struct lazy_fold : 112 fold<typename Sequence::type, typename State::type, typename ForwardOp::type> 113 {}; 114 115 using plus_action = 116 lazy_fold<back<_1>, front<_1>, lambda<lazy_plus<_1, back<_2>>>::type>; 117 118 using plus_grammar = 119 grammar<BOOST_METAPARSE_STRING("plus_exp")> 120 ::import<BOOST_METAPARSE_STRING("int_token"), token<int_>>::type 121 122 ::rule<BOOST_METAPARSE_STRING("ws ::= (' ' | '\n' | '\r' | '\t')*")>::type 123 ::rule<BOOST_METAPARSE_STRING("plus_token ::= '+' ws"), front<_1>>::type 124 ::rule<BOOST_METAPARSE_STRING("plus_exp ::= int_token (plus_token int_token)*"), plus_action>::type 125 ; 126 127 using plus_parser = build_parser<entire_input<plus_grammar>>; 128 129 static_assert( 130 plus_parser::apply<BOOST_METAPARSE_STRING("1 + 2 + 3 + 4")>::type::value == 10, 131 "Arithmetic expression should be evaluated" 132 ); 133 134[endsect] 135 136