2 * This file is part of cparser.
3 * Copyright (C) 2012 Matthias Braun <matze@braunis.de>
12 #include "lang_features.h"
13 #include "adt/array.h"
14 #include "adt/error.h"
16 #include "symbol_table.h"
18 symbol_t *token_symbols[T_LAST_TOKEN];
20 const position_t builtin_position = { "<built-in>", 0, 0, true };
22 static token_kind_t last_id;
24 static symbol_t *intern_register_token(token_kind_t id, const char *string)
26 assert(id < T_LAST_TOKEN);
27 symbol_t *symbol = symbol_table_insert(string);
28 if (token_symbols[id] == NULL)
29 token_symbols[id] = symbol;
33 static void register_token(unsigned mode, token_kind_t id, const char *string)
36 assert(id >= last_id);
40 symbol_t *symbol = intern_register_token(id, string);
45 static void register_pp_token(pp_token_kind_t const id, char const *const string)
47 assert(id < TP_LAST_TOKEN);
48 symbol_t *const symbol = symbol_table_insert(string);
52 void init_tokens(void)
54 static bool tokens_initialized = false;
55 if (tokens_initialized)
57 tokens_initialized = true;
59 memset(token_symbols, 0, T_LAST_TOKEN * sizeof(token_symbols[0]));
61 #define T(mode,x,str,val) register_token(mode, x, str);
65 #define T(token) register_pp_token(TP_##token, #token);
66 #include "tokens_preprocessor.inc"
70 void exit_tokens(void)
74 void print_token_kind(FILE *f, token_kind_t token_kind)
76 if (token_kind >= lengthof(token_symbols)) {
77 fputs("invalid token", f);
81 fputs(token_symbols[token_kind]->string, f);
84 char const *get_string_encoding_prefix(string_encoding_t const enc)
87 case STRING_ENCODING_CHAR: return "";
88 case STRING_ENCODING_CHAR16: return "u";
89 case STRING_ENCODING_CHAR32: return "U";
90 case STRING_ENCODING_UTF8: return "u8";
91 case STRING_ENCODING_WIDE: return "L";
93 panic("invalid string encoding");
96 void print_token(FILE *f, const token_t *token)
101 switch (token->kind) {
103 case T_MACRO_PARAMETER:
105 val = token->base.symbol->string;
108 case T_STRING_LITERAL:
111 case T_CHARACTER_CONSTANT:
112 enc = get_string_encoding_prefix(token->literal.string.encoding);
115 val = token->literal.string.begin;
119 char const *kind = (token->base.symbol ? token->base.symbol : token_symbols[token->kind])->string;
120 fprintf(f, "'%s'", kind);
124 fprintf(f, "%s %s%c%s%c", token_symbols[token->kind]->string, enc, delim, val, delim);
127 bool tokens_would_paste(token_kind_t token1, token_kind_t token2)
129 char const c = token_symbols[token2]->string[0];
132 case '>': return c == '>' || c == '=';
133 case '<': return c == '<' || c == '=' || c == '%' || c == ':';
134 case '+': return c == '+' || c == '=';
135 case '-': return c == '-' || c == '>';
136 case '/': return c == '/' || c == '=' || c == '*';
137 case '%': return c == ':' || c == '=' || c == '>';
138 case '&': return c == '&' || c == '=';
139 case '|': return c == '|' || c == '=';
140 case ':': return c == ':' || c == '>';
141 case '*': return c == '*' || c == '=';
142 case '.': return c == '.' || c == '%' || token2 == T_NUMBER;
143 case '#': return c == '#' || c == '%';
144 case T_GREATERGREATER: return c == '=';
145 case T_LESSLESS: return c == '=';
146 case '^': return c == '=';
147 case '!': return c == '=';
150 return token2 == T_CHARACTER_CONSTANT ||
151 token2 == T_IDENTIFIER ||
152 token2 == T_NUMBER ||
153 token2 == T_STRING_LITERAL; /* L */
156 return token2 == T_IDENTIFIER || token2 == T_NUMBER ||
157 token2 == '.' || token2 == '+' || token2 == '-';