/* parses declarations of the form * use Foo * use Foo\Bar\Class * use Foo\Bar\Class as FooBarClass * use function Foo\Bar\func * use function Foo\Bar\func as foobarfunc * use const Foo\Bar\CONST * use const Foo\Bar\CONST as FOOBARCONST * use Foo, Bar * use Foo, Bar as Baz * use Foo as Test, Bar as Baz * use Foo\{Bar, Baz as Child, Nested\Other, Even\More as Something} */ static boolean parseUse (tokenInfo *const token) { boolean readNext = FALSE; /* we can't know the use type, because class, interface and namespaces * aliases are the same, and the only difference is the referenced name's * type */ const char *refType = "unknown"; vString *refName = vStringNew (); tokenInfo *nameToken = newToken (); boolean grouped = FALSE; readToken (token); /* skip use keyword itself */ if (token->type == TOKEN_KEYWORD && (token->keyword == KEYWORD_function || token->keyword == KEYWORD_const)) { switch (token->keyword) { case KEYWORD_function: refType = PhpKinds[K_FUNCTION].name; break; case KEYWORD_const: refType = PhpKinds[K_DEFINE].name; break; default: break; /* silence compilers */ } readNext = TRUE; } if (readNext) readToken (token); readQualifiedName (token, refName, nameToken); grouped = readNext = (token->type == TOKEN_OPEN_CURLY); do { size_t refNamePrefixLength = grouped ? vStringLength (refName) : 0; /* if it's either not the first name in a comma-separated list, or we * are in a grouped alias and need to read the leaf name */ if (readNext) { readToken (token); readQualifiedName (token, refName, nameToken); } if (token->type == TOKEN_KEYWORD && token->keyword == KEYWORD_as) { readToken (token); copyToken (nameToken, token, TRUE); readToken (token); } if (nameToken->type == TOKEN_IDENTIFIER && PhpKinds[K_ALIAS].enabled) { tagEntryInfo entry; initPhpEntry (&entry, nameToken, K_ALIAS, ACCESS_UNDEFINED); entry.extensionFields.typeRef[0] = refType; entry.extensionFields.typeRef[1] = vStringValue (refName); makePhpTagEntry (&entry); } vStringTruncate (refName, refNamePrefixLength); readNext = TRUE; } while (token->type == TOKEN_COMMA); if (grouped && token->type == TOKEN_CLOSE_CURLY) readToken (token); vStringDelete (refName); deleteToken (nameToken); return (token->type == TOKEN_SEMICOLON); }
static void popScope (tokenInfo *const token, const tokenInfo *const parent) { vStringTruncate (token->scope, vStringLength (parent->scope)); token->scopeKind = parent->scopeKind; }