Doxygen
Loading...
Searching...
No Matches
declinfo.l
Go to the documentation of this file.
1/******************************************************************************
2 *
3 * Copyright (C) 1997-2015 by Dimitri van Heesch.
4 *
5 * Permission to use, copy, modify, and distribute this software and its
6 * documentation under the terms of the GNU General Public License is hereby
7 * granted. No representations are made about the suitability of this software
8 * for any purpose. It is provided "as is" without express or implied warranty.
9 * See the GNU General Public License for more details.
10 *
11 * Documents produced by Doxygen are derivative works derived from the
12 * input used in their production; they are not affected by this license.
13 *
14 */
15%option never-interactive
16%option prefix="declinfoYY"
17%option nounput
18%option noyywrap
19%option reentrant
20%option extra-type="struct declinfoYY_state *"
21%top{
22#include <stdint.h>
23// forward declare yyscan_t to improve type safety
24#define YY_TYPEDEF_YY_SCANNER_T
25struct yyguts_t;
26typedef yyguts_t *yyscan_t;
yyguts_t * yyscan_t
Definition code.l:24
27}
28
29%{
30
31// own header
32#include "declinfo.h"
33
34// other includes
35#include "debug.h"
36#include "message.h"
37#include "types.h"
38#include "util.h"
39
40#define YY_NO_INPUT 1
41#define YY_NO_UNISTD_H 1
42#define YY_NEVER_INTERACTIVE 1
43
44/* -----------------------------------------------------------------
45 *
46 * statics
47 */
68
69[[maybe_unused]] static const char *stateToString(int state);
70
71static void addType(yyscan_t yyscanner);
72static void addTypeName(yyscan_t yyscanner);
73static int yyread(char *buf,int max_size, yyscan_t yyscanner);
74
75/* -----------------------------------------------------------------
76 */
77#undef YY_INPUT
78#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size,yyscanner);
79
80// otherwise the filename would be the name of the converted file (*.cpp instead of *.l)
81static inline const char *getLexerFILE() {return __FILE__;}
82#define LEX_NO_INPUT_FILENAME
83#include "doxygen_lex.h"
A String class for use with Doxygen wrapping std::string and adding some additional functionality off...
Definition dstring.h:84
static int yyread(char *buf, int max_size, yyscan_t yyscanner)
Definition declinfo.l:312
static void addTypeName(yyscan_t yyscanner)
Definition declinfo.l:297
static const char * stateToString(int state)
static const char * getLexerFILE()
Definition declinfo.l:81
static void addType(yyscan_t yyscanner)
Definition declinfo.l:281
DString className
Definition declinfo.l:53
const char * inputString
Definition declinfo.l:50
DString funcTempList
Definition declinfo.l:55
bool funcTempListFound
Definition declinfo.l:62
DString classTempList
Definition declinfo.l:54
bool classTempListFound
Definition declinfo.l:61
DString exceptionString
Definition declinfo.l:63
DString scope
Definition declinfo.l:52
This file contains a number of basic enums and types.
A bunch of utility functions.
84%}
85
86B [ \t]
87Bopt {B}*
88ID ([$a-z_A-Z\x80-\xFF][$a-z_A-Z0-9\x80-\xFF]*)|(@[0-9]+)
89
90%x Start
91%x Template
92%x ReadArgs
93%x Operator
94%x DeclType
95%x ReadExceptions
96
97%%
98
99<Start>"operator"/({B}*"["{B}*"]")* { // operator rule must be before {ID} rule
100 yyextra->name += yytext;
101 BEGIN(Operator);
102 }
103<Start>{ID}({B}*"*")?{B}*"("{B}*"^"{B}*")"{B}*"(" { // Objective-C 2.0 block return type
104 if (!yyextra->insideObjC)
105 {
106 REJECT;
107 }
108 else
109 {
110 addType(yyscanner);
111 yyextra->type += yytext;
112 }
113 }
114<Start>{ID}{B}*"("{B}*{ID}{B}*")" { // Objective-C class categories
115 if (!yyextra->insideObjC)
116 {
117 REJECT;
118 }
119 else
120 {
121 yyextra->name += yytext;
122 }
123 }
124<Start>([~!]{B}*)?{ID}{B}*"["{B}*"]" { // PHP
125 if (!yyextra->insidePHP)
126 {
127 REJECT;
128 }
129 addTypeName(yyscanner);
130 yyextra->name += removeRedundantWhiteSpace(yytext);
131 }
DString removeRedundantWhiteSpace(const DString &s)
Definition util.cpp:427
132<Start>"anonymous_namespace{"[^}]+"}" { // anonymous namespace
133 if (!yyextra->scope.empty())
134 {
135 yyextra->scope+=DString("::")+yytext;
136 }
137 else
138 {
139 yyextra->scope = yytext;
140 }
141 }
142<Start>([~!]{B}*)?{ID}/({B}*"["{B}*"]")* { // the []'s are for Java,
143 // the / was add to deal with multi-
144 // dimensional C++ arrays like A[][15]
145 // the leading ~ is for a destructor
146 // the leading ! is for a C++/CLI finalizer (see bug 456475 and 635198)
147 addTypeName(yyscanner);
148 yyextra->name += removeRedundantWhiteSpace(yytext);
149 }
150<Start>{B}*"::"{B}* { // found a yyextra->scope specifier
151 if (!yyextra->scope.empty() && !yyextra->scope.endsWith("::"))
152 {
153 if (!yyextra->name.empty()) yyextra->scope+="::"+yyextra->name; // add yyextra->name to yyextra->scope
154 }
155 else
156 {
157 yyextra->scope = yyextra->name; // yyextra->scope becomes yyextra->name
158 }
159 yyextra->name.clear();
160 }
161<Start>{B}*":" { // Objective-C argument separator
162 yyextra->name+=yytext;
163 }
164<Start>[*&]+ {
165 addType(yyscanner);
166 yyextra->type+=yytext;
167 }
168<Start>{B}+ {
169 addType(yyscanner);
170 }
171<Start>{B}*"("({ID}"::")*{B}*[&*]({B}*("const"|"volatile"){B}+)? {
172 if (yyextra->insidePHP) REJECT;
173 if (yyextra->insidePython) REJECT;
174 addType(yyscanner);
175 DString text(yytext);
176 yyextra->type+=text.stripWhiteSpace();
177 }
178<Start>{B}*")" {
179 yyextra->type+=")";
180 }
181<Start>{B}*"const"/{B}+ |
182<Start>{B}*"consteval"/{B}+ |
183<Start>{B}*"constinit"/{B}+ |
184<Start>{B}*"constexpr"/{B}+ {
185 if (!yyextra->type.empty()) yyextra->type+=" ";
186 yyextra->type+=yytext;
187 }
188<Start>{B}*"decltype"/{B}*"(" {
189 yyextra->roundCount=0;
190 if (!yyextra->type.empty()) yyextra->type+=" ";
191 yyextra->type+="decltype";
192 BEGIN(DeclType);
193 }
194<DeclType>{B}*"(" {
195 ++yyextra->roundCount;
196 yyextra->type+="(";
197 }
198<DeclType>{B}*")" {
199 yyextra->type+=")";
200 if (--yyextra->roundCount == 0) {
201 BEGIN(Start);
202 }
203 }
204<DeclType>. {
205 yyextra->type+=yytext;
206 }
207<Start>{B}*"(" { // TODO: function pointers
208 yyextra->args+="(";
209 BEGIN(ReadArgs);
210 }
211<Start>{B}*"[" {
212 yyextra->args+="[";
213 BEGIN(ReadArgs);
214 }
215<Start>{B}*"<" {
216 yyextra->name+="<";
217 yyextra->sharpCount=0;
218 yyextra->roundCount=0;
219 BEGIN(Template);
220 }
221<Template>"<<" { yyextra->name+="<<"; }
222<Template>">>" { yyextra->name+=">>"; }
223<Template>"(" { yyextra->name+="(";
224 yyextra->roundCount++;
225 }
226<Template>")" { yyextra->name+=")";
227 if (yyextra->roundCount>0)
228 {
229 yyextra->roundCount--;
230 }
231 }
232<Template>"<" {
233 yyextra->name+="<";
234 if (yyextra->roundCount==0)
235 {
236 yyextra->sharpCount++;
237 }
238 }
239<Template>">" {
240 yyextra->name+=">";
241 if (yyextra->roundCount==0)
242 {
243 if (yyextra->sharpCount)
244 --yyextra->sharpCount;
245 else
246 {
247 BEGIN(Start);
248 }
249 }
250 }
251<Template>. {
252 yyextra->name+=*yytext;
253 }
254<Operator>{B}*"("{B}*")"{B}*"<>"{Bopt}/"(" {
255 yyextra->name+="() <>";
256 BEGIN(ReadArgs);
257 }
258<Operator>{B}*"("{B}*")"{Bopt}/"(" {
259 yyextra->name+="()";
260 BEGIN(ReadArgs);
261 }
262<Operator>[^(]*{B}*("<>"{B}*)?/"(" {
263 yyextra->name+=yytext;
264 BEGIN(ReadArgs);
265 }
266<ReadArgs>"throw"{B}*"(" {
267 yyextra->exceptionString="throw(";
268 BEGIN(ReadExceptions);
269 }
270<ReadArgs>. {
271 yyextra->args+=*yytext;
272 }
273<ReadExceptions>. {
274 yyextra->exceptionString+=*yytext;
275 }
276<*>.
277<*>\n
278
279%%
280
281static void addType(yyscan_t yyscanner)
282{
283 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
284 //printf("addType() yyextra->type='%s' yyextra->scope='%s' yyextra->name='%s'\n",
285 // qPrint(yyextra->type),qPrint(yyextra->scope),qPrint(yyextra->name));
286 if (yyextra->name.empty() && yyextra->scope.empty())
287 {
288 return;
289 }
290 if (!yyextra->type.empty()) yyextra->type+=" ";
291 if (!yyextra->scope.empty()) yyextra->type+=yyextra->scope+"::";
292 yyextra->type+=yyextra->name;
293 yyextra->scope.clear();
294 yyextra->name.clear();
295}
296
297static void addTypeName(yyscan_t yyscanner)
298{
299 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
300 //printf("addTypeName() yyextra->type='%s' yyextra->scope='%s' yyextra->name='%s'\n",
301 // qPrint(yyextra->type),qPrint(yyextra->scope),qPrint(yyextra->name));
302 if (yyextra->name.empty() ||
303 yyextra->name.at(yyextra->name.length()-1)==':') // end of Objective-C keyword => append to yyextra->name not yyextra->type
304 {
305 return;
306 }
307 if (!yyextra->type.empty()) yyextra->type+=' ';
308 yyextra->type+=yyextra->name;
309 yyextra->name.clear();
310}
311
312static int yyread(char *buf,int max_size, yyscan_t yyscanner)
313{
314 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
315 int c=0;
316 while( c < max_size && yyextra->inputString[yyextra->inputPosition] )
317 {
318 *buf = yyextra->inputString[yyextra->inputPosition++] ;
319 c++; buf++;
320 }
321 return c;
322}
323
324/*@ public interface------------------------------------------------------------
325 */
328
329void parseFuncDecl(const DString &decl,const SrcLangExt lang,DString &cl,DString &t,
330 DString &n,DString &a,DString &ftl,DString &exc)
331{
332 if (decl.empty())
333 {
334 return;
335 }
336 declinfoYYlex_init_extra(&g_declinfo_extra, &g_yyscanner);
337 struct yyguts_t *yyg = (struct yyguts_t*)g_yyscanner;
338
339#ifdef FLEX_DEBUG
340 declinfoYYset_debug(Debug::isFlagSet(Debug::Lex_declinfo)?1:0,g_yyscanner);
341#endif
342
343 DebugLex debugLex(Debug::Lex_declinfo,__FILE__, NULL);
344 yyextra->inputString = decl.data();
345 //printf("Input='%s'\n",yyextra->inputString);
346 yyextra->inputPosition = 0;
347 yyextra->classTempListFound = false;
348 yyextra->funcTempListFound = false;
349 yyextra->insideObjC = lang==SrcLangExt::ObjC;
350 yyextra->insidePHP = lang==SrcLangExt::PHP;
351 yyextra->insidePython = lang==SrcLangExt::Python;
352 yyextra->scope.clear();
353 yyextra->className.clear();
354 yyextra->classTempList.clear();
355 yyextra->funcTempList.clear();
356 yyextra->name.clear();
357 yyextra->type.clear();
358 yyextra->args.clear();
359 yyextra->exceptionString.clear();
360 // first we try to find the yyextra->type, yyextra->scope, yyextra->name and arguments
361 declinfoYYrestart( yyin, g_yyscanner );
362 BEGIN( Start );
363 declinfoYYlex(g_yyscanner);
364
365 //printf("yyextra->type='%s' class='%s' yyextra->name='%s' yyextra->args='%s'\n",
366 // qPrint(yyextra->type),qPrint(yyextra->scope),qPrint(yyextra->name),qPrint(yyextra->args));
367
368 if (size_t nb = yyextra->name.rfind('[') ; nb!=DString::npos && yyextra->args.empty()) // correct for [] in yyextra->name ambiguity (due to Java return yyextra->type allowing [])
369 {
370 yyextra->args.prepend(yyextra->name.mid(nb));
371 yyextra->name=yyextra->name.left(nb);
372 }
373
374 cl=yyextra->scope;
375 n=removeRedundantWhiteSpace(yyextra->name);
376 size_t il=n.find('<'), ir=n.rfind('>');
377 if (il!=DString::npos && ir!=DString::npos && n.at(il+1)!='=')
378 // prevent <=>
379 // TODO: handle cases like where n="operator<< <T>"
380 {
382 n=n.left(il);
383 }
384
385 //ctl=yyextra->classTempList.copy();
386 //ftl=yyextra->funcTempList.copy();
387 t=removeRedundantWhiteSpace(yyextra->type);
388 a=removeRedundantWhiteSpace(yyextra->args);
389 exc=removeRedundantWhiteSpace(yyextra->exceptionString);
390
391 size_t len = t.length();
392 if (!t.empty() && t.at(len-1)==')') // for function pointers
393 {
394 // check if `)` is from decltype(`
395 size_t pos = t.find("decltype(");
396 if (pos != DString::npos)
397 {
398 size_t cnt = 1;
399 for (size_t i = pos + 9; i < len; i++)
400 {
401 if (t.at(i) == '(') cnt++;
402 else if (t.at(i) == ')')
403 {
404 cnt--;
405 if (cnt == 0)
406 {
407 if (i != len-1)
408 {
409 a.prepend(")");
410 t=t.left(len-1);
411 }
412 }
413 }
414 }
415 }
416 else
417 {
418 a.prepend(")");
419 t=t.left(len-1);
420 }
421 }
422 //printf("yyextra->type='%s' class='%s' yyextra->name='%s' yyextra->args='%s'\n",
423 // qPrint(t),qPrint(cl),qPrint(n),qPrint(a));
424
425 declinfoYYlex_destroy(g_yyscanner);
426 return;
427}
428
429#if 0
430void dumpDecl(const char *s)
431{
432 DString yyextra->className;
433 DString classTNames;
434 DString yyextra->type;
435 DString yyextra->name;
436 DString yyextra->args;
437 DString funcTNames;
438 msg("-----------------------------------------\n");
439 parseFuncDecl(s,yyextra->className,classTNames,yyextra->type,yyextra->name,yyextra->args,funcTNames);
440 msg("yyextra->type='{}' class='{}' classTempl='{}' yyextra->name='{}' "
441 "funcTemplateNames='{}' yyextra->args='{}'\n",
442 yyextra->type,yyextra->className,classTNames,
443 yyextra->name,funcTNames,yyextra->args
444 );
445}
446
447// some test code
448int main()
449{
450 dumpDecl("A < T > :: Value * A < T > :: getValue < S > ( const A < T > & a )");
451 dumpDecl("const A<T>::Value* A<T>::getValue<S>(const A<T>&a)");
452 dumpDecl("func()");
453 dumpDecl("friend void bla<>()");
454 dumpDecl("yyextra->name< T > :: operator () (int bla)");
455 dumpDecl("yyextra->name< T > :: operator << (int bla)");
456 dumpDecl("yyextra->name< T > :: operator << <> (int bla)");
457 dumpDecl("yyextra->className::func()");
458 dumpDecl("void ( * yyextra->Name < T > :: bla ) ( int, char * )");
459}
460#endif
461
462#include "declinfo.l.h"
size_t rfind(char c, size_t pos=npos) const
Definition dstring.h:244
DString mid(size_t index, size_t len=npos) const
Definition dstring.h:318
bool empty() const
Returns true iff the string is empty (std::string compatible alias for isEmpty()).
Definition dstring.h:148
static constexpr size_t npos
value used to indicate 'not found' or 'to the end of the string', matching std::string::npos
Definition dstring.h:178
char & at(size_t i)
Returns a reference to the character at index i.
Definition dstring.h:686
DString & prepend(const char *s)
Definition dstring.h:515
size_t find(char c, size_t pos=0) const
Definition dstring.h:239
DString left(size_t len) const
Definition dstring.h:306
const char * data() const
Returns a pointer to the contents of the string in the form of a 0-terminated C string.
Definition dstring.h:157
size_t length() const
Returns the length of the string, not counting the 0-terminator.
Definition dstring.h:151
@ Lex_declinfo
Definition debug.h:59
static bool isFlagSet(const DebugMask mask)
Definition debug.cpp:132
void parseFuncDecl(const DString &decl, const SrcLangExt lang, DString &clName, DString &type, DString &name, DString &args, DString &funcTempList, DString &exceptions)
Definition declinfo.l:329
static yyscan_t g_yyscanner
Definition declinfo.l:326
static struct declinfoYY_state g_declinfo_extra
Definition declinfo.l:327
int main(int argc, char **argv)
Definition main.cpp:28
#define msg(fmt,...)
Definition message.h:94
SrcLangExt
Definition types.h:207