xref: /Universal-ctags/parsers/objc.c (revision 3671ad7255885a0c8f6ff4979d80c70f201ea411)
13ae02089SMasatake YAMATO 
23ae02089SMasatake YAMATO /*
33ae02089SMasatake YAMATO *   Copyright (c) 2010, Vincent Berthoux
43ae02089SMasatake YAMATO *
53ae02089SMasatake YAMATO *   This source code is released for free distribution under the terms of the
60ce38835Sviccuad *   GNU General Public License version 2 or (at your option) any later version.
73ae02089SMasatake YAMATO *
83ae02089SMasatake YAMATO *   This module contains functions for generating tags for Objective C
93ae02089SMasatake YAMATO *   language files.
103ae02089SMasatake YAMATO */
113ae02089SMasatake YAMATO /*
123ae02089SMasatake YAMATO *   INCLUDE FILES
133ae02089SMasatake YAMATO */
143ae02089SMasatake YAMATO #include "general.h"	/* must always come first */
153ae02089SMasatake YAMATO 
163ae02089SMasatake YAMATO #include <string.h>
173ae02089SMasatake YAMATO 
183ae02089SMasatake YAMATO #include "keyword.h"
19a67d9dbeSMasatake YAMATO #include "debug.h"
203ae02089SMasatake YAMATO #include "entry.h"
210d502ef0SMasatake YAMATO #include "parse.h"
223ae02089SMasatake YAMATO #include "read.h"
233ae02089SMasatake YAMATO #include "routines.h"
2467b3f87eSMasatake YAMATO #include "selectors.h"
25d650c941SMasatake YAMATO #include "trashbox.h"
263ae02089SMasatake YAMATO #include "vstring.h"
273ae02089SMasatake YAMATO 
283ae02089SMasatake YAMATO typedef enum {
293ae02089SMasatake YAMATO 	K_INTERFACE,
303ae02089SMasatake YAMATO 	K_IMPLEMENTATION,
313ae02089SMasatake YAMATO 	K_PROTOCOL,
323ae02089SMasatake YAMATO 	K_METHOD,
333ae02089SMasatake YAMATO 	K_CLASSMETHOD,
343ae02089SMasatake YAMATO 	K_VAR,
353ae02089SMasatake YAMATO 	K_FIELD,
363ae02089SMasatake YAMATO 	K_FUNCTION,
373ae02089SMasatake YAMATO 	K_PROPERTY,
383ae02089SMasatake YAMATO 	K_TYPEDEF,
393ae02089SMasatake YAMATO 	K_STRUCT,
403ae02089SMasatake YAMATO 	K_ENUM,
419af73c5bSMasatake YAMATO 	K_MACRO,
429af73c5bSMasatake YAMATO 	K_CATEGORY,
433ae02089SMasatake YAMATO } objcKind;
443ae02089SMasatake YAMATO 
45e112e8abSMasatake YAMATO static kindDefinition ObjcKinds[] = {
46ce990805SThomas Braun 	{true, 'i', "interface", "class interface"},
47ce990805SThomas Braun 	{true, 'I', "implementation", "class implementation"},
48ce990805SThomas Braun 	{true, 'P', "protocol", "Protocol"},
49ce990805SThomas Braun 	{true, 'm', "method", "Object's method"},
50ce990805SThomas Braun 	{true, 'c', "class", "Class' method"},
51ce990805SThomas Braun 	{true, 'v', "var", "Global variable"},
528050d8baSMasatake YAMATO 	{true, 'E', "field", "Object field"},
53ce990805SThomas Braun 	{true, 'f', "function", "A function"},
54ce990805SThomas Braun 	{true, 'p', "property", "A property"},
55ce990805SThomas Braun 	{true, 't', "typedef", "A type alias"},
56ce990805SThomas Braun 	{true, 's', "struct", "A type structure"},
57ce990805SThomas Braun 	{true, 'e', "enum", "An enumeration"},
58ce990805SThomas Braun 	{true, 'M', "macro", "A preprocessor macro"},
599af73c5bSMasatake YAMATO 	{true, 'C', "category", "categories"},
603ae02089SMasatake YAMATO };
613ae02089SMasatake YAMATO 
623ae02089SMasatake YAMATO typedef enum {
633ae02089SMasatake YAMATO 	ObjcTYPEDEF,
643ae02089SMasatake YAMATO 	ObjcSTRUCT,
653ae02089SMasatake YAMATO 	ObjcENUM,
663ae02089SMasatake YAMATO 	ObjcIMPLEMENTATION,
673ae02089SMasatake YAMATO 	ObjcINTERFACE,
683ae02089SMasatake YAMATO 	ObjcPROTOCOL,
693ae02089SMasatake YAMATO 	ObjcENCODE,
702b88b85fSMasatake YAMATO 	ObjcEXTERN,
713ae02089SMasatake YAMATO 	ObjcSYNCHRONIZED,
723ae02089SMasatake YAMATO 	ObjcSELECTOR,
733ae02089SMasatake YAMATO 	ObjcPROPERTY,
743ae02089SMasatake YAMATO 	ObjcEND,
753ae02089SMasatake YAMATO 	ObjcDEFS,
763ae02089SMasatake YAMATO 	ObjcCLASS,
773ae02089SMasatake YAMATO 	ObjcPRIVATE,
783ae02089SMasatake YAMATO 	ObjcPACKAGE,
793ae02089SMasatake YAMATO 	ObjcPUBLIC,
803ae02089SMasatake YAMATO 	ObjcPROTECTED,
813ae02089SMasatake YAMATO 	ObjcSYNTHESIZE,
823ae02089SMasatake YAMATO 	ObjcDYNAMIC,
833ae02089SMasatake YAMATO 	ObjcOPTIONAL,
843ae02089SMasatake YAMATO 	ObjcREQUIRED,
853ae02089SMasatake YAMATO 	ObjcSTRING,
863ae02089SMasatake YAMATO 	ObjcIDENTIFIER,
873ae02089SMasatake YAMATO 
883ae02089SMasatake YAMATO 	Tok_COMA,	/* ',' */
893ae02089SMasatake YAMATO 	Tok_PLUS,	/* '+' */
903ae02089SMasatake YAMATO 	Tok_MINUS,	/* '-' */
913ae02089SMasatake YAMATO 	Tok_PARL,	/* '(' */
923ae02089SMasatake YAMATO 	Tok_PARR,	/* ')' */
933ae02089SMasatake YAMATO 	Tok_CurlL,	/* '{' */
943ae02089SMasatake YAMATO 	Tok_CurlR,	/* '}' */
953ae02089SMasatake YAMATO 	Tok_SQUAREL,	/* '[' */
963ae02089SMasatake YAMATO 	Tok_SQUARER,	/* ']' */
973ae02089SMasatake YAMATO 	Tok_semi,	/* ';' */
983ae02089SMasatake YAMATO 	Tok_dpoint,	/* ':' */
993ae02089SMasatake YAMATO 	Tok_Sharp,	/* '#' */
1003ae02089SMasatake YAMATO 	Tok_Backslash,	/* '\\' */
10180eb4460SMasatake YAMATO 	Tok_Asterisk,	/* '*' */
102d650c941SMasatake YAMATO 	Tok_ANGLEL,		/* '<' */
103d650c941SMasatake YAMATO 	Tok_ANGLER,		/* '>' */
1043ae02089SMasatake YAMATO 	Tok_EOL,	/* '\r''\n' */
1052b88b85fSMasatake YAMATO 	Tok_CSTRING,	/* "..." */
1063ae02089SMasatake YAMATO 	Tok_any,
1073ae02089SMasatake YAMATO 
1083ae02089SMasatake YAMATO 	Tok_EOF	/* END of file */
1093ae02089SMasatake YAMATO } objcKeyword;
1103ae02089SMasatake YAMATO 
1113ae02089SMasatake YAMATO typedef objcKeyword objcToken;
1123ae02089SMasatake YAMATO 
11382c11d8cSRich Siegel static const keywordTable objcKeywordTable[] = {
1143ae02089SMasatake YAMATO 	{"typedef", ObjcTYPEDEF},
1153ae02089SMasatake YAMATO 	{"struct", ObjcSTRUCT},
1163ae02089SMasatake YAMATO 	{"enum", ObjcENUM},
1172b88b85fSMasatake YAMATO 	{"extern", ObjcEXTERN},
1183ae02089SMasatake YAMATO 	{"@implementation", ObjcIMPLEMENTATION},
1193ae02089SMasatake YAMATO 	{"@interface", ObjcINTERFACE},
1203ae02089SMasatake YAMATO 	{"@protocol", ObjcPROTOCOL},
1213ae02089SMasatake YAMATO 	{"@encode", ObjcENCODE},
1223ae02089SMasatake YAMATO 	{"@property", ObjcPROPERTY},
1233ae02089SMasatake YAMATO 	{"@synchronized", ObjcSYNCHRONIZED},
1243ae02089SMasatake YAMATO 	{"@selector", ObjcSELECTOR},
1253ae02089SMasatake YAMATO 	{"@end", ObjcEND},
1263ae02089SMasatake YAMATO 	{"@defs", ObjcDEFS},
1273ae02089SMasatake YAMATO 	{"@class", ObjcCLASS},
1283ae02089SMasatake YAMATO 	{"@private", ObjcPRIVATE},
1293ae02089SMasatake YAMATO 	{"@package", ObjcPACKAGE},
1303ae02089SMasatake YAMATO 	{"@public", ObjcPUBLIC},
1313ae02089SMasatake YAMATO 	{"@protected", ObjcPROTECTED},
1323ae02089SMasatake YAMATO 	{"@synthesize", ObjcSYNTHESIZE},
1333ae02089SMasatake YAMATO 	{"@dynamic", ObjcDYNAMIC},
1343ae02089SMasatake YAMATO 	{"@optional", ObjcOPTIONAL},
1353ae02089SMasatake YAMATO 	{"@required", ObjcREQUIRED},
1363ae02089SMasatake YAMATO };
1373ae02089SMasatake YAMATO 
1389af73c5bSMasatake YAMATO typedef enum {
1399af73c5bSMasatake YAMATO 	F_CATEGORY,
140d650c941SMasatake YAMATO 	F_PROTOCOLS,
1419af73c5bSMasatake YAMATO } objcField;
1429af73c5bSMasatake YAMATO 
1439af73c5bSMasatake YAMATO static fieldDefinition ObjcFields [] = {
1449af73c5bSMasatake YAMATO 	{
1459af73c5bSMasatake YAMATO 		.name = "category",
1469af73c5bSMasatake YAMATO 		.description = "category attached to the class",
1479af73c5bSMasatake YAMATO 		.enabled = true,
1489af73c5bSMasatake YAMATO 	},
149d650c941SMasatake YAMATO 	{
150d650c941SMasatake YAMATO 		.name = "protocols",
151d650c941SMasatake YAMATO 		.description = "protocols that the class (or category) confirms to",
152d650c941SMasatake YAMATO 		.enabled = true,
153d650c941SMasatake YAMATO 	},
1549af73c5bSMasatake YAMATO };
1559af73c5bSMasatake YAMATO 
1563ae02089SMasatake YAMATO static langType Lang_ObjectiveC;
1573ae02089SMasatake YAMATO 
1583ae02089SMasatake YAMATO /*//////////////////////////////////////////////////////////////////
1593ae02089SMasatake YAMATO //// lexingInit             */
1603ae02089SMasatake YAMATO typedef struct _lexingState {
1613ae02089SMasatake YAMATO 	vString *name;	/* current parsed identifier/operator */
1623ae02089SMasatake YAMATO 	const unsigned char *cp;	/* position in stream */
1633ae02089SMasatake YAMATO } lexingState;
1643ae02089SMasatake YAMATO 
1653ae02089SMasatake YAMATO /*//////////////////////////////////////////////////////////////////////
1663ae02089SMasatake YAMATO //// Lexing                                     */
isNum(char c)167ce990805SThomas Braun static bool isNum (char c)
1683ae02089SMasatake YAMATO {
1693ae02089SMasatake YAMATO 	return c >= '0' && c <= '9';
1703ae02089SMasatake YAMATO }
1713ae02089SMasatake YAMATO 
isLowerAlpha(char c)172ce990805SThomas Braun static bool isLowerAlpha (char c)
1733ae02089SMasatake YAMATO {
1743ae02089SMasatake YAMATO 	return c >= 'a' && c <= 'z';
1753ae02089SMasatake YAMATO }
1763ae02089SMasatake YAMATO 
isUpperAlpha(char c)177ce990805SThomas Braun static bool isUpperAlpha (char c)
1783ae02089SMasatake YAMATO {
1793ae02089SMasatake YAMATO 	return c >= 'A' && c <= 'Z';
1803ae02089SMasatake YAMATO }
1813ae02089SMasatake YAMATO 
isAlpha(char c)182ce990805SThomas Braun static bool isAlpha (char c)
1833ae02089SMasatake YAMATO {
1843ae02089SMasatake YAMATO 	return isLowerAlpha (c) || isUpperAlpha (c);
1853ae02089SMasatake YAMATO }
1863ae02089SMasatake YAMATO 
isIdent(char c)187ce990805SThomas Braun static bool isIdent (char c)
1883ae02089SMasatake YAMATO {
1893ae02089SMasatake YAMATO 	return isNum (c) || isAlpha (c) || c == '_';
1903ae02089SMasatake YAMATO }
1913ae02089SMasatake YAMATO 
isSpace(char c)192ce990805SThomas Braun static bool isSpace (char c)
1933ae02089SMasatake YAMATO {
1943ae02089SMasatake YAMATO 	return c == ' ' || c == '\t';
1953ae02089SMasatake YAMATO }
1963ae02089SMasatake YAMATO 
1973ae02089SMasatake YAMATO /* return true if it end with an end of line */
eatWhiteSpace(lexingState * st)1983ae02089SMasatake YAMATO static void eatWhiteSpace (lexingState * st)
1993ae02089SMasatake YAMATO {
2003ae02089SMasatake YAMATO 	const unsigned char *cp = st->cp;
2013ae02089SMasatake YAMATO 	while (isSpace (*cp))
2023ae02089SMasatake YAMATO 		cp++;
2033ae02089SMasatake YAMATO 
2043ae02089SMasatake YAMATO 	st->cp = cp;
2053ae02089SMasatake YAMATO }
2063ae02089SMasatake YAMATO 
readCString(lexingState * st)2072b88b85fSMasatake YAMATO static void readCString (lexingState * st)
2083ae02089SMasatake YAMATO {
209ce990805SThomas Braun 	bool lastIsBackSlash = false;
210ce990805SThomas Braun 	bool unfinished = true;
2113ae02089SMasatake YAMATO 	const unsigned char *c = st->cp + 1;
2123ae02089SMasatake YAMATO 
2132b88b85fSMasatake YAMATO 	vStringClear (st->name);
2142b88b85fSMasatake YAMATO 
2153ae02089SMasatake YAMATO 	while (unfinished)
2163ae02089SMasatake YAMATO 	{
2173ae02089SMasatake YAMATO 		/* end of line should never happen.
2183ae02089SMasatake YAMATO 		 * we tolerate it */
2193ae02089SMasatake YAMATO 		if (c == NULL || c[0] == '\0')
2203ae02089SMasatake YAMATO 			break;
2213ae02089SMasatake YAMATO 		else if (*c == '"' && !lastIsBackSlash)
222ce990805SThomas Braun 			unfinished = false;
2233ae02089SMasatake YAMATO 		else
2242b88b85fSMasatake YAMATO 		{
2253ae02089SMasatake YAMATO 			lastIsBackSlash = *c == '\\';
2262b88b85fSMasatake YAMATO 			vStringPut (st->name, (int) *c);
2272b88b85fSMasatake YAMATO 		}
2283ae02089SMasatake YAMATO 
2293ae02089SMasatake YAMATO 		c++;
2303ae02089SMasatake YAMATO 	}
2313ae02089SMasatake YAMATO 
2323ae02089SMasatake YAMATO 	st->cp = c;
2333ae02089SMasatake YAMATO }
2343ae02089SMasatake YAMATO 
eatComment(lexingState * st)2353ae02089SMasatake YAMATO static void eatComment (lexingState * st)
2363ae02089SMasatake YAMATO {
237ce990805SThomas Braun 	bool unfinished = true;
238ce990805SThomas Braun 	bool lastIsStar = false;
2393ae02089SMasatake YAMATO 	const unsigned char *c = st->cp + 2;
2403ae02089SMasatake YAMATO 
2413ae02089SMasatake YAMATO 	while (unfinished)
2423ae02089SMasatake YAMATO 	{
2433ae02089SMasatake YAMATO 		/* we've reached the end of the line..
2443ae02089SMasatake YAMATO 		 * so we have to reload a line... */
2453ae02089SMasatake YAMATO 		if (c == NULL || *c == '\0')
2463ae02089SMasatake YAMATO 		{
2471b312fe7SMasatake YAMATO 			st->cp = readLineFromInputFile ();
2483ae02089SMasatake YAMATO 			/* WOOPS... no more input...
2493ae02089SMasatake YAMATO 			 * we return, next lexing read
2503ae02089SMasatake YAMATO 			 * will be null and ok */
2513ae02089SMasatake YAMATO 			if (st->cp == NULL)
2523ae02089SMasatake YAMATO 				return;
2533ae02089SMasatake YAMATO 			c = st->cp;
2543ae02089SMasatake YAMATO 		}
2553ae02089SMasatake YAMATO 		/* we've reached the end of the comment */
2563ae02089SMasatake YAMATO 		else if (*c == '/' && lastIsStar)
257ce990805SThomas Braun 			unfinished = false;
2583ae02089SMasatake YAMATO 		else
2593ae02089SMasatake YAMATO 		{
2603ae02089SMasatake YAMATO 			lastIsStar = '*' == *c;
2613ae02089SMasatake YAMATO 			c++;
2623ae02089SMasatake YAMATO 		}
2633ae02089SMasatake YAMATO 	}
2643ae02089SMasatake YAMATO 
2653ae02089SMasatake YAMATO 	st->cp = c;
2663ae02089SMasatake YAMATO }
2673ae02089SMasatake YAMATO 
readIdentifier(lexingState * st)2683ae02089SMasatake YAMATO static void readIdentifier (lexingState * st)
2693ae02089SMasatake YAMATO {
2703ae02089SMasatake YAMATO 	const unsigned char *p;
2713ae02089SMasatake YAMATO 	vStringClear (st->name);
2723ae02089SMasatake YAMATO 
2733ae02089SMasatake YAMATO 	/* first char is a simple letter */
2743ae02089SMasatake YAMATO 	if (isAlpha (*st->cp) || *st->cp == '_')
2753ae02089SMasatake YAMATO 		vStringPut (st->name, (int) *st->cp);
2763ae02089SMasatake YAMATO 
2773ae02089SMasatake YAMATO 	/* Go till you get identifier chars */
2783ae02089SMasatake YAMATO 	for (p = st->cp + 1; isIdent (*p); p++)
2793ae02089SMasatake YAMATO 		vStringPut (st->name, (int) *p);
2803ae02089SMasatake YAMATO 
2813ae02089SMasatake YAMATO 	st->cp = p;
2823ae02089SMasatake YAMATO }
2833ae02089SMasatake YAMATO 
2843ae02089SMasatake YAMATO /* read the @something directives */
readIdentifierObjcDirective(lexingState * st)2853ae02089SMasatake YAMATO static void readIdentifierObjcDirective (lexingState * st)
2863ae02089SMasatake YAMATO {
2873ae02089SMasatake YAMATO 	const unsigned char *p;
2883ae02089SMasatake YAMATO 	vStringClear (st->name);
2893ae02089SMasatake YAMATO 
2903ae02089SMasatake YAMATO 	/* first char is a simple letter */
2913ae02089SMasatake YAMATO 	if (*st->cp == '@')
2923ae02089SMasatake YAMATO 		vStringPut (st->name, (int) *st->cp);
2933ae02089SMasatake YAMATO 
2943ae02089SMasatake YAMATO 	/* Go till you get identifier chars */
2953ae02089SMasatake YAMATO 	for (p = st->cp + 1; isIdent (*p); p++)
2963ae02089SMasatake YAMATO 		vStringPut (st->name, (int) *p);
2973ae02089SMasatake YAMATO 
2983ae02089SMasatake YAMATO 	st->cp = p;
2993ae02089SMasatake YAMATO }
3003ae02089SMasatake YAMATO 
3013ae02089SMasatake YAMATO /* The lexer is in charge of reading the file.
3023ae02089SMasatake YAMATO  * Some of sub-lexer (like eatComment) also read file.
3033ae02089SMasatake YAMATO  * lexing is finished when the lexer return Tok_EOF */
lex(lexingState * st)3043ae02089SMasatake YAMATO static objcKeyword lex (lexingState * st)
3053ae02089SMasatake YAMATO {
3063ae02089SMasatake YAMATO 	int retType;
3073ae02089SMasatake YAMATO 
3083ae02089SMasatake YAMATO 	/* handling data input here */
3093ae02089SMasatake YAMATO 	while (st->cp == NULL || st->cp[0] == '\0')
3103ae02089SMasatake YAMATO 	{
3111b312fe7SMasatake YAMATO 		st->cp = readLineFromInputFile ();
3123ae02089SMasatake YAMATO 		if (st->cp == NULL)
3133ae02089SMasatake YAMATO 			return Tok_EOF;
3143ae02089SMasatake YAMATO 
3153ae02089SMasatake YAMATO 		return Tok_EOL;
3163ae02089SMasatake YAMATO 	}
3173ae02089SMasatake YAMATO 
31894653669SRich Siegel 	if (isAlpha (*st->cp) || (*st->cp == '_'))
3193ae02089SMasatake YAMATO 	{
3203ae02089SMasatake YAMATO 		readIdentifier (st);
3213ae02089SMasatake YAMATO 		retType = lookupKeyword (vStringValue (st->name), Lang_ObjectiveC);
3223ae02089SMasatake YAMATO 
3233ae02089SMasatake YAMATO 		if (retType == -1)	/* If it's not a keyword */
3243ae02089SMasatake YAMATO 		{
3253ae02089SMasatake YAMATO 			return ObjcIDENTIFIER;
3263ae02089SMasatake YAMATO 		}
3273ae02089SMasatake YAMATO 		else
3283ae02089SMasatake YAMATO 		{
3293ae02089SMasatake YAMATO 			return retType;
3303ae02089SMasatake YAMATO 		}
3313ae02089SMasatake YAMATO 	}
3323ae02089SMasatake YAMATO 	else if (*st->cp == '@')
3333ae02089SMasatake YAMATO 	{
3343ae02089SMasatake YAMATO 		readIdentifierObjcDirective (st);
3353ae02089SMasatake YAMATO 		retType = lookupKeyword (vStringValue (st->name), Lang_ObjectiveC);
3363ae02089SMasatake YAMATO 
3373ae02089SMasatake YAMATO 		if (retType == -1)	/* If it's not a keyword */
3383ae02089SMasatake YAMATO 		{
3393ae02089SMasatake YAMATO 			return Tok_any;
3403ae02089SMasatake YAMATO 		}
3413ae02089SMasatake YAMATO 		else
3423ae02089SMasatake YAMATO 		{
3433ae02089SMasatake YAMATO 			return retType;
3443ae02089SMasatake YAMATO 		}
3453ae02089SMasatake YAMATO 	}
3463ae02089SMasatake YAMATO 	else if (isSpace (*st->cp))
3473ae02089SMasatake YAMATO 	{
3483ae02089SMasatake YAMATO 		eatWhiteSpace (st);
3493ae02089SMasatake YAMATO 		return lex (st);
3503ae02089SMasatake YAMATO 	}
3513ae02089SMasatake YAMATO 	else
3523ae02089SMasatake YAMATO 		switch (*st->cp)
3533ae02089SMasatake YAMATO 		{
3543ae02089SMasatake YAMATO 		case '(':
3553ae02089SMasatake YAMATO 			st->cp++;
3563ae02089SMasatake YAMATO 			return Tok_PARL;
3573ae02089SMasatake YAMATO 
3583ae02089SMasatake YAMATO 		case '\\':
3593ae02089SMasatake YAMATO 			st->cp++;
3603ae02089SMasatake YAMATO 			return Tok_Backslash;
3613ae02089SMasatake YAMATO 
3623ae02089SMasatake YAMATO 		case '#':
3633ae02089SMasatake YAMATO 			st->cp++;
3643ae02089SMasatake YAMATO 			return Tok_Sharp;
3653ae02089SMasatake YAMATO 
3663ae02089SMasatake YAMATO 		case '/':
3673ae02089SMasatake YAMATO 			if (st->cp[1] == '*')	/* ergl, a comment */
3683ae02089SMasatake YAMATO 			{
3693ae02089SMasatake YAMATO 				eatComment (st);
3703ae02089SMasatake YAMATO 				return lex (st);
3713ae02089SMasatake YAMATO 			}
3723ae02089SMasatake YAMATO 			else if (st->cp[1] == '/')
3733ae02089SMasatake YAMATO 			{
3743ae02089SMasatake YAMATO 				st->cp = NULL;
3753ae02089SMasatake YAMATO 				return lex (st);
3763ae02089SMasatake YAMATO 			}
3773ae02089SMasatake YAMATO 			else
3783ae02089SMasatake YAMATO 			{
3793ae02089SMasatake YAMATO 				st->cp++;
3803ae02089SMasatake YAMATO 				return Tok_any;
3813ae02089SMasatake YAMATO 			}
3823ae02089SMasatake YAMATO 			break;
3833ae02089SMasatake YAMATO 
3843ae02089SMasatake YAMATO 		case ')':
3853ae02089SMasatake YAMATO 			st->cp++;
3863ae02089SMasatake YAMATO 			return Tok_PARR;
3873ae02089SMasatake YAMATO 		case '{':
3883ae02089SMasatake YAMATO 			st->cp++;
3893ae02089SMasatake YAMATO 			return Tok_CurlL;
3903ae02089SMasatake YAMATO 		case '}':
3913ae02089SMasatake YAMATO 			st->cp++;
3923ae02089SMasatake YAMATO 			return Tok_CurlR;
3933ae02089SMasatake YAMATO 		case '[':
3943ae02089SMasatake YAMATO 			st->cp++;
3953ae02089SMasatake YAMATO 			return Tok_SQUAREL;
3963ae02089SMasatake YAMATO 		case ']':
3973ae02089SMasatake YAMATO 			st->cp++;
3983ae02089SMasatake YAMATO 			return Tok_SQUARER;
3993ae02089SMasatake YAMATO 		case ',':
4003ae02089SMasatake YAMATO 			st->cp++;
4013ae02089SMasatake YAMATO 			return Tok_COMA;
4023ae02089SMasatake YAMATO 		case ';':
4033ae02089SMasatake YAMATO 			st->cp++;
4043ae02089SMasatake YAMATO 			return Tok_semi;
4053ae02089SMasatake YAMATO 		case ':':
4063ae02089SMasatake YAMATO 			st->cp++;
4073ae02089SMasatake YAMATO 			return Tok_dpoint;
4083ae02089SMasatake YAMATO 		case '"':
4092b88b85fSMasatake YAMATO 			readCString (st);
4102b88b85fSMasatake YAMATO 			return Tok_CSTRING;
4113ae02089SMasatake YAMATO 		case '+':
4123ae02089SMasatake YAMATO 			st->cp++;
4133ae02089SMasatake YAMATO 			return Tok_PLUS;
4143ae02089SMasatake YAMATO 		case '-':
4153ae02089SMasatake YAMATO 			st->cp++;
4163ae02089SMasatake YAMATO 			return Tok_MINUS;
41780eb4460SMasatake YAMATO 		case '*':
41880eb4460SMasatake YAMATO 			st->cp++;
41980eb4460SMasatake YAMATO 			return Tok_Asterisk;
420d650c941SMasatake YAMATO 		case '<':
421d650c941SMasatake YAMATO 			st->cp++;
422d650c941SMasatake YAMATO 			return Tok_ANGLEL;
423d650c941SMasatake YAMATO 		case '>':
424d650c941SMasatake YAMATO 			st->cp++;
425d650c941SMasatake YAMATO 			return Tok_ANGLER;
4263ae02089SMasatake YAMATO 
4273ae02089SMasatake YAMATO 		default:
4283ae02089SMasatake YAMATO 			st->cp++;
4293ae02089SMasatake YAMATO 			break;
4303ae02089SMasatake YAMATO 		}
4313ae02089SMasatake YAMATO 
4323ae02089SMasatake YAMATO 	/* default return if nothing is recognized,
4333ae02089SMasatake YAMATO 	 * shouldn't happen, but at least, it will
4343ae02089SMasatake YAMATO 	 * be handled without destroying the parsing. */
4353ae02089SMasatake YAMATO 	return Tok_any;
4363ae02089SMasatake YAMATO }
4373ae02089SMasatake YAMATO 
4383ae02089SMasatake YAMATO /*//////////////////////////////////////////////////////////////////////
4393ae02089SMasatake YAMATO //// Parsing                                    */
4403ae02089SMasatake YAMATO typedef void (*parseNext) (vString * const ident, objcToken what);
4413ae02089SMasatake YAMATO 
4423ae02089SMasatake YAMATO /********** Helpers */
4433ae02089SMasatake YAMATO /* This variable hold the 'parser' which is going to
4443ae02089SMasatake YAMATO  * handle the next token */
4453ae02089SMasatake YAMATO static parseNext toDoNext;
4463ae02089SMasatake YAMATO 
4473ae02089SMasatake YAMATO /* Special variable used by parser eater to
4483ae02089SMasatake YAMATO  * determine which action to put after their
4493ae02089SMasatake YAMATO  * job is finished. */
4503ae02089SMasatake YAMATO static parseNext comeAfter;
4513ae02089SMasatake YAMATO 
4523ae02089SMasatake YAMATO /* Used by some parsers detecting certain token
4533ae02089SMasatake YAMATO  * to revert to previous parser. */
4543ae02089SMasatake YAMATO static parseNext fallback;
4553ae02089SMasatake YAMATO 
4563ae02089SMasatake YAMATO 
4573ae02089SMasatake YAMATO /********** Grammar */
4583ae02089SMasatake YAMATO static void globalScope (vString * const ident, objcToken what);
4593ae02089SMasatake YAMATO static void parseMethods (vString * const ident, objcToken what);
4603ae02089SMasatake YAMATO static void parseImplemMethods (vString * const ident, objcToken what);
4613ae02089SMasatake YAMATO static vString *tempName = NULL;
4623ae02089SMasatake YAMATO static vString *parentName = NULL;
4633ae02089SMasatake YAMATO static objcKind parentType = K_INTERFACE;
4643afb5475SMasatake YAMATO static int parentCorkIndex = CORK_NIL;
4653afb5475SMasatake YAMATO static int categoryCorkIndex = CORK_NIL;
4663ae02089SMasatake YAMATO 
4673ae02089SMasatake YAMATO /* used to prepare tag for OCaml, just in case their is a need to
4683ae02089SMasatake YAMATO  * add additional information to the tag. */
prepareTag(tagEntryInfo * tag,vString const * name,objcKind kind)4693ae02089SMasatake YAMATO static void prepareTag (tagEntryInfo * tag, vString const *name, objcKind kind)
4703ae02089SMasatake YAMATO {
47116a2541cSMasatake YAMATO 	initTagEntry (tag, vStringValue (name), kind);
4723ae02089SMasatake YAMATO 
473c848d905SMasatake YAMATO 	if (vStringLength (parentName) > 0)
4743ae02089SMasatake YAMATO 	{
475f92e6bf2SMasatake YAMATO 		tag->extensionFields.scopeKindIndex = parentType;
476015ab54cSMasatake YAMATO 		tag->extensionFields.scopeName = vStringValue (parentName);
4773ae02089SMasatake YAMATO 	}
4783ae02089SMasatake YAMATO }
4793ae02089SMasatake YAMATO 
pushEnclosingContext(const vString * parent,objcKind type)4803ae02089SMasatake YAMATO static void pushEnclosingContext (const vString * parent, objcKind type)
4813ae02089SMasatake YAMATO {
4823ae02089SMasatake YAMATO 	vStringCopy (parentName, parent);
4833ae02089SMasatake YAMATO 	parentType = type;
4843ae02089SMasatake YAMATO }
4853ae02089SMasatake YAMATO 
pushEnclosingContextFull(const vString * parent,objcKind type,int corkIndex)4863afb5475SMasatake YAMATO static void pushEnclosingContextFull (const vString * parent, objcKind type, int corkIndex)
487a67d9dbeSMasatake YAMATO {
488a67d9dbeSMasatake YAMATO 	pushEnclosingContext (parent, type);
489a67d9dbeSMasatake YAMATO 	parentCorkIndex = corkIndex;
490a67d9dbeSMasatake YAMATO }
491a67d9dbeSMasatake YAMATO 
popEnclosingContext(void)4923ae02089SMasatake YAMATO static void popEnclosingContext (void)
4933ae02089SMasatake YAMATO {
4943ae02089SMasatake YAMATO 	vStringClear (parentName);
49509152b33SMasatake YAMATO 	parentCorkIndex = CORK_NIL;
4963ae02089SMasatake YAMATO }
4973ae02089SMasatake YAMATO 
pushCategoryContext(int category_index)4983afb5475SMasatake YAMATO static void pushCategoryContext (int category_index)
4999af73c5bSMasatake YAMATO {
5009af73c5bSMasatake YAMATO 	categoryCorkIndex = category_index;
5019af73c5bSMasatake YAMATO }
5029af73c5bSMasatake YAMATO 
popCategoryContext(void)5039af73c5bSMasatake YAMATO static void popCategoryContext (void)
5049af73c5bSMasatake YAMATO {
5059af73c5bSMasatake YAMATO 	categoryCorkIndex = CORK_NIL;
5069af73c5bSMasatake YAMATO }
5079af73c5bSMasatake YAMATO 
5083ae02089SMasatake YAMATO /* Used to centralise tag creation, and be able to add
5093ae02089SMasatake YAMATO  * more information to it in the future */
addTag(vString * const ident,int kind)51080eb4460SMasatake YAMATO static int addTag (vString * const ident, int kind)
5113ae02089SMasatake YAMATO {
5123ae02089SMasatake YAMATO 	tagEntryInfo toCreate;
5134a95e4a5SColomban Wendling 
5144a95e4a5SColomban Wendling 	if (! ObjcKinds[kind].enabled)
51580eb4460SMasatake YAMATO 		return CORK_NIL;
5164a95e4a5SColomban Wendling 
5173ae02089SMasatake YAMATO 	prepareTag (&toCreate, ident, kind);
51880eb4460SMasatake YAMATO 	return makeTagEntry (&toCreate);
5193ae02089SMasatake YAMATO }
5203ae02089SMasatake YAMATO 
5213ae02089SMasatake YAMATO static objcToken waitedToken, fallBackToken;
5223ae02089SMasatake YAMATO 
5233ae02089SMasatake YAMATO /* Ignore everything till waitedToken and jump to comeAfter.
5243ae02089SMasatake YAMATO  * If the "end" keyword is encountered break, doesn't remember
5253ae02089SMasatake YAMATO  * why though. */
tillToken(vString * const ident CTAGS_ATTR_UNUSED,objcToken what)5268ccb7ee9SJiří Techet static void tillToken (vString * const ident CTAGS_ATTR_UNUSED, objcToken what)
5273ae02089SMasatake YAMATO {
5283ae02089SMasatake YAMATO 	if (what == waitedToken)
5293ae02089SMasatake YAMATO 		toDoNext = comeAfter;
5303ae02089SMasatake YAMATO }
5313ae02089SMasatake YAMATO 
tillTokenOrFallBack(vString * const ident CTAGS_ATTR_UNUSED,objcToken what)5328ccb7ee9SJiří Techet static void tillTokenOrFallBack (vString * const ident CTAGS_ATTR_UNUSED, objcToken what)
5333ae02089SMasatake YAMATO {
5343ae02089SMasatake YAMATO 	if (what == waitedToken)
5353ae02089SMasatake YAMATO 		toDoNext = comeAfter;
5363ae02089SMasatake YAMATO 	else if (what == fallBackToken)
5373ae02089SMasatake YAMATO 	{
5383ae02089SMasatake YAMATO 		toDoNext = fallback;
5393ae02089SMasatake YAMATO 	}
5403ae02089SMasatake YAMATO }
5413ae02089SMasatake YAMATO 
5423ae02089SMasatake YAMATO static int ignoreBalanced_count = 0;
ignoreBalanced(vString * const ident CTAGS_ATTR_UNUSED,objcToken what)5438ccb7ee9SJiří Techet static void ignoreBalanced (vString * const ident CTAGS_ATTR_UNUSED, objcToken what)
5443ae02089SMasatake YAMATO {
5453ae02089SMasatake YAMATO 
5463ae02089SMasatake YAMATO 	switch (what)
5473ae02089SMasatake YAMATO 	{
5483ae02089SMasatake YAMATO 	case Tok_PARL:
5493ae02089SMasatake YAMATO 	case Tok_CurlL:
5503ae02089SMasatake YAMATO 	case Tok_SQUAREL:
5513ae02089SMasatake YAMATO 		ignoreBalanced_count++;
5523ae02089SMasatake YAMATO 		break;
5533ae02089SMasatake YAMATO 
5543ae02089SMasatake YAMATO 	case Tok_PARR:
5553ae02089SMasatake YAMATO 	case Tok_CurlR:
5563ae02089SMasatake YAMATO 	case Tok_SQUARER:
5573ae02089SMasatake YAMATO 		ignoreBalanced_count--;
5583ae02089SMasatake YAMATO 		break;
5593ae02089SMasatake YAMATO 
5603ae02089SMasatake YAMATO 	default:
5613ae02089SMasatake YAMATO 		/* don't care */
5623ae02089SMasatake YAMATO 		break;
5633ae02089SMasatake YAMATO 	}
5643ae02089SMasatake YAMATO 
5653ae02089SMasatake YAMATO 	if (ignoreBalanced_count == 0)
5663ae02089SMasatake YAMATO 		toDoNext = comeAfter;
5673ae02089SMasatake YAMATO }
5683ae02089SMasatake YAMATO 
parseFields(vString * const ident,objcToken what)5693ae02089SMasatake YAMATO static void parseFields (vString * const ident, objcToken what)
5703ae02089SMasatake YAMATO {
5713ae02089SMasatake YAMATO 	switch (what)
5723ae02089SMasatake YAMATO 	{
5733ae02089SMasatake YAMATO 	case Tok_CurlR:
5743ae02089SMasatake YAMATO 		toDoNext = &parseMethods;
5753ae02089SMasatake YAMATO 		break;
5763ae02089SMasatake YAMATO 
5773ae02089SMasatake YAMATO 	case Tok_SQUAREL:
5783ae02089SMasatake YAMATO 	case Tok_PARL:
5793ae02089SMasatake YAMATO 		toDoNext = &ignoreBalanced;
5803ae02089SMasatake YAMATO 		comeAfter = &parseFields;
5813ae02089SMasatake YAMATO 		break;
5823ae02089SMasatake YAMATO 
5833ae02089SMasatake YAMATO 		/* we got an identifier, keep track of it */
5843ae02089SMasatake YAMATO 	case ObjcIDENTIFIER:
5853ae02089SMasatake YAMATO 		vStringCopy (tempName, ident);
5863ae02089SMasatake YAMATO 		break;
5873ae02089SMasatake YAMATO 
5883ae02089SMasatake YAMATO 		/* our last kept identifier must be our variable name =) */
5893ae02089SMasatake YAMATO 	case Tok_semi:
5903ae02089SMasatake YAMATO 		addTag (tempName, K_FIELD);
5913ae02089SMasatake YAMATO 		vStringClear (tempName);
5923ae02089SMasatake YAMATO 		break;
5933ae02089SMasatake YAMATO 
5943ae02089SMasatake YAMATO 	default:
5953ae02089SMasatake YAMATO 		/* NOTHING */
5963ae02089SMasatake YAMATO 		break;
5973ae02089SMasatake YAMATO 	}
5983ae02089SMasatake YAMATO }
5993ae02089SMasatake YAMATO 
6003ae02089SMasatake YAMATO static objcKind methodKind;
6013ae02089SMasatake YAMATO 
6023ae02089SMasatake YAMATO 
6033ae02089SMasatake YAMATO static vString *fullMethodName;
6043ae02089SMasatake YAMATO static vString *prevIdent;
60580eb4460SMasatake YAMATO static vString *signature;
60680eb4460SMasatake YAMATO 
tillTokenWithCapturingSignature(vString * const ident,objcToken what)60780eb4460SMasatake YAMATO static void tillTokenWithCapturingSignature (vString * const ident, objcToken what)
60880eb4460SMasatake YAMATO {
60980eb4460SMasatake YAMATO 	tillToken (ident, what);
61080eb4460SMasatake YAMATO 
61180eb4460SMasatake YAMATO 	if (what != waitedToken)
61280eb4460SMasatake YAMATO 	{
61380eb4460SMasatake YAMATO 		if (what == Tok_Asterisk)
61480eb4460SMasatake YAMATO 			vStringPut (signature, '*');
61580eb4460SMasatake YAMATO 		else if (vStringLength (ident) > 0)
61680eb4460SMasatake YAMATO 		{
61780eb4460SMasatake YAMATO 			if (! (vStringLast (signature) == ','
61880eb4460SMasatake YAMATO 				   || vStringLast (signature) == '('
61980eb4460SMasatake YAMATO 				   || vStringLast (signature) == ' '))
62080eb4460SMasatake YAMATO 				vStringPut (signature, ' ');
62180eb4460SMasatake YAMATO 
62280eb4460SMasatake YAMATO 			vStringCat (signature, ident);
62380eb4460SMasatake YAMATO 		}
62480eb4460SMasatake YAMATO 	}
62580eb4460SMasatake YAMATO }
6263ae02089SMasatake YAMATO 
parseMethodsNameCommon(vString * const ident,objcToken what,parseNext reEnter,parseNext nextAction)6279f8df264SMasatake YAMATO static void parseMethodsNameCommon (vString * const ident, objcToken what,
6289f8df264SMasatake YAMATO 									parseNext reEnter,
6299f8df264SMasatake YAMATO 									parseNext nextAction)
6303ae02089SMasatake YAMATO {
6313afb5475SMasatake YAMATO 	int index;
63280eb4460SMasatake YAMATO 
6333ae02089SMasatake YAMATO 	switch (what)
6343ae02089SMasatake YAMATO 	{
6353ae02089SMasatake YAMATO 	case Tok_PARL:
6363ae02089SMasatake YAMATO 		toDoNext = &tillToken;
6379f8df264SMasatake YAMATO 		comeAfter = reEnter;
6383ae02089SMasatake YAMATO 		waitedToken = Tok_PARR;
63980eb4460SMasatake YAMATO 
64080eb4460SMasatake YAMATO 		if (! (vStringLength(prevIdent) == 0
64180eb4460SMasatake YAMATO 			   && vStringLength(fullMethodName) == 0))
64280eb4460SMasatake YAMATO 			toDoNext = &tillTokenWithCapturingSignature;
6433ae02089SMasatake YAMATO 		break;
6443ae02089SMasatake YAMATO 
6453ae02089SMasatake YAMATO 	case Tok_dpoint:
6463ae02089SMasatake YAMATO 		vStringCat (fullMethodName, prevIdent);
6471da6e7e4SMasatake YAMATO 		vStringPut (fullMethodName, ':');
6483ae02089SMasatake YAMATO 		vStringClear (prevIdent);
64980eb4460SMasatake YAMATO 
65080eb4460SMasatake YAMATO 		if (vStringLength (signature) > 1)
65180eb4460SMasatake YAMATO 			vStringPut (signature, ',');
6523ae02089SMasatake YAMATO 		break;
6533ae02089SMasatake YAMATO 
6543ae02089SMasatake YAMATO 	case ObjcIDENTIFIER:
65580eb4460SMasatake YAMATO 		if ((vStringLength (prevIdent) > 0
65680eb4460SMasatake YAMATO 			 /* "- initWithObject: o0 withAnotherObject: o1;"
65780eb4460SMasatake YAMATO 				Overwriting the last value of prevIdent ("o0");
65880eb4460SMasatake YAMATO 				a parameter name ("o0") was stored to prevIdent,
65980eb4460SMasatake YAMATO 				and a part of selector("withAnotherObject")
66080eb4460SMasatake YAMATO 				overwrites it.
66180eb4460SMasatake YAMATO 				If type for the parameter specified explicitly,
66280eb4460SMasatake YAMATO 				the last char of signature should not be ',' nor
66380eb4460SMasatake YAMATO 				'('. In this case, "id" must be put as the type for
66480eb4460SMasatake YAMATO 				the parameter. */
66580eb4460SMasatake YAMATO 			 && (vStringLast (signature) == ','
66680eb4460SMasatake YAMATO 				 || vStringLast (signature) == '('))
66780eb4460SMasatake YAMATO 			|| (/* "- initWithObject: object;"
66880eb4460SMasatake YAMATO 				   In this case no overwriting happens.
66980eb4460SMasatake YAMATO 				   However, "id" for "object" is part
67080eb4460SMasatake YAMATO 				   of signature. */
67180eb4460SMasatake YAMATO 				vStringLength (prevIdent) == 0
67280eb4460SMasatake YAMATO 				&& vStringLength (fullMethodName) > 0
67380eb4460SMasatake YAMATO 				&& vStringLast (signature) == '('))
67480eb4460SMasatake YAMATO 			vStringCatS (signature, "id");
67580eb4460SMasatake YAMATO 
6763ae02089SMasatake YAMATO 		vStringCopy (prevIdent, ident);
6773ae02089SMasatake YAMATO 		break;
6783ae02089SMasatake YAMATO 
6793ae02089SMasatake YAMATO 	case Tok_CurlL:
6803ae02089SMasatake YAMATO 	case Tok_semi:
6813ae02089SMasatake YAMATO 		/* method name is not simple */
6823ae02089SMasatake YAMATO 		if (vStringLength (fullMethodName) != '\0')
6833ae02089SMasatake YAMATO 		{
68480eb4460SMasatake YAMATO 			index = addTag (fullMethodName, methodKind);
6853ae02089SMasatake YAMATO 			vStringClear (fullMethodName);
6863ae02089SMasatake YAMATO 		}
6873ae02089SMasatake YAMATO 		else
68880eb4460SMasatake YAMATO 			index = addTag (prevIdent, methodKind);
6893ae02089SMasatake YAMATO 
6909f8df264SMasatake YAMATO 		toDoNext = nextAction;
6913ae02089SMasatake YAMATO 		parseImplemMethods (ident, what);
6923ae02089SMasatake YAMATO 		vStringClear (prevIdent);
69380eb4460SMasatake YAMATO 
69480eb4460SMasatake YAMATO 		tagEntryInfo *e = getEntryInCorkQueue (index);
695*3671ad72SMasatake YAMATO 		if (e)
696*3671ad72SMasatake YAMATO 		{
69780eb4460SMasatake YAMATO 			if (vStringLast (signature) == ',')
69880eb4460SMasatake YAMATO 				vStringCatS (signature, "id");
69980eb4460SMasatake YAMATO 			vStringPut (signature, ')');
70080eb4460SMasatake YAMATO 
701f270909bSMasatake YAMATO 			e->extensionFields.signature = vStringStrdup (signature);
70280eb4460SMasatake YAMATO 
70380eb4460SMasatake YAMATO 			vStringClear (signature);
70480eb4460SMasatake YAMATO 			vStringPut (signature, '(');
70566fba980SMasatake YAMATO 
706*3671ad72SMasatake YAMATO 			tagEntryInfo *e_cat = getEntryInCorkQueue (categoryCorkIndex);
707*3671ad72SMasatake YAMATO 			if (e_cat)
70866fba980SMasatake YAMATO 				attachParserFieldToCorkEntry (index,
70966fba980SMasatake YAMATO 											  ObjcFields [F_CATEGORY].ftype,
710*3671ad72SMasatake YAMATO 											  e_cat->name);
71180eb4460SMasatake YAMATO 		}
7123ae02089SMasatake YAMATO 		break;
7133ae02089SMasatake YAMATO 
7143ae02089SMasatake YAMATO 	default:
7153ae02089SMasatake YAMATO 		break;
7163ae02089SMasatake YAMATO 	}
7173ae02089SMasatake YAMATO }
7183ae02089SMasatake YAMATO 
parseMethodsName(vString * const ident,objcToken what)7199f8df264SMasatake YAMATO static void parseMethodsName (vString * const ident, objcToken what)
7209f8df264SMasatake YAMATO {
7219f8df264SMasatake YAMATO 	parseMethodsNameCommon (ident, what, parseMethodsName, parseMethods);
7229f8df264SMasatake YAMATO }
7239f8df264SMasatake YAMATO 
parseMethodsImplemName(vString * const ident,objcToken what)7243ae02089SMasatake YAMATO static void parseMethodsImplemName (vString * const ident, objcToken what)
7253ae02089SMasatake YAMATO {
7269f8df264SMasatake YAMATO 	parseMethodsNameCommon (ident, what, parseMethodsImplemName, parseImplemMethods);
7273ae02089SMasatake YAMATO }
7283ae02089SMasatake YAMATO 
parseCategory(vString * const ident,objcToken what)7299af73c5bSMasatake YAMATO static void parseCategory (vString * const ident, objcToken what)
7309af73c5bSMasatake YAMATO {
7319af73c5bSMasatake YAMATO 	if (what == ObjcIDENTIFIER)
7329af73c5bSMasatake YAMATO 	{
7339af73c5bSMasatake YAMATO 		tagEntryInfo *e = getEntryInCorkQueue (parentCorkIndex);
7349af73c5bSMasatake YAMATO 		if (e)
735*3671ad72SMasatake YAMATO 		{
7369af73c5bSMasatake YAMATO 			attachParserFieldToCorkEntry (parentCorkIndex,
7379af73c5bSMasatake YAMATO 										  ObjcFields [F_CATEGORY].ftype,
7389af73c5bSMasatake YAMATO 										  vStringValue (ident));
7399af73c5bSMasatake YAMATO 			if (e->kindIndex == K_INTERFACE)
7409af73c5bSMasatake YAMATO 				toDoNext = &parseMethods;
7419af73c5bSMasatake YAMATO 			else
7429af73c5bSMasatake YAMATO 				toDoNext = &parseImplemMethods;
743*3671ad72SMasatake YAMATO 		}
7449af73c5bSMasatake YAMATO 
7453afb5475SMasatake YAMATO 		int index = addTag (ident, K_CATEGORY);
7469af73c5bSMasatake YAMATO 		pushCategoryContext (index);
7479af73c5bSMasatake YAMATO 	}
7489af73c5bSMasatake YAMATO }
7499af73c5bSMasatake YAMATO 
parseImplemMethods(vString * const ident,objcToken what)7503ae02089SMasatake YAMATO static void parseImplemMethods (vString * const ident, objcToken what)
7513ae02089SMasatake YAMATO {
7523ae02089SMasatake YAMATO 	switch (what)
7533ae02089SMasatake YAMATO 	{
7543ae02089SMasatake YAMATO 	case Tok_PLUS:	/* + */
7553ae02089SMasatake YAMATO 		toDoNext = &parseMethodsImplemName;
7563ae02089SMasatake YAMATO 		methodKind = K_CLASSMETHOD;
7573ae02089SMasatake YAMATO 		break;
7583ae02089SMasatake YAMATO 
7593ae02089SMasatake YAMATO 	case Tok_MINUS:	/* - */
7603ae02089SMasatake YAMATO 		toDoNext = &parseMethodsImplemName;
7613ae02089SMasatake YAMATO 		methodKind = K_METHOD;
7623ae02089SMasatake YAMATO 		break;
7633ae02089SMasatake YAMATO 
7643ae02089SMasatake YAMATO 	case ObjcEND:	/* @end */
7653ae02089SMasatake YAMATO 		popEnclosingContext ();
7669af73c5bSMasatake YAMATO 		popCategoryContext ();
7673ae02089SMasatake YAMATO 		toDoNext = &globalScope;
7683ae02089SMasatake YAMATO 		break;
7693ae02089SMasatake YAMATO 
7703ae02089SMasatake YAMATO 	case Tok_CurlL:	/* { */
7713ae02089SMasatake YAMATO 		toDoNext = &ignoreBalanced;
7723ae02089SMasatake YAMATO 		ignoreBalanced (ident, what);
7733ae02089SMasatake YAMATO 		comeAfter = &parseImplemMethods;
7743ae02089SMasatake YAMATO 		break;
7753ae02089SMasatake YAMATO 
7769af73c5bSMasatake YAMATO 	case Tok_PARL: /* ( */
7779af73c5bSMasatake YAMATO 		toDoNext = &parseCategory;
7789af73c5bSMasatake YAMATO 		break;
7799af73c5bSMasatake YAMATO 
7803ae02089SMasatake YAMATO 	default:
7813ae02089SMasatake YAMATO 		break;
7823ae02089SMasatake YAMATO 	}
7833ae02089SMasatake YAMATO }
7843ae02089SMasatake YAMATO 
parseProperty(vString * const ident,objcToken what)7853ae02089SMasatake YAMATO static void parseProperty (vString * const ident, objcToken what)
7863ae02089SMasatake YAMATO {
7873ae02089SMasatake YAMATO 	switch (what)
7883ae02089SMasatake YAMATO 	{
7893ae02089SMasatake YAMATO 	case Tok_PARL:
7903ae02089SMasatake YAMATO 		toDoNext = &tillToken;
7913ae02089SMasatake YAMATO 		comeAfter = &parseProperty;
7923ae02089SMasatake YAMATO 		waitedToken = Tok_PARR;
7933ae02089SMasatake YAMATO 		break;
7943ae02089SMasatake YAMATO 
7953ae02089SMasatake YAMATO 		/* we got an identifier, keep track of it */
7963ae02089SMasatake YAMATO 	case ObjcIDENTIFIER:
7973ae02089SMasatake YAMATO 		vStringCopy (tempName, ident);
7983ae02089SMasatake YAMATO 		break;
7993ae02089SMasatake YAMATO 
8003ae02089SMasatake YAMATO 		/* our last kept identifier must be our variable name =) */
8013ae02089SMasatake YAMATO 	case Tok_semi:
8023ae02089SMasatake YAMATO 		addTag (tempName, K_PROPERTY);
8033ae02089SMasatake YAMATO 		vStringClear (tempName);
80421e74e6aSsolawing 		toDoNext = &parseMethods;
8053ae02089SMasatake YAMATO 		break;
8063ae02089SMasatake YAMATO 
8073ae02089SMasatake YAMATO 	default:
8083ae02089SMasatake YAMATO 		break;
8093ae02089SMasatake YAMATO 	}
8103ae02089SMasatake YAMATO }
8113ae02089SMasatake YAMATO 
parseInterfaceSuperclass(vString * const ident,objcToken what)812a67d9dbeSMasatake YAMATO static void parseInterfaceSuperclass (vString * const ident, objcToken what)
813a67d9dbeSMasatake YAMATO {
814a67d9dbeSMasatake YAMATO 	tagEntryInfo *e = getEntryInCorkQueue (parentCorkIndex);
815*3671ad72SMasatake YAMATO 	if (what == ObjcIDENTIFIER && e)
816a67d9dbeSMasatake YAMATO 		e->extensionFields.inheritance = vStringStrdup (ident);
817a67d9dbeSMasatake YAMATO 
818a67d9dbeSMasatake YAMATO 	toDoNext = &parseMethods;
819a67d9dbeSMasatake YAMATO }
820a67d9dbeSMasatake YAMATO 
parseInterfaceProtocolList(vString * const ident,objcToken what)821d650c941SMasatake YAMATO static void parseInterfaceProtocolList (vString * const ident, objcToken what)
822d650c941SMasatake YAMATO {
823d650c941SMasatake YAMATO 	static vString *protocol_list;
824d650c941SMasatake YAMATO 
825d650c941SMasatake YAMATO 	if (parentCorkIndex == CORK_NIL)
826d650c941SMasatake YAMATO 	{
827d650c941SMasatake YAMATO 		toDoNext = &parseMethods;
828d650c941SMasatake YAMATO 		return;
829d650c941SMasatake YAMATO 	}
830d650c941SMasatake YAMATO 
831d650c941SMasatake YAMATO 	if (protocol_list == NULL)
832d650c941SMasatake YAMATO 	{
833d650c941SMasatake YAMATO 		protocol_list = vStringNew ();
834d650c941SMasatake YAMATO 		DEFAULT_TRASH_BOX(protocol_list, vStringDelete);
835d650c941SMasatake YAMATO 	}
836d650c941SMasatake YAMATO 
837d650c941SMasatake YAMATO 	if (what == ObjcIDENTIFIER)
838d650c941SMasatake YAMATO 		vStringCat(protocol_list, ident);
839d650c941SMasatake YAMATO 	else if (what == Tok_COMA)
840d650c941SMasatake YAMATO 		vStringPut (protocol_list, ',');
841d650c941SMasatake YAMATO 	else if (what == Tok_ANGLER)
842d650c941SMasatake YAMATO 	{
843d650c941SMasatake YAMATO 		attachParserFieldToCorkEntry (parentCorkIndex,
844d650c941SMasatake YAMATO 									  ObjcFields [F_PROTOCOLS].ftype,
845d650c941SMasatake YAMATO 									  vStringValue (protocol_list));
846d650c941SMasatake YAMATO 		if (categoryCorkIndex != CORK_NIL)
847d650c941SMasatake YAMATO 			attachParserFieldToCorkEntry (categoryCorkIndex,
848d650c941SMasatake YAMATO 										  ObjcFields [F_PROTOCOLS].ftype,
849d650c941SMasatake YAMATO 										  vStringValue (protocol_list));
850d650c941SMasatake YAMATO 		vStringClear (protocol_list);
851d650c941SMasatake YAMATO 		toDoNext = &parseMethods;
852d650c941SMasatake YAMATO 	}
853d650c941SMasatake YAMATO }
854d650c941SMasatake YAMATO 
parseMethods(vString * const ident CTAGS_ATTR_UNUSED,objcToken what)8558ccb7ee9SJiří Techet static void parseMethods (vString * const ident CTAGS_ATTR_UNUSED, objcToken what)
8563ae02089SMasatake YAMATO {
8573ae02089SMasatake YAMATO 	switch (what)
8583ae02089SMasatake YAMATO 	{
8593ae02089SMasatake YAMATO 	case Tok_PLUS:	/* + */
8603ae02089SMasatake YAMATO 		toDoNext = &parseMethodsName;
8613ae02089SMasatake YAMATO 		methodKind = K_CLASSMETHOD;
8623ae02089SMasatake YAMATO 		break;
8633ae02089SMasatake YAMATO 
8643ae02089SMasatake YAMATO 	case Tok_MINUS:	/* - */
8653ae02089SMasatake YAMATO 		toDoNext = &parseMethodsName;
8663ae02089SMasatake YAMATO 		methodKind = K_METHOD;
8673ae02089SMasatake YAMATO 		break;
8683ae02089SMasatake YAMATO 
8693ae02089SMasatake YAMATO 	case ObjcPROPERTY:
8703ae02089SMasatake YAMATO 		toDoNext = &parseProperty;
8713ae02089SMasatake YAMATO 		break;
8723ae02089SMasatake YAMATO 
8733ae02089SMasatake YAMATO 	case ObjcEND:	/* @end */
8743ae02089SMasatake YAMATO 		popEnclosingContext ();
8759af73c5bSMasatake YAMATO 		popCategoryContext ();
8763ae02089SMasatake YAMATO 		toDoNext = &globalScope;
8773ae02089SMasatake YAMATO 		break;
8783ae02089SMasatake YAMATO 
8793ae02089SMasatake YAMATO 	case Tok_CurlL:	/* { */
8803ae02089SMasatake YAMATO 		toDoNext = &parseFields;
8813ae02089SMasatake YAMATO 		break;
8823ae02089SMasatake YAMATO 
883a67d9dbeSMasatake YAMATO 	case Tok_dpoint: /* : */
884a67d9dbeSMasatake YAMATO 		toDoNext = &parseInterfaceSuperclass;
885a67d9dbeSMasatake YAMATO 		break;
886a67d9dbeSMasatake YAMATO 
8879af73c5bSMasatake YAMATO 	case Tok_PARL: /* ( */
8889af73c5bSMasatake YAMATO 		toDoNext = &parseCategory;
8899af73c5bSMasatake YAMATO 		break;
8909af73c5bSMasatake YAMATO 
891d650c941SMasatake YAMATO 	case Tok_ANGLEL: /* < */
892d650c941SMasatake YAMATO 		toDoNext = &parseInterfaceProtocolList;
893d650c941SMasatake YAMATO 		break;
894d650c941SMasatake YAMATO 
8953ae02089SMasatake YAMATO 	default:
8963ae02089SMasatake YAMATO 		break;
8973ae02089SMasatake YAMATO 	}
8983ae02089SMasatake YAMATO }
8993ae02089SMasatake YAMATO 
9003ae02089SMasatake YAMATO 
parseProtocol(vString * const ident,objcToken what)9013ae02089SMasatake YAMATO static void parseProtocol (vString * const ident, objcToken what)
9023ae02089SMasatake YAMATO {
9033ae02089SMasatake YAMATO 	if (what == ObjcIDENTIFIER)
9043ae02089SMasatake YAMATO 	{
9053afb5475SMasatake YAMATO 		int index = addTag (ident, K_PROTOCOL);
906f92402a3SMasatake YAMATO 		pushEnclosingContextFull (ident, K_PROTOCOL, index);
9073ae02089SMasatake YAMATO 	}
9083ae02089SMasatake YAMATO 	toDoNext = &parseMethods;
9093ae02089SMasatake YAMATO }
9103ae02089SMasatake YAMATO 
parseImplementation(vString * const ident,objcToken what)9113ae02089SMasatake YAMATO static void parseImplementation (vString * const ident, objcToken what)
9123ae02089SMasatake YAMATO {
9133ae02089SMasatake YAMATO 	if (what == ObjcIDENTIFIER)
9143ae02089SMasatake YAMATO 	{
9153afb5475SMasatake YAMATO 		int index = addTag (ident, K_IMPLEMENTATION);
9169af73c5bSMasatake YAMATO 		pushEnclosingContextFull (ident, K_IMPLEMENTATION, index);
9173ae02089SMasatake YAMATO 	}
9183ae02089SMasatake YAMATO 	toDoNext = &parseImplemMethods;
9193ae02089SMasatake YAMATO }
9203ae02089SMasatake YAMATO 
parseInterface(vString * const ident,objcToken what)9213ae02089SMasatake YAMATO static void parseInterface (vString * const ident, objcToken what)
9223ae02089SMasatake YAMATO {
9233ae02089SMasatake YAMATO 	if (what == ObjcIDENTIFIER)
9243ae02089SMasatake YAMATO 	{
9253afb5475SMasatake YAMATO 		int index = addTag (ident, K_INTERFACE);
926a67d9dbeSMasatake YAMATO 		pushEnclosingContextFull (ident, K_INTERFACE, index);
9273ae02089SMasatake YAMATO 	}
9283ae02089SMasatake YAMATO 
9293ae02089SMasatake YAMATO 	toDoNext = &parseMethods;
9303ae02089SMasatake YAMATO }
9313ae02089SMasatake YAMATO 
parseStructMembers(vString * const ident,objcToken what)9323ae02089SMasatake YAMATO static void parseStructMembers (vString * const ident, objcToken what)
9333ae02089SMasatake YAMATO {
9343ae02089SMasatake YAMATO 	static parseNext prev = NULL;
9353ae02089SMasatake YAMATO 
9363ae02089SMasatake YAMATO 	if (prev != NULL)
9373ae02089SMasatake YAMATO 	{
9383ae02089SMasatake YAMATO 		comeAfter = prev;
9393ae02089SMasatake YAMATO 		prev = NULL;
9403ae02089SMasatake YAMATO 	}
9413ae02089SMasatake YAMATO 
9423ae02089SMasatake YAMATO 	switch (what)
9433ae02089SMasatake YAMATO 	{
9443ae02089SMasatake YAMATO 	case ObjcIDENTIFIER:
9453ae02089SMasatake YAMATO 		vStringCopy (tempName, ident);
9463ae02089SMasatake YAMATO 		break;
9473ae02089SMasatake YAMATO 
9483ae02089SMasatake YAMATO 	case Tok_semi:	/* ';' */
9493ae02089SMasatake YAMATO 		addTag (tempName, K_FIELD);
9503ae02089SMasatake YAMATO 		vStringClear (tempName);
9513ae02089SMasatake YAMATO 		break;
9523ae02089SMasatake YAMATO 
9533ae02089SMasatake YAMATO 		/* some types are complex, the only one
9543ae02089SMasatake YAMATO 		 * we will loose is the function type.
9553ae02089SMasatake YAMATO 		 */
9563ae02089SMasatake YAMATO 	case Tok_CurlL:	/* '{' */
9573ae02089SMasatake YAMATO 	case Tok_PARL:	/* '(' */
9583ae02089SMasatake YAMATO 	case Tok_SQUAREL:	/* '[' */
9593ae02089SMasatake YAMATO 		toDoNext = &ignoreBalanced;
9603ae02089SMasatake YAMATO 		prev = comeAfter;
9613ae02089SMasatake YAMATO 		comeAfter = &parseStructMembers;
9623ae02089SMasatake YAMATO 		ignoreBalanced (ident, what);
9633ae02089SMasatake YAMATO 		break;
9643ae02089SMasatake YAMATO 
9653ae02089SMasatake YAMATO 	case Tok_CurlR:
9663ae02089SMasatake YAMATO 		toDoNext = comeAfter;
9673ae02089SMasatake YAMATO 		break;
9683ae02089SMasatake YAMATO 
9693ae02089SMasatake YAMATO 	default:
9703ae02089SMasatake YAMATO 		/* don't care */
9713ae02089SMasatake YAMATO 		break;
9723ae02089SMasatake YAMATO 	}
9733ae02089SMasatake YAMATO }
9743ae02089SMasatake YAMATO 
9753ae02089SMasatake YAMATO /* Called just after the struct keyword */
976ce990805SThomas Braun static bool parseStruct_gotName = false;
parseStruct(vString * const ident,objcToken what)9773ae02089SMasatake YAMATO static void parseStruct (vString * const ident, objcToken what)
9783ae02089SMasatake YAMATO {
9793ae02089SMasatake YAMATO 	switch (what)
9803ae02089SMasatake YAMATO 	{
9813ae02089SMasatake YAMATO 	case ObjcIDENTIFIER:
9823ae02089SMasatake YAMATO 		if (!parseStruct_gotName)
9833ae02089SMasatake YAMATO 		{
9843ae02089SMasatake YAMATO 			addTag (ident, K_STRUCT);
9853ae02089SMasatake YAMATO 			pushEnclosingContext (ident, K_STRUCT);
986ce990805SThomas Braun 			parseStruct_gotName = true;
9873ae02089SMasatake YAMATO 		}
9883ae02089SMasatake YAMATO 		else
9893ae02089SMasatake YAMATO 		{
990ce990805SThomas Braun 			parseStruct_gotName = false;
9913ae02089SMasatake YAMATO 			popEnclosingContext ();
9923ae02089SMasatake YAMATO 			toDoNext = comeAfter;
9933ae02089SMasatake YAMATO 			comeAfter (ident, what);
9943ae02089SMasatake YAMATO 		}
9953ae02089SMasatake YAMATO 		break;
9963ae02089SMasatake YAMATO 
9973ae02089SMasatake YAMATO 	case Tok_CurlL:
9983ae02089SMasatake YAMATO 		toDoNext = &parseStructMembers;
9993ae02089SMasatake YAMATO 		break;
10003ae02089SMasatake YAMATO 
10013ae02089SMasatake YAMATO 		/* maybe it was just a forward declaration
10023ae02089SMasatake YAMATO 		 * in which case, we pop the context */
10033ae02089SMasatake YAMATO 	case Tok_semi:
10043ae02089SMasatake YAMATO 		if (parseStruct_gotName)
10053ae02089SMasatake YAMATO 			popEnclosingContext ();
10063ae02089SMasatake YAMATO 
10073ae02089SMasatake YAMATO 		toDoNext = comeAfter;
10083ae02089SMasatake YAMATO 		comeAfter (ident, what);
10093ae02089SMasatake YAMATO 		break;
10103ae02089SMasatake YAMATO 
10113ae02089SMasatake YAMATO 	default:
10123ae02089SMasatake YAMATO 		/* we don't care */
10133ae02089SMasatake YAMATO 		break;
10143ae02089SMasatake YAMATO 	}
10153ae02089SMasatake YAMATO }
10163ae02089SMasatake YAMATO 
10173ae02089SMasatake YAMATO /* Parse enumeration members, ignoring potential initialization */
10183ae02089SMasatake YAMATO static parseNext parseEnumFields_prev = NULL;
parseEnumFields(vString * const ident,objcToken what)10193ae02089SMasatake YAMATO static void parseEnumFields (vString * const ident, objcToken what)
10203ae02089SMasatake YAMATO {
10213ae02089SMasatake YAMATO 	if (parseEnumFields_prev != NULL)
10223ae02089SMasatake YAMATO 	{
10233ae02089SMasatake YAMATO 		comeAfter = parseEnumFields_prev;
10243ae02089SMasatake YAMATO 		parseEnumFields_prev = NULL;
10253ae02089SMasatake YAMATO 	}
10263ae02089SMasatake YAMATO 
10273ae02089SMasatake YAMATO 	switch (what)
10283ae02089SMasatake YAMATO 	{
10293ae02089SMasatake YAMATO 	case ObjcIDENTIFIER:
10303ae02089SMasatake YAMATO 		addTag (ident, K_ENUM);
10313ae02089SMasatake YAMATO 		parseEnumFields_prev = comeAfter;
10323ae02089SMasatake YAMATO 		waitedToken = Tok_COMA;
10333ae02089SMasatake YAMATO 		/* last item might not have a coma */
10343ae02089SMasatake YAMATO 		fallBackToken = Tok_CurlR;
10353ae02089SMasatake YAMATO 		fallback = comeAfter;
10363ae02089SMasatake YAMATO 		comeAfter = parseEnumFields;
10373ae02089SMasatake YAMATO 		toDoNext = &tillTokenOrFallBack;
10383ae02089SMasatake YAMATO 		break;
10393ae02089SMasatake YAMATO 
10403ae02089SMasatake YAMATO 	case Tok_CurlR:
10413ae02089SMasatake YAMATO 		toDoNext = comeAfter;
10423ae02089SMasatake YAMATO 		popEnclosingContext ();
10433ae02089SMasatake YAMATO 		break;
10443ae02089SMasatake YAMATO 
10453ae02089SMasatake YAMATO 	default:
10463ae02089SMasatake YAMATO 		/* don't care */
10473ae02089SMasatake YAMATO 		break;
10483ae02089SMasatake YAMATO 	}
10493ae02089SMasatake YAMATO }
10503ae02089SMasatake YAMATO 
10513ae02089SMasatake YAMATO /* parse enum ... { ... */
1052ce990805SThomas Braun static bool parseEnum_named = false;
parseEnum(vString * const ident,objcToken what)10533ae02089SMasatake YAMATO static void parseEnum (vString * const ident, objcToken what)
10543ae02089SMasatake YAMATO {
10553ae02089SMasatake YAMATO 	switch (what)
10563ae02089SMasatake YAMATO 	{
10573ae02089SMasatake YAMATO 	case ObjcIDENTIFIER:
10583ae02089SMasatake YAMATO 		if (!parseEnum_named)
10593ae02089SMasatake YAMATO 		{
10603ae02089SMasatake YAMATO 			addTag (ident, K_ENUM);
10613ae02089SMasatake YAMATO 			pushEnclosingContext (ident, K_ENUM);
1062ce990805SThomas Braun 			parseEnum_named = true;
10633ae02089SMasatake YAMATO 		}
10643ae02089SMasatake YAMATO 		else
10653ae02089SMasatake YAMATO 		{
1066ce990805SThomas Braun 			parseEnum_named = false;
10673ae02089SMasatake YAMATO 			popEnclosingContext ();
10683ae02089SMasatake YAMATO 			toDoNext = comeAfter;
10693ae02089SMasatake YAMATO 			comeAfter (ident, what);
10703ae02089SMasatake YAMATO 		}
10713ae02089SMasatake YAMATO 		break;
10723ae02089SMasatake YAMATO 
10733ae02089SMasatake YAMATO 	case Tok_CurlL:	/* '{' */
10743ae02089SMasatake YAMATO 		toDoNext = &parseEnumFields;
1075ce990805SThomas Braun 		parseEnum_named = false;
10763ae02089SMasatake YAMATO 		break;
10773ae02089SMasatake YAMATO 
10783ae02089SMasatake YAMATO 	case Tok_semi:	/* ';' */
10793ae02089SMasatake YAMATO 		if (parseEnum_named)
10803ae02089SMasatake YAMATO 			popEnclosingContext ();
10813ae02089SMasatake YAMATO 		toDoNext = comeAfter;
10823ae02089SMasatake YAMATO 		comeAfter (ident, what);
10833ae02089SMasatake YAMATO 		break;
10843ae02089SMasatake YAMATO 
10853ae02089SMasatake YAMATO 	default:
10863ae02089SMasatake YAMATO 		/* don't care */
10873ae02089SMasatake YAMATO 		break;
10883ae02089SMasatake YAMATO 	}
10893ae02089SMasatake YAMATO }
10903ae02089SMasatake YAMATO 
10913ae02089SMasatake YAMATO /* Parse something like
10923ae02089SMasatake YAMATO  * typedef .... ident ;
10933ae02089SMasatake YAMATO  * ignoring the defined type but in the case of struct,
10943ae02089SMasatake YAMATO  * in which case struct are parsed.
10953ae02089SMasatake YAMATO  */
parseTypedef(vString * const ident,objcToken what)10963ae02089SMasatake YAMATO static void parseTypedef (vString * const ident, objcToken what)
10973ae02089SMasatake YAMATO {
10983ae02089SMasatake YAMATO 	switch (what)
10993ae02089SMasatake YAMATO 	{
11003ae02089SMasatake YAMATO 	case ObjcSTRUCT:
11013ae02089SMasatake YAMATO 		toDoNext = &parseStruct;
11023ae02089SMasatake YAMATO 		comeAfter = &parseTypedef;
11033ae02089SMasatake YAMATO 		break;
11043ae02089SMasatake YAMATO 
11053ae02089SMasatake YAMATO 	case ObjcENUM:
11063ae02089SMasatake YAMATO 		toDoNext = &parseEnum;
11073ae02089SMasatake YAMATO 		comeAfter = &parseTypedef;
11083ae02089SMasatake YAMATO 		break;
11093ae02089SMasatake YAMATO 
11103ae02089SMasatake YAMATO 	case ObjcIDENTIFIER:
11113ae02089SMasatake YAMATO 		vStringCopy (tempName, ident);
11123ae02089SMasatake YAMATO 		break;
11133ae02089SMasatake YAMATO 
11143ae02089SMasatake YAMATO 	case Tok_semi:	/* ';' */
11153ae02089SMasatake YAMATO 		addTag (tempName, K_TYPEDEF);
11163ae02089SMasatake YAMATO 		vStringClear (tempName);
11173ae02089SMasatake YAMATO 		toDoNext = &globalScope;
11183ae02089SMasatake YAMATO 		break;
11193ae02089SMasatake YAMATO 
11203ae02089SMasatake YAMATO 	default:
11213ae02089SMasatake YAMATO 		/* we don't care */
11223ae02089SMasatake YAMATO 		break;
11233ae02089SMasatake YAMATO 	}
11243ae02089SMasatake YAMATO }
11253ae02089SMasatake YAMATO 
1126ce990805SThomas Braun static bool ignorePreprocStuff_escaped = false;
ignorePreprocStuff(vString * const ident CTAGS_ATTR_UNUSED,objcToken what)11278ccb7ee9SJiří Techet static void ignorePreprocStuff (vString * const ident CTAGS_ATTR_UNUSED, objcToken what)
11283ae02089SMasatake YAMATO {
11293ae02089SMasatake YAMATO 	switch (what)
11303ae02089SMasatake YAMATO 	{
11313ae02089SMasatake YAMATO 	case Tok_Backslash:
1132ce990805SThomas Braun 		ignorePreprocStuff_escaped = true;
11333ae02089SMasatake YAMATO 		break;
11343ae02089SMasatake YAMATO 
11353ae02089SMasatake YAMATO 	case Tok_EOL:
11363ae02089SMasatake YAMATO 		if (ignorePreprocStuff_escaped)
11373ae02089SMasatake YAMATO 		{
1138ce990805SThomas Braun 			ignorePreprocStuff_escaped = false;
11393ae02089SMasatake YAMATO 		}
11403ae02089SMasatake YAMATO 		else
11413ae02089SMasatake YAMATO 		{
11423ae02089SMasatake YAMATO 			toDoNext = &globalScope;
11433ae02089SMasatake YAMATO 		}
11443ae02089SMasatake YAMATO 		break;
11453ae02089SMasatake YAMATO 
11463ae02089SMasatake YAMATO 	default:
1147ce990805SThomas Braun 		ignorePreprocStuff_escaped = false;
11483ae02089SMasatake YAMATO 		break;
11493ae02089SMasatake YAMATO 	}
11503ae02089SMasatake YAMATO }
11513ae02089SMasatake YAMATO 
parseMacroName(vString * const ident,objcToken what)11523ae02089SMasatake YAMATO static void parseMacroName (vString * const ident, objcToken what)
11533ae02089SMasatake YAMATO {
11543ae02089SMasatake YAMATO 	if (what == ObjcIDENTIFIER)
11553ae02089SMasatake YAMATO 		addTag (ident, K_MACRO);
11563ae02089SMasatake YAMATO 
11573ae02089SMasatake YAMATO 	toDoNext = &ignorePreprocStuff;
11583ae02089SMasatake YAMATO }
11593ae02089SMasatake YAMATO 
parsePreproc(vString * const ident,objcToken what)11603ae02089SMasatake YAMATO static void parsePreproc (vString * const ident, objcToken what)
11613ae02089SMasatake YAMATO {
11623ae02089SMasatake YAMATO 	switch (what)
11633ae02089SMasatake YAMATO 	{
11643ae02089SMasatake YAMATO 	case ObjcIDENTIFIER:
11653ae02089SMasatake YAMATO 		if (strcmp (vStringValue (ident), "define") == 0)
11663ae02089SMasatake YAMATO 			toDoNext = &parseMacroName;
11673ae02089SMasatake YAMATO 		else
11683ae02089SMasatake YAMATO 			toDoNext = &ignorePreprocStuff;
11693ae02089SMasatake YAMATO 		break;
11703ae02089SMasatake YAMATO 
11713ae02089SMasatake YAMATO 	default:
11723ae02089SMasatake YAMATO 		toDoNext = &ignorePreprocStuff;
11733ae02089SMasatake YAMATO 		break;
11743ae02089SMasatake YAMATO 	}
11753ae02089SMasatake YAMATO }
11763ae02089SMasatake YAMATO 
skipCurlL(vString * const ident,objcToken what)11772b88b85fSMasatake YAMATO static void skipCurlL (vString * const ident, objcToken what)
11782b88b85fSMasatake YAMATO {
11792b88b85fSMasatake YAMATO 	if (what == Tok_CurlL)
11802b88b85fSMasatake YAMATO 		toDoNext = comeAfter;
11812b88b85fSMasatake YAMATO }
11822b88b85fSMasatake YAMATO 
parseCPlusPlusCLinkage(vString * const ident,objcToken what)11832b88b85fSMasatake YAMATO static void parseCPlusPlusCLinkage (vString * const ident, objcToken what)
11842b88b85fSMasatake YAMATO {
11852b88b85fSMasatake YAMATO 	toDoNext = comeAfter;
11862b88b85fSMasatake YAMATO 
11872b88b85fSMasatake YAMATO 	/* Linkage specification like "C" */
11882b88b85fSMasatake YAMATO 	if (what == Tok_CSTRING)
11892b88b85fSMasatake YAMATO 		toDoNext = skipCurlL;
11902b88b85fSMasatake YAMATO 	else
11912b88b85fSMasatake YAMATO 		/* Force handle this ident in globalScope */
11922b88b85fSMasatake YAMATO 		globalScope (ident, what);
11932b88b85fSMasatake YAMATO }
11942b88b85fSMasatake YAMATO 
11953ae02089SMasatake YAMATO /* Handle the "strong" top levels, all 'big' declarations
11963ae02089SMasatake YAMATO  * happen here */
globalScope(vString * const ident,objcToken what)11973ae02089SMasatake YAMATO static void globalScope (vString * const ident, objcToken what)
11983ae02089SMasatake YAMATO {
11993ae02089SMasatake YAMATO 	switch (what)
12003ae02089SMasatake YAMATO 	{
12013ae02089SMasatake YAMATO 	case Tok_Sharp:
12023ae02089SMasatake YAMATO 		toDoNext = &parsePreproc;
12033ae02089SMasatake YAMATO 		break;
12043ae02089SMasatake YAMATO 
12053ae02089SMasatake YAMATO 	case ObjcSTRUCT:
12063ae02089SMasatake YAMATO 		toDoNext = &parseStruct;
12073ae02089SMasatake YAMATO 		comeAfter = &globalScope;
12083ae02089SMasatake YAMATO 		break;
12093ae02089SMasatake YAMATO 
12103ae02089SMasatake YAMATO 	case ObjcIDENTIFIER:
12113ae02089SMasatake YAMATO 		/* we keep track of the identifier if we
12123ae02089SMasatake YAMATO 		 * come across a function. */
12133ae02089SMasatake YAMATO 		vStringCopy (tempName, ident);
12143ae02089SMasatake YAMATO 		break;
12153ae02089SMasatake YAMATO 
12163ae02089SMasatake YAMATO 	case Tok_PARL:
12173ae02089SMasatake YAMATO 		/* if we find an opening parenthesis it means we
12183ae02089SMasatake YAMATO 		 * found a function (or a macro...) */
12193ae02089SMasatake YAMATO 		addTag (tempName, K_FUNCTION);
12203ae02089SMasatake YAMATO 		vStringClear (tempName);
12213ae02089SMasatake YAMATO 		comeAfter = &globalScope;
12223ae02089SMasatake YAMATO 		toDoNext = &ignoreBalanced;
12233ae02089SMasatake YAMATO 		ignoreBalanced (ident, what);
12243ae02089SMasatake YAMATO 		break;
12253ae02089SMasatake YAMATO 
12263ae02089SMasatake YAMATO 	case ObjcINTERFACE:
12273ae02089SMasatake YAMATO 		toDoNext = &parseInterface;
12283ae02089SMasatake YAMATO 		break;
12293ae02089SMasatake YAMATO 
12303ae02089SMasatake YAMATO 	case ObjcIMPLEMENTATION:
12313ae02089SMasatake YAMATO 		toDoNext = &parseImplementation;
12323ae02089SMasatake YAMATO 		break;
12333ae02089SMasatake YAMATO 
12343ae02089SMasatake YAMATO 	case ObjcPROTOCOL:
12353ae02089SMasatake YAMATO 		toDoNext = &parseProtocol;
12363ae02089SMasatake YAMATO 		break;
12373ae02089SMasatake YAMATO 
12383ae02089SMasatake YAMATO 	case ObjcTYPEDEF:
12393ae02089SMasatake YAMATO 		toDoNext = parseTypedef;
12403ae02089SMasatake YAMATO 		comeAfter = &globalScope;
12413ae02089SMasatake YAMATO 		break;
12423ae02089SMasatake YAMATO 
12433ae02089SMasatake YAMATO 	case Tok_CurlL:
12443ae02089SMasatake YAMATO 		comeAfter = &globalScope;
12453ae02089SMasatake YAMATO 		toDoNext = &ignoreBalanced;
12463ae02089SMasatake YAMATO 		ignoreBalanced (ident, what);
12473ae02089SMasatake YAMATO 		break;
12483ae02089SMasatake YAMATO 
12492b88b85fSMasatake YAMATO 	case ObjcEXTERN:
12502b88b85fSMasatake YAMATO 		comeAfter = &globalScope;
12512b88b85fSMasatake YAMATO 		toDoNext = &parseCPlusPlusCLinkage;
12522b88b85fSMasatake YAMATO 		break;
12532b88b85fSMasatake YAMATO 
12543ae02089SMasatake YAMATO 	case ObjcEND:
12553ae02089SMasatake YAMATO 	case ObjcPUBLIC:
12563ae02089SMasatake YAMATO 	case ObjcPROTECTED:
12573ae02089SMasatake YAMATO 	case ObjcPRIVATE:
12583ae02089SMasatake YAMATO 
12593ae02089SMasatake YAMATO 	default:
12603ae02089SMasatake YAMATO 		/* we don't care */
12613ae02089SMasatake YAMATO 		break;
12623ae02089SMasatake YAMATO 	}
12633ae02089SMasatake YAMATO }
12643ae02089SMasatake YAMATO 
12653ae02089SMasatake YAMATO /*////////////////////////////////////////////////////////////////
12663ae02089SMasatake YAMATO //// Deal with the system                                       */
12673ae02089SMasatake YAMATO 
findObjcTags(void)12683ae02089SMasatake YAMATO static void findObjcTags (void)
12693ae02089SMasatake YAMATO {
12703ae02089SMasatake YAMATO 	vString *name = vStringNew ();
12713ae02089SMasatake YAMATO 	lexingState st;
12723ae02089SMasatake YAMATO 	objcToken tok;
12733ae02089SMasatake YAMATO 
12743ae02089SMasatake YAMATO 	parentName = vStringNew ();
12753ae02089SMasatake YAMATO 	tempName = vStringNew ();
12763ae02089SMasatake YAMATO 	fullMethodName = vStringNew ();
12773ae02089SMasatake YAMATO 	prevIdent = vStringNew ();
127880eb4460SMasatake YAMATO 	signature = vStringNewInit ("(");
12793ae02089SMasatake YAMATO 
12803ae02089SMasatake YAMATO 	/* (Re-)initialize state variables, this might be a second file */
12813ae02089SMasatake YAMATO 	comeAfter = NULL;
12823ae02089SMasatake YAMATO 	fallback = NULL;
12833ae02089SMasatake YAMATO 	parentType = K_INTERFACE;
12843ae02089SMasatake YAMATO 	ignoreBalanced_count = 0;
12853ae02089SMasatake YAMATO 	methodKind = 0;
1286ce990805SThomas Braun 	parseStruct_gotName = false;
12873ae02089SMasatake YAMATO 	parseEnumFields_prev = NULL;
1288ce990805SThomas Braun 	parseEnum_named = false;
1289ce990805SThomas Braun 	ignorePreprocStuff_escaped = false;
12903ae02089SMasatake YAMATO 
12913ae02089SMasatake YAMATO 	st.name = vStringNew ();
12921b312fe7SMasatake YAMATO 	st.cp = readLineFromInputFile ();
12933ae02089SMasatake YAMATO 	toDoNext = &globalScope;
12943ae02089SMasatake YAMATO 	tok = lex (&st);
12953ae02089SMasatake YAMATO 	while (tok != Tok_EOF)
12963ae02089SMasatake YAMATO 	{
12973ae02089SMasatake YAMATO 		(*toDoNext) (st.name, tok);
12983ae02089SMasatake YAMATO 		tok = lex (&st);
12993ae02089SMasatake YAMATO 	}
13003ae02089SMasatake YAMATO 	vStringDelete(st.name);
13013ae02089SMasatake YAMATO 
13023ae02089SMasatake YAMATO 	vStringDelete (name);
13033ae02089SMasatake YAMATO 	vStringDelete (parentName);
13043ae02089SMasatake YAMATO 	vStringDelete (tempName);
13053ae02089SMasatake YAMATO 	vStringDelete (fullMethodName);
13063ae02089SMasatake YAMATO 	vStringDelete (prevIdent);
130780eb4460SMasatake YAMATO 	vStringDelete (signature);
130880eb4460SMasatake YAMATO 	signature = NULL;
13093ae02089SMasatake YAMATO 	parentName = NULL;
13103ae02089SMasatake YAMATO 	tempName = NULL;
13113ae02089SMasatake YAMATO 	prevIdent = NULL;
13123ae02089SMasatake YAMATO 	fullMethodName = NULL;
13139af73c5bSMasatake YAMATO 	categoryCorkIndex = CORK_NIL;
131409152b33SMasatake YAMATO 	parentCorkIndex = CORK_NIL;
13153ae02089SMasatake YAMATO }
13163ae02089SMasatake YAMATO 
objcInitialize(const langType language)13173ae02089SMasatake YAMATO static void objcInitialize (const langType language)
13183ae02089SMasatake YAMATO {
13193ae02089SMasatake YAMATO 	Lang_ObjectiveC = language;
13203ae02089SMasatake YAMATO }
13213ae02089SMasatake YAMATO 
ObjcParser(void)13223ae02089SMasatake YAMATO extern parserDefinition *ObjcParser (void)
13233ae02089SMasatake YAMATO {
13243ae02089SMasatake YAMATO 	static const char *const extensions[] = { "mm", "m", "h",
13253ae02089SMasatake YAMATO 						  NULL };
13263ae02089SMasatake YAMATO 	static const char *const aliases[] = { "objc", "objective-c",
13273ae02089SMasatake YAMATO 					       NULL };
13285a38b5ceSMasatake YAMATO 	static selectLanguage selectors[] = { selectByObjectiveCAndMatLabKeywords,
13298e1e6125SMasatake YAMATO 					      selectByObjectiveCKeywords,
13305a38b5ceSMasatake YAMATO 					      NULL };
1331b29ae60fSMasatake YAMATO 	parserDefinition *def = parserNew ("ObjectiveC");
133209ae690fSMasatake YAMATO 	def->kindTable = ObjcKinds;
13333db72c21SMasatake YAMATO 	def->kindCount = ARRAY_SIZE (ObjcKinds);
13343ae02089SMasatake YAMATO 	def->extensions = extensions;
13359af73c5bSMasatake YAMATO 	def->fieldTable = ObjcFields;
13369af73c5bSMasatake YAMATO 	def->fieldCount = ARRAY_SIZE (ObjcFields);
13373ae02089SMasatake YAMATO 	def->aliases = aliases;
13383ae02089SMasatake YAMATO 	def->parser = findObjcTags;
13393ae02089SMasatake YAMATO 	def->initialize = objcInitialize;
13405a38b5ceSMasatake YAMATO 	def->selectLanguage = selectors;
1341c379c5d2SMasatake YAMATO 	def->keywordTable = objcKeywordTable;
13423db72c21SMasatake YAMATO 	def->keywordCount = ARRAY_SIZE (objcKeywordTable);
13436b1a862eSMasatake YAMATO 	def->useCork = CORK_QUEUE;
13443ae02089SMasatake YAMATO 	return def;
13453ae02089SMasatake YAMATO }
1346