Doxygen
declinfo.l
浏览该文件的文档.
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  */
17 %option never-interactive
18 %option prefix="declinfoYY"
19 %option nounput
20 %option noyywrap
21 %option reentrant
22 %option extra-type="struct declinfoYY_state *"
23 %top{
24 #include <stdint.h>
25 // forward declare yyscan_t to improve type safety
26 #define YY_TYPEDEF_YY_SCANNER_T
27 struct yyguts_t;
28 typedef yyguts_t *yyscan_t;
29 }
30 
31 %{
32 
33 /*
34  * includes
35  */
36 #include <stdio.h>
37 //#include <iostream.h>
38 #include <assert.h>
39 #include <ctype.h>
40 
41 #include "declinfo.h"
42 #include "util.h"
43 #include "message.h"
44 #include "types.h"
45 
46 #define YY_NO_INPUT 1
47 #define YY_NO_UNISTD_H 1
48 #define YY_NEVER_INTERACTIVE 1
49 
50 #define USE_STATE2STRING 0
51 
52 /* -----------------------------------------------------------------
53  *
54  * statics
55  */
56 struct declinfoYY_state
57 {
58  const char *inputString;
59  int inputPosition;
60  QCString scope;
61  QCString className;
62  QCString classTempList;
63  QCString funcTempList;
64  QCString type;
65  QCString name;
66  QCString args;
67  int sharpCount;
68  int roundCount;
69  bool classTempListFound;
70  bool funcTempListFound;
71  QCString exceptionString;
72  bool insideObjC;
73  bool insidePHP;
74 };
75 
76 #if USE_STATE2STRING
77 static const char *stateToString(int state);
78 #endif
79 
80 static void addType(yyscan_t yyscanner);
81 static void addTypeName(yyscan_t yyscanner);
82 static yy_size_t yyread(char *buf,yy_size_t max_size, yyscan_t yyscanner);
83 
84 /* -----------------------------------------------------------------
85  */
86 #undef YY_INPUT
87 #define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size,yyscanner);
88 %}
89 
90 B [ \t]
91 Bopt {B}*
92 ID ([$a-z_A-Z\x80-\xFF][$a-z_A-Z0-9\x80-\xFF]*)|(@[0-9]+)
93 
94 %x Start
95 %x Template
96 %x ReadArgs
97 %x Operator
98 %x DeclType
99 %x ReadExceptions
100 
101 %%
102 
103 <Start>"operator"/({B}*"["{B}*"]")* { // operator rule must be before {ID} rule
104  yyextra->name += yytext;
105  BEGIN(Operator);
106  }
107 <Start>{ID}{B}*"("{B}*{ID}{B}*")" { // Objective-C class categories
108  if (!yyextra->insideObjC)
109  {
110  REJECT;
111  }
112  else
113  {
114  yyextra->name += yytext;
115  }
116  }
117 <Start>([~!]{B}*)?{ID}{B}*"["{B}*"]" { // PHP
118  if (!yyextra->insidePHP)
119  {
120  REJECT;
121  }
122  addTypeName(yyscanner);
123  yyextra->name += removeRedundantWhiteSpace(QCString(yytext));
124  }
125 <Start>([~!]{B}*)?{ID}/({B}*"["{B}*"]")* { // the []'s are for Java,
126  // the / was add to deal with multi-
127  // dimensional C++ arrays like A[][15]
128  // the leading ~ is for a destructor
129  // the leading ! is for a C++/CLI finalizer (see bug 456475 and 635198)
130  addTypeName(yyscanner);
131  yyextra->name += removeRedundantWhiteSpace(QCString(yytext));
132  }
133 <Start>{B}*"::"{B}* { // found a yyextra->scope specifier
134  if (!yyextra->scope.isEmpty())
135  {
136  yyextra->scope+="::"+yyextra->name; // add yyextra->name to yyextra->scope
137  }
138  else
139  {
140  yyextra->scope = yyextra->name; // yyextra->scope becomes yyextra->name
141  }
142  yyextra->name.resize(0);
143  }
144 <Start>{B}*":" { // Objective-C argument separator
145  yyextra->name+=yytext;
146  }
147 <Start>[*&]+ {
148  addType(yyscanner);
149  yyextra->type+=yytext;
150  }
151 <Start>{B}+ {
152  addType(yyscanner);
153  }
154 <Start>{B}*"("({ID}"::")*{B}*[&*]({B}*("const"|"volatile"){B}+)? {
155  if (yyextra->insidePHP) REJECT;
156  addType(yyscanner);
157  QCString text(yytext);
158  yyextra->type+=text.stripWhiteSpace();
159  }
160 <Start>{B}*")" {
161  yyextra->type+=")";
162  }
163 <Start>{B}*"decltype"/{B}*"(" {
164  yyextra->roundCount=0;
165  yyextra->type="decltype";
166  BEGIN(DeclType);
167  }
168 <DeclType>{B}*"(" {
169  ++yyextra->roundCount;
170  yyextra->type+="(";
171  }
172 <DeclType>{B}*")" {
173  yyextra->type+=")";
174  if (--yyextra->roundCount == 0) {
175  BEGIN(Start);
176  }
177  }
178 <DeclType>. {
179  yyextra->type+=yytext;
180  }
181 <Start>{B}*"(" { // TODO: function pointers
182  yyextra->args+="(";
183  BEGIN(ReadArgs);
184  }
185 <Start>{B}*"[" {
186  yyextra->args+="[";
187  BEGIN(ReadArgs);
188  }
189 <Start>{B}*"<" {
190  yyextra->name+="<";
191  yyextra->sharpCount=0;
192  yyextra->roundCount=0;
193  BEGIN(Template);
194  }
195 <Template>"<<" { yyextra->name+="<<"; }
196 <Template>">>" { yyextra->name+=">>"; }
197 <Template>"(" { yyextra->name+="(";
198  yyextra->roundCount++;
199  }
200 <Template>")" { yyextra->name+=")";
201  if (yyextra->roundCount>0)
202  {
203  yyextra->roundCount--;
204  }
205  }
206 <Template>"<" {
207  yyextra->name+="<";
208  if (yyextra->roundCount==0)
209  {
210  yyextra->sharpCount++;
211  }
212  }
213 <Template>">" {
214  yyextra->name+=">";
215  if (yyextra->roundCount==0)
216  {
217  if (yyextra->sharpCount)
218  --yyextra->sharpCount;
219  else
220  {
221  BEGIN(Start);
222  }
223  }
224  }
225 <Template>. {
226  yyextra->name+=*yytext;
227  }
228 <Operator>{B}*"("{B}*")"{B}*"<>"{Bopt}/"(" {
229  yyextra->name+="() <>";
230  BEGIN(ReadArgs);
231  }
232 <Operator>{B}*"("{B}*")"{Bopt}/"(" {
233  yyextra->name+="()";
234  BEGIN(ReadArgs);
235  }
236 <Operator>[^(]*{B}*("<>"{B}*)?/"(" {
237  yyextra->name+=yytext;
238  BEGIN(ReadArgs);
239  }
240 <ReadArgs>"throw"{B}*"(" {
241  yyextra->exceptionString="throw(";
242  BEGIN(ReadExceptions);
243  }
244 <ReadArgs>. {
245  yyextra->args+=*yytext;
246  }
247 <ReadExceptions>. {
248  yyextra->exceptionString+=*yytext;
249  }
250 <*>.
251 <*>\n
252 
253 %%
254 
255 static void addType(yyscan_t yyscanner)
256 {
257  struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
258  //printf("addType() yyextra->type='%s' yyextra->scope='%s' yyextra->name='%s'\n",
259  // qPrint(yyextra->type),qPrint(yyextra->scope),qPrint(yyextra->name));
260  if (yyextra->name.isEmpty() && yyextra->scope.isEmpty()) return;
261  if (!yyextra->type.isEmpty()) yyextra->type+=" ";
262  if (!yyextra->scope.isEmpty()) yyextra->type+=yyextra->scope+"::";
263  yyextra->type+=yyextra->name;
264  yyextra->scope.resize(0);
265  yyextra->name.resize(0);
266 }
267 
268 static void addTypeName(yyscan_t yyscanner)
269 {
270  struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
271  //printf("addTypeName() yyextra->type='%s' yyextra->scope='%s' yyextra->name='%s'\n",
272  // qPrint(yyextra->type),qPrint(yyextra->scope),qPrint(yyextra->name));
273  if (yyextra->name.isEmpty() ||
274  yyextra->name.at(yyextra->name.length()-1)==':') // end of Objective-C keyword => append to yyextra->name not yyextra->type
275  {
276  return;
277  }
278  if (!yyextra->type.isEmpty()) yyextra->type+=' ';
279  yyextra->type+=yyextra->name;
280  yyextra->name.resize(0);
281 }
282 
283 static yy_size_t yyread(char *buf,yy_size_t max_size, yyscan_t yyscanner)
284 {
285  struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
286  yy_size_t c=0;
287  while( c < max_size && yyextra->inputString[yyextra->inputPosition] )
288  {
289  *buf = yyextra->inputString[yyextra->inputPosition++] ;
290  c++; buf++;
291  }
292  return c;
293 }
294 
295 /*@ public interface------------------------------------------------------------
296  */
297 static yyscan_t g_yyscanner;
298 static struct declinfoYY_state g_declinfo_extra;
299 
300 void parseFuncDecl(const QCString &decl,const SrcLangExt lang,QCString &cl,QCString &t,
301  QCString &n,QCString &a,QCString &ftl,QCString &exc)
302 {
303  if (decl.isEmpty())
304  {
305  return;
306  }
307  declinfoYYlex_init_extra(&g_declinfo_extra, &g_yyscanner);
308  struct yyguts_t *yyg = (struct yyguts_t*)g_yyscanner;
309 
310 #ifdef FLEX_DEBUG
311  declinfoYYset_debug(1,g_yyscanner);
312 #endif
313 
314  printlex(yy_flex_debug, TRUE, __FILE__, NULL);
315  yyextra->inputString = decl.data();
316  //printf("Input='%s'\n",yyextra->inputString);
317  yyextra->inputPosition = 0;
318  yyextra->classTempListFound = FALSE;
319  yyextra->funcTempListFound = FALSE;
320  yyextra->insideObjC = lang==SrcLangExt_ObjC;
321  yyextra->insidePHP = lang==SrcLangExt_PHP;
322  yyextra->scope.resize(0);
323  yyextra->className.resize(0);
324  yyextra->classTempList.resize(0);
325  yyextra->funcTempList.resize(0);
326  yyextra->name.resize(0);
327  yyextra->type.resize(0);
328  yyextra->args.resize(0);
329  yyextra->exceptionString.resize(0);
330  // first we try to find the yyextra->type, yyextra->scope, yyextra->name and arguments
331  declinfoYYrestart( yyin, g_yyscanner );
332  BEGIN( Start );
333  declinfoYYlex(g_yyscanner);
334 
335  //printf("yyextra->type='%s' class='%s' yyextra->name='%s' yyextra->args='%s'\n",
336  // qPrint(yyextra->type),qPrint(yyextra->scope),qPrint(yyextra->name),qPrint(yyextra->args));
337 
338  int nb = yyextra->name.findRev('[');
339  if (nb!=-1 && yyextra->args.isEmpty()) // correct for [] in yyextra->name ambiguity (due to Java return yyextra->type allowing [])
340  {
341  yyextra->args.prepend(yyextra->name.right(yyextra->name.length()-nb));
342  yyextra->name=yyextra->name.left(nb);
343  }
344 
345 #if 0
346  {
347  int l=yyextra->scope.length();
348  int i=0;
349  int skipCount=0;
350  cl.resize(0);
351  ctl.resize(0);
352  for (i=0;i<l;i++)
353  {
354  char c=yyextra->scope.at(i);
355  if (c=='<')
356  skipCount++;
357  else if (c=='>')
358  skipCount--;
359  else if (skipCount==0)
360  cl+=c;
361  }
362  }
363  cl=stripTemplateSpecifiersFromScope(removeRedundantWhiteSpace(yyextra->scope),FALSE);
364  ctl.resize(0);
365 #endif
366 
367  cl=yyextra->scope;
368  n=removeRedundantWhiteSpace(yyextra->name);
369  int il,ir;
370  if ((il=n.find('<'))!=-1 && (ir=n.findRev('>'))!=-1)
371  // TODO: handle cases like where n="operator<< <T>"
372  {
373  ftl=removeRedundantWhiteSpace(n.right(n.length()-il));
374  n=n.left(il);
375  }
376 
377  //ctl=yyextra->classTempList.copy();
378  //ftl=yyextra->funcTempList.copy();
379  t=removeRedundantWhiteSpace(yyextra->type);
380  a=removeRedundantWhiteSpace(yyextra->args);
381  exc=removeRedundantWhiteSpace(yyextra->exceptionString);
382 
383  if (!t.isEmpty() && !t.startsWith("decltype") && t.at(t.length()-1)==')') // for function pointers
384  {
385  a.prepend(")");
386  t=t.left(t.length()-1);
387  }
388  //printf("yyextra->type='%s' class='%s' yyextra->name='%s' yyextra->args='%s'\n",
389  // qPrint(t),qPrint(cl),qPrint(n),qPrint(a));
390 
391  printlex(yy_flex_debug, FALSE, __FILE__, NULL);
392  declinfoYYlex_destroy(g_yyscanner);
393  return;
394 }
395 
396 #if 0
397 void dumpDecl(const char *s)
398 {
399  QCString yyextra->className;
400  QCString classTNames;
401  QCString yyextra->type;
402  QCString yyextra->name;
403  QCString yyextra->args;
404  QCString funcTNames;
405  msg("-----------------------------------------\n");
406  parseFuncDecl(s,yyextra->className,classTNames,yyextra->type,yyextra->name,yyextra->args,funcTNames);
407  msg("yyextra->type='%s' class='%s' classTempl='%s' yyextra->name='%s' "
408  "funcTemplateNames='%s' yyextra->args='%s'\n",
409  qPrint(yyextra->type),qPrint(yyextra->className),qPrint(classTNames),
410  qPrint(yyextra->name),qPrint(funcTNames),qPrint(yyextra->args)
411  );
412 }
413 
414 // some test code
415 int main()
416 {
417  dumpDecl("A < T > :: Value * A < T > :: getValue < S > ( const A < T > & a )");
418  dumpDecl("const A<T>::Value* A<T>::getValue<S>(const A<T>&a)");
419  dumpDecl("func()");
420  dumpDecl("friend void bla<>()");
421  dumpDecl("yyextra->name< T > :: operator () (int bla)");
422  dumpDecl("yyextra->name< T > :: operator << (int bla)");
423  dumpDecl("yyextra->name< T > :: operator << <> (int bla)");
424  dumpDecl("yyextra->className::func()");
425  dumpDecl("void ( * yyextra->Name < T > :: bla ) ( int, char * )");
426 }
427 #endif
428 
429 #if USE_STATE2STRING
430 #include "declinfo.l.h"
431 #endif