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