⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 parse.c

📁 VIM文本编辑器
💻 C
📖 第 1 页 / 共 3 页
字号:
/*****************************************************************************
*   $Id: parse.c,v 6.6 1998/08/20 04:50:36 darren Exp $

*
*   Copyright (c) 1996-1998, Darren Hiebert
*
*   This source code is released for free distribution under the terms of the
*   GNU General Public License.
*
*   This module contains functions for parsing and scanning of a source file.
*****************************************************************************/

/*============================================================================
=   Include files
============================================================================*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "ctags.h"

/*============================================================================
=   Macros
============================================================================*/
#define hashIndex(c)		((c) - '_')
#define activeTag(st)		((st)->tag[(int)(st)->buf1])
#define activeName(st)		(activeTag(st).name)
#define swapNameBuffers(st)	((st)->buf1 = (boolean)!(st)->buf1)

#define isExternCDecl(st,c)	((c) == STRING_SYMBOL  &&  !(st)->gotName  && \
				 (st)->scope == SCOPE_EXTERN)

/*============================================================================
=   Data declarations
============================================================================*/

/*  Used to specify type of keyword.
 */
typedef enum _keywordId {
    KEYWORD_UNKNOWN,
    KEYWORD_ABSTRACT, KEYWORD_ATTRIBUTE,
    KEYWORD_BOOLEAN, KEYWORD_BYTE,
    KEYWORD_CHAR, KEYWORD_CLASS, KEYWORD_CONST,
    KEYWORD_DOUBLE,
    KEYWORD_ENUM, KEYWORD_EXPLICIT, KEYWORD_EXTERN, KEYWORD_EXTENDS,
    KEYWORD_FINAL, KEYWORD_FLOAT, KEYWORD_FRIEND,
    KEYWORD_IMPLEMENTS, KEYWORD_IMPORT, KEYWORD_INLINE, KEYWORD_INT,
    KEYWORD_INTERFACE,
    KEYWORD_LONG,
    KEYWORD_MUTABLE,
    KEYWORD_NAMESPACE, KEYWORD_NEW, KEYWORD_NATIVE,
    KEYWORD_OPERATOR, KEYWORD_OVERLOAD,
    KEYWORD_PACKAGE, KEYWORD_PRIVATE, KEYWORD_PROTECTED, KEYWORD_PUBLIC,
    KEYWORD_REGISTER,
    KEYWORD_SHORT, KEYWORD_SIGNED, KEYWORD_STATIC, KEYWORD_STRUCT,
    KEYWORD_SYNCHRONIZED,
    KEYWORD_TEMPLATE, KEYWORD_THROW, KEYWORD_THROWS, KEYWORD_TRANSIENT,
    KEYWORD_TYPEDEF, KEYWORD_TYPENAME,
    KEYWORD_UNION, KEYWORD_UNSIGNED, KEYWORD_USING,
    KEYWORD_VIRTUAL, KEYWORD_VOID, KEYWORD_VOLATILE,
    KEYWORD_WCHAR_T
} keywordId;

/*  Used to determine whether keyword is valid for the current language and
 *  what its ID is.
 */
typedef struct _keywordDesc {
    const char *name;
    keywordId id;
    short isValid[LANG_COUNT]; /* indicates languages for which kw is valid */
} keywordDesc;

/*  Used for reporting the type of object parsed by nextToken().
 */
typedef enum _tokenType {
    TOK_NONE,		/* none */
    TOK_ARGS,		/* a parenthetical pair and its contents */
    TOK_BODY,		/* a brace enclosed block */
    TOK_COMMA,		/* the comma character */
    TOK_IGNORE,		/* a sequence not to be seen by createTags() */
    TOK_ENUM_BODY_END,	/* the beginning of a list of enumeration values */
    TOK_EOF,		/* end of file */
    TOK_NAME,		/* an unknown name */
    TOK_SEMICOLON,	/* the semicolon character */
    TOK_SPEC		/* a storage class specifier, qualifier, type, etc. */
} tokenType;

