Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
generate_keywords.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 TheQt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3#include <stdio.h>
4#include <string.h>
5#include <qbytearray.h>
6#include <qlist.h>
7
8struct Keyword
9{
10 const char *lexem;
11 const char *token;
12};
13
14static const Keyword pp_keywords[] = {
15 { "<", "PP_LANGLE" },
16 { ">", "PP_RANGLE" },
17 { "(", "PP_LPAREN"},
18 { ")", "PP_RPAREN"},
19 { ",", "PP_COMMA"},
20 { "\n", "PP_NEWLINE"},
21 { "#define", "PP_DEFINE"},
22 { "#if", "PP_IF"},
23 { "#undef", "PP_UNDEF"},
24 { "#ifdef", "PP_IFDEF"},
25 { "#ifndef", "PP_IFNDEF"},
26 { "#elif", "PP_ELIF"},
27 { "#else", "PP_ELSE"},
28 { "#endif", "PP_ENDIF"},
29 { "#include", "PP_INCLUDE"},
30 { "#include_next", "PP_INCLUDE_NEXT"},
31 { "__has_include", "PP_HAS_INCLUDE"},
32 { "__has_include_next", "PP_HAS_INCLUDE_NEXT"},
33 { "defined", "PP_DEFINED"},
34 { "+", "PP_PLUS" },
35 { "-", "PP_MINUS" },
36 { "*", "PP_STAR" },
37 { "/", "PP_SLASH" },
38 { "%", "PP_PERCENT" },
39 { "^", "PP_HAT" },
40 { "&", "PP_AND" },
41 { "bitand", "PP_AND" },
42 { "|", "PP_OR" },
43 { "bitor", "PP_OR" },
44 { "~", "PP_TILDE" },
45 { "compl", "PP_TILDE" },
46 { "!", "PP_NOT" },
47 { "not", "PP_NOT" },
48 { "<<", "PP_LTLT" },
49 { ">>", "PP_GTGT" },
50 { "==", "PP_EQEQ" },
51 { "!=", "PP_NE" },
52 { "not_eq", "PP_NE" },
53 { "<=", "PP_LE" },
54 { ">=", "PP_GE" },
55 { "&&", "PP_ANDAND" },
56 { "||", "PP_OROR" },
57 { "?", "PP_QUESTION" },
58 { ":", "PP_COLON" },
59 { "##", "PP_HASHHASH"},
60 { "%:%:", "PP_HASHHASH"},
61 { "#", "PP_HASH"},
62 { "\"", "PP_QUOTE"},
63 { "\'", "PP_SINGLEQUOTE"},
64 { " ", "PP_WHITESPACE" },
65 { "\t", "PP_WHITESPACE" },
66 { "//", "PP_CPP_COMMENT" },
67 { "/*", "PP_C_COMMENT" },
68 { "\\", "PP_BACKSLASH" },
69 { 0, "PP_NOTOKEN"}
70};
71
72static const Keyword keywords[] = {
73 { "<", "LANGLE" },
74 { ">", "RANGLE" },
75 { "(", "LPAREN" },
76 { ")", "RPAREN" },
77 { "...", "ELIPSIS" },
78 { ",", "COMMA" },
79 { "[", "LBRACK" },
80 { "]", "RBRACK" },
81 { "<:", "LBRACK" },
82 { ":>", "RBRACK" },
83 { "<::", "LANGLE_SCOPE" },
84 { "{", "LBRACE" },
85 { "<%", "LBRACE" },
86 { "}", "RBRACE" },
87 { "%>", "RBRACE" },
88 { "=", "EQ" },
89 { "::", "SCOPE" },
90 { ";", "SEMIC" },
91 { ":", "COLON" },
92 { ".*", "DOTSTAR" },
93 { "?", "QUESTION" },
94 { ".", "DOT" },
95 { "dynamic_cast", "DYNAMIC_CAST" },
96 { "static_cast", "STATIC_CAST" },
97 { "reinterpret_cast", "REINTERPRET_CAST" },
98 { "const_cast", "CONST_CAST" },
99 { "typeid", "TYPEID" },
100 { "this", "THIS" },
101 { "template", "TEMPLATE" },
102 { "throw", "THROW" },
103 { "try", "TRY" },
104 { "catch", "CATCH" },
105 { "typedef", "TYPEDEF" },
106 { "friend", "FRIEND" },
107 { "class", "CLASS" },
108 { "namespace", "NAMESPACE" },
109 { "enum", "ENUM" },
110 { "struct", "STRUCT" },
111 { "union", "UNION" },
112 { "virtual", "VIRTUAL" },
113 { "private", "PRIVATE" },
114 { "protected", "PROTECTED" },
115 { "public", "PUBLIC" },
116 { "export", "EXPORT" },
117 { "auto", "AUTO" },
118 { "register", "REGISTER" },
119 { "extern", "EXTERN" },
120 { "mutable", "MUTABLE" },
121 { "asm", "ASM" },
122 { "using", "USING" },
123 { "inline", "INLINE" },
124 { "explicit", "EXPLICIT" },
125 { "static", "STATIC" },
126 { "const", "CONST" },
127 { "constexpr", "CONSTEXPR" },
128 { "volatile", "VOLATILE" },
129 { "operator", "OPERATOR" },
130 { "sizeof", "SIZEOF" },
131 { "new", "NEW" },
132 { "delete", "DELETE" },
133 { "+", "PLUS" },
134 { "-", "MINUS" },
135 { "*", "STAR" },
136 { "/", "SLASH" },
137 { "%", "PERCENT" },
138 { "^", "HAT" },
139 { "&", "AND" },
140 { "bitand", "AND" },
141 { "|", "OR" },
142 { "bitor", "OR" },
143 { "~", "TILDE" },
144 { "compl", "TILDE" },
145 { "!", "NOT" },
146 { "not", "NOT" },
147 { "+=", "PLUS_EQ" },
148 { "-=", "MINUS_EQ" },
149 { "*=", "STAR_EQ" },
150 { "/=", "SLASH_EQ" },
151 { "%=", "PERCENT_EQ" },
152 { "^=", "HAT_EQ" },
153 { "&=", "AND_EQ" },
154 { "|=", "OR_EQ" },
155 { "<<", "LTLT" },
156 { ">>", "GTGT" },
157 { ">>=", "GTGT_EQ" },
158 { "<<=", "LTLT_EQ" },
159 { "==", "EQEQ" },
160 { "!=", "NE" },
161 { "not_eq", "NE" },
162 { "<=", "LE" },
163 { ">=", "GE" },
164 { "&&", "ANDAND" },
165 { "||", "OROR" },
166 { "++", "INCR" },
167 { "--", "DECR" },
168 { ",", "COMMA" },
169 { "->*", "ARROW_STAR" },
170 { "->", "ARROW" },
171 { "char", "CHAR" },
172 { "wchar", "WCHAR" },
173 { "bool", "BOOL" },
174 { "short", "SHORT" },
175 { "int", "INT" },
176 { "long", "LONG" },
177 { "signed", "SIGNED" },
178 { "unsigned", "UNSIGNED" },
179 { "float", "FLOAT" },
180 { "double", "DOUBLE" },
181 { "void", "VOID" },
182 { "case", "CASE" },
183 { "default", "DEFAULT" },
184 { "if", "IF" },
185 { "else", "ELSE" },
186 { "switch", "SWITCH" },
187 { "while", "WHILE" },
188 { "do", "DO" },
189 { "for", "FOR" },
190 { "break", "BREAK" },
191 { "continue", "CONTINUE" },
192 { "goto", "GOTO" },
193 { "return", "RETURN" },
194 { "Q_OBJECT", "Q_OBJECT_TOKEN" },
195 { "Q_NAMESPACE", "Q_NAMESPACE_TOKEN" },
196 { "Q_NAMESPACE_EXPORT", "Q_NAMESPACE_EXPORT_TOKEN" },
197 { "Q_GADGET", "Q_GADGET_TOKEN" },
198 { "Q_GADGET_EXPORT", "Q_GADGET_EXPORT_TOKEN" },
199 { "Q_PROPERTY", "Q_PROPERTY_TOKEN" },
200 { "QT_ANONYMOUS_PROPERTY", "QT_ANONYMOUS_PROPERTY_TOKEN" },
201 { "Q_PLUGIN_METADATA", "Q_PLUGIN_METADATA_TOKEN" },
202 { "Q_ENUMS", "Q_ENUMS_TOKEN" },
203 { "Q_ENUM", "Q_ENUM_TOKEN" },
204 { "Q_ENUM_NS", "Q_ENUM_NS_TOKEN" },
205 { "Q_FLAGS", "Q_FLAGS_TOKEN" },
206 { "Q_FLAG", "Q_FLAG_TOKEN" },
207 { "Q_FLAG_NS", "Q_FLAG_NS_TOKEN" },
208 { "Q_DECLARE_FLAGS", "Q_DECLARE_FLAGS_TOKEN" },
209 { "Q_DECLARE_INTERFACE", "Q_DECLARE_INTERFACE_TOKEN" },
210 { "Q_DECLARE_METATYPE", "Q_DECLARE_METATYPE_TOKEN" },
211 { "Q_DECLARE_EXTENSION_INTERFACE", "Q_DECLARE_INTERFACE_TOKEN" },
212 { "Q_SETS", "Q_FLAGS_TOKEN" },
213 { "Q_CLASSINFO", "Q_CLASSINFO_TOKEN" },
214 { "Q_INTERFACES", "Q_INTERFACES_TOKEN" },
215 { "signals", "SIGNALS" },
216 { "slots", "SLOTS" },
217 { "Q_SIGNALS", "Q_SIGNALS_TOKEN" },
218 { "Q_SLOTS", "Q_SLOTS_TOKEN" },
219 { "Q_PRIVATE_SLOT", "Q_PRIVATE_SLOT_TOKEN" },
220 { "QT_MOC_COMPAT", "Q_MOC_COMPAT_TOKEN" },
221 { "Q_INVOKABLE", "Q_INVOKABLE_TOKEN" },
222 { "Q_SIGNAL", "Q_SIGNAL_TOKEN" },
223 { "Q_SLOT", "Q_SLOT_TOKEN" },
224 { "Q_SCRIPTABLE", "Q_SCRIPTABLE_TOKEN" },
225 { "Q_PRIVATE_PROPERTY", "Q_PRIVATE_PROPERTY_TOKEN" },
226 { "QT_ANONYMOUS_PRIVATE_PROPERTY", "QT_ANONYMOUS_PRIVATE_PROPERTY_TOKEN" },
227 { "Q_REVISION", "Q_REVISION_TOKEN" },
228 { "Q_MOC_INCLUDE", "Q_MOC_INCLUDE_TOKEN" },
229 { "\n", "NEWLINE" },
230 { "\"", "QUOTE" },
231 { "\'", "SINGLEQUOTE" },
232 { " ", "WHITESPACE" },
233 { "\t", "WHITESPACE" },
234 { "#", "HASH" },
235 { "##", "PP_HASHHASH" },
236 { "\\", "BACKSLASH" },
237 { "//", "CPP_COMMENT" },
238 { "/*", "C_COMMENT" },
239 { 0, "NOTOKEN"}
240};
241
242
243inline bool is_ident_start(char s)
244{
245 return ((s >= 'a' && s <= 'z')
246 || (s >= 'A' && s <= 'Z')
247 || s == '_' || s == '$'
248 );
249}
250
251inline bool is_ident_char(char s)
252{
253 return ((s >= 'a' && s <= 'z')
254 || (s >= 'A' && s <= 'Z')
255 || (s >= '0' && s <= '9')
256 || s == '_' || s == '$'
257 );
258}
259struct State
260{
261 State(const char* token):token(token), nextindex(0),
262 defchar(0), defnext(0), ident(0) {
263 memset( next, 0, sizeof(next));
264 }
266 int next[128];
268
271
272 const char *ident;
273
274 bool operator==(const State& o) const
275 {
276 return (token == o.token
277 && nextindex == o.nextindex
278 && defchar == o.defchar
279 && defnext == o.defnext
280 && ident == o.ident);
281 }
282};
283
284void newState(QList<State> &states, const char *token, const char *lexem, bool pre)
285{
286 const char *ident = nullptr;
287 if (is_ident_start(*lexem))
288 ident = pre?"PP_CHARACTER" : "CHARACTER";
289 else if (*lexem == '#')
290 ident = pre?"PP_HASH" : "HASH";
291
292 int state = 0;
293 while (*lexem) {
294 int next = states[state].next[(int)*lexem];
295 if (!next) {
296 const char *t = nullptr;
297 if (ident)
298 t = ident;
299 else
300 t = pre?"PP_INCOMPLETE":"INCOMPLETE";
301 next = states.size();
302 states += State(t);
303 states[state].next[(int)*lexem] = next;
304 states[next].ident = ident;
305 }
306 state = next;
307 ++lexem;
308 if (ident && !is_ident_char(*lexem))
309 ident = nullptr;
310 }
311 states[state].token = token;
312}
313
314void newState(QList<State> &states, const char *token, char lexem)
315{
316 int next = states[0].next[(int)lexem];
317 if (!next) {
318 next = states.size();
319 states += State(token);
320 states[0].next[(int)lexem] = next;
321 } else {
322 states[next].token = token;
323 }
324}
325
326
327void makeTable(const Keyword keywords[])
328{
329 int i,c;
330 bool pre = (keywords == pp_keywords);
331 QList<State> states;
332 states += State(pre?"PP_NOTOKEN":"NOTOKEN");
333
334 // identifiers
335 for (c = 'a'; c <= 'z'; ++c)
336 newState(states, pre?"PP_CHARACTER":"CHARACTER", c);
337 for (c = 'A'; c <= 'Z'; ++c)
338 newState(states, pre?"PP_CHARACTER":"CHARACTER", c);
339
340 newState(states, pre?"PP_CHARACTER":"CHARACTER", '_');
341 newState(states, pre?"PP_CHARACTER":"CHARACTER", '$');
342
343 // add digits
344 for (c = '0'; c <= '9'; ++c)
345 newState(states, pre?"PP_DIGIT":"DIGIT", c);
346
347 // keywords
348 for (i = 0; keywords[i].lexem; ++i)
349 newState(states, keywords[i].token, keywords[i].lexem, pre);
350
351 // some floats
352 for (c = '0'; c <= '9'; ++c)
353 newState(states, pre?"PP_FLOATING_LITERAL":"FLOATING_LITERAL",
354 QByteArray(".") + char(c), pre);
355
356 // simplify table with default transitions
357 int transindex = -1;
358 for (i = 0; i < states.size(); ++i) {
359 int n = 0;
360 int defchar = -1;
361 for (c = 0; c < 128; ++c)
362 if (states[i].next[c]) {
363 ++n;
364 defchar = c;
365 }
366 if (!n)
367 continue;
368 if (n == 1) {
369 states[i].defnext = states[i].next[defchar];
370 states[i].defchar = defchar;
371 continue;
372 }
373 states[i].nextindex = ++transindex;
374 }
375
376#if 1
377 // compress table
378 int j, k;
379 for (i = 0; i < states.size(); ++i) {
380 for (j = i + 1; j < states.size(); ++j) {
381 if ( states[i] == states[j] ) {
382 for (k = 0; k < states.size(); ++k) {
383 if (states[k].defnext == j)
384 states[k].defnext = i;
385 if (states[k].defnext > j)
386 --states[k].defnext;
387 for (c = 0; c < 128; ++c) {
388 if (states[k].next[c] == j)
389 states[k].next[c] = i;
390 if (states[k].next[c] > j)
391 --states[k].next[c];
392 }
393 }
394 states.removeAt(j);
395 --j;
396 }
397 }
398 }
399#endif
400 printf("static const short %skeyword_trans[][128] = {\n",
401 pre?"pp_":"");
402 for (i = 0; i < states.size(); ++i) {
403 if (i && !states[i].nextindex)
404 continue;
405 printf("%s {", i?",\n":"");
406 for (c = 0; c < 128; ++c)
407 printf("%s%s%d",
408 c?",":"",
409 (!c || c%16)?"":"\n ",
410 states[i].next[c]
411 );
412 printf("}");
413 }
414 printf("\n};\n\n");
415
416 printf("static const struct\n{\n"
417 " %sToken token;\n"
418 " short next;\n"
419 " char defchar;\n"
420 " short defnext;\n"
421 " %sToken ident;\n"
422 "} %skeywords[] = {\n",
423 pre ? "PP_":"",
424 pre ? "PP_":"",
425 pre ? "pp_":"");
426 for (i = 0; i < states.size(); ++i) {
427 printf("%s {%s, %d, %d, %d, %s}",
428 i?",\n":"",
429 states[i].token.data(),
430 states[i].nextindex,
431 states[i].defchar,
432 states[i].defnext,
433 states[i].ident?states[i].ident:(pre?"PP_NOTOKEN":"NOTOKEN"));
434 }
435 printf("\n};\n");
436}
437
438int main(int argc, char **)
439{
440 printf("// auto generated\n"
441 "// DO NOT EDIT.\n\n");
442 if ( argc > 1 )
444 else
446 return 0;
447}
Definition qlist.h:81
void newState(QList< State > &states, const char *token, char lexem)
static const Keyword keywords[]
void makeTable(const Keyword keywords[])
void newState(QList< State > &states, const char *token, const char *lexem, bool pre)
static const Keyword pp_keywords[]
bool is_ident_char(char s)
Definition utils.h:30
bool is_ident_start(char s)
Definition utils.h:24
int main(int argc, char *argv[])
[ctor_close]
State(const char *token)
int next[128]
bool operator==(const State &o) const
QByteArray token
const char * ident