13ae02089SMasatake YAMATO /*
293c4b724Sviccuad * This source code is released for free distribution under the terms of the
30ce38835Sviccuad * GNU General Public License version 2 or (at your option) any later version.
493c4b724Sviccuad *
523e3161cSMasatake YAMATO * Reference:
623e3161cSMasatake YAMATO * https://golang.org/ref/spec
723e3161cSMasatake YAMATO */
823e3161cSMasatake YAMATO
923e3161cSMasatake YAMATO
1023e3161cSMasatake YAMATO /*
113ae02089SMasatake YAMATO * INCLUDE FILES
123ae02089SMasatake YAMATO */
133ae02089SMasatake YAMATO #include "general.h" /* must always come first */
143ae02089SMasatake YAMATO
153ae02089SMasatake YAMATO #include "debug.h"
163ae02089SMasatake YAMATO #include "entry.h"
173ae02089SMasatake YAMATO #include "keyword.h"
183ae02089SMasatake YAMATO #include "read.h"
192232a75eSMasatake YAMATO #include "numarray.h"
206cbb2243SMasatake YAMATO #include "objpool.h"
210d502ef0SMasatake YAMATO #include "parse.h"
223ae02089SMasatake YAMATO #include "routines.h"
233ae02089SMasatake YAMATO #include "vstring.h"
2435c59e96SMasatake YAMATO #include "xtag.h"
25d153b5a9SMasatake YAMATO #include "field.h"
26c49999e5SMasatake YAMATO #include "htable.h"
27d153b5a9SMasatake YAMATO
28d153b5a9SMasatake YAMATO #include <string.h>
293ae02089SMasatake YAMATO
303ae02089SMasatake YAMATO /*
313ae02089SMasatake YAMATO * MACROS
323ae02089SMasatake YAMATO */
33be658b95SMasatake YAMATO #define MAX_COLLECTOR_LENGTH 512
34ce990805SThomas Braun #define isType(token,t) (bool) ((token)->type == (t))
35ce990805SThomas Braun #define isKeyword(token,k) (bool) ((token)->keyword == (k))
362b28d0e0SJiří Techet #define isStartIdentChar(c) (isalpha (c) || (c) == '_' || (c) > 128) /* XXX UTF-8 */
372b28d0e0SJiří Techet #define isIdentChar(c) (isStartIdentChar (c) || isdigit (c))
386cbb2243SMasatake YAMATO #define newToken() (objPoolGet (TokenPool))
396cbb2243SMasatake YAMATO #define deleteToken(t) (objPoolPut (TokenPool, (t)))
403ae02089SMasatake YAMATO
413ae02089SMasatake YAMATO /*
423ae02089SMasatake YAMATO * DATA DECLARATIONS
433ae02089SMasatake YAMATO */
443ae02089SMasatake YAMATO
454faa2076SColomban Wendling enum eKeywordId {
463ae02089SMasatake YAMATO KEYWORD_package,
473ae02089SMasatake YAMATO KEYWORD_import,
483ae02089SMasatake YAMATO KEYWORD_const,
493ae02089SMasatake YAMATO KEYWORD_type,
503ae02089SMasatake YAMATO KEYWORD_var,
513ae02089SMasatake YAMATO KEYWORD_func,
523ae02089SMasatake YAMATO KEYWORD_struct,
533ae02089SMasatake YAMATO KEYWORD_interface,
543ae02089SMasatake YAMATO KEYWORD_map,
553ae02089SMasatake YAMATO KEYWORD_chan
564faa2076SColomban Wendling };
574faa2076SColomban Wendling typedef int keywordId; /* to allow KEYWORD_NONE */
583ae02089SMasatake YAMATO
593ae02089SMasatake YAMATO typedef enum eTokenType {
603ae02089SMasatake YAMATO TOKEN_NONE = -1,
613ae02089SMasatake YAMATO // Token not important for top-level Go parsing
623ae02089SMasatake YAMATO TOKEN_OTHER,
633ae02089SMasatake YAMATO TOKEN_KEYWORD,
643ae02089SMasatake YAMATO TOKEN_IDENTIFIER,
653ae02089SMasatake YAMATO TOKEN_STRING,
663ae02089SMasatake YAMATO TOKEN_OPEN_PAREN,
673ae02089SMasatake YAMATO TOKEN_CLOSE_PAREN,
683ae02089SMasatake YAMATO TOKEN_OPEN_CURLY,
693ae02089SMasatake YAMATO TOKEN_CLOSE_CURLY,
703ae02089SMasatake YAMATO TOKEN_OPEN_SQUARE,
713ae02089SMasatake YAMATO TOKEN_CLOSE_SQUARE,
723ae02089SMasatake YAMATO TOKEN_SEMICOLON,
733ae02089SMasatake YAMATO TOKEN_STAR,
743ae02089SMasatake YAMATO TOKEN_LEFT_ARROW,
753ae02089SMasatake YAMATO TOKEN_DOT,
763ae02089SMasatake YAMATO TOKEN_COMMA,
7721c1aeedSMasatake YAMATO TOKEN_EQUAL,
78903997b9SMasatake YAMATO TOKEN_3DOTS,
793ae02089SMasatake YAMATO TOKEN_EOF
803ae02089SMasatake YAMATO } tokenType;
813ae02089SMasatake YAMATO
823ae02089SMasatake YAMATO typedef struct sTokenInfo {
833ae02089SMasatake YAMATO tokenType type;
843ae02089SMasatake YAMATO keywordId keyword;
853ae02089SMasatake YAMATO vString *string; /* the name of the token */
863ae02089SMasatake YAMATO unsigned long lineNumber; /* line number of tag */
87509a47dbSJiří Techet MIOPos filePosition; /* file position of line containing name */
889de7b977SMasatake YAMATO int c; /* Used in AppendTokenToVString */
893ae02089SMasatake YAMATO } tokenInfo;
903ae02089SMasatake YAMATO
912235f9b5SMasatake YAMATO typedef struct sCollector {
922235f9b5SMasatake YAMATO vString *str;
932235f9b5SMasatake YAMATO size_t last_len;
942235f9b5SMasatake YAMATO } collector;
952235f9b5SMasatake YAMATO
963ae02089SMasatake YAMATO /*
973ae02089SMasatake YAMATO * DATA DEFINITIONS
983ae02089SMasatake YAMATO */
993ae02089SMasatake YAMATO
1003ae02089SMasatake YAMATO static int Lang_go;
1016cbb2243SMasatake YAMATO static objPool *TokenPool = NULL;
1023ae02089SMasatake YAMATO
1033ae02089SMasatake YAMATO typedef enum {
1043ae02089SMasatake YAMATO GOTAG_UNDEFINED = -1,
1053ae02089SMasatake YAMATO GOTAG_PACKAGE,
1063ae02089SMasatake YAMATO GOTAG_FUNCTION,
1073ae02089SMasatake YAMATO GOTAG_CONST,
1083ae02089SMasatake YAMATO GOTAG_TYPE,
1093ae02089SMasatake YAMATO GOTAG_VAR,
110d5bc0fc5SJiří Techet GOTAG_STRUCT,
111d5bc0fc5SJiří Techet GOTAG_INTERFACE,
112563bf975SMasatake YAMATO GOTAG_MEMBER,
11353140b39SMasatake YAMATO GOTAG_ANONMEMBER,
114ced34385SMasatake YAMATO GOTAG_METHODSPEC,
115563bf975SMasatake YAMATO GOTAG_UNKNOWN,
116d153b5a9SMasatake YAMATO GOTAG_PACKAGE_NAME,
11749db5ecfSMasatake YAMATO GOTAG_TALIAS,
1185a8e67d7SMasatake YAMATO GOTAG_RECEIVER,
1193ae02089SMasatake YAMATO } goKind;
1203ae02089SMasatake YAMATO
121563bf975SMasatake YAMATO typedef enum {
122d153b5a9SMasatake YAMATO R_GOTAG_PACKAGE_IMPORTED,
123d153b5a9SMasatake YAMATO } GoPackageRole;
124d153b5a9SMasatake YAMATO
125d153b5a9SMasatake YAMATO static roleDefinition GoPackageRoles [] = {
126d153b5a9SMasatake YAMATO { true, "imported", "imported package" },
127d153b5a9SMasatake YAMATO };
128d153b5a9SMasatake YAMATO
129d153b5a9SMasatake YAMATO typedef enum {
130563bf975SMasatake YAMATO R_GOTAG_UNKNOWN_RECEIVER,
131563bf975SMasatake YAMATO } GoUnknownRole;
132563bf975SMasatake YAMATO
13313457258SMasatake YAMATO static roleDefinition GoUnknownRoles [] = {
134563bf975SMasatake YAMATO { true, "receiverType", "receiver type" },
135563bf975SMasatake YAMATO };
136563bf975SMasatake YAMATO
137e112e8abSMasatake YAMATO static kindDefinition GoKinds[] = {
138d153b5a9SMasatake YAMATO {true, 'p', "package", "packages",
139d153b5a9SMasatake YAMATO .referenceOnly = false, ATTACH_ROLES (GoPackageRoles)},
140ce990805SThomas Braun {true, 'f', "func", "functions"},
141ce990805SThomas Braun {true, 'c', "const", "constants"},
142ce990805SThomas Braun {true, 't', "type", "types"},
143ce990805SThomas Braun {true, 'v', "var", "variables"},
144ce990805SThomas Braun {true, 's', "struct", "structs"},
145ce990805SThomas Braun {true, 'i', "interface", "interfaces"},
146563bf975SMasatake YAMATO {true, 'm', "member", "struct members"},
14753140b39SMasatake YAMATO {true, 'M', "anonMember", "struct anonymous members"},
148ced34385SMasatake YAMATO {true, 'n', "methodSpec", "interface method specification"},
149563bf975SMasatake YAMATO {true, 'u', "unknown", "unknown",
15065031e09SMasatake YAMATO .referenceOnly = true, ATTACH_ROLES (GoUnknownRoles)},
151d153b5a9SMasatake YAMATO {true, 'P', "packageName", "name for specifying imported package"},
15221c1aeedSMasatake YAMATO {true, 'a', "talias", "type aliases"},
1535a8e67d7SMasatake YAMATO {false,'R', "receiver", "receivers"},
1543ae02089SMasatake YAMATO };
1553ae02089SMasatake YAMATO
15682c11d8cSRich Siegel static const keywordTable GoKeywordTable[] = {
1573ae02089SMasatake YAMATO {"package", KEYWORD_package},
1583ae02089SMasatake YAMATO {"import", KEYWORD_import},
1593ae02089SMasatake YAMATO {"const", KEYWORD_const},
1603ae02089SMasatake YAMATO {"type", KEYWORD_type},
1613ae02089SMasatake YAMATO {"var", KEYWORD_var},
1623ae02089SMasatake YAMATO {"func", KEYWORD_func},
1633ae02089SMasatake YAMATO {"struct", KEYWORD_struct},
1643ae02089SMasatake YAMATO {"interface", KEYWORD_interface},
1653ae02089SMasatake YAMATO {"map", KEYWORD_map},
1663ae02089SMasatake YAMATO {"chan", KEYWORD_chan}
1673ae02089SMasatake YAMATO };
1683ae02089SMasatake YAMATO
169d153b5a9SMasatake YAMATO typedef enum {
170d153b5a9SMasatake YAMATO F_PACKAGE,
171d153b5a9SMasatake YAMATO F_PACKAGE_NAME,
172d153b5a9SMasatake YAMATO F_HOW_IMPORTED,
173d153b5a9SMasatake YAMATO } goField;
174d153b5a9SMasatake YAMATO
175d153b5a9SMasatake YAMATO static fieldDefinition GoFields [] = {
176d153b5a9SMasatake YAMATO {
177d153b5a9SMasatake YAMATO .name = "package",
178d153b5a9SMasatake YAMATO .description = "the real package specified by the package name",
179d153b5a9SMasatake YAMATO .enabled = true,
180d153b5a9SMasatake YAMATO },
181d153b5a9SMasatake YAMATO {
182d153b5a9SMasatake YAMATO .name = "packageName",
183d153b5a9SMasatake YAMATO .description = "the name for referring the package",
184d153b5a9SMasatake YAMATO .enabled = true,
185d153b5a9SMasatake YAMATO },
186d153b5a9SMasatake YAMATO {
187d153b5a9SMasatake YAMATO .name = "howImported",
188d153b5a9SMasatake YAMATO .description = "how the package is imported (\"inline\" for `.' or \"init\" for `_')",
189d153b5a9SMasatake YAMATO .enabled = false,
190d153b5a9SMasatake YAMATO },
191d153b5a9SMasatake YAMATO };
192d153b5a9SMasatake YAMATO
193c49999e5SMasatake YAMATO
1943ae02089SMasatake YAMATO /*
1953ae02089SMasatake YAMATO * FUNCTION DEFINITIONS
1963ae02089SMasatake YAMATO */
1973ae02089SMasatake YAMATO
newPoolToken(void * createArg CTAGS_ATTR_UNUSED)1986cbb2243SMasatake YAMATO static void *newPoolToken (void *createArg CTAGS_ATTR_UNUSED)
1993ae02089SMasatake YAMATO {
2003ae02089SMasatake YAMATO tokenInfo *const token = xMalloc (1, tokenInfo);
2016cbb2243SMasatake YAMATO token->string = vStringNew ();
2026cbb2243SMasatake YAMATO return token;
2036cbb2243SMasatake YAMATO }
2046cbb2243SMasatake YAMATO
clearPoolToken(void * data)2056cbb2243SMasatake YAMATO static void clearPoolToken (void *data)
2066cbb2243SMasatake YAMATO {
2076cbb2243SMasatake YAMATO tokenInfo *token = data;
2086cbb2243SMasatake YAMATO
2093ae02089SMasatake YAMATO token->type = TOKEN_NONE;
2103ae02089SMasatake YAMATO token->keyword = KEYWORD_NONE;
211a31b37dcSMasatake YAMATO token->lineNumber = getInputLineNumber ();
2123ae02089SMasatake YAMATO token->filePosition = getInputFilePosition ();
2136cbb2243SMasatake YAMATO vStringClear (token->string);
2143ae02089SMasatake YAMATO }
2153ae02089SMasatake YAMATO
copyToken(tokenInfo * const dest,const tokenInfo * const other)216fbbf969bSJiří Techet static void copyToken (tokenInfo *const dest, const tokenInfo *const other)
217d5bc0fc5SJiří Techet {
218fbbf969bSJiří Techet dest->type = other->type;
219fbbf969bSJiří Techet dest->keyword = other->keyword;
220fbbf969bSJiří Techet vStringCopy(dest->string, other->string);
221fbbf969bSJiří Techet dest->lineNumber = other->lineNumber;
222fbbf969bSJiří Techet dest->filePosition = other->filePosition;
223d5bc0fc5SJiří Techet }
224d5bc0fc5SJiří Techet
deletePoolToken(void * data)2256cbb2243SMasatake YAMATO static void deletePoolToken (void* data)
2263ae02089SMasatake YAMATO {
2276cbb2243SMasatake YAMATO tokenInfo * const token = data;
2286cbb2243SMasatake YAMATO
2293ae02089SMasatake YAMATO vStringDelete (token->string);
2303ae02089SMasatake YAMATO eFree (token);
2313ae02089SMasatake YAMATO }
2326cbb2243SMasatake YAMATO
initialize(const langType language)2336cbb2243SMasatake YAMATO static void initialize (const langType language)
2346cbb2243SMasatake YAMATO {
2356cbb2243SMasatake YAMATO Lang_go = language;
2366cbb2243SMasatake YAMATO TokenPool = objPoolNew (16, newPoolToken, deletePoolToken, clearPoolToken, NULL);
2376cbb2243SMasatake YAMATO }
2386cbb2243SMasatake YAMATO
finalize(const langType language,bool initialized)2396cbb2243SMasatake YAMATO static void finalize (const langType language, bool initialized)
2406cbb2243SMasatake YAMATO {
2416cbb2243SMasatake YAMATO if (!initialized)
2426cbb2243SMasatake YAMATO return;
2436cbb2243SMasatake YAMATO
2446cbb2243SMasatake YAMATO objPoolDelete (TokenPool);
2453ae02089SMasatake YAMATO }
2463ae02089SMasatake YAMATO
2473ae02089SMasatake YAMATO /*
2483ae02089SMasatake YAMATO * Parsing functions
2493ae02089SMasatake YAMATO */
2503ae02089SMasatake YAMATO
parseString(vString * const string,const int delimiter)2513ae02089SMasatake YAMATO static void parseString (vString *const string, const int delimiter)
2523ae02089SMasatake YAMATO {
253ce990805SThomas Braun bool end = false;
2543ae02089SMasatake YAMATO while (!end)
2553ae02089SMasatake YAMATO {
256018bce0bSMasatake YAMATO int c = getcFromInputFile ();
2573ae02089SMasatake YAMATO if (c == EOF)
258ce990805SThomas Braun end = true;
2593ae02089SMasatake YAMATO else if (c == '\\' && delimiter != '`')
2603ae02089SMasatake YAMATO {
261018bce0bSMasatake YAMATO c = getcFromInputFile ();
2623ae02089SMasatake YAMATO if (c != '\'' && c != '\"')
2633ae02089SMasatake YAMATO vStringPut (string, '\\');
2643ae02089SMasatake YAMATO vStringPut (string, c);
2653ae02089SMasatake YAMATO }
2663ae02089SMasatake YAMATO else if (c == delimiter)
267ce990805SThomas Braun end = true;
2683ae02089SMasatake YAMATO else
2693ae02089SMasatake YAMATO vStringPut (string, c);
2703ae02089SMasatake YAMATO }
2713ae02089SMasatake YAMATO }
2723ae02089SMasatake YAMATO
parseIdentifier(vString * const string,const int firstChar)2733ae02089SMasatake YAMATO static void parseIdentifier (vString *const string, const int firstChar)
2743ae02089SMasatake YAMATO {
2753ae02089SMasatake YAMATO int c = firstChar;
2763ae02089SMasatake YAMATO do
2773ae02089SMasatake YAMATO {
2783ae02089SMasatake YAMATO vStringPut (string, c);
279018bce0bSMasatake YAMATO c = getcFromInputFile ();
2803ae02089SMasatake YAMATO } while (isIdentChar (c));
28161f14fa5SMasatake YAMATO ungetcToInputFile (c); /* always unget, LF might add a semicolon */
2823ae02089SMasatake YAMATO }
2833ae02089SMasatake YAMATO
collectorIsEmpty(collector * collector)284ced34385SMasatake YAMATO static bool collectorIsEmpty(collector *collector)
285ced34385SMasatake YAMATO {
286ced34385SMasatake YAMATO return !vStringLength(collector->str);
287ced34385SMasatake YAMATO }
288ced34385SMasatake YAMATO
collectorPut(collector * collector,char c)2892235f9b5SMasatake YAMATO static void collectorPut (collector *collector, char c)
2902235f9b5SMasatake YAMATO {
291903997b9SMasatake YAMATO if ((vStringLength(collector->str) > 2)
292903997b9SMasatake YAMATO && strcmp (vStringValue (collector->str) + (vStringLength(collector->str) - 3),
293903997b9SMasatake YAMATO "...") == 0
294903997b9SMasatake YAMATO && c == ' ')
295903997b9SMasatake YAMATO return;
296903997b9SMasatake YAMATO else if (vStringLength(collector->str) > 0)
297a783bb3eSMasatake YAMATO {
298a783bb3eSMasatake YAMATO if (vStringLast(collector->str) == '(' && c == ' ')
299a783bb3eSMasatake YAMATO return;
300a783bb3eSMasatake YAMATO else if (vStringLast(collector->str) == ' ' && c == ')')
301a783bb3eSMasatake YAMATO vStringChop(collector->str);
302a783bb3eSMasatake YAMATO }
303a783bb3eSMasatake YAMATO
3042235f9b5SMasatake YAMATO collector->last_len = vStringLength (collector->str);
3052235f9b5SMasatake YAMATO vStringPut (collector->str, c);
3062235f9b5SMasatake YAMATO }
3072235f9b5SMasatake YAMATO
collectorCatS(collector * collector,char * cstr)3082235f9b5SMasatake YAMATO static void collectorCatS (collector *collector, char *cstr)
3092235f9b5SMasatake YAMATO {
3102235f9b5SMasatake YAMATO collector->last_len = vStringLength (collector->str);
3112235f9b5SMasatake YAMATO vStringCatS (collector->str, cstr);
3122235f9b5SMasatake YAMATO }
3132235f9b5SMasatake YAMATO
collectorCat(collector * collector,vString * str)3142235f9b5SMasatake YAMATO static void collectorCat (collector *collector, vString *str)
3152235f9b5SMasatake YAMATO {
3162235f9b5SMasatake YAMATO collector->last_len = vStringLength (collector->str);
3172235f9b5SMasatake YAMATO vStringCat (collector->str, str);
3182235f9b5SMasatake YAMATO }
3192235f9b5SMasatake YAMATO
collectorAppendToken(collector * collector,const tokenInfo * const token)3207371853fSMasatake YAMATO static void collectorAppendToken (collector *collector, const tokenInfo *const token)
3219de7b977SMasatake YAMATO {
3229de7b977SMasatake YAMATO if (token->type == TOKEN_LEFT_ARROW)
3232235f9b5SMasatake YAMATO collectorCatS (collector, "<-");
3249de7b977SMasatake YAMATO else if (token->type == TOKEN_STRING)
3259de7b977SMasatake YAMATO {
3269de7b977SMasatake YAMATO // only struct member annotations can appear in function prototypes
3279de7b977SMasatake YAMATO // so only `` type strings are possible
3282235f9b5SMasatake YAMATO collector->last_len = vStringLength (collector->str);
3292235f9b5SMasatake YAMATO vStringPut(collector->str, '`');
3302235f9b5SMasatake YAMATO vStringCat(collector->str, token->string);
3312235f9b5SMasatake YAMATO vStringPut(collector->str, '`');
3329de7b977SMasatake YAMATO }
3339de7b977SMasatake YAMATO else if (token->type == TOKEN_IDENTIFIER || token->type == TOKEN_KEYWORD)
3342235f9b5SMasatake YAMATO collectorCat (collector, token->string);
335903997b9SMasatake YAMATO else if (token->type == TOKEN_3DOTS)
336903997b9SMasatake YAMATO {
337903997b9SMasatake YAMATO if ((vStringLength (collector->str) > 0)
338903997b9SMasatake YAMATO && vStringLast(collector->str) != ' ')
339903997b9SMasatake YAMATO collectorPut (collector, ' ');
340903997b9SMasatake YAMATO collectorCatS (collector, "...");
341903997b9SMasatake YAMATO }
3429de7b977SMasatake YAMATO else if (token->c != EOF)
3432235f9b5SMasatake YAMATO collectorPut (collector, token->c);
3449de7b977SMasatake YAMATO }
3459de7b977SMasatake YAMATO
collectorTruncate(collector * collector,bool dropLast)3462235f9b5SMasatake YAMATO static void collectorTruncate (collector *collector, bool dropLast)
3472235f9b5SMasatake YAMATO {
3482235f9b5SMasatake YAMATO if (dropLast)
3492235f9b5SMasatake YAMATO vStringTruncate (collector->str, collector->last_len);
3502235f9b5SMasatake YAMATO
3512235f9b5SMasatake YAMATO vStringStripLeading (collector->str);
3522235f9b5SMasatake YAMATO vStringStripTrailing (collector->str);
3532235f9b5SMasatake YAMATO }
3542235f9b5SMasatake YAMATO
readTokenFull(tokenInfo * const token,collector * collector)3552235f9b5SMasatake YAMATO static void readTokenFull (tokenInfo *const token, collector *collector)
3563ae02089SMasatake YAMATO {
3573ae02089SMasatake YAMATO int c;
3583ae02089SMasatake YAMATO static tokenType lastTokenType = TOKEN_NONE;
359ce990805SThomas Braun bool firstWhitespace = true;
360ce990805SThomas Braun bool whitespace;
3613ae02089SMasatake YAMATO
3629de7b977SMasatake YAMATO token->c = EOF;
3633ae02089SMasatake YAMATO token->type = TOKEN_NONE;
3643ae02089SMasatake YAMATO token->keyword = KEYWORD_NONE;
3653ae02089SMasatake YAMATO vStringClear (token->string);
3663ae02089SMasatake YAMATO
3673ae02089SMasatake YAMATO getNextChar:
3683ae02089SMasatake YAMATO do
3693ae02089SMasatake YAMATO {
370018bce0bSMasatake YAMATO c = getcFromInputFile ();
371a31b37dcSMasatake YAMATO token->lineNumber = getInputLineNumber ();
3723ae02089SMasatake YAMATO token->filePosition = getInputFilePosition ();
3733ae02089SMasatake YAMATO if (c == '\n' && (lastTokenType == TOKEN_IDENTIFIER ||
3743ae02089SMasatake YAMATO lastTokenType == TOKEN_STRING ||
3753ae02089SMasatake YAMATO lastTokenType == TOKEN_OTHER ||
3763ae02089SMasatake YAMATO lastTokenType == TOKEN_CLOSE_PAREN ||
3773ae02089SMasatake YAMATO lastTokenType == TOKEN_CLOSE_CURLY ||
3783ae02089SMasatake YAMATO lastTokenType == TOKEN_CLOSE_SQUARE))
3793ae02089SMasatake YAMATO {
3803ae02089SMasatake YAMATO c = ';'; // semicolon injection
3813ae02089SMasatake YAMATO }
382d532b168SJiří Techet whitespace = c == '\t' || c == ' ' || c == '\r' || c == '\n';
3832235f9b5SMasatake YAMATO if (collector && whitespace && firstWhitespace && vStringLength (collector->str) < MAX_COLLECTOR_LENGTH)
384d532b168SJiří Techet {
385ce990805SThomas Braun firstWhitespace = false;
3862235f9b5SMasatake YAMATO collectorPut (collector, ' ');
3873ae02089SMasatake YAMATO }
388d532b168SJiří Techet }
389d532b168SJiří Techet while (whitespace);
3903ae02089SMasatake YAMATO
3913ae02089SMasatake YAMATO switch (c)
3923ae02089SMasatake YAMATO {
3933ae02089SMasatake YAMATO case EOF:
3943ae02089SMasatake YAMATO token->type = TOKEN_EOF;
3953ae02089SMasatake YAMATO break;
3963ae02089SMasatake YAMATO
3973ae02089SMasatake YAMATO case ';':
3983ae02089SMasatake YAMATO token->type = TOKEN_SEMICOLON;
3993ae02089SMasatake YAMATO break;
4003ae02089SMasatake YAMATO
4013ae02089SMasatake YAMATO case '/':
4023ae02089SMasatake YAMATO {
403ce990805SThomas Braun bool hasNewline = false;
404018bce0bSMasatake YAMATO int d = getcFromInputFile ();
4053ae02089SMasatake YAMATO switch (d)
4063ae02089SMasatake YAMATO {
4073ae02089SMasatake YAMATO case '/':
4084fffc5afSMasatake YAMATO skipToCharacterInInputFile ('\n');
4093ae02089SMasatake YAMATO /* Line comments start with the
4103ae02089SMasatake YAMATO * character sequence // and
4113ae02089SMasatake YAMATO * continue through the next
4123ae02089SMasatake YAMATO * newline. A line comment acts
4133ae02089SMasatake YAMATO * like a newline. */
41461f14fa5SMasatake YAMATO ungetcToInputFile ('\n');
4153ae02089SMasatake YAMATO goto getNextChar;
4163ae02089SMasatake YAMATO case '*':
4173ae02089SMasatake YAMATO do
4183ae02089SMasatake YAMATO {
4193ae02089SMasatake YAMATO do
4203ae02089SMasatake YAMATO {
421018bce0bSMasatake YAMATO d = getcFromInputFile ();
4223ae02089SMasatake YAMATO if (d == '\n')
4233ae02089SMasatake YAMATO {
424ce990805SThomas Braun hasNewline = true;
4253ae02089SMasatake YAMATO }
4263ae02089SMasatake YAMATO } while (d != EOF && d != '*');
4273ae02089SMasatake YAMATO
428018bce0bSMasatake YAMATO c = getcFromInputFile ();
4293ae02089SMasatake YAMATO if (c == '/')
4303ae02089SMasatake YAMATO break;
4313ae02089SMasatake YAMATO else
43261f14fa5SMasatake YAMATO ungetcToInputFile (c);
4333ae02089SMasatake YAMATO } while (c != EOF && c != '\0');
4343ae02089SMasatake YAMATO
43561f14fa5SMasatake YAMATO ungetcToInputFile (hasNewline ? '\n' : ' ');
4363ae02089SMasatake YAMATO goto getNextChar;
4373ae02089SMasatake YAMATO default:
4383ae02089SMasatake YAMATO token->type = TOKEN_OTHER;
43961f14fa5SMasatake YAMATO ungetcToInputFile (d);
4403ae02089SMasatake YAMATO break;
4413ae02089SMasatake YAMATO }
4423ae02089SMasatake YAMATO }
4433ae02089SMasatake YAMATO break;
4443ae02089SMasatake YAMATO
4453ae02089SMasatake YAMATO case '"':
4463ae02089SMasatake YAMATO case '\'':
4473ae02089SMasatake YAMATO case '`':
4483ae02089SMasatake YAMATO token->type = TOKEN_STRING;
4493ae02089SMasatake YAMATO parseString (token->string, c);
450a31b37dcSMasatake YAMATO token->lineNumber = getInputLineNumber ();
4513ae02089SMasatake YAMATO token->filePosition = getInputFilePosition ();
4523ae02089SMasatake YAMATO break;
4533ae02089SMasatake YAMATO
4543ae02089SMasatake YAMATO case '<':
4553ae02089SMasatake YAMATO {
456018bce0bSMasatake YAMATO int d = getcFromInputFile ();
4573ae02089SMasatake YAMATO if (d == '-')
4583ae02089SMasatake YAMATO token->type = TOKEN_LEFT_ARROW;
4593ae02089SMasatake YAMATO else
4603ae02089SMasatake YAMATO {
46161f14fa5SMasatake YAMATO ungetcToInputFile (d);
4623ae02089SMasatake YAMATO token->type = TOKEN_OTHER;
4633ae02089SMasatake YAMATO }
4643ae02089SMasatake YAMATO }
4653ae02089SMasatake YAMATO break;
4663ae02089SMasatake YAMATO
4673ae02089SMasatake YAMATO case '(':
4683ae02089SMasatake YAMATO token->type = TOKEN_OPEN_PAREN;
4693ae02089SMasatake YAMATO break;
4703ae02089SMasatake YAMATO
4713ae02089SMasatake YAMATO case ')':
4723ae02089SMasatake YAMATO token->type = TOKEN_CLOSE_PAREN;
4733ae02089SMasatake YAMATO break;
4743ae02089SMasatake YAMATO
4753ae02089SMasatake YAMATO case '{':
4763ae02089SMasatake YAMATO token->type = TOKEN_OPEN_CURLY;
4773ae02089SMasatake YAMATO break;
4783ae02089SMasatake YAMATO
4793ae02089SMasatake YAMATO case '}':
4803ae02089SMasatake YAMATO token->type = TOKEN_CLOSE_CURLY;
4813ae02089SMasatake YAMATO break;
4823ae02089SMasatake YAMATO
4833ae02089SMasatake YAMATO case '[':
4843ae02089SMasatake YAMATO token->type = TOKEN_OPEN_SQUARE;
4853ae02089SMasatake YAMATO break;
4863ae02089SMasatake YAMATO
4873ae02089SMasatake YAMATO case ']':
4883ae02089SMasatake YAMATO token->type = TOKEN_CLOSE_SQUARE;
4893ae02089SMasatake YAMATO break;
4903ae02089SMasatake YAMATO
4913ae02089SMasatake YAMATO case '*':
4923ae02089SMasatake YAMATO token->type = TOKEN_STAR;
4933ae02089SMasatake YAMATO break;
4943ae02089SMasatake YAMATO
4953ae02089SMasatake YAMATO case '.':
496903997b9SMasatake YAMATO {
497903997b9SMasatake YAMATO int d, e;
498903997b9SMasatake YAMATO d = getcFromInputFile ();
499903997b9SMasatake YAMATO if (d == '.')
500903997b9SMasatake YAMATO {
501903997b9SMasatake YAMATO e = getcFromInputFile ();
502903997b9SMasatake YAMATO if (e == '.')
503903997b9SMasatake YAMATO {
504903997b9SMasatake YAMATO token->type = TOKEN_3DOTS;
505903997b9SMasatake YAMATO break;
506903997b9SMasatake YAMATO }
507903997b9SMasatake YAMATO else
508903997b9SMasatake YAMATO {
509903997b9SMasatake YAMATO ungetcToInputFile (e);
510903997b9SMasatake YAMATO ungetcToInputFile (d);
511903997b9SMasatake YAMATO }
512903997b9SMasatake YAMATO }
513903997b9SMasatake YAMATO else
514903997b9SMasatake YAMATO ungetcToInputFile (d);
515903997b9SMasatake YAMATO }
5163ae02089SMasatake YAMATO token->type = TOKEN_DOT;
5173ae02089SMasatake YAMATO break;
5183ae02089SMasatake YAMATO
5193ae02089SMasatake YAMATO case ',':
5203ae02089SMasatake YAMATO token->type = TOKEN_COMMA;
5213ae02089SMasatake YAMATO break;
5223ae02089SMasatake YAMATO
52321c1aeedSMasatake YAMATO case '=':
52421c1aeedSMasatake YAMATO token->type = TOKEN_EQUAL;
52521c1aeedSMasatake YAMATO break;
52621c1aeedSMasatake YAMATO
5273ae02089SMasatake YAMATO default:
5283ae02089SMasatake YAMATO if (isStartIdentChar (c))
5293ae02089SMasatake YAMATO {
5303ae02089SMasatake YAMATO parseIdentifier (token->string, c);
531a31b37dcSMasatake YAMATO token->lineNumber = getInputLineNumber ();
5323ae02089SMasatake YAMATO token->filePosition = getInputFilePosition ();
5333ae02089SMasatake YAMATO token->keyword = lookupKeyword (vStringValue (token->string), Lang_go);
5343ae02089SMasatake YAMATO if (isKeyword (token, KEYWORD_NONE))
5353ae02089SMasatake YAMATO token->type = TOKEN_IDENTIFIER;
5363ae02089SMasatake YAMATO else
5373ae02089SMasatake YAMATO token->type = TOKEN_KEYWORD;
5383ae02089SMasatake YAMATO }
5393ae02089SMasatake YAMATO else
5403ae02089SMasatake YAMATO token->type = TOKEN_OTHER;
5413ae02089SMasatake YAMATO break;
5423ae02089SMasatake YAMATO }
5433ae02089SMasatake YAMATO
5449de7b977SMasatake YAMATO token->c = c;
5459de7b977SMasatake YAMATO
5462235f9b5SMasatake YAMATO if (collector && vStringLength (collector->str) < MAX_COLLECTOR_LENGTH)
5477371853fSMasatake YAMATO collectorAppendToken (collector, token);
548d532b168SJiří Techet
5493ae02089SMasatake YAMATO lastTokenType = token->type;
5503ae02089SMasatake YAMATO }
5513ae02089SMasatake YAMATO
readToken(tokenInfo * const token)552be658b95SMasatake YAMATO static void readToken (tokenInfo *const token)
553be658b95SMasatake YAMATO {
554be658b95SMasatake YAMATO readTokenFull (token, NULL);
555be658b95SMasatake YAMATO }
556be658b95SMasatake YAMATO
skipToMatchedNoRead(tokenInfo * const token,collector * collector)5572235f9b5SMasatake YAMATO static bool skipToMatchedNoRead (tokenInfo *const token, collector *collector)
5583ae02089SMasatake YAMATO {
5593ae02089SMasatake YAMATO int nest_level = 0;
5603ae02089SMasatake YAMATO tokenType open_token = token->type;
5613ae02089SMasatake YAMATO tokenType close_token;
5623ae02089SMasatake YAMATO
5633ae02089SMasatake YAMATO switch (open_token)
5643ae02089SMasatake YAMATO {
5653ae02089SMasatake YAMATO case TOKEN_OPEN_PAREN:
5663ae02089SMasatake YAMATO close_token = TOKEN_CLOSE_PAREN;
5673ae02089SMasatake YAMATO break;
5683ae02089SMasatake YAMATO case TOKEN_OPEN_CURLY:
5693ae02089SMasatake YAMATO close_token = TOKEN_CLOSE_CURLY;
5703ae02089SMasatake YAMATO break;
5713ae02089SMasatake YAMATO case TOKEN_OPEN_SQUARE:
5723ae02089SMasatake YAMATO close_token = TOKEN_CLOSE_SQUARE;
5733ae02089SMasatake YAMATO break;
5743ae02089SMasatake YAMATO default:
575ce990805SThomas Braun return false;
5763ae02089SMasatake YAMATO }
5773ae02089SMasatake YAMATO
5783ae02089SMasatake YAMATO /*
5793ae02089SMasatake YAMATO * This routine will skip to a matching closing token.
5803ae02089SMasatake YAMATO * It will also handle nested tokens.
5813ae02089SMasatake YAMATO */
5823ae02089SMasatake YAMATO nest_level++;
5833ae02089SMasatake YAMATO while (nest_level > 0 && !isType (token, TOKEN_EOF))
5843ae02089SMasatake YAMATO {
585be658b95SMasatake YAMATO readTokenFull (token, collector);
5863ae02089SMasatake YAMATO if (isType (token, open_token))
5873ae02089SMasatake YAMATO nest_level++;
5883ae02089SMasatake YAMATO else if (isType (token, close_token))
5893ae02089SMasatake YAMATO nest_level--;
5903ae02089SMasatake YAMATO }
591d532b168SJiří Techet
592ce990805SThomas Braun return true;
593d532b168SJiří Techet }
594d532b168SJiří Techet
skipToMatched(tokenInfo * const token,collector * collector)595469a4eeaSMasatake YAMATO static void skipToMatched (tokenInfo *const token, collector *collector)
596d532b168SJiří Techet {
597469a4eeaSMasatake YAMATO if (skipToMatchedNoRead (token, collector))
598469a4eeaSMasatake YAMATO readTokenFull (token, collector);
5993ae02089SMasatake YAMATO }
6003ae02089SMasatake YAMATO
skipType(tokenInfo * const token,collector * collector)601469a4eeaSMasatake YAMATO static bool skipType (tokenInfo *const token, collector *collector)
6023ae02089SMasatake YAMATO {
6033ae02089SMasatake YAMATO // Type = TypeName | TypeLit | "(" Type ")" .
6043ae02089SMasatake YAMATO // Skips also function multiple return values "(" Type {"," Type} ")"
6053ae02089SMasatake YAMATO if (isType (token, TOKEN_OPEN_PAREN))
6063ae02089SMasatake YAMATO {
607469a4eeaSMasatake YAMATO skipToMatched (token, collector);
608ce990805SThomas Braun return true;
6093ae02089SMasatake YAMATO }
6103ae02089SMasatake YAMATO
6113ae02089SMasatake YAMATO // TypeName = QualifiedIdent.
6123ae02089SMasatake YAMATO // QualifiedIdent = [ PackageName "." ] identifier .
6133ae02089SMasatake YAMATO // PackageName = identifier .
6143ae02089SMasatake YAMATO if (isType (token, TOKEN_IDENTIFIER))
6153ae02089SMasatake YAMATO {
616469a4eeaSMasatake YAMATO readTokenFull (token, collector);
6173ae02089SMasatake YAMATO if (isType (token, TOKEN_DOT))
6183ae02089SMasatake YAMATO {
619469a4eeaSMasatake YAMATO readTokenFull (token, collector);
6203ae02089SMasatake YAMATO if (isType (token, TOKEN_IDENTIFIER))
621469a4eeaSMasatake YAMATO readTokenFull (token, collector);
6223ae02089SMasatake YAMATO }
623ce990805SThomas Braun return true;
6243ae02089SMasatake YAMATO }
6253ae02089SMasatake YAMATO
6263ae02089SMasatake YAMATO // StructType = "struct" "{" { FieldDecl ";" } "}"
6273ae02089SMasatake YAMATO // InterfaceType = "interface" "{" { MethodSpec ";" } "}" .
6283ae02089SMasatake YAMATO if (isKeyword (token, KEYWORD_struct) || isKeyword (token, KEYWORD_interface))
6293ae02089SMasatake YAMATO {
630469a4eeaSMasatake YAMATO readTokenFull (token, collector);
6313ae02089SMasatake YAMATO // skip over "{}"
632469a4eeaSMasatake YAMATO skipToMatched (token, collector);
633ce990805SThomas Braun return true;
6343ae02089SMasatake YAMATO }
6353ae02089SMasatake YAMATO
6363ae02089SMasatake YAMATO // ArrayType = "[" ArrayLength "]" ElementType .
6373ae02089SMasatake YAMATO // SliceType = "[" "]" ElementType .
6383ae02089SMasatake YAMATO // ElementType = Type .
6393ae02089SMasatake YAMATO if (isType (token, TOKEN_OPEN_SQUARE))
6403ae02089SMasatake YAMATO {
641469a4eeaSMasatake YAMATO skipToMatched (token, collector);
642469a4eeaSMasatake YAMATO return skipType (token, collector);
6433ae02089SMasatake YAMATO }
6443ae02089SMasatake YAMATO
6453ae02089SMasatake YAMATO // PointerType = "*" BaseType .
6463ae02089SMasatake YAMATO // BaseType = Type .
6473ae02089SMasatake YAMATO // ChannelType = ( "chan" [ "<-" ] | "<-" "chan" ) ElementType .
6483ae02089SMasatake YAMATO if (isType (token, TOKEN_STAR) || isKeyword (token, KEYWORD_chan) || isType (token, TOKEN_LEFT_ARROW))
6493ae02089SMasatake YAMATO {
650469a4eeaSMasatake YAMATO readTokenFull (token, collector);
651469a4eeaSMasatake YAMATO return skipType (token, collector);
6523ae02089SMasatake YAMATO }
6533ae02089SMasatake YAMATO
6543ae02089SMasatake YAMATO // MapType = "map" "[" KeyType "]" ElementType .
6553ae02089SMasatake YAMATO // KeyType = Type .
6563ae02089SMasatake YAMATO if (isKeyword (token, KEYWORD_map))
6573ae02089SMasatake YAMATO {
658469a4eeaSMasatake YAMATO readTokenFull (token, collector);
6593ae02089SMasatake YAMATO // skip over "[]"
660469a4eeaSMasatake YAMATO skipToMatched (token, collector);
661469a4eeaSMasatake YAMATO return skipType (token, collector);
6623ae02089SMasatake YAMATO }
6633ae02089SMasatake YAMATO
6643ae02089SMasatake YAMATO // FunctionType = "func" Signature .
6653ae02089SMasatake YAMATO // Signature = Parameters [ Result ] .
6663ae02089SMasatake YAMATO // Result = Parameters | Type .
6673ae02089SMasatake YAMATO // Parameters = "(" [ ParameterList [ "," ] ] ")" .
6683ae02089SMasatake YAMATO if (isKeyword (token, KEYWORD_func))
6693ae02089SMasatake YAMATO {
670469a4eeaSMasatake YAMATO readTokenFull (token, collector);
6713ae02089SMasatake YAMATO // Parameters, skip over "()"
672469a4eeaSMasatake YAMATO skipToMatched (token, collector);
6733ae02089SMasatake YAMATO // Result is parameters or type or nothing. skipType treats anything
6743ae02089SMasatake YAMATO // surrounded by parentheses as a type, and does nothing if what
6753ae02089SMasatake YAMATO // follows is not a type.
676469a4eeaSMasatake YAMATO return skipType (token, collector);
6773ae02089SMasatake YAMATO }
6783ae02089SMasatake YAMATO
679ce990805SThomas Braun return false;
680b00d9760SJiří Techet }
681b00d9760SJiří Techet
makeTagFull(tokenInfo * const token,const goKind kind,const int scope,const char * argList,const char * typeref,const int role)682d153b5a9SMasatake YAMATO static int makeTagFull (tokenInfo *const token, const goKind kind,
683d153b5a9SMasatake YAMATO const int scope, const char *argList, const char *typeref,
684d153b5a9SMasatake YAMATO const int role)
6853ae02089SMasatake YAMATO {
6863ae02089SMasatake YAMATO const char *const name = vStringValue (token->string);
6873ae02089SMasatake YAMATO
6883ae02089SMasatake YAMATO tagEntryInfo e;
689563bf975SMasatake YAMATO
690ebf1bd78SMasatake YAMATO /* Don't record `_' placeholder variable */
691ebf1bd78SMasatake YAMATO if (kind == GOTAG_VAR && name[0] == '_' && name[1] == '\0')
692ebf1bd78SMasatake YAMATO return CORK_NIL;
693ebf1bd78SMasatake YAMATO
694d153b5a9SMasatake YAMATO initRefTagEntry (&e, name, kind, role);
6953ae02089SMasatake YAMATO
6963ae02089SMasatake YAMATO e.lineNumber = token->lineNumber;
6973ae02089SMasatake YAMATO e.filePosition = token->filePosition;
698d532b168SJiří Techet if (argList)
699d532b168SJiří Techet e.extensionFields.signature = argList;
700aadb9521SMasatake YAMATO if (typeref)
701aadb9521SMasatake YAMATO {
702aadb9521SMasatake YAMATO /* Follows Cxx parser convention */
703aadb9521SMasatake YAMATO e.extensionFields.typeRef [0] = "typename";
704aadb9521SMasatake YAMATO e.extensionFields.typeRef [1] = typeref;
705aadb9521SMasatake YAMATO }
7063ae02089SMasatake YAMATO
7075c7bd5b5SMasatake YAMATO e.extensionFields.scopeIndex = scope;
7085c7bd5b5SMasatake YAMATO return makeTagEntry (&e);
7093ae02089SMasatake YAMATO }
7103ae02089SMasatake YAMATO
makeTag(tokenInfo * const token,const goKind kind,const int scope,const char * argList,const char * typeref)711d153b5a9SMasatake YAMATO static int makeTag (tokenInfo *const token, const goKind kind,
712d153b5a9SMasatake YAMATO const int scope, const char *argList, const char *typeref)
713d153b5a9SMasatake YAMATO {
714d153b5a9SMasatake YAMATO return makeTagFull (token, kind, scope, argList, typeref,
71524b256e3SMasatake YAMATO ROLE_DEFINITION_INDEX);
716d153b5a9SMasatake YAMATO }
717d153b5a9SMasatake YAMATO
makeRefTag(tokenInfo * const token,const goKind kind,const int role)718d153b5a9SMasatake YAMATO static int makeRefTag (tokenInfo *const token, const goKind kind,
719d153b5a9SMasatake YAMATO const int role)
720d153b5a9SMasatake YAMATO {
721d153b5a9SMasatake YAMATO return makeTagFull (token, kind, CORK_NIL, NULL, NULL, role);
722d153b5a9SMasatake YAMATO }
723d153b5a9SMasatake YAMATO
parsePackage(tokenInfo * const token)7245c7bd5b5SMasatake YAMATO static int parsePackage (tokenInfo *const token)
7253ae02089SMasatake YAMATO {
7263ae02089SMasatake YAMATO readToken (token);
7273ae02089SMasatake YAMATO if (isType (token, TOKEN_IDENTIFIER))
7283ae02089SMasatake YAMATO {
729aadb9521SMasatake YAMATO return makeTag (token, GOTAG_PACKAGE, CORK_NIL, NULL, NULL);
7303ae02089SMasatake YAMATO }
7315c7bd5b5SMasatake YAMATO else
7325c7bd5b5SMasatake YAMATO return CORK_NIL;
7333ae02089SMasatake YAMATO }
7343ae02089SMasatake YAMATO
parseReceiver(tokenInfo * const token,int * corkIndex)7355a8e67d7SMasatake YAMATO static tokenInfo * parseReceiver (tokenInfo *const token, int *corkIndex)
736563bf975SMasatake YAMATO {
737563bf975SMasatake YAMATO tokenInfo *receiver_type_token = NULL;
738563bf975SMasatake YAMATO int nest_level = 1;
739563bf975SMasatake YAMATO
7405a8e67d7SMasatake YAMATO *corkIndex = CORK_NIL;
7415a8e67d7SMasatake YAMATO
742563bf975SMasatake YAMATO /* Looking for an identifier before ')'. */
743563bf975SMasatake YAMATO while (nest_level > 0 && !isType (token, TOKEN_EOF))
744563bf975SMasatake YAMATO {
745563bf975SMasatake YAMATO if (isType (token, TOKEN_IDENTIFIER))
746563bf975SMasatake YAMATO {
7475a8e67d7SMasatake YAMATO if (*corkIndex == CORK_NIL)
7485a8e67d7SMasatake YAMATO *corkIndex = makeTag (token, GOTAG_RECEIVER, CORK_NIL, NULL, NULL);
749563bf975SMasatake YAMATO if (!receiver_type_token)
750563bf975SMasatake YAMATO receiver_type_token = newToken ();
751563bf975SMasatake YAMATO copyToken (receiver_type_token, token);
752563bf975SMasatake YAMATO }
753563bf975SMasatake YAMATO
754563bf975SMasatake YAMATO readToken (token);
755563bf975SMasatake YAMATO if (isType (token, TOKEN_OPEN_PAREN))
756563bf975SMasatake YAMATO nest_level++;
757563bf975SMasatake YAMATO else if (isType (token, TOKEN_CLOSE_PAREN))
758563bf975SMasatake YAMATO nest_level--;
759563bf975SMasatake YAMATO }
760563bf975SMasatake YAMATO
761563bf975SMasatake YAMATO if (nest_level > 0 && receiver_type_token)
762563bf975SMasatake YAMATO {
763563bf975SMasatake YAMATO deleteToken (receiver_type_token);
764563bf975SMasatake YAMATO receiver_type_token = NULL;
765563bf975SMasatake YAMATO }
766563bf975SMasatake YAMATO
7673671ad72SMasatake YAMATO if (receiver_type_token)
7685a8e67d7SMasatake YAMATO {
7695a8e67d7SMasatake YAMATO tagEntryInfo *e = getEntryInCorkQueue (*corkIndex);
7703671ad72SMasatake YAMATO if (e)
7713671ad72SMasatake YAMATO {
7725a8e67d7SMasatake YAMATO e->extensionFields.typeRef [0] = eStrdup ("typename");
7735a8e67d7SMasatake YAMATO e->extensionFields.typeRef [1] = vStringStrdup (receiver_type_token->string);
7745a8e67d7SMasatake YAMATO }
7753671ad72SMasatake YAMATO }
776563bf975SMasatake YAMATO readToken (token);
777563bf975SMasatake YAMATO return receiver_type_token;
778563bf975SMasatake YAMATO }
779563bf975SMasatake YAMATO
parseFunctionOrMethod(tokenInfo * const token,const int scope)7805c7bd5b5SMasatake YAMATO static void parseFunctionOrMethod (tokenInfo *const token, const int scope)
7813ae02089SMasatake YAMATO {
7825a8e67d7SMasatake YAMATO int receiver_cork = CORK_NIL;
783563bf975SMasatake YAMATO tokenInfo *receiver_type_token = NULL;
784563bf975SMasatake YAMATO
7853ae02089SMasatake YAMATO // FunctionDecl = "func" identifier Signature [ Body ] .
7863ae02089SMasatake YAMATO // Body = Block.
7873ae02089SMasatake YAMATO //
7883ae02089SMasatake YAMATO // MethodDecl = "func" Receiver MethodName Signature [ Body ] .
7893ae02089SMasatake YAMATO // Receiver = "(" [ identifier ] [ "*" ] BaseTypeName ")" .
7903ae02089SMasatake YAMATO // BaseTypeName = identifier .
7913ae02089SMasatake YAMATO
792563bf975SMasatake YAMATO // Pick up receiver type.
7933ae02089SMasatake YAMATO readToken (token);
7943ae02089SMasatake YAMATO if (isType (token, TOKEN_OPEN_PAREN))
7955a8e67d7SMasatake YAMATO receiver_type_token = parseReceiver (token, &receiver_cork);
7963ae02089SMasatake YAMATO
7973ae02089SMasatake YAMATO if (isType (token, TOKEN_IDENTIFIER))
7983ae02089SMasatake YAMATO {
799d21aa13cSMasatake YAMATO int cork;
800d21aa13cSMasatake YAMATO tagEntryInfo *e = NULL;
801fbbf969bSJiří Techet tokenInfo *functionToken = newToken ();
802563bf975SMasatake YAMATO int func_scope;
803fbbf969bSJiří Techet
804fbbf969bSJiří Techet copyToken (functionToken, token);
805d532b168SJiří Techet
806d532b168SJiří Techet // Start recording signature
8072e4bb69eSMasatake YAMATO vString *buffer = vStringNew ();
8082e4bb69eSMasatake YAMATO collector collector = { .str = buffer, .last_len = 0, };
8093ae02089SMasatake YAMATO
8103ae02089SMasatake YAMATO // Skip over parameters.
8112235f9b5SMasatake YAMATO readTokenFull (token, &collector);
8122235f9b5SMasatake YAMATO skipToMatchedNoRead (token, &collector);
813d532b168SJiří Techet
8142235f9b5SMasatake YAMATO collectorTruncate (&collector, false);
815563bf975SMasatake YAMATO if (receiver_type_token)
816c49999e5SMasatake YAMATO {
817*aaaac7eeSMasatake YAMATO func_scope = anyEntryInScope (scope, vStringValue (receiver_type_token->string), false);
81865f5bc5bSMasatake YAMATO if (func_scope == CORK_NIL)
819d153b5a9SMasatake YAMATO func_scope = makeTagFull(receiver_type_token, GOTAG_UNKNOWN,
820d153b5a9SMasatake YAMATO scope, NULL, NULL,
821d153b5a9SMasatake YAMATO R_GOTAG_UNKNOWN_RECEIVER);
822c49999e5SMasatake YAMATO }
823563bf975SMasatake YAMATO else
824563bf975SMasatake YAMATO func_scope = scope;
825d21aa13cSMasatake YAMATO
826d21aa13cSMasatake YAMATO cork = makeTag (functionToken, GOTAG_FUNCTION,
8272e4bb69eSMasatake YAMATO func_scope, vStringValue (buffer), NULL);
8283671ad72SMasatake YAMATO if ((e = getEntryInCorkQueue (cork)))
8295a8e67d7SMasatake YAMATO {
8305a8e67d7SMasatake YAMATO tagEntryInfo *receiver = getEntryInCorkQueue (receiver_cork);
8313671ad72SMasatake YAMATO if (receiver)
8325a8e67d7SMasatake YAMATO receiver->extensionFields.scopeIndex = cork;
8335a8e67d7SMasatake YAMATO }
8345a8e67d7SMasatake YAMATO
835d532b168SJiří Techet deleteToken (functionToken);
836d532b168SJiří Techet
8372e4bb69eSMasatake YAMATO vStringClear (collector.str);
8382e4bb69eSMasatake YAMATO collector.last_len = 0;
8392e4bb69eSMasatake YAMATO
8402e4bb69eSMasatake YAMATO readTokenFull (token, &collector);
8413ae02089SMasatake YAMATO
8423ae02089SMasatake YAMATO // Skip over result.
8432e4bb69eSMasatake YAMATO skipType (token, &collector);
8442e4bb69eSMasatake YAMATO
8452e4bb69eSMasatake YAMATO // Neither "{" nor " {".
8462e4bb69eSMasatake YAMATO if (!(isType (token, TOKEN_OPEN_CURLY) && collector.last_len < 2))
8472e4bb69eSMasatake YAMATO {
8482e4bb69eSMasatake YAMATO collectorTruncate(&collector, isType (token, TOKEN_OPEN_CURLY));
8492e4bb69eSMasatake YAMATO if (e)
8502e4bb69eSMasatake YAMATO {
8512e4bb69eSMasatake YAMATO e->extensionFields.typeRef [0] = eStrdup ("typename");
8522e4bb69eSMasatake YAMATO e->extensionFields.typeRef [1] = vStringDeleteUnwrap (buffer);
8532e4bb69eSMasatake YAMATO buffer = NULL;
8542e4bb69eSMasatake YAMATO }
8552e4bb69eSMasatake YAMATO }
8562e4bb69eSMasatake YAMATO
8572e4bb69eSMasatake YAMATO if (buffer)
8582e4bb69eSMasatake YAMATO vStringDelete (buffer);
8593ae02089SMasatake YAMATO
8603ae02089SMasatake YAMATO // Skip over function body.
8613ae02089SMasatake YAMATO if (isType (token, TOKEN_OPEN_CURLY))
862d21aa13cSMasatake YAMATO {
863469a4eeaSMasatake YAMATO skipToMatched (token, NULL);
864d21aa13cSMasatake YAMATO if (e)
865d21aa13cSMasatake YAMATO e->extensionFields.endLine = getInputLineNumber ();
866d21aa13cSMasatake YAMATO }
8673ae02089SMasatake YAMATO }
868563bf975SMasatake YAMATO
869563bf975SMasatake YAMATO if (receiver_type_token)
870563bf975SMasatake YAMATO deleteToken(receiver_type_token);
8713ae02089SMasatake YAMATO }
8723ae02089SMasatake YAMATO
attachTypeRefField(int scope,intArray * corks,const char * const type)87365f5bc5bSMasatake YAMATO static void attachTypeRefField (int scope, intArray *corks, const char *const type)
8742232a75eSMasatake YAMATO {
875*aaaac7eeSMasatake YAMATO int type_cork = anyEntryInScope (scope, type, false);
8763671ad72SMasatake YAMATO tagEntryInfo *type_e = getEntryInCorkQueue (type_cork);
8772f245e21SMasatake YAMATO
8784c64e833SMasatake YAMATO for (unsigned int i = 0; i < intArrayCount (corks); i++)
8792232a75eSMasatake YAMATO {
8802232a75eSMasatake YAMATO int cork = intArrayItem (corks, i);
8812232a75eSMasatake YAMATO tagEntryInfo *e = getEntryInCorkQueue (cork);
8823671ad72SMasatake YAMATO if (!e)
8833671ad72SMasatake YAMATO continue;
8843671ad72SMasatake YAMATO e->extensionFields.typeRef [0] = eStrdup (type_e
8853671ad72SMasatake YAMATO ?GoKinds[type_e->kindIndex].name
8863671ad72SMasatake YAMATO :"typename");
8872232a75eSMasatake YAMATO e->extensionFields.typeRef [1] = eStrdup (type);
8882232a75eSMasatake YAMATO }
8892232a75eSMasatake YAMATO }
8902232a75eSMasatake YAMATO
parseInterfaceMethods(tokenInfo * const token,const int scope)891ced34385SMasatake YAMATO static void parseInterfaceMethods (tokenInfo *const token, const int scope)
892ced34385SMasatake YAMATO {
893ced34385SMasatake YAMATO // InterfaceType = "interface" "{" { MethodSpec ";" } "}" .
894ced34385SMasatake YAMATO // MethodSpec = MethodName Signature | InterfaceTypeName .
895ced34385SMasatake YAMATO // MethodName = identifier .
896ced34385SMasatake YAMATO // InterfaceTypeName = TypeName .
897ced34385SMasatake YAMATO
898ced34385SMasatake YAMATO vString *inheritsBuf = vStringNew ();
899ced34385SMasatake YAMATO collector inherits = { .str = inheritsBuf, .last_len = 0, };
900ced34385SMasatake YAMATO
901ced34385SMasatake YAMATO readToken (token);
902ced34385SMasatake YAMATO if (!isType (token, TOKEN_OPEN_CURLY))
903ced34385SMasatake YAMATO return;
904ced34385SMasatake YAMATO
905ced34385SMasatake YAMATO readToken (token);
906ced34385SMasatake YAMATO while (!isType (token, TOKEN_EOF) && !isType (token, TOKEN_CLOSE_CURLY))
907ced34385SMasatake YAMATO {
908ced34385SMasatake YAMATO if (isType (token, TOKEN_IDENTIFIER))
909ced34385SMasatake YAMATO {
910ced34385SMasatake YAMATO tokenInfo * headToken = newToken();
911ced34385SMasatake YAMATO copyToken (headToken, token);
912ced34385SMasatake YAMATO
913ced34385SMasatake YAMATO readToken (token);
914ced34385SMasatake YAMATO if(isType (token, TOKEN_DOT))
915ced34385SMasatake YAMATO {
916ced34385SMasatake YAMATO if (!collectorIsEmpty(&inherits))
917ced34385SMasatake YAMATO collectorPut (&inherits, ',');
918ced34385SMasatake YAMATO collectorAppendToken (&inherits, headToken);
919ced34385SMasatake YAMATO readTokenFull (token, NULL);
920ced34385SMasatake YAMATO if (isType (token, TOKEN_IDENTIFIER))
921ced34385SMasatake YAMATO {
922ced34385SMasatake YAMATO collectorPut (&inherits, '.');
923ced34385SMasatake YAMATO collectorAppendToken (&inherits, token);
924ced34385SMasatake YAMATO readToken (token);
925ced34385SMasatake YAMATO }
926ced34385SMasatake YAMATO /* If the token is not an identifier, the input
927ced34385SMasatake YAMATO may be wrong. */
928ced34385SMasatake YAMATO }
929ced34385SMasatake YAMATO else if (isType (token, TOKEN_SEMICOLON))
930ced34385SMasatake YAMATO {
931ced34385SMasatake YAMATO if (!collectorIsEmpty(&inherits))
932ced34385SMasatake YAMATO collectorPut (&inherits, ',');
933ced34385SMasatake YAMATO collectorAppendToken (&inherits, headToken);
934ced34385SMasatake YAMATO readToken (token);
935ced34385SMasatake YAMATO }
936ced34385SMasatake YAMATO else if (isType (token, TOKEN_OPEN_PAREN))
937ced34385SMasatake YAMATO {
938ced34385SMasatake YAMATO // => Signature
939ced34385SMasatake YAMATO // Signature = Parameters [ Result ] .
940ced34385SMasatake YAMATO vString *pbuf = vStringNew ();
941ced34385SMasatake YAMATO collector pcol = { .str = pbuf, .last_len = 0, };
942ced34385SMasatake YAMATO vString *rbuf = NULL;
943ced34385SMasatake YAMATO collector rcol = { .str = NULL, .last_len = 0, };
944ced34385SMasatake YAMATO
945ced34385SMasatake YAMATO // Parameters
946ced34385SMasatake YAMATO collectorPut (&pcol, '(');
947ced34385SMasatake YAMATO skipToMatched (token, &pcol);
948ced34385SMasatake YAMATO collectorTruncate(&pcol, true);
949ced34385SMasatake YAMATO
950ced34385SMasatake YAMATO if (!isType (token, TOKEN_SEMICOLON))
951ced34385SMasatake YAMATO {
952ced34385SMasatake YAMATO rbuf = vStringNew ();
953ced34385SMasatake YAMATO rcol.str = rbuf;
954ced34385SMasatake YAMATO
955ced34385SMasatake YAMATO collectorAppendToken (&rcol, token);
956ced34385SMasatake YAMATO skipType (token, &rcol);
957ced34385SMasatake YAMATO collectorTruncate(&rcol, true);
958ced34385SMasatake YAMATO }
959ced34385SMasatake YAMATO
960ced34385SMasatake YAMATO makeTag (headToken, GOTAG_METHODSPEC, scope,
961ced34385SMasatake YAMATO vStringValue (pbuf),
962ced34385SMasatake YAMATO rbuf? vStringValue(rbuf): NULL);
963ced34385SMasatake YAMATO
964ced34385SMasatake YAMATO if (rbuf)
965ced34385SMasatake YAMATO vStringDelete (rbuf);
966ced34385SMasatake YAMATO vStringDelete (pbuf);
967ced34385SMasatake YAMATO }
968ced34385SMasatake YAMATO deleteToken (headToken);
969ced34385SMasatake YAMATO }
970ced34385SMasatake YAMATO else
971ced34385SMasatake YAMATO readToken (token);
972ced34385SMasatake YAMATO }
973ced34385SMasatake YAMATO
974ced34385SMasatake YAMATO if (!collectorIsEmpty(&inherits))
975ced34385SMasatake YAMATO {
976ced34385SMasatake YAMATO tagEntryInfo *e = getEntryInCorkQueue (scope);
9773671ad72SMasatake YAMATO if (e)
9783671ad72SMasatake YAMATO {
979ced34385SMasatake YAMATO e->extensionFields.inheritance = vStringDeleteUnwrap (inheritsBuf);
9803671ad72SMasatake YAMATO inheritsBuf = NULL;
981ced34385SMasatake YAMATO }
9823671ad72SMasatake YAMATO }
983ced34385SMasatake YAMATO vStringDelete (inheritsBuf);
984ced34385SMasatake YAMATO }
985ced34385SMasatake YAMATO
parseStructMembers(tokenInfo * const token,const int scope)9865c7bd5b5SMasatake YAMATO static void parseStructMembers (tokenInfo *const token, const int scope)
987b00d9760SJiří Techet {
988b00d9760SJiří Techet // StructType = "struct" "{" { FieldDecl ";" } "}" .
989b00d9760SJiří Techet // FieldDecl = (IdentifierList Type | AnonymousField) [ Tag ] .
990b00d9760SJiří Techet // AnonymousField = [ "*" ] TypeName .
991b00d9760SJiří Techet // Tag = string_lit .
992b00d9760SJiří Techet
993b00d9760SJiří Techet readToken (token);
994b00d9760SJiří Techet if (!isType (token, TOKEN_OPEN_CURLY))
995b00d9760SJiří Techet return;
996b00d9760SJiří Techet
997aadb9521SMasatake YAMATO vString *typeForAnonMember = vStringNew ();
9982232a75eSMasatake YAMATO intArray *corkForFields = intArrayNew ();
999aadb9521SMasatake YAMATO
1000b00d9760SJiří Techet readToken (token);
1001b00d9760SJiří Techet while (!isType (token, TOKEN_EOF) && !isType (token, TOKEN_CLOSE_CURLY))
1002b00d9760SJiří Techet {
1003b00d9760SJiří Techet tokenInfo *memberCandidate = NULL;
1004ce990805SThomas Braun bool first = true;
1005b00d9760SJiří Techet
1006b00d9760SJiří Techet while (!isType (token, TOKEN_EOF))
1007b00d9760SJiří Techet {
1008b00d9760SJiří Techet if (isType (token, TOKEN_IDENTIFIER))
1009b00d9760SJiří Techet {
1010b00d9760SJiří Techet if (first)
1011b00d9760SJiří Techet {
1012b00d9760SJiří Techet // could be anonymous field like in 'struct {int}' - we don't know yet
1013fbbf969bSJiří Techet memberCandidate = newToken ();
1014fbbf969bSJiří Techet copyToken (memberCandidate, token);
1015ce990805SThomas Braun first = false;
1016b00d9760SJiří Techet }
1017b00d9760SJiří Techet else
1018b00d9760SJiří Techet {
10192232a75eSMasatake YAMATO int cork;
1020b00d9760SJiří Techet if (memberCandidate)
1021b00d9760SJiří Techet {
1022b00d9760SJiří Techet // if we are here, there was a comma and memberCandidate isn't an anonymous field
10232232a75eSMasatake YAMATO cork = makeTag (memberCandidate, GOTAG_MEMBER, scope, NULL, NULL);
1024b00d9760SJiří Techet deleteToken (memberCandidate);
1025b00d9760SJiří Techet memberCandidate = NULL;
10262232a75eSMasatake YAMATO intArrayAdd (corkForFields, cork);
1027b00d9760SJiří Techet }
10282232a75eSMasatake YAMATO cork = makeTag (token, GOTAG_MEMBER, scope, NULL, NULL);
10292232a75eSMasatake YAMATO intArrayAdd (corkForFields, cork);
1030b00d9760SJiří Techet }
1031b00d9760SJiří Techet readToken (token);
1032b00d9760SJiří Techet }
1033b00d9760SJiří Techet if (!isType (token, TOKEN_COMMA))
1034b00d9760SJiří Techet break;
1035b00d9760SJiří Techet readToken (token);
1036b00d9760SJiří Techet }
1037b00d9760SJiří Techet
1038aadb9521SMasatake YAMATO if (first && isType (token, TOKEN_STAR))
10397fd5d457SJiří Techet {
1040aadb9521SMasatake YAMATO vStringPut (typeForAnonMember, '*');
10417fd5d457SJiří Techet readToken (token);
10427fd5d457SJiří Techet }
10437fd5d457SJiří Techet else if (memberCandidate &&
10447fd5d457SJiří Techet (isType (token, TOKEN_DOT) ||
10457fd5d457SJiří Techet isType (token, TOKEN_STRING) ||
10467fd5d457SJiří Techet isType (token, TOKEN_SEMICOLON)))
10477fd5d457SJiří Techet // memberCandidate is part of anonymous type
1048aadb9521SMasatake YAMATO vStringCat (typeForAnonMember, memberCandidate->string);
1049aadb9521SMasatake YAMATO
10507fd5d457SJiří Techet // the above two cases that set typeForAnonMember guarantee
10517fd5d457SJiří Techet // this is an anonymous member
10527fd5d457SJiří Techet if (vStringLength (typeForAnonMember) > 0)
105353140b39SMasatake YAMATO {
10547fd5d457SJiří Techet tokenInfo *anonMember = NULL;
10557fd5d457SJiří Techet
10567fd5d457SJiří Techet if (memberCandidate)
10577fd5d457SJiří Techet {
10587fd5d457SJiří Techet anonMember = newToken ();
10597fd5d457SJiří Techet copyToken (anonMember, memberCandidate);
10607fd5d457SJiří Techet }
10617fd5d457SJiří Techet
106253140b39SMasatake YAMATO // TypeName of AnonymousField has a dot like package"."type.
106353140b39SMasatake YAMATO // Pick up the last package component, and store it to
106453140b39SMasatake YAMATO // memberCandidate.
106553140b39SMasatake YAMATO while (isType (token, TOKEN_IDENTIFIER) ||
106653140b39SMasatake YAMATO isType (token, TOKEN_DOT))
106753140b39SMasatake YAMATO {
106853140b39SMasatake YAMATO if (isType (token, TOKEN_IDENTIFIER))
106953140b39SMasatake YAMATO {
10707fd5d457SJiří Techet if (!anonMember)
10717fd5d457SJiří Techet anonMember = newToken ();
10727fd5d457SJiří Techet copyToken (anonMember, token);
10737fd5d457SJiří Techet vStringCat (typeForAnonMember, anonMember->string);
107453140b39SMasatake YAMATO }
10757fd5d457SJiří Techet else if (isType (token, TOKEN_DOT))
10767fd5d457SJiří Techet vStringPut (typeForAnonMember, '.');
107753140b39SMasatake YAMATO readToken (token);
107853140b39SMasatake YAMATO }
107953140b39SMasatake YAMATO
10807fd5d457SJiří Techet // optional tag
10817fd5d457SJiří Techet if (isType (token, TOKEN_STRING))
10827fd5d457SJiří Techet readToken (token);
10837fd5d457SJiří Techet
10847fd5d457SJiří Techet if (anonMember)
108553140b39SMasatake YAMATO {
10867fd5d457SJiří Techet makeTag (anonMember, GOTAG_ANONMEMBER, scope, NULL,
1087aadb9521SMasatake YAMATO vStringValue (typeForAnonMember));
10887fd5d457SJiří Techet deleteToken (anonMember);
108953140b39SMasatake YAMATO }
10907fd5d457SJiří Techet }
10912232a75eSMasatake YAMATO else
10927fd5d457SJiří Techet {
10932232a75eSMasatake YAMATO vString *typeForMember = vStringNew ();
10942232a75eSMasatake YAMATO collector collector = { .str = typeForMember, .last_len = 0, };
10952232a75eSMasatake YAMATO
10967371853fSMasatake YAMATO collectorAppendToken (&collector, token);
10972232a75eSMasatake YAMATO skipType (token, &collector);
10982232a75eSMasatake YAMATO collectorTruncate (&collector, true);
10992232a75eSMasatake YAMATO
11002232a75eSMasatake YAMATO if (memberCandidate)
11012232a75eSMasatake YAMATO makeTag (memberCandidate, GOTAG_MEMBER, scope, NULL,
11022232a75eSMasatake YAMATO vStringValue (typeForMember));
11032232a75eSMasatake YAMATO
110465f5bc5bSMasatake YAMATO attachTypeRefField (scope, corkForFields, vStringValue (typeForMember));
11052232a75eSMasatake YAMATO intArrayClear (corkForFields);
11062232a75eSMasatake YAMATO vStringDelete (typeForMember);
11077fd5d457SJiří Techet }
1108b870b2ccSJiří Techet
1109b870b2ccSJiří Techet if (memberCandidate)
1110b00d9760SJiří Techet deleteToken (memberCandidate);
1111b00d9760SJiří Techet
1112aadb9521SMasatake YAMATO vStringClear (typeForAnonMember);
1113aadb9521SMasatake YAMATO
1114b00d9760SJiří Techet while (!isType (token, TOKEN_SEMICOLON) && !isType (token, TOKEN_CLOSE_CURLY)
1115b00d9760SJiří Techet && !isType (token, TOKEN_EOF))
1116b00d9760SJiří Techet {
1117b00d9760SJiří Techet readToken (token);
1118469a4eeaSMasatake YAMATO skipToMatched (token, NULL);
1119b00d9760SJiří Techet }
1120b00d9760SJiří Techet
1121b00d9760SJiří Techet if (!isType (token, TOKEN_CLOSE_CURLY))
1122b00d9760SJiří Techet {
1123b00d9760SJiří Techet // we are at TOKEN_SEMICOLON
1124b00d9760SJiří Techet readToken (token);
1125b00d9760SJiří Techet }
1126b00d9760SJiří Techet }
1127aadb9521SMasatake YAMATO
11282232a75eSMasatake YAMATO intArrayDelete (corkForFields);
1129aadb9521SMasatake YAMATO vStringDelete (typeForAnonMember);
1130b00d9760SJiří Techet }
1131b00d9760SJiří Techet
parseConstTypeVar(tokenInfo * const token,goKind kind,const int scope)11325c7bd5b5SMasatake YAMATO static void parseConstTypeVar (tokenInfo *const token, goKind kind, const int scope)
11333ae02089SMasatake YAMATO {
11343ae02089SMasatake YAMATO // ConstDecl = "const" ( ConstSpec | "(" { ConstSpec ";" } ")" ) .
11353ae02089SMasatake YAMATO // ConstSpec = IdentifierList [ [ Type ] "=" ExpressionList ] .
11363ae02089SMasatake YAMATO // IdentifierList = identifier { "," identifier } .
11373ae02089SMasatake YAMATO // ExpressionList = Expression { "," Expression } .
11383ae02089SMasatake YAMATO // TypeDecl = "type" ( TypeSpec | "(" { TypeSpec ";" } ")" ) .
113921c1aeedSMasatake YAMATO // TypeSpec = identifier [ "=" ] Type .
11403ae02089SMasatake YAMATO // VarDecl = "var" ( VarSpec | "(" { VarSpec ";" } ")" ) .
11413ae02089SMasatake YAMATO // VarSpec = IdentifierList ( Type [ "=" ExpressionList ] | "=" ExpressionList ) .
1142ce990805SThomas Braun bool usesParens = false;
1143ccf5c712SMasatake YAMATO intArray *corks
1144ccf5c712SMasatake YAMATO = (kind == GOTAG_VAR || kind == GOTAG_CONST)? intArrayNew (): NULL;
11453ae02089SMasatake YAMATO
11463ae02089SMasatake YAMATO readToken (token);
11473ae02089SMasatake YAMATO
11483ae02089SMasatake YAMATO if (isType (token, TOKEN_OPEN_PAREN))
11493ae02089SMasatake YAMATO {
1150ce990805SThomas Braun usesParens = true;
11513ae02089SMasatake YAMATO readToken (token);
11523ae02089SMasatake YAMATO }
11533ae02089SMasatake YAMATO
11543ae02089SMasatake YAMATO do
11553ae02089SMasatake YAMATO {
1156b00d9760SJiří Techet tokenInfo *typeToken = NULL;
1157c635977cSMasatake YAMATO int member_scope = scope;
1158b00d9760SJiří Techet
11593ae02089SMasatake YAMATO while (!isType (token, TOKEN_EOF))
11603ae02089SMasatake YAMATO {
11613ae02089SMasatake YAMATO if (isType (token, TOKEN_IDENTIFIER))
11623ae02089SMasatake YAMATO {
1163d5bc0fc5SJiří Techet if (kind == GOTAG_TYPE)
1164d5bc0fc5SJiří Techet {
1165fbbf969bSJiří Techet typeToken = newToken ();
1166fbbf969bSJiří Techet copyToken (typeToken, token);
1167d5bc0fc5SJiří Techet readToken (token);
116821c1aeedSMasatake YAMATO if (isType (token, TOKEN_EQUAL))
116921c1aeedSMasatake YAMATO {
117049db5ecfSMasatake YAMATO kind = GOTAG_TALIAS;
117121c1aeedSMasatake YAMATO readToken (token);
117221c1aeedSMasatake YAMATO }
117321c1aeedSMasatake YAMATO
1174d5bc0fc5SJiří Techet if (isKeyword (token, KEYWORD_struct))
1175aadb9521SMasatake YAMATO member_scope = makeTag (typeToken, GOTAG_STRUCT,
1176aadb9521SMasatake YAMATO scope, NULL, NULL);
1177d5bc0fc5SJiří Techet else if (isKeyword (token, KEYWORD_interface))
1178aadb9521SMasatake YAMATO member_scope = makeTag (typeToken, GOTAG_INTERFACE,
1179aadb9521SMasatake YAMATO scope, NULL, NULL);
1180d5bc0fc5SJiří Techet else
1181aadb9521SMasatake YAMATO member_scope = makeTag (typeToken, kind,
1182aadb9521SMasatake YAMATO scope, NULL, NULL);
1183c49999e5SMasatake YAMATO
1184c49999e5SMasatake YAMATO if (member_scope != CORK_NIL)
118565f5bc5bSMasatake YAMATO registerEntry (member_scope);
1186d5bc0fc5SJiří Techet break;
1187d5bc0fc5SJiří Techet }
1188d5bc0fc5SJiří Techet else
1189ccf5c712SMasatake YAMATO {
1190ccf5c712SMasatake YAMATO int c = makeTag (token, kind, scope, NULL, NULL);
119197512e33SMasatake YAMATO if (c != CORK_NIL && corks)
1192ccf5c712SMasatake YAMATO intArrayAdd (corks, c);
1193ccf5c712SMasatake YAMATO }
11943ae02089SMasatake YAMATO readToken (token);
11953ae02089SMasatake YAMATO }
11963ae02089SMasatake YAMATO if (!isType (token, TOKEN_COMMA))
11973ae02089SMasatake YAMATO break;
11983ae02089SMasatake YAMATO readToken (token);
11993ae02089SMasatake YAMATO }
12003ae02089SMasatake YAMATO
1201b00d9760SJiří Techet if (typeToken)
1202b00d9760SJiří Techet {
1203b00d9760SJiří Techet if (isKeyword (token, KEYWORD_struct))
12045c7bd5b5SMasatake YAMATO parseStructMembers (token, member_scope);
12055fbaed96SMasatake YAMATO else if (isKeyword (token, KEYWORD_interface))
1206ced34385SMasatake YAMATO parseInterfaceMethods (token, member_scope);
12075fbaed96SMasatake YAMATO else
12085fbaed96SMasatake YAMATO {
12095fbaed96SMasatake YAMATO /* Filling "typeref:" field of typeToken. */
12105fbaed96SMasatake YAMATO vString *buffer = vStringNew ();
12115fbaed96SMasatake YAMATO collector collector = { .str = buffer, .last_len = 0, };
12125fbaed96SMasatake YAMATO
12135fbaed96SMasatake YAMATO collectorAppendToken (&collector, token);
12145fbaed96SMasatake YAMATO skipType (token, &collector);
12155fbaed96SMasatake YAMATO collectorTruncate (&collector, true);
12165fbaed96SMasatake YAMATO
121772ec2e5fSMasatake YAMATO if ((member_scope != CORK_NIL) && !vStringIsEmpty (buffer))
12185fbaed96SMasatake YAMATO {
12195fbaed96SMasatake YAMATO tagEntryInfo *e = getEntryInCorkQueue (member_scope);
12203671ad72SMasatake YAMATO if (e)
12213671ad72SMasatake YAMATO {
12225fbaed96SMasatake YAMATO e->extensionFields.typeRef [0] = eStrdup ("typename");
12235fbaed96SMasatake YAMATO e->extensionFields.typeRef [1] = vStringDeleteUnwrap (buffer);
12245fbaed96SMasatake YAMATO }
12253671ad72SMasatake YAMATO }
12265fbaed96SMasatake YAMATO else
12275fbaed96SMasatake YAMATO vStringDelete (buffer);
12285fbaed96SMasatake YAMATO }
1229b00d9760SJiří Techet deleteToken (typeToken);
1230b00d9760SJiří Techet }
1231ccf5c712SMasatake YAMATO else if (corks)
1232ccf5c712SMasatake YAMATO {
1233ccf5c712SMasatake YAMATO vString *buffer = vStringNew ();
1234ccf5c712SMasatake YAMATO collector collector = { .str = buffer, .last_len = 0, };
1235ccf5c712SMasatake YAMATO
1236ccf5c712SMasatake YAMATO collectorAppendToken (&collector, token);
1237ccf5c712SMasatake YAMATO skipType (token, &collector);
1238ccf5c712SMasatake YAMATO collectorTruncate (&collector, true);
1239ccf5c712SMasatake YAMATO
1240ccf5c712SMasatake YAMATO if (!vStringIsEmpty (buffer))
124165f5bc5bSMasatake YAMATO attachTypeRefField (scope, corks, vStringValue (buffer));
1242ccf5c712SMasatake YAMATO vStringDelete (buffer);
1243ccf5c712SMasatake YAMATO intArrayClear (corks);
1244ccf5c712SMasatake YAMATO }
1245b00d9760SJiří Techet else
1246469a4eeaSMasatake YAMATO skipType (token, NULL);
1247b00d9760SJiří Techet
12483ae02089SMasatake YAMATO while (!isType (token, TOKEN_SEMICOLON) && !isType (token, TOKEN_CLOSE_PAREN)
12493ae02089SMasatake YAMATO && !isType (token, TOKEN_EOF))
12503ae02089SMasatake YAMATO {
12513ae02089SMasatake YAMATO readToken (token);
1252469a4eeaSMasatake YAMATO skipToMatched (token, NULL);
12533ae02089SMasatake YAMATO }
12543ae02089SMasatake YAMATO
1255c635977cSMasatake YAMATO if (member_scope != scope && member_scope != CORK_NIL)
1256c635977cSMasatake YAMATO {
1257c635977cSMasatake YAMATO tagEntryInfo *e = getEntryInCorkQueue (member_scope);
12583671ad72SMasatake YAMATO if (e)
1259c635977cSMasatake YAMATO e->extensionFields.endLine = getInputLineNumber ();
1260c635977cSMasatake YAMATO }
1261c635977cSMasatake YAMATO
12623ae02089SMasatake YAMATO if (usesParens && !isType (token, TOKEN_CLOSE_PAREN))
12633ae02089SMasatake YAMATO {
12643ae02089SMasatake YAMATO // we are at TOKEN_SEMICOLON
12653ae02089SMasatake YAMATO readToken (token);
12663ae02089SMasatake YAMATO }
12673ae02089SMasatake YAMATO }
12683ae02089SMasatake YAMATO while (!isType (token, TOKEN_EOF) &&
12693ae02089SMasatake YAMATO usesParens && !isType (token, TOKEN_CLOSE_PAREN));
1270ccf5c712SMasatake YAMATO
1271ccf5c712SMasatake YAMATO intArrayDelete (corks);
12723ae02089SMasatake YAMATO }
12733ae02089SMasatake YAMATO
parseImportSpec(tokenInfo * const token)1274d153b5a9SMasatake YAMATO static void parseImportSpec (tokenInfo *const token)
1275d153b5a9SMasatake YAMATO {
1276d153b5a9SMasatake YAMATO // ImportSpec = [ "." | PackageName ] ImportPath .
1277d153b5a9SMasatake YAMATO // ImportPath = string_lit .
1278d153b5a9SMasatake YAMATO
1279d153b5a9SMasatake YAMATO int packageName_cork = CORK_NIL;
1280d153b5a9SMasatake YAMATO char *how_imported = NULL;
1281d153b5a9SMasatake YAMATO if (isType (token, TOKEN_IDENTIFIER))
1282d153b5a9SMasatake YAMATO {
1283d153b5a9SMasatake YAMATO if (strcmp(vStringValue (token->string), "_") == 0)
1284d153b5a9SMasatake YAMATO how_imported = "init";
1285d153b5a9SMasatake YAMATO else
1286d153b5a9SMasatake YAMATO {
1287d153b5a9SMasatake YAMATO packageName_cork = makeTag (token, GOTAG_PACKAGE_NAME,
1288d153b5a9SMasatake YAMATO CORK_NIL, NULL, NULL);
1289d153b5a9SMasatake YAMATO }
1290d153b5a9SMasatake YAMATO readToken (token);
1291d153b5a9SMasatake YAMATO }
1292d153b5a9SMasatake YAMATO else if (isType (token, TOKEN_DOT))
1293d153b5a9SMasatake YAMATO {
1294d153b5a9SMasatake YAMATO how_imported = "inline";
1295d153b5a9SMasatake YAMATO readToken (token);
1296d153b5a9SMasatake YAMATO }
1297d153b5a9SMasatake YAMATO
1298d153b5a9SMasatake YAMATO if (isType (token, TOKEN_STRING))
1299d153b5a9SMasatake YAMATO {
1300d153b5a9SMasatake YAMATO int package_cork =
1301d153b5a9SMasatake YAMATO makeRefTag (token, GOTAG_PACKAGE, R_GOTAG_PACKAGE_IMPORTED);
1302d153b5a9SMasatake YAMATO
1303d153b5a9SMasatake YAMATO if (package_cork != CORK_NIL && how_imported)
1304d153b5a9SMasatake YAMATO attachParserFieldToCorkEntry (package_cork,
1305d153b5a9SMasatake YAMATO GoFields [F_HOW_IMPORTED].ftype,
1306d153b5a9SMasatake YAMATO how_imported);
1307d153b5a9SMasatake YAMATO
1308d153b5a9SMasatake YAMATO if (packageName_cork != CORK_NIL)
1309d153b5a9SMasatake YAMATO {
1310d153b5a9SMasatake YAMATO attachParserFieldToCorkEntry (packageName_cork,
1311d153b5a9SMasatake YAMATO GoFields [F_PACKAGE].ftype,
1312d153b5a9SMasatake YAMATO vStringValue (token->string));
1313d153b5a9SMasatake YAMATO if (package_cork != CORK_NIL)
1314d153b5a9SMasatake YAMATO {
1315d153b5a9SMasatake YAMATO tagEntryInfo *e = getEntryInCorkQueue (packageName_cork);
13163671ad72SMasatake YAMATO if (e)
1317d153b5a9SMasatake YAMATO attachParserFieldToCorkEntry (package_cork,
1318d153b5a9SMasatake YAMATO GoFields [F_PACKAGE_NAME].ftype,
1319d153b5a9SMasatake YAMATO e->name);
1320d153b5a9SMasatake YAMATO }
1321d153b5a9SMasatake YAMATO }
1322d153b5a9SMasatake YAMATO }
1323d153b5a9SMasatake YAMATO }
1324d153b5a9SMasatake YAMATO
parseImport(tokenInfo * const token)1325d153b5a9SMasatake YAMATO static void parseImport (tokenInfo *const token)
1326d153b5a9SMasatake YAMATO {
1327d153b5a9SMasatake YAMATO // ImportDecl = "import" ( ImportSpec | "(" { ImportSpec ";" } ")" ) .
1328d153b5a9SMasatake YAMATO
1329d153b5a9SMasatake YAMATO readToken (token);
1330d153b5a9SMasatake YAMATO if (isType (token, TOKEN_EOF))
1331d153b5a9SMasatake YAMATO return;
1332d153b5a9SMasatake YAMATO
1333d153b5a9SMasatake YAMATO if (isType (token, TOKEN_OPEN_PAREN))
1334d153b5a9SMasatake YAMATO {
1335d153b5a9SMasatake YAMATO do
1336d153b5a9SMasatake YAMATO {
1337d153b5a9SMasatake YAMATO parseImportSpec (token);
1338d153b5a9SMasatake YAMATO readToken (token);
1339d153b5a9SMasatake YAMATO } while (!isType (token, TOKEN_EOF) &&
1340d153b5a9SMasatake YAMATO !isType (token, TOKEN_CLOSE_PAREN));
1341d153b5a9SMasatake YAMATO }
1342d153b5a9SMasatake YAMATO else
1343d153b5a9SMasatake YAMATO {
1344d153b5a9SMasatake YAMATO parseImportSpec (token);
1345d153b5a9SMasatake YAMATO return;
1346d153b5a9SMasatake YAMATO }
1347d153b5a9SMasatake YAMATO }
1348d153b5a9SMasatake YAMATO
parseGoFile(tokenInfo * const token)13493ae02089SMasatake YAMATO static void parseGoFile (tokenInfo *const token)
13503ae02089SMasatake YAMATO {
13515c7bd5b5SMasatake YAMATO int scope = CORK_NIL;
13523ae02089SMasatake YAMATO do
13533ae02089SMasatake YAMATO {
13543ae02089SMasatake YAMATO readToken (token);
13553ae02089SMasatake YAMATO
13563ae02089SMasatake YAMATO if (isType (token, TOKEN_KEYWORD))
13573ae02089SMasatake YAMATO {
13583ae02089SMasatake YAMATO switch (token->keyword)
13593ae02089SMasatake YAMATO {
13603ae02089SMasatake YAMATO case KEYWORD_package:
13615c7bd5b5SMasatake YAMATO scope = parsePackage (token);
13623ae02089SMasatake YAMATO break;
13633ae02089SMasatake YAMATO case KEYWORD_func:
13645c7bd5b5SMasatake YAMATO parseFunctionOrMethod (token, scope);
13653ae02089SMasatake YAMATO break;
13663ae02089SMasatake YAMATO case KEYWORD_const:
13675c7bd5b5SMasatake YAMATO parseConstTypeVar (token, GOTAG_CONST, scope);
13683ae02089SMasatake YAMATO break;
13693ae02089SMasatake YAMATO case KEYWORD_type:
13705c7bd5b5SMasatake YAMATO parseConstTypeVar (token, GOTAG_TYPE, scope);
13713ae02089SMasatake YAMATO break;
13723ae02089SMasatake YAMATO case KEYWORD_var:
13735c7bd5b5SMasatake YAMATO parseConstTypeVar (token, GOTAG_VAR, scope);
13743ae02089SMasatake YAMATO break;
1375d153b5a9SMasatake YAMATO case KEYWORD_import:
1376d153b5a9SMasatake YAMATO parseImport (token);
1377d153b5a9SMasatake YAMATO break;
13783ae02089SMasatake YAMATO default:
13793ae02089SMasatake YAMATO break;
13803ae02089SMasatake YAMATO }
13813ae02089SMasatake YAMATO }
13823ae02089SMasatake YAMATO else if (isType (token, TOKEN_OPEN_PAREN) || isType (token, TOKEN_OPEN_CURLY) ||
13833ae02089SMasatake YAMATO isType (token, TOKEN_OPEN_SQUARE))
13843ae02089SMasatake YAMATO {
1385469a4eeaSMasatake YAMATO skipToMatched (token, NULL);
13863ae02089SMasatake YAMATO }
13873ae02089SMasatake YAMATO } while (token->type != TOKEN_EOF);
13883ae02089SMasatake YAMATO }
13893ae02089SMasatake YAMATO
findGoTags(void)13903ae02089SMasatake YAMATO static void findGoTags (void)
13913ae02089SMasatake YAMATO {
13923ae02089SMasatake YAMATO tokenInfo *const token = newToken ();
13933ae02089SMasatake YAMATO
13943ae02089SMasatake YAMATO parseGoFile (token);
13953ae02089SMasatake YAMATO
13963ae02089SMasatake YAMATO deleteToken (token);
13973ae02089SMasatake YAMATO }
13983ae02089SMasatake YAMATO
GoParser(void)13993ae02089SMasatake YAMATO extern parserDefinition *GoParser (void)
14003ae02089SMasatake YAMATO {
14013ae02089SMasatake YAMATO static const char *const extensions[] = { "go", NULL };
14023ae02089SMasatake YAMATO parserDefinition *def = parserNew ("Go");
140309ae690fSMasatake YAMATO def->kindTable = GoKinds;
14043db72c21SMasatake YAMATO def->kindCount = ARRAY_SIZE (GoKinds);
14053ae02089SMasatake YAMATO def->extensions = extensions;
14063ae02089SMasatake YAMATO def->parser = findGoTags;
14073ae02089SMasatake YAMATO def->initialize = initialize;
14086cbb2243SMasatake YAMATO def->finalize = finalize;
1409c379c5d2SMasatake YAMATO def->keywordTable = GoKeywordTable;
14103db72c21SMasatake YAMATO def->keywordCount = ARRAY_SIZE (GoKeywordTable);
1411d153b5a9SMasatake YAMATO def->fieldTable = GoFields;
1412d153b5a9SMasatake YAMATO def->fieldCount = ARRAY_SIZE (GoFields);
141365f5bc5bSMasatake YAMATO def->useCork = CORK_QUEUE | CORK_SYMTAB;
14145c7bd5b5SMasatake YAMATO def->requestAutomaticFQTag = true;
14153ae02089SMasatake YAMATO return def;
14163ae02089SMasatake YAMATO }
1417