|
1 /****************************************************************************** |
|
2 * |
|
3 * |
|
4 * |
|
5 * Copyright (C) 1997-2008 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 |
|
18 %{ |
|
19 |
|
20 /* |
|
21 * includes |
|
22 */ |
|
23 #include <stdio.h> |
|
24 //#include <iostream.h> |
|
25 #include <assert.h> |
|
26 #include <ctype.h> |
|
27 |
|
28 #include "declinfo.h" |
|
29 #include "util.h" |
|
30 #include "message.h" |
|
31 |
|
32 /* ----------------------------------------------------------------- |
|
33 * |
|
34 * statics |
|
35 */ |
|
36 |
|
37 static const char * inputString; |
|
38 static int inputPosition; |
|
39 static QCString scope; |
|
40 static QCString className; |
|
41 static QCString classTempList; |
|
42 static QCString funcTempList; |
|
43 static QCString type; |
|
44 static QCString name; |
|
45 static QCString args; |
|
46 static QCString tmpType; |
|
47 static int sharpCount; |
|
48 static bool classTempListFound; |
|
49 static bool funcTempListFound; |
|
50 static QCString exceptionString; |
|
51 static bool insideObjC; |
|
52 |
|
53 static void addType() |
|
54 { |
|
55 //printf("addType() type=`%s' scope=`%s' name=`%s'\n", |
|
56 // type.data(),scope.data(),name.data()); |
|
57 if (name.isEmpty() && scope.isEmpty()) return; |
|
58 if (!type.isEmpty()) type+=" "; |
|
59 if (!scope.isEmpty()) type+=scope+"::"; |
|
60 type+=name; |
|
61 scope.resize(0); |
|
62 name.resize(0); |
|
63 } |
|
64 |
|
65 static void addTypeName() |
|
66 { |
|
67 //printf("addTypeName() type=`%s' scope=`%s' name=`%s'\n", |
|
68 // type.data(),scope.data(),name.data()); |
|
69 if (name.isEmpty() || |
|
70 name.at(name.length()-1)==':') // end of Objective-C keyword => append to name not type |
|
71 { |
|
72 return; |
|
73 } |
|
74 if (!type.isEmpty()) type+=' '; |
|
75 type+=name; |
|
76 name.resize(0); |
|
77 } |
|
78 |
|
79 #define YY_NEVER_INTERACTIVE 1 |
|
80 |
|
81 /* ----------------------------------------------------------------- |
|
82 */ |
|
83 #undef YY_INPUT |
|
84 #define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size); |
|
85 |
|
86 static int yyread(char *buf,int max_size) |
|
87 { |
|
88 int c=0; |
|
89 while( c < max_size && inputString[inputPosition] ) |
|
90 { |
|
91 *buf = inputString[inputPosition++] ; |
|
92 c++; buf++; |
|
93 } |
|
94 return c; |
|
95 } |
|
96 |
|
97 %} |
|
98 |
|
99 B [ \t] |
|
100 ID "$"?([a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]*)|(@[0-9]+) |
|
101 |
|
102 %option nounput |
|
103 %option noyywrap |
|
104 |
|
105 %x Start |
|
106 %x Template |
|
107 %x ReadArgs |
|
108 %x Operator |
|
109 %x FuncPtr |
|
110 %x EndTemplate |
|
111 %x StripTempArgs |
|
112 %x SkipSharp |
|
113 %x ReadExceptions |
|
114 |
|
115 %% |
|
116 |
|
117 <Start>"operator"/({B}*"["{B}*"]")* { // operator rule must be before {ID} rule |
|
118 name += yytext; |
|
119 BEGIN(Operator); |
|
120 } |
|
121 <Start>{ID}{B}*"("{B}*{ID}{B}*")" { // Objective-C class categories |
|
122 if (!insideObjC) |
|
123 { |
|
124 REJECT; |
|
125 } |
|
126 else |
|
127 { |
|
128 name += yytext; |
|
129 } |
|
130 } |
|
131 <Start>(~{B}*)?{ID}/({B}*"["{B}*"]")* { // the []'s are for Java, |
|
132 // the / was add to deal with multi- |
|
133 // dimensional C++ arrays like A[][15] |
|
134 addTypeName(); |
|
135 name += yytext; |
|
136 } |
|
137 <Start>{B}*"::"{B}* { // found a scope specifier |
|
138 if (!scope.isEmpty()) |
|
139 { |
|
140 scope+="::"+name; // add name to scope |
|
141 } |
|
142 else |
|
143 { |
|
144 scope = name.copy(); // scope becomes name |
|
145 } |
|
146 name.resize(0); |
|
147 } |
|
148 <Start>{B}*":" { // Objective-C argument separator |
|
149 name+=yytext; |
|
150 } |
|
151 <Start>[*&]+ { |
|
152 addType(); |
|
153 type+=yytext; |
|
154 } |
|
155 <Start>{B}+ { |
|
156 addType(); |
|
157 } |
|
158 <Start>{B}*"("({ID}"::")*{B}*[&*]({B}*("const"|"volatile"){B}+)? { |
|
159 addType(); |
|
160 QCString text=yytext; |
|
161 type+=text.stripWhiteSpace(); |
|
162 } |
|
163 <Start>{B}*")" { |
|
164 type+=")"; |
|
165 } |
|
166 <Start>{B}*"(" { // TODO: function pointers |
|
167 args+="("; |
|
168 BEGIN(ReadArgs); |
|
169 } |
|
170 <Start>{B}*"[" { |
|
171 args+="["; |
|
172 BEGIN(ReadArgs); |
|
173 } |
|
174 <Start>{B}*"<" { |
|
175 name+="<"; |
|
176 sharpCount=0; |
|
177 BEGIN(Template); |
|
178 } |
|
179 <Template>"<<" { name+="<<"; } |
|
180 <Template>">>" { name+=">>"; } |
|
181 <Template>"<" { |
|
182 name+="<"; |
|
183 sharpCount++; |
|
184 } |
|
185 <Template>">" { |
|
186 name+=">"; |
|
187 if (sharpCount) |
|
188 --sharpCount; |
|
189 else |
|
190 { |
|
191 BEGIN(Start); |
|
192 } |
|
193 } |
|
194 <Template>. { |
|
195 name+=*yytext; |
|
196 } |
|
197 <Operator>{B}*"("{B}*")"{B}*"<>"{B}*/"(" { |
|
198 name+="() <>"; |
|
199 BEGIN(ReadArgs); |
|
200 } |
|
201 <Operator>{B}*"("{B}*")"{B}*/"(" { |
|
202 name+="()"; |
|
203 BEGIN(ReadArgs); |
|
204 } |
|
205 <Operator>[^(]*{B}*("<>"{B}*)?/"(" { |
|
206 name+=yytext; |
|
207 BEGIN(ReadArgs); |
|
208 } |
|
209 <ReadArgs>"throw"{B}*"(" { |
|
210 exceptionString="throw("; |
|
211 BEGIN(ReadExceptions); |
|
212 } |
|
213 <ReadArgs>. { |
|
214 args+=*yytext; |
|
215 } |
|
216 <ReadExceptions>. { |
|
217 exceptionString+=*yytext; |
|
218 } |
|
219 <*>. |
|
220 <*>\n |
|
221 |
|
222 %% |
|
223 |
|
224 /*@ ---------------------------------------------------------------------------- |
|
225 */ |
|
226 |
|
227 void parseFuncDecl(const QCString &decl,bool objC,QCString &cl,QCString &t, |
|
228 QCString &n,QCString &a,QCString &ftl,QCString &exc) |
|
229 { |
|
230 inputString = decl; |
|
231 //printf("Input=`%s'\n",inputString); |
|
232 if (inputString==0) return; |
|
233 inputPosition = 0; |
|
234 classTempListFound = FALSE; |
|
235 funcTempListFound = FALSE; |
|
236 insideObjC = objC; |
|
237 scope.resize(0); |
|
238 className.resize(0); |
|
239 classTempList.resize(0); |
|
240 funcTempList.resize(0); |
|
241 name.resize(0); |
|
242 type.resize(0); |
|
243 args.resize(0); |
|
244 exceptionString.resize(0); |
|
245 // first we try to find the type, scope, name and arguments |
|
246 declinfoYYrestart( declinfoYYin ); |
|
247 BEGIN( Start ); |
|
248 declinfoYYlex(); |
|
249 |
|
250 //printf("type=`%s' class=`%s' name=`%s' args=`%s'\n", |
|
251 // type.data(),scope.data(),name.data(),args.data()); |
|
252 |
|
253 int nb = name.findRev('['); |
|
254 if (nb!=-1 && args.isEmpty()) // correct for [] in name ambigity (due to Java return type allowing []) |
|
255 { |
|
256 args.prepend(name.right(name.length()-nb)); |
|
257 name=name.left(nb); |
|
258 } |
|
259 |
|
260 #if 0 |
|
261 { |
|
262 int l=scope.length(); |
|
263 int i=0; |
|
264 int skipCount=0; |
|
265 cl.resize(0); |
|
266 ctl.resize(0); |
|
267 for (i=0;i<l;i++) |
|
268 { |
|
269 char c=scope.at(i); |
|
270 if (c=='<') |
|
271 skipCount++; |
|
272 else if (c=='>') |
|
273 skipCount--; |
|
274 else if (skipCount==0) |
|
275 cl+=c; |
|
276 } |
|
277 } |
|
278 cl=stripTemplateSpecifiersFromScope(removeRedundantWhiteSpace(scope),FALSE); |
|
279 ctl.resize(0); |
|
280 #endif |
|
281 |
|
282 cl=scope; |
|
283 n=removeRedundantWhiteSpace(name); |
|
284 int il,ir; |
|
285 if ((il=n.find('<'))!=-1 && (ir=n.findRev('>'))!=-1) |
|
286 // TODO: handle cases like where n="operator<< <T>" |
|
287 { |
|
288 ftl=removeRedundantWhiteSpace(n.right(n.length()-il)); |
|
289 n=n.left(il); |
|
290 } |
|
291 |
|
292 //ctl=classTempList.copy(); |
|
293 //ftl=funcTempList.copy(); |
|
294 t=removeRedundantWhiteSpace(type); |
|
295 a=removeRedundantWhiteSpace(args); |
|
296 exc=removeRedundantWhiteSpace(exceptionString); |
|
297 |
|
298 if (!t.isEmpty() && t.at(t.length()-1)==')') // for function pointers |
|
299 { |
|
300 a.prepend(")"); |
|
301 t=t.left(t.length()-1); |
|
302 } |
|
303 //printf("type=`%s' class=`%s' name=`%s' args=`%s'\n", |
|
304 // t.data(),cl.data(),n.data(),a.data()); |
|
305 |
|
306 return; |
|
307 |
|
308 |
|
309 } |
|
310 |
|
311 //extern "C" { // some bogus code to keep the compiler happy |
|
312 // int declinfoYYwrap() { return 1 ; } |
|
313 // void declinfoYYdummy() { yy_flex_realloc(0,0); } |
|
314 //} |
|
315 |
|
316 #if 0 |
|
317 void dumpDecl(const char *s) |
|
318 { |
|
319 QCString className; |
|
320 QCString classTNames; |
|
321 QCString type; |
|
322 QCString name; |
|
323 QCString args; |
|
324 QCString funcTNames; |
|
325 msg("-----------------------------------------\n"); |
|
326 parseFuncDecl(s,className,classTNames,type,name,args,funcTNames); |
|
327 msg("type=`%s' class=`%s' classTempl=`%s' name=`%s' " |
|
328 "funcTemplateNames=`%s' args=`%s'\n", |
|
329 type.data(),className.data(),classTNames.data(), |
|
330 name.data(),funcTNames.data(),args.data() |
|
331 ); |
|
332 } |
|
333 |
|
334 // some test code |
|
335 int main() |
|
336 { |
|
337 dumpDecl("A < T > :: Value * A < T > :: getValue < S > ( const A < T > & a )"); |
|
338 dumpDecl("const A<T>::Value* A<T>::getValue<S>(const A<T>&a)"); |
|
339 dumpDecl("func()"); |
|
340 dumpDecl("friend void bla<>()"); |
|
341 dumpDecl("name< T > :: operator () (int bla)"); |
|
342 dumpDecl("name< T > :: operator << (int bla)"); |
|
343 dumpDecl("name< T > :: operator << <> (int bla)"); |
|
344 dumpDecl("className::func()"); |
|
345 dumpDecl("void ( * Name < T > :: bla ) ( int, char * )"); |
|
346 } |
|
347 #endif |
|
348 |
|
349 #if !defined(YY_FLEX_SUBMINOR_VERSION) |
|
350 //---------------------------------------------------------------------------- |
|
351 extern "C" { // some bogus code to keep the compiler happy |
|
352 void declinfoYYdummy() { yy_flex_realloc(0,0); } |
|
353 } |
|
354 #endif |
|
355 |