static void parseType (tokenInfo *const token) { tokenInfo *const name = newToken (); readToken (name); if (isType (name, TOKEN_IDENTIFIER)) { readToken (token); if (isKeyword (token, KEYWORD_is)) { readToken (token); switch (token->keyword) { case KEYWORD_record: makeSqlTag (name, SQLTAG_RECORD); parseRecord (token); break; case KEYWORD_table: makeSqlTag (name, SQLTAG_TABLE); break; case KEYWORD_ref: readToken (token); if (isKeyword (token, KEYWORD_cursor)) makeSqlTag (name, SQLTAG_CURSOR); break; default: break; } } } deleteToken (name); }
static void parseModule (tokenInfo * const token) { tokenInfo *const name = newToken (); const vhdlKind kind = isKeyword (token, KEYWORD_ENTITY) ? VHDLTAG_ENTITY : VHDLTAG_COMPONENT; Assert (isKeyword (token, KEYWORD_ENTITY) || isKeyword (token, KEYWORD_COMPONENT)); readToken (name); if (kind == VHDLTAG_COMPONENT) { makeVhdlTag (name, VHDLTAG_COMPONENT); skipToKeyword (KEYWORD_END); fileSkipToCharacter (';'); } else { readToken (token); if (isKeyword (token, KEYWORD_IS)) { makeVhdlTag (name, VHDLTAG_ENTITY); skipToKeyword (KEYWORD_END); fileSkipToCharacter (';'); } } deleteToken (name); }
static void parseSubProgram (tokenInfo *const token) { tokenInfo *const name = newToken (); const sqlKind kind = isKeyword (token, KEYWORD_function) ? SQLTAG_FUNCTION : SQLTAG_PROCEDURE; Assert (isKeyword (token, KEYWORD_function) || isKeyword (token, KEYWORD_procedure)); readToken (name); readToken (token); skipArgumentList (token); if (isKeyword (token, KEYWORD_return)) { do readToken (token); /* read return type */ while (!(isKeyword (token, KEYWORD_is) || isType (token, TOKEN_SEMICOLON))); } if (isKeyword (token, KEYWORD_is)) { if (isType (name, TOKEN_IDENTIFIER)) makeSqlTag (name, kind); parseBlock (token, TRUE); } else if (isType (token, TOKEN_SEMICOLON)) makeSqlTag (name, SQLTAG_PROTOTYPE); deleteToken (name); }
static void parseTypes (tokenInfo * const token) { tokenInfo *const name = newToken (); const vhdlKind kind = isKeyword (token, KEYWORD_TYPE) ? VHDLTAG_TYPE : VHDLTAG_SUBTYPE; Assert (isKeyword (token, KEYWORD_TYPE) || isKeyword (token, KEYWORD_SUBTYPE)); readToken (name); readToken (token); if (isKeyword (token, KEYWORD_IS)) { readToken (token); /* type */ if (isKeyword (token, KEYWORD_RECORD)) { makeVhdlTag (name, kind); /*TODO: make tags of the record's names */ parseRecord (token); } else { makeVhdlTag (name, kind); } } deleteToken (name); }
/* parses declarations of the form * $var = VALUE */ static bool parseVariable (tokenInfo *const token) { tokenInfo *name; bool readNext = true; const char *access; name = newToken (); copyToken (name, token, true); readToken (token); if (token->type == TOKEN_EQUAL_SIGN) { if (token->parentKind != K_FUNCTION) { /* ignore local variables (i.e. within a function) */ access = parsePowerShellScope (name); makeSimplePowerShellTag (name, K_VARIABLE, access); readNext = true; } } else readNext = false; deleteToken (name); return readNext; }
static void findVhdlTags (void) { tokenInfo *const token = newToken (); while (parseVhdlFile (token) != TOKEN_EOF); deleteToken (token); }
static void findSqlTags (void) { tokenInfo *const token = newToken (); exception_t exception = (exception_t) (setjmp (Exception)); while (exception == ExceptionNone) parseSqlFile (token); deleteToken (token); }
static void findEiffelTags (void) { tokenInfo *const token = newToken (); while (findKeyword (token, KEYWORD_class)) parseClass (token); deleteToken (token); }
/* parses a class or an interface: * class Foo {} * class Foo extends Bar {} * class Foo extends Bar implements iFoo, iBar {} * interface iFoo {} * interface iBar extends iFoo {} * * if @name is not NULL, parses an anonymous class with name @name * new class {} * new class(1, 2) {} * new class(1, 2) extends Foo implements iFoo, iBar {} */ static boolean parseClassOrIface (tokenInfo *const token, const phpKind kind, const tokenInfo *name) { boolean readNext = TRUE; implType impl = CurrentStatement.impl; tokenInfo *nameFree = NULL; vString *inheritance = NULL; readToken (token); if (name) /* anonymous class */ { /* skip possible construction arguments */ skipOverParens (token); } else /* normal, named class */ { if (token->type != TOKEN_IDENTIFIER) return FALSE; name = nameFree = newToken (); copyToken (nameFree, token, TRUE); readToken (token); } inheritance = vStringNew (); /* read every identifiers, keywords and commas, and assume each * identifier (not keyword) is an inheritance * (like in "class Foo extends Bar implements iA, iB") */ while (token->type == TOKEN_IDENTIFIER || token->type == TOKEN_KEYWORD || token->type == TOKEN_COMMA) { if (token->type == TOKEN_IDENTIFIER) { if (vStringLength (inheritance) > 0) vStringPut (inheritance, ','); vStringCat (inheritance, token->string); } readToken (token); } makeClassOrIfaceTag (kind, name, inheritance, impl); if (token->type == TOKEN_OPEN_CURLY) enterScope (token, name->string, kind); else readNext = FALSE; if (nameFree) deleteToken (nameFree); vStringDelete (inheritance); return readNext; }
static void skipToKeyword (const keywordId keyword) { tokenInfo *const token = newToken (); do { readToken (token); } while (!isType (token, TOKEN_EOF) && !isKeyword (token, keyword)); deleteToken (token); }
static void findGoTags (void) { tokenInfo *const token = newToken (); parseGoFile (token); deleteToken (token); vStringDelete (scope); scope = NULL; }
static void parseFunctionOrMethod (tokenInfo *const token) { // FunctionDecl = "func" identifier Signature [ Body ] . // Body = Block. // // MethodDecl = "func" Receiver MethodName Signature [ Body ] . // Receiver = "(" [ identifier ] [ "*" ] BaseTypeName ")" . // BaseTypeName = identifier . // Skip over receiver. readToken (token); if (isType (token, TOKEN_OPEN_PAREN)) skipToMatched (token); if (isType (token, TOKEN_IDENTIFIER)) { vString *argList; tokenInfo *functionToken = copyToken (token); // Start recording signature signature = vStringNew (); // Skip over parameters. readToken (token); skipToMatchedNoRead (token); vStringStripLeading (signature); vStringStripTrailing (signature); argList = signature; signature = vStringNew (); readToken (token); // Skip over result. skipType (token); // Remove the extra { we have just read vStringStripTrailing (signature); vStringChop (signature); vStringStripLeading (signature); vStringStripTrailing (signature); makeTag (functionToken, GOTAG_FUNCTION, NULL, GOTAG_UNDEFINED, argList->buffer, signature->buffer); deleteToken (functionToken); vStringDelete(signature); vStringDelete(argList); // Stop recording signature signature = NULL; // Skip over function body. if (isType (token, TOKEN_OPEN_CURLY)) skipToMatched (token); } }
static tokenInfo *popToken (tokenInfo * const token) { tokenInfo *localToken; if (token != NULL) { localToken = token->scope; deleteToken (token); return localToken; } return NULL; }
static void findVerilogTags (void) { tokenInfo *const token = newToken (); int c = '\0'; currentContext = newToken (); while (c != EOF) { c = vGetc (); c = skipWhite (c); switch (c) { /* Store current block name whenever a : is found * This is used later by any tag type that requires this information * */ case ':': vStringCopy (currentContext->blockName, token->name); break; /* Skip interface modport port declarations */ case '(': if (currentContext && currentContext->lastKind == K_MODPORT) { skipPastMatch ("()"); } break; /* Drop context on prototypes because they don't have an end * statement */ case ';': if (currentContext->scope && currentContext->scope->prototype) { verbose ("Dropping context %s\n", vStringValue (currentContext->name)); currentContext = popToken (currentContext); currentContext->prototype = FALSE; } /* Prototypes end at the end of statement */ if (currentContext->prototype) { currentContext->prototype = FALSE; } break; default : if (isIdentifierCharacter (c)) { readIdentifier (token, c); updateKind (token); findTag (token); } } } deleteToken (token); pruneTokens (currentContext); currentContext = NULL; }
static void findPowerShellTags (void) { tokenInfo *const token = newToken (); do { enterScope (token, NULL, -1); } while (token->type != TOKEN_EOF); /* keep going even with unmatched braces */ deleteToken (token); }
static void findEiffelTags (void) { tokenInfo *const token = newToken (); exception_t exception; exception = (exception_t) (setjmp (Exception)); while (exception == ExceptionNone) { findKeyword (token, KEYWORD_class); parseClass (token); } deleteToken (token); }
/* parses declarations of the form * $var = VALUE * $var; */ static boolean parseVariable (tokenInfo *const token) { tokenInfo *name; boolean readNext = TRUE; accessType access = CurrentStatement.access; name = newToken (); copyToken (name, token, TRUE); readToken (token); if (token->type == TOKEN_EQUAL_SIGN) { phpKind kind = K_VARIABLE; if (token->parentKind == K_FUNCTION) kind = K_LOCAL_VARIABLE; readToken (token); if (token->type == TOKEN_KEYWORD && token->keyword == KEYWORD_function && PhpKinds[kind].enabled) { if (parseFunction (token, name)) readToken (token); readNext = (boolean) (token->type == TOKEN_SEMICOLON); } else { makeSimplePhpTag (name, kind, access); readNext = FALSE; } } else if (token->type == TOKEN_SEMICOLON) { /* generate tags for variable declarations in classes * class Foo { * protected $foo; * } * but don't get fooled by stuff like $foo = $bar; */ if (token->parentKind == K_CLASS || token->parentKind == K_INTERFACE || token->parentKind == K_TRAIT) makeSimplePhpTag (name, K_VARIABLE, access); } else readNext = FALSE; deleteToken (name); return readNext; }
static void parseConstant (boolean local) { tokenInfo *const name = newToken (); readToken (name); if (local) { makeVhdlTag (name, VHDLTAG_LOCAL); } else { makeVhdlTag (name, VHDLTAG_CONSTANT); } fileSkipToCharacter (';'); deleteToken (name); }
static void parseTable (tokenInfo *const token) { tokenInfo *const name = newToken (); readToken (name); readToken (token); if (isType (token, TOKEN_OPEN_PAREN)) { if (isType (name, TOKEN_IDENTIFIER)) { makeSqlTag (name, SQLTAG_TABLE); parseRecord (token); } } findToken (token, TOKEN_SEMICOLON); deleteToken (name); }
static void parsePackage (tokenInfo *const token) { tokenInfo *const name = newToken (); readToken (name); if (isKeyword (name, KEYWORD_body)) readToken (name); readToken (token); if (isKeyword (token, KEYWORD_is)) { if (isType (name, TOKEN_IDENTIFIER)) makeSqlTag (name, SQLTAG_PACKAGE); parseBlock (token, FALSE); } findToken (token, TOKEN_SEMICOLON); deleteToken (name); }
static void findJsonTags (void) { tokenInfo *const token = newToken (); /* We allow multiple top-level elements, although it's not actually valid * JSON. An interesting side effect of this is that we allow a leading * Unicode BOM mark -- even though ok, many JSON parsers will choke on it */ do { readToken (token); parseValue (token); } while (token->type != TOKEN_EOF); deleteToken (token); }
static void parseRecord (tokenInfo * const token) { tokenInfo *const name = newToken (); Assert (isKeyword (token, KEYWORD_RECORD)); readToken (name); do { readToken (token); /* should be a colon */ fileSkipToCharacter (';'); makeVhdlTag (name, VHDLTAG_RECORD); readToken (name); } while (!isKeyword (name, KEYWORD_END) && !isType (name, TOKEN_EOF)); fileSkipToCharacter (';'); deleteToken (name); }
static void parsePackage (tokenInfo * const token) { tokenInfo *const name = newToken (); Assert (isKeyword (token, KEYWORD_PACKAGE)); readToken (token); if (isKeyword (token, KEYWORD_BODY)) { readToken (name); makeVhdlTag (name, VHDLTAG_PACKAGE); } else if (isType (token, TOKEN_IDENTIFIER)) { makeVhdlTag (token, VHDLTAG_PACKAGE); } deleteToken (name); }
static void parseFunction (tokenInfo *const token) { tokenInfo *const name = newToken (); vString *const signature = vStringNew (); boolean is_class = FALSE; /* * This deals with these formats * function validFunctionTwo(a,b) {} */ readToken (name); if (!isType (name, TOKEN_IDENTIFIER)) goto cleanUp; /* Add scope in case this is an INNER function */ addToScope(name, token->scope); readToken (token); while (isType (token, TOKEN_PERIOD)) { readToken (token); if ( isKeyword(token, KEYWORD_NONE) ) { addContext (name, token); readToken (token); } } if ( isType (token, TOKEN_OPEN_PAREN) ) skipArgumentList(token, FALSE, signature); if ( isType (token, TOKEN_OPEN_CURLY) ) { is_class = parseBlock (token, name); if ( is_class ) makeClassTag (name, signature); else makeFunctionTag (name, signature); } findCmdTerm (token, FALSE, FALSE); cleanUp: vStringDelete (signature); deleteToken (name); }
static void enterScope (tokenInfo *const parentToken, const vString *const extraScope, const int parentKind) { tokenInfo *token = newToken (); int origParentKind = parentToken->parentKind; copyToken (token, parentToken, true); if (extraScope) { addToScope (token, extraScope); token->parentKind = parentKind; } readToken (token); while (token->type != TOKEN_EOF && token->type != TOKEN_CLOSE_CURLY) { bool readNext = true; switch (token->type) { case TOKEN_OPEN_CURLY: enterScope (token, NULL, -1); break; case TOKEN_KEYWORD: readNext = parseFunction (token); break; case TOKEN_VARIABLE: readNext = parseVariable (token); break; default: break; } if (readNext) readToken (token); } copyToken (parentToken, token, false); parentToken->parentKind = origParentKind; deleteToken (token); }
/* parses declarations of the form * const NAME = VALUE */ static boolean parseConstant (tokenInfo *const token) { tokenInfo *name; readToken (token); /* skip const keyword */ if (token->type != TOKEN_IDENTIFIER && token->type != TOKEN_KEYWORD) return FALSE; name = newToken (); copyToken (name, token, TRUE); readToken (token); if (token->type == TOKEN_EQUAL_SIGN) makeSimplePhpTag (name, K_DEFINE, ACCESS_UNDEFINED); deleteToken (name); return token->type == TOKEN_EQUAL_SIGN; }
static void parseTemplateString (vString *const string) { int c; do { c = fileGetc (); if (c == '`') break; vStringPut (string, c); if (c == '\\') { c = fileGetc(); vStringPut(string, c); } else if (c == '$') { c = fileGetc (); if (c != '{') fileUngetc (c); else { int depth = 1; /* we need to use the real token machinery to handle strings, * comments, regexes and whatnot */ tokenInfo *token = newToken (); LastTokenType = TOKEN_UNDEFINED; vStringPut(string, c); do { readTokenFull (token, FALSE, string); if (isType (token, TOKEN_OPEN_CURLY)) depth++; else if (isType (token, TOKEN_CLOSE_CURLY)) depth--; } while (! isType (token, TOKEN_EOF) && depth > 0); deleteToken (token); } } } while (c != EOF); vStringTerminate (string); }
static void findTags (boolean startsInPhpMode) { tokenInfo *const token = newToken (); InPhp = startsInPhpMode; CurrentStatement.access = ACCESS_UNDEFINED; CurrentStatement.impl = IMPL_UNDEFINED; CurrentNamesapce = vStringNew (); FullScope = vStringNew (); AnonymousID = 0; do { enterScope (token, NULL, -1); } while (token->type != TOKEN_EOF); /* keep going even with unmatched braces */ vStringDelete (FullScope); vStringDelete (CurrentNamesapce); deleteToken (token); }
static boolean parseType (tokenInfo *const token) { tokenInfo* const id = newToken (); copyToken (id, token); readToken (token); if (isType (token, TOKEN_COLON)) /* check for "{entity: TYPE}" */ { readToken (id); readToken (token); } if (isKeyword (id, KEYWORD_like)) { if (isType (token, TOKEN_IDENTIFIER) || isKeyword (token, KEYWORD_Current)) readToken (token); } else { if (isKeyword (id, KEYWORD_attached) || isKeyword (id, KEYWORD_detachable) || isKeyword (id, KEYWORD_expanded)) { copyToken (id, token); readToken (token); } if (isType (id, TOKEN_IDENTIFIER)) { #ifdef TYPE_REFERENCE_TOOL reportType (id); #endif if (isType (token, TOKEN_OPEN_BRACKET)) parseGeneric (token, FALSE); else if ((strcmp ("BIT", vStringValue (id->string)) == 0)) readToken (token); /* read token after number of bits */ } } deleteToken (id); return TRUE; }
/* parses namespace declarations * namespace Foo {} * namespace Foo\Bar {} * namespace Foo; * namespace Foo\Bar; * namespace; * napespace {} */ static boolean parseNamespace (tokenInfo *const token) { tokenInfo *nsToken = newToken (); vStringClear (CurrentNamesapce); copyToken (nsToken, token, FALSE); do { readToken (token); if (token->type == TOKEN_IDENTIFIER) { if (vStringLength (CurrentNamesapce) > 0) { const char *sep; sep = phpScopeSeparatorFor(K_NAMESPACE, K_NAMESPACE); vStringCatS (CurrentNamesapce, sep); } vStringCat (CurrentNamesapce, token->string); } } while (token->type != TOKEN_EOF && token->type != TOKEN_SEMICOLON && token->type != TOKEN_OPEN_CURLY); vStringTerminate (CurrentNamesapce); if (vStringLength (CurrentNamesapce) > 0) makeNamespacePhpTag (nsToken, CurrentNamesapce); if (token->type == TOKEN_OPEN_CURLY) enterScope (token, NULL, -1); deleteToken (nsToken); return TRUE; }