📄 sql.c
字号:
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 + -