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 |
|
---|
46 | struct Keyword
|
---|
47 | {
|
---|
48 | const char *lexem;
|
---|
49 | const char *token;
|
---|
50 | };
|
---|
51 |
|
---|
52 | static 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 |
|
---|
107 | static 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 |
|
---|
265 | inline bool is_ident_start(char s)
|
---|
266 | {
|
---|
267 | return ((s >= 'a' && s <= 'z')
|
---|
268 | || (s >= 'A' && s <= 'Z')
|
---|
269 | || s == '_'
|
---|
270 | );
|
---|
271 | }
|
---|
272 |
|
---|
273 | inline 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 | }
|
---|
281 | struct 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 |
|
---|
306 | void 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 |
|
---|
336 | void 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 |
|
---|
349 | void 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 |
|
---|
459 | int 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 | }
|
---|