// Copyright (c) 2018 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include #include #include #include #include namespace pegtl = tao::TAO_PEGTL_NAMESPACE; namespace example { // Examples for grammars on all levels of the Chomsky hierarchy. // Type 3 - Regular Languages // The regular language (ab+)* implemented in a straight-forward fashion. struct type_3 : pegtl::star< pegtl::one< 'a' >, pegtl::plus< pegtl::one< 'b' > > > { }; // Type 2 - Context Free Languages // The context-free, but not regular, language a^n b^n. // Implementation that implicitly uses the C++ call stack. struct type_2_recursive : pegtl::sor< pegtl::string< 'a', 'b' >, pegtl::seq< pegtl::one< 'a' >, type_2_recursive, pegtl::one< 'b' > > > { }; // Implementation that uses state instead of recursion, an // action to set the state, and a custom rule to use it. template< char C > struct match_n { template< pegtl::apply_mode, pegtl::rewind_mode, template< typename... > class Action, template< typename... > class Control, typename Input > static bool match( Input& in, std::size_t& count ) { if( in.size( count ) >= count ) { for( std::size_t i = 0; i < count; ++i ) { if( in.peek_char( i ) != C ) { return false; } } in.bump_in_this_line( count ); return true; } return false; } }; struct type_2_with_state : pegtl::seq< pegtl::star< pegtl::one< 'a' > >, match_n< 'b' > > { }; template< typename Rule > struct action_2_with_state : pegtl::nothing< Rule > { }; template<> struct action_2_with_state< pegtl::star< pegtl::one< 'a' > > > { template< typename Input > static void apply( const Input& in, std::size_t& count ) { count = in.size(); } }; // Type 1 - Context Sensitive Languages // The context-sensitive, but not context-free, language a^n b^n c^n. // Here only the implementation that uses state can be used. // Both the match_n<> rule and the action are the same as in // the previous non-recursive implementation of a^n b^n. struct type_1 : pegtl::seq< pegtl::star< pegtl::one< 'a' > >, match_n< 'b' >, match_n< 'c' > > { }; template< typename Rule > struct action_1 : action_2_with_state< Rule > { }; // Type 0 - Recursively Enumerable Languages // We can use the entire Turing-complete C++ language in custom rules, // so we can pretty much do everything if we decide to (pun intended), // including recursive and recursively enumerable languages ... within // the limits of time and space that we are able to dedicate. } // namespace example int main( int argc, char** argv ) { for( int i = 1; i < argc; ++i ) { pegtl::argv_input<> in( argv, i ); const auto r3 = pegtl::parse< pegtl::seq< example::type_3, pegtl::eof > >( in ); in.restart(); const auto r2r = pegtl::parse< pegtl::seq< example::type_2_recursive, pegtl::eof > >( in ); in.restart(); std::size_t count = 0; const auto r2s = pegtl::parse< pegtl::seq< example::type_2_with_state, pegtl::eof >, example::action_2_with_state >( in, count ); in.restart(); const auto r1 = pegtl::parse< pegtl::seq< example::type_1, pegtl::eof >, example::action_1 >( in, count ); std::cout << r3 << r2r << r2s << r1 << std::endl; assert( r2r == r2s ); } return 0; }