source: trunk/src/tools/moc/util/generate_keywords.cpp@ 5

Last change on this file since 5 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

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