/*  Describes the statement currently undergoing analysis.
 */
typedef struct _statementInfo {
    tagScope	scope;
    enum _declaration {
	DECL_BASE,		/* base type (default) */
	DECL_CLASS,		/* C++ class */
	DECL_ENUM,		/* enumeration */
	DECL_IGNORE,		/* non-taggable "declaration" */
	DECL_INTERFACE,		/* interface */
	DECL_NAMESPACE,		/* namespace */
	DECL_STRUCT,		/* structure */
	DECL_UNION,		/* union */
	DECL_NOMANGLE		/* C++ name demangling block */
    } declaration;	/* describes specifier associated with TOK_SPEC */
    tokenType token;	/* the most recent type of token */
    tokenType prev[2];	/* the previous tokens */
    boolean gotName;	/* was a name parsed yet? */
    boolean isFuncPtr;	/* is 'name' a pointer? */
    boolean inEnumBody;	/* currently within enumeration value list? */
    boolean buf1;	/* is tag[1] the primary buffer? */
    tagInfo tag[2];	/* information regarding last 2 tag candidates */
    tagInfo class;	/* class declaration name info */
    memberInfo member;	/* information regarding parent class/struct */
} statementInfo;

/*  Information about an identifier within parentheses.
 */
typedef struct _parenInfo {
    char name[MaxNameLength];
    boolean gotName;
    long location;
    long lineNumber;
} parenInfo;

/*============================================================================
=   Data definitions
============================================================================*/

enum { HashSize = ('z' - '_' + 1) };	/* '_' through 'z' */
static short KeywordHash[(int)HashSize];

