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

📄 parse.c

📁 VIM文本编辑器
💻 C
📖 第 1 页 / 共 3 页
字号:
#if 0
/*  Skip to the next occurance of the specified character.
 */
static int skipToCharacter( findchar )
    const int findchar;
{
    int c;

    do
	c = cppGetc();
    while (c != EOF  &&  c != findchar);

    return c;
}
#endif

/*  Skips to the next brace in column 1. This is intended for cases where
 *  preprocessor constructs result in unbalanced braces.
 */
static void skipToFormattedBraceMatch()
{
    int c, next;

    c = cppGetc();
    next = cppGetc();
    while (c != EOF  &&  (c != '\n'  ||  next != '}'))
    {
	c = next;
	next = cppGetc();
    }
}

/*  Skip to the matching character indicated by the pair string. If skipping
 *  to a matching brace and any brace is found within a different level of a
 *  #if conditional statement while brace formatting is in effect, we skip to
 *  the brace matched by its formatting. It is assumed that we have already
 *  read the character which starts the group (i.e. the first character of
 *  "pair").
 */
static boolean skipToMatch( pair )
    const char *const pair;
{
    const int begin = pair[0], end = pair[1];
    const unsigned int initialLevel = Cpp.directive.nestLevel;
    const boolean braceFormatting = (boolean)(Option.braceFormat &&
					      strcmp("{}", pair) == 0);
    boolean ok = TRUE;
    int matchLevel = 1;
    int c = '\0';

    while (matchLevel > 0  &&  (c = cppGetc()) != EOF)
    {
	if (c == begin)
	{
	    ++matchLevel;
	    if (braceFormatting  &&  Cpp.directive.nestLevel != initialLevel)
	    {
		skipToFormattedBraceMatch();
		break;
	    }
	}
	else if (c == end)
	{
	    --matchLevel;
	    if (braceFormatting  &&  Cpp.directive.nestLevel != initialLevel)
	    {
		skipToFormattedBraceMatch();
		break;
	    }
	}
    }
    if (c == EOF)
	ok = FALSE;

    return ok;
}

/*  Read a C identifier beginning with "firstChar" and places it into "name".
 */
static void readIdentifier( firstChar, name )
    const int firstChar;
    char *const name;
{
    int c, i;

    name[0] = firstChar;
    for (i = 1, c = cppGetc() ;
	 i < (int)MaxNameLength - 1  &&  isident(c) ;
	 i++, c = cppGetc())
    {
	name[i] = c;
    }
    name[i] = '\0';		/* null terminate name */

    cppUngetc(c);		/* unget non-identifier character */
}

/*  Read a C++ operator and appends to "name" (which should contain "operator").
 */
static void readOperator( firstChar, name )
    const int firstChar;
    char *const name;
{
    int c, i;

    for (c = firstChar, i = strlen(name) ;
	 i < (int)MaxNameLength - 1  &&  ! isspace(c)  &&  c != '(' ;
	 i++, c = cppGetc())
    {
	name[i] = c;
    }
    if (i > 0)
	name[i] = '\0';		/* null terminate operator */

    cppUngetc(c);		/* unget non-operator character */
}

/*  Analyzes the identifier contained in a statement described by the
 *  statement structure and adjusts the structure according the significance
 *  of the identifier.
 */
static keywordId analyzeKeyword( name )
    const char *const name;
{
    keywordId id = KEYWORD_UNKNOWN;

    if (name[0] == '_'  ||  islower(name[0]))
    {
	const short hash = KeywordHash[hashIndex(name[0])];

	if (hash >= 0)
	{
	    unsigned int i;

	    for (i = hash  ;  i < KeywordTableSize  ;  ++i)
	    {
		const keywordDesc *pKw = &KeywordTable[i];

		if (pKw->name[0] != name[0])
		    break;

		if (pKw->isValid[File.language] && strcmp(pKw->name, name) == 0)
		{
		    id = pKw->id;
		    break;
		}
	    }
	}
    }
    return id;
}

static void processKeyword( st, keyword )
    statementInfo *const st;
    keywordId keyword;
{
    st->token = TOK_SPEC;			/* default unless otherwise */

    switch (keyword)		/* is it a reserved word? */
    {
	default:		st->token	= TOK_IGNORE;		break;

	case KEYWORD_CHAR:	st->declaration = DECL_BASE;		break;
	case KEYWORD_CLASS:	st->declaration = DECL_CLASS;		break;
	case KEYWORD_DOUBLE:	st->declaration = DECL_BASE;		break;
	case KEYWORD_ENUM:	st->declaration = DECL_ENUM;		break;
	case KEYWORD_EXTERN:	st->scope	= SCOPE_EXTERN;		break;
	case KEYWORD_FLOAT:	st->declaration = DECL_BASE;		break;
	case KEYWORD_FRIEND:	st->scope	= SCOPE_FRIEND;		break;
	case KEYWORD_IMPORT:	st->declaration = DECL_IGNORE;		break;
	case KEYWORD_INT:	st->declaration = DECL_BASE;		break;
	case KEYWORD_INTERFACE:	st->declaration = DECL_INTERFACE;	break;
	case KEYWORD_LONG:	st->declaration = DECL_BASE;		break;
	case KEYWORD_NAMESPACE:	st->declaration = DECL_NAMESPACE;	break;
	case KEYWORD_PACKAGE:	st->declaration = DECL_IGNORE;		break;
	case KEYWORD_PRIVATE:	st->member.visibility = VIS_PRIVATE;	break;
	case KEYWORD_PROTECTED:	st->member.visibility = VIS_PROTECTED;	break;
	case KEYWORD_PUBLIC:	st->member.visibility = VIS_PUBLIC;	break;
	case KEYWORD_SHORT:	st->declaration = DECL_BASE;		break;
	case KEYWORD_SIGNED:	st->declaration = DECL_BASE;		break;
	case KEYWORD_STRUCT:	st->declaration = DECL_STRUCT;		break;
	case KEYWORD_TYPEDEF:	st->scope	= SCOPE_TYPEDEF;	break;
	case KEYWORD_UNION:	st->declaration = DECL_UNION;		break;
	case KEYWORD_UNSIGNED:	st->declaration = DECL_BASE;		break;
	case KEYWORD_VOID:	st->declaration = DECL_BASE;		break;

	case KEYWORD_ATTRIBUTE:
	{
	    const int c = skipToNonWhite();

	    if (c == '(')
		skipToMatch("()");
	    else
		cppUngetc(c);
	    st->token = TOK_IGNORE;
	    break;
	}

	case KEYWORD_EXTENDS:
	case KEYWORD_IMPLEMENTS:
	case KEYWORD_THROWS:
	{
	    char *const name = activeName(st);
	    int c = skipToNonWhite();

	    /*  Read and discard interface or class type-list (ident[, ident]).
	     */
	    while (isident1(c))
	    {
		readIdentifier(c, name);
		c = skipToNonWhite();
		if (c == '.'  ||  c == ',')
		    c = skipToNonWhite();
	    }
	    cppUngetc(c);
	    st->token = TOK_IGNORE;
	    break;
	}

	case KEYWORD_STATIC:
	    if (File.language != LANG_JAVA)
		st->scope = SCOPE_STATIC;
	    break;

	case KEYWORD_OPERATOR:
	{
	    char *const name = activeName(st);
	    const int c = skipToNonWhite();

	    if (isident1(c))
		readIdentifier(c, name);
	    else
		readOperator(c, name);
	} /* fall through to unknown keyword case */
	case KEYWORD_UNKNOWN:
	{
	    tagInfo *const tag = &activeTag(st);

	    st->token	= TOK_NAME;
	    st->gotName	= TRUE;

	    tag->location   = File.seek;
	    tag->lineNumber = File.lineNumber;

	    if (st->declaration == DECL_CLASS  &&  st->class.name[0] == '\0')
	    {
		strcpy(st->class.name, tag->name);
		st->class.location   = tag->location;
		st->class.lineNumber = tag->lineNumber;
	    }
	    break;
	}
    }
}

/*  Skips over characters following the parameter list. This might be non-ANSI
 *  style function declarations, a C++ exception specification, or another C++
 *  construct that I don't yet understand (e.g. "void Class::foo(int a):
 *  attr(v1), attr(v2)").
 */
static int skipPostArgumentStuff( c, st, emptyArgList )
    int c;
    statementInfo *const st;
    const boolean emptyArgList;
{
    boolean end = FALSE, firstSemicolon = TRUE;
    boolean skipCPlusStuff = (boolean)(c == ':');
    unsigned int tokenCount = 0;

    while (c != EOF  &&  ! end)
    {
	if (skipCPlusStuff)
	{
	    if (c == '{'  ||  c == ';')
		break;
	}
	else if (isident1(c))
	{
	    char name[MaxNameLength];
	    keywordId keyword;

	    readIdentifier(c, name);
	    ++tokenCount;
	    keyword = analyzeKeyword(name);
	    switch (keyword)
	    {
	    /*  These words are explicitly allowed following the closing
	     *  parenthesis in C++.
	     */
	    case KEYWORD_CONST:
		break;

	    case KEYWORD_THROW:
		skipCPlusStuff = TRUE;
		break;

	    /*  These words are never allowed within parameter declarations.
	     */
	    case KEYWORD_CLASS:
	    case KEYWORD_EXTERN:
	    case KEYWORD_STATIC:
	    case KEYWORD_TYPEDEF:
		DebugStatement( if (debug(DEBUG_PARSE)) printf("<ES>"); )
		reinitStatement(st);
		processKeyword(st, keyword);
		c = skipToNonWhite();
		end = TRUE;
		continue;		/* skip read of next character */

	    case KEYWORD_ATTRIBUTE:
		{
		    c = skipToNonWhite();
		    if (c == '('  &&  ! skipToMatch("()"))
			c = EOF;
		}
		break;

	    default:
		/*  If we encounter any other identifier immediately following
		 *  an empty parameter list, this is almost certainly one of
		 *  those Microsoft macro "thingies" that the automatic source
		 *  code generation sticks in. Terminate the current statement.
		 */
		if (emptyArgList)
		{
		    DebugStatement( if (debug(DEBUG_PARSE)) printf("<ES>"); )
		    reinitStatement(st);
		    processKeyword(st, keyword);
		    c = skipToNonWhite();
		    end = TRUE;
		    continue;		/* skip read of next character */
		}
		break;
	    }
	}
	else switch (c)
	{
	default:    break;	/* ignore */

	case ';':
	    /*  A lone word is most likely a preprocessor qualifier.
	     */
	    if (firstSemicolon  &&  tokenCount == 1)
	    {
		end = TRUE;
		continue;
	    }
	    else
	    {
		tokenCount = 0;
		firstSemicolon = FALSE;
		break;
	    }

	case '(':
	    ++tokenCount;
	    if (! skipToMatch("()"))
		c = EOF;
	    break;

	case '[':   if (! skipToMatch("[]"))  c = EOF;	break;
	case '{':
	case '}':   end = TRUE;
		    continue;		/* skip read of next character */
	}
	if (c != EOF)
	    c = cppGetc();
    }
    return c;
}

static boolean analyzePostParens( st, paren, emptyArgList )
    statementInfo *const st;
    const parenInfo *const paren;
    const boolean emptyArgList;
{
    boolean ok = TRUE;
    int c;

    /*	At this point we should be at the character following the
     *	closing parenthesis.
     */
    c = skipToNonWhite();
    if (st->gotName)
    {
	if (strchr("{;,", c) != NULL)
	{
	    st->token = TOK_ARGS;		/* parameter list to a func. */
	    st->declaration = DECL_BASE;	/* clear any other decl. */
	}
	else if (isident1(c)  ||  c == ':')
	{
	    st->token = TOK_ARGS;		/* parameter list to a func. */
	    st->declaration = DECL_BASE;	/* clear any other decl. */
	    if (File.language != LANG_JAVA)
		c = skipPostArgumentStuff(c, st, emptyArgList);
	}
	else
	    st->token = TOK_IGNORE;
    }
    /*	The name inside the parentheses must have been a function or
     *	variable name.
     */
    else if (paren->gotName)
    {
	tagInfo *const tag = &activeTag(st);

	st->gotName	= TRUE;
	st->token	= TOK_NAME;
	tag->location	= paren->location;
	tag->lineNumber	= paren->lineNumber;
	strcpy(tag->name, paren->name);
    }
    else
	st->token = TOK_IGNORE;
    if (c == EOF)
	ok = FALSE;
    else
	cppUngetc(c);

⌨️ 快捷键说明

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