xref: /Universal-ctags/parsers/eiffel.c (revision 14781660f5ef320b4f27fe28dbf3a87dc47481d3)
13ae02089SMasatake YAMATO /*
23ae02089SMasatake YAMATO *   Copyright (c) 1998-2002, Darren Hiebert
33ae02089SMasatake YAMATO *
43ae02089SMasatake YAMATO *   This source code is released for free distribution under the terms of the
50ce38835Sviccuad *   GNU General Public License version 2 or (at your option) any later version.
63ae02089SMasatake YAMATO *
73ae02089SMasatake YAMATO *   This module contains functions for generating tags for Eiffel language
83ae02089SMasatake YAMATO *   files.
93ae02089SMasatake YAMATO */
103ae02089SMasatake YAMATO 
113ae02089SMasatake YAMATO /*
123ae02089SMasatake YAMATO *   INCLUDE FILES
133ae02089SMasatake YAMATO */
143ae02089SMasatake YAMATO #include "general.h"  /* must always come first */
153ae02089SMasatake YAMATO 
163ae02089SMasatake YAMATO #include <string.h>
173ae02089SMasatake YAMATO #include <limits.h>
183ae02089SMasatake YAMATO #include <ctype.h>  /* to define tolower () */
193ae02089SMasatake YAMATO 
203ae02089SMasatake YAMATO #include "debug.h"
213ae02089SMasatake YAMATO #include "keyword.h"
223ae02089SMasatake YAMATO #include "routines.h"
233ae02089SMasatake YAMATO #include "vstring.h"
243ae02089SMasatake YAMATO #include "entry.h"
253ae02089SMasatake YAMATO #include "parse.h"
263ae02089SMasatake YAMATO #include "read.h"
2735c59e96SMasatake YAMATO #include "xtag.h"
283ae02089SMasatake YAMATO 
293ae02089SMasatake YAMATO /*
303ae02089SMasatake YAMATO *   MACROS
313ae02089SMasatake YAMATO */
323ae02089SMasatake YAMATO #define isident(c)            (isalnum(c) || (c) == '_')
333ae02089SMasatake YAMATO #define isFreeOperatorChar(c) ((c) == '@' || (c) == '#' || \
343ae02089SMasatake YAMATO                                (c) == '|' || (c) == '&')
35ce990805SThomas Braun #define isType(token,t)       (bool) ((token)->type == (t))
36ce990805SThomas Braun #define isKeyword(token,k)    (bool) ((token)->keyword == (k))
373ae02089SMasatake YAMATO 
383ae02089SMasatake YAMATO /*
393ae02089SMasatake YAMATO *   DATA DECLARATIONS
403ae02089SMasatake YAMATO */
413ae02089SMasatake YAMATO 
423ae02089SMasatake YAMATO /*  Used to specify type of keyword.
433ae02089SMasatake YAMATO  */
444faa2076SColomban Wendling enum eKeywordId {
4531fb7468SDoug Kearns 	KEYWORD_across,
4631fb7468SDoug Kearns 	KEYWORD_alias,
4731fb7468SDoug Kearns 	KEYWORD_all,
4831fb7468SDoug Kearns 	KEYWORD_and,
4931fb7468SDoug Kearns 	KEYWORD_as,
5031fb7468SDoug Kearns 	KEYWORD_assign,
5131fb7468SDoug Kearns 	KEYWORD_attached,
5261fa5d66SDoug Kearns 	KEYWORD_attribute,
5331fb7468SDoug Kearns 	KEYWORD_check,
5431fb7468SDoug Kearns 	KEYWORD_class,
5531fb7468SDoug Kearns 	KEYWORD_convert,
5631fb7468SDoug Kearns 	KEYWORD_create,
5731fb7468SDoug Kearns 	KEYWORD_creation,
5831fb7468SDoug Kearns 	KEYWORD_Current,
5931fb7468SDoug Kearns 	KEYWORD_debug,
6031fb7468SDoug Kearns 	KEYWORD_deferred,
6131fb7468SDoug Kearns 	KEYWORD_detachable,
6231fb7468SDoug Kearns 	KEYWORD_do,
6331fb7468SDoug Kearns 	KEYWORD_else,
6431fb7468SDoug Kearns 	KEYWORD_elseif,
6531fb7468SDoug Kearns 	KEYWORD_end,
6631fb7468SDoug Kearns 	KEYWORD_ensure,
6731fb7468SDoug Kearns 	KEYWORD_expanded,
6831fb7468SDoug Kearns 	KEYWORD_export,
6931fb7468SDoug Kearns 	KEYWORD_external,
7031fb7468SDoug Kearns 	KEYWORD_false,
7131fb7468SDoug Kearns 	KEYWORD_feature,
7231fb7468SDoug Kearns 	KEYWORD_from,
7331fb7468SDoug Kearns 	KEYWORD_frozen,
7431fb7468SDoug Kearns 	KEYWORD_if,
7531fb7468SDoug Kearns 	KEYWORD_implies,
7631fb7468SDoug Kearns 	KEYWORD_infix,
7731fb7468SDoug Kearns 	KEYWORD_inherit,
7831fb7468SDoug Kearns 	KEYWORD_inspect,
7931fb7468SDoug Kearns 	KEYWORD_invariant,
8031fb7468SDoug Kearns 	KEYWORD_is,
8131fb7468SDoug Kearns 	KEYWORD_like,
8231fb7468SDoug Kearns 	KEYWORD_local,
8331fb7468SDoug Kearns 	KEYWORD_loop,
8431fb7468SDoug Kearns 	KEYWORD_not,
853995772dSDoug Kearns 	KEYWORD_note,
8631fb7468SDoug Kearns 	KEYWORD_obsolete,
8731fb7468SDoug Kearns 	KEYWORD_old,
8831fb7468SDoug Kearns 	KEYWORD_once,
8931fb7468SDoug Kearns 	KEYWORD_or,
9031fb7468SDoug Kearns 	KEYWORD_prefix,
9131fb7468SDoug Kearns 	KEYWORD_redefine,
9231fb7468SDoug Kearns 	KEYWORD_rename,
9331fb7468SDoug Kearns 	KEYWORD_require,
9431fb7468SDoug Kearns 	KEYWORD_rescue,
9531fb7468SDoug Kearns 	KEYWORD_Result,
9631fb7468SDoug Kearns 	KEYWORD_retry,
9731fb7468SDoug Kearns 	KEYWORD_select,
9831fb7468SDoug Kearns 	KEYWORD_separate,
9931fb7468SDoug Kearns 	KEYWORD_strip,
10031fb7468SDoug Kearns 	KEYWORD_then,
10131fb7468SDoug Kearns 	KEYWORD_true,
10231fb7468SDoug Kearns 	KEYWORD_undefine,
10331fb7468SDoug Kearns 	KEYWORD_unique,
10431fb7468SDoug Kearns 	KEYWORD_until,
10531fb7468SDoug Kearns 	KEYWORD_variant,
10631fb7468SDoug Kearns 	KEYWORD_when,
10731fb7468SDoug Kearns 	KEYWORD_xor
1084faa2076SColomban Wendling };
1094faa2076SColomban Wendling typedef int keywordId; /* to allow KEYWORD_NONE */
1103ae02089SMasatake YAMATO 
1113ae02089SMasatake YAMATO typedef enum eTokenType {
112a46c1e65SColomban Wendling 	TOKEN_EOF,
1133ae02089SMasatake YAMATO 	TOKEN_UNDEFINED,
1143ae02089SMasatake YAMATO 	TOKEN_BANG,
1153ae02089SMasatake YAMATO 	TOKEN_CHARACTER,
1163ae02089SMasatake YAMATO 	TOKEN_CLOSE_BRACE,
1173ae02089SMasatake YAMATO 	TOKEN_CLOSE_BRACKET,
1183ae02089SMasatake YAMATO 	TOKEN_CLOSE_PAREN,
1193ae02089SMasatake YAMATO 	TOKEN_COLON,
1203ae02089SMasatake YAMATO 	TOKEN_COMMA,
1213ae02089SMasatake YAMATO 	TOKEN_CONSTRAINT,
1223ae02089SMasatake YAMATO 	TOKEN_DOT,
1233ae02089SMasatake YAMATO 	TOKEN_DOLLAR,
1243ae02089SMasatake YAMATO 	TOKEN_IDENTIFIER,
1253ae02089SMasatake YAMATO 	TOKEN_KEYWORD,
1263ae02089SMasatake YAMATO 	TOKEN_NUMERIC,
1273ae02089SMasatake YAMATO 	TOKEN_OPEN_BRACE,
1283ae02089SMasatake YAMATO 	TOKEN_OPEN_BRACKET,
1293ae02089SMasatake YAMATO 	TOKEN_OPEN_PAREN,
1303ae02089SMasatake YAMATO 	TOKEN_OPERATOR,
1313ae02089SMasatake YAMATO 	TOKEN_QUESTION,
1323ae02089SMasatake YAMATO 	TOKEN_SEMICOLON,
1333ae02089SMasatake YAMATO 	TOKEN_STRING,
1343ae02089SMasatake YAMATO 	TOKEN_TILDE
1353ae02089SMasatake YAMATO } tokenType;
1363ae02089SMasatake YAMATO 
1373ae02089SMasatake YAMATO typedef struct sTokenInfo {
1383ae02089SMasatake YAMATO 	tokenType type;
1393ae02089SMasatake YAMATO 	keywordId keyword;
140ce990805SThomas Braun 	bool   isExported;
1413ae02089SMasatake YAMATO 	vString*  string;
1423ae02089SMasatake YAMATO 	vString*  className;
1433ae02089SMasatake YAMATO 	vString*  featureName;
1443ae02089SMasatake YAMATO } tokenInfo;
1453ae02089SMasatake YAMATO 
1463ae02089SMasatake YAMATO /*
1473ae02089SMasatake YAMATO *   DATA DEFINITIONS
1483ae02089SMasatake YAMATO */
1493ae02089SMasatake YAMATO 
1503ae02089SMasatake YAMATO static langType Lang_eiffel;
1513ae02089SMasatake YAMATO 
1523ae02089SMasatake YAMATO typedef enum {
1533ae02089SMasatake YAMATO 	EKIND_CLASS, EKIND_FEATURE, EKIND_LOCAL, EKIND_QUALIFIED_TAGS
1543ae02089SMasatake YAMATO } eiffelKind;
1553ae02089SMasatake YAMATO 
156e112e8abSMasatake YAMATO static kindDefinition EiffelKinds [] = {
157ce990805SThomas Braun 	{ true,  'c', "class",   "classes"},
158ce990805SThomas Braun 	{ true,  'f', "feature", "features"},
159ce990805SThomas Braun 	{ false, 'l', "local",   "local entities"}
1603ae02089SMasatake YAMATO };
1613ae02089SMasatake YAMATO 
16282c11d8cSRich Siegel static const keywordTable EiffelKeywordTable [] = {
1633ae02089SMasatake YAMATO 	/* keyword          keyword ID */
16407a179deSDoug Kearns 	{ "across",         KEYWORD_across     },
1653ae02089SMasatake YAMATO 	{ "alias",          KEYWORD_alias      },
1663ae02089SMasatake YAMATO 	{ "all",            KEYWORD_all        },
1673ae02089SMasatake YAMATO 	{ "and",            KEYWORD_and        },
1683ae02089SMasatake YAMATO 	{ "as",             KEYWORD_as         },
1693ae02089SMasatake YAMATO 	{ "assign",         KEYWORD_assign     },
1703ae02089SMasatake YAMATO 	{ "attached",       KEYWORD_attached   },
17161fa5d66SDoug Kearns 	{ "attribute",      KEYWORD_attribute  },
1723ae02089SMasatake YAMATO 	{ "check",          KEYWORD_check      },
1733ae02089SMasatake YAMATO 	{ "class",          KEYWORD_class      },
1743ae02089SMasatake YAMATO 	{ "convert",        KEYWORD_convert    },
1753ae02089SMasatake YAMATO 	{ "create",         KEYWORD_create     },
1763ae02089SMasatake YAMATO 	{ "creation",       KEYWORD_creation   },
1773ae02089SMasatake YAMATO 	{ "current",        KEYWORD_Current    },
1783ae02089SMasatake YAMATO 	{ "debug",          KEYWORD_debug      },
1793ae02089SMasatake YAMATO 	{ "deferred",       KEYWORD_deferred   },
1803ae02089SMasatake YAMATO 	{ "detachable",     KEYWORD_detachable },
1813ae02089SMasatake YAMATO 	{ "do",             KEYWORD_do         },
1823ae02089SMasatake YAMATO 	{ "else",           KEYWORD_else       },
1833ae02089SMasatake YAMATO 	{ "elseif",         KEYWORD_elseif     },
1843ae02089SMasatake YAMATO 	{ "end",            KEYWORD_end        },
1853ae02089SMasatake YAMATO 	{ "ensure",         KEYWORD_ensure     },
1863ae02089SMasatake YAMATO 	{ "expanded",       KEYWORD_expanded   },
1873ae02089SMasatake YAMATO 	{ "export",         KEYWORD_export     },
1883ae02089SMasatake YAMATO 	{ "external",       KEYWORD_external   },
1893ae02089SMasatake YAMATO 	{ "false",          KEYWORD_false      },
1903ae02089SMasatake YAMATO 	{ "feature",        KEYWORD_feature    },
1913ae02089SMasatake YAMATO 	{ "from",           KEYWORD_from       },
1923ae02089SMasatake YAMATO 	{ "frozen",         KEYWORD_frozen     },
1933ae02089SMasatake YAMATO 	{ "if",             KEYWORD_if         },
1943ae02089SMasatake YAMATO 	{ "implies",        KEYWORD_implies    },
1953995772dSDoug Kearns 	{ "indexing",       KEYWORD_note       },
1963ae02089SMasatake YAMATO 	{ "infix",          KEYWORD_infix      },
1973ae02089SMasatake YAMATO 	{ "inherit",        KEYWORD_inherit    },
198ea95372fSDoug Kearns 	{ "insert",         KEYWORD_inherit    },
1993ae02089SMasatake YAMATO 	{ "inspect",        KEYWORD_inspect    },
2003ae02089SMasatake YAMATO 	{ "invariant",      KEYWORD_invariant  },
2013ae02089SMasatake YAMATO 	{ "is",             KEYWORD_is         },
2023ae02089SMasatake YAMATO 	{ "like",           KEYWORD_like       },
2033ae02089SMasatake YAMATO 	{ "local",          KEYWORD_local      },
2043ae02089SMasatake YAMATO 	{ "loop",           KEYWORD_loop       },
2053ae02089SMasatake YAMATO 	{ "not",            KEYWORD_not        },
2063995772dSDoug Kearns 	{ "note",           KEYWORD_note       },
2073ae02089SMasatake YAMATO 	{ "obsolete",       KEYWORD_obsolete   },
2083ae02089SMasatake YAMATO 	{ "old",            KEYWORD_old        },
2093ae02089SMasatake YAMATO 	{ "once",           KEYWORD_once       },
2103ae02089SMasatake YAMATO 	{ "or",             KEYWORD_or         },
2113ae02089SMasatake YAMATO 	{ "prefix",         KEYWORD_prefix     },
2123ae02089SMasatake YAMATO 	{ "redefine",       KEYWORD_redefine   },
2133ae02089SMasatake YAMATO 	{ "rename",         KEYWORD_rename     },
2143ae02089SMasatake YAMATO 	{ "require",        KEYWORD_require    },
2153ae02089SMasatake YAMATO 	{ "rescue",         KEYWORD_rescue     },
2163ae02089SMasatake YAMATO 	{ "result",         KEYWORD_Result     },
2173ae02089SMasatake YAMATO 	{ "retry",          KEYWORD_retry      },
2183ae02089SMasatake YAMATO 	{ "select",         KEYWORD_select     },
2193ae02089SMasatake YAMATO 	{ "separate",       KEYWORD_separate   },
2203ae02089SMasatake YAMATO 	{ "strip",          KEYWORD_strip      },
2213ae02089SMasatake YAMATO 	{ "then",           KEYWORD_then       },
2223ae02089SMasatake YAMATO 	{ "true",           KEYWORD_true       },
2233ae02089SMasatake YAMATO 	{ "undefine",       KEYWORD_undefine   },
2243ae02089SMasatake YAMATO 	{ "unique",         KEYWORD_unique     },
2253ae02089SMasatake YAMATO 	{ "until",          KEYWORD_until      },
2263ae02089SMasatake YAMATO 	{ "variant",        KEYWORD_variant    },
2273ae02089SMasatake YAMATO 	{ "when",           KEYWORD_when       },
2283ae02089SMasatake YAMATO 	{ "xor",            KEYWORD_xor        }
2293ae02089SMasatake YAMATO };
2303ae02089SMasatake YAMATO 
2313ae02089SMasatake YAMATO /*
2323ae02089SMasatake YAMATO *   FUNCTION DEFINITIONS
2333ae02089SMasatake YAMATO */
2343ae02089SMasatake YAMATO 
2353ae02089SMasatake YAMATO /*
2363ae02089SMasatake YAMATO *   Tag generation functions
2373ae02089SMasatake YAMATO */
2383ae02089SMasatake YAMATO 
makeEiffelClassTag(tokenInfo * const token)2393ae02089SMasatake YAMATO static void makeEiffelClassTag (tokenInfo *const token)
2403ae02089SMasatake YAMATO {
2413ae02089SMasatake YAMATO 	if (EiffelKinds [EKIND_CLASS].enabled)
2423ae02089SMasatake YAMATO 	{
2433ae02089SMasatake YAMATO 		const char *const name = vStringValue (token->string);
2443ae02089SMasatake YAMATO 		tagEntryInfo e;
2453ae02089SMasatake YAMATO 
24616a2541cSMasatake YAMATO 		initTagEntry (&e, name, EKIND_CLASS);
2473ae02089SMasatake YAMATO 
2483ae02089SMasatake YAMATO 		makeTagEntry (&e);
2493ae02089SMasatake YAMATO 	}
2503ae02089SMasatake YAMATO 	vStringCopy (token->className, token->string);
2513ae02089SMasatake YAMATO }
2523ae02089SMasatake YAMATO 
makeEiffelFeatureTag(tokenInfo * const token)2533ae02089SMasatake YAMATO static void makeEiffelFeatureTag (tokenInfo *const token)
2543ae02089SMasatake YAMATO {
2553ae02089SMasatake YAMATO 	if (EiffelKinds [EKIND_FEATURE].enabled  &&
25635c59e96SMasatake YAMATO 		(token->isExported  ||  isXtagEnabled(XTAG_FILE_SCOPE)))
2573ae02089SMasatake YAMATO 	{
2583ae02089SMasatake YAMATO 		const char *const name = vStringValue (token->string);
2593ae02089SMasatake YAMATO 		tagEntryInfo e;
2603ae02089SMasatake YAMATO 
26116a2541cSMasatake YAMATO 		initTagEntry (&e, name, EKIND_FEATURE);
2623ae02089SMasatake YAMATO 
263ce990805SThomas Braun 		e.isFileScope = (bool) (! token->isExported);
2643397ae72SMasatake YAMATO 		if (e.isFileScope)
2653397ae72SMasatake YAMATO 			markTagExtraBit (&e, XTAG_FILE_SCOPE);
266*f92e6bf2SMasatake YAMATO 		e.extensionFields.scopeKindIndex = EKIND_CLASS;
267015ab54cSMasatake YAMATO 		e.extensionFields.scopeName = vStringValue (token->className);
2683ae02089SMasatake YAMATO 
2693ae02089SMasatake YAMATO 		makeTagEntry (&e);
2703ae02089SMasatake YAMATO 
27135c59e96SMasatake YAMATO 		if (isXtagEnabled(XTAG_QUALIFIED_TAGS))
2723ae02089SMasatake YAMATO 		{
2733ae02089SMasatake YAMATO 			vString* qualified = vStringNewInit (vStringValue (token->className));
2743ae02089SMasatake YAMATO 			vStringPut (qualified, '.');
2753ae02089SMasatake YAMATO 			vStringCat (qualified, token->string);
2763ae02089SMasatake YAMATO 			e.name = vStringValue (qualified);
2775022e63aSMasatake YAMATO 			markTagExtraBit (&e, XTAG_QUALIFIED_TAGS);
2783ae02089SMasatake YAMATO 			makeTagEntry (&e);
2793ae02089SMasatake YAMATO 			vStringDelete (qualified);
2803ae02089SMasatake YAMATO 		}
2813ae02089SMasatake YAMATO 	}
2823ae02089SMasatake YAMATO 	vStringCopy (token->featureName, token->string);
2833ae02089SMasatake YAMATO }
2843ae02089SMasatake YAMATO 
makeEiffelLocalTag(tokenInfo * const token)2853ae02089SMasatake YAMATO static void makeEiffelLocalTag (tokenInfo *const token)
2863ae02089SMasatake YAMATO {
28735c59e96SMasatake YAMATO 	if (EiffelKinds [EKIND_LOCAL].enabled && isXtagEnabled(XTAG_FILE_SCOPE))
2883ae02089SMasatake YAMATO 	{
2893ae02089SMasatake YAMATO 		const char *const name = vStringValue (token->string);
2903ae02089SMasatake YAMATO 		vString* scope = vStringNew ();
2913ae02089SMasatake YAMATO 		tagEntryInfo e;
2923ae02089SMasatake YAMATO 
29316a2541cSMasatake YAMATO 		initTagEntry (&e, name, EKIND_LOCAL);
2943ae02089SMasatake YAMATO 
295ce990805SThomas Braun 		e.isFileScope = true;
2963397ae72SMasatake YAMATO 		markTagExtraBit (&e, XTAG_FILE_SCOPE);
2973ae02089SMasatake YAMATO 
2983ae02089SMasatake YAMATO 		vStringCopy (scope, token->className);
2993ae02089SMasatake YAMATO 		vStringPut (scope, '.');
3003ae02089SMasatake YAMATO 		vStringCat (scope, token->featureName);
3013ae02089SMasatake YAMATO 
302*f92e6bf2SMasatake YAMATO 		e.extensionFields.scopeKindIndex = EKIND_FEATURE;
303015ab54cSMasatake YAMATO 		e.extensionFields.scopeName = vStringValue (scope);
3043ae02089SMasatake YAMATO 
3053ae02089SMasatake YAMATO 		makeTagEntry (&e);
3063ae02089SMasatake YAMATO 		vStringDelete (scope);
3073ae02089SMasatake YAMATO 	}
3083ae02089SMasatake YAMATO }
3093ae02089SMasatake YAMATO 
3103ae02089SMasatake YAMATO /*
3113ae02089SMasatake YAMATO *   Parsing functions
3123ae02089SMasatake YAMATO */
3133ae02089SMasatake YAMATO 
skipToCharacter(const int c)3143ae02089SMasatake YAMATO static int skipToCharacter (const int c)
3153ae02089SMasatake YAMATO {
3163ae02089SMasatake YAMATO 	int d;
3173ae02089SMasatake YAMATO 
3183ae02089SMasatake YAMATO 	do
3193ae02089SMasatake YAMATO 	{
320018bce0bSMasatake YAMATO 		d = getcFromInputFile ();
3213ae02089SMasatake YAMATO 	} while (d != EOF  &&  d != c);
3223ae02089SMasatake YAMATO 
3233ae02089SMasatake YAMATO 	return d;
3243ae02089SMasatake YAMATO }
3253ae02089SMasatake YAMATO 
3263ae02089SMasatake YAMATO /*  If a numeric is passed in 'c', this is used as the first digit of the
3273ae02089SMasatake YAMATO  *  numeric being parsed.
3283ae02089SMasatake YAMATO  */
parseInteger(int c)3293ae02089SMasatake YAMATO static vString *parseInteger (int c)
3303ae02089SMasatake YAMATO {
3313ae02089SMasatake YAMATO 	vString *string = vStringNew ();
3323ae02089SMasatake YAMATO 
3333ae02089SMasatake YAMATO 	if (c == '\0')
334018bce0bSMasatake YAMATO 		c = getcFromInputFile ();
3353ae02089SMasatake YAMATO 	if (c == '-')
3363ae02089SMasatake YAMATO 	{
3373ae02089SMasatake YAMATO 		vStringPut (string, c);
338018bce0bSMasatake YAMATO 		c = getcFromInputFile ();
3393ae02089SMasatake YAMATO 	}
3403ae02089SMasatake YAMATO 	else if (! isdigit (c))
341018bce0bSMasatake YAMATO 		c = getcFromInputFile ();
3423ae02089SMasatake YAMATO 	while (c != EOF  &&  (isdigit (c)  ||  c == '_'))
3433ae02089SMasatake YAMATO 	{
3443ae02089SMasatake YAMATO 		vStringPut (string, c);
345018bce0bSMasatake YAMATO 		c = getcFromInputFile ();
3463ae02089SMasatake YAMATO 	}
34761f14fa5SMasatake YAMATO 	ungetcToInputFile (c);
3483ae02089SMasatake YAMATO 
3493ae02089SMasatake YAMATO 	return string;
3503ae02089SMasatake YAMATO }
3513ae02089SMasatake YAMATO 
parseNumeric(int c)3523ae02089SMasatake YAMATO static vString *parseNumeric (int c)
3533ae02089SMasatake YAMATO {
3543ae02089SMasatake YAMATO 	vString *string = vStringNew ();
3553ae02089SMasatake YAMATO 	vString *integer = parseInteger (c);
3563ae02089SMasatake YAMATO 	vStringCopy (string, integer);
3573ae02089SMasatake YAMATO 	vStringDelete (integer);
3583ae02089SMasatake YAMATO 
359018bce0bSMasatake YAMATO 	c = getcFromInputFile ();
3603ae02089SMasatake YAMATO 	if (c == '.')
3613ae02089SMasatake YAMATO 	{
3623ae02089SMasatake YAMATO 		integer = parseInteger ('\0');
3633ae02089SMasatake YAMATO 		vStringPut (string, c);
3643ae02089SMasatake YAMATO 		vStringCat (string, integer);
3653ae02089SMasatake YAMATO 		vStringDelete (integer);
366018bce0bSMasatake YAMATO 		c = getcFromInputFile ();
3673ae02089SMasatake YAMATO 	}
3683ae02089SMasatake YAMATO 	if (tolower (c) == 'e')
3693ae02089SMasatake YAMATO 	{
3703ae02089SMasatake YAMATO 		integer = parseInteger ('\0');
3713ae02089SMasatake YAMATO 		vStringPut (string, c);
3723ae02089SMasatake YAMATO 		vStringCat (string, integer);
3733ae02089SMasatake YAMATO 		vStringDelete (integer);
3743ae02089SMasatake YAMATO 	}
3753ae02089SMasatake YAMATO 	else if (!isspace (c))
37661f14fa5SMasatake YAMATO 		ungetcToInputFile (c);
3773ae02089SMasatake YAMATO 
3783ae02089SMasatake YAMATO 	return string;
3793ae02089SMasatake YAMATO }
3803ae02089SMasatake YAMATO 
parseEscapedCharacter(void)3813ae02089SMasatake YAMATO static int parseEscapedCharacter (void)
3823ae02089SMasatake YAMATO {
3833ae02089SMasatake YAMATO 	int d = '\0';
384018bce0bSMasatake YAMATO 	int c = getcFromInputFile ();
3853ae02089SMasatake YAMATO 
3863ae02089SMasatake YAMATO 	switch (c)
3873ae02089SMasatake YAMATO 	{
3883ae02089SMasatake YAMATO 		case 'A':  d = '@';   break;
3893ae02089SMasatake YAMATO 		case 'B':  d = '\b';  break;
3903ae02089SMasatake YAMATO 		case 'C':  d = '^';   break;
3913ae02089SMasatake YAMATO 		case 'D':  d = '$';   break;
3923ae02089SMasatake YAMATO 		case 'F':  d = '\f';  break;
3933ae02089SMasatake YAMATO 		case 'H':  d = '\\';  break;
3943ae02089SMasatake YAMATO 		case 'L':  d = '~';   break;
3953ae02089SMasatake YAMATO 		case 'N':  d = '\n';  break;
3963ae02089SMasatake YAMATO 		case 'Q':  d = '`';   break;
3973ae02089SMasatake YAMATO 		case 'R':  d = '\r';  break;
3983ae02089SMasatake YAMATO 		case 'S':  d = '#';   break;
3993ae02089SMasatake YAMATO 		case 'T':  d = '\t';  break;
4003ae02089SMasatake YAMATO 		case 'U':  d = '\0';  break;
4013ae02089SMasatake YAMATO 		case 'V':  d = '|';   break;
4023ae02089SMasatake YAMATO 		case '%':  d = '%';   break;
4033ae02089SMasatake YAMATO 		case '\'': d = '\'';  break;
4043ae02089SMasatake YAMATO 		case '"':  d = '"';   break;
4053ae02089SMasatake YAMATO 		case '(':  d = '[';   break;
4063ae02089SMasatake YAMATO 		case ')':  d = ']';   break;
4073ae02089SMasatake YAMATO 		case '<':  d = '{';   break;
4083ae02089SMasatake YAMATO 		case '>':  d = '}';   break;
4093ae02089SMasatake YAMATO 
4103ae02089SMasatake YAMATO 		case '\n': skipToCharacter ('%'); break;
4113ae02089SMasatake YAMATO 
4123ae02089SMasatake YAMATO 		case '/':
4133ae02089SMasatake YAMATO 		{
4143ae02089SMasatake YAMATO 			vString *string = parseInteger ('\0');
4153ae02089SMasatake YAMATO 			const char *value = vStringValue (string);
4163ae02089SMasatake YAMATO 			const unsigned long ascii = atol (value);
4173ae02089SMasatake YAMATO 			vStringDelete (string);
4183ae02089SMasatake YAMATO 
419018bce0bSMasatake YAMATO 			c = getcFromInputFile ();
4203ae02089SMasatake YAMATO 			if (c == '/'  &&  ascii < 256)
4213ae02089SMasatake YAMATO 				d = ascii;
4223ae02089SMasatake YAMATO 			break;
4233ae02089SMasatake YAMATO 		}
4243ae02089SMasatake YAMATO 
4253ae02089SMasatake YAMATO 		default: break;
4263ae02089SMasatake YAMATO 	}
4273ae02089SMasatake YAMATO 	return d;
4283ae02089SMasatake YAMATO }
4293ae02089SMasatake YAMATO 
parseCharacter(void)4303ae02089SMasatake YAMATO static int parseCharacter (void)
4313ae02089SMasatake YAMATO {
432018bce0bSMasatake YAMATO 	int c = getcFromInputFile ();
4333ae02089SMasatake YAMATO 	int result = c;
4343ae02089SMasatake YAMATO 
4353ae02089SMasatake YAMATO 	if (c == '%')
4363ae02089SMasatake YAMATO 		result = parseEscapedCharacter ();
4373ae02089SMasatake YAMATO 
438018bce0bSMasatake YAMATO 	c = getcFromInputFile ();
4393ae02089SMasatake YAMATO 	if (c != '\'')
4403ae02089SMasatake YAMATO 		skipToCharacter ('\n');
4413ae02089SMasatake YAMATO 
4423ae02089SMasatake YAMATO 	return result;
4433ae02089SMasatake YAMATO }
4443ae02089SMasatake YAMATO 
parseString(vString * const string)4453ae02089SMasatake YAMATO static void parseString (vString *const string)
4463ae02089SMasatake YAMATO {
447ce990805SThomas Braun 	bool verbatim = false;
448ce990805SThomas Braun 	bool align = false;
449ce990805SThomas Braun 	bool end = false;
4503ae02089SMasatake YAMATO 	vString *verbatimCloser = vStringNew ();
4513ae02089SMasatake YAMATO 	vString *lastLine = vStringNew ();
4523ae02089SMasatake YAMATO 	int prev = '\0';
4533ae02089SMasatake YAMATO 	int c;
4543ae02089SMasatake YAMATO 
4553ae02089SMasatake YAMATO 	while (! end)
4563ae02089SMasatake YAMATO 	{
457018bce0bSMasatake YAMATO 		c = getcFromInputFile ();
4583ae02089SMasatake YAMATO 		if (c == EOF)
459ce990805SThomas Braun 			end = true;
4603ae02089SMasatake YAMATO 		else if (c == '"')
4613ae02089SMasatake YAMATO 		{
4623ae02089SMasatake YAMATO 			if (! verbatim)
463ce990805SThomas Braun 				end = true;
4643ae02089SMasatake YAMATO 			else
465ce990805SThomas Braun 				end = (bool) (strcmp (vStringValue (lastLine),
4663ae02089SMasatake YAMATO 				                         vStringValue (verbatimCloser)) == 0);
4673ae02089SMasatake YAMATO 		}
4683ae02089SMasatake YAMATO 		else if (c == '\n')
4693ae02089SMasatake YAMATO 		{
4703ae02089SMasatake YAMATO 			if (verbatim)
4713ae02089SMasatake YAMATO 				vStringClear (lastLine);
4723ae02089SMasatake YAMATO 			if (prev == '[' /* ||  prev == '{' */)
4733ae02089SMasatake YAMATO 			{
474ce990805SThomas Braun 				verbatim = true;
4753ae02089SMasatake YAMATO 				vStringClear (verbatimCloser);
4763ae02089SMasatake YAMATO 				vStringClear (lastLine);
4773ae02089SMasatake YAMATO 				if (prev == '{')
4783ae02089SMasatake YAMATO 					vStringPut (verbatimCloser, '}');
4793ae02089SMasatake YAMATO 				else
4803ae02089SMasatake YAMATO 				{
4813ae02089SMasatake YAMATO 					vStringPut (verbatimCloser, ']');
482ce990805SThomas Braun 					align = true;
4833ae02089SMasatake YAMATO 				}
4843ae02089SMasatake YAMATO 				vStringNCat (verbatimCloser, string, vStringLength (string) - 1);
4853ae02089SMasatake YAMATO 				vStringClear (string);
4863ae02089SMasatake YAMATO 			}
4873ae02089SMasatake YAMATO 			if (verbatim && align)
4883ae02089SMasatake YAMATO 			{
4893ae02089SMasatake YAMATO 				do
490018bce0bSMasatake YAMATO 					c = getcFromInputFile ();
4913ae02089SMasatake YAMATO 				while (isspace (c));
4923ae02089SMasatake YAMATO 			}
4933ae02089SMasatake YAMATO 		}
4943ae02089SMasatake YAMATO 		else if (c == '%')
4953ae02089SMasatake YAMATO 			c = parseEscapedCharacter ();
4963ae02089SMasatake YAMATO 		if (! end)
4973ae02089SMasatake YAMATO 		{
4983ae02089SMasatake YAMATO 			vStringPut (string, c);
4993ae02089SMasatake YAMATO 			if (verbatim)
5003ae02089SMasatake YAMATO 				vStringPut (lastLine, c);
5013ae02089SMasatake YAMATO 			prev = c;
5023ae02089SMasatake YAMATO 		}
5033ae02089SMasatake YAMATO 	}
5043ae02089SMasatake YAMATO 	vStringDelete (lastLine);
5053ae02089SMasatake YAMATO 	vStringDelete (verbatimCloser);
5063ae02089SMasatake YAMATO }
5073ae02089SMasatake YAMATO 
5083ae02089SMasatake YAMATO /*  Read a C identifier beginning with "firstChar" and places it into "name".
5093ae02089SMasatake YAMATO  */
parseIdentifier(vString * const string,const int firstChar)5103ae02089SMasatake YAMATO static void parseIdentifier (vString *const string, const int firstChar)
5113ae02089SMasatake YAMATO {
5123ae02089SMasatake YAMATO 	int c = firstChar;
5133ae02089SMasatake YAMATO 
5143ae02089SMasatake YAMATO 	do
5153ae02089SMasatake YAMATO 	{
5163ae02089SMasatake YAMATO 		vStringPut (string, c);
517018bce0bSMasatake YAMATO 		c = getcFromInputFile ();
5183ae02089SMasatake YAMATO 	} while (isident (c));
5193ae02089SMasatake YAMATO 
5203ae02089SMasatake YAMATO 	if (!isspace (c))
52161f14fa5SMasatake YAMATO 		ungetcToInputFile (c);  /* unget non-identifier character */
5223ae02089SMasatake YAMATO }
5233ae02089SMasatake YAMATO 
parseFreeOperator(vString * const string,const int firstChar)5243ae02089SMasatake YAMATO static void parseFreeOperator (vString *const string, const int firstChar)
5253ae02089SMasatake YAMATO {
5263ae02089SMasatake YAMATO 	int c = firstChar;
5273ae02089SMasatake YAMATO 
5283ae02089SMasatake YAMATO 	do
5293ae02089SMasatake YAMATO 	{
5303ae02089SMasatake YAMATO 		vStringPut (string, c);
531018bce0bSMasatake YAMATO 		c = getcFromInputFile ();
5323ae02089SMasatake YAMATO 	} while (c > ' ');
5333ae02089SMasatake YAMATO 
5343ae02089SMasatake YAMATO 	if (!isspace (c))
53561f14fa5SMasatake YAMATO 		ungetcToInputFile (c);  /* unget non-identifier character */
5363ae02089SMasatake YAMATO }
5373ae02089SMasatake YAMATO 
copyToken(tokenInfo * dst,const tokenInfo * src)5383ae02089SMasatake YAMATO static void copyToken (tokenInfo* dst, const tokenInfo *src)
5393ae02089SMasatake YAMATO {
5403ae02089SMasatake YAMATO 	dst->type       = src->type;
5413ae02089SMasatake YAMATO 	dst->keyword    = src->keyword;
5423ae02089SMasatake YAMATO 	dst->isExported = src->isExported;
5433ae02089SMasatake YAMATO 
5443ae02089SMasatake YAMATO 	vStringCopy (dst->string, src->string);
5453ae02089SMasatake YAMATO 	vStringCopy (dst->className, src->className);
5463ae02089SMasatake YAMATO 	vStringCopy (dst->featureName, src->featureName);
5473ae02089SMasatake YAMATO }
5483ae02089SMasatake YAMATO 
newToken(void)5493ae02089SMasatake YAMATO static tokenInfo *newToken (void)
5503ae02089SMasatake YAMATO {
5513ae02089SMasatake YAMATO 	tokenInfo *const token = xMalloc (1, tokenInfo);
5523ae02089SMasatake YAMATO 
5533ae02089SMasatake YAMATO 	token->type			= TOKEN_UNDEFINED;
5543ae02089SMasatake YAMATO 	token->keyword		= KEYWORD_NONE;
555ce990805SThomas Braun 	token->isExported	= true;
5563ae02089SMasatake YAMATO 
5573ae02089SMasatake YAMATO 	token->string = vStringNew ();
5583ae02089SMasatake YAMATO 	token->className = vStringNew ();
5593ae02089SMasatake YAMATO 	token->featureName = vStringNew ();
5603ae02089SMasatake YAMATO 
5613ae02089SMasatake YAMATO 	return token;
5623ae02089SMasatake YAMATO }
5633ae02089SMasatake YAMATO 
deleteToken(tokenInfo * const token)5643ae02089SMasatake YAMATO static void deleteToken (tokenInfo *const token)
5653ae02089SMasatake YAMATO {
5663ae02089SMasatake YAMATO 	vStringDelete (token->string);
5673ae02089SMasatake YAMATO 	vStringDelete (token->className);
5683ae02089SMasatake YAMATO 	vStringDelete (token->featureName);
5693ae02089SMasatake YAMATO 
5703ae02089SMasatake YAMATO 	eFree (token);
5713ae02089SMasatake YAMATO }
5723ae02089SMasatake YAMATO 
readToken(tokenInfo * const token)5733ae02089SMasatake YAMATO static void readToken (tokenInfo *const token)
5743ae02089SMasatake YAMATO {
5753ae02089SMasatake YAMATO 	int c;
5763ae02089SMasatake YAMATO 
5773ae02089SMasatake YAMATO 	token->type    = TOKEN_UNDEFINED;
5783ae02089SMasatake YAMATO 	token->keyword = KEYWORD_NONE;
5793ae02089SMasatake YAMATO 	vStringClear (token->string);
5803ae02089SMasatake YAMATO 
5813ae02089SMasatake YAMATO getNextChar:
5823ae02089SMasatake YAMATO 
5833ae02089SMasatake YAMATO 	do
584018bce0bSMasatake YAMATO 		c = getcFromInputFile ();
5853ae02089SMasatake YAMATO 	while (c == '\t'  ||  c == ' '  ||  c == '\n');
5863ae02089SMasatake YAMATO 
5873ae02089SMasatake YAMATO 	switch (c)
5883ae02089SMasatake YAMATO 	{
589a46c1e65SColomban Wendling 		case EOF:  token->type = TOKEN_EOF;                break;
5903ae02089SMasatake YAMATO 		case ';':  token->type = TOKEN_SEMICOLON;          break;
5913ae02089SMasatake YAMATO 		case '!':  token->type = TOKEN_BANG;               break;
5923ae02089SMasatake YAMATO 		case '}':  token->type = TOKEN_CLOSE_BRACE;        break;
5933ae02089SMasatake YAMATO 		case ']':  token->type = TOKEN_CLOSE_BRACKET;      break;
5943ae02089SMasatake YAMATO 		case ')':  token->type = TOKEN_CLOSE_PAREN;        break;
5953ae02089SMasatake YAMATO 		case ',':  token->type = TOKEN_COMMA;              break;
5963ae02089SMasatake YAMATO 		case '$':  token->type = TOKEN_DOLLAR;             break;
5973ae02089SMasatake YAMATO 		case '.':  token->type = TOKEN_DOT;                break;
5983ae02089SMasatake YAMATO 		case '{':  token->type = TOKEN_OPEN_BRACE;         break;
5993ae02089SMasatake YAMATO 		case '[':  token->type = TOKEN_OPEN_BRACKET;       break;
6003ae02089SMasatake YAMATO 		case '(':  token->type = TOKEN_OPEN_PAREN;         break;
6013ae02089SMasatake YAMATO 		case '~':  token->type = TOKEN_TILDE;              break;
6023ae02089SMasatake YAMATO 
6033ae02089SMasatake YAMATO 
6043ae02089SMasatake YAMATO 		case '+':
6053ae02089SMasatake YAMATO 		case '*':
6063ae02089SMasatake YAMATO 		case '^':
6073ae02089SMasatake YAMATO 		case '=':  token->type = TOKEN_OPERATOR;           break;
6083ae02089SMasatake YAMATO 
6093ae02089SMasatake YAMATO 		case '-':
610018bce0bSMasatake YAMATO 			c = getcFromInputFile ();
6113ae02089SMasatake YAMATO 			if (c == '>')
6123ae02089SMasatake YAMATO 				token->type = TOKEN_CONSTRAINT;
6133ae02089SMasatake YAMATO 			else if (c == '-')  /* is this the start of a comment? */
6143ae02089SMasatake YAMATO 			{
6153ae02089SMasatake YAMATO 				skipToCharacter ('\n');
6163ae02089SMasatake YAMATO 				goto getNextChar;
6173ae02089SMasatake YAMATO 			}
6183ae02089SMasatake YAMATO 			else
6193ae02089SMasatake YAMATO 			{
6203ae02089SMasatake YAMATO 				if (!isspace (c))
62161f14fa5SMasatake YAMATO 					ungetcToInputFile (c);
6223ae02089SMasatake YAMATO 				token->type = TOKEN_OPERATOR;
6233ae02089SMasatake YAMATO 			}
6243ae02089SMasatake YAMATO 			break;
6253ae02089SMasatake YAMATO 
6263ae02089SMasatake YAMATO 		case '?':
6273ae02089SMasatake YAMATO 		case ':':
6283ae02089SMasatake YAMATO 		{
629018bce0bSMasatake YAMATO 			int c2 = getcFromInputFile ();
6303ae02089SMasatake YAMATO 			if (c2 == '=')
6313ae02089SMasatake YAMATO 				token->type = TOKEN_OPERATOR;
6323ae02089SMasatake YAMATO 			else
6333ae02089SMasatake YAMATO 			{
6343ae02089SMasatake YAMATO 				if (!isspace (c2))
63561f14fa5SMasatake YAMATO 					ungetcToInputFile (c2);
6363ae02089SMasatake YAMATO 				if (c == ':')
6373ae02089SMasatake YAMATO 					token->type = TOKEN_COLON;
6383ae02089SMasatake YAMATO 				else
6393ae02089SMasatake YAMATO 					token->type = TOKEN_QUESTION;
6403ae02089SMasatake YAMATO 			}
6413ae02089SMasatake YAMATO 			break;
6423ae02089SMasatake YAMATO 		}
6433ae02089SMasatake YAMATO 
6443ae02089SMasatake YAMATO 		case '<':
645018bce0bSMasatake YAMATO 			c = getcFromInputFile ();
6463ae02089SMasatake YAMATO 			if (c != '='  &&  c != '>'  &&  !isspace (c))
64761f14fa5SMasatake YAMATO 				ungetcToInputFile (c);
6483ae02089SMasatake YAMATO 			token->type = TOKEN_OPERATOR;
6493ae02089SMasatake YAMATO 			break;
6503ae02089SMasatake YAMATO 
6513ae02089SMasatake YAMATO 		case '>':
652018bce0bSMasatake YAMATO 			c = getcFromInputFile ();
6533ae02089SMasatake YAMATO 			if (c != '='  &&  c != '>'  &&  !isspace (c))
65461f14fa5SMasatake YAMATO 				ungetcToInputFile (c);
6553ae02089SMasatake YAMATO 			token->type = TOKEN_OPERATOR;
6563ae02089SMasatake YAMATO 			break;
6573ae02089SMasatake YAMATO 
6583ae02089SMasatake YAMATO 		case '/':
659018bce0bSMasatake YAMATO 			c = getcFromInputFile ();
6603ae02089SMasatake YAMATO 			if (c != '/'  &&  c != '='  &&  !isspace (c))
66161f14fa5SMasatake YAMATO 				ungetcToInputFile (c);
6623ae02089SMasatake YAMATO 			token->type = TOKEN_OPERATOR;
6633ae02089SMasatake YAMATO 			break;
6643ae02089SMasatake YAMATO 
6653ae02089SMasatake YAMATO 		case '\\':
666018bce0bSMasatake YAMATO 			c = getcFromInputFile ();
6673ae02089SMasatake YAMATO 			if (c != '\\'  &&  !isspace (c))
66861f14fa5SMasatake YAMATO 				ungetcToInputFile (c);
6693ae02089SMasatake YAMATO 			token->type = TOKEN_OPERATOR;
6703ae02089SMasatake YAMATO 			break;
6713ae02089SMasatake YAMATO 
6723ae02089SMasatake YAMATO 		case '"':
6733ae02089SMasatake YAMATO 			token->type = TOKEN_STRING;
6743ae02089SMasatake YAMATO 			parseString (token->string);
6753ae02089SMasatake YAMATO 			break;
6763ae02089SMasatake YAMATO 
6773ae02089SMasatake YAMATO 		case '\'':
6783ae02089SMasatake YAMATO 			token->type = TOKEN_CHARACTER;
6793ae02089SMasatake YAMATO 			parseCharacter ();
6803ae02089SMasatake YAMATO 			break;
6813ae02089SMasatake YAMATO 
6823ae02089SMasatake YAMATO 		default:
6833ae02089SMasatake YAMATO 			if (isalpha (c))
6843ae02089SMasatake YAMATO 			{
6853ae02089SMasatake YAMATO 				parseIdentifier (token->string, c);
68631a85388SJiří Techet 				token->keyword = lookupCaseKeyword (vStringValue (token->string), Lang_eiffel);
6873ae02089SMasatake YAMATO 				if (isKeyword (token, KEYWORD_NONE))
6883ae02089SMasatake YAMATO 					token->type = TOKEN_IDENTIFIER;
6893ae02089SMasatake YAMATO 				else
6903ae02089SMasatake YAMATO 					token->type = TOKEN_KEYWORD;
6913ae02089SMasatake YAMATO 			}
6923ae02089SMasatake YAMATO 			else if (isdigit (c))
6933ae02089SMasatake YAMATO 			{
6943ae02089SMasatake YAMATO 				vString* numeric = parseNumeric (c);
6953ae02089SMasatake YAMATO 				vStringCat (token->string, numeric);
6963ae02089SMasatake YAMATO 				vStringDelete (numeric);
6973ae02089SMasatake YAMATO 				token->type = TOKEN_NUMERIC;
6983ae02089SMasatake YAMATO 			}
6993ae02089SMasatake YAMATO 			else if (isFreeOperatorChar (c))
7003ae02089SMasatake YAMATO 			{
7013ae02089SMasatake YAMATO 				parseFreeOperator (token->string, c);
7023ae02089SMasatake YAMATO 				token->type = TOKEN_OPERATOR;
7033ae02089SMasatake YAMATO 			}
7043ae02089SMasatake YAMATO 			else
7053ae02089SMasatake YAMATO 				token->type = TOKEN_UNDEFINED;
7063ae02089SMasatake YAMATO 			break;
7073ae02089SMasatake YAMATO 	}
7083ae02089SMasatake YAMATO }
7093ae02089SMasatake YAMATO 
7103ae02089SMasatake YAMATO /*
7113ae02089SMasatake YAMATO *   Scanning functions
7123ae02089SMasatake YAMATO */
7133ae02089SMasatake YAMATO 
isIdentifierMatch(const tokenInfo * const token,const char * const name)714ce990805SThomas Braun static bool isIdentifierMatch (
7153ae02089SMasatake YAMATO 		const tokenInfo *const token, const char *const name)
7163ae02089SMasatake YAMATO {
717ce990805SThomas Braun 	return (bool) (isType (token, TOKEN_IDENTIFIER)  &&
7183ae02089SMasatake YAMATO 		strcasecmp (vStringValue (token->string), name) == 0);
7193ae02089SMasatake YAMATO }
7203ae02089SMasatake YAMATO 
findToken(tokenInfo * const token,const tokenType type)721ce990805SThomas Braun static bool findToken (tokenInfo *const token, const tokenType type)
7223ae02089SMasatake YAMATO {
723a46c1e65SColomban Wendling 	while (! isType (token, type) && ! isType (token, TOKEN_EOF))
7243ae02089SMasatake YAMATO 		readToken (token);
725a46c1e65SColomban Wendling 	return isType (token, type);
7263ae02089SMasatake YAMATO }
7273ae02089SMasatake YAMATO 
findKeyword(tokenInfo * const token,const keywordId keyword)728ce990805SThomas Braun static bool findKeyword (tokenInfo *const token, const keywordId keyword)
7293ae02089SMasatake YAMATO {
730a46c1e65SColomban Wendling 	while (! isKeyword (token, keyword) && ! isType (token, TOKEN_EOF))
7313ae02089SMasatake YAMATO 		readToken (token);
732a46c1e65SColomban Wendling 	return isKeyword (token, keyword);
7333ae02089SMasatake YAMATO }
7343ae02089SMasatake YAMATO 
735ce990805SThomas Braun static bool parseType (tokenInfo *const token);
7363ae02089SMasatake YAMATO 
parseGeneric(tokenInfo * const token,bool declaration CTAGS_ATTR_UNUSED)737ce990805SThomas Braun static void parseGeneric (tokenInfo *const token, bool declaration CTAGS_ATTR_UNUSED)
7383ae02089SMasatake YAMATO {
7393ae02089SMasatake YAMATO 	unsigned int depth = 0;
7404c3dba54SMasatake YAMATO 
7413ae02089SMasatake YAMATO 	Assert (isType (token, TOKEN_OPEN_BRACKET));
7423ae02089SMasatake YAMATO 	do
7433ae02089SMasatake YAMATO 	{
7443ae02089SMasatake YAMATO 		if (isType (token, TOKEN_OPEN_BRACKET))
7453ae02089SMasatake YAMATO 		{
7463ae02089SMasatake YAMATO 			++depth;
7473ae02089SMasatake YAMATO 			readToken (token);
7483ae02089SMasatake YAMATO 		}
7493ae02089SMasatake YAMATO 		else if (isType (token, TOKEN_CLOSE_BRACKET))
7503ae02089SMasatake YAMATO 		{
7513ae02089SMasatake YAMATO 			--depth;
7523ae02089SMasatake YAMATO 			readToken (token);
7533ae02089SMasatake YAMATO 		}
7543ae02089SMasatake YAMATO 		else
7553ae02089SMasatake YAMATO 			parseType (token);
756a46c1e65SColomban Wendling 	} while (depth > 0 && ! isType (token, TOKEN_EOF));
7573ae02089SMasatake YAMATO }
7583ae02089SMasatake YAMATO 
parseType(tokenInfo * const token)759ce990805SThomas Braun static bool parseType (tokenInfo *const token)
7603ae02089SMasatake YAMATO {
7613ae02089SMasatake YAMATO 	tokenInfo* const id = newToken ();
7623ae02089SMasatake YAMATO 	copyToken (id, token);
7633ae02089SMasatake YAMATO 	readToken (token);
7643ae02089SMasatake YAMATO 	if (isType (token, TOKEN_COLON))  /* check for "{entity: TYPE}" */
7653ae02089SMasatake YAMATO 	{
7663ae02089SMasatake YAMATO 		readToken (id);
7673ae02089SMasatake YAMATO 		readToken (token);
7683ae02089SMasatake YAMATO 	}
7693ae02089SMasatake YAMATO 	if (isKeyword (id, KEYWORD_like))
7703ae02089SMasatake YAMATO 	{
7713ae02089SMasatake YAMATO 		if (isType (token, TOKEN_IDENTIFIER) ||
7723ae02089SMasatake YAMATO 				isKeyword (token, KEYWORD_Current))
7733ae02089SMasatake YAMATO 			readToken (token);
7743ae02089SMasatake YAMATO 	}
7753ae02089SMasatake YAMATO 	else
7763ae02089SMasatake YAMATO 	{
7773ae02089SMasatake YAMATO 		if (isKeyword (id, KEYWORD_attached) ||
7783ae02089SMasatake YAMATO 		    isKeyword (id, KEYWORD_detachable) ||
7793ae02089SMasatake YAMATO 		    isKeyword (id, KEYWORD_expanded))
7803ae02089SMasatake YAMATO 		{
7813ae02089SMasatake YAMATO 			copyToken (id, token);
7823ae02089SMasatake YAMATO 			readToken (token);
7833ae02089SMasatake YAMATO 		}
7843ae02089SMasatake YAMATO 		if (isType (id, TOKEN_IDENTIFIER))
7853ae02089SMasatake YAMATO 		{
7863ae02089SMasatake YAMATO 			if (isType (token, TOKEN_OPEN_BRACKET))
787ce990805SThomas Braun 				parseGeneric (token, false);
7883ae02089SMasatake YAMATO 			else if ((strcmp ("BIT", vStringValue (id->string)) == 0))
7893ae02089SMasatake YAMATO 				readToken (token);  /* read token after number of bits */
7903ae02089SMasatake YAMATO 		}
7913ae02089SMasatake YAMATO 	}
7923ae02089SMasatake YAMATO 	deleteToken (id);
793ce990805SThomas Braun 	return true;
7943ae02089SMasatake YAMATO }
7953ae02089SMasatake YAMATO 
parseEntityType(tokenInfo * const token)7963ae02089SMasatake YAMATO static void parseEntityType (tokenInfo *const token)
7973ae02089SMasatake YAMATO {
7983ae02089SMasatake YAMATO 	Assert (isType (token, TOKEN_COLON));
7993ae02089SMasatake YAMATO 	readToken (token);
8003ae02089SMasatake YAMATO 
8013ae02089SMasatake YAMATO 	if (isType (token, TOKEN_BANG) || isType (token, TOKEN_QUESTION))
8023ae02089SMasatake YAMATO 		readToken (token);  /* skip over '!' or '?' */
8033ae02089SMasatake YAMATO 	parseType (token);
8043ae02089SMasatake YAMATO }
8053ae02089SMasatake YAMATO 
parseLocal(tokenInfo * const token)8063ae02089SMasatake YAMATO static void parseLocal (tokenInfo *const token)
8073ae02089SMasatake YAMATO {
8083ae02089SMasatake YAMATO 	Assert (isKeyword (token, KEYWORD_local));
8093ae02089SMasatake YAMATO 	readToken (token);
8103ae02089SMasatake YAMATO 
8113ae02089SMasatake YAMATO 	/*  Check keyword first in case local clause is empty
8123ae02089SMasatake YAMATO 	 */
8133ae02089SMasatake YAMATO 	while (! isKeyword (token, KEYWORD_do)  &&
814a46c1e65SColomban Wendling 		   ! isKeyword (token, KEYWORD_once) &&
81561fa5d66SDoug Kearns 		   ! isKeyword (token, KEYWORD_attribute) &&
816a46c1e65SColomban Wendling 		   ! isType (token, TOKEN_EOF))
8173ae02089SMasatake YAMATO 	{
8183ae02089SMasatake YAMATO 		if (isType (token, TOKEN_IDENTIFIER))
8193ae02089SMasatake YAMATO 			makeEiffelLocalTag (token);
8203ae02089SMasatake YAMATO 		readToken (token);
8213ae02089SMasatake YAMATO 		if (isType (token, TOKEN_COLON))
8223ae02089SMasatake YAMATO 			parseEntityType (token);
8233ae02089SMasatake YAMATO 	}
8243ae02089SMasatake YAMATO }
8253ae02089SMasatake YAMATO 
findFeatureEnd(tokenInfo * const token)8263ae02089SMasatake YAMATO static void findFeatureEnd (tokenInfo *const token)
8273ae02089SMasatake YAMATO {
828ce990805SThomas Braun 	bool isFound = isKeyword (token, KEYWORD_is);
8293ae02089SMasatake YAMATO 	if (isFound)
8303ae02089SMasatake YAMATO 		readToken (token);
8313ae02089SMasatake YAMATO 	switch (token->keyword)
8323ae02089SMasatake YAMATO 	{
83361fa5d66SDoug Kearns 		case KEYWORD_attribute:
8343ae02089SMasatake YAMATO 		case KEYWORD_deferred:
8353ae02089SMasatake YAMATO 		case KEYWORD_do:
8363ae02089SMasatake YAMATO 		case KEYWORD_external:
8373ae02089SMasatake YAMATO 		case KEYWORD_local:
8383995772dSDoug Kearns 		case KEYWORD_note:
8393ae02089SMasatake YAMATO 		case KEYWORD_obsolete:
8403ae02089SMasatake YAMATO 		case KEYWORD_once:
8413ae02089SMasatake YAMATO 		case KEYWORD_require:
8423ae02089SMasatake YAMATO 		{
8433ae02089SMasatake YAMATO 			int depth = 1;
8443ae02089SMasatake YAMATO 
845a46c1e65SColomban Wendling 			while (depth > 0 && ! isType (token, TOKEN_EOF))
8463ae02089SMasatake YAMATO 			{
8473ae02089SMasatake YAMATO 				switch (token->keyword)
8483ae02089SMasatake YAMATO 				{
8493ae02089SMasatake YAMATO 					case KEYWORD_check:
8503ae02089SMasatake YAMATO 					case KEYWORD_debug:
8513ae02089SMasatake YAMATO 					case KEYWORD_from:
85207a179deSDoug Kearns 					case KEYWORD_across:
8533ae02089SMasatake YAMATO 					case KEYWORD_if:
8543ae02089SMasatake YAMATO 					case KEYWORD_inspect:
8553ae02089SMasatake YAMATO 						++depth;
8563ae02089SMasatake YAMATO 						break;
8573ae02089SMasatake YAMATO 
8583ae02089SMasatake YAMATO 					case KEYWORD_local:
8593ae02089SMasatake YAMATO 						parseLocal (token);
8603ae02089SMasatake YAMATO 						break;
8613ae02089SMasatake YAMATO 
8623ae02089SMasatake YAMATO 					case KEYWORD_end:
8633ae02089SMasatake YAMATO 						--depth;
8643ae02089SMasatake YAMATO 						break;
8653ae02089SMasatake YAMATO 
8663ae02089SMasatake YAMATO 					default:
8673ae02089SMasatake YAMATO 						break;
8683ae02089SMasatake YAMATO 				}
8693ae02089SMasatake YAMATO 				readToken (token);
8703ae02089SMasatake YAMATO 			}
8713ae02089SMasatake YAMATO 			break;
8723ae02089SMasatake YAMATO 		}
8733ae02089SMasatake YAMATO 
8743ae02089SMasatake YAMATO 		default:
8753ae02089SMasatake YAMATO 			/* is this a manifest constant? */
8763ae02089SMasatake YAMATO 			if (isFound || isType (token, TOKEN_OPERATOR)) {
8773ae02089SMasatake YAMATO 				if (isType (token, TOKEN_OPERATOR))
8783ae02089SMasatake YAMATO 					readToken (token);
8793ae02089SMasatake YAMATO 				readToken (token);
8803ae02089SMasatake YAMATO 			}
8813ae02089SMasatake YAMATO 			break;
8823ae02089SMasatake YAMATO 	}
8833ae02089SMasatake YAMATO }
8843ae02089SMasatake YAMATO 
readFeatureName(tokenInfo * const token)885ce990805SThomas Braun static bool readFeatureName (tokenInfo *const token)
8863ae02089SMasatake YAMATO {
887ce990805SThomas Braun 	bool isFeatureName = false;
8883ae02089SMasatake YAMATO 
8893ae02089SMasatake YAMATO 	if (isKeyword (token, KEYWORD_frozen))
8903ae02089SMasatake YAMATO 		readToken (token);
8913ae02089SMasatake YAMATO 	if (isType (token, TOKEN_IDENTIFIER))
892ce990805SThomas Braun 		isFeatureName = true;
8933ae02089SMasatake YAMATO 	else if (isKeyword (token, KEYWORD_assign))  /* legacy code */
894ce990805SThomas Braun 		isFeatureName = true;
8953ae02089SMasatake YAMATO 	else if (isKeyword (token, KEYWORD_infix)  ||
8963ae02089SMasatake YAMATO 			isKeyword (token, KEYWORD_prefix))
8973ae02089SMasatake YAMATO 	{
8983ae02089SMasatake YAMATO 		readToken (token);
8993ae02089SMasatake YAMATO 		if (isType (token, TOKEN_STRING))
900ce990805SThomas Braun 			isFeatureName = true;
9013ae02089SMasatake YAMATO 	}
9023ae02089SMasatake YAMATO 	return isFeatureName;
9033ae02089SMasatake YAMATO }
9043ae02089SMasatake YAMATO 
parseArguments(tokenInfo * const token)9053ae02089SMasatake YAMATO static void parseArguments (tokenInfo *const token)
9063ae02089SMasatake YAMATO {
907a46c1e65SColomban Wendling 	if (findToken (token, TOKEN_CLOSE_PAREN))
9083ae02089SMasatake YAMATO 		readToken (token);
9093ae02089SMasatake YAMATO }
9103ae02089SMasatake YAMATO 
parseFeature(tokenInfo * const token)911ce990805SThomas Braun static bool parseFeature (tokenInfo *const token)
9123ae02089SMasatake YAMATO {
913ce990805SThomas Braun 	bool found = false;
9143ae02089SMasatake YAMATO 	while (readFeatureName (token))
9153ae02089SMasatake YAMATO 	{
916ce990805SThomas Braun 		found = true;
9173ae02089SMasatake YAMATO 		makeEiffelFeatureTag (token);
9183ae02089SMasatake YAMATO 		readToken (token);
9193ae02089SMasatake YAMATO 		if (isType (token, TOKEN_COMMA))
9203ae02089SMasatake YAMATO 			readToken (token);
9213ae02089SMasatake YAMATO 	}
9223ae02089SMasatake YAMATO 	if (found)
9233ae02089SMasatake YAMATO 	{
9243ae02089SMasatake YAMATO 		if (isKeyword (token, KEYWORD_alias)) {
9253ae02089SMasatake YAMATO 			readToken (token);
9263ae02089SMasatake YAMATO 			if (isType (token, TOKEN_STRING))
9273ae02089SMasatake YAMATO 				makeEiffelFeatureTag (token);
9283ae02089SMasatake YAMATO 			readToken (token);
9293ae02089SMasatake YAMATO 		}
9303ae02089SMasatake YAMATO 		if (isType (token, TOKEN_OPEN_PAREN))  /* arguments? */
9313ae02089SMasatake YAMATO 			parseArguments (token);
9323ae02089SMasatake YAMATO 		if (isType (token, TOKEN_COLON))       /* a query? */
9333ae02089SMasatake YAMATO 			parseEntityType (token);
9343ae02089SMasatake YAMATO 		if (isKeyword (token, KEYWORD_assign))
9353ae02089SMasatake YAMATO 		{
9363ae02089SMasatake YAMATO 			readToken (token);
9373ae02089SMasatake YAMATO 			readToken (token);
9383ae02089SMasatake YAMATO 		}
9393ae02089SMasatake YAMATO 		if (isKeyword (token, KEYWORD_obsolete))
9403ae02089SMasatake YAMATO 		{
9413ae02089SMasatake YAMATO 			readToken (token);
9423ae02089SMasatake YAMATO 			if (isType (token, TOKEN_STRING))
9433ae02089SMasatake YAMATO 				readToken (token);
9443ae02089SMasatake YAMATO 		}
9453ae02089SMasatake YAMATO 		findFeatureEnd (token);
9463ae02089SMasatake YAMATO 	}
9473ae02089SMasatake YAMATO 	return found;
9483ae02089SMasatake YAMATO }
9493ae02089SMasatake YAMATO 
parseExport(tokenInfo * const token)9503ae02089SMasatake YAMATO static void parseExport (tokenInfo *const token)
9513ae02089SMasatake YAMATO {
952ce990805SThomas Braun 	token->isExported = true;
9533ae02089SMasatake YAMATO 	readToken (token);
9543ae02089SMasatake YAMATO 	if (isType (token, TOKEN_OPEN_BRACE))
9553ae02089SMasatake YAMATO 	{
956ce990805SThomas Braun 		token->isExported = false;
957a46c1e65SColomban Wendling 		while (! isType (token, TOKEN_CLOSE_BRACE) &&
958a46c1e65SColomban Wendling 		       ! isType (token, TOKEN_EOF))
9593ae02089SMasatake YAMATO 		{
9603ae02089SMasatake YAMATO 			if (isType (token, TOKEN_IDENTIFIER))
9613ae02089SMasatake YAMATO 				token->isExported |= !isIdentifierMatch (token, "NONE");
9623ae02089SMasatake YAMATO 			readToken (token);
9633ae02089SMasatake YAMATO 		}
9643ae02089SMasatake YAMATO 		readToken (token);
9653ae02089SMasatake YAMATO 	}
9663ae02089SMasatake YAMATO }
9673ae02089SMasatake YAMATO 
parseFeatureClauses(tokenInfo * const token)9683ae02089SMasatake YAMATO static void parseFeatureClauses (tokenInfo *const token)
9693ae02089SMasatake YAMATO {
9703ae02089SMasatake YAMATO 	Assert (isKeyword (token, KEYWORD_feature));
9713ae02089SMasatake YAMATO 	do
9723ae02089SMasatake YAMATO 	{
9733ae02089SMasatake YAMATO 		if (isKeyword (token, KEYWORD_feature))
9743ae02089SMasatake YAMATO 			parseExport (token);
9753ae02089SMasatake YAMATO 		if (! isKeyword (token, KEYWORD_feature) &&
9763ae02089SMasatake YAMATO 			! isKeyword (token, KEYWORD_invariant) &&
9773995772dSDoug Kearns 			! isKeyword (token, KEYWORD_note))
9783ae02089SMasatake YAMATO 		{
9793ae02089SMasatake YAMATO 			if (! parseFeature (token))
9803ae02089SMasatake YAMATO 				readToken (token);
9813ae02089SMasatake YAMATO 		}
9823ae02089SMasatake YAMATO 	} while (! isKeyword (token, KEYWORD_end) &&
9833ae02089SMasatake YAMATO 			 ! isKeyword (token, KEYWORD_invariant) &&
9843995772dSDoug Kearns 			 ! isKeyword (token, KEYWORD_note) &&
985a46c1e65SColomban Wendling 			 ! isType (token, TOKEN_EOF));
9863ae02089SMasatake YAMATO }
9873ae02089SMasatake YAMATO 
parseRename(tokenInfo * const token)9883ae02089SMasatake YAMATO static void parseRename (tokenInfo *const token)
9893ae02089SMasatake YAMATO {
9903ae02089SMasatake YAMATO 	Assert (isKeyword (token, KEYWORD_rename));
9913ae02089SMasatake YAMATO 	do {
9923ae02089SMasatake YAMATO 		readToken (token);
9933ae02089SMasatake YAMATO 		if (readFeatureName (token))
9943ae02089SMasatake YAMATO 		{
9953ae02089SMasatake YAMATO 			readToken (token);
9963ae02089SMasatake YAMATO 			if (isKeyword (token, KEYWORD_as))
9973ae02089SMasatake YAMATO 			{
9983ae02089SMasatake YAMATO 				readToken (token);
9993ae02089SMasatake YAMATO 				if (readFeatureName (token))
10003ae02089SMasatake YAMATO 				{
10013ae02089SMasatake YAMATO 					makeEiffelFeatureTag (token);  /* renamed feature */
10023ae02089SMasatake YAMATO 					readToken (token);
10033ae02089SMasatake YAMATO 				}
10043ae02089SMasatake YAMATO 			}
10053ae02089SMasatake YAMATO 		}
10063ae02089SMasatake YAMATO 	} while (isType (token, TOKEN_COMMA));
10073ae02089SMasatake YAMATO }
10083ae02089SMasatake YAMATO 
parseInherit(tokenInfo * const token)10093ae02089SMasatake YAMATO static void parseInherit (tokenInfo *const token)
10103ae02089SMasatake YAMATO {
10113ae02089SMasatake YAMATO 	Assert (isKeyword (token, KEYWORD_inherit));
10123ae02089SMasatake YAMATO 	readToken (token);
10133ae02089SMasatake YAMATO 	while (isType (token, TOKEN_IDENTIFIER))
10143ae02089SMasatake YAMATO 	{
10153ae02089SMasatake YAMATO 		parseType (token);
10163ae02089SMasatake YAMATO 		if (isType (token, TOKEN_KEYWORD))
10173ae02089SMasatake YAMATO 		{
10183ae02089SMasatake YAMATO 			switch (token->keyword)  /* check for feature adaptation */
10193ae02089SMasatake YAMATO 			{
10203ae02089SMasatake YAMATO 				case KEYWORD_rename:
10213ae02089SMasatake YAMATO 					parseRename (token);
10223ae02089SMasatake YAMATO 				case KEYWORD_export:
10233ae02089SMasatake YAMATO 				case KEYWORD_undefine:
10243ae02089SMasatake YAMATO 				case KEYWORD_redefine:
10253ae02089SMasatake YAMATO 				case KEYWORD_select:
1026a46c1e65SColomban Wendling 					if (findKeyword (token, KEYWORD_end))
10273ae02089SMasatake YAMATO 						readToken (token);
10283ae02089SMasatake YAMATO 					break;
10293ae02089SMasatake YAMATO 
10303ae02089SMasatake YAMATO 				case KEYWORD_end:
10313ae02089SMasatake YAMATO 					readToken (token);
10323ae02089SMasatake YAMATO 					break;
10333ae02089SMasatake YAMATO 
10343ae02089SMasatake YAMATO 				default: break;
10353ae02089SMasatake YAMATO 			}
10363ae02089SMasatake YAMATO 		}
10373ae02089SMasatake YAMATO 		if (isType (token, TOKEN_SEMICOLON))
10383ae02089SMasatake YAMATO 			readToken (token);
10393ae02089SMasatake YAMATO 	}
10403ae02089SMasatake YAMATO }
10413ae02089SMasatake YAMATO 
parseConvert(tokenInfo * const token)10423ae02089SMasatake YAMATO static void parseConvert (tokenInfo *const token)
10433ae02089SMasatake YAMATO {
10443ae02089SMasatake YAMATO 	Assert (isKeyword (token, KEYWORD_convert));
10453ae02089SMasatake YAMATO 	do
10463ae02089SMasatake YAMATO 	{
10473ae02089SMasatake YAMATO 		readToken (token);
10483ae02089SMasatake YAMATO 		if (! isType (token, TOKEN_IDENTIFIER))
10493ae02089SMasatake YAMATO 			break;
10503ae02089SMasatake YAMATO 		else if (isType (token, TOKEN_OPEN_PAREN))
10513ae02089SMasatake YAMATO 		{
1052a46c1e65SColomban Wendling 			while (! isType (token, TOKEN_CLOSE_PAREN) &&
1053a46c1e65SColomban Wendling 			       ! isType (token, TOKEN_EOF))
10543ae02089SMasatake YAMATO 				readToken (token);
10553ae02089SMasatake YAMATO 		}
10563ae02089SMasatake YAMATO 		else if (isType (token, TOKEN_COLON))
10573ae02089SMasatake YAMATO 		{
10583ae02089SMasatake YAMATO 			readToken (token);
10593ae02089SMasatake YAMATO 			if (! isType (token, TOKEN_OPEN_BRACE))
10603ae02089SMasatake YAMATO 				break;
10613ae02089SMasatake YAMATO 			else while (! isType (token, TOKEN_CLOSE_BRACE))
10623ae02089SMasatake YAMATO 				readToken (token);
10633ae02089SMasatake YAMATO 		}
10643ae02089SMasatake YAMATO 	} while (isType (token, TOKEN_COMMA));
10653ae02089SMasatake YAMATO }
10663ae02089SMasatake YAMATO 
parseClass(tokenInfo * const token)10673ae02089SMasatake YAMATO static void parseClass (tokenInfo *const token)
10683ae02089SMasatake YAMATO {
10693ae02089SMasatake YAMATO 	Assert (isKeyword (token, KEYWORD_class));
10703ae02089SMasatake YAMATO 	readToken (token);
10713ae02089SMasatake YAMATO 	if (isType (token, TOKEN_IDENTIFIER))
10723ae02089SMasatake YAMATO 	{
10733ae02089SMasatake YAMATO 		makeEiffelClassTag (token);
10743ae02089SMasatake YAMATO 		readToken (token);
10753ae02089SMasatake YAMATO 	}
10763ae02089SMasatake YAMATO 
10773ae02089SMasatake YAMATO 	do
10783ae02089SMasatake YAMATO 	{
10793ae02089SMasatake YAMATO 		if (isType (token, TOKEN_OPEN_BRACKET))
1080ce990805SThomas Braun 			parseGeneric (token, true);
10813ae02089SMasatake YAMATO 		else if (! isType (token, TOKEN_KEYWORD))
10823ae02089SMasatake YAMATO 			readToken (token);
10833ae02089SMasatake YAMATO 		else switch (token->keyword)
10843ae02089SMasatake YAMATO 		{
10853ae02089SMasatake YAMATO 			case KEYWORD_inherit:  parseInherit (token);        break;
10863ae02089SMasatake YAMATO 			case KEYWORD_feature:  parseFeatureClauses (token); break;
10873ae02089SMasatake YAMATO 			case KEYWORD_convert:  parseConvert (token);        break;
10883ae02089SMasatake YAMATO 			default:               readToken (token);           break;
10893ae02089SMasatake YAMATO 		}
1090a46c1e65SColomban Wendling 	} while (! isKeyword (token, KEYWORD_end) &&
1091a46c1e65SColomban Wendling 	         ! isType (token, TOKEN_EOF));
10923ae02089SMasatake YAMATO }
10933ae02089SMasatake YAMATO 
initialize(const langType language)10943ae02089SMasatake YAMATO static void initialize (const langType language)
10953ae02089SMasatake YAMATO {
10963ae02089SMasatake YAMATO 	Lang_eiffel = language;
10973ae02089SMasatake YAMATO }
10983ae02089SMasatake YAMATO 
findEiffelTags(void)10993ae02089SMasatake YAMATO static void findEiffelTags (void)
11003ae02089SMasatake YAMATO {
11013ae02089SMasatake YAMATO 	tokenInfo *const token = newToken ();
11023ae02089SMasatake YAMATO 
1103a46c1e65SColomban Wendling 	while (findKeyword (token, KEYWORD_class))
11043ae02089SMasatake YAMATO 		parseClass (token);
11053ae02089SMasatake YAMATO 	deleteToken (token);
11063ae02089SMasatake YAMATO }
11073ae02089SMasatake YAMATO 
EiffelParser(void)11083ae02089SMasatake YAMATO extern parserDefinition* EiffelParser (void)
11093ae02089SMasatake YAMATO {
11103ae02089SMasatake YAMATO 	static const char *const extensions [] = { "e", NULL };
11113ae02089SMasatake YAMATO 	parserDefinition* def = parserNew ("Eiffel");
111209ae690fSMasatake YAMATO 	def->kindTable      = EiffelKinds;
11133db72c21SMasatake YAMATO 	def->kindCount  = ARRAY_SIZE (EiffelKinds);
11143ae02089SMasatake YAMATO 	def->extensions = extensions;
11153ae02089SMasatake YAMATO 	def->parser     = findEiffelTags;
11163ae02089SMasatake YAMATO 	def->initialize = initialize;
1117c379c5d2SMasatake YAMATO 	def->keywordTable = EiffelKeywordTable;
11183db72c21SMasatake YAMATO 	def->keywordCount = ARRAY_SIZE (EiffelKeywordTable);
11193ae02089SMasatake YAMATO 	return def;
11203ae02089SMasatake YAMATO }
1121