📄 eiffel.c
字号:
{ 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); } }}static void findFeatureEnd (tokenInfo *const token){ readToken (token); switch (token->keyword) { default: if (isType (token, TOKEN_OPERATOR)) /* sign of manifest constant */ readToken (token); readToken (token); /* skip to next token after constant */ break; case KEYWORD_deferred: case KEYWORD_do: case KEYWORD_external: case KEYWORD_local: case KEYWORD_obsolete: case KEYWORD_once: case KEYWORD_require: { int depth = 1; while (depth > 0) {#ifdef TYPE_REFERENCE_TOOL if (isType (token, TOKEN_OPEN_BRACE)) { readToken (token); if (isType (token, TOKEN_IDENTIFIER)) parseType (token); if (isType (token, TOKEN_CLOSE_BRACE)) readToken (token); } else if (isType (token, TOKEN_BANG)) { readToken (token); if (isType (token, TOKEN_IDENTIFIER)) parseType (token); if (isType (token, TOKEN_BANG)) readToken (token); } else#endif switch (token->keyword) { case KEYWORD_check: case KEYWORD_debug: case KEYWORD_from: case KEYWORD_if: case KEYWORD_inspect: ++depth; break; case KEYWORD_local: parseLocal (token); break; case KEYWORD_end: --depth; break; default: break; } readToken (token); } break; } }}static boolean readFeatureName (tokenInfo *const token){ boolean isFeatureName = FALSE; if (isKeyword (token, KEYWORD_frozen)) readToken (token); if (isType (token, TOKEN_IDENTIFIER)) isFeatureName = TRUE; else if (isKeyword (token, KEYWORD_infix) || isKeyword (token, KEYWORD_prefix)) { readToken (token); if (isType (token, TOKEN_STRING)) isFeatureName = TRUE; } return isFeatureName;}static void parseArguments (tokenInfo *const token){#ifndef TYPE_REFERENCE_TOOL findToken (token, TOKEN_CLOSE_PAREN); readToken (token);#else Assert (isType (token, TOKEN_OPEN_PAREN)); readToken (token); do { if (! isType (token, TOKEN_COLON)) readToken (token); else { readToken (token); if (isType (token, TOKEN_IDENTIFIER)) parseType (token); } } while (! isType (token, TOKEN_CLOSE_PAREN)); readToken (token);#endif}static boolean parseFeature (tokenInfo *const token){ boolean found = FALSE; while (readFeatureName (token)) { found = TRUE;#ifndef TYPE_REFERENCE_TOOL makeEiffelFeatureTag (token);#endif readToken (token); if (isType (token, TOKEN_COMMA)) readToken (token); } if (found) { if (isType (token, TOKEN_OPEN_PAREN)) /* arguments? */ parseArguments (token); if (isType (token, TOKEN_COLON)) /* a query? */ parseEntityType (token); if (isKeyword (token, KEYWORD_obsolete)) { readToken (token); if (isType (token, TOKEN_STRING)) readToken (token); } if (isKeyword (token, KEYWORD_is)) findFeatureEnd (token); } return found;}static void parseExport (tokenInfo *const token){ token->isExported = TRUE; readToken (token); if (isType (token, TOKEN_OPEN_BRACE)) { token->isExported = FALSE; while (! isType (token, TOKEN_CLOSE_BRACE)) { if (isType (token, TOKEN_IDENTIFIER)) token->isExported |= !isIdentifierMatch (token, "NONE"); readToken (token); } readToken (token); }}static void parseFeatureClauses (tokenInfo *const token){ Assert (isKeyword (token, KEYWORD_feature)); do { if (isKeyword (token, KEYWORD_feature)) parseExport (token); if (! isKeyword (token, KEYWORD_feature) && ! isKeyword (token, KEYWORD_invariant) && ! isKeyword (token, KEYWORD_indexing)) { if (! parseFeature (token)) readToken (token); } } while (! isKeyword (token, KEYWORD_end) && ! isKeyword (token, KEYWORD_invariant) && ! isKeyword (token, KEYWORD_indexing));}static void parseRename (tokenInfo *const token){ do { readToken (token); if (readFeatureName (token)) { readToken (token); if (isKeyword (token, KEYWORD_as)) { readToken (token); if (readFeatureName (token)) {#ifndef TYPE_REFERENCE_TOOL makeEiffelFeatureTag (token); /* renamed feature */#endif readToken (token); } } } } while (isType (token, TOKEN_COMMA)); findKeyword (token, KEYWORD_end); readToken (token);}static void parseInherit (tokenInfo *const token){ Assert (isKeyword (token, KEYWORD_inherit));#ifdef TYPE_REFERENCE_TOOL readToken (token); while (isType (token, TOKEN_IDENTIFIER)) { parseType (token); if (isType (token, TOKEN_KEYWORD)) { switch (token->keyword) /* check for feature adaptation */ { case KEYWORD_rename: case KEYWORD_export: case KEYWORD_undefine: case KEYWORD_redefine: case KEYWORD_select: findKeyword (token, KEYWORD_end); readToken (token); default: break; } } }#else readToken (token); while (isType (token, TOKEN_IDENTIFIER)) { parseType (token); switch (token->keyword) /* check for feature adaptation */ { case KEYWORD_rename: parseRename (token); if (isKeyword (token, KEYWORD_end)) readToken (token); break; case KEYWORD_export: case KEYWORD_undefine: case KEYWORD_redefine: case KEYWORD_select: findKeyword (token, KEYWORD_end); readToken (token); break; case KEYWORD_end: readToken (token); break; default: break; } }#endif}static void parseClass (tokenInfo *const token){ Assert (isKeyword (token, KEYWORD_class)); readToken (token); if (isType (token, TOKEN_IDENTIFIER)) {#ifndef TYPE_REFERENCE_TOOL makeEiffelClassTag (token); readToken (token);#else vStringCopy (token->className, token->string); if (PrintClass) puts (vStringValue (token->className)); if (! PrintReferences) exit (0); readToken (token);#endif } do { if (isType (token, TOKEN_OPEN_BRACKET)) parseGeneric (token, TRUE); else if (! isType (token, TOKEN_KEYWORD)) readToken (token); else switch (token->keyword) { case KEYWORD_inherit: parseInherit (token); break; case KEYWORD_feature: parseFeatureClauses (token); break; default: readToken (token); break; } } while (! isKeyword (token, KEYWORD_end));}static tokenInfo *newToken (void){ tokenInfo *const token = xMalloc (1, tokenInfo); token->type = TOKEN_UNDEFINED; token->keyword = KEYWORD_NONE; token->isExported = TRUE; token->string = vStringNew (); token->className = vStringNew (); token->featureName = vStringNew (); return token;}static void deleteToken (tokenInfo *const token){ vStringDelete (token->string); vStringDelete (token->className); vStringDelete (token->featureName); eFree (token);}static void initialize (const langType language){ Lang_eiffel = language; buildEiffelKeywordHash ();}static void findEiffelTags (void){ tokenInfo *const token = newToken (); exception_t exception; exception = (exception_t) (setjmp (Exception)); while (exception == ExceptionNone) { findKeyword (token, KEYWORD_class); parseClass (token); } deleteToken (token);}#ifndef TYPE_REFERENCE_TOOLextern parserDefinition* EiffelParser (void){ static const char *const extensions [] = { "e", NULL }; parserDefinition* def = parserNew ("Eiffel"); def->kinds = EiffelKinds; def->kindCount = KIND_COUNT (EiffelKinds); def->extensions = extensions; def->parser = findEiffelTags; def->initialize = initialize; return def;}#elsestatic void findReferences (void){ ReferencedTypes = stringListNew (); GenericNames = stringListNew (); initialize (0); findEiffelTags (); stringListDelete (GenericNames); GenericNames = NULL; stringListDelete (ReferencedTypes); ReferencedTypes = NULL;}static const char *const Usage = "Prints names of types referenced by an Eiffel language file.\n" "\n" "Usage: %s [-cdrs] [file_name | -]\n" "\n" "Options:\n" " -c Print class name of current file (on first line of output).\n" " -d Enable debug output.\n" " -r Print types referenced by current file (default unless -c).\n" " -s Include self-references.\n" "\n";extern main (int argc, char** argv){ int i; for (i = 1 ; argv [i] != NULL ; ++i) { const char *const arg = argv [i]; if (arg [0] == '-') { int j; if (arg [1] == '\0') { File = stdin; FileName = "stdin"; } else for (j = 1 ; arg [j] != '\0' ; ++j) switch (arg [j]) { case 'c': PrintClass = 1; break; case 'r': PrintReferences = 1; break; case 's': SelfReferences = 1; break; case 'd': Debug = 1; break; default: fprintf (errout, "%s: unknown option: %c\n", argv [0], arg [1]); fprintf (errout, Usage, argv [0]); exit (1); break; } } else if (File != NULL) { fprintf (errout, Usage, argv [0]); exit (1); } else { FileName = arg; File = fopen (FileName, "r"); if (File == NULL) { perror (argv [0]); exit (1); } } } if (! PrintClass) PrintReferences = 1; if (File == NULL) { fprintf (errout, Usage, argv [0]); exit (1); } findReferences ();}#endif/* vi:set tabstop=8 shiftwidth=4: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -