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