|
35 | 35 | #include "core/print_string.h"
|
36 | 36 | #include "gdscript_functions.h"
|
37 | 37 |
|
| 38 | +OAHashMap<String, int> *GDScriptTokenizer::token_hashtable = nullptr; |
| 39 | + |
38 | 40 | const char *GDScriptTokenizer::token_names[TK_MAX] = {
|
39 | 41 | "Empty",
|
40 | 42 | "Identifier",
|
@@ -235,6 +237,96 @@ static const _kws _keyword_list[] = {
|
235 | 237 | { GDScriptTokenizer::TK_ERROR, nullptr }
|
236 | 238 | };
|
237 | 239 |
|
| 240 | +// Prepare the hash table for parsing as a one off at startup. |
| 241 | +void GDScriptTokenizer::initialize() { |
| 242 | + token_hashtable = memnew((OAHashMap<String, int>)); |
| 243 | + |
| 244 | + token_hashtable->insert("null", 0); |
| 245 | + token_hashtable->insert("true", 1); |
| 246 | + token_hashtable->insert("false", 2); |
| 247 | + |
| 248 | + // _type_list |
| 249 | + int id = TOKEN_HASH_TABLE_TYPE_START; |
| 250 | + int idx = 0; |
| 251 | + while (_type_list[idx].text) { |
| 252 | + token_hashtable->insert(_type_list[idx].text, id++); |
| 253 | + idx++; |
| 254 | + } |
| 255 | + |
| 256 | + // built in funcs |
| 257 | + id = TOKEN_HASH_TABLE_BUILTIN_START; |
| 258 | + for (int j = 0; j < GDScriptFunctions::FUNC_MAX; j++) { |
| 259 | + token_hashtable->insert(GDScriptFunctions::get_func_name(GDScriptFunctions::Function(j)), id++); |
| 260 | + } |
| 261 | + |
| 262 | + // keywords |
| 263 | + id = TOKEN_HASH_TABLE_KEYWORD_START; |
| 264 | + idx = 0; |
| 265 | + while (_keyword_list[idx].text) { |
| 266 | + token_hashtable->insert(_keyword_list[idx].text, id++); |
| 267 | + idx++; |
| 268 | + } |
| 269 | +} |
| 270 | + |
| 271 | +void GDScriptTokenizer::terminate() { |
| 272 | + if (token_hashtable) { |
| 273 | + memdelete(token_hashtable); |
| 274 | + token_hashtable = nullptr; |
| 275 | + } |
| 276 | +} |
| 277 | + |
| 278 | +// return whether found |
| 279 | +bool GDScriptTokenizerText::_parse_identifier(const String &p_str) { |
| 280 | + // N.B. GDScriptTokenizer::initialize() must have been called before using this function, |
| 281 | + // else token_hashtable will be NULL. |
| 282 | + const int *found = token_hashtable->lookup_ptr(p_str); |
| 283 | + |
| 284 | + if (found) { |
| 285 | + int id = *found; |
| 286 | + if (id < TOKEN_HASH_TABLE_TYPE_START) { |
| 287 | + switch (id) { |
| 288 | + case 0: { |
| 289 | + _make_constant(Variant()); |
| 290 | + } break; |
| 291 | + case 1: { |
| 292 | + _make_constant(true); |
| 293 | + } break; |
| 294 | + case 2: { |
| 295 | + _make_constant(false); |
| 296 | + } break; |
| 297 | + default: { |
| 298 | + DEV_ASSERT(0); |
| 299 | + } break; |
| 300 | + } |
| 301 | + return true; |
| 302 | + } else { |
| 303 | + // type list |
| 304 | + if (id < TOKEN_HASH_TABLE_BUILTIN_START) { |
| 305 | + int idx = id - TOKEN_HASH_TABLE_TYPE_START; |
| 306 | + _make_type(_type_list[idx].type); |
| 307 | + return true; |
| 308 | + } |
| 309 | + |
| 310 | + // built in func |
| 311 | + if (id < TOKEN_HASH_TABLE_KEYWORD_START) { |
| 312 | + int idx = id - TOKEN_HASH_TABLE_BUILTIN_START; |
| 313 | + _make_built_in_func(GDScriptFunctions::Function(idx)); |
| 314 | + return true; |
| 315 | + } |
| 316 | + |
| 317 | + // keyword |
| 318 | + int idx = id - TOKEN_HASH_TABLE_KEYWORD_START; |
| 319 | + _make_token(_keyword_list[idx].token); |
| 320 | + return true; |
| 321 | + } |
| 322 | + |
| 323 | + return true; |
| 324 | + } |
| 325 | + |
| 326 | + // not found |
| 327 | + return false; |
| 328 | +} |
| 329 | + |
238 | 330 | const char *GDScriptTokenizer::get_token_name(Token p_token) {
|
239 | 331 | ERR_FAIL_INDEX_V(p_token, TK_MAX, "<error>");
|
240 | 332 | return token_names[p_token];
|
@@ -977,68 +1069,13 @@ void GDScriptTokenizerText::_advance() {
|
977 | 1069 | i++;
|
978 | 1070 | }
|
979 | 1071 |
|
980 |
| - bool identifier = false; |
981 |
| - |
982 |
| - if (str == "null") { |
983 |
| - _make_constant(Variant()); |
984 |
| - |
985 |
| - } else if (str == "true") { |
986 |
| - _make_constant(true); |
987 |
| - |
988 |
| - } else if (str == "false") { |
989 |
| - _make_constant(false); |
990 |
| - } else { |
991 |
| - bool found = false; |
992 |
| - |
993 |
| - { |
994 |
| - int idx = 0; |
995 |
| - |
996 |
| - while (_type_list[idx].text) { |
997 |
| - if (str == _type_list[idx].text) { |
998 |
| - _make_type(_type_list[idx].type); |
999 |
| - found = true; |
1000 |
| - break; |
1001 |
| - } |
1002 |
| - idx++; |
1003 |
| - } |
1004 |
| - } |
1005 |
| - |
1006 |
| - if (!found) { |
1007 |
| - //built in func? |
1008 |
| - |
1009 |
| - for (int j = 0; j < GDScriptFunctions::FUNC_MAX; j++) { |
1010 |
| - if (str == GDScriptFunctions::get_func_name(GDScriptFunctions::Function(j))) { |
1011 |
| - _make_built_in_func(GDScriptFunctions::Function(j)); |
1012 |
| - found = true; |
1013 |
| - break; |
1014 |
| - } |
1015 |
| - } |
1016 |
| - } |
1017 |
| - |
1018 |
| - if (!found) { |
1019 |
| - //keyword |
| 1072 | + // Detect preset keywords / functions using hashtable. |
| 1073 | + bool found = _parse_identifier(str); |
1020 | 1074 |
|
1021 |
| - int idx = 0; |
1022 |
| - found = false; |
1023 |
| - |
1024 |
| - while (_keyword_list[idx].text) { |
1025 |
| - if (str == _keyword_list[idx].text) { |
1026 |
| - _make_token(_keyword_list[idx].token); |
1027 |
| - found = true; |
1028 |
| - break; |
1029 |
| - } |
1030 |
| - idx++; |
1031 |
| - } |
1032 |
| - } |
1033 |
| - |
1034 |
| - if (!found) { |
1035 |
| - identifier = true; |
1036 |
| - } |
1037 |
| - } |
1038 |
| - |
1039 |
| - if (identifier) { |
| 1075 | + if (!found) { |
1040 | 1076 | _make_identifier(str);
|
1041 | 1077 | }
|
| 1078 | + |
1042 | 1079 | INCPOS(str.length());
|
1043 | 1080 | return;
|
1044 | 1081 | }
|
|
0 commit comments