123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247 |
- #include <iostream>
- #include <utility>
- #include <cstring>
- #include <boost/mpl/identity.hpp>
- namespace boost { namespace spirit { namespace x3
- {
- template <typename Derived>
- struct parser
- {
- Derived const& derived() const
- {
- return *static_cast<Derived const*>(this);
- }
- };
- template <typename Char>
- struct char_parser : parser<char_parser<Char>>
- {
- char_parser(Char ch) : ch(ch) {}
- template <typename Iterator, typename Context>
- bool parse(Iterator& first, Iterator last, Context const& ctx) const
- {
- if (first != last && *first == ch)
- {
- ++first;
- return true;
- }
- return false;
- }
- Char ch;
- };
- template <typename Char>
- inline char_parser<Char> char_(Char ch)
- {
- return char_parser<Char>(ch);
- };
- template <typename Left, typename Right>
- struct sequence_parser : parser<sequence_parser<Left, Right>>
- {
- sequence_parser(Left left, Right right)
- : left(left), right(right) {}
- template <typename Iterator, typename Context>
- bool parse(Iterator& first, Iterator last, Context const& ctx) const
- {
- return left.parse(first, last, ctx)
- && right.parse(first, last, ctx);
- }
- Left left;
- Right right;
- };
- template <typename Left, typename Right>
- inline sequence_parser<Left, Right> operator>>(
- parser<Left> const& left, parser<Right> const& right)
- {
- return sequence_parser<Left, Right>(
- left.derived(), right.derived());
- }
- template <typename Left, typename Right>
- struct alternative_parser : parser<alternative_parser<Left, Right>>
- {
- alternative_parser(Left left, Right right)
- : left(left), right(right) {}
- template <typename Iterator, typename Context>
- bool parse(Iterator& first, Iterator last, Context const& ctx) const
- {
- if (left.parse(first, last, ctx))
- return true;
- return right.parse(first, last, ctx);
- }
- Left left;
- Right right;
- };
- template <typename Left, typename Right>
- inline alternative_parser<Left, Right> operator|(
- parser<Left> const& left, parser<Right> const& right)
- {
- return alternative_parser<Left, Right>(
- left.derived(), right.derived());
- }
- template <typename ID, typename T, typename NextContext>
- struct context
- {
- context(T const& val, NextContext const& next_ctx)
- : val(val), next_ctx(next_ctx) {}
- T const& get(mpl::identity<ID>) const
- {
- return val;
- }
- template <typename Identity>
- decltype(std::declval<NextContext>().get(Identity()))
- get(Identity id) const
- {
- return next_ctx.get(id);
- }
- T const& val;
- NextContext const& next_ctx;
- };
- struct empty_context
- {
- struct undefined {};
- template <typename ID>
- undefined get(ID) const
- {
- return undefined();
- }
- };
- template <typename ID, typename RHS>
- struct rule_definition : parser<rule_definition<ID, RHS>>
- {
- rule_definition(RHS rhs)
- : rhs(rhs) {}
- template <typename Iterator, typename Context>
- bool parse(Iterator& first, Iterator last, Context const& ctx) const
- {
- context<ID, RHS, Context> this_ctx(rhs, ctx);
- return rhs.parse(first, last, this_ctx);
- }
- RHS rhs;
- };
- template <typename ID>
- struct rule : parser<rule<ID>>
- {
- template <typename Derived>
- rule_definition<ID, Derived>
- operator=(parser<Derived> const& definition) const
- {
- return rule_definition<ID, Derived>(definition.derived());
- }
- template <typename Iterator, typename Context>
- bool parse(Iterator& first, Iterator last, Context const& ctx) const
- {
- return ctx.get(mpl::identity<ID>()).parse(first, last, ctx);
- }
- };
- template <typename Iterator, typename Derived>
- inline bool parse(parser<Derived> const& p, Iterator& first, Iterator last)
- {
- empty_context ctx;
- return p.derived().parse(first, last, ctx);
- }
- }}}
- ///////////////////////////////////////////////////////////////////////////////
- // test code
- template <typename Parser>
- bool test_parse(Parser const& p, char const* in)
- {
- return parse(p, in, in + std::strlen(in));
- }
- namespace parser
- {
- using namespace boost::spirit::x3;
- namespace g_definition
- {
- auto const x = rule<class x>();
- auto const ax = char_('a') >> x;
- auto const g =
- x = char_('x') | ax;
- }
- using g_definition::g;
- }
- int main()
- {
- { // a non-recursive parser
- using namespace boost::spirit::x3;
- auto abc = char_('a') >> char_('b') >> char_('c');
- std::cout << test_parse(abc, "abc") << std::endl;
- std::cout << test_parse(abc, "abx") << std::endl;
- std::cout << "==========================================" << std::endl;
- }
- { // a recursive rule
- using namespace boost::spirit::x3;
- auto const x = rule<class x>();
- auto const ax = char_('a') >> x;
- auto const start = (x = char_('x') | ax);
- std::cout << test_parse(start, "x") << std::endl;
- std::cout << test_parse(start, "ax") << std::endl;
- std::cout << test_parse(start, "aaaaax") << std::endl;
- std::cout << test_parse(start, "aaz") << std::endl;
- std::cout << "==========================================" << std::endl;
- }
- { // a grammar ( gcc and clang only: see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3582.html )
- using namespace boost::spirit::x3;
- auto g = []()
- {
- rule<class x> x;
- auto ax = char_('a') >> x;
- return x = char_('x') | ax;
- }();
- std::cout << test_parse(g, "x") << std::endl;
- std::cout << test_parse(g, "ax") << std::endl;
- std::cout << test_parse(g, "aaaaax") << std::endl;
- std::cout << test_parse(g, "aaz") << std::endl;
- std::cout << "==========================================" << std::endl;
- }
- { // another grammar using namespaces (standard c++, see grammar g definition above in namespace parser.)
- using parser::g;
- std::cout << test_parse(g, "x") << std::endl;
- std::cout << test_parse(g, "ax") << std::endl;
- std::cout << test_parse(g, "aaaaax") << std::endl;
- std::cout << test_parse(g, "aaz") << std::endl;
- std::cout << "==========================================" << std::endl;
- }
- return 0;
- }
|