2 * This file is part of cparser.
3 * Copyright (C) 2012 Matthias Braun <matze@braunis.de>
15 #include "lang_features.h"
16 #include "adt/array.h"
17 #include "adt/error.h"
20 symbol_t *token_symbols[T_LAST_TOKEN];
22 const position_t builtin_position = { "<built-in>", 0, 0, true };
24 static token_kind_t last_id;
26 static symbol_t *intern_register_token(token_kind_t id, const char *string)
28 assert(id < T_LAST_TOKEN);
29 symbol_t *symbol = symbol_table_insert(string);
30 if (token_symbols[id] == NULL)
31 token_symbols[id] = symbol;
35 static void register_token(unsigned mode, token_kind_t id, const char *string)
38 assert(id >= last_id);
42 symbol_t *symbol = intern_register_token(id, string);
47 static void register_pp_token(pp_token_kind_t const id, char const *const string)
49 assert(id < TP_LAST_TOKEN);
50 symbol_t *const symbol = symbol_table_insert(string);
54 void init_tokens(void)
56 static bool tokens_initialized = false;
57 if (tokens_initialized)
59 tokens_initialized = true;
61 memset(token_symbols, 0, T_LAST_TOKEN * sizeof(token_symbols[0]));
63 #define T(mode,x,str,val) register_token(mode, x, str);
67 #define T(token) register_pp_token(TP_##token, #token);
68 #include "tokens_preprocessor.inc"
72 void exit_tokens(void)
76 void print_token_kind(FILE *f, token_kind_t token_kind)
78 if (token_kind >= lengthof(token_symbols)) {
79 fputs("invalid token", f);
83 fputs(token_symbols[token_kind]->string, f);
86 char const *get_string_encoding_prefix(string_encoding_t const enc)
89 case STRING_ENCODING_CHAR: return "";
90 case STRING_ENCODING_CHAR16: return "u";
91 case STRING_ENCODING_CHAR32: return "U";
92 case STRING_ENCODING_UTF8: return "u8";
93 case STRING_ENCODING_WIDE: return "L";
95 panic("invalid string encoding");
98 void print_token(FILE *f, const token_t *token)
101 char const *enc = "";
103 switch (token->kind) {
105 case T_MACRO_PARAMETER:
107 val = token->base.symbol->string;
110 case T_STRING_LITERAL:
113 case T_CHARACTER_CONSTANT:
114 enc = get_string_encoding_prefix(token->literal.string.encoding);
117 val = token->literal.string.begin;
121 char const *kind = (token->base.symbol ? token->base.symbol : token_symbols[token->kind])->string;
122 fprintf(f, "'%s'", kind);
126 fprintf(f, "%s %s%c%s%c", token_symbols[token->kind]->string, enc, delim, val, delim);
129 bool tokens_would_paste(token_kind_t token1, token_kind_t token2)
131 char const c = token_symbols[token2]->string[0];
134 case '>': return c == '>' || c == '=';
135 case '<': return c == '<' || c == '=' || c == '%' || c == ':';
136 case '+': return c == '+' || c == '=';
137 case '-': return c == '-' || c == '>';
138 case '/': return c == '/' || c == '=' || c == '*';
139 case '%': return c == ':' || c == '=' || c == '>';
140 case '&': return c == '&' || c == '=';
141 case '|': return c == '|' || c == '=';
142 case ':': return c == ':' || c == '>';
143 case '*': return c == '*' || c == '=';
144 case '.': return c == '.' || c == '%' || token2 == T_NUMBER;
145 case '#': return c == '#' || c == '%';
146 case T_GREATERGREATER: return c == '=';
147 case T_LESSLESS: return c == '=';
148 case '^': return c == '=';
149 case '!': return c == '=';
152 return token2 == T_CHARACTER_CONSTANT ||
153 token2 == T_IDENTIFIER ||
154 token2 == T_NUMBER ||
155 token2 == T_STRING_LITERAL; /* L */
158 return token2 == T_IDENTIFIER || token2 == T_NUMBER ||
159 token2 == '.' || token2 == '+' || token2 == '-';