static const keywordDesc KeywordTable[] = {
    /* 						    C++		*/
    /* 					     ANSI C  |  Java	*/
    /* keyword		keyword ID		 \   |   /  	*/
    { "__attribute__",	KEYWORD_ATTRIBUTE,	{ 1, 1, 0 } },
    { "abstract",	KEYWORD_ABSTRACT,	{ 0, 0, 1 } },
    { "boolean",	KEYWORD_BOOLEAN,	{ 0, 0, 1 } },
    { "byte",		KEYWORD_BYTE,		{ 0, 0, 1 } },
    { "char",		KEYWORD_CHAR,		{ 1, 1, 1 } },
    { "class",		KEYWORD_CLASS,		{ 0, 1, 1 } },
    { "const",		KEYWORD_CONST,		{ 1, 1, 1 } },
    { "double",		KEYWORD_DOUBLE,		{ 1, 1, 1 } },
    { "enum",		KEYWORD_ENUM,		{ 1, 1, 0 } },
    { "explicit",	KEYWORD_EXPLICIT,	{ 0, 1, 0 } },
    { "extends",	KEYWORD_EXTENDS,	{ 0, 0, 1 } },
    { "extern",		KEYWORD_EXTERN,		{ 1, 1, 0 } },
    { "final",		KEYWORD_FINAL,		{ 0, 0, 1 } },
    { "float",		KEYWORD_FLOAT,		{ 1, 1, 1 } },
    { "friend",		KEYWORD_FRIEND,		{ 0, 1, 0 } },
    { "implements",	KEYWORD_IMPLEMENTS,	{ 0, 0, 1 } },
    { "import",		KEYWORD_IMPORT,		{ 0, 0, 1 } },
    { "inline",		KEYWORD_INLINE,		{ 0, 1, 0 } },
    { "int",		KEYWORD_INT,		{ 1, 1, 1 } },
    { "interface",	KEYWORD_INTERFACE,	{ 0, 0, 1 } },
    { "long",		KEYWORD_LONG,		{ 1, 1, 1 } },
    { "mutable",	KEYWORD_MUTABLE,	{ 0, 1, 0 } },
    { "namespace",	KEYWORD_NAMESPACE,	{ 0, 1, 0 } },
    { "native",		KEYWORD_NATIVE,		{ 0, 0, 1 } },
    { "new",		KEYWORD_NEW,		{ 0, 1, 1 } },
    { "operator",	KEYWORD_OPERATOR,	{ 0, 1, 0 } },
    { "overload",	KEYWORD_OVERLOAD,	{ 0, 1, 0 } },
    { "package",	KEYWORD_PACKAGE,	{ 0, 0, 1 } },
    { "private",	KEYWORD_PRIVATE,	{ 0, 1, 1 } },
    { "protected",	KEYWORD_PROTECTED,	{ 0, 1, 1 } },
    { "public",		KEYWORD_PUBLIC,		{ 0, 1, 1 } },
    { "register",	KEYWORD_REGISTER,	{ 1, 1, 0 } },
    { "short",		KEYWORD_SHORT,		{ 1, 1, 1 } },
    { "signed",		KEYWORD_SIGNED,		{ 1, 1, 0 } },
    { "static",		KEYWORD_STATIC,		{ 1, 1, 1 } },
    { "struct",		KEYWORD_STRUCT,		{ 1, 1, 0 } },
    { "synchronized",	KEYWORD_SYNCHRONIZED,	{ 0, 0, 1 } },
    { "template",	KEYWORD_TEMPLATE,	{ 0, 1, 0 } },
    { "throw",		KEYWORD_THROW,		{ 0, 1, 1 } },
    { "throws",		KEYWORD_THROWS,		{ 0, 0, 1 } },
    { "transient",	KEYWORD_TRANSIENT,	{ 0, 0, 1 } },
    { "typedef",	KEYWORD_TYPEDEF,	{ 1, 1, 0 } },
    { "typename",	KEYWORD_TYPENAME,	{ 0, 1, 0 } },
    { "union",		KEYWORD_UNION,		{ 1, 1, 0 } },
    { "unsigned",	KEYWORD_UNSIGNED,	{ 1, 1, 0 } },
    { "using",		KEYWORD_USING,		{ 0, 1, 0 } },
    { "virtual",	KEYWORD_VIRTUAL,	{ 0, 1, 0 } },
    { "void",		KEYWORD_VOID,		{ 1, 1, 1 } },
    { "volatile",	KEYWORD_VOLATILE,	{ 1, 1, 1 } },
    { "wchar_t",	KEYWORD_WCHAR_T,	{ 1, 1, 0 } }
};

static const size_t KeywordTableSize =
				sizeof(KeywordTable)/sizeof(KeywordTable[0]);

/*============================================================================
=   Function prototypes
============================================================================*/
static void initTag __ARGS((tagInfo *const tag));
static void initMemberInfo __ARGS((memberInfo *const pMember));
static void reinitStatement __ARGS((statementInfo *const st));
static void initStatement __ARGS((statementInfo *const st, const statementInfo *const parent));

/*  Tag generation functions.
 */
static void qualifyBlockTag __ARGS((const statementInfo *const st, const tagInfo *const tag, const tagScope declScope));
static void qualifyEnumeratorTag __ARGS((const statementInfo *const st, const tagInfo *const tag, const tagScope declScope));
static void qualifyFunctionTag __ARGS((statementInfo *const st, const tagInfo *const tag));
static void qualifyVariableTag __ARGS((const statementInfo *const st, const tagInfo *const tag));
static void qualifyFunctionDeclTag __ARGS((const statementInfo *const st, const tagInfo *const tag));

/*  Parsing functions.
 */
