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
16 #include "cxx_debug.h"
18 #include "cxx_scope.h"
19 #include "cxx_parser_internal.h"
21 #include "cxx_subparser.h"
35 static kindDefinition QtMocKinds
[] = {
36 { true, 's', "slot", "slots" },
37 { true, 'S', "signal", "signals" },
38 { true, 'p', "property", "properties" },
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
;
71 enum QtMocMemberMarker eMemberMarker
;
74 static langType Lang_QtMoc
;
76 static bool cxxParserSkipToClosingParenthesisOrEOF(void)
78 if(cxxTokenTypeIsOneOf(g_cxx
.pToken
,CXXTokenTypeClosingParenthesis
| CXXTokenTypeEOF
))
81 return cxxParserParseUpToOneOf(CXXTokenTypeClosingParenthesis
| CXXTokenTypeEOF
,
85 static void qtMocMakeTagForProperty (CXXToken
* pToken
, const char *pszType
)
90 vStringValue(pToken
->pszWord
),
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
;
108 static bool qtMocParseProperty(void)
114 if(!cxxParserParseNextToken())
116 CXX_DEBUG_LEAVE_TEXT("EOF in cxxParserParseNextToken");
119 if (!cxxTokenTypeIs(g_cxx
.pToken
, CXXTokenTypeOpeningParenthesis
))
121 CXX_DEBUG_LEAVE_TEXT("Found no Opening Parenthesis after Q_PROPERTY");
125 if (!cxxParserParseNextToken())
127 CXX_DEBUG_LEAVE_TEXT("EOF in cxxParserParseNextToken");
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 ();
141 pszPropType
= vStringStrdup (g_cxx
.pToken
->pszWord
);
142 if(!cxxParserParseNextToken())
144 CXX_DEBUG_LEAVE_TEXT("EOF in cxxParserParseNextToken");
149 if (!cxxTokenTypeIs(g_cxx
.pToken
, CXXTokenTypeIdentifier
))
151 CXX_DEBUG_LEAVE_TEXT("Found no identifier after Q_PROPERTY(%s", pszPropType
);
152 cxxParserSkipToClosingParenthesisOrEOF ();
157 qtMocMakeTagForProperty (g_cxx
.pToken
, pszPropType
);
160 cxxParserSkipToClosingParenthesisOrEOF ();
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)
182 if ((pQtMoc
->eMemberMarker
!= QtMocMemberMarkerNone
) &&
183 entry
->kindIndex
== CXXTagKindPROTOTYPE
)
185 tagEntryInfo parasiteTag
= *entry
;
186 parasiteTag
.langType
= getInputLanguage ();
187 parasiteTag
.kindIndex
= (pQtMoc
->eMemberMarker
== QtMocMemberMarkerSlot
)
191 parasiteTag
.extensionFields
.scopeLangType
= entry
->langType
;
192 makeTagEntry (¶siteTag
);
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
,
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
);
230 static bool unknownIdentifierInClassNotify (struct sCxxSubparser
*pSubparser
,
233 struct sQtMocSubparser
*pQtMoc
= (struct sQtMocSubparser
*)pSubparser
;
235 if (pQtMoc
->iDepthOfQtClass
== 0)
238 keywordId keyword
= lookupKeyword (vStringValue (pToken
->pszWord
), Lang_QtMoc
);
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
;
250 CXX_DEBUG_PRINT("Found \"slots\" QtMoc Keyword");
251 pToken
->eType
= CXXTokenTypeKeyword
;
252 g_cxx
.pToken
->eKeyword
= CXXKeywordPUBLIC
; /* ??? */
253 cxxParserParseAccessSpecifier();
254 pQtMoc
->eMemberMarker
= QtMocMemberMarkerSlot
;
256 case KEYWORD_PROPERTY
:
257 CXX_DEBUG_PRINT("Found \"Q_PROPERTY\" QtMoc Keyword");
258 qtMocParseProperty ();
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
;
280 static void foundExtraIdentifierAsAccessSpecifier(struct sCxxSubparser
*pSubparser
,
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
)
303 extern parserDefinition
* QtMocParser (void)
305 parserDefinition
* const def
= parserNew("QtMoc");
307 static struct sQtMocSubparser qtMocSubparser
= {
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
;