allowArray allows parsing of array types. It is disabled when parsing a type for "new" expression allowGenericType is used in parsing of generic function declaration, it allows parts of types to be "generic" allowGenericBase is used for parsing of external generic type member function definitions so that a function can be applied to all generic type instances allowExtendedTypeof is used to allow e
| 394 | // instanceType is used when semi-instancing a generic function to resolve "generic" types to real types |
| 395 | // instanceFailure is a variable that signals if failure was during instancing, so we have to silent the error |
| 396 | bool ParseSelectType(Lexeme** str, bool allowArray, bool allowGenericType, bool allowGenericBase, bool allowExtendedTypeof, TypeInfo* instanceType, bool* instanceFailure) |
| 397 | { |
| 398 | // If instance type is passed, we must remove array and pointer qualifiers and strip function type of its arguments |
| 399 | TypeInfo *strippedType = instanceType; |
| 400 | if(instanceType) |
| 401 | { |
| 402 | assert(instanceFailure); |
| 403 | // remove array and pointer qualifiers |
| 404 | while(strippedType->refLevel || strippedType->arrLevel) |
| 405 | strippedType = strippedType->subType; |
| 406 | } |
| 407 | bool notType = false; |
| 408 | if((*str)->type == lex_typeof) |
| 409 | { |
| 410 | (*str)++; |
| 411 | if(!ParseLexem(str, lex_oparen)) |
| 412 | ThrowError((*str)->pos, "ERROR: typeof must be followed by '('"); |
| 413 | |
| 414 | unsigned nodeCount = CodeInfo::nodeList.size(); |
| 415 | Lexeme *curr = *str; |
| 416 | bool isType = ParseSelectType(str); |
| 417 | if(!isType || (*str)->type != lex_cparen) |
| 418 | { |
| 419 | // If ParseSelectType parser extended type expression that returned a number, remove that number |
| 420 | if(isType && CodeInfo::nodeList.size() == nodeCount + 1) |
| 421 | CodeInfo::nodeList.pop_back(); |
| 422 | *str = curr; |
| 423 | jmp_buf oldHandler; |
| 424 | memcpy(oldHandler, CodeInfo::errorHandler, sizeof(jmp_buf)); |
| 425 | if(!allowGenericType || !setjmp(CodeInfo::errorHandler)) // if allowGenericType is enabled, we will set error handler |
| 426 | { |
| 427 | if(!ParseVaribleSet(str)) |
| 428 | ThrowError((*str)->pos, "ERROR: expression not found after typeof("); |
| 429 | SetTypeOfLastNode(); |
| 430 | }else{ |
| 431 | // Node count shouldn't change while we did this |
| 432 | if(!FunctionGeneric(false) || nodeCount != CodeInfo::nodeList.size()) |
| 433 | { |
| 434 | memcpy(CodeInfo::errorHandler, oldHandler, sizeof(jmp_buf)); |
| 435 | longjmp(CodeInfo::errorHandler, 1); |
| 436 | } |
| 437 | SelectTypeByPointer(typeGeneric); |
| 438 | } |
| 439 | if(allowGenericType) |
| 440 | memcpy(CodeInfo::errorHandler, oldHandler, sizeof(jmp_buf)); |
| 441 | }else if(!GetSelectedType()){ |
| 442 | ThrowError((*str)->pos, "ERROR: cannot take typeid from auto type"); |
| 443 | }else{ |
| 444 | // If there was a node pushed during type selection because of extended typeof expressions, get its type |
| 445 | if(CodeInfo::nodeList.size() == nodeCount + 1) |
| 446 | SetTypeOfLastNode(); |
| 447 | } |
| 448 | if(!ParseLexem(str, lex_cparen)) |
| 449 | ThrowError((*str)->pos, "ERROR: ')' not found after expression in typeof"); |
| 450 | while(ParseTypeofExtended(str, notType)); |
| 451 | }else if((*str)->type == lex_auto){ |
| 452 | SelectTypeByPointer(NULL); |
| 453 | (*str)++; |
no test coverage detected