Update all parsers and related files to ctags p6.1.20240421.0
[geany-mirror.git] / ctags / parsers / cxx / cxx_qtmoc.c
blob02f512a2c88a089242ff1de40d19a663fe539d2b
1 /*
2 * Copyright (c) 2017, Red Hat, Inc.
3 * Copyright (c) 2017, Masatake YAMATO
5 * This source code is released for free distribution under the terms of the
6 * GNU General Public License version 2 or (at your option) any later version.
8 * This module contains functions for handling Qt Moc tokens
9 */
11 #include "general.h"
13 #include "types.h"
15 #include "debug.h"
16 #include "cxx_debug.h"
18 #include "cxx_scope.h"
19 #include "cxx_parser_internal.h"
21 #include "cxx_subparser.h"
23 #include "keyword.h"
24 #include "read.h"
26 #include <string.h>
29 typedef enum {
30 K_SLOT,
31 K_SIGNAL,
32 K_PROPERTY,
33 } qtMocKind;
35 static kindDefinition QtMocKinds [] = {
36 { true, 's', "slot", "slots" },
37 { true, 'S', "signal", "signals" },
38 { true, 'p', "property", "properties" },
41 enum {
42 KEYWORD_QOBJECT,
43 KEYWORD_SIGNALS,
44 KEYWORD_SLOTS,
45 KEYWORD_PROPERTY,
48 typedef int keywordId; /* to allow KEYWORD_NONE */
50 static const keywordTable QtMocKeywordTable[] = {
51 /* keyword keyword ID */
52 { "Q_OBJECT", KEYWORD_QOBJECT },
53 { "Q_SIGNALS", KEYWORD_SIGNALS },
54 { "signals", KEYWORD_SIGNALS },
55 { "Q_SLOTS", KEYWORD_SLOTS },
56 { "slots", KEYWORD_SLOTS },
57 { "Q_PROPERTY", KEYWORD_PROPERTY },
60 enum QtMocMemberMarker
62 QtMocMemberMarkerNone = 0,
63 QtMocMemberMarkerSlot,
64 QtMocMemberMarkerSignal,
67 struct sQtMocSubparser {
68 struct sCxxSubparser cxx;
69 int iBlockDepth;
70 int iDepthOfQtClass;
71 enum QtMocMemberMarker eMemberMarker;
74 static langType Lang_QtMoc;
76 static bool cxxParserSkipToClosingParenthesisOrEOF(void)
78 if(cxxTokenTypeIsOneOf(g_cxx.pToken,CXXTokenTypeClosingParenthesis | CXXTokenTypeEOF))
79 return true;
81 return cxxParserParseUpToOneOf(CXXTokenTypeClosingParenthesis | CXXTokenTypeEOF,
82 false);
85 static void qtMocMakeTagForProperty (CXXToken * pToken, const char *pszType)
87 tagEntryInfo tag;
89 initTagEntry(&tag,
90 vStringValue(pToken->pszWord),
91 K_PROPERTY);
92 updateTagLine (&tag, pToken->iLineNumber, pToken->oFilePosition);
93 tag.isFileScope = false;
95 if(!cxxScopeIsGlobal())
97 tag.extensionFields.scopeLangType = getNamedLanguage ("C++", 0); /* ??? */
98 tag.extensionFields.scopeKindIndex = cxxScopeGetKind();
99 tag.extensionFields.scopeName = cxxScopeGetFullName();
102 tag.extensionFields.typeRef[0] = "typename";
103 tag.extensionFields.typeRef[1] = pszType;
105 makeTagEntry(&tag);
108 static bool qtMocParseProperty(void)
110 char *pszPropType;
112 CXX_DEBUG_ENTER();
114 if(!cxxParserParseNextToken())
116 CXX_DEBUG_LEAVE_TEXT("EOF in cxxParserParseNextToken");
117 return false;
119 if (!cxxTokenTypeIs(g_cxx.pToken, CXXTokenTypeOpeningParenthesis))
121 CXX_DEBUG_LEAVE_TEXT("Found no Opening Parenthesis after Q_PROPERTY");
122 return false;
125 if (!cxxParserParseNextToken())
127 CXX_DEBUG_LEAVE_TEXT("EOF in cxxParserParseNextToken");
128 return false;
130 if (!(cxxTokenTypeIs(g_cxx.pToken, CXXTokenTypeIdentifier)
131 || (cxxTokenTypeIs(g_cxx.pToken, CXXTokenTypeKeyword)
132 && cxxKeywordMayBePartOfTypeName (g_cxx.pToken->eKeyword))))
135 CXX_DEBUG_LEAVE_TEXT("Found no identifier after Q_PROPERTY(");
137 cxxParserSkipToClosingParenthesisOrEOF ();
138 return false;
141 pszPropType = vStringStrdup (g_cxx.pToken->pszWord);
142 if(!cxxParserParseNextToken())
144 CXX_DEBUG_LEAVE_TEXT("EOF in cxxParserParseNextToken");
145 eFree (pszPropType);
146 return false;
149 if (!cxxTokenTypeIs(g_cxx.pToken, CXXTokenTypeIdentifier))
151 CXX_DEBUG_LEAVE_TEXT("Found no identifier after Q_PROPERTY(%s", pszPropType);
152 cxxParserSkipToClosingParenthesisOrEOF ();
153 eFree (pszPropType);
154 return false;
157 qtMocMakeTagForProperty (g_cxx.pToken, pszPropType);
159 eFree (pszPropType);
160 cxxParserSkipToClosingParenthesisOrEOF ();
162 CXX_DEBUG_LEAVE();
163 return true;
166 static void inputStart(subparser *s)
168 struct sQtMocSubparser *pQtMoc = (struct sQtMocSubparser*)s;
170 pQtMoc->iBlockDepth = 0;
171 pQtMoc->iDepthOfQtClass = 0;
172 pQtMoc->eMemberMarker = QtMocMemberMarkerNone;
175 static void makeTagEntryNotify (subparser *s, const tagEntryInfo *entry, int corkIndex)
177 struct sQtMocSubparser *pQtMoc = (struct sQtMocSubparser*)s;
179 if (pQtMoc->iDepthOfQtClass == 0)
180 return;
182 if ((pQtMoc->eMemberMarker != QtMocMemberMarkerNone) &&
183 entry->kindIndex == CXXTagKindPROTOTYPE)
185 tagEntryInfo parasiteTag = *entry;
186 parasiteTag.langType = getInputLanguage ();
187 parasiteTag.kindIndex = (pQtMoc->eMemberMarker == QtMocMemberMarkerSlot)
188 ? K_SLOT
189 : K_SIGNAL;
191 parasiteTag.extensionFields.scopeLangType = entry->langType;
192 makeTagEntry (&parasiteTag);
196 static void enterBlockNotify (struct sCxxSubparser *pSubparser)
198 struct sQtMocSubparser *pQtMoc = (struct sQtMocSubparser *)pSubparser;
200 pQtMoc->iBlockDepth++;
203 static void leaveBlockNotify (struct sCxxSubparser *pSubparser)
205 struct sQtMocSubparser *pQtMoc = (struct sQtMocSubparser *)pSubparser;
207 if (pQtMoc->iDepthOfQtClass == pQtMoc->iBlockDepth)
208 pQtMoc->iDepthOfQtClass = 0;
210 pQtMoc->iBlockDepth--;
213 static bool newIdentifierAsHeadOfMemberNotify (struct sCxxSubparser *pSubparser,
214 CXXToken *pToken)
216 struct sQtMocSubparser *pQtMoc = (struct sQtMocSubparser *)pSubparser;
217 keywordId keyword = lookupKeyword (vStringValue (pToken->pszWord), Lang_QtMoc);
219 if (keyword == KEYWORD_QOBJECT)
221 if (pQtMoc->iDepthOfQtClass == 0)
222 pQtMoc->iDepthOfQtClass = pQtMoc->iBlockDepth;
223 CXX_DEBUG_PRINT("Found \"Q_OBJECT\" Qt Object Marker in depth: %d",
224 pQtMoc->iDepthOfQtClass);
225 return true;
227 return false;
230 static bool unknownIdentifierInClassNotify (struct sCxxSubparser *pSubparser,
231 CXXToken *pToken)
233 struct sQtMocSubparser *pQtMoc = (struct sQtMocSubparser *)pSubparser;
235 if (pQtMoc->iDepthOfQtClass == 0)
236 return false;
238 keywordId keyword = lookupKeyword (vStringValue (pToken->pszWord), Lang_QtMoc);
240 switch (keyword)
242 case KEYWORD_SIGNALS:
243 CXX_DEBUG_PRINT("Found \"signals\" QtMoc Keyword");
244 pToken->eType = CXXTokenTypeKeyword;
245 pToken->eKeyword = CXXKeywordPUBLIC;
246 cxxParserParseAccessSpecifier();
247 pQtMoc->eMemberMarker = QtMocMemberMarkerSignal;
248 return true;
249 case KEYWORD_SLOTS:
250 CXX_DEBUG_PRINT("Found \"slots\" QtMoc Keyword");
251 pToken->eType = CXXTokenTypeKeyword;
252 g_cxx.pToken->eKeyword = CXXKeywordPUBLIC; /* ??? */
253 cxxParserParseAccessSpecifier();
254 pQtMoc->eMemberMarker = QtMocMemberMarkerSlot;
255 return true;
256 case KEYWORD_PROPERTY:
257 CXX_DEBUG_PRINT("Found \"Q_PROPERTY\" QtMoc Keyword");
258 qtMocParseProperty ();
259 return true;
260 default:
261 break;
264 return false;
267 static bool parseAccessSpecifierNotify(struct sCxxSubparser *pSubparser)
269 struct sQtMocSubparser *pQtMoc = (struct sQtMocSubparser *)pSubparser;
271 if (pQtMoc->iBlockDepth > 0)
273 CXX_DEBUG_PRINT("Reset QtMoc member marker state");
274 pQtMoc->eMemberMarker = QtMocMemberMarkerNone;
275 return true;
277 return false;
280 static void foundExtraIdentifierAsAccessSpecifier(struct sCxxSubparser *pSubparser,
281 CXXToken *pToken)
283 struct sQtMocSubparser *pQtMoc = (struct sQtMocSubparser *)pSubparser;
284 keywordId keyword = lookupKeyword (vStringValue (pToken->pszWord), Lang_QtMoc);
286 if (keyword == KEYWORD_SLOTS)
288 CXX_DEBUG_PRINT("Found \"slots\" QtMoc Keyword");
289 pQtMoc->eMemberMarker = QtMocMemberMarkerSlot;
293 static void findQtMocTags(void)
295 scheduleRunningBaseparser (0);
298 static void initialize (langType lang)
300 Lang_QtMoc = lang;
303 extern parserDefinition* QtMocParser (void)
305 parserDefinition* const def = parserNew("QtMoc");
307 static struct sQtMocSubparser qtMocSubparser = {
308 .cxx = {
309 .subparser = {
310 .direction = SUBPARSER_BI_DIRECTION,
311 .inputStart = inputStart,
312 .makeTagEntryNotify = makeTagEntryNotify,
314 .enterBlockNotify = enterBlockNotify,
315 .leaveBlockNotify = leaveBlockNotify,
316 .newIdentifierAsHeadOfMemberNotify = newIdentifierAsHeadOfMemberNotify,
317 .unknownIdentifierInClassNotify = unknownIdentifierInClassNotify,
318 .parseAccessSpecifierNotify = parseAccessSpecifierNotify,
319 .foundExtraIdentifierAsAccessSpecifier = foundExtraIdentifierAsAccessSpecifier,
321 /* The rest fields are initialized in inputStart(). */
323 static parserDependency dependencies [] = {
324 [0] = { DEPTYPE_SUBPARSER, "C++", &qtMocSubparser },
327 def->dependencies = dependencies;
328 def->dependencyCount = ARRAY_SIZE (dependencies);
330 def->kindTable = QtMocKinds;
331 def->kindCount = ARRAY_SIZE(QtMocKinds);
333 def->keywordTable = QtMocKeywordTable;
334 def->keywordCount = ARRAY_SIZE (QtMocKeywordTable);
336 def->parser = findQtMocTags;
337 def->initialize = initialize;
338 def->useCork = CORK_QUEUE;
340 return def;