xref: /Universal-ctags/parsers/go.c (revision aaaac7eeac8399141aa8e6d9e6ec0379931848b2)
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