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

📄 sql.c

📁 ultraEdit的Ctag标签工具的实现源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	    int d = fileGetc ();
	    if (d == initial)
	    {
		if (initial == '<')
		    token->type = TOKEN_BLOCK_LABEL_BEGIN;
		else
		    token->type = TOKEN_BLOCK_LABEL_END;
	    }
	    else
	    {
		fileUngetc (d);
		token->type = TOKEN_UNDEFINED;
	    }
	    break;
	}

	case '/':
	{
	    int d = fileGetc ();
	    if (d != '*')		/* is this the start of a comment? */
		fileUngetc (d);
	    else
	    {
		do
		{
		    skipToCharacter ('*');
		    c = fileGetc ();
		    if (c == '/')
			break;
		    else
			fileUngetc (c);
		} while (c != '\0');
		goto getNextChar;
	    }
	    break;
	}

	default:
	    if (! isIdentChar1 (c))
		token->type = TOKEN_UNDEFINED;
	    else
	    {
		parseIdentifier (token->string, c);
		token->lineNumber = getSourceLineNumber ();
		token->filePosition = getInputFilePosition ();
		token->keyword = analyzeToken (token->string);
		if (isKeyword (token, KEYWORD_rem))
		{
		    vStringClear (token->string);
		    skipToCharacter ('\n');
		    goto getNextChar;
		}
		else if (isKeyword (token, KEYWORD_NONE))
		    token->type = TOKEN_IDENTIFIER;
		else
		    token->type = TOKEN_KEYWORD;
	    }
	    break;
    }
}

/*
*   Scanning functions
*/

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

static void skipArgumentList (tokenInfo *const token)
{
    if (isType (token, TOKEN_OPEN_PAREN))	/* arguments? */
    {
	findToken (token, TOKEN_CLOSE_PAREN);
	readToken (token);
    }
}

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);
	readToken (token);
	parseBlock (token, TRUE);
    }
    else if (isType (token, TOKEN_SEMICOLON))
	makeSqlTag (name, SQLTAG_PROTOTYPE);
    deleteToken (name);
}

static void parseRecord (tokenInfo *const token)
{
    Assert (isType (token, TOKEN_OPEN_PAREN));
    readToken (token);
    do
    {
	readToken (token);
	if (isType (token, TOKEN_IDENTIFIER))
	    makeSqlTag (token, SQLTAG_FIELD);
	do
	    readToken (token);
	while (!(isType (token, TOKEN_COMMA) ||
		 isType (token, TOKEN_CLOSE_PAREN)));
    } while (! isType (token, TOKEN_CLOSE_PAREN));
}

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 parseSimple (tokenInfo *const token, const sqlKind kind)
{
    readToken (token);
    if (isType (token, TOKEN_IDENTIFIER))
	makeSqlTag (token, kind);
}

static void parseDeclare (tokenInfo *const token, const boolean local)
{
    if (isKeyword (token, KEYWORD_declare))
	readToken (token);
    while (! isKeyword (token, KEYWORD_begin) && ! isKeyword (token, KEYWORD_end))
    {
	switch (token->keyword)
	{
	    case KEYWORD_cursor:    parseSimple (token, SQLTAG_CURSOR); break;
	    case KEYWORD_function:  parseSubProgram (token); break;
	    case KEYWORD_procedure: parseSubProgram (token); break;
	    case KEYWORD_subtype:   parseSimple (token, SQLTAG_SUBTYPE); break;
	    case KEYWORD_trigger:   parseSimple (token, SQLTAG_TRIGGER); break;
	    case KEYWORD_type:      parseType (token); break;

	    default:
		if (isType (token, TOKEN_IDENTIFIER))
		{
		    if (local)
			makeSqlTag (token, SQLTAG_LOCAL_VARIABLE);
		    else
			makeSqlTag (token, SQLTAG_VARIABLE);
		}
		break;
	}
	findToken (token, TOKEN_SEMICOLON);
	readToken (token);
    }
}

static void parseLabel (tokenInfo *const token)
{
    Assert (isType (token, TOKEN_BLOCK_LABEL_BEGIN));
    readToken (token);
    if (isType (token, TOKEN_IDENTIFIER))
    {
	makeSqlTag (token, SQLTAG_BLOCK_LABEL);
	readToken (token);        /* read end of label */
    }
}

static void parseStatements (tokenInfo *const token)
{
    do
    {
	if (isType (token, TOKEN_BLOCK_LABEL_BEGIN))
	    parseLabel (token);
	else
	{
	    switch (token->keyword)
	    {
		case KEYWORD_if:
		case KEYWORD_loop:
		    readToken (token);
		    parseStatements (token);
		    break;

		case KEYWORD_declare:
		case KEYWORD_begin:
		    parseBlock (token, TRUE);
		    break;

		default:
		    readToken (token);
		    break;
	    }
	    findToken (token, TOKEN_SEMICOLON);
	}
	readToken (token);
    } while (! isKeyword (token, KEYWORD_end));
}

static void parseBlock (tokenInfo *const token, const boolean local)
{
    if (isType (token, TOKEN_BLOCK_LABEL_BEGIN))
    {
	parseLabel (token);
	readToken (token);
    }
    if (! isKeyword (token, KEYWORD_begin))
	parseDeclare (token, local);
    if (isKeyword (token, KEYWORD_begin))
    {
	readToken (token);
	while (! isKeyword (token, KEYWORD_end))
	    parseStatements (token);
	findToken (token, TOKEN_SEMICOLON);
    }
}

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);
	readToken (token);
	parseBlock (token, FALSE);
    }
    findToken (token, TOKEN_SEMICOLON);
    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 parseSqlFile (tokenInfo *const token)
{
    do
    {
	readToken (token);
	if (isType (token, TOKEN_BLOCK_LABEL_BEGIN))
	    parseLabel (token);
	else switch (token->keyword)
	{
	    case KEYWORD_begin:     parseBlock (token, FALSE); break;
	    case KEYWORD_cursor:    parseSimple (token, SQLTAG_CURSOR); break;
	    case KEYWORD_declare:   parseBlock (token, FALSE); break;
	    case KEYWORD_function:  parseSubProgram (token); break;
	    case KEYWORD_package:   parsePackage (token); break;
	    case KEYWORD_procedure: parseSubProgram (token); break;
	    case KEYWORD_subtype:   parseSimple (token, SQLTAG_SUBTYPE); break;
	    case KEYWORD_table:     parseTable (token); break;
	    case KEYWORD_trigger:   parseSimple (token, SQLTAG_TRIGGER); break;
	    case KEYWORD_type:      parseType (token); break;
	    default:                break;
	}
    } while (! isKeyword (token, KEYWORD_end));
}

static void initialize (const langType language)
{
    Assert (sizeof (SqlKinds) / sizeof (SqlKinds [0]) == SQLTAG_COUNT);
    Lang_sql = language;
    buildSqlKeywordHash ();
}

static void findSqlTags (void)
{
    tokenInfo *const token = newToken ();
    exception_t exception = (exception_t) (setjmp (Exception));
    while (exception == ExceptionNone)
	parseSqlFile (token);
    deleteToken (token);
}

extern parserDefinition* SqlParser (void)
{
    static const char *const extensions [] = { "sql", NULL };
    parserDefinition* def = parserNew ("SQL");
    def->kinds      = SqlKinds;
    def->kindCount  = KIND_COUNT (SqlKinds);
    def->extensions = extensions;
    def->parser     = findSqlTags;
    def->initialize = initialize;
    return def;
}

/* vi:set tabstop=8 shiftwidth=4: */

⌨️ 快捷键说明

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