Preprocessor to iterate through enum ?

Hi
im making a lexer and i have this Token struct:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#pragma once

namespace qq
{

  enum TokenType
  {
    Symbol,
    String,
    If,
    FuncDecl,

    OpenScope,
    CloseScope,
    OpenParenth,
    ClosingParenth,


    AssignOp,
    AdditionOp,
    SubtractOp,
    DivideOp,
    MultiplyOp,
  };

  template <TokenType TType>
  struct Token
  {
    TokenType Type;
    char* Value;

    Token() : Type(TType){}
  };
}


i would like to make an alias for each token so that rather than doing this: Token<TokenType::Symbol> token i can just do this: SymbolToken token

i know i can just typdef each token like this:
 
typedef Token<TokenType::Symbol> SymbolToken;


but it's just really tedious to do for every single token
so i was wondering if anyone know of a way to do it with the preprocessor?
(something that automatically iterates through the enum elements and makes typedefs for the corresponding token)
Last edited on
It's not possible.

There are ways to do something like, say you have a list of symbols like [A, B, C, Theta, Epsilon] and you want, in several places, to generate various pieces of code that relate to these symbols in different ways. For example, in one place you may want to generate
1
2
3
4
5
A,
B,
C,
Theta,
Epsilon,
and in another
1
2
3
4
5
foo_A();
foo_B();
foo_C();
foo_Theta();
foo_Epsilon();
This can be done, but I don't recommend it. The method is very ugly.
Is this kind of what you want?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#define E_LIST \
E(Symbol)\
E(String)\
E(If)\
E(FuncDecl)\
E(OpenScope)\
E(CloseScope)\
E(OpenParenth)\
E(ClosingParenth)\
E(AssignOp)\
E(AdditionOp)\
E(SubtractOp)\
E(DivideOp)\
E(MultiplyOp)

namespace qq
{
	#define E(e) e,
	enum TokenType
	{
		E_LIST
	};
	#undef E
	
	#define E(e) \
	struct e ## Token \
	{\
		static constexpr TokenType Type = e;\
		static constexpr const char* Value = #e;\
	};
	E_LIST
	#undef E
}
#undef E_LIST 


The inspiration comes from this short video: https://www.youtube.com/watch?v=hXZrGh9kCVs
Last edited on
See, for instance, this library:
https://github.com/aantron/better-enums
Boost can also help here:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <boost/preprocessor/tuple/to_seq.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/cat.hpp>

#define TOKEN_TYPE_SEQ BOOST_PP_TUPLE_TO_SEQ(13, ( \
                        \
    Symbol,             \
    String,             \
    If,                 \
    FuncDecl,           \
                        \
    OpenScope,          \
    CloseScope,         \
    OpenParenth,        \
    ClosingParenth,     \
                        \
                        \
    AssignOp,           \
    AdditionOp,         \
    SubtractOp,         \
    DivideOp,           \
    MultiplyOp))


#define ENUM_ELEM(r, data, elem) elem,

#define TYPEDEF(r, data, elem) typedef Token<TokenType::elem> BOOST_PP_CAT(elem, Token);

namespace qq
{

  enum TokenType
  {
     BOOST_PP_SEQ_FOR_EACH(ENUM_ELEM, _, TOKEN_TYPE_SEQ)
  };

  template <TokenType TType>
  struct Token
  {
    TokenType Type;
    char* Value;

    Token() : Type(TType){}
  };

  BOOST_PP_SEQ_FOR_EACH(TYPEDEF, _, TOKEN_TYPE_SEQ)

}

int main() { }


This is what I get after macro expansion:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
namespace qq
{

  enum TokenType
  {
     Symbol, String, If, FuncDecl, OpenScope, CloseScope, OpenParenth, ClosingParenth, AssignOp, AdditionOp, SubtractOp, DivideOp, MultiplyOp,
  };

  template <TokenType TType>
  struct Token
  {
    TokenType Type;
    char* Value;

    Token() : Type(TType){}
  };

  typedef Token<TokenType::Symbol> SymbolToken; typedef Token<TokenType::String> StringToken; typedef Token<TokenType::If> IfToken; typedef Token<TokenType::FuncDecl> FuncDeclToken; typedef Token<TokenType::OpenScope> OpenScopeToken; typedef Token<TokenType::CloseScope> CloseScopeToken; typedef Token<TokenType::OpenParenth> OpenParenthToken; typedef Token<TokenType::ClosingParenth> ClosingParenthToken; typedef Token<TokenType::AssignOp> AssignOpToken; typedef Token<TokenType::AdditionOp> AdditionOpToken; typedef Token<TokenType::SubtractOp> SubtractOpToken; typedef Token<TokenType::DivideOp> DivideOpToken; typedef Token<TokenType::MultiplyOp> MultiplyOpToken;

}

int main() { }

Topic archived. No new replies allowed.