parser: Remove the unused attribute alignment from struct declaration_specifiers_t.
[cparser] / token.c
1 /*
2  * This file is part of cparser.
3  * Copyright (C) 2012 Matthias Braun <matze@braunis.de>
4  */
5 #include <config.h>
6
7 #include "token_t.h"
8 #include "symbol_t.h"
9
10 #include <assert.h>
11
12 #include "lang_features.h"
13 #include "adt/array.h"
14 #include "adt/error.h"
15 #include "adt/util.h"
16 #include "symbol_table.h"
17
18 symbol_t *token_symbols[T_LAST_TOKEN];
19
20 const position_t builtin_position = { "<built-in>", 0, 0, true };
21
22 static token_kind_t last_id;
23
24 static symbol_t *intern_register_token(token_kind_t id, const char *string)
25 {
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;
30         return symbol;
31 }
32
33 static void register_token(unsigned mode, token_kind_t id, const char *string)
34 {
35         if (id > 255) {
36                 assert(id >= last_id);
37                 last_id = id;
38         }
39         if (c_mode & mode) {
40                 symbol_t *symbol = intern_register_token(id, string);
41                 symbol->ID = id;
42         }
43 }
44
45 static void register_pp_token(pp_token_kind_t const id, char const *const string)
46 {
47         assert(id < TP_LAST_TOKEN);
48         symbol_t *const symbol = symbol_table_insert(string);
49         symbol->pp_ID = id;
50 }
51
52 void init_tokens(void)
53 {
54         static bool tokens_initialized = false;
55         if (tokens_initialized)
56                 return;
57         tokens_initialized = true;
58
59         memset(token_symbols, 0, T_LAST_TOKEN * sizeof(token_symbols[0]));
60
61 #define T(mode,x,str,val)  register_token(mode, x, str);
62 #include "tokens.inc"
63 #undef T
64
65 #define T(token) register_pp_token(TP_##token, #token);
66 #include "tokens_preprocessor.inc"
67 #undef T
68 }
69
70 void exit_tokens(void)
71 {
72 }
73
74 void print_token_kind(FILE *f, token_kind_t token_kind)
75 {
76         if (token_kind >= lengthof(token_symbols)) {
77                 fputs("invalid token", f);
78                 return;
79         }
80
81         fputs(token_symbols[token_kind]->string, f);
82 }
83
84 char const *get_string_encoding_prefix(string_encoding_t const enc)
85 {
86         switch (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";
92         }
93         panic("invalid string encoding");
94 }
95
96 void print_token(FILE *f, const token_t *token)
97 {
98         char        delim = '\'';
99         char const *enc   = "";
100         char const *val;
101         switch (token->kind) {
102         case T_IDENTIFIER:
103         case T_MACRO_PARAMETER:
104         case T_UNKNOWN_CHAR:
105                 val = token->base.symbol->string;
106                 break;
107
108         case T_STRING_LITERAL:
109                 delim = '"';
110                 /* FALLTHROUGH */
111         case T_CHARACTER_CONSTANT:
112                 enc = get_string_encoding_prefix(token->literal.string.encoding);
113                 /* FALLTHROUGH */
114         case T_NUMBER:
115                 val = token->literal.string.begin;
116                 break;
117
118         default: {
119                 char const *kind  = (token->base.symbol ? token->base.symbol : token_symbols[token->kind])->string;
120                 fprintf(f, "'%s'", kind);
121                 return;
122         }
123         }
124         fprintf(f, "%s %s%c%s%c", token_symbols[token->kind]->string, enc, delim, val, delim);
125 }
126
127 bool tokens_would_paste(token_kind_t token1, token_kind_t token2)
128 {
129         char const c = token_symbols[token2]->string[0];
130
131         switch (token1) {
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 == '=';
148
149         case T_IDENTIFIER:
150                 return token2 == T_CHARACTER_CONSTANT ||
151                        token2 == T_IDENTIFIER         ||
152                        token2 == T_NUMBER             ||
153                        token2 == T_STRING_LITERAL; /* L */
154
155         case T_NUMBER:
156                 return token2 == T_IDENTIFIER || token2 == T_NUMBER ||
157                        token2 == '.' || token2 == '+' || token2 == '-';
158
159         default:
160                 return false;
161         }
162 }