Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <type_traits>
- #include <utility>
- #include <system_error>
- #include <sstream>
- #include <stdexcept>
- #include <regex>
- #include <tuple>
- template< typename char_type, char_type ...chars >
- struct string_literal
- {
- static constexpr auto size = sizeof...(chars);
- static constexpr char_type value[size] = {chars...};
- };
- template< typename char_type, char_type ...chars >
- constexpr const char_type string_literal< char_type, chars... >::value[size];
- template< typename char_type, char_type ...chars >
- constexpr
- string_literal< char_type, chars... >
- operator "" _s ()
- {
- return {};
- }
- template< typename type >
- struct is_string_literal
- : std::false_type
- {
- };
- template< typename char_type, char_type ...chars >
- struct is_string_literal< string_literal< char_type, chars... > >
- : std::true_type
- {
- };
- template< typename Iterator, typename Skipper >
- struct parser
- {
- Iterator & beg;
- Iterator const & end;
- Skipper skipper;
- bool success = true;
- constexpr
- operator bool () const
- {
- return success;
- }
- template< typename Attribute >
- operator Attribute ();
- template< typename A, typename index_sequence = std::index_sequence<>, typename = void >
- struct aggregate_arity
- : index_sequence
- {
- };
- template< typename A, std::size_t ...indices >
- struct aggregate_arity< A, std::index_sequence< indices... >, std::__void_t< decltype(A{(indices, std::declval< parser >())..., std::declval< parser >()}) > >
- : aggregate_arity< A, std::index_sequence< indices..., sizeof...(indices) > >
- {
- };
- enum class category
- {
- unknown,
- string_literal,
- arithmetic,
- aggregate
- };
- template< typename Attribute >
- static
- constexpr
- bool
- get_category(category const expected)
- {
- category category_ = category::unknown;
- if (is_string_literal< Attribute >::value) {
- category_ = category::string_literal;
- } else if (std::is_arithmetic< Attribute >::value) {
- category_ = category::arithmetic;
- } else {
- category_ = category::aggregate;
- }
- return (category_ == expected);
- }
- constexpr
- void
- fail()
- {
- success = false;
- }
- constexpr
- void
- fail(Iterator & first)
- {
- beg = first;
- return fail();
- }
- template< typename Attribute >
- constexpr
- std::enable_if_t< get_category< Attribute >(category::string_literal), Attribute >
- dispatch()
- {
- Iterator first = beg;
- for (auto const & c : Attribute::value) {
- if ((beg != end) && (c == *beg)) {
- ++beg;
- } else {
- fail(first);
- break;
- }
- }
- return {};
- }
- template< typename Attribute >
- constexpr
- Attribute
- dispatch(std::index_sequence<>)
- {
- return {*this};
- }
- template< typename Attribute, std::size_t ...indices >
- constexpr
- Attribute
- dispatch(std::index_sequence< indices... >)
- {
- return {(static_cast< void >(indices), *this)...};
- }
- template< typename Attribute >
- std::enable_if_t< get_category< Attribute >(category::aggregate), Attribute >
- dispatch()
- {
- return dispatch< Attribute >(aggregate_arity< Attribute >{});
- }
- template< typename Attribute >
- std::enable_if_t< get_category< Attribute >(category::arithmetic), Attribute >
- dispatch()
- {
- Attribute attr;
- std::istringstream iss_({beg, end});
- if (iss_ >> attr) {
- std::advance(beg, iss_.tellg());
- } else {
- fail();
- }
- return attr;
- }
- };
- template< typename Iterator, typename Skipper >
- parser< Iterator, Skipper >
- parse(Iterator & beg, Iterator const & end, Skipper && skipper)
- {
- return {beg, end, std::forward< Skipper >(skipper)};
- }
- template< typename Iterator >
- auto
- parse(Iterator & beg, Iterator const & end)
- {
- return parse(beg, end, std::ignore);
- }
- template< typename Iterator, typename Skipper >
- template< typename Attribute >
- parser< Iterator, Skipper >::operator Attribute ()
- {
- Attribute attr{};
- if (operator bool ()) {
- skipper = parse(beg, end);
- attr = dispatch< Attribute >();
- }
- return attr;
- }
- #include <iostream>
- #include <iterator>
- #include <algorithm>
- #include <cstdlib>
- struct ast
- {
- int a;
- decltype("@"_s) s123;
- struct
- {
- double x;
- char c;
- } s;
- };
- int
- main()
- {
- std::string input = "0123@ 12E-1 c rest";
- auto it = std::cbegin(input);
- auto const end = std::cend(input);
- auto skipper = " "_s;
- auto parser = parse(it, end, skipper);
- ast a{};
- a = parser;
- std::cout << a.a << ' ' << a.s.x << ' ' << a.s.c << std::endl;
- if (it != end) {
- std::cerr << "End of input is not reached. Rest of input:" << std::endl;
- std::copy(it, end, std::ostreambuf_iterator< typename std::string::value_type >(std::cerr));
- std::cerr << std::endl;
- }
- return EXIT_SUCCESS;
- }
Advertisement
Add Comment
Please, Sign In to add comment