1 #include <iostream>
2 #include <utility>
3 #include <cstring>
4 #include <boost/mpl/identity.hpp>
5 
6 namespace boost { namespace spirit { namespace x3
7 {
8     template <typename Derived>
9     struct parser
10     {
derivedboost::spirit::x3::parser11         Derived const& derived() const
12         {
13             return *static_cast<Derived const*>(this);
14         }
15     };
16 
17     template <typename Char>
18     struct char_parser : parser<char_parser<Char>>
19     {
char_parserboost::spirit::x3::char_parser20         char_parser(Char ch) : ch(ch) {}
21 
22         template <typename Iterator, typename Context>
parseboost::spirit::x3::char_parser23         bool parse(Iterator& first, Iterator last, Context const& ctx) const
24         {
25             if (first != last && *first == ch)
26             {
27                 ++first;
28                 return true;
29             }
30             return false;
31         }
32 
33         Char ch;
34     };
35 
36     template <typename Char>
char_(Char ch)37     inline char_parser<Char> char_(Char ch)
38     {
39         return char_parser<Char>(ch);
40     };
41 
42     template <typename Left, typename Right>
43     struct sequence_parser : parser<sequence_parser<Left, Right>>
44     {
sequence_parserboost::spirit::x3::sequence_parser45         sequence_parser(Left left, Right right)
46             : left(left), right(right) {}
47 
48         template <typename Iterator, typename Context>
parseboost::spirit::x3::sequence_parser49         bool parse(Iterator& first, Iterator last, Context const& ctx) const
50         {
51             return left.parse(first, last, ctx)
52                 && right.parse(first, last, ctx);
53         }
54 
55         Left left;
56         Right right;
57     };
58 
59     template <typename Left, typename Right>
operator >>(parser<Left> const & left,parser<Right> const & right)60     inline sequence_parser<Left, Right> operator>>(
61         parser<Left> const& left, parser<Right> const& right)
62     {
63         return sequence_parser<Left, Right>(
64             left.derived(), right.derived());
65     }
66 
67     template <typename Left, typename Right>
68     struct alternative_parser : parser<alternative_parser<Left, Right>>
69     {
alternative_parserboost::spirit::x3::alternative_parser70         alternative_parser(Left left, Right right)
71             : left(left), right(right) {}
72 
73         template <typename Iterator, typename Context>
parseboost::spirit::x3::alternative_parser74         bool parse(Iterator& first, Iterator last, Context const& ctx) const
75         {
76             if (left.parse(first, last, ctx))
77                 return true;
78             return right.parse(first, last, ctx);
79         }
80 
81         Left left;
82         Right right;
83     };
84 
85     template <typename Left, typename Right>
operator |(parser<Left> const & left,parser<Right> const & right)86     inline alternative_parser<Left, Right> operator|(
87         parser<Left> const& left, parser<Right> const& right)
88     {
89         return alternative_parser<Left, Right>(
90             left.derived(), right.derived());
91     }
92 
93     template <typename ID, typename T, typename NextContext>
94     struct context
95     {
contextboost::spirit::x3::context96         context(T const& val, NextContext const& next_ctx)
97             : val(val), next_ctx(next_ctx) {}
98 
getboost::spirit::x3::context99         T const& get(mpl::identity<ID>) const
100         {
101             return val;
102         }
103 
104         template <typename Identity>
105         decltype(std::declval<NextContext>().get(Identity()))
getboost::spirit::x3::context106         get(Identity id) const
107         {
108             return next_ctx.get(id);
109         }
110 
111         T const& val;
112         NextContext const& next_ctx;
113     };
114 
115     struct empty_context
116     {
117         struct undefined {};
118         template <typename ID>
getboost::spirit::x3::empty_context119         undefined get(ID) const
120         {
121             return undefined();
122         }
123     };
124 
125     template <typename ID, typename RHS>
126     struct rule_definition : parser<rule_definition<ID, RHS>>
127     {
rule_definitionboost::spirit::x3::rule_definition128         rule_definition(RHS rhs)
129             : rhs(rhs) {}
130 
131         template <typename Iterator, typename Context>
parseboost::spirit::x3::rule_definition132         bool parse(Iterator& first, Iterator last, Context const& ctx) const
133         {
134             context<ID, RHS, Context> this_ctx(rhs,  ctx);
135             return rhs.parse(first, last, this_ctx);
136         }
137 
138         RHS rhs;
139     };
140 
141     template <typename ID>
142     struct rule : parser<rule<ID>>
143     {
144         template <typename Derived>
145         rule_definition<ID, Derived>
operator =boost::spirit::x3::rule146         operator=(parser<Derived> const& definition) const
147         {
148             return rule_definition<ID, Derived>(definition.derived());
149         }
150 
151         template <typename Iterator, typename Context>
parseboost::spirit::x3::rule152         bool parse(Iterator& first, Iterator last, Context const& ctx) const
153         {
154             return ctx.get(mpl::identity<ID>()).parse(first, last, ctx);
155         }
156     };
157 
158     template <typename Iterator, typename Derived>
parse(parser<Derived> const & p,Iterator & first,Iterator last)159     inline bool parse(parser<Derived> const& p, Iterator& first, Iterator last)
160     {
161         empty_context ctx;
162         return p.derived().parse(first, last, ctx);
163     }
164 
165 }}}
166 
167 ///////////////////////////////////////////////////////////////////////////////
168 // test code
169 
170 template <typename Parser>
test_parse(Parser const & p,char const * in)171 bool test_parse(Parser const& p, char const* in)
172 {
173     return parse(p, in, in + std::strlen(in));
174 }
175 
176 namespace parser
177 {
178     using namespace boost::spirit::x3;
179 
180     namespace g_definition
181     {
182         auto const x = rule<class x>();
183         auto const ax = char_('a') >> x;
184 
185         auto const g =
186             x = char_('x') | ax;
187     }
188     using g_definition::g;
189 }
190 
main()191 int main()
192 {
193 
194    { // a non-recursive parser
195       using namespace boost::spirit::x3;
196 
197       auto abc = char_('a') >> char_('b') >> char_('c');
198       std::cout << test_parse(abc, "abc") << std::endl;
199       std::cout << test_parse(abc, "abx") << std::endl;
200       std::cout << "==========================================" << std::endl;
201    }
202 
203    { // a recursive rule
204       using namespace boost::spirit::x3;
205 
206       auto const x = rule<class x>();
207       auto const ax = char_('a') >> x;
208       auto const start = (x = char_('x') | ax);
209 
210       std::cout << test_parse(start, "x") << std::endl;
211       std::cout << test_parse(start, "ax") << std::endl;
212       std::cout << test_parse(start, "aaaaax") << std::endl;
213       std::cout << test_parse(start, "aaz") << std::endl;
214       std::cout << "==========================================" << std::endl;
215    }
216 
217    { // a grammar ( gcc and clang only: see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3582.html )
218 
219       using namespace boost::spirit::x3;
220       auto g = []()
221       {
222          rule<class x> x;
223          auto ax = char_('a') >> x;
224          return x = char_('x') | ax;
225 
226       }();
227 
228       std::cout << test_parse(g, "x") << std::endl;
229       std::cout << test_parse(g, "ax") << std::endl;
230       std::cout << test_parse(g, "aaaaax") << std::endl;
231       std::cout << test_parse(g, "aaz") << std::endl;
232       std::cout << "==========================================" << std::endl;
233    }
234 
235    { // another grammar using namespaces (standard c++, see grammar g definition above in namespace parser.)
236       using parser::g;
237 
238       std::cout << test_parse(g, "x") << std::endl;
239       std::cout << test_parse(g, "ax") << std::endl;
240       std::cout << test_parse(g, "aaaaax") << std::endl;
241       std::cout << test_parse(g, "aaz") << std::endl;
242       std::cout << "==========================================" << std::endl;
243    }
244 
245    return 0;
246 }
247 
248