Preprocessor to iterate through enum ?

Sep 26, 2018 at 6:38pm
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 Sep 26, 2018 at 6:39pm
Sep 26, 2018 at 7:50pm
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.
Sep 26, 2018 at 10:13pm
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 Sep 26, 2018 at 10:14pm
Sep 26, 2018 at 10:17pm
See, for instance, this library:
https://github.com/aantron/better-enums
Sep 26, 2018 at 10:43pm
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.