static int skipToNonWhite __ARGS((void));
static void skipToFormattedBraceMatch __ARGS((void));
static boolean skipToMatch __ARGS((const char *const pair));
static void readIdentifier __ARGS((const int firstChar, char *const name));
static void readOperator __ARGS((const int firstChar, char *const name));
static keywordId analyzeKeyword __ARGS((const char *const name));
static void processKeyword __ARGS((statementInfo *const st, keywordId keyword));
static int skipPostArgumentStuff __ARGS((int c, statementInfo *const st, const boolean emptyArgList));
static boolean analyzePostParens __ARGS((statementInfo *const st, const parenInfo *const paren, const boolean emptyArgList));
static void initParenInfo __ARGS((parenInfo *const paren));
static boolean saveParenInfo __ARGS((parenInfo *const paren, int c));
static boolean doubleParens __ARGS((statementInfo *const st));
static boolean analyzeParens __ARGS((statementInfo *const st));
static void analyzeIdentifier __ARGS((statementInfo *const st));
static boolean beginBlock __ARGS((statementInfo *const st, const unsigned int nesting));
static boolean endBlock __ARGS((statementInfo *const st, const unsigned int nesting));
static void processColon __ARGS((statementInfo *const st));
static int skipInitializer __ARGS((const boolean inEnumBody));
static boolean processInitializer __ARGS((statementInfo *const st));
static boolean processArray __ARGS((statementInfo *const st));
static boolean processTemplate __ARGS((statementInfo *const st));
static void processIdentifier __ARGS((statementInfo *const st, const int c));
static boolean nextToken __ARGS((statementInfo *const st, const unsigned int nesting));

/*============================================================================
=   Function definitions
============================================================================*/

static void initTag( tag )
    tagInfo *const tag;
{
    tag->location	= 0;
    tag->lineNumber	= 0;
    tag->name[0]	= '\0';
    DebugStatement( clearString(tag->name, MaxNameLength); )
}

static void initMemberInfo( pMember )
    memberInfo *const pMember;
{
    pMember->type	= MEMBER_NONE;
    pMember->visibility	= VIS_UNDEFINED;
    pMember->parent[0]	= '\0';
    DebugStatement( clearString(pMember->parent, MaxNameLength); )
}

static void reinitStatement( st )
    statementInfo *const st;
{
    int i;

    st->scope		= SCOPE_GLOBAL;
    st->declaration	= DECL_BASE;
    st->token		= TOK_NONE;
    st->prev[0]		= TOK_NONE;
    st->prev[1]		= TOK_NONE;
    st->gotName		= FALSE;
    st->isFuncPtr	= FALSE;
    st->buf1		= FALSE;

    for (i = 0  ;  i < 2  ;  ++i)
	initTag(&st->tag[i]);

    initTag(&st->class);

    if (st->member.type != MEMBER_NONE  &&  ! st->member.persistent)
	initMemberInfo(&st->member);
}

static void initStatement( st, parent )
    statementInfo *const st;
    const statementInfo *const parent;
{
    /*  Set the member information. If there is a parent statement, inherit
     *  the parent member information from it.
     */
    if (parent == NULL)
    {
	initMemberInfo(&st->member);
	st->inEnumBody = FALSE;
    }
    else
    {
	st->inEnumBody = (boolean)(parent->declaration == DECL_ENUM);
	st->member.visibility = VIS_UNDEFINED;
	switch (parent->declaration)
	{
	    case DECL_ENUM:	st->member.type = MEMBER_ENUM;		break;
	    case DECL_CLASS:	st->member.type = MEMBER_CLASS;
				st->member.visibility = VIS_PRIVATE;	break;
	    case DECL_INTERFACE:st->member.type = MEMBER_INTERFACE;	break;
	    case DECL_NAMESPACE:st->member.type = MEMBER_NAMESPACE;	break;
	    case DECL_STRUCT:	st->member.type = MEMBER_STRUCT;
				st->member.visibility = VIS_PUBLIC;	break;
	    case DECL_UNION:	st->member.type = MEMBER_UNION;		break;
	    default:		st->member.type = MEMBER_NONE;		break;
	}
	DebugStatement( clearString(st->member.parent, MaxNameLength); )
	if (st->member.type != MEMBER_NONE)
	{
	    st->member.persistent = TRUE;
	    if (parent->declaration == DECL_CLASS)
		strcpy(st->member.parent, parent->class.name);
	    else
		strcpy(st->member.parent,
		       (parent->prev[0] == TOK_NAME) ? activeName(parent) : "");
	}
    }
    reinitStatement(st);
}

/*----------------------------------------------------------------------------
*-	Tag generation functions
----------------------------------------------------------------------------*/

static void qualifyBlockTag( st, tag, declScope )
    const statementInfo *const st;
    const tagInfo *const tag;
    const tagScope declScope;
{
    if (st->prev[0] == TOK_NAME)
    {
	boolean ok = TRUE;
	tagType type = TAG_NUMTYPES;	/* assignment to avoid warning */

	switch (st->declaration)
	{
	    case DECL_CLASS:	type = TAG_CLASS;	break;
	    case DECL_ENUM:	type = TAG_ENUM;	break;
	    case DECL_INTERFACE:type = TAG_INTERFACE;	break;
	    case DECL_NAMESPACE:type = TAG_NAMESPACE;	break;
	    case DECL_STRUCT:	type = TAG_STRUCT;	break;
	    case DECL_UNION:	type = TAG_UNION;	break;
	    default:		ok = FALSE;		break;
	}
	if (ok)
	    makeTag(tag, &st->member, declScope, type);
    }
}

static void qualifyEnumeratorTag( st, tag, declScope )
    const statementInfo *const st;
    const tagInfo *const tag;
    const tagScope declScope;
{
    if (st->token == TOK_NAME)
	makeTag(tag, &st->member, declScope, TAG_ENUMERATOR);
}

static void qualifyFunctionTag( st, tag )
    statementInfo *const st;
    const tagInfo *const tag;
{
    if (st->scope == SCOPE_EXTERN)		/* allowed for func. def. */
	st->scope = SCOPE_GLOBAL;
    makeTag(tag, &st->member, st->scope, TAG_FUNCTION);
}

static void qualifyVariableTag( st, tag )
    const statementInfo *const st;
    const tagInfo *const tag;
{
    /*	We have to watch that we do not interpret a declaration of the
     *	form "struct tag;" as a variable definition. In such a case, the
     *	declaration will be either class, enum, struct or union, and prev[1]
     *	will be empty.
     */
    if (st->declaration == DECL_IGNORE)
	;
    else if (st->declaration == DECL_BASE  ||  st->prev[1] != TOK_SPEC)
    {
	if (st->member.type == MEMBER_NONE)
	{
	    if (st->scope == SCOPE_EXTERN)
		makeTag(tag, &st->member, st->scope, TAG_EXTERN_VAR);
	    else
		makeTag(tag, &st->member, st->scope, TAG_VARIABLE);
	}
	else
	{
	    if (st->scope == SCOPE_GLOBAL)
		makeTag(tag, &st->member, st->scope, TAG_MEMBER);
	    else if (st->scope == SCOPE_STATIC)
		makeTag(tag, &st->member, SCOPE_EXTERN, TAG_MEMBER);
	}
    }
}

static void qualifyFunctionDeclTag( st, tag )
    const statementInfo *const st;
    const tagInfo *const tag;
{
    if (! File.isHeader)
	makeTag(tag, &st->member, SCOPE_STATIC, TAG_FUNCDECL);
    else if (st->scope == SCOPE_GLOBAL  ||  st->scope == SCOPE_EXTERN)
	makeTag(tag, &st->member, SCOPE_GLOBAL, TAG_FUNCDECL);
}

/*----------------------------------------------------------------------------
*-	Parsing functions
----------------------------------------------------------------------------*/

/*  Skip to the next non-white character.
 */
static int skipToNonWhite()
{
    int c;

    do
    {
	c = cppGetc();
    } while (c != EOF  &&  isspace(c));

    return c;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -