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

📄 eiffel.c

📁 ultraEdit的Ctag标签工具的实现源代码
💻 C
📖 第 1 页 / 共 3 页
字号:

    switch (c)
    {
	case 'A':	d = '@';	break;
	case 'B':	d = '\b';	break;
	case 'C':	d = '^';	break;
	case 'D':	d = '$';	break;
	case 'F':	d = '\f';	break;
	case 'H':	d = '\\';	break;
	case 'L':	d = '~';	break;
	case 'N':	d = '\n';	break;
#ifdef QDOS
	case 'Q':	d = 0x9F;	break;
#else
	case 'Q':	d = '`';	break;
#endif
	case 'R':	d = '\r';	break;
	case 'S':	d = '#';	break;
	case 'T':	d = '\t';	break;
	case 'U':	d = '\0';	break;
	case 'V':	d = '|';	break;
	case '%':	d = '%';	break;
	case '\'':	d = '\'';	break;
	case '"':	d = '"';	break;
	case '(':	d = '[';	break;
	case ')':	d = ']';	break;
	case '<':	d = '{';	break;
	case '>':	d = '}';	break;

	case '\n': skipToCharacter ('%'); break;

	case '/':
	{
	    vString *string = parseInteger ('\0');
	    const char *value = vStringValue (string);
	    const unsigned long ascii = atol (value);

	    c = fileGetc ();
	    if (c == '/'  &&  ascii < 256)
		d = ascii;
	    break;
	}

	default: break;
    }
    return d;
}

static int parseCharacter (void)
{
    int c = fileGetc ();
    int result = c;

    if (c == '%')
	result = parseEscapedCharacter ();

    c = fileGetc ();
    if (c != '\'')
	skipToCharacter ('\n');

    return result;
}

static void parseString (vString *const string)
{
    boolean verbatim = FALSE;
    boolean align = FALSE;
    boolean end = FALSE;
    vString *verbatimCloser = NULL;
    vString *lastLine = NULL;
    int prev = '\0';
    int c;

    while (! end)
    {
	c = fileGetc ();
	if (c == EOF)
	    end = TRUE;
	else if (c == '"')
	{
	    if (! verbatim)
		end = TRUE;
	    else
		end = (boolean) (strcmp (vStringValue (lastLine),
					 vStringValue (verbatimCloser)) == 0);
	}
	else if (c == '\n')
	{
	    if (verbatim)
		vStringClear (lastLine);
	    if (prev == '[' /* ||  prev == '{' */)
	    {
		verbatim = TRUE;
		verbatimCloser = vStringNew ();
		lastLine = vStringNew ();
		if (prev == '{')
		    vStringPut (verbatimCloser, '}');
		else
		{
		    vStringPut (verbatimCloser, ']');
		    align = TRUE;
		}
		vStringNCat (verbatimCloser, string, vStringLength (string) - 1);
		vStringClear (string);
	    }
	    if (verbatim && align)
	    {
		do
		    c = fileGetc ();
		while (isspace (c));
	    }
	}
	else if (c == '%')
	    c = parseEscapedCharacter ();
	if (! end)
	{
	    vStringPut (string, c);
	    if (verbatim)
	    {
		vStringPut (lastLine, c);
		vStringTerminate (lastLine);
	    }
	    prev = c;
	}
    }
    vStringTerminate (string);
}

/*  Read a C identifier beginning with "firstChar" and places it into "name".
 */
static void parseIdentifier (vString *const string, const int firstChar)
{
    int c = firstChar;

    do
    {
	vStringPut (string, c);
	c = fileGetc ();
    } while (isident (c));

    vStringTerminate (string);
    if (!isspace (c))
	fileUngetc (c);		/* unget non-identifier character */
}

static void parseFreeOperator (vString *const string, const int firstChar)
{
    int c = firstChar;

    do
    {
	vStringPut (string, c);
	c = fileGetc ();
    } while (c > ' ');

    vStringTerminate (string);
    if (!isspace (c))
	fileUngetc (c);		/* unget non-identifier character */
}

static keywordId analyzeToken (vString *const name)
{
    static vString *keyword = NULL;
    keywordId id;

    if (keyword == NULL)
	keyword = vStringNew ();
    vStringCopyToLower (keyword, name);
    id = (keywordId) lookupKeyword (vStringValue (keyword), Lang_eiffel);

    return id;
}

static void readToken (tokenInfo *const token)
{
    int c;

    token->type    = TOKEN_UNDEFINED;
    token->keyword = KEYWORD_NONE;
    vStringClear (token->string);

getNextChar:

    do
	c = fileGetc ();
    while (c == '\t'  ||  c == ' '  ||  c == '\n');

    switch (c)
    {
	case EOF:	longjmp (Exception, (int)ExceptionEOF);	break;
	case '!':	token->type = TOKEN_BANG;		break;
	case '$':	token->type = TOKEN_DOLLAR;		break;
	case '(':	token->type = TOKEN_OPEN_PAREN;		break;
	case ')':	token->type = TOKEN_CLOSE_PAREN;	break;
	case ',':	token->type = TOKEN_COMMA;		break;
	case '.':	token->type = TOKEN_DOT;		break;
	case ';':	goto getNextChar;
	case '[':	token->type = TOKEN_OPEN_BRACKET;	break;
	case ']':	token->type = TOKEN_CLOSE_BRACKET;	break;
	case '{':	token->type = TOKEN_OPEN_BRACE;		break;
	case '}':	token->type = TOKEN_CLOSE_BRACE;	break;
	case '~':	token->type = TOKEN_TILDE;		break;


	case '+':
	case '*':
	case '^':
	case '=':	token->type = TOKEN_OPERATOR;		break;

	case '-':
	    c = fileGetc ();
	    if (c == '>')
		token->type = TOKEN_CONSTRAINT;
	    else if (c == '-')		/* is this the start of a comment? */
	    {
		skipToCharacter ('\n');
		goto getNextChar;
	    }
	    else
	    {
		if (!isspace (c))
		    fileUngetc (c);
 		token->type = TOKEN_OPERATOR;
	    }
	    break;

	case '?':
	case ':':
	    c = fileGetc ();
	    if (c == '=')
		token->type = TOKEN_OPERATOR;
	    else
	    {
		token->type = TOKEN_COLON;
		if (!isspace (c))
		    fileUngetc (c);
	    }
	    break;

	case '<':
	    c = fileGetc ();
	    if (c != '='  &&  c != '>'  &&  !isspace (c))
		fileUngetc (c);
	    token->type = TOKEN_OPERATOR;
	    break;

	case '>':
	    c = fileGetc ();
	    if (c != '='  &&  c != '>'  &&  !isspace (c))
		fileUngetc (c);
	    token->type = TOKEN_OPERATOR;
	    break;

	case '/':
	    c = fileGetc ();
	    if (c != '/'  &&  c != '='  &&  !isspace (c))
		fileUngetc (c);
	    token->type = TOKEN_OPERATOR;
	    break;

	case '\\':
	    c = fileGetc ();
	    if (c != '\\'  &&  !isspace (c))
		fileUngetc (c);
	    token->type = TOKEN_OPERATOR;
	    break;

	case '"':
	    token->type = TOKEN_STRING;
	    parseString (token->string);
	    break;

	case '\'':
	    token->type = TOKEN_CHARACTER;
	    parseCharacter ();
	    break;

	default:
	    if (isalpha (c))
	    {
		parseIdentifier (token->string, c);
		token->keyword = analyzeToken (token->string);
		if (isKeyword (token, KEYWORD_NONE))
		    token->type = TOKEN_IDENTIFIER;
		else
		    token->type = TOKEN_KEYWORD;
	    }
	    else if (isdigit (c))
	    {
		vStringCat (token->string, parseNumeric (c));
		token->type = TOKEN_NUMERIC;
	    }
	    else if (isFreeOperatorChar (c))
	    {
		parseFreeOperator (token->string, c);
		token->type = TOKEN_OPERATOR;
	    }
	    else
	    {
		token->type = TOKEN_UNDEFINED;
		Assert (! isType (token, TOKEN_UNDEFINED));
	    }
	    break;
    }
}

/*
*   Scanning functions
*/

static boolean isIdentifierMatch (const tokenInfo *const token,
				  const char *const name)
{
    return (boolean) (isType (token, TOKEN_IDENTIFIER)  &&
		     strcasecmp (vStringValue (token->string), name) == 0);
}

static void findToken (tokenInfo *const token, const tokenType type)
{
    while (! isType (token, type))
	readToken (token);
}

static void findKeyword (tokenInfo *const token, const keywordId keyword)
{
    while (! isKeyword (token, keyword))
	readToken (token);
}

static void parseGeneric (tokenInfo *const token, boolean declaration __unused__)
{
    unsigned int depth = 0;
#ifdef TYPE_REFERENCE_TOOL
    boolean constraint = FALSE;
#endif
    Assert (isType (token, TOKEN_OPEN_BRACKET));
    do
    {
	if (isType (token, TOKEN_OPEN_BRACKET))
	    ++depth;
	else if (isType (token, TOKEN_CLOSE_BRACKET))
	    --depth;
#ifdef TYPE_REFERENCE_TOOL
	else if (declaration)
	{
	    if (depth == 1)
	    {
		if (isType (token, TOKEN_CONSTRAINT))
		    constraint = TRUE;
		else if (isKeyword (token, KEYWORD_create))
		    findKeyword (token, KEYWORD_end);
		else if (isType (token, TOKEN_IDENTIFIER))
		{
		    if (constraint)
			reportType (token);
		    else
			addGenericName (token);
		    constraint = FALSE;
		}
	    }
	    else if (isKeyword (token, KEYWORD_like))
		readToken (token);
	    else if (isType (token, TOKEN_IDENTIFIER))
		reportType (token);
	}
	else
	{
	    if (isType (token, TOKEN_OPEN_BRACKET))
		++depth;
	    else if (isType (token, TOKEN_IDENTIFIER))
		reportType (token);
	    else if (isKeyword (token, KEYWORD_like))
		readToken (token);
	}
#endif
	readToken (token);
    } while (depth > 0);
}

static void parseType (tokenInfo *const token)
{
    boolean bitType;
    Assert (isType (token, TOKEN_IDENTIFIER));
#ifdef TYPE_REFERENCE_TOOL
    reportType (token);
#endif
    bitType = (boolean)(strcmp ("BIT", vStringValue (token->string)) == 0);
    readToken (token);
    if (bitType && isType (token, TOKEN_NUMERIC))
	readToken (token);
    else if (isType (token, TOKEN_OPEN_BRACKET))
	parseGeneric (token, FALSE);
}

static void parseEntityType (tokenInfo *const token)
{
    Assert (isType (token, TOKEN_COLON));
    readToken (token);

    if (isKeyword (token, KEYWORD_expanded))
	readToken (token);

    /*  Skip over the type name, with possible generic parameters.
     */
    if (isType (token, TOKEN_IDENTIFIER))
	parseType (token);
    else if (isKeyword (token, KEYWORD_like))
    {
	readToken (token);
	if (isType (token, TOKEN_IDENTIFIER) ||
		isKeyword (token, KEYWORD_Current))
	    readToken (token);
    }
}


static void parseLocal (tokenInfo *const token)
{
    Assert (isKeyword (token, KEYWORD_local));
    readToken (token);

    /*  Check keyword first in case local clause is empty
     */
    while (! isKeyword (token, KEYWORD_do)  &&
	   ! isKeyword (token, KEYWORD_once))
    {
#ifndef TYPE_REFERENCE_TOOL
	if (isType (token, TOKEN_IDENTIFIER))
	    makeEiffelLocalTag (token);

#endif
	readToken (token);
	if (isType (token, TOKEN_COLON))
	{
	    readToken (token);
	    if (isType (token, TOKEN_IDENTIFIER))
		parseType (token);
	}
    }
}

⌨️ 快捷键说明

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