parseEnums.cpp 4.25 KB
Newer Older
1
#include <type_traits>
daminetreg's avatar
daminetreg committed
2 3
#include <iostream>

4 5
#define BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
#define BOOST_MPL_LIMIT_VECTOR_SIZE 50
6 7

#define MPLLIBS_LIMIT_SEQUENCE_SIZE 10
8 9
#define MPLLIBS_LIMIT_STRING_SIZE 64

daminetreg's avatar
daminetreg committed
10 11 12 13 14 15 16 17
#include <mpllibs/metaparse/string.hpp>
#include <mpllibs/metaparse/lit_c.hpp>
#include <mpllibs/metaparse/sequence.hpp>

#include <mpllibs/metaparse/entire_input.hpp>
#include <mpllibs/metaparse/token.hpp>
#include <mpllibs/metaparse/build_parser.hpp>

daminetreg's avatar
daminetreg committed
18 19 20 21 22 23 24 25
#include <mpllibs/metaparse/foldl.hpp>
#include <mpllibs/metaparse/any.hpp>

#include <mpllibs/metaparse/one_char_except.hpp>
#include <mpllibs/metaparse/empty.hpp>

#include <mpllibs/metaparse/one_of.hpp>

26 27
#include <mpllibs/metaparse/transform.hpp>

28 29
#include <mpllibs/metaparse/keyword.hpp>

daminetreg's avatar
daminetreg committed
30 31 32 33
#include <boost/mpl/size.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/int.hpp>

34 35
#include <boost/mpl/lambda.hpp>

36 37 38 39
#include <boost/mpl/vector.hpp>

#include <boost/mpl/string.hpp>

40 41 42
#include <boost/preprocessor/punctuation/remove_parens.hpp>
#include <boost/preprocessor/tuple/elem.hpp>

daminetreg's avatar
daminetreg committed
43 44
using namespace mpllibs::metaparse;

45 46 47 48
using enum_keyword = keyword<MPLLIBS_STRING("enum")>;
using enumclass_keyword = keyword<MPLLIBS_STRING("class")>;
using enum_name = any<one_char_except<std::integral_constant<char, '{'>>>; 

daminetreg's avatar
daminetreg committed
49 50
using enumeration_ids = sequence< 
      token<lit_c<'{'>>, 
daminetreg's avatar
daminetreg committed
51
      any<
52
        sequence<
daminetreg's avatar
daminetreg committed
53 54
          token<any<one_char_except<std::integral_constant<char, ','>>>>,
          token<lit_c<','>>
55
        >
56
      >,
daminetreg's avatar
daminetreg committed
57 58
      token<lit_c<'}'>>
>;
daminetreg's avatar
daminetreg committed
59 60 61 62

using enum_parser = build_parser<
  entire_input<
    sequence<
63
      token<lit_c<'('>>,
64 65 66
      token<enum_keyword>,
      token<enumclass_keyword>,
      token<enum_name>,
67 68
      enumeration_ids,
      token<lit_c<')'>>
daminetreg's avatar
daminetreg committed
69 70 71 72
    >
  >
>;

73
template<class enum_parse_result>
74
using get_enum_entry_count = 
75
  typename boost::mpl::size< typename boost::mpl::at_c< typename boost::mpl::at_c<enum_parse_result, 4>::type, 1 >::type>::type;
daminetreg's avatar
daminetreg committed
76

77
template<class enum_parse_result, int x>
78
using get_enum_entry = 
79
  typename boost::mpl::at_c< typename boost::mpl::at_c< typename boost::mpl::at_c< typename boost::mpl::at_c<enum_parse_result, 4>::type, 1 >::type, x >::type, 0>::type;
daminetreg's avatar
daminetreg committed
80

81

82 83 84 85 86 87 88
template <class enum_parse_result, int x>
using enum_strval = 
  typename boost::mpl::fold< 
    typename get_enum_entry< enum_parse_result, x >::type,
    boost::mpl::string<>::type,
    boost::mpl::lambda< boost::mpl::push_back<boost::mpl::_1, boost::mpl::_2> >::type
  >::type;
daminetreg's avatar
daminetreg committed
89

90 91 92
template <class enum_parse_result, int x>
using enum_as_cstr = typename boost::mpl::c_str< typename enum_strval< enum_parse_result, x >::type >::type;

93 94 95 96 97 98 99 100 101 102 103 104 105
template <class adapted_enum_type>
struct adapted_enum; 



#define SMART_ENUM(name, ENUMDECL)                                              \
  BOOST_PP_REMOVE_PARENS(ENUMDECL);                                             \
                                                                                \
  template <>                                                                   \
  struct adapted_enum<name> {                                                   \
    typedef enum_parser::apply<MPLLIBS_STRING(#ENUMDECL)>::type parsed_enum;    \
  };

106

daminetreg's avatar
daminetreg committed
107 108 109 110 111 112 113 114 115 116 117
SMART_ENUM(banana, (
      
      enum class banana { first, second, }
      
))

SMART_ENUM(test, (

      enum class test { Oh, Yeah, Cool, }
))

118

daminetreg's avatar
daminetreg committed
119
int main(int argc, const char** argv) {
daminetreg's avatar
daminetreg committed
120
  using namespace boost::mpl;
121

122 123 124 125 126 127 128 129 130 131 132
  std::cout << "There are " << get_enum_entry_count<adapted_enum<banana>::parsed_enum>::value << " identifiers. " << std::endl;
  //std::cout << "Enum as string is " << to_string(banana::first) << std::endl;
  //std::cout << "Enum as string is " << to_string(banana::second) << std::endl;
  std::cout << "Enum as string is " << enum_as_cstr< adapted_enum<banana>::parsed_enum, int(banana::second)>::value << std::endl;
  //
  //std::cout << "There are " << get_enum_entry_count<adapted_test>::value << " identifiers. " << std::endl;
  //std::cout << "Enum as string is " << enum_as_cstr<adapted_test, int(test::Oh)>::value << std::endl;
  //std::cout << "Enum as string is " << enum_as_cstr<adapted_test, int(test::Yeah)>::value << std::endl;
  //std::cout << "Enum as string is " << enum_as_cstr<adapted_test, int(test::Cool)>::value << std::endl;
  //
  //std::cout << "Enum as string is " << enum_as_cstr<adapted_test, 1>::value << std::endl;
133

daminetreg's avatar
daminetreg committed
134 135
  return 0;
}