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