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