• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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