eiffel.c

来自「Exuberant Ctags is a multilanguage reimp」· C语言 代码 · 共 1,320 行 · 第 1/2 页

C
1,320
字号
				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);				}				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);		vStringUpper (token->className);		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 int 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);	}	else	{		findReferences ();		fclose (File);	}	return 0;}#endif/* vi:set tabstop=4 shiftwidth=4: */

⌨️ 快捷键说明

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