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