• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #ifndef BOOST_METAPARSE_V1_GRAMMAR_HPP
2 #define BOOST_METAPARSE_V1_GRAMMAR_HPP
3 
4 // Copyright Abel Sinkovics (abel@sinkovics.hu)  2012.
5 // Distributed under the Boost Software License, Version 1.0.
6 //    (See accompanying file LICENSE_1_0.txt or copy at
7 //          http://www.boost.org/LICENSE_1_0.txt)
8 
9 #include <boost/metaparse/v1/repeated.hpp>
10 #include <boost/metaparse/v1/repeated1.hpp>
11 #include <boost/metaparse/v1/sequence.hpp>
12 #include <boost/metaparse/v1/one_of.hpp>
13 #include <boost/metaparse/v1/transform.hpp>
14 #include <boost/metaparse/v1/lit.hpp>
15 #include <boost/metaparse/v1/lit_c.hpp>
16 #include <boost/metaparse/v1/token.hpp>
17 #include <boost/metaparse/v1/keyword.hpp>
18 #include <boost/metaparse/v1/middle_of.hpp>
19 #include <boost/metaparse/v1/last_of.hpp>
20 #include <boost/metaparse/v1/always.hpp>
21 #include <boost/metaparse/v1/one_char_except_c.hpp>
22 #include <boost/metaparse/v1/foldr1.hpp>
23 #include <boost/metaparse/v1/foldl_start_with_parser.hpp>
24 #include <boost/metaparse/v1/alphanum.hpp>
25 #include <boost/metaparse/v1/build_parser.hpp>
26 #include <boost/metaparse/v1/entire_input.hpp>
27 #include <boost/metaparse/v1/string.hpp>
28 #include <boost/metaparse/v1/impl/front_inserter.hpp>
29 
30 #include <boost/mpl/at.hpp>
31 #include <boost/mpl/map.hpp>
32 #include <boost/mpl/eval_if.hpp>
33 #include <boost/mpl/has_key.hpp>
34 #include <boost/mpl/lambda.hpp>
35 #include <boost/mpl/front.hpp>
36 #include <boost/mpl/back.hpp>
37 #include <boost/mpl/pair.hpp>
38 #include <boost/mpl/insert.hpp>
39 
40 /*
41  * The grammar
42  *
43  * rule_definition ::= name_token define_token expression
44  * expression ::= seq_expression (or_token seq_expression)*
45  * seq_expression ::= repeated_expression+
46  * repeated_expression ::= name_expression (repeated_token | repeated1_token)*
47  * name_expression ::= char_token | name_token | bracket_expression
48  * bracket_expression ::= open_bracket_token expression close_bracket_token
49  */
50 
51 namespace boost
52 {
53   namespace metaparse
54   {
55     namespace v1
56     {
57       namespace grammar_util
58       {
59         template <char Op, class FState>
60         struct repeated_apply_impl
61         {
62           typedef repeated_apply_impl type;
63 
64           template <class G>
65           struct apply :
66             repeated<typename FState::template apply<G>::type>
67           {};
68         };
69 
70         template <class FState>
71         struct repeated_apply_impl<'+', FState>
72         {
73           typedef repeated_apply_impl type;
74 
75           template <class G>
76           struct apply :
77             repeated1<typename FState::template apply<G>::type>
78           {};
79         };
80 
81         struct build_repeated
82         {
83           typedef build_repeated type;
84 
85           template <class FState, class T>
86           struct apply : repeated_apply_impl<T::type::value, FState> {};
87         };
88 
89         struct build_sequence
90         {
91           typedef build_sequence type;
92 
93           template <class FState, class FP>
94           struct apply_impl
95           {
96             typedef apply_impl type;
97 
98             template <class G>
99             struct apply :
100               sequence<
101                 typename FState::template apply<G>::type,
102                 typename FP::template apply<G>::type
103               >
104             {};
105           };
106 
107           template <class FState, class FP>
108           struct apply : apply_impl<FState, FP> {};
109         };
110 
111         struct build_selection
112         {
113           typedef build_selection type;
114 
115           template <class FState, class FP>
116           struct apply_impl
117           {
118             typedef apply_impl type;
119 
120             template <class G>
121             struct apply :
122               one_of<
123                 typename FState::template apply<G>::type,
124                 typename FP::template apply<G>::type
125               >
126             {};
127           };
128 
129           template <class FState, class FP>
130           struct apply : apply_impl<FState, FP> {};
131         };
132 
133         template <class G, class Name>
134         struct get_parser
135         {
136           typedef
137             typename boost::mpl::at<typename G::rules, Name>::type
138               ::template apply<G>
139             p;
140 
141           template <class Actions>
142           struct impl : transform<typename p::type, typename Actions::type> {};
143 
144           typedef
145             typename boost::mpl::eval_if<
146               typename boost::mpl::has_key<typename G::actions, Name>::type,
147               impl<boost::mpl::at<typename G::actions, Name> >,
148               p
149             >::type
150             type;
151         };
152 
153         struct build_name
154         {
155           typedef build_name type;
156 
157           template <class Name>
158           struct apply_impl
159           {
160             typedef apply_impl type;
161 
162             template <class G>
163             struct apply : get_parser<G, Name> {};
164           };
165 
166           template <class Name>
167           struct apply : apply_impl<Name> {};
168         };
169 
170         struct build_char
171         {
172           typedef build_char type;
173 
174           template <class C>
175           struct apply_impl
176           {
177             typedef apply_impl type;
178 
179             template <class G>
180             struct apply : lit<C> {};
181           };
182 
183           template <class C>
184           struct apply : apply_impl<C> {};
185         };
186 
187         typedef token<lit_c<'*'> > repeated_token;
188         typedef token<lit_c<'+'> > repeated1_token;
189         typedef token<lit_c<'|'> > or_token;
190         typedef token<lit_c<'('> > open_bracket_token;
191         typedef token<lit_c<')'> > close_bracket_token;
192         typedef token<keyword<string<':',':','='> > > define_token;
193 
194         typedef
195           middle_of<
196             lit_c<'\''>,
197             one_of<
198               last_of<
199                 lit_c<'\\'>,
200                 one_of<
201                   always<lit_c<'n'>, boost::mpl::char_<'\n'> >,
202                   always<lit_c<'r'>, boost::mpl::char_<'\r'> >,
203                   always<lit_c<'t'>, boost::mpl::char_<'\t'> >,
204                   lit_c<'\\'>,
205                   lit_c<'\''>
206                 >
207               >,
208               one_char_except_c<'\''>
209             >,
210             token<lit_c<'\''> >
211           >
212           char_token;
213 
214         typedef
215           token<
216             foldr1<
217               one_of<alphanum, lit_c<'_'> >,
218               string<>,
219               impl::front_inserter
220             >
221           >
222           name_token;
223 
224         struct expression;
225 
226         typedef
227           middle_of<open_bracket_token, expression, close_bracket_token>
228           bracket_expression;
229 
230         typedef
231           one_of<
232             transform<char_token, build_char>,
233             transform<name_token, build_name>,
234             bracket_expression
235           >
236           name_expression;
237 
238         typedef
239           foldl_start_with_parser<
240             one_of<repeated_token, repeated1_token>,
241             name_expression,
242             build_repeated
243           >
244           repeated_expression;
245 
246         typedef
247           foldl_start_with_parser<
248             repeated_expression,
249             repeated_expression,
250             build_sequence
251           >
252           seq_expression;
253 
254         struct expression :
255           foldl_start_with_parser<
256             last_of<or_token, seq_expression>,
257             seq_expression,
258             build_selection
259           >
260         {};
261 
262         typedef sequence<name_token, define_token, expression> rule_definition;
263 
264         typedef build_parser<entire_input<rule_definition> > parser_parser;
265 
266         template <class P>
267         struct build_native_parser
268         {
269           typedef build_native_parser type;
270 
271           template <class G>
272           struct apply
273           {
274             typedef P type;
275           };
276         };
277 
278         template <class S>
279         struct build_parsed_parser
280         {
281           typedef typename parser_parser::apply<S>::type p;
282           typedef typename boost::mpl::front<p>::type name;
283           typedef typename boost::mpl::back<p>::type exp;
284 
285           struct the_parser
286           {
287             typedef the_parser type;
288 
289             template <class G>
290             struct apply : exp::template apply<G> {};
291           };
292 
293           typedef boost::mpl::pair<name, the_parser> type;
294         };
295 
296         typedef build_parser<name_token> name_parser;
297 
298         template <class S>
299         struct rebuild : name_parser::template apply<S> {};
300 
301         struct no_action;
302 
303         template <class G, class P, class F>
304         struct add_rule;
305 
306         template <class G, class Name, class P>
307         struct add_import;
308 
309         template <class Start, class Rules, class Actions>
310         struct grammar_builder
311         {
312           typedef grammar_builder type;
313           typedef Rules rules;
314           typedef Actions actions;
315 
316           // Make it a parser
317           template <class S, class Pos>
318           struct apply :
319             get_parser<
320               grammar_builder,
321               typename rebuild<Start>::type
322             >::type::template apply<S, Pos>
323           {};
324 
325           template <class Name, class P>
326           struct import :
327             add_import<grammar_builder, typename rebuild<Name>::type, P>
328           {};
329 
330           template <class Def, class Action = no_action>
331           struct rule :
332             add_rule<grammar_builder, build_parsed_parser<Def>, Action>
333           {};
334         };
335 
336         template <class Start, class Rules, class Actions, class P>
337         struct add_rule<grammar_builder<Start, Rules, Actions>, P, no_action> :
338           grammar_builder<
339             Start,
340             typename boost::mpl::insert<Rules, typename P::type>::type,
341             Actions
342           >
343         {};
344 
345         template <class Start, class Rules, class Actions, class P, class F>
346         struct add_rule<grammar_builder<Start, Rules, Actions>, P, F> :
347           grammar_builder<
348             Start,
349             typename boost::mpl::insert<Rules, typename P::type>::type,
350             typename boost::mpl::insert<
351               Actions,
352               boost::mpl::pair<
353                 typename P::name,
354                 typename boost::mpl::lambda<F>::type
355               >
356             >
357             ::type
358           >
359         {};
360 
361         template <class Start, class Rules, class Actions, class Name, class P>
362         struct add_import<grammar_builder<Start, Rules, Actions>, Name, P> :
363           grammar_builder<
364             Start,
365             typename boost::mpl::insert<
366               Rules,
367               boost::mpl::pair<Name, build_native_parser<P> >
368             >::type,
369             Actions
370           >
371         {};
372       }
373 
374       template <class Start = string<'S'> >
375       struct grammar :
376         grammar_util::grammar_builder<
377           Start,
378           boost::mpl::map<>,
379           boost::mpl::map<>
380         >
381       {};
382     }
383   }
384 }
385 
386 #endif
387