transform token_t into a union (similar to ast-nodes)
authorMatthias Braun <matze@braunis.de>
Tue, 26 Jul 2011 12:50:42 +0000 (14:50 +0200)
committerMatthias Braun <matze@braunis.de>
Tue, 9 Aug 2011 18:19:26 +0000 (20:19 +0200)
ast.c
ast2firm.c
ast_t.h
diagnostic.c
lexer.c
main.c
parser.c
preprocessor.c
token.c
token_t.h
tokens_preprocessor.inc

diff --git a/ast.c b/ast.c
index 4394732..dc551de 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -66,11 +66,6 @@ void print_indent(void)
                print_string("\t");
 }
 
-static void print_symbol(const symbol_t *symbol)
-{
-       print_string(symbol->string);
-}
-
 static void print_stringrep(const string_t *string)
 {
        for (size_t i = 0; i < string->size; ++i) {
@@ -266,8 +261,8 @@ static void print_literal(const literal_expression_t *literal)
        case EXPR_LITERAL_INTEGER_OCTAL:
        case EXPR_LITERAL_FLOATINGPOINT:
                print_stringrep(&literal->value);
-               if (literal->suffix != NULL)
-                       print_symbol(literal->suffix);
+               if (literal->suffix.size > 0)
+                       print_stringrep(&literal->suffix);
                return;
        case EXPR_LITERAL_WIDE_CHARACTER:
                print_char('L');
index 2b47167..61fc5da 100644 (file)
@@ -1207,12 +1207,12 @@ static bool try_create_integer(literal_expression_t *literal,
 
 static void create_integer_tarval(literal_expression_t *literal)
 {
-       unsigned  us     = 0;
-       unsigned  ls     = 0;
-       symbol_t *suffix = literal->suffix;
+       unsigned        us     = 0;
+       unsigned        ls     = 0;
+       const string_t *suffix = &literal->suffix;
        /* parse suffix */
-       if (suffix != NULL) {
-               for (const char *c = suffix->string; *c != '\0'; ++c) {
+       if (suffix->size > 0) {
+               for (const char *c = suffix->begin; *c != '\0'; ++c) {
                        if (*c == 'u' || *c == 'U') { ++us; }
                        if (*c == 'l' || *c == 'L') { ++ls; }
                }
diff --git a/ast_t.h b/ast_t.h
index 92caf95..9bd17ef 100644 (file)
--- a/ast_t.h
+++ b/ast_t.h
@@ -265,7 +265,7 @@ struct expression_base_t {
 struct literal_expression_t {
        expression_base_t  base;
        string_t           value;
-       symbol_t          *suffix;
+       string_t           suffix;
 
        /* ast2firm data */
        ir_tarval         *target_value;
index af15aa4..447ed7d 100644 (file)
@@ -153,7 +153,7 @@ static void diagnosticvf(const char *const fmt, va_list ap)
                                                va_list*          toks      = va_arg(ap, va_list*);
                                                const char* const delimiter = va_arg(ap, const char*);
                                                for (;;) {
-                                                       const token_type_t tok = va_arg(*toks, token_type_t);
+                                                       const token_kind_t tok = va_arg(*toks, token_kind_t);
                                                        if (tok == 0)
                                                                break;
                                                        if (first) {
@@ -161,11 +161,11 @@ static void diagnosticvf(const char *const fmt, va_list ap)
                                                        } else {
                                                                fputs(delimiter, stderr);
                                                        }
-                                                       print_token_type(stderr, tok);
+                                                       print_token_kind(stderr, tok);
                                                }
                                        } else {
-                                               const token_type_t token = va_arg(ap, token_type_t);
-                                               print_token_type(stderr, token);
+                                               const token_kind_t token = va_arg(ap, token_kind_t);
+                                               print_token_kind(stderr, token);
                                        }
                                        break;
                                }
diff --git a/lexer.c b/lexer.c
index cc528eb..e29ec4a 100644 (file)
--- a/lexer.c
+++ b/lexer.c
@@ -277,14 +277,28 @@ end_symbol:
        char     *string = obstack_finish(&symbol_obstack);
        symbol_t *symbol = symbol_table_insert(string);
 
-       lexer_token.type   = symbol->ID;
-       lexer_token.symbol = symbol;
+       lexer_token.kind              = symbol->ID;
+       lexer_token.identifier.symbol = symbol;
 
        if (symbol->string != string) {
                obstack_free(&symbol_obstack, string);
        }
 }
 
+static string_t identify_string(char *string, size_t len)
+{
+       /* TODO hash */
+#if 0
+       const char *result = strset_insert(&stringset, concat);
+       if (result != concat) {
+               obstack_free(&symbol_obstack, concat);
+       }
+#else
+       const char *result = string;
+#endif
+       return (string_t) {result, len};
+}
+
 /**
  * parse suffixes like 'LU' or 'f' after numbers
  */
@@ -304,32 +318,16 @@ static void parse_number_suffix(void)
        }
 finish_suffix:
        if (obstack_object_size(&symbol_obstack) == 0) {
-               lexer_token.symbol = NULL;
+               lexer_token.number.suffix.begin = NULL;
+               lexer_token.number.suffix.size  = 0;
                return;
        }
 
        obstack_1grow(&symbol_obstack, '\0');
+       size_t    size   = obstack_object_size(&symbol_obstack);
        char     *string = obstack_finish(&symbol_obstack);
-       symbol_t *symbol = symbol_table_insert(string);
-
-       if (symbol->string != string) {
-               obstack_free(&symbol_obstack, string);
-       }
-       lexer_token.symbol = symbol;
-}
 
-static string_t identify_string(char *string, size_t len)
-{
-       /* TODO hash */
-#if 0
-       const char *result = strset_insert(&stringset, concat);
-       if (result != concat) {
-               obstack_free(&symbol_obstack, concat);
-       }
-#else
-       const char *result = string;
-#endif
-       return (string_t) {result, len};
+       lexer_token.number.suffix = identify_string(string, size);
 }
 
 /**
@@ -374,23 +372,23 @@ static void parse_number_hex(void)
                        next_char();
                }
        } else if (is_float) {
-               errorf(&lexer_token.source_position,
+               errorf(&lexer_token.base.source_position,
                       "hexadecimal floatingpoint constant requires an exponent");
        }
        obstack_1grow(&symbol_obstack, '\0');
 
        size_t  size   = obstack_object_size(&symbol_obstack) - 1;
        char   *string = obstack_finish(&symbol_obstack);
-       lexer_token.literal = identify_string(string, size);
+       lexer_token.number.number = identify_string(string, size);
 
-       lexer_token.type    =
+       lexer_token.kind    =
                is_float ? T_FLOATINGPOINT_HEXADECIMAL : T_INTEGER_HEXADECIMAL;
 
        if (!has_digits) {
-               errorf(&lexer_token.source_position, "invalid number literal '0x%S'",
-                      &lexer_token.literal);
-               lexer_token.literal.begin = "0";
-               lexer_token.literal.size  = 1;
+               errorf(&lexer_token.base.source_position,
+                      "invalid number literal '0x%S'", &lexer_token.number.number);
+               lexer_token.number.number.begin = "0";
+               lexer_token.number.number.size  = 1;
        }
 
        parse_number_suffix();
@@ -463,28 +461,28 @@ static void parse_number(void)
        obstack_1grow(&symbol_obstack, '\0');
        size_t  size   = obstack_object_size(&symbol_obstack) - 1;
        char   *string = obstack_finish(&symbol_obstack);
-       lexer_token.literal = identify_string(string, size);
+       lexer_token.number.number = identify_string(string, size);
 
        /* is it an octal number? */
        if (is_float) {
-               lexer_token.type = T_FLOATINGPOINT;
+               lexer_token.kind = T_FLOATINGPOINT;
        } else if (string[0] == '0') {
-               lexer_token.type = T_INTEGER_OCTAL;
+               lexer_token.kind = T_INTEGER_OCTAL;
 
                /* check for invalid octal digits */
                for (size_t i= 0; i < size; ++i) {
                        char t = string[i];
                        if (t >= '8')
-                               errorf(&lexer_token.source_position,
+                               errorf(&lexer_token.base.source_position,
                                       "invalid digit '%c' in octal number", t);
                }
        } else {
-               lexer_token.type = T_INTEGER;
+               lexer_token.kind = T_INTEGER;
        }
 
        if (!has_digits) {
-               errorf(&lexer_token.source_position, "invalid number literal '%S'",
-                      &lexer_token.literal);
+               errorf(&lexer_token.base.source_position, "invalid number literal '%S'",
+                      &lexer_token.number.number);
        }
 
        parse_number_suffix();
@@ -673,8 +671,8 @@ static void parse_string_literal(void)
                }
 
                case EOF: {
-                       errorf(&lexer_token.source_position, "string has no end");
-                       lexer_token.type = T_ERROR;
+                       errorf(&lexer_token.base.source_position, "string has no end");
+                       lexer_token.kind = T_ERROR;
                        return;
                }
 
@@ -698,8 +696,8 @@ end_of_string:
        const size_t  size   = (size_t)obstack_object_size(&symbol_obstack);
        char         *string = obstack_finish(&symbol_obstack);
 
-       lexer_token.type    = T_STRING_LITERAL;
-       lexer_token.literal = identify_string(string, size);
+       lexer_token.kind          = T_STRING_LITERAL;
+       lexer_token.string.string = identify_string(string, size);
 }
 
 /**
@@ -727,8 +725,9 @@ static void parse_wide_character_constant(void)
                        goto end_of_wide_char_constant;
 
                case EOF: {
-                       errorf(&lexer_token.source_position, "EOF while parsing character constant");
-                       lexer_token.type = T_ERROR;
+                       errorf(&lexer_token.base.source_position,
+                              "EOF while parsing character constant");
+                       lexer_token.kind = T_ERROR;
                        return;
                }
 
@@ -744,11 +743,11 @@ end_of_wide_char_constant:;
        size_t  size   = (size_t) obstack_object_size(&symbol_obstack) - 1;
        char   *string = obstack_finish(&symbol_obstack);
 
-       lexer_token.type     = T_WIDE_CHARACTER_CONSTANT;
-       lexer_token.literal  = identify_string(string, size);
+       lexer_token.kind          = T_WIDE_CHARACTER_CONSTANT;
+       lexer_token.string.string = identify_string(string, size);
 
        if (size == 0) {
-               errorf(&lexer_token.source_position, "empty character constant");
+               errorf(&lexer_token.base.source_position, "empty character constant");
        }
 }
 
@@ -758,8 +757,8 @@ end_of_wide_char_constant:;
 static void parse_wide_string_literal(void)
 {
        parse_string_literal();
-       if (lexer_token.type == T_STRING_LITERAL)
-               lexer_token.type = T_WIDE_STRING_LITERAL;
+       if (lexer_token.kind == T_STRING_LITERAL)
+               lexer_token.kind = T_WIDE_STRING_LITERAL;
 }
 
 /**
@@ -790,8 +789,9 @@ static void parse_character_constant(void)
                        goto end_of_char_constant;
 
                case EOF: {
-                       errorf(&lexer_token.source_position, "EOF while parsing character constant");
-                       lexer_token.type = T_ERROR;
+                       errorf(&lexer_token.base.source_position,
+                              "EOF while parsing character constant");
+                       lexer_token.kind = T_ERROR;
                        return;
                }
 
@@ -808,11 +808,11 @@ end_of_char_constant:;
        const size_t        size   = (size_t)obstack_object_size(&symbol_obstack)-1;
        char         *const string = obstack_finish(&symbol_obstack);
 
-       lexer_token.type    = T_CHARACTER_CONSTANT;
-       lexer_token.literal = identify_string(string, size);
+       lexer_token.kind          = T_CHARACTER_CONSTANT;
+       lexer_token.string.string = identify_string(string, size);
 
        if (size == 0) {
-               errorf(&lexer_token.source_position, "empty character constant");
+               errorf(&lexer_token.base.source_position, "empty character constant");
        }
 }
 
@@ -841,7 +841,8 @@ static void skip_multiline_comment(void)
                MATCH_NEWLINE(break;)
 
                case EOF: {
-                       errorf(&lexer_token.source_position, "at end of file while looking for comment end");
+                       errorf(&lexer_token.base.source_position,
+                              "at end of file while looking for comment end");
                        return;
                }
 
@@ -898,7 +899,7 @@ static inline void next_pp_token(void)
  */
 static void eat_until_newline(void)
 {
-       while (pp_token.type != '\n' && pp_token.type != T_EOF) {
+       while (pp_token.kind != '\n' && pp_token.kind != T_EOF) {
                next_pp_token();
        }
 }
@@ -909,7 +910,7 @@ static void eat_until_newline(void)
 static void define_directive(void)
 {
        lexer_next_preprocessing_token();
-       if (lexer_token.type != T_IDENTIFIER) {
+       if (lexer_token.kind != T_IDENTIFIER) {
                parse_error("expected identifier after #define\n");
                eat_until_newline();
        }
@@ -939,15 +940,15 @@ static void endif_directive(void)
  */
 static void parse_line_directive(void)
 {
-       if (pp_token.type != T_INTEGER) {
+       if (pp_token.kind != T_INTEGER) {
                parse_error("expected integer");
        } else {
                /* use offset -1 as this is about the next line */
-               lexer_pos.lineno = atoi(pp_token.literal.begin) - 1;
+               lexer_pos.lineno = atoi(pp_token.number.number.begin) - 1;
                next_pp_token();
        }
-       if (pp_token.type == T_STRING_LITERAL) {
-               lexer_pos.input_name = pp_token.literal.begin;
+       if (pp_token.kind == T_STRING_LITERAL) {
+               lexer_pos.input_name = pp_token.string.string.begin;
                next_pp_token();
        }
 
@@ -982,13 +983,21 @@ static void parse_pragma(void)
        bool unknown_pragma = true;
 
        next_pp_token();
-       if (pp_token.symbol->pp_ID == TP_STDC) {
+       if (pp_token.kind != T_IDENTIFIER) {
+               warningf(WARN_UNKNOWN_PRAGMAS, &pp_token.base.source_position,
+                        "expected identifier after #pragma");
+               eat_until_newline();
+               return;
+       }
+
+       symbol_t *symbol = pp_token.identifier.symbol;
+       if (symbol->pp_ID == TP_STDC) {
                stdc_pragma_kind_t kind = STDC_UNKNOWN;
                /* a STDC pragma */
                if (c_mode & _C99) {
                        next_pp_token();
 
-                       switch (pp_token.symbol->pp_ID) {
+                       switch (pp_token.identifier.symbol->pp_ID) {
                        case TP_FP_CONTRACT:
                                kind = STDC_FP_CONTRACT;
                                break;
@@ -1004,7 +1013,7 @@ static void parse_pragma(void)
                        if (kind != STDC_UNKNOWN) {
                                stdc_pragma_value_kind_t value = STDC_VALUE_UNKNOWN;
                                next_pp_token();
-                               switch (pp_token.symbol->pp_ID) {
+                               switch (pp_token.identifier.symbol->pp_ID) {
                                case TP_ON:
                                        value = STDC_VALUE_ON;
                                        break;
@@ -1020,7 +1029,8 @@ static void parse_pragma(void)
                                if (value != STDC_VALUE_UNKNOWN) {
                                        unknown_pragma = false;
                                } else {
-                                       errorf(&pp_token.source_position, "bad STDC pragma argument");
+                                       errorf(&pp_token.base.source_position,
+                                              "bad STDC pragma argument");
                                }
                        }
                }
@@ -1029,7 +1039,8 @@ static void parse_pragma(void)
        }
        eat_until_newline();
        if (unknown_pragma) {
-               warningf(WARN_UNKNOWN_PRAGMAS, &pp_token.source_position, "encountered unknown #pragma");
+               warningf(WARN_UNKNOWN_PRAGMAS, &pp_token.base.source_position,
+                        "encountered unknown #pragma");
        }
 }
 
@@ -1038,8 +1049,8 @@ static void parse_pragma(void)
  */
 static void parse_preprocessor_identifier(void)
 {
-       assert(pp_token.type == T_IDENTIFIER);
-       symbol_t *symbol = pp_token.symbol;
+       assert(pp_token.kind == T_IDENTIFIER);
+       symbol_t *symbol = pp_token.identifier.symbol;
 
        switch (symbol->pp_ID) {
        case TP_include:
@@ -1082,7 +1093,7 @@ static void parse_preprocessor_directive(void)
 {
        next_pp_token();
 
-       switch (pp_token.type) {
+       switch (pp_token.kind) {
        case T_IDENTIFIER:
                parse_preprocessor_identifier();
                break;
@@ -1107,7 +1118,7 @@ static void parse_preprocessor_directive(void)
 #define MAYBE(ch, set_type)                                \
                                case ch:                                   \
                                        next_char();                           \
-                                       lexer_token.type = set_type;           \
+                                       lexer_token.kind = set_type;           \
                                        return;
 
 /* must use this as last thing */
@@ -1115,7 +1126,7 @@ static void parse_preprocessor_directive(void)
                                case ch:                                   \
                                        if (c_mode & mode) {                   \
                                                next_char();                       \
-                                               lexer_token.type = set_type;       \
+                                               lexer_token.kind = set_type;       \
                                                return;                            \
                                        }                                      \
                                        /* fallthrough */
@@ -1129,13 +1140,13 @@ static void parse_preprocessor_directive(void)
 
 #define ELSE(set_type)                                     \
                ELSE_CODE(                                         \
-                       lexer_token.type = set_type;                   \
+                       lexer_token.kind = set_type;                   \
                )
 
 void lexer_next_preprocessing_token(void)
 {
        while (true) {
-               lexer_token.source_position = lexer_pos;
+               lexer_token.base.source_position = lexer_pos;
 
                switch (c) {
                case ' ':
@@ -1144,14 +1155,14 @@ void lexer_next_preprocessing_token(void)
                        break;
 
                MATCH_NEWLINE(
-                       lexer_token.type = '\n';
+                       lexer_token.kind = '\n';
                        return;
                )
 
                SYMBOL_CHARS
                        parse_symbol();
                        /* might be a wide string ( L"string" ) */
-                       if (lexer_token.symbol == symbol_L) {
+                       if (lexer_token.identifier.symbol == symbol_L) {
                                switch (c) {
                                        case '"':  parse_wide_string_literal();     break;
                                        case '\'': parse_wide_character_constant(); break;
@@ -1185,7 +1196,7 @@ void lexer_next_preprocessing_token(void)
                                        ELSE_CODE(
                                                put_back(c);
                                                c = '.';
-                                               lexer_token.type = '.';
+                                               lexer_token.kind = '.';
                                        )
                        ELSE('.')
                case '&':
@@ -1238,7 +1249,7 @@ void lexer_next_preprocessing_token(void)
                                                        ELSE_CODE(
                                                                put_back(c);
                                                                c = '%';
-                                                               lexer_token.type = '#';
+                                                               lexer_token.kind = '#';
                                                        )
                                        ELSE('#')
                        ELSE('%')
@@ -1294,19 +1305,19 @@ void lexer_next_preprocessing_token(void)
                case ';':
                case ',':
                case '\\':
-                       lexer_token.type = c;
+                       lexer_token.kind = c;
                        next_char();
                        return;
 
                case EOF:
-                       lexer_token.type = T_EOF;
+                       lexer_token.kind = T_EOF;
                        return;
 
                default:
 dollar_sign:
                        errorf(&lexer_pos, "unknown character '%c' found", c);
                        next_char();
-                       lexer_token.type = T_ERROR;
+                       lexer_token.kind = T_ERROR;
                        return;
                }
        }
@@ -1316,12 +1327,12 @@ void lexer_next_token(void)
 {
        lexer_next_preprocessing_token();
 
-       while (lexer_token.type == '\n') {
+       while (lexer_token.kind == '\n') {
 newline_found:
                lexer_next_preprocessing_token();
        }
 
-       if (lexer_token.type == '#') {
+       if (lexer_token.kind == '#') {
                parse_preprocessor_directive();
                goto newline_found;
        }
diff --git a/main.c b/main.c
index f0be72c..dc75056 100644 (file)
--- a/main.c
+++ b/main.c
@@ -197,7 +197,7 @@ static void lextest(FILE *in, const char *fname)
                lexer_next_preprocessing_token();
                print_token(stdout, &lexer_token);
                putchar('\n');
-       } while (lexer_token.type != T_EOF);
+       } while (lexer_token.kind != T_EOF);
 }
 
 static void add_flag(struct obstack *obst, const char *format, ...)
index d60a90d..c6d38f3 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -137,7 +137,7 @@ static symbol_t *sym_anonymous = NULL;
 static unsigned short token_anchor_set[T_LAST_TOKEN];
 
 /** The current source position. */
-#define HERE (&token.source_position)
+#define HERE (&token.base.source_position)
 
 /** true if we are in GCC mode. */
 #define GNU_MODE ((c_mode & _GNUC) || in_gcc_extension)
@@ -372,7 +372,7 @@ static statement_t *allocate_statement_zero(statement_kind_t kind)
 
        res->base.kind            = kind;
        res->base.parent          = current_parent;
-       res->base.source_position = token.source_position;
+       res->base.source_position = token.base.source_position;
        return res;
 }
 
@@ -389,7 +389,7 @@ static expression_t *allocate_expression_zero(expression_kind_t kind)
 
        res->base.kind            = kind;
        res->base.type            = type_error_type;
-       res->base.source_position = token.source_position;
+       res->base.source_position = token.base.source_position;
        return res;
 }
 
@@ -484,7 +484,7 @@ static inline void next_token(void)
 
 static inline bool next_if(int const type)
 {
-       if (token.type == type) {
+       if (token.kind == type) {
                next_token();
                return true;
        } else {
@@ -505,41 +505,41 @@ static inline const token_t *look_ahead(size_t num)
 /**
  * Adds a token type to the token type anchor set (a multi-set).
  */
-static void add_anchor_token(int token_type)
+static void add_anchor_token(int token_kind)
 {
-       assert(0 <= token_type && token_type < T_LAST_TOKEN);
-       ++token_anchor_set[token_type];
+       assert(0 <= token_kind && token_kind < T_LAST_TOKEN);
+       ++token_anchor_set[token_kind];
 }
 
 /**
  * Set the number of tokens types of the given type
  * to zero and return the old count.
  */
-static int save_and_reset_anchor_state(int token_type)
+static int save_and_reset_anchor_state(int token_kind)
 {
-       assert(0 <= token_type && token_type < T_LAST_TOKEN);
-       int count = token_anchor_set[token_type];
-       token_anchor_set[token_type] = 0;
+       assert(0 <= token_kind && token_kind < T_LAST_TOKEN);
+       int count = token_anchor_set[token_kind];
+       token_anchor_set[token_kind] = 0;
        return count;
 }
 
 /**
  * Restore the number of token types to the given count.
  */
-static void restore_anchor_state(int token_type, int count)
+static void restore_anchor_state(int token_kind, int count)
 {
-       assert(0 <= token_type && token_type < T_LAST_TOKEN);
-       token_anchor_set[token_type] = count;
+       assert(0 <= token_kind && token_kind < T_LAST_TOKEN);
+       token_anchor_set[token_kind] = count;
 }
 
 /**
  * Remove a token type from the token type anchor set (a multi-set).
  */
-static void rem_anchor_token(int token_type)
+static void rem_anchor_token(int token_kind)
 {
-       assert(0 <= token_type && token_type < T_LAST_TOKEN);
-       assert(token_anchor_set[token_type] != 0);
-       --token_anchor_set[token_type];
+       assert(0 <= token_kind && token_kind < T_LAST_TOKEN);
+       assert(token_anchor_set[token_kind] != 0);
+       --token_anchor_set[token_kind];
 }
 
 /**
@@ -548,9 +548,9 @@ static void rem_anchor_token(int token_type)
  */
 static bool at_anchor(void)
 {
-       if (token.type < 0)
+       if (token.kind < 0)
                return false;
-       return token_anchor_set[token.type];
+       return token_anchor_set[token.kind];
 }
 
 /**
@@ -569,11 +569,11 @@ static void eat_until_matching_token(int type)
        unsigned parenthesis_count = 0;
        unsigned brace_count       = 0;
        unsigned bracket_count     = 0;
-       while (token.type        != end_token ||
+       while (token.kind        != end_token ||
               parenthesis_count != 0         ||
               brace_count       != 0         ||
               bracket_count     != 0) {
-               switch (token.type) {
+               switch (token.kind) {
                case T_EOF: return;
                case '(': ++parenthesis_count; break;
                case '{': ++brace_count;       break;
@@ -593,7 +593,7 @@ static void eat_until_matching_token(int type)
                        if (bracket_count > 0)
                                --bracket_count;
 check_stop:
-                       if (token.type        == end_token &&
+                       if (token.kind        == end_token &&
                            parenthesis_count == 0         &&
                            brace_count       == 0         &&
                            bracket_count     == 0)
@@ -612,9 +612,9 @@ check_stop:
  */
 static void eat_until_anchor(void)
 {
-       while (token_anchor_set[token.type] == 0) {
-               if (token.type == '(' || token.type == '{' || token.type == '[')
-                       eat_until_matching_token(token.type);
+       while (token_anchor_set[token.kind] == 0) {
+               if (token.kind == '(' || token.kind == '{' || token.kind == '[')
+                       eat_until_matching_token(token.kind);
                next_token();
        }
 }
@@ -628,7 +628,7 @@ static void eat_block(void)
        next_if('}');
 }
 
-#define eat(token_type) (assert(token.type == (token_type)), next_token())
+#define eat(token_kind) (assert(token.kind == (token_kind)), next_token())
 
 /**
  * Report a parse error because an expected token was not found.
@@ -665,12 +665,12 @@ static void type_error_incompatible(const char *msg,
  */
 #define expect(expected, error_label)                     \
        do {                                                  \
-               if (UNLIKELY(token.type != (expected))) {         \
+               if (UNLIKELY(token.kind != (expected))) {         \
                        parse_error_expected(NULL, (expected), NULL); \
                        add_anchor_token(expected);                   \
                        eat_until_anchor();                           \
                        rem_anchor_token(expected);                   \
-                       if (token.type != (expected))                 \
+                       if (token.kind != (expected))                 \
                          goto error_label;                           \
                }                                                 \
                next_token();                                     \
@@ -1070,14 +1070,14 @@ static void warn_string_concat(const source_position_t *pos)
 
 static string_t parse_string_literals(void)
 {
-       assert(token.type == T_STRING_LITERAL);
-       string_t result = token.literal;
+       assert(token.kind == T_STRING_LITERAL);
+       string_t result = token.string.string;
 
        next_token();
 
-       while (token.type == T_STRING_LITERAL) {
-               warn_string_concat(&token.source_position);
-               result = concat_strings(&result, &token.literal);
+       while (token.kind == T_STRING_LITERAL) {
+               warn_string_concat(&token.base.source_position);
+               result = concat_strings(&result, &token.string.string);
                next_token();
        }
 
@@ -1140,13 +1140,13 @@ static attribute_argument_t *parse_attribute_arguments(void)
 {
        attribute_argument_t  *first  = NULL;
        attribute_argument_t **anchor = &first;
-       if (token.type != ')') do {
+       if (token.kind != ')') do {
                attribute_argument_t *argument = allocate_ast_zero(sizeof(*argument));
 
                /* is it an identifier */
-               if (token.type == T_IDENTIFIER
-                               && (look_ahead(1)->type == ',' || look_ahead(1)->type == ')')) {
-                       symbol_t *symbol   = token.symbol;
+               if (token.kind == T_IDENTIFIER
+                               && (look_ahead(1)->kind == ',' || look_ahead(1)->kind == ')')) {
+                       symbol_t *symbol   = token.identifier.symbol;
                        argument->kind     = ATTRIBUTE_ARGUMENT_SYMBOL;
                        argument->v.symbol = symbol;
                        next_token();
@@ -1186,9 +1186,9 @@ end_error:
 
 static symbol_t *get_symbol_from_token(void)
 {
-       switch(token.type) {
+       switch(token.kind) {
        case T_IDENTIFIER:
-               return token.symbol;
+               return token.identifier.symbol;
        case T_auto:
        case T_char:
        case T_double:
@@ -1218,7 +1218,7 @@ static symbol_t *get_symbol_from_token(void)
        case T_volatile:
        case T_inline:
                /* maybe we need more tokens ... add them on demand */
-               return get_token_symbol(&token);
+               return get_token_kind_symbol(token.kind);
        default:
                return NULL;
        }
@@ -1268,7 +1268,7 @@ static attribute_t *parse_attribute_gnu(void)
        expect('(', end_error);
        expect('(', end_error);
 
-       if (token.type != ')') do {
+       if (token.kind != ')') do {
                attribute_t *attribute = parse_attribute_gnu_single();
                if (attribute == NULL)
                        goto end_error;
@@ -1292,7 +1292,7 @@ static attribute_t *parse_attributes(attribute_t *first)
                        anchor = &(*anchor)->next;
 
                attribute_t *attribute;
-               switch (token.type) {
+               switch (token.kind) {
                case T___attribute__:
                        attribute = parse_attribute_gnu();
                        if (attribute == NULL)
@@ -1578,10 +1578,10 @@ static designator_t *parse_designation(void)
 
        for (;;) {
                designator_t *designator;
-               switch (token.type) {
+               switch (token.kind) {
                case '[':
                        designator = allocate_ast_zero(sizeof(designator[0]));
-                       designator->source_position = token.source_position;
+                       designator->source_position = token.base.source_position;
                        next_token();
                        add_anchor_token(']');
                        designator->array_index = parse_constant_expression();
@@ -1590,14 +1590,14 @@ static designator_t *parse_designation(void)
                        break;
                case '.':
                        designator = allocate_ast_zero(sizeof(designator[0]));
-                       designator->source_position = token.source_position;
+                       designator->source_position = token.base.source_position;
                        next_token();
-                       if (token.type != T_IDENTIFIER) {
+                       if (token.kind != T_IDENTIFIER) {
                                parse_error_expected("while parsing designator",
                                                     T_IDENTIFIER, NULL);
                                return NULL;
                        }
-                       designator->symbol = token.symbol;
+                       designator->symbol = token.identifier.symbol;
                        next_token();
                        break;
                default:
@@ -1713,12 +1713,12 @@ static initializer_t *parse_scalar_initializer(type_t *type,
 {
        /* there might be extra {} hierarchies */
        int braces = 0;
-       if (token.type == '{') {
+       if (token.kind == '{') {
                warningf(WARN_OTHER, HERE, "extra curly braces around scalar initializer");
                do {
                        eat('{');
                        ++braces;
-               } while (token.type == '{');
+               } while (token.kind == '{');
        }
 
        expression_t *expression = parse_assignment_expression();
@@ -1742,7 +1742,7 @@ static initializer_t *parse_scalar_initializer(type_t *type,
        bool additional_warning_displayed = false;
        while (braces > 0) {
                next_if(',');
-               if (token.type != '}') {
+               if (token.kind != '}') {
                        if (!additional_warning_displayed) {
                                warningf(WARN_OTHER, HERE, "additional elements in scalar initializer");
                                additional_warning_displayed = true;
@@ -2038,10 +2038,10 @@ static void skip_initializers(void)
 {
        next_if('{');
 
-       while (token.type != '}') {
-               if (token.type == T_EOF)
+       while (token.kind != '}') {
+               if (token.kind == T_EOF)
                        return;
-               if (token.type == '{') {
+               if (token.kind == '{') {
                        eat_block();
                        continue;
                }
@@ -2063,7 +2063,7 @@ static initializer_t *parse_sub_initializer(type_path_t *path,
                type_t *outer_type, size_t top_path_level,
                parse_initializer_env_t *env)
 {
-       if (token.type == '}') {
+       if (token.kind == '}') {
                /* empty initializer */
                return create_empty_initializer();
        }
@@ -2081,14 +2081,14 @@ static initializer_t *parse_sub_initializer(type_path_t *path,
 
        while (true) {
                designator_t *designator = NULL;
-               if (token.type == '.' || token.type == '[') {
+               if (token.kind == '.' || token.kind == '[') {
                        designator = parse_designation();
                        goto finish_designator;
-               } else if (token.type == T_IDENTIFIER && look_ahead(1)->type == ':') {
+               } else if (token.kind == T_IDENTIFIER && look_ahead(1)->kind == ':') {
                        /* GNU-style designator ("identifier: value") */
                        designator = allocate_ast_zero(sizeof(designator[0]));
-                       designator->source_position = token.source_position;
-                       designator->symbol          = token.symbol;
+                       designator->source_position = token.base.source_position;
+                       designator->symbol          = token.identifier.symbol;
                        eat(T_IDENTIFIER);
                        eat(':');
 
@@ -2111,7 +2111,7 @@ finish_designator:
 
                initializer_t *sub;
 
-               if (token.type == '{') {
+               if (token.kind == '{') {
                        if (type != NULL && is_type_scalar(type)) {
                                sub = parse_scalar_initializer(type, env->must_be_constant);
                        } else {
@@ -2179,7 +2179,7 @@ finish_designator:
                                sub = initializer_from_expression(outer_type, expression);
                                if (sub != NULL) {
                                        next_if(',');
-                                       if (token.type != '}') {
+                                       if (token.kind != '}') {
                                                warningf(WARN_OTHER, HERE, "excessive elements in initializer for type '%T'", orig_type);
                                        }
                                        /* TODO: eat , ... */
@@ -2224,11 +2224,11 @@ finish_designator:
                ARR_APP1(initializer_t*, initializers, sub);
 
 error_parse_next:
-               if (token.type == '}') {
+               if (token.kind == '}') {
                        break;
                }
                expect(',', end_error);
-               if (token.type == '}') {
+               if (token.kind == '}') {
                        break;
                }
 
@@ -2287,7 +2287,7 @@ static initializer_t *parse_initializer(parse_initializer_env_t *env)
 
        if (is_type_scalar(type)) {
                result = parse_scalar_initializer(type, env->must_be_constant);
-       } else if (token.type == '{') {
+       } else if (token.kind == '{') {
                eat('{');
 
                type_path_t path;
@@ -2374,31 +2374,31 @@ static compound_t *parse_compound_type_specifier(bool is_struct)
        entity_t    *entity     = NULL;
        attribute_t *attributes = NULL;
 
-       if (token.type == T___attribute__) {
+       if (token.kind == T___attribute__) {
                attributes = parse_attributes(NULL);
        }
 
        entity_kind_tag_t const kind = is_struct ? ENTITY_STRUCT : ENTITY_UNION;
-       if (token.type == T_IDENTIFIER) {
+       if (token.kind == T_IDENTIFIER) {
                /* the compound has a name, check if we have seen it already */
-               symbol = token.symbol;
+               symbol = token.identifier.symbol;
                entity = get_tag(symbol, kind);
                next_token();
 
                if (entity != NULL) {
                        if (entity->base.parent_scope != current_scope &&
-                           (token.type == '{' || token.type == ';')) {
+                           (token.kind == '{' || token.kind == ';')) {
                                /* we're in an inner scope and have a definition. Shadow
                                 * existing definition in outer scope */
                                entity = NULL;
-                       } else if (entity->compound.complete && token.type == '{') {
+                       } else if (entity->compound.complete && token.kind == '{') {
                                source_position_t const *const ppos = &entity->base.source_position;
                                errorf(&pos, "multiple definitions of '%N' (previous definition %P)", entity, ppos);
                                /* clear members in the hope to avoid further errors */
                                entity->compound.members.entities = NULL;
                        }
                }
-       } else if (token.type != '{') {
+       } else if (token.kind != '{') {
                char const *const msg =
                        is_struct ? "while parsing struct type specifier" :
                                    "while parsing union type specifier";
@@ -2418,7 +2418,7 @@ static compound_t *parse_compound_type_specifier(bool is_struct)
                append_entity(current_scope, entity);
        }
 
-       if (token.type == '{') {
+       if (token.kind == '{') {
                parse_compound_type_entries(&entity->compound);
 
                /* ISO/IEC 14882:1998(E) Â§7.1.3:5 */
@@ -2439,7 +2439,7 @@ static void parse_enum_entries(type_t *const enum_type)
 {
        eat('{');
 
-       if (token.type == '}') {
+       if (token.kind == '}') {
                errorf(HERE, "empty enum not allowed");
                next_token();
                return;
@@ -2447,16 +2447,18 @@ static void parse_enum_entries(type_t *const enum_type)
 
        add_anchor_token('}');
        do {
-               if (token.type != T_IDENTIFIER) {
+               if (token.kind != T_IDENTIFIER) {
                        parse_error_expected("while parsing enum entry", T_IDENTIFIER, NULL);
                        eat_block();
                        rem_anchor_token('}');
                        return;
                }
 
-               entity_t *const entity = allocate_entity_zero(ENTITY_ENUM_VALUE, NAMESPACE_NORMAL, token.symbol);
+               symbol_t *symbol       = token.identifier.symbol;
+               entity_t *const entity
+                       = allocate_entity_zero(ENTITY_ENUM_VALUE, NAMESPACE_NORMAL, symbol);
                entity->enum_value.enum_type = enum_type;
-               entity->base.source_position = token.source_position;
+               entity->base.source_position = token.base.source_position;
                next_token();
 
                if (next_if('=')) {
@@ -2469,7 +2471,7 @@ static void parse_enum_entries(type_t *const enum_type)
                }
 
                record_entity(entity, false);
-       } while (next_if(',') && token.type != '}');
+       } while (next_if(',') && token.kind != '}');
        rem_anchor_token('}');
 
        expect('}', end_error);
@@ -2485,19 +2487,19 @@ static type_t *parse_enum_specifier(void)
        symbol_t               *symbol;
 
        eat(T_enum);
-       switch (token.type) {
+       switch (token.kind) {
                case T_IDENTIFIER:
-                       symbol = token.symbol;
+                       symbol = token.identifier.symbol;
                        entity = get_tag(symbol, ENTITY_ENUM);
                        next_token();
 
                        if (entity != NULL) {
                                if (entity->base.parent_scope != current_scope &&
-                                               (token.type == '{' || token.type == ';')) {
+                                               (token.kind == '{' || token.kind == ';')) {
                                        /* we're in an inner scope and have a definition. Shadow
                                         * existing definition in outer scope */
                                        entity = NULL;
-                               } else if (entity->enume.complete && token.type == '{') {
+                               } else if (entity->enume.complete && token.kind == '{') {
                                        source_position_t const *const ppos = &entity->base.source_position;
                                        errorf(&pos, "multiple definitions of '%N' (previous definition %P)", entity, ppos);
                                }
@@ -2525,7 +2527,7 @@ static type_t *parse_enum_specifier(void)
        type->enumt.enume  = &entity->enume;
        type->enumt.akind  = ATOMIC_TYPE_INT;
 
-       if (token.type == '{') {
+       if (token.kind == '{') {
                if (symbol != NULL) {
                        environment_push(entity);
                }
@@ -2567,9 +2569,9 @@ static type_t *parse_typeof(void)
 
        expression_t *expression  = NULL;
 
-       switch (token.type) {
+       switch (token.kind) {
        case T_IDENTIFIER:
-               if (is_typedef_symbol(token.symbol)) {
+               if (is_typedef_symbol(token.identifier.symbol)) {
        DECLARATION_START
                        type = parse_typename();
                } else {
@@ -2634,14 +2636,14 @@ static attribute_t *parse_attribute_ms_property(attribute_t *attribute)
                = allocate_ast_zero(sizeof(*property));
 
        do {
-               if (token.type != T_IDENTIFIER) {
+               if (token.kind != T_IDENTIFIER) {
                        parse_error_expected("while parsing property declspec",
                                             T_IDENTIFIER, NULL);
                        goto end_error;
                }
 
                symbol_t **prop;
-               symbol_t  *symbol = token.symbol;
+               symbol_t  *symbol = token.identifier.symbol;
                if (strcmp(symbol->string, "put") == 0) {
                        prop = &property->put_symbol;
                } else if (strcmp(symbol->string, "get") == 0) {
@@ -2652,13 +2654,13 @@ static attribute_t *parse_attribute_ms_property(attribute_t *attribute)
                }
                eat(T_IDENTIFIER);
                expect('=', end_error);
-               if (token.type != T_IDENTIFIER) {
+               if (token.kind != T_IDENTIFIER) {
                        parse_error_expected("while parsing property declspec",
                                             T_IDENTIFIER, NULL);
                        goto end_error;
                }
                if (prop != NULL)
-                       *prop = token.symbol;
+                       *prop = token.identifier.symbol;
                next_token();
        } while (next_if(','));
 
@@ -2675,8 +2677,8 @@ static attribute_t *parse_microsoft_extended_decl_modifier_single(void)
        attribute_kind_t kind = ATTRIBUTE_UNKNOWN;
        if (next_if(T_restrict)) {
                kind = ATTRIBUTE_MS_RESTRICT;
-       } else if (token.type == T_IDENTIFIER) {
-               const char *name = token.symbol->string;
+       } else if (token.kind == T_IDENTIFIER) {
+               const char *name = token.identifier.symbol->string;
                for (attribute_kind_t k = ATTRIBUTE_MS_FIRST; k <= ATTRIBUTE_MS_LAST;
                     ++k) {
                        const char *attribute_name = get_attribute_name(k);
@@ -2767,12 +2769,12 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers)
        bool               saw_error       = false;
 
        memset(specifiers, 0, sizeof(*specifiers));
-       specifiers->source_position = token.source_position;
+       specifiers->source_position = token.base.source_position;
 
        while (true) {
                specifiers->attributes = parse_attributes(specifiers->attributes);
 
-               switch (token.type) {
+               switch (token.kind) {
                /* storage class */
 #define MATCH_STORAGE_CLASS(token, class)                                  \
                case token:                                                        \
@@ -2923,7 +2925,7 @@ wrong_thread_storage_class:
                                /* Be somewhat resilient to typos like 'unsigned lng* f()' in a
                                 * declaration, so it doesn't generate errors about expecting '(' or
                                 * '{' later on. */
-                               switch (look_ahead(1)->type) {
+                               switch (look_ahead(1)->kind) {
                                        STORAGE_CLASSES
                                        TYPE_SPECIFIERS
                                        case T_const:
@@ -2943,12 +2945,12 @@ wrong_thread_storage_class:
                                }
                        }
 
-                       type_t *const typedef_type = get_typedef_type(token.symbol);
+                       type_t *const typedef_type = get_typedef_type(token.identifier.symbol);
                        if (typedef_type == NULL) {
                                /* Be somewhat resilient to typos like 'vodi f()' at the beginning of a
                                 * declaration, so it doesn't generate 'implicit int' followed by more
                                 * errors later on. */
-                               token_type_t const la1_type = (token_type_t)look_ahead(1)->type;
+                               token_kind_t const la1_type = (token_kind_t)look_ahead(1)->kind;
                                switch (la1_type) {
                                        DECLARATION_START
                                        case T_IDENTIFIER:
@@ -2956,8 +2958,9 @@ wrong_thread_storage_class:
                                        case '*': {
                                                errorf(HERE, "%K does not name a type", &token);
 
-                                               entity_t *entity =
-                                                       create_error_entity(token.symbol, ENTITY_TYPEDEF);
+                                               symbol_t *symbol = token.identifier.symbol;
+                                               entity_t *entity
+                                                       = create_error_entity(symbol, ENTITY_TYPEDEF);
 
                                                type = allocate_type_zero(TYPE_TYPEDEF);
                                                type->typedeft.typedefe = &entity->typedefe;
@@ -3185,7 +3188,7 @@ static type_qualifiers_t parse_type_qualifiers(void)
        type_qualifiers_t qualifiers = TYPE_QUALIFIER_NONE;
 
        while (true) {
-               switch (token.type) {
+               switch (token.kind) {
                /* type qualifiers */
                MATCH_TYPE_QUALIFIER(T_const,    TYPE_QUALIFIER_CONST);
                MATCH_TYPE_QUALIFIER(T_restrict, TYPE_QUALIFIER_RESTRICT);
@@ -3208,15 +3211,16 @@ static type_qualifiers_t parse_type_qualifiers(void)
  */
 static void parse_identifier_list(scope_t *scope)
 {
+       assert(token.kind == T_IDENTIFIER);
        do {
-               entity_t *const entity = allocate_entity_zero(ENTITY_PARAMETER, NAMESPACE_NORMAL, token.symbol);
-               entity->base.source_position = token.source_position;
+               entity_t *const entity = allocate_entity_zero(ENTITY_PARAMETER, NAMESPACE_NORMAL, token.identifier.symbol);
+               entity->base.source_position = token.base.source_position;
                /* a K&R parameter has no type, yet */
                next_token();
 
                if (scope != NULL)
                        append_entity(scope, entity);
-       } while (next_if(',') && token.type == T_IDENTIFIER);
+       } while (next_if(',') && token.kind == T_IDENTIFIER);
 }
 
 static entity_t *parse_parameter(void)
@@ -3247,18 +3251,19 @@ static void semantic_parameter_incomplete(const entity_t *entity)
 static bool has_parameters(void)
 {
        /* func(void) is not a parameter */
-       if (token.type == T_IDENTIFIER) {
-               entity_t const *const entity = get_entity(token.symbol, NAMESPACE_NORMAL);
+       if (token.kind == T_IDENTIFIER) {
+               entity_t const *const entity
+                       = get_entity(token.identifier.symbol, NAMESPACE_NORMAL);
                if (entity == NULL)
                        return true;
                if (entity->kind != ENTITY_TYPEDEF)
                        return true;
                if (skip_typeref(entity->typedefe.type) != type_void)
                        return true;
-       } else if (token.type != T_void) {
+       } else if (token.kind != T_void) {
                return true;
        }
-       if (look_ahead(1)->type != ')')
+       if (look_ahead(1)->kind != ')')
                return true;
        next_token();
        return false;
@@ -3274,9 +3279,9 @@ static void parse_parameters(function_type_t *type, scope_t *scope)
        add_anchor_token(')');
        int saved_comma_state = save_and_reset_anchor_state(',');
 
-       if (token.type == T_IDENTIFIER &&
-           !is_typedef_symbol(token.symbol)) {
-               token_type_t la1_type = (token_type_t)look_ahead(1)->type;
+       if (token.kind == T_IDENTIFIER
+           && !is_typedef_symbol(token.identifier.symbol)) {
+               token_kind_t la1_type = (token_kind_t)look_ahead(1)->kind;
                if (la1_type == ',' || la1_type == ')') {
                        type->kr_style_parameters = true;
                        parse_identifier_list(scope);
@@ -3284,14 +3289,14 @@ static void parse_parameters(function_type_t *type, scope_t *scope)
                }
        }
 
-       if (token.type == ')') {
+       if (token.kind == ')') {
                /* ISO/IEC 14882:1998(E) Â§C.1.6:1 */
                if (!(c_mode & _CXX))
                        type->unspecified_parameters = true;
        } else if (has_parameters()) {
                function_parameter_t **anchor = &type->parameters;
                do {
-                       switch (token.type) {
+                       switch (token.kind) {
                        case T_DOTDOTDOT:
                                next_token();
                                type->variadic = true;
@@ -3436,10 +3441,10 @@ static construct_type_t *parse_array_declarator(void)
        array->is_static       = is_static;
 
        expression_t *size = NULL;
-       if (token.type == '*' && look_ahead(1)->type == ']') {
+       if (token.kind == '*' && look_ahead(1)->kind == ']') {
                array->is_variable = true;
                next_token();
-       } else if (token.type != ']') {
+       } else if (token.kind != ']') {
                size = parse_assignment_expression();
 
                /* Â§6.7.5.2:1  Array size must have integer type */
@@ -3506,7 +3511,7 @@ static construct_type_t *parse_inner_declarator(parse_declarator_env_t *env)
        for (;;) {
                construct_type_t *type;
                //variable_t       *based = NULL; /* MS __based extension */
-               switch (token.type) {
+               switch (token.kind) {
                        case '&':
                                type = parse_reference_declarator();
                                break;
@@ -3534,13 +3539,13 @@ static construct_type_t *parse_inner_declarator(parse_declarator_env_t *env)
 ptr_operator_end: ;
        construct_type_t *inner_types = NULL;
 
-       switch (token.type) {
+       switch (token.kind) {
        case T_IDENTIFIER:
                if (env->must_be_abstract) {
                        errorf(HERE, "no identifier expected in typename");
                } else {
-                       env->symbol          = token.symbol;
-                       env->source_position = token.source_position;
+                       env->symbol          = token.identifier.symbol;
+                       env->source_position = token.base.source_position;
                }
                next_token();
                break;
@@ -3548,9 +3553,9 @@ ptr_operator_end: ;
        case '(': {
                /* Parenthesized declarator or function declarator? */
                token_t const *const la1 = look_ahead(1);
-               switch (la1->type) {
+               switch (la1->kind) {
                        case T_IDENTIFIER:
-                               if (is_typedef_symbol(la1->symbol)) {
+                               if (is_typedef_symbol(la1->identifier.symbol)) {
                        case ')':
                                        /* Â§6.7.6:2 footnote 126:  Empty parentheses in a type name are
                                         * interpreted as ``function with no parameter specification'', rather
@@ -3594,7 +3599,7 @@ ptr_operator_end: ;
 
        for (;;) {
                construct_type_t *type;
-               switch (token.type) {
+               switch (token.kind) {
                case '(': {
                        scope_t *scope = NULL;
                        if (!env->must_be_abstract) {
@@ -4282,11 +4287,11 @@ static void parser_error_multiple_definition(entity_t *entity,
 
 static bool is_declaration_specifier(const token_t *token)
 {
-       switch (token->type) {
+       switch (token->kind) {
                DECLARATION_START
                        return true;
                case T_IDENTIFIER:
-                       return is_typedef_symbol(token->symbol);
+                       return is_typedef_symbol(token->identifier.symbol);
 
                default:
                        return false;
@@ -4408,9 +4413,9 @@ static void parse_declaration_rest(entity_t *ndeclaration,
        add_anchor_token(';');
        add_anchor_token(',');
        while (true) {
-               entity_t *entity = finished_declaration(ndeclaration, token.type == '=');
+               entity_t *entity = finished_declaration(ndeclaration, token.kind == '=');
 
-               if (token.type == '=') {
+               if (token.kind == '=') {
                        parse_init_declarator_rest(entity);
                } else if (entity->kind == ENTITY_VARIABLE) {
                        /* ISO/IEC 14882:1998(E) Â§8.5.3:3  The initializer can be omitted
@@ -4472,7 +4477,7 @@ static void parse_declaration(parsed_declaration_func finished_declaration,
        parse_declaration_specifiers(&specifiers);
        rem_anchor_token(';');
 
-       if (token.type == ';') {
+       if (token.kind == ';') {
                parse_anonymous_declaration_rest(&specifiers);
        } else {
                entity_t *entity = parse_declarator(&specifiers, flags);
@@ -4518,7 +4523,7 @@ static void parse_kr_declaration_list(entity_t *entity)
 
        /* parse declaration list */
        for (;;) {
-               switch (token.type) {
+               switch (token.kind) {
                        DECLARATION_START
                        /* This covers symbols, which are no type, too, and results in
                         * better error messages.  The typical cases are misspelled type
@@ -5349,7 +5354,7 @@ static void parse_external_declaration(void)
        rem_anchor_token(';');
 
        /* must be a declaration */
-       if (token.type == ';') {
+       if (token.kind == ';') {
                parse_anonymous_declaration_rest(&specifiers);
                return;
        }
@@ -5368,7 +5373,7 @@ static void parse_external_declaration(void)
        rem_anchor_token(',');
 
        /* must be a declaration */
-       switch (token.type) {
+       switch (token.kind) {
                case ',':
                case ';':
                case '=':
@@ -5380,7 +5385,7 @@ static void parse_external_declaration(void)
        /* must be a function definition */
        parse_kr_declaration_list(ndeclaration);
 
-       if (token.type != '{') {
+       if (token.kind != '{') {
                parse_error_expected("while parsing function definition", '{', NULL);
                eat_until_matching_token(';');
                return;
@@ -5654,7 +5659,7 @@ static void parse_compound_declarators(compound_t *compound,
        do {
                entity_t *entity;
 
-               if (token.type == ':') {
+               if (token.kind == ':') {
                        source_position_t source_position = *HERE;
                        next_token();
 
@@ -5700,7 +5705,7 @@ static void parse_compound_declarators(compound_t *compound,
                                        }
                                }
 
-                               if (token.type == ':') {
+                               if (token.kind == ':') {
                                        source_position_t source_position = *HERE;
                                        next_token();
                                        expression_t *size = parse_constant_expression();
@@ -5720,8 +5725,8 @@ static void parse_compound_declarators(compound_t *compound,
                                        } else if (is_type_incomplete(type)) {
                                                /* Â§6.7.2.1:16 flexible array member */
                                                if (!is_type_array(type)       ||
-                                                               token.type          != ';' ||
-                                                               look_ahead(1)->type != '}') {
+                                                               token.kind          != ';' ||
+                                                               look_ahead(1)->kind != '}') {
                                                        errorf(pos, "'%N' has incomplete type '%T'", entity, orig_type);
                                                }
                                        }
@@ -5743,7 +5748,7 @@ static void parse_compound_type_entries(compound_t *compound)
        add_anchor_token('}');
 
        for (;;) {
-               switch (token.type) {
+               switch (token.kind) {
                        DECLARATION_START
                        case T___extension__:
                        case T_IDENTIFIER: {
@@ -5804,7 +5809,7 @@ static expression_parser_function_t expression_parsers[T_LAST_TOKEN];
 static expression_t *expected_expression_error(void)
 {
        /* skip the error message if the error token was read */
-       if (token.type != T_ERROR) {
+       if (token.kind != T_ERROR) {
                errorf(HERE, "expected expression, got token %K", &token);
        }
        next_token();
@@ -5827,17 +5832,17 @@ static type_t *get_wide_string_type(void)
  */
 static expression_t *parse_string_literal(void)
 {
-       source_position_t begin   = token.source_position;
-       string_t          res     = token.literal;
-       bool              is_wide = (token.type == T_WIDE_STRING_LITERAL);
+       source_position_t begin   = token.base.source_position;
+       string_t          res     = token.string.string;
+       bool              is_wide = (token.kind == T_WIDE_STRING_LITERAL);
 
        next_token();
-       while (token.type == T_STRING_LITERAL
-                       || token.type == T_WIDE_STRING_LITERAL) {
-               warn_string_concat(&token.source_position);
-               res = concat_strings(&res, &token.literal);
+       while (token.kind == T_STRING_LITERAL
+                       || token.kind == T_WIDE_STRING_LITERAL) {
+               warn_string_concat(&token.base.source_position);
+               res = concat_strings(&res, &token.string.string);
                next_token();
-               is_wide |= token.type == T_WIDE_STRING_LITERAL;
+               is_wide |= token.kind == T_WIDE_STRING_LITERAL;
        }
 
        expression_t *literal;
@@ -5870,17 +5875,18 @@ static expression_t *parse_boolean_literal(bool value)
 
 static void warn_traditional_suffix(void)
 {
-       warningf(WARN_TRADITIONAL, HERE, "traditional C rejects the '%Y' suffix", token.symbol);
+       warningf(WARN_TRADITIONAL, HERE, "traditional C rejects the '%S' suffix",
+                &token.number.suffix);
 }
 
 static void check_integer_suffix(void)
 {
-       symbol_t *suffix = token.symbol;
-       if (suffix == NULL)
+       const string_t *suffix = &token.number.suffix;
+       if (suffix->size == 0)
                return;
 
        bool not_traditional = false;
-       const char *c = suffix->string;
+       const char *c = suffix->begin;
        if (*c == 'l' || *c == 'L') {
                ++c;
                if (*c == *(c-1)) {
@@ -5904,8 +5910,8 @@ static void check_integer_suffix(void)
                }
        }
        if (*c != '\0') {
-               errorf(&token.source_position,
-                      "invalid suffix '%s' on integer constant", suffix->string);
+               errorf(&token.base.source_position,
+                      "invalid suffix '%S' on integer constant", suffix);
        } else if (not_traditional) {
                warn_traditional_suffix();
        }
@@ -5913,13 +5919,13 @@ static void check_integer_suffix(void)
 
 static type_t *check_floatingpoint_suffix(void)
 {
-       symbol_t *suffix = token.symbol;
-       type_t   *type   = type_double;
-       if (suffix == NULL)
+       const string_t *suffix = &token.number.suffix;
+       type_t         *type   = type_double;
+       if (suffix->size == 0)
                return type;
 
        bool not_traditional = false;
-       const char *c = suffix->string;
+       const char *c = suffix->begin;
        if (*c == 'f' || *c == 'F') {
                ++c;
                type = type_float;
@@ -5928,8 +5934,8 @@ static type_t *check_floatingpoint_suffix(void)
                type = type_long_double;
        }
        if (*c != '\0') {
-               errorf(&token.source_position,
-                      "invalid suffix '%s' on floatingpoint constant", suffix->string);
+               errorf(&token.base.source_position,
+                      "invalid suffix '%S' on floatingpoint constant", suffix);
        } else if (not_traditional) {
                warn_traditional_suffix();
        }
@@ -5945,7 +5951,7 @@ static expression_t *parse_number_literal(void)
        expression_kind_t  kind;
        type_t            *type;
 
-       switch (token.type) {
+       switch (token.kind) {
        case T_INTEGER:
                kind = EXPR_LITERAL_INTEGER;
                check_integer_suffix();
@@ -5975,8 +5981,8 @@ static expression_t *parse_number_literal(void)
 
        expression_t *literal = allocate_expression_zero(kind);
        literal->base.type      = type;
-       literal->literal.value  = token.literal;
-       literal->literal.suffix = token.symbol;
+       literal->literal.value  = token.number.number;
+       literal->literal.suffix = token.number.suffix;
        next_token();
 
        /* integer type depends on the size of the number and the size
@@ -5994,7 +6000,7 @@ static expression_t *parse_character_constant(void)
 {
        expression_t *literal = allocate_expression_zero(EXPR_LITERAL_CHARACTER);
        literal->base.type     = c_mode & _CXX ? type_char : type_int;
-       literal->literal.value = token.literal;
+       literal->literal.value = token.string.string;
 
        size_t len = literal->literal.value.size;
        if (len > 1) {
@@ -6017,7 +6023,7 @@ static expression_t *parse_wide_character_constant(void)
 {
        expression_t *literal = allocate_expression_zero(EXPR_LITERAL_WIDE_CHARACTER);
        literal->base.type     = type_int;
-       literal->literal.value = token.literal;
+       literal->literal.value = token.string.string;
 
        size_t len = wstrlen(&literal->literal.value);
        if (len > 1) {
@@ -6169,11 +6175,11 @@ static entity_t *parse_qualified_identifier(void)
 
        entity_t *entity;
        while (true) {
-               if (token.type != T_IDENTIFIER) {
+               if (token.kind != T_IDENTIFIER) {
                        parse_error_expected("while parsing identifier", T_IDENTIFIER, NULL);
                        return create_error_entity(sym_anonymous, ENTITY_VARIABLE);
                }
-               symbol = token.symbol;
+               symbol = token.identifier.symbol;
                pos    = *HERE;
                next_token();
 
@@ -6204,7 +6210,7 @@ static entity_t *parse_qualified_identifier(void)
        }
 
        if (entity == NULL) {
-               if (!strict_mode && token.type == '(') {
+               if (!strict_mode && token.kind == '(') {
                        /* an implicitly declared function */
                        warningf(WARN_IMPLICIT_FUNCTION_DECLARATION, &pos, "implicit declaration of function '%Y'", symbol);
                        entity = create_implicit_function(symbol, &pos);
@@ -6219,7 +6225,7 @@ static entity_t *parse_qualified_identifier(void)
 
 static expression_t *parse_reference(void)
 {
-       source_position_t const pos    = token.source_position;
+       source_position_t const pos    = token.base.source_position;
        entity_t         *const entity = parse_qualified_identifier();
 
        type_t *orig_type;
@@ -6345,7 +6351,7 @@ static expression_t *parse_cast(void)
        rem_anchor_token(')');
        expect(')', end_error);
 
-       if (token.type == '{') {
+       if (token.kind == '{') {
                return parse_compound_literal(&pos, type);
        }
 
@@ -6408,13 +6414,13 @@ end_error:
 static expression_t *parse_parenthesized_expression(void)
 {
        token_t const* const la1 = look_ahead(1);
-       switch (la1->type) {
+       switch (la1->kind) {
        case '{':
                /* gcc extension: a statement expression */
                return parse_statement_expression();
 
        case T_IDENTIFIER:
-               if (is_typedef_symbol(la1->symbol)) {
+               if (is_typedef_symbol(la1->identifier.symbol)) {
        DECLARATION_START
                        return parse_cast();
                }
@@ -6498,25 +6504,25 @@ static designator_t *parse_designator(void)
        designator_t *result    = allocate_ast_zero(sizeof(result[0]));
        result->source_position = *HERE;
 
-       if (token.type != T_IDENTIFIER) {
+       if (token.kind != T_IDENTIFIER) {
                parse_error_expected("while parsing member designator",
                                     T_IDENTIFIER, NULL);
                return NULL;
        }
-       result->symbol = token.symbol;
+       result->symbol = token.identifier.symbol;
        next_token();
 
        designator_t *last_designator = result;
        while (true) {
                if (next_if('.')) {
-                       if (token.type != T_IDENTIFIER) {
+                       if (token.kind != T_IDENTIFIER) {
                                parse_error_expected("while parsing member designator",
                                                     T_IDENTIFIER, NULL);
                                return NULL;
                        }
                        designator_t *designator    = allocate_ast_zero(sizeof(result[0]));
                        designator->source_position = *HERE;
-                       designator->symbol          = token.symbol;
+                       designator->symbol          = token.identifier.symbol;
                        next_token();
 
                        last_designator->next = designator;
@@ -6729,7 +6735,7 @@ static expression_t *parse_compare_builtin(void)
 {
        expression_t *expression;
 
-       switch (token.type) {
+       switch (token.kind) {
        case T___builtin_isgreater:
                expression = allocate_expression_zero(EXPR_BINARY_ISGREATER);
                break;
@@ -6805,10 +6811,10 @@ end_error:
  */
 static label_t *get_label(void)
 {
-       assert(token.type == T_IDENTIFIER);
+       assert(token.kind == T_IDENTIFIER);
        assert(current_function != NULL);
 
-       entity_t *label = get_entity(token.symbol, NAMESPACE_LABEL);
+       entity_t *label = get_entity(token.identifier.symbol, NAMESPACE_LABEL);
        /* If we find a local label, we already created the declaration. */
        if (label != NULL && label->kind == ENTITY_LOCAL_LABEL) {
                if (label->base.parent_scope != current_scope) {
@@ -6817,7 +6823,7 @@ static label_t *get_label(void)
                }
        } else if (label == NULL || label->base.parent_scope != &current_function->parameters) {
                /* There is no matching label in the same function, so create a new one. */
-               label = allocate_entity_zero(ENTITY_LABEL, NAMESPACE_LABEL, token.symbol);
+               label = allocate_entity_zero(ENTITY_LABEL, NAMESPACE_LABEL, token.identifier.symbol);
                label_push(label);
        }
 
@@ -6830,9 +6836,9 @@ static label_t *get_label(void)
  */
 static expression_t *parse_label_address(void)
 {
-       source_position_t source_position = token.source_position;
+       source_position_t source_position = token.base.source_position;
        eat(T_ANDAND);
-       if (token.type != T_IDENTIFIER) {
+       if (token.kind != T_IDENTIFIER) {
                parse_error_expected("while parsing label address", T_IDENTIFIER, NULL);
                return create_invalid_expression();
        }
@@ -6863,13 +6869,13 @@ static expression_t *parse_noop_expression(void)
 
        eat(T___noop);
 
-       if (token.type == '(') {
+       if (token.kind == '(') {
                /* parse arguments */
                eat('(');
                add_anchor_token(')');
                add_anchor_token(',');
 
-               if (token.type != ')') do {
+               if (token.kind != ')') do {
                        (void)parse_assignment_expression();
                } while (next_if(','));
        }
@@ -6886,7 +6892,7 @@ end_error:
  */
 static expression_t *parse_primary_expression(void)
 {
-       switch (token.type) {
+       switch (token.kind) {
        case T_false:                        return parse_boolean_literal(false);
        case T_true:                         return parse_boolean_literal(true);
        case T_INTEGER:
@@ -6928,7 +6934,7 @@ static expression_t *parse_primary_expression(void)
        case T_COLONCOLON:
                return parse_reference();
        case T_IDENTIFIER:
-               if (!is_typedef_symbol(token.symbol)) {
+               if (!is_typedef_symbol(token.identifier.symbol)) {
                        return parse_reference();
                }
                /* FALLTHROUGH */
@@ -7015,7 +7021,7 @@ static expression_t *parse_typeprop(expression_kind_t const kind)
 
        type_t       *orig_type;
        expression_t *expression;
-       if (token.type == '(' && is_declaration_specifier(look_ahead(1))) {
+       if (token.kind == '(' && is_declaration_specifier(look_ahead(1))) {
                source_position_t const pos = *HERE;
                next_token();
                add_anchor_token(')');
@@ -7023,7 +7029,7 @@ static expression_t *parse_typeprop(expression_kind_t const kind)
                rem_anchor_token(')');
                expect(')', end_error);
 
-               if (token.type == '{') {
+               if (token.kind == '{') {
                        /* It was not sizeof(type) after all.  It is sizeof of an expression
                         * starting with a compound literal */
                        expression = parse_compound_literal(&pos, orig_type);
@@ -7084,16 +7090,16 @@ static expression_t *parse_alignof(void)
 
 static expression_t *parse_select_expression(expression_t *addr)
 {
-       assert(token.type == '.' || token.type == T_MINUSGREATER);
-       bool select_left_arrow = (token.type == T_MINUSGREATER);
+       assert(token.kind == '.' || token.kind == T_MINUSGREATER);
+       bool select_left_arrow = (token.kind == T_MINUSGREATER);
        source_position_t const pos = *HERE;
        next_token();
 
-       if (token.type != T_IDENTIFIER) {
+       if (token.kind != T_IDENTIFIER) {
                parse_error_expected("while parsing select", T_IDENTIFIER, NULL);
                return create_invalid_expression();
        }
-       symbol_t *symbol = token.symbol;
+       symbol_t *symbol = token.identifier.symbol;
        next_token();
 
        type_t *const orig_type = addr->base.type;
@@ -7294,7 +7300,7 @@ static expression_t *parse_call_expression(expression_t *expression)
        add_anchor_token(')');
        add_anchor_token(',');
 
-       if (token.type != ')') {
+       if (token.kind != ')') {
                call_argument_t **anchor = &call->arguments;
                do {
                        call_argument_t *argument = allocate_ast_zero(sizeof(*argument));
@@ -7451,7 +7457,7 @@ static expression_t *parse_conditional_expression(expression_t *expression)
 
        expression_t *true_expression = expression;
        bool          gnu_cond = false;
-       if (GNU_MODE && token.type == ':') {
+       if (GNU_MODE && token.kind == ':') {
                gnu_cond = true;
        } else {
                true_expression = parse_expression();
@@ -7627,7 +7633,7 @@ static expression_t *parse_throw(void)
        eat(T_throw);
 
        expression_t *value = NULL;
-       switch (token.type) {
+       switch (token.kind) {
                EXPRESSION_START {
                        value = parse_assignment_expression();
                        /* ISO/IEC 14882:1998(E) Â§15.1:3 */
@@ -7849,12 +7855,12 @@ static void semantic_take_addr(unary_expression_t *expression)
        expression->base.type = make_pointer_type(orig_type, TYPE_QUALIFIER_NONE);
 }
 
-#define CREATE_UNARY_EXPRESSION_PARSER(token_type, unexpression_type, sfunc) \
+#define CREATE_UNARY_EXPRESSION_PARSER(token_kind, unexpression_type, sfunc) \
 static expression_t *parse_##unexpression_type(void)                         \
 {                                                                            \
        expression_t *unary_expression                                           \
                = allocate_expression_zero(unexpression_type);                       \
-       eat(token_type);                                                         \
+       eat(token_kind);                                                         \
        unary_expression->unary.value = parse_subexpression(PREC_UNARY);         \
                                                                                 \
        sfunc(&unary_expression->unary);                                         \
@@ -7879,13 +7885,13 @@ CREATE_UNARY_EXPRESSION_PARSER(T_PLUSPLUS,   EXPR_UNARY_PREFIX_INCREMENT,
 CREATE_UNARY_EXPRESSION_PARSER(T_MINUSMINUS, EXPR_UNARY_PREFIX_DECREMENT,
                                semantic_incdec)
 
-#define CREATE_UNARY_POSTFIX_EXPRESSION_PARSER(token_type, unexpression_type, \
+#define CREATE_UNARY_POSTFIX_EXPRESSION_PARSER(token_kind, unexpression_type, \
                                                sfunc)                         \
 static expression_t *parse_##unexpression_type(expression_t *left)            \
 {                                                                             \
        expression_t *unary_expression                                            \
                = allocate_expression_zero(unexpression_type);                        \
-       eat(token_type);                                                          \
+       eat(token_kind);                                                          \
        unary_expression->unary.value = left;                                     \
                                                                                  \
        sfunc(&unary_expression->unary);                                          \
@@ -8663,12 +8669,12 @@ static void semantic_comma(binary_expression_t *expression)
 /**
  * @param prec_r precedence of the right operand
  */
-#define CREATE_BINEXPR_PARSER(token_type, binexpression_type, prec_r, sfunc) \
+#define CREATE_BINEXPR_PARSER(token_kind, binexpression_type, prec_r, sfunc) \
 static expression_t *parse_##binexpression_type(expression_t *left)          \
 {                                                                            \
        expression_t *binexpr = allocate_expression_zero(binexpression_type);    \
        binexpr->binary.left  = left;                                            \
-       eat(token_type);                                                         \
+       eat(token_kind);                                                         \
                                                                              \
        expression_t *right = parse_subexpression(prec_r);                       \
                                                                              \
@@ -8712,12 +8718,12 @@ CREATE_BINEXPR_PARSER(',',                    EXPR_BINARY_COMMA,              PR
 
 static expression_t *parse_subexpression(precedence_t precedence)
 {
-       if (token.type < 0) {
+       if (token.kind < 0) {
                return expected_expression_error();
        }
 
        expression_parser_function_t *parser
-               = &expression_parsers[token.type];
+               = &expression_parsers[token.kind];
        expression_t                 *left;
 
        if (parser->parser != NULL) {
@@ -8728,11 +8734,11 @@ static expression_t *parse_subexpression(precedence_t precedence)
        assert(left != NULL);
 
        while (true) {
-               if (token.type < 0) {
+               if (token.kind < 0) {
                        return expected_expression_error();
                }
 
-               parser = &expression_parsers[token.type];
+               parser = &expression_parsers[token.kind];
                if (parser->infix_parser == NULL)
                        break;
                if (parser->infix_precedence < precedence)
@@ -8759,15 +8765,15 @@ static expression_t *parse_expression(void)
  * Register a parser for a prefix-like operator.
  *
  * @param parser      the parser function
- * @param token_type  the token type of the prefix token
+ * @param token_kind  the token type of the prefix token
  */
 static void register_expression_parser(parse_expression_function parser,
-                                       int token_type)
+                                       int token_kind)
 {
-       expression_parser_function_t *entry = &expression_parsers[token_type];
+       expression_parser_function_t *entry = &expression_parsers[token_kind];
 
        if (entry->parser != NULL) {
-               diagnosticf("for token '%k'\n", (token_type_t)token_type);
+               diagnosticf("for token '%k'\n", (token_kind_t)token_kind);
                panic("trying to register multiple expression parsers for a token");
        }
        entry->parser = parser;
@@ -8777,16 +8783,16 @@ static void register_expression_parser(parse_expression_function parser,
  * Register a parser for an infix operator with given precedence.
  *
  * @param parser      the parser function
- * @param token_type  the token type of the infix operator
+ * @param token_kind  the token type of the infix operator
  * @param precedence  the precedence of the operator
  */
 static void register_infix_parser(parse_expression_infix_function parser,
-                                  int token_type, precedence_t precedence)
+                                  int token_kind, precedence_t precedence)
 {
-       expression_parser_function_t *entry = &expression_parsers[token_type];
+       expression_parser_function_t *entry = &expression_parsers[token_kind];
 
        if (entry->infix_parser != NULL) {
-               diagnosticf("for token '%k'\n", (token_type_t)token_type);
+               diagnosticf("for token '%k'\n", (token_kind_t)token_kind);
                panic("trying to register multiple infix expression parsers for a "
                      "token");
        }
@@ -8863,17 +8869,17 @@ static asm_argument_t *parse_asm_arguments(bool is_out)
        asm_argument_t  *result = NULL;
        asm_argument_t **anchor = &result;
 
-       while (token.type == T_STRING_LITERAL || token.type == '[') {
+       while (token.kind == T_STRING_LITERAL || token.kind == '[') {
                asm_argument_t *argument = allocate_ast_zero(sizeof(argument[0]));
                memset(argument, 0, sizeof(argument[0]));
 
                if (next_if('[')) {
-                       if (token.type != T_IDENTIFIER) {
+                       if (token.kind != T_IDENTIFIER) {
                                parse_error_expected("while parsing asm argument",
                                                     T_IDENTIFIER, NULL);
                                return NULL;
                        }
-                       argument->symbol = token.symbol;
+                       argument->symbol = token.identifier.symbol;
 
                        expect(']', end_error);
                }
@@ -8965,7 +8971,7 @@ static asm_clobber_t *parse_asm_clobbers(void)
        asm_clobber_t *result  = NULL;
        asm_clobber_t **anchor = &result;
 
-       while (token.type == T_STRING_LITERAL) {
+       while (token.kind == T_STRING_LITERAL) {
                asm_clobber_t *clobber = allocate_ast_zero(sizeof(clobber[0]));
                clobber->clobber       = parse_string_literals();
 
@@ -8994,7 +9000,7 @@ static statement_t *parse_asm_statement(void)
 
        expect('(', end_error);
        add_anchor_token(')');
-       if (token.type != T_STRING_LITERAL) {
+       if (token.kind != T_STRING_LITERAL) {
                parse_error_expected("after asm(", T_STRING_LITERAL, NULL);
                goto end_of_asm;
        }
@@ -9040,7 +9046,7 @@ end_error:
 static statement_t *parse_label_inner_statement(statement_t const *const label, char const *const label_kind)
 {
        statement_t *inner_stmt;
-       switch (token.type) {
+       switch (token.kind) {
                case '}':
                        errorf(&label->base.source_position, "%s at end of compound statement", label_kind);
                        inner_stmt = create_invalid_statement();
@@ -9217,7 +9223,7 @@ static statement_t *parse_label_statement(void)
 
        eat(':');
 
-       if (token.type == T___attribute__ && !(c_mode & _CXX)) {
+       if (token.kind == T___attribute__ && !(c_mode & _CXX)) {
                parse_attributes(NULL); // TODO process attributes
        }
 
@@ -9487,7 +9493,7 @@ static statement_t *parse_for(void)
 
        POP_EXTENSION();
 
-       if (token.type != ';') {
+       if (token.kind != ';') {
                add_anchor_token(';');
                expression_t *const cond = parse_expression();
                statement->fors.condition = cond;
@@ -9498,7 +9504,7 @@ static statement_t *parse_for(void)
                rem_anchor_token(';');
        }
        expect(';', end_error2);
-       if (token.type != ')') {
+       if (token.kind != ')') {
                expression_t *const step = parse_expression();
                statement->fors.step = step;
                mark_vars_read(step, ENT_ANY);
@@ -9551,7 +9557,7 @@ static statement_t *parse_goto(void)
                }
 
                statement->gotos.expression = expression;
-       } else if (token.type == T_IDENTIFIER) {
+       } else if (token.kind == T_IDENTIFIER) {
                label_t *const label = get_label();
                label->used            = true;
                statement->gotos.label = label;
@@ -9688,7 +9694,7 @@ static statement_t *parse_return(void)
        eat(T_return);
 
        expression_t *return_value = NULL;
-       if (token.type != ';') {
+       if (token.kind != ';') {
                return_value = parse_expression();
                mark_vars_read(return_value, NULL);
        }
@@ -9854,12 +9860,12 @@ static statement_t *parse_local_label_declaration(void)
        entity_t *end     = NULL;
        entity_t **anchor = &begin;
        do {
-               if (token.type != T_IDENTIFIER) {
+               if (token.kind != T_IDENTIFIER) {
                        parse_error_expected("while parsing local label declaration",
                                T_IDENTIFIER, NULL);
                        goto end_error;
                }
-               symbol_t *symbol = token.symbol;
+               symbol_t *symbol = token.identifier.symbol;
                entity_t *entity = get_entity(symbol, NAMESPACE_LABEL);
                if (entity != NULL && entity->base.parent_scope == current_scope) {
                        source_position_t const *const ppos = &entity->base.source_position;
@@ -9867,7 +9873,7 @@ static statement_t *parse_local_label_declaration(void)
                } else {
                        entity = allocate_entity_zero(ENTITY_LOCAL_LABEL, NAMESPACE_LABEL, symbol);
                        entity->base.parent_scope    = current_scope;
-                       entity->base.source_position = token.source_position;
+                       entity->base.source_position = token.base.source_position;
 
                        *anchor = entity;
                        anchor  = &entity->base.next;
@@ -9891,8 +9897,8 @@ static void parse_namespace_definition(void)
        entity_t *entity = NULL;
        symbol_t *symbol = NULL;
 
-       if (token.type == T_IDENTIFIER) {
-               symbol = token.symbol;
+       if (token.kind == T_IDENTIFIER) {
+               symbol = token.identifier.symbol;
                next_token();
 
                entity = get_entity(symbol, NAMESPACE_NORMAL);
@@ -9900,7 +9906,7 @@ static void parse_namespace_definition(void)
                                && entity->kind != ENTITY_NAMESPACE
                                && entity->base.parent_scope == current_scope) {
                        if (is_entity_valid(entity)) {
-                               error_redefined_as_different_kind(&token.source_position,
+                               error_redefined_as_different_kind(&token.base.source_position,
                                                entity, ENTITY_NAMESPACE);
                        }
                        entity = NULL;
@@ -9909,11 +9915,11 @@ static void parse_namespace_definition(void)
 
        if (entity == NULL) {
                entity = allocate_entity_zero(ENTITY_NAMESPACE, NAMESPACE_NORMAL, symbol);
-               entity->base.source_position = token.source_position;
+               entity->base.source_position = token.base.source_position;
                entity->base.parent_scope    = current_scope;
        }
 
-       if (token.type == '=') {
+       if (token.kind == '=') {
                /* TODO: parse namespace alias */
                panic("namespace alias definition not supported yet");
        }
@@ -9947,12 +9953,12 @@ static statement_t *intern_parse_statement(void)
 
        /* declaration or statement */
        add_anchor_token(';');
-       switch (token.type) {
+       switch (token.kind) {
        case T_IDENTIFIER: {
-               token_type_t la1_type = (token_type_t)look_ahead(1)->type;
+               token_kind_t la1_type = (token_kind_t)look_ahead(1)->kind;
                if (la1_type == ':') {
                        statement = parse_label_statement();
-               } else if (is_typedef_symbol(token.symbol)) {
+               } else if (is_typedef_symbol(token.identifier.symbol)) {
                        statement = parse_declaration_statement();
                } else {
                        /* it's an identifier, the grammar says this must be an
@@ -9962,7 +9968,7 @@ static statement_t *intern_parse_statement(void)
                        switch (la1_type) {
                        case '&':
                        case '*':
-                               if (get_entity(token.symbol, NAMESPACE_NORMAL) != NULL) {
+                               if (get_entity(token.identifier.symbol, NAMESPACE_NORMAL) != NULL) {
                        default:
                                        statement = parse_expression_statement();
                                } else {
@@ -10152,8 +10158,8 @@ static statement_t *parse_compound_statement(bool inside_expression_statement)
 
        statement_t **anchor            = &statement->compound.statements;
        bool          only_decls_so_far = true;
-       while (token.type != '}') {
-               if (token.type == T_EOF) {
+       while (token.kind != '}') {
+               if (token.kind == T_EOF) {
                        errorf(&statement->base.source_position,
                               "EOF while parsing compound statement");
                        break;
@@ -10382,9 +10388,9 @@ end_error:
 
 static void parse_external(void)
 {
-       switch (token.type) {
+       switch (token.kind) {
                case T_extern:
-                       if (look_ahead(1)->type == T_STRING_LITERAL) {
+                       if (look_ahead(1)->kind == T_STRING_LITERAL) {
                                parse_linkage_specification();
                        } else {
                DECLARATION_START_NO_EXTERN
@@ -10419,8 +10425,8 @@ static void parse_external(void)
 
                default:
                        errorf(HERE, "stray %K outside of function", &token);
-                       if (token.type == '(' || token.type == '{' || token.type == '[')
-                               eat_until_matching_token(token.type);
+                       if (token.kind == '(' || token.kind == '{' || token.kind == '[')
+                               eat_until_matching_token(token.kind);
                        next_token();
                        return;
        }
@@ -10437,7 +10443,7 @@ static void parse_externals(void)
        memcpy(token_anchor_copy, token_anchor_set, sizeof(token_anchor_copy));
 #endif
 
-       while (token.type != T_EOF && token.type != '}') {
+       while (token.kind != T_EOF && token.kind != '}') {
 #ifndef NDEBUG
                for (int i = 0; i < T_LAST_TOKEN; ++i) {
                        unsigned short count = token_anchor_set[i] - token_anchor_copy[i];
@@ -10469,12 +10475,12 @@ static void parse_translation_unit(void)
        while (true) {
                parse_externals();
 
-               if (token.type == T_EOF)
+               if (token.kind == T_EOF)
                        break;
 
                errorf(HERE, "stray %K outside of function", &token);
-               if (token.type == '(' || token.type == '{' || token.type == '[')
-                       eat_until_matching_token(token.type);
+               if (token.kind == '(' || token.kind == '{' || token.kind == '[')
+                       eat_until_matching_token(token.kind);
                next_token();
        }
 }
index 48825af..75b01d7 100644 (file)
@@ -100,7 +100,7 @@ static const char       *printed_input_name = NULL;
 static source_position_t expansion_pos;
 static pp_definition_t  *current_expansion  = NULL;
 static strset_t          stringset;
-static preprocessor_token_type_t last_token = TP_ERROR;
+static preprocessor_token_kind_t last_token = TP_ERROR;
 
 static searchpath_entry_t *searchpath;
 
@@ -188,7 +188,7 @@ static void pop_restore_input(void)
  */
 static void parse_error(const char *msg)
 {
-       errorf(&pp_token.source_position,  "%s", msg);
+       errorf(&pp_token.base.source_position,  "%s", msg);
 }
 
 static inline void next_real_char(void)
@@ -499,10 +499,10 @@ static void parse_string_literal(void)
 
                case EOF: {
                        source_position_t source_position;
-                       source_position.input_name = pp_token.source_position.input_name;
+                       source_position.input_name = pp_token.base.source_position.input_name;
                        source_position.lineno     = start_linenr;
                        errorf(&source_position, "string has no end");
-                       pp_token.type = TP_ERROR;
+                       pp_token.kind = TP_ERROR;
                        return;
                }
 
@@ -523,8 +523,8 @@ end_of_string:
        const size_t size   = (size_t)obstack_object_size(&symbol_obstack);
        char *const  string = obstack_finish(&symbol_obstack);
 
-       pp_token.type    = TP_STRING_LITERAL;
-       pp_token.literal = make_string(string, size);
+       pp_token.kind          = TP_STRING_LITERAL;
+       pp_token.string.string = make_string(string, size);
 }
 
 /**
@@ -533,8 +533,8 @@ end_of_string:
 static void parse_wide_string_literal(void)
 {
        parse_string_literal();
-       if (pp_token.type == TP_STRING_LITERAL)
-               pp_token.type = TP_WIDE_STRING_LITERAL;
+       if (pp_token.kind == TP_STRING_LITERAL)
+               pp_token.kind = TP_WIDE_STRING_LITERAL;
 }
 
 static void parse_wide_character_constant(void)
@@ -560,7 +560,7 @@ static void parse_wide_character_constant(void)
 
                case EOF:
                        parse_error("EOF while parsing character constant");
-                       pp_token.type = TP_ERROR;
+                       pp_token.kind = TP_ERROR;
                        return;
 
                default:
@@ -574,8 +574,8 @@ end_of_wide_char_constant:
        obstack_1grow(&symbol_obstack, '\0');
        size_t  size = (size_t) obstack_object_size(&symbol_obstack)-1;
        char   *string = obstack_finish(&symbol_obstack);
-       pp_token.type    = TP_WIDE_CHARACTER_CONSTANT;
-       pp_token.literal = make_string(string, size);
+       pp_token.kind          = TP_WIDE_CHARACTER_CONSTANT;
+       pp_token.string.string = make_string(string, size);
 
        if (size == 0) {
                parse_error("empty character constant");
@@ -603,10 +603,10 @@ static void parse_character_constant(void)
 
                case EOF: {
                        source_position_t source_position;
-                       source_position.input_name = pp_token.source_position.input_name;
+                       source_position.input_name = pp_token.base.source_position.input_name;
                        source_position.lineno     = start_linenr;
                        errorf(&source_position, "EOF while parsing character constant");
-                       pp_token.type = TP_ERROR;
+                       pp_token.kind = TP_ERROR;
                        return;
                }
 
@@ -623,12 +623,16 @@ static void parse_character_constant(void)
        }
 
 end_of_char_constant:;
-       const size_t      size   = (size_t)obstack_object_size(&symbol_obstack);
-       const char *const string = obstack_finish(&symbol_obstack);
+       obstack_1grow(&symbol_obstack, '\0');
+       const size_t size   = (size_t)obstack_object_size(&symbol_obstack);
+       char *const  string = obstack_finish(&symbol_obstack);
+
+       pp_token.kind          = TP_CHARACTER_CONSTANT;
+       pp_token.string.string = make_string(string, size);
 
-       pp_token.type          = TP_CHARACTER_CONSTANT;
-       pp_token.literal.begin = string;
-       pp_token.literal.size  = size;
+       if (size == 0) {
+               parse_error("empty character constant");
+       }
 }
 
 #define SYMBOL_CHARS_WITHOUT_E_P \
@@ -730,14 +734,14 @@ restart:
                goto restart;
        }
        pp_token = definition->token_list[definition->expand_pos];
-       pp_token.source_position = expansion_pos;
+       pp_token.base.source_position = expansion_pos;
        ++definition->expand_pos;
 
-       if (pp_token.type != TP_IDENTIFIER)
+       if (pp_token.kind != TP_IDENTIFIER)
                return;
 
        /* if it was an identifier then we might need to expand again */
-       pp_definition_t *symbol_definition = pp_token.symbol->pp_definition;
+       pp_definition_t *symbol_definition = pp_token.identifier.symbol->pp_definition;
        if (symbol_definition != NULL && !symbol_definition->is_expanding) {
                symbol_definition->parent_expansion = definition;
                symbol_definition->expand_pos       = 0;
@@ -793,7 +797,7 @@ static void skip_multiline_comment(void)
 
                case EOF: {
                        source_position_t source_position;
-                       source_position.input_name = pp_token.source_position.input_name;
+                       source_position.input_name = pp_token.base.source_position.input_name;
                        source_position.lineno     = start_linenr;
                        errorf(&source_position, "at end of file while looking for comment end");
                        return;
@@ -844,7 +848,7 @@ static void skip_whitespace(void)
 static void eat_pp(int type)
 {
        (void) type;
-       assert(pp_token.type == type);
+       assert(pp_token.kind == type);
        next_preprocessing_token();
 }
 
@@ -883,8 +887,8 @@ end_symbol:
 
        symbol_t *symbol = symbol_table_insert(string);
 
-       pp_token.type   = symbol->pp_ID;
-       pp_token.symbol = symbol;
+       pp_token.kind              = symbol->pp_ID;
+       pp_token.identifier.symbol = symbol;
 
        /* we can free the memory from symbol obstack if we already had an entry in
         * the symbol table */
@@ -929,9 +933,8 @@ end_number:
        size_t  size   = obstack_object_size(&symbol_obstack);
        char   *string = obstack_finish(&symbol_obstack);
 
-       pp_token.type          = TP_NUMBER;
-       pp_token.literal.begin = string;
-       pp_token.literal.size  = size;
+       pp_token.kind          = TP_NUMBER;
+       pp_token.number.number = make_string(string, size);
 }
 
 
@@ -943,7 +946,7 @@ end_number:
 #define MAYBE(ch, set_type)                                \
                                case ch:                                   \
                                        next_char();                           \
-                                       pp_token.type = set_type;              \
+                                       pp_token.kind = set_type;              \
                                        return;
 
 #define ELSE_CODE(code)                                    \
@@ -955,7 +958,7 @@ end_number:
 
 #define ELSE(set_type)                                     \
                ELSE_CODE(                                         \
-                       pp_token.type = set_type;                      \
+                       pp_token.kind = set_type;                      \
                )
 
 static void next_preprocessing_token(void)
@@ -968,7 +971,7 @@ static void next_preprocessing_token(void)
        info.at_line_begin  = false;
        info.had_whitespace = false;
 restart:
-       pp_token.source_position = input.position;
+       pp_token.base.source_position = input.position;
        switch (input.c) {
        case ' ':
        case '\t':
@@ -1022,7 +1025,7 @@ restart:
                                ELSE_CODE(
                                        put_back(input.c);
                                        input.c = '.';
-                                       pp_token.type = '.';
+                                       pp_token.kind = '.';
                                )
                ELSE('.')
        case '&':
@@ -1075,7 +1078,7 @@ restart:
                                                ELSE_CODE(
                                                        put_back(input.c);
                                                        input.c = '%';
-                                                       pp_token.type = '#';
+                                                       pp_token.kind = '#';
                                                )
                                ELSE('#')
                ELSE('%')
@@ -1118,7 +1121,7 @@ restart:
                MAYBE_PROLOG
                MAYBE('#', TP_HASHHASH)
                ELSE_CODE(
-                       pp_token.type = '#';
+                       pp_token.kind = '#';
                )
 
        case '?':
@@ -1132,7 +1135,7 @@ restart:
        case ';':
        case ',':
        case '\\':
-               pp_token.type = input.c;
+               pp_token.kind = input.c;
                next_char();
                return;
 
@@ -1144,20 +1147,20 @@ restart:
                        print_line_directive(&input.position, "2");
                        goto restart;
                } else {
-                       pp_token.source_position.lineno++;
+                       pp_token.base.source_position.lineno++;
                        info.at_line_begin = true;
-                       pp_token.type = TP_EOF;
+                       pp_token.kind = TP_EOF;
                }
                return;
 
        default:
                next_char();
                if (!ignore_unknown_chars) {
-                       errorf(&pp_token.source_position, "unknown character '%c' found\n",
-                              input.c);
-                       pp_token.type = TP_ERROR;
+                       errorf(&pp_token.base.source_position,
+                              "unknown character '%c' found\n", input.c);
+                       pp_token.kind = TP_ERROR;
                } else {
-                       pp_token.type = input.c;
+                       pp_token.kind = input.c;
                }
                return;
        }
@@ -1205,18 +1208,18 @@ static void print_line_directive(const source_position_t *pos, const char *add)
 
 static void emit_newlines(void)
 {
-       unsigned delta = pp_token.source_position.lineno - input.output_line;
+       unsigned delta = pp_token.base.source_position.lineno - input.output_line;
 
        if (delta >= 9) {
                fputc('\n', out);
-               print_line_directive(&pp_token.source_position, NULL);
+               print_line_directive(&pp_token.base.source_position, NULL);
                fputc('\n', out);
        } else {
                for (unsigned i = 0; i < delta; ++i) {
                        fputc('\n', out);
                }
        }
-       input.output_line = pp_token.source_position.lineno;
+       input.output_line = pp_token.base.source_position.lineno;
 }
 
 static void emit_pp_token(void)
@@ -1231,36 +1234,36 @@ static void emit_pp_token(void)
                        fputc(' ', out);
 
        } else if (info.had_whitespace ||
-                          tokens_would_paste(last_token, pp_token.type)) {
+                          tokens_would_paste(last_token, pp_token.kind)) {
                fputc(' ', out);
        }
 
-       switch (pp_token.type) {
+       switch (pp_token.kind) {
        case TP_IDENTIFIER:
-               fputs(pp_token.symbol->string, out);
+               fputs(pp_token.identifier.symbol->string, out);
                break;
        case TP_NUMBER:
-               fputs(pp_token.literal.begin, out);
+               fputs(pp_token.number.number.begin, out);
                break;
        case TP_WIDE_STRING_LITERAL:
                fputc('L', out);
        case TP_STRING_LITERAL:
                fputc('"', out);
-               fputs(pp_token.literal.begin, out);
+               fputs(pp_token.string.string.begin, out);
                fputc('"', out);
                break;
        case TP_WIDE_CHARACTER_CONSTANT:
                fputc('L', out);
        case TP_CHARACTER_CONSTANT:
                fputc('\'', out);
-               fputs(pp_token.literal.begin, out);
+               fputs(pp_token.string.string.begin, out);
                fputc('\'', out);
                break;
        default:
-               print_pp_token_type(out, pp_token.type);
+               print_pp_token_kind(out, pp_token.kind);
                break;
        }
-       last_token = pp_token.type;
+       last_token = pp_token.kind;
 }
 
 static void eat_pp_directive(void)
@@ -1287,19 +1290,16 @@ static bool strings_equal(const string_t *string1, const string_t *string2)
 
 static bool pp_tokens_equal(const token_t *token1, const token_t *token2)
 {
-       if (token1->type != token2->type)
+       if (token1->kind != token2->kind)
                return false;
 
-       switch (token1->type) {
-       case TP_HEADERNAME:
-               /* TODO */
-               return false;
+       switch (token1->kind) {
        case TP_IDENTIFIER:
-               return token1->symbol == token2->symbol;
+               return token1->identifier.symbol == token2->identifier.symbol;
        case TP_NUMBER:
        case TP_CHARACTER_CONSTANT:
        case TP_STRING_LITERAL:
-               return strings_equal(&token1->literal, &token2->literal);
+               return strings_equal(&token1->string.string, &token2->string.string);
 
        default:
                return true;
@@ -1327,12 +1327,12 @@ static void parse_define_directive(void)
        eat_pp(TP_define);
        assert(obstack_object_size(&pp_obstack) == 0);
 
-       if (pp_token.type != TP_IDENTIFIER || info.at_line_begin) {
-               errorf(&pp_token.source_position,
+       if (pp_token.kind != TP_IDENTIFIER || info.at_line_begin) {
+               errorf(&pp_token.base.source_position,
                       "expected identifier after #define, got '%t'", &pp_token);
                goto error_out;
        }
-       symbol_t *symbol = pp_token.symbol;
+       symbol_t *symbol = pp_token.identifier.symbol;
 
        pp_definition_t *new_definition
                = obstack_alloc(&pp_obstack, sizeof(new_definition[0]));
@@ -1349,27 +1349,27 @@ static void parse_define_directive(void)
                next_preprocessing_token();
 
                while (true) {
-                       switch (pp_token.type) {
+                       switch (pp_token.kind) {
                        case TP_DOTDOTDOT:
                                new_definition->is_variadic = true;
                                next_preprocessing_token();
-                               if (pp_token.type != ')') {
+                               if (pp_token.kind != ')') {
                                        errorf(&input.position,
                                                        "'...' not at end of macro argument list");
                                        goto error_out;
                                }
                                break;
                        case TP_IDENTIFIER:
-                               obstack_ptr_grow(&pp_obstack, pp_token.symbol);
+                               obstack_ptr_grow(&pp_obstack, pp_token.identifier.symbol);
                                next_preprocessing_token();
 
-                               if (pp_token.type == ',') {
+                               if (pp_token.kind == ',') {
                                        next_preprocessing_token();
                                        break;
                                }
 
-                               if (pp_token.type != ')') {
-                                       errorf(&pp_token.source_position,
+                               if (pp_token.kind != ')') {
+                                       errorf(&pp_token.base.source_position,
                                               "expected ',' or ')' after identifier, got '%t'",
                                               &pp_token);
                                        goto error_out;
@@ -1379,7 +1379,7 @@ static void parse_define_directive(void)
                                next_preprocessing_token();
                                goto finish_argument_list;
                        default:
-                               errorf(&pp_token.source_position,
+                               errorf(&pp_token.base.source_position,
                                       "expected identifier, '...' or ')' in #define argument list, got '%t'",
                                       &pp_token);
                                goto error_out;
@@ -1433,14 +1433,14 @@ static void parse_undef_directive(void)
 {
        eat_pp(TP_undef);
 
-       if (pp_token.type != TP_IDENTIFIER) {
+       if (pp_token.kind != TP_IDENTIFIER) {
                errorf(&input.position,
                       "expected identifier after #undef, got '%t'", &pp_token);
                eat_pp_directive();
                return;
        }
 
-       symbol_t *symbol = pp_token.symbol;
+       symbol_t *symbol = pp_token.identifier.symbol;
        symbol->pp_definition = NULL;
        next_preprocessing_token();
 
@@ -1570,12 +1570,13 @@ static bool parse_include_directive(void)
        }
 
        if (!info.at_line_begin) {
-               warningf(WARN_OTHER, &pp_token.source_position, "extra tokens at end of #include directive");
+               warningf(WARN_OTHER, &pp_token.base.source_position,
+                        "extra tokens at end of #include directive");
                eat_pp_directive();
        }
 
        if (n_inputs > INCLUDE_LIMIT) {
-               errorf(&pp_token.source_position, "#include nested too deeply");
+               errorf(&pp_token.base.source_position, "#include nested too deeply");
                /* eat \n or EOF */
                next_preprocessing_token();
                return false;
@@ -1592,7 +1593,7 @@ static bool parse_include_directive(void)
        push_input();
        bool res = do_include(system_include, headername);
        if (!res) {
-               errorf(&pp_token.source_position,
+               errorf(&pp_token.base.source_position,
                       "failed including '%s': %s", headername, strerror(errno));
                pop_restore_input();
                return false;
@@ -1635,20 +1636,20 @@ static void check_unclosed_conditionals(void)
 
 static void parse_ifdef_ifndef_directive(void)
 {
-       bool is_ifndef = (pp_token.type == TP_ifndef);
+       bool is_ifndef = (pp_token.kind == TP_ifndef);
        bool condition;
        next_preprocessing_token();
 
        if (skip_mode) {
                eat_pp_directive();
                pp_conditional_t *conditional = push_conditional();
-               conditional->source_position  = pp_token.source_position;
+               conditional->source_position  = pp_token.base.source_position;
                conditional->skip             = true;
                return;
        }
 
-       if (pp_token.type != TP_IDENTIFIER || info.at_line_begin) {
-               errorf(&pp_token.source_position,
+       if (pp_token.kind != TP_IDENTIFIER || info.at_line_begin) {
+               errorf(&pp_token.base.source_position,
                       "expected identifier after #%s, got '%t'",
                       is_ifndef ? "ifndef" : "ifdef", &pp_token);
                eat_pp_directive();
@@ -1656,12 +1657,12 @@ static void parse_ifdef_ifndef_directive(void)
                /* just take the true case in the hope to avoid further errors */
                condition = true;
        } else {
-               symbol_t        *symbol        = pp_token.symbol;
+               symbol_t        *symbol        = pp_token.identifier.symbol;
                pp_definition_t *pp_definition = symbol->pp_definition;
                next_preprocessing_token();
 
                if (!info.at_line_begin) {
-                       errorf(&pp_token.source_position,
+                       errorf(&pp_token.base.source_position,
                               "extra tokens at end of #%s",
                               is_ifndef ? "ifndef" : "ifdef");
                        eat_pp_directive();
@@ -1672,7 +1673,7 @@ static void parse_ifdef_ifndef_directive(void)
        }
 
        pp_conditional_t *conditional = push_conditional();
-       conditional->source_position  = pp_token.source_position;
+       conditional->source_position  = pp_token.base.source_position;
        conditional->condition        = condition;
 
        if (!condition) {
@@ -1686,19 +1687,19 @@ static void parse_else_directive(void)
 
        if (!info.at_line_begin) {
                if (!skip_mode) {
-                       warningf(WARN_OTHER, &pp_token.source_position, "extra tokens at end of #else");
+                       warningf(WARN_OTHER, &pp_token.base.source_position, "extra tokens at end of #else");
                }
                eat_pp_directive();
        }
 
        pp_conditional_t *conditional = conditional_stack;
        if (conditional == NULL) {
-               errorf(&pp_token.source_position, "#else without prior #if");
+               errorf(&pp_token.base.source_position, "#else without prior #if");
                return;
        }
 
        if (conditional->in_else) {
-               errorf(&pp_token.source_position,
+               errorf(&pp_token.base.source_position,
                       "#else after #else (condition started %P)",
                       conditional->source_position);
                skip_mode = true;
@@ -1709,7 +1710,7 @@ static void parse_else_directive(void)
        if (!conditional->skip) {
                skip_mode = conditional->condition;
        }
-       conditional->source_position = pp_token.source_position;
+       conditional->source_position = pp_token.base.source_position;
 }
 
 static void parse_endif_directive(void)
@@ -1718,14 +1719,14 @@ static void parse_endif_directive(void)
 
        if (!info.at_line_begin) {
                if (!skip_mode) {
-                       warningf(WARN_OTHER, &pp_token.source_position, "extra tokens at end of #endif");
+                       warningf(WARN_OTHER, &pp_token.base.source_position, "extra tokens at end of #endif");
                }
                eat_pp_directive();
        }
 
        pp_conditional_t *conditional = conditional_stack;
        if (conditional == NULL) {
-               errorf(&pp_token.source_position, "#endif without prior #if");
+               errorf(&pp_token.base.source_position, "#endif without prior #if");
                return;
        }
 
@@ -1741,7 +1742,7 @@ static void parse_preprocessing_directive(void)
        eat_pp('#');
 
        if (skip_mode) {
-               switch (pp_token.type) {
+               switch (pp_token.kind) {
                case TP_ifdef:
                case TP_ifndef:
                        parse_ifdef_ifndef_directive();
@@ -1757,7 +1758,7 @@ static void parse_preprocessing_directive(void)
                        break;
                }
        } else {
-               switch (pp_token.type) {
+               switch (pp_token.kind) {
                case TP_define:
                        parse_define_directive();
                        break;
@@ -1782,7 +1783,7 @@ static void parse_preprocessing_directive(void)
                                /* the nop directive "#" */
                                break;
                        }
-                       errorf(&pp_token.source_position,
+                       errorf(&pp_token.base.source_position,
                                   "invalid preprocessing directive #%t", &pp_token);
                        eat_pp_directive();
                        break;
@@ -1887,35 +1888,35 @@ int pptest_main(int argc, char **argv)
        switch_input(file, filename);
 
        while (true) {
-               if (pp_token.type == '#' && info.at_line_begin) {
+               if (pp_token.kind == '#' && info.at_line_begin) {
                        parse_preprocessing_directive();
                        continue;
-               } else if (pp_token.type == TP_EOF) {
+               } else if (pp_token.kind == TP_EOF) {
                        goto end_of_main_loop;
-               } else if (pp_token.type == TP_IDENTIFIER && !in_pp_directive) {
-                       symbol_t *symbol = pp_token.symbol;
+               } else if (pp_token.kind == TP_IDENTIFIER && !in_pp_directive) {
+                       symbol_t *symbol = pp_token.identifier.symbol;
                        pp_definition_t *pp_definition = symbol->pp_definition;
                        if (pp_definition != NULL && !pp_definition->is_expanding) {
-                               expansion_pos = pp_token.source_position;
+                               expansion_pos = pp_token.base.source_position;
                                if (pp_definition->has_parameters) {
-                                       source_position_t position = pp_token.source_position;
+                                       source_position_t position = pp_token.base.source_position;
                                        add_token_info_t old_info = info;
                                        next_preprocessing_token();
                                        add_token_info_t new_info = info;
 
                                        /* no opening brace -> no expansion */
-                                       if (pp_token.type == '(') {
+                                       if (pp_token.kind == '(') {
                                                eat_pp('(');
 
                                                /* parse arguments (TODO) */
-                                               while (pp_token.type != TP_EOF && pp_token.type != ')')
+                                               while (pp_token.kind != TP_EOF && pp_token.kind != ')')
                                                        next_preprocessing_token();
                                        } else {
                                                token_t next_token = pp_token;
                                                /* restore identifier token */
-                                               pp_token.type            = TP_IDENTIFIER;
-                                               pp_token.symbol          = symbol;
-                                               pp_token.source_position = position;
+                                               pp_token.kind                 = TP_IDENTIFIER;
+                                               pp_token.identifier.symbol    = symbol;
+                                               pp_token.base.source_position = position;
                                                info = old_info;
                                                emit_pp_token();
 
diff --git a/token.c b/token.c
index 47806f1..183a0ca 100644 (file)
--- a/token.c
+++ b/token.c
@@ -36,7 +36,7 @@ const source_position_t builtin_source_position = { "<built-in>", 0, 0 };
 
 static int last_id;
 
-static symbol_t *intern_register_token(token_type_t id, const char *string)
+static symbol_t *intern_register_token(token_kind_t id, const char *string)
 {
        assert(0 <= id && id < T_LAST_TOKEN);
        symbol_t *symbol = symbol_table_insert(string);
@@ -45,7 +45,7 @@ static symbol_t *intern_register_token(token_type_t id, const char *string)
        return symbol;
 }
 
-static symbol_t *intern_register_pp_token(preprocessor_token_type_t id, const char *string)
+static symbol_t *intern_register_pp_token(preprocessor_token_kind_t id, const char *string)
 {
        assert(0 <= id && id < TP_LAST_TOKEN);
        symbol_t *symbol = symbol_table_insert(string);
@@ -54,7 +54,7 @@ static symbol_t *intern_register_pp_token(preprocessor_token_type_t id, const ch
        return symbol;
 }
 
-static void register_token(unsigned mode, token_type_t id, const char *string)
+static void register_token(unsigned mode, token_kind_t id, const char *string)
 {
        if (id > 255) {
                assert(id >= last_id);
@@ -66,7 +66,7 @@ static void register_token(unsigned mode, token_type_t id, const char *string)
        }
 }
 
-static void register_pp_token(unsigned mode, token_type_t id,
+static void register_pp_token(unsigned mode, token_kind_t id,
                               const char *string)
 {
        if (! (c_mode & mode))
@@ -100,38 +100,38 @@ void exit_tokens(void)
 {
 }
 
-void print_token_type(FILE *f, token_type_t token_type)
+void print_token_kind(FILE *f, token_kind_t token_kind)
 {
-       if(token_type == T_EOF) {
+       if(token_kind == T_EOF) {
                fputs("end of file", f);
                return;
        }
-       if(token_type == T_ERROR) {
+       if(token_kind == T_ERROR) {
                fputs("error", f);
                return;
        }
 
        int token_symbols_len = T_LAST_TOKEN;
-       if(token_type < 0 || token_type >= token_symbols_len) {
+       if(token_kind < 0 || token_kind >= token_symbols_len) {
                fputs("invalid token", f);
                return;
        }
 
-       const symbol_t *symbol = token_symbols[token_type];
+       const symbol_t *symbol = token_symbols[token_kind];
        if(symbol != NULL) {
                fputs(symbol->string, f);
        } else {
-               if(token_type >= 0 && token_type < 256) {
-                       fputc(token_type, f);
+               if(token_kind >= 0 && token_kind < 256) {
+                       fputc(token_kind, f);
                        return;
                }
                fputs("unknown token", f);
        }
 }
 
-symbol_t *get_token_symbol(const token_t *token)
+symbol_t *get_token_kind_symbol(int kind)
 {
-       return token_symbols[token->type];
+       return token_symbols[kind];
 }
 
 static void print_stringrep(const string_t *string, FILE *f)
@@ -143,65 +143,65 @@ static void print_stringrep(const string_t *string, FILE *f)
 
 void print_token(FILE *f, const token_t *token)
 {
-       switch(token->type) {
+       switch(token->kind) {
        case T_IDENTIFIER:
-               fprintf(f, "identifier '%s'", token->symbol->string);
+               fprintf(f, "identifier '%s'", token->identifier.symbol->string);
                break;
        case T_INTEGER:
        case T_INTEGER_OCTAL:
        case T_INTEGER_HEXADECIMAL:
        case T_FLOATINGPOINT:
        case T_FLOATINGPOINT_HEXADECIMAL:
-               print_token_type(f, (token_type_t)token->type);
+               print_token_kind(f, (token_kind_t)token->kind);
                fputs(" '", f);
-               print_stringrep(&token->literal, f);
-               if (token->symbol != NULL)
-                       fputs(token->symbol->string, f);
+               print_stringrep(&token->number.number, f);
+               if (token->number.suffix.size > 0)
+                       print_stringrep(&token->number.suffix, f);
                fputc('\'', f);
                break;
        case T_WIDE_STRING_LITERAL:
        case T_STRING_LITERAL:
-               print_token_type(f, (token_type_t)token->type);
-               fprintf(f, " \"%s\"", token->literal.begin);
+               print_token_kind(f, (token_kind_t)token->kind);
+               fprintf(f, " \"%s\"", token->string.string.begin);
                break;
        case T_CHARACTER_CONSTANT:
        case T_WIDE_CHARACTER_CONSTANT:
-               print_token_type(f, (token_type_t)token->type);
+               print_token_kind(f, (token_kind_t)token->kind);
                fputs(" \'", f);
-               print_stringrep(&token->literal, f);
+               print_stringrep(&token->string.string, f);
                fputs("'", f);
                break;
        default:
                fputc('\'', f);
-               print_token_type(f, (token_type_t)token->type);
+               print_token_kind(f, (token_kind_t)token->kind);
                fputc('\'', f);
                break;
        }
 }
 
-void print_pp_token_type(FILE *f, int token_type)
+void print_pp_token_kind(FILE *f, int token_kind)
 {
-       if (token_type == TP_EOF) {
+       if (token_kind == TP_EOF) {
                fputs("end of file", f);
                return;
        }
-       if (token_type == TP_ERROR) {
+       if (token_kind == TP_ERROR) {
                fputs("error", f);
                return;
        }
 
        int token_symbols_len = TP_LAST_TOKEN;
-       if (token_type < 0 || token_type >= token_symbols_len) {
+       if (token_kind < 0 || token_kind >= token_symbols_len) {
                fputs("invalid token", f);
                return;
        }
 
-       const symbol_t *symbol = pp_token_symbols[token_type];
+       const symbol_t *symbol = pp_token_symbols[token_kind];
        if (symbol != NULL) {
                fputs(symbol->string, f);
        } else {
-               if(token_type >= 0 && token_type < 256) {
-                       fputc(token_type, f);
+               if(token_kind >= 0 && token_kind < 256) {
+                       fputc(token_kind, f);
                        return;
                }
                fputs("unknown token", f);
@@ -210,24 +210,24 @@ void print_pp_token_type(FILE *f, int token_type)
 
 void print_pp_token(FILE *f, const token_t *token)
 {
-       switch((preprocessor_token_type_t) token->type) {
+       switch((preprocessor_token_kind_t) token->kind) {
        case TP_IDENTIFIER:
-               fprintf(f, "identifier '%s'", token->symbol->string);
+               fprintf(f, "identifier '%s'", token->identifier.symbol->string);
                break;
        case TP_NUMBER:
-               fprintf(f, "number '%s'", token->literal.begin);
+               fprintf(f, "number '%s'", token->number.number.begin);
                break;
        case TP_STRING_LITERAL:
-               fprintf(f, "string \"%s\"", token->literal.begin);
+               fprintf(f, "string \"%s\"", token->string.string.begin);
                break;
        default:
-               print_pp_token_type(f, (preprocessor_token_type_t) token->type);
+               print_pp_token_kind(f, (preprocessor_token_kind_t) token->kind);
                break;
        }
 }
 
-bool tokens_would_paste(preprocessor_token_type_t token1,
-                        preprocessor_token_type_t token2)
+bool tokens_would_paste(preprocessor_token_kind_t token1,
+                        preprocessor_token_kind_t token2)
 {
        char c = token2 < 256 ? (char) token2 : pp_token_symbols[token2]->string[0];
 
index 0f1697d..2f2918d 100644 (file)
--- a/token_t.h
+++ b/token_t.h
@@ -26,7 +26,7 @@
 #include "symbol_table.h"
 #include "type.h"
 
-typedef enum token_type_t {
+typedef enum token_kind_t {
        T_ERROR = -1,
        T_NULL  =  0,
        T_EOF   = '\x04', // EOT
@@ -36,9 +36,9 @@ typedef enum token_type_t {
 #undef TS
 #undef T
        T_LAST_TOKEN
-} token_type_t;
+} token_kind_t;
 
-typedef enum preprocessor_token_type_t {
+typedef enum preprocessor_token_kind_t {
        TP_NULL  = T_NULL,
        TP_EOF   = T_EOF,
        TP_ERROR = T_ERROR,
@@ -48,7 +48,7 @@ typedef enum preprocessor_token_type_t {
 #undef TS
 #undef T
        TP_LAST_TOKEN
-} preprocessor_token_type_t;
+} preprocessor_token_kind_t;
 
 typedef struct source_position_t source_position_t;
 struct source_position_t {
@@ -60,28 +60,56 @@ struct source_position_t {
 /* position used for "builtin" declarations/types */
 extern const source_position_t builtin_source_position;
 
-typedef struct {
-       int                type;
-       symbol_t          *symbol;  /**< contains identifier. Contains number suffix for numbers */
-       string_t           literal; /**< string value/literal value */
-       source_position_t  source_position;
-} token_t;
+typedef struct token_base_t     token_base_t;
+typedef struct identifier_t     identifier_t;
+typedef struct string_literal_t string_literal_t;
+typedef struct number_literal_t number_literal_t;
+typedef union  token_t          token_t;
+
+struct token_base_t {
+       int               kind;
+       source_position_t source_position;
+};
+
+struct identifier_t {
+       token_base_t  base;
+       symbol_t     *symbol;
+};
+
+struct string_literal_t {
+       token_base_t  base;
+       string_t      string;
+};
+
+struct number_literal_t {
+       token_base_t  base;
+       string_t      number;
+       string_t      suffix;
+};
+
+union token_t {
+       int               kind;
+       token_base_t      base;
+       identifier_t      identifier;
+       string_literal_t  string;
+       number_literal_t  number;
+};
 
 void init_tokens(void);
 void exit_tokens(void);
-void print_token_type(FILE *out, token_type_t token_type);
+void print_token_kind(FILE *out, token_kind_t token_kind);
 void print_token(FILE *out, const token_t *token);
 
-symbol_t *get_token_symbol(const token_t *token);
+symbol_t *get_token_kind_symbol(int token_kind);
 
-void print_pp_token_type(FILE *out, int type);
+void print_pp_token_kind(FILE *out, int kind);
 void print_pp_token(FILE *out, const token_t *token);
 
 /**
  * returns true if pasting 2 preprocessing tokens next to each other
  * without a space in between would generate (an)other preprocessing token(s)
  */
-bool tokens_would_paste(preprocessor_token_type_t token1,
-                        preprocessor_token_type_t token2);
+bool tokens_would_paste(preprocessor_token_kind_t token1,
+                        preprocessor_token_kind_t token2);
 
 #endif
index acdc8aa..f5bfe3e 100644 (file)
@@ -2,8 +2,7 @@
 #define TS(x,str,val)
 #endif
 
-TS(HEADERNAME,              "header name", = 256)
-TS(IDENTIFIER,              "identifier",)
+TS(IDENTIFIER,              "identifier", = 256)
 TS(NUMBER,                  "number",)
 TS(CHARACTER_CONSTANT,      "character constant",)
 TS(WIDE_CHARACTER_CONSTANT, "character constant",)