|
1 /****************************************************************************** |
|
2 * |
|
3 * |
|
4 * |
|
5 * |
|
6 * Copyright (C) 1997-2008 by Dimitri van Heesch. |
|
7 * |
|
8 * Permission to use, copy, modify, and distribute this software and its |
|
9 * documentation under the terms of the GNU General Public License is hereby |
|
10 * granted. No representations are made about the suitability of this software |
|
11 * for any purpose. It is provided "as is" without express or implied warranty. |
|
12 * See the GNU General Public License for more details. |
|
13 * |
|
14 * Documents produced by Doxygen are derivative works derived from the |
|
15 * input used in their production; they are not affected by this license. |
|
16 * |
|
17 */ |
|
18 |
|
19 %{ |
|
20 |
|
21 #include <qfile.h> |
|
22 #include <qstring.h> |
|
23 #include <qstack.h> |
|
24 #include <qdict.h> |
|
25 |
|
26 #include "doctokenizer.h" |
|
27 #include "cmdmapper.h" |
|
28 #include "config.h" |
|
29 #include "message.h" |
|
30 #include "section.h" |
|
31 #include "membergroup.h" |
|
32 #include "definition.h" |
|
33 #include "doxygen.h" |
|
34 #include "portable.h" |
|
35 |
|
36 #define YY_NEVER_INTERACTIVE 1 |
|
37 |
|
38 //-------------------------------------------------------------------------- |
|
39 |
|
40 // context for tokenizer phase |
|
41 static int g_commentState; |
|
42 TokenInfo *g_token = 0; |
|
43 static int g_inputPos = 0; |
|
44 static const char *g_inputString; |
|
45 static QString g_fileName; |
|
46 static bool g_insidePre; |
|
47 |
|
48 // context for section finding phase |
|
49 static Definition *g_definition; |
|
50 static MemberGroup *g_memberGroup; |
|
51 static QCString g_secLabel; |
|
52 static QCString g_secTitle; |
|
53 static SectionInfo::SectionType g_secType; |
|
54 static QCString g_endMarker; |
|
55 |
|
56 struct DocLexerContext |
|
57 { |
|
58 TokenInfo *token; |
|
59 int rule; |
|
60 int inputPos; |
|
61 const char *inputString; |
|
62 YY_BUFFER_STATE state; |
|
63 }; |
|
64 |
|
65 static QStack<DocLexerContext> g_lexerStack; |
|
66 |
|
67 //-------------------------------------------------------------------------- |
|
68 |
|
69 void doctokenizerYYpushContext() |
|
70 { |
|
71 DocLexerContext *ctx = new DocLexerContext; |
|
72 ctx->rule = YY_START; |
|
73 ctx->token = g_token; |
|
74 ctx->inputPos = g_inputPos; |
|
75 ctx->inputString = g_inputString; |
|
76 ctx->state = YY_CURRENT_BUFFER; |
|
77 g_lexerStack.push(ctx); |
|
78 yy_switch_to_buffer(yy_create_buffer(doctokenizerYYin, YY_BUF_SIZE)); |
|
79 } |
|
80 |
|
81 bool doctokenizerYYpopContext() |
|
82 { |
|
83 if (g_lexerStack.isEmpty()) return FALSE; |
|
84 DocLexerContext *ctx = g_lexerStack.pop(); |
|
85 g_inputPos = ctx->inputPos; |
|
86 g_inputString = ctx->inputString; |
|
87 yy_delete_buffer(YY_CURRENT_BUFFER); |
|
88 yy_switch_to_buffer(ctx->state); |
|
89 BEGIN(ctx->rule); |
|
90 delete ctx; |
|
91 return TRUE; |
|
92 } |
|
93 |
|
94 |
|
95 //-------------------------------------------------------------------------- |
|
96 |
|
97 const char *tokToString(int token) |
|
98 { |
|
99 switch (token) |
|
100 { |
|
101 case 0: return "TK_EOF"; |
|
102 case TK_WORD: return "TK_WORD"; |
|
103 case TK_LNKWORD: return "TK_LNKWORD"; |
|
104 case TK_WHITESPACE: return "TK_WHITESPACE"; |
|
105 case TK_LISTITEM: return "TK_LISTITEM"; |
|
106 case TK_ENDLIST: return "TK_ENDLIST"; |
|
107 case TK_COMMAND: return "TK_COMMAND"; |
|
108 case TK_HTMLTAG: return "TK_HTMLTAG"; |
|
109 case TK_SYMBOL: return "TK_SYMBOL"; |
|
110 case TK_NEWPARA: return "TK_NEWPARA"; |
|
111 case TK_RCSTAG: return "TK_RCSTAG"; |
|
112 case TK_URL: return "TK_URL"; |
|
113 } |
|
114 return "ERROR"; |
|
115 } |
|
116 |
|
117 static int computeIndent(const char *str,int length) |
|
118 { |
|
119 int i; |
|
120 int indent=0; |
|
121 int tabSize=Config_getInt("TAB_SIZE"); |
|
122 for (i=0;i<length;i++) |
|
123 { |
|
124 if (str[i]=='\t') |
|
125 { |
|
126 indent+=tabSize - (indent%tabSize); |
|
127 } |
|
128 else if (str[i]=='\n') |
|
129 { |
|
130 indent=0; |
|
131 } |
|
132 else |
|
133 { |
|
134 indent++; |
|
135 } |
|
136 } |
|
137 return indent; |
|
138 } |
|
139 |
|
140 //-------------------------------------------------------------------------- |
|
141 |
|
142 static void processSection() |
|
143 { |
|
144 //printf("%s: found section/anchor with name `%s'\n",g_fileName.data(),g_secLabel.data()); |
|
145 QCString file; |
|
146 if (g_memberGroup) |
|
147 { |
|
148 file = g_memberGroup->parent()->getOutputFileBase(); |
|
149 } |
|
150 else if (g_definition) |
|
151 { |
|
152 file = g_definition->getOutputFileBase(); |
|
153 } |
|
154 else |
|
155 { |
|
156 warn(g_fileName,yylineno,"Found section/anchor %s without context\n",g_secLabel.data()); |
|
157 } |
|
158 SectionInfo *si=0; |
|
159 if ((si=Doxygen::sectionDict.find(g_secLabel))) |
|
160 { |
|
161 si->fileName = file; |
|
162 //si = new SectionInfo(file,g_secLabel,g_secTitle,g_secType); |
|
163 //Doxygen::sectionDict.insert(g_secLabel,si); |
|
164 } |
|
165 } |
|
166 |
|
167 static void handleHtmlTag() |
|
168 { |
|
169 QCString tagText=yytext; |
|
170 g_token->attribs.clear(); |
|
171 g_token->endTag = FALSE; |
|
172 g_token->emptyTag = FALSE; |
|
173 |
|
174 // Check for end tag |
|
175 int startNamePos=1; |
|
176 if (tagText.at(1)=='/') |
|
177 { |
|
178 g_token->endTag = TRUE; |
|
179 startNamePos++; |
|
180 } |
|
181 |
|
182 // Parse the name portion |
|
183 int i = startNamePos; |
|
184 for (i=startNamePos; i < yyleng; i++) |
|
185 { |
|
186 // Check for valid HTML/XML name chars (including namespaces) |
|
187 char c = tagText.at(i); |
|
188 if (!(isalnum(c) || c=='-' || c=='_' || c==':')) break; |
|
189 } |
|
190 g_token->name = tagText.mid(startNamePos,i-startNamePos); |
|
191 |
|
192 // Parse the attributes. Each attribute is a name, value pair |
|
193 // The result is stored in g_token->attribs. |
|
194 int startName,endName,startAttrib,endAttrib; |
|
195 while (i<yyleng) |
|
196 { |
|
197 char c=tagText.at(i); |
|
198 // skip spaces |
|
199 while (i<yyleng && isspace(c)) { c=tagText.at(++i); } |
|
200 // check for end of the tag |
|
201 if (c == '>') break; |
|
202 // Check for XML style "empty" tag. |
|
203 if (c == '/') |
|
204 { |
|
205 g_token->emptyTag = TRUE; |
|
206 break; |
|
207 } |
|
208 startName=i; |
|
209 // search for end of name |
|
210 while (i<yyleng && !isspace(c) && c!='=') { c=tagText.at(++i); } |
|
211 endName=i; |
|
212 HtmlAttrib opt; |
|
213 opt.name = tagText.mid(startName,endName-startName).lower(); |
|
214 // skip spaces |
|
215 while (i<yyleng && isspace(c)) { c=tagText.at(++i); } |
|
216 if (tagText.at(i)=='=') // option has value |
|
217 { |
|
218 c=tagText.at(++i); |
|
219 // skip spaces |
|
220 while (i<yyleng && isspace(c)) { c=tagText.at(++i); } |
|
221 if (tagText.at(i)=='\'') // option '...' |
|
222 { |
|
223 c=tagText.at(++i); |
|
224 startAttrib=i; |
|
225 |
|
226 // search for matching quote |
|
227 while (i<yyleng && c!='\'') { c=tagText.at(++i); } |
|
228 endAttrib=i; |
|
229 if (i<yyleng) c=tagText.at(++i); |
|
230 } |
|
231 else if (tagText.at(i)=='"') // option "..." |
|
232 { |
|
233 c=tagText.at(++i); |
|
234 startAttrib=i; |
|
235 // search for matching quote |
|
236 while (i<yyleng && c!='"') { c=tagText.at(++i); } |
|
237 endAttrib=i; |
|
238 if (i<yyleng) c=tagText.at(++i); |
|
239 } |
|
240 else // value without any quotes |
|
241 { |
|
242 startAttrib=i; |
|
243 // search for separator or end symbol |
|
244 while (i<yyleng && !isspace(c) && c!='>') { c=tagText.at(++i); } |
|
245 endAttrib=i; |
|
246 if (i<yyleng) c=tagText.at(++i); |
|
247 } |
|
248 opt.value = tagText.mid(startAttrib,endAttrib-startAttrib); |
|
249 } |
|
250 else // start next option |
|
251 { |
|
252 } |
|
253 //printf("=====> Adding option name=<%s> value=<%s>\n", |
|
254 // opt.name.data(),opt.value.data()); |
|
255 g_token->attribs.append(&opt); |
|
256 } |
|
257 } |
|
258 |
|
259 static QString stripEmptyLines(const char *s) |
|
260 { |
|
261 int result=0,p=0; |
|
262 for (;;) |
|
263 { |
|
264 int c; |
|
265 while ((c=s[p]) && isspace(c)) p++; |
|
266 if (s[p]=='\n') result=++p; else break; |
|
267 } |
|
268 return &s[result]; |
|
269 } |
|
270 |
|
271 //-------------------------------------------------------------------------- |
|
272 |
|
273 #undef YY_INPUT |
|
274 #define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size); |
|
275 |
|
276 static int yyread(char *buf,int max_size) |
|
277 { |
|
278 int c=0; |
|
279 const char *src=g_inputString+g_inputPos; |
|
280 while ( c < max_size && *src ) *buf++ = *src++, c++; |
|
281 g_inputPos+=c; |
|
282 return c; |
|
283 } |
|
284 |
|
285 //-------------------------------------------------------------------------- |
|
286 |
|
287 %} |
|
288 |
|
289 CMD ("\\"|"@") |
|
290 WS [ \t\r\n] |
|
291 NONWS [^ \t\r\n] |
|
292 BLANK [ \t\r] |
|
293 ID "$"?[a-z_A-Z][a-z_A-Z0-9]* |
|
294 MAILADR [a-z_A-Z0-9.+-]+"@"[a-z_A-Z0-9-]+("."[a-z_A-Z0-9\-]+)+[a-z_A-Z0-9\-]+ |
|
295 OPTSTARS ("//"{BLANK}*)?"*"*{BLANK}* |
|
296 LISTITEM {BLANK}*{OPTSTARS}"-"("#")?{WS} |
|
297 ENDLIST {BLANK}*{OPTSTARS}"."{BLANK}*\n |
|
298 ATTRIB {ID}{WS}*("="{WS}*(("\""[^\"]*"\"")|("'"[^\']*"'")|[^ \t\r\n'"><]+))? |
|
299 URLCHAR [a-z_A-Z0-9\!\~\,\:\;\'\$\?\@\&\%\#\.\-\+\/\=] |
|
300 URLMASK (([a-z_A-Z][^\>\"\n]*{URLCHAR})|({URLCHAR}+))([({]{URLCHAR}*[)}])? |
|
301 FILESCHAR [a-z_A-Z0-9\\:\\\/\-\+] |
|
302 FILEECHAR [a-z_A-Z0-9\-\+] |
|
303 HFILEMASK ("."{FILESCHAR}*{FILEECHAR}+)* |
|
304 FILEMASK ({FILESCHAR}*{FILEECHAR}+("."{FILESCHAR}*{FILEECHAR}+)*)|{HFILEMASK} |
|
305 LINKMASK [^ \t\n\r\\@<&${}]+("("[^\n)]*")")?({BLANK}*("const"|"volatile"){BLANK}+)? |
|
306 VERBATIM "verbatim"{BLANK}* |
|
307 SPCMD1 {CMD}([a-z_A-Z0-9]+|{VERBATIM}) |
|
308 SPCMD2 {CMD}[\\@<>&$#%~"] |
|
309 SPCMD3 {CMD}form#[0-9]+ |
|
310 INOUT "in"|"out"|("in"{BLANK}*","{BLANK}*"out")|("out"{BLANK}*","{BLANK}*"in") |
|
311 PARAMIO {CMD}param{BLANK}*"["{BLANK}*{INOUT}{BLANK}*"]" |
|
312 TEMPCHAR [a-z_A-Z0-9,: \t\*\&] |
|
313 FUNCCHAR [a-z_A-Z0-9,:\<\> \t\*\&] |
|
314 SCOPESEP "::"|"#"|"." |
|
315 TEMPLPART "<"{TEMPCHAR}*">" |
|
316 SCOPEPRE {ID}{TEMPLPART}?{SCOPESEP} |
|
317 SCOPEKEYS ":"({ID}":")* |
|
318 SCOPECPP {SCOPEPRE}*(~)?{ID}("<"{TEMPCHAR}*">")? |
|
319 SCOPEOBJC {SCOPEPRE}?{ID}{SCOPEKEYS}? |
|
320 SCOPEMASK {SCOPECPP}|{SCOPEOBJC} |
|
321 FUNCARG "("{FUNCCHAR}*")"({BLANK}*("volatile"|"const"){BLANK})? |
|
322 OPNEW {BLANK}+"new"({BLANK}*"[]")? |
|
323 OPDEL {BLANK}+"delete"({BLANK}*"[]")? |
|
324 OPNORM {OPNEW}|{OPDEL}|"+"|"-"|"*"|"/"|"%"|"^"|"&"|"|"|"~"|"!"|"="|"<"|">"|"+="|"-="|"*="|"/="|"%="|"^="|"&="|"|="|"<<"|">>"|"<<="|">>="|"=="|"!="|"<="|">="|"&&"|"||"|"++"|"--"|","|"->*"|"->"|"[]"|"()" |
|
325 OPCAST {BLANK}+[^<(\r\n.,][^(\r\n.,]* |
|
326 OPMASK ({BLANK}*{OPNORM}{FUNCARG}) |
|
327 OPMASKOPT ({BLANK}*{OPNORM}{FUNCARG}?)|({OPCAST}{FUNCARG}) |
|
328 LNKWORD1 ("::"|"#")?{SCOPEMASK} |
|
329 CVSPEC {BLANK}*("const"|"volatile") |
|
330 LNKWORD2 ({SCOPEPRE}*"operator"{OPMASK})|({SCOPEPRE}"operator"{OPMASKOPT})|(("::"|"#"){SCOPEPRE}*"operator"{OPMASKOPT}) |
|
331 LNKWORD3 ([0-9a-z_A-Z\-]+("/"|"\\"))*[0-9a-z_A-Z\-]+("."[0-9a-z_A-Z]+)+ |
|
332 CHARWORDQ [^ \t\n\r\\@<>()\[\]:;\?{}&%$#,."] |
|
333 WORD1 "%"?{CHARWORDQ}+|"{"|"}"|("\""[^"\n]*\n?[^"\n]*"\"") |
|
334 WORD2 "."|","|"("|")"|"["|"]"|":"|";"|"\?" |
|
335 WORD1NQ "%"?{CHARWORDQ}+ |
|
336 WORD2NQ "."|","|"("|")"|"["|"]"|":"|";"|"\?" |
|
337 HTMLTAG "<"(("/")?){ID}({WS}+{ATTRIB})*{WS}*(("/")?)">" |
|
338 HTMLKEYL "strong"|"center"|"table"|"caption"|"small"|"code"|"dfn"|"var"|"img"|"pre"|"sub"|"sup"|"tr"|"td"|"th"|"ol"|"ul"|"li"|"tt"|"kbd"|"em"|"hr"|"dl"|"dt"|"dd"|"br"|"i"|"a"|"b"|"p" |
|
339 HTMLKEYU "STRONG"|"CENTER"|"TABLE"|"CAPTION"|"SMALL"|"CODE"|"DFN"|"VAR"|"IMG"|"PRE"|"SUB"|"SUP"|"TR"|"TD"|"TH"|"OL"|"UL"|"LI"|"TT"|"KBD"|"EM"|"HR"|"DL"|"DT"|"DD"|"BR"|"I"|"A"|"B"|"P" |
|
340 HTMLKEYW {HTMLKEYL}|{HTMLKEYU} |
|
341 LABELID [a-z_A-Z][a-z_A-Z0-9\-]* |
|
342 REFWORD2 ("#"|"::")?({ID}{TEMPLPART}?("."|"#"|"::"|"-"|"/"))*({ID}(":")?){FUNCARG}? |
|
343 REFWORD {LABELID}|{REFWORD2} |
|
344 |
|
345 %option noyywrap |
|
346 %option yylineno |
|
347 |
|
348 %x St_Para |
|
349 %x St_Comment |
|
350 %x St_Title |
|
351 %x St_TitleN |
|
352 %x St_TitleQ |
|
353 %x St_TitleA |
|
354 %x St_TitleV |
|
355 %x St_Code |
|
356 %x St_XmlCode |
|
357 %x St_HtmlOnly |
|
358 %x St_ManOnly |
|
359 %x St_LatexOnly |
|
360 %x St_XmlOnly |
|
361 %x St_Verbatim |
|
362 %x St_Dot |
|
363 %x St_Msc |
|
364 %x St_Param |
|
365 %x St_XRefItem |
|
366 %x St_XRefItem2 |
|
367 %x St_File |
|
368 %x St_Pattern |
|
369 %x St_Link |
|
370 %x St_Ref |
|
371 %x St_Ref2 |
|
372 %x St_IntRef |
|
373 %x St_Text |
|
374 %x St_SkipTitle |
|
375 |
|
376 %x St_Sections |
|
377 %s St_SecLabel1 |
|
378 %s St_SecLabel2 |
|
379 %s St_SecTitle |
|
380 %x St_SecSkip |
|
381 |
|
382 %% |
|
383 <St_Para>\r /* skip carriage return */ |
|
384 <St_Para>^{LISTITEM} { /* list item */ |
|
385 QString text=yytext; |
|
386 int dashPos = text.findRev('-'); |
|
387 g_token->isEnumList = text.at(dashPos+1)=='#'; |
|
388 g_token->indent = computeIndent(yytext,dashPos); |
|
389 return TK_LISTITEM; |
|
390 } |
|
391 <St_Para>{BLANK}*\n{LISTITEM} { /* list item on next line */ |
|
392 QString text=yytext; |
|
393 text=text.right(text.length()-text.find('\n')-1); |
|
394 int dashPos = text.findRev('-'); |
|
395 g_token->isEnumList = text.at(dashPos+1)=='#'; |
|
396 g_token->indent = computeIndent(text,dashPos); |
|
397 return TK_LISTITEM; |
|
398 } |
|
399 <St_Para>^{ENDLIST} { /* end list */ |
|
400 int dotPos = QString(yytext).findRev('.'); |
|
401 g_token->indent = computeIndent(yytext,dotPos); |
|
402 return TK_ENDLIST; |
|
403 } |
|
404 <St_Para>{BLANK}*\n{ENDLIST} { /* end list on next line */ |
|
405 QString text=yytext; |
|
406 text=text.right(text.length()-text.find('\n')-1); |
|
407 int dotPos = text.findRev('.'); |
|
408 g_token->indent = computeIndent(text,dotPos); |
|
409 return TK_ENDLIST; |
|
410 } |
|
411 <St_Para>"{"{BLANK}*"@link" { |
|
412 g_token->name = "javalink"; |
|
413 return TK_COMMAND; |
|
414 } |
|
415 <St_Para>"{"{BLANK}*"@inheritDoc"{BLANK}*"}" { |
|
416 g_token->name = "inheritdoc"; |
|
417 return TK_COMMAND; |
|
418 } |
|
419 <St_Para>"\\_fakenl" { // artificial new line |
|
420 yylineno++; |
|
421 } |
|
422 <St_Para>{SPCMD3} { |
|
423 g_token->name = "form"; |
|
424 bool ok; |
|
425 g_token->id = QString(yytext).right(yyleng-6).toInt(&ok); |
|
426 ASSERT(ok); |
|
427 return TK_COMMAND; |
|
428 } |
|
429 <St_Para>{SPCMD1} | |
|
430 <St_Para>{SPCMD2} { /* special command */ |
|
431 g_token->name = yytext+1; |
|
432 g_token->name = g_token->name.stripWhiteSpace(); |
|
433 g_token->paramDir=TokenInfo::Unspecified; |
|
434 return TK_COMMAND; |
|
435 } |
|
436 <St_Para>{PARAMIO} { /* param [in,out] command */ |
|
437 g_token->name = "param"; |
|
438 QString s(yytext); |
|
439 bool isIn = s.find("in")!=-1; |
|
440 bool isOut = s.find("out")!=-1; |
|
441 if (isIn) |
|
442 { |
|
443 if (isOut) |
|
444 { |
|
445 g_token->paramDir=TokenInfo::InOut; |
|
446 } |
|
447 else |
|
448 { |
|
449 g_token->paramDir=TokenInfo::In; |
|
450 } |
|
451 } |
|
452 else if (isOut) |
|
453 { |
|
454 g_token->paramDir=TokenInfo::Out; |
|
455 } |
|
456 else |
|
457 { |
|
458 g_token->paramDir=TokenInfo::Unspecified; |
|
459 } |
|
460 return TK_COMMAND; |
|
461 } |
|
462 <St_Para>("http:"|"https:"|"ftp:"|"file:"|"news:"){URLMASK} { // URL |
|
463 g_token->name=yytext; |
|
464 g_token->isEMailAddr=FALSE; |
|
465 return TK_URL; |
|
466 } |
|
467 <St_Para>{MAILADR} { // Mail address |
|
468 g_token->name=yytext; |
|
469 g_token->isEMailAddr=TRUE; |
|
470 return TK_URL; |
|
471 } |
|
472 <St_Para>"$"{ID}":"[^\n$]+"$" { /* RCS tag */ |
|
473 QString tagName(yytext+1); |
|
474 int index=tagName.find(':'); |
|
475 g_token->name = tagName.left(index); |
|
476 g_token->text = tagName.mid(index+1,tagName.length()-index-2); |
|
477 return TK_RCSTAG; |
|
478 } |
|
479 <St_Para,St_HtmlOnly>"$("{ID}")" { /* environment variable */ |
|
480 QCString name = &yytext[2]; |
|
481 name = name.left(name.length()-1); |
|
482 QCString value = portable_getenv(name); |
|
483 for (int i=value.length()-1;i>=0;i--) unput(value.at(i)); |
|
484 } |
|
485 <St_Para>{HTMLTAG} { /* html tag */ |
|
486 handleHtmlTag(); |
|
487 return TK_HTMLTAG; |
|
488 } |
|
489 <St_Para,St_Text>"&"{ID}";" { /* special symbol */ |
|
490 g_token->name = yytext; |
|
491 return TK_SYMBOL; |
|
492 } |
|
493 |
|
494 /********* patterns for linkable words ******************/ |
|
495 |
|
496 <St_Para>{ID}/"<"{HTMLKEYW}">" { /* this rule is to prevent opening html |
|
497 * tag to be recognized as a templated classes |
|
498 */ |
|
499 g_token->name = yytext; |
|
500 return TK_LNKWORD; |
|
501 } |
|
502 <St_Para>{LNKWORD1}/"<br>" | // prevent <br> html tag to be parsed as template arguments |
|
503 <St_Para>{LNKWORD1} | |
|
504 <St_Para>{LNKWORD1}{FUNCARG} | |
|
505 <St_Para>{LNKWORD2} | |
|
506 <St_Para>{LNKWORD3} { |
|
507 g_token->name = yytext; |
|
508 return TK_LNKWORD; |
|
509 } |
|
510 <St_Para>{LNKWORD1}{FUNCARG}{CVSPEC}[^a-z_A-Z0-9] { |
|
511 g_token->name = yytext; |
|
512 g_token->name = g_token->name.left(g_token->name.length()-1); |
|
513 unput(yytext[yyleng-1]); |
|
514 return TK_LNKWORD; |
|
515 } |
|
516 /********* patterns for normal words ******************/ |
|
517 |
|
518 <St_Para,St_Text>{WORD1} | |
|
519 <St_Para,St_Text>{WORD2} { /* function call */ |
|
520 if (yytext[0]=='%') // strip % if present |
|
521 g_token->name = &yytext[1]; |
|
522 else |
|
523 g_token->name = yytext; |
|
524 return TK_WORD; |
|
525 |
|
526 /* the following is dummy code to please the |
|
527 * compiler, removing this results in a warning |
|
528 * on my machine |
|
529 */ |
|
530 goto find_rule; |
|
531 } |
|
532 <St_Para,St_Text>"operator"/{BLANK}*"<"[a-zA-Z_0-9]+">" { // Special case: word "operator" followed by a HTML command |
|
533 // avoid interpretation as "operator <" |
|
534 g_token->name = yytext; |
|
535 return TK_WORD; |
|
536 } |
|
537 |
|
538 /*******************************************************/ |
|
539 |
|
540 <St_Para,St_Text>{BLANK}+ | |
|
541 <St_Para,St_Text>{BLANK}*\n{BLANK}* { /* white space */ |
|
542 g_token->chars=yytext; |
|
543 return TK_WHITESPACE; |
|
544 } |
|
545 <St_Text>[\\@<>&$#%~] { |
|
546 g_token->name = yytext; |
|
547 return TK_COMMAND; |
|
548 } |
|
549 <St_Para>({BLANK}*\n)+{BLANK}*\n { |
|
550 if (g_insidePre) |
|
551 { |
|
552 /* Inside a <pre>..</pre> blank lines are treated |
|
553 * as whitespace. |
|
554 */ |
|
555 g_token->chars=yytext; |
|
556 return TK_WHITESPACE; |
|
557 } |
|
558 else |
|
559 { |
|
560 /* start of a new paragraph */ |
|
561 return TK_NEWPARA; |
|
562 } |
|
563 } |
|
564 <St_Code>{WS}*{CMD}"endcode" { |
|
565 return RetVal_OK; |
|
566 } |
|
567 <St_XmlCode>{WS}*"</code>" { |
|
568 return RetVal_OK; |
|
569 } |
|
570 <St_Code,St_XmlCode>[^\\@\n<]+ | |
|
571 <St_Code,St_XmlCode>\n | |
|
572 <St_Code,St_XmlCode>. { |
|
573 g_token->verb+=yytext; |
|
574 } |
|
575 <St_HtmlOnly>{CMD}"endhtmlonly" { |
|
576 return RetVal_OK; |
|
577 } |
|
578 <St_HtmlOnly>[^\\@\n$]+ | |
|
579 <St_HtmlOnly>\n | |
|
580 <St_HtmlOnly>. { |
|
581 g_token->verb+=yytext; |
|
582 } |
|
583 <St_ManOnly>{CMD}"endmanonly" { |
|
584 return RetVal_OK; |
|
585 } |
|
586 <St_ManOnly>[^\\@\n$]+ | |
|
587 <St_ManOnly>\n | |
|
588 <St_ManOnly>. { |
|
589 g_token->verb+=yytext; |
|
590 } |
|
591 <St_LatexOnly>{CMD}"endlatexonly" { |
|
592 return RetVal_OK; |
|
593 } |
|
594 <St_LatexOnly>[^\\@\n]+ | |
|
595 <St_LatexOnly>\n | |
|
596 <St_LatexOnly>. { |
|
597 g_token->verb+=yytext; |
|
598 } |
|
599 <St_XmlOnly>{CMD}"endxmlonly" { |
|
600 return RetVal_OK; |
|
601 } |
|
602 <St_XmlOnly>[^\\@\n]+ | |
|
603 <St_XmlOnly>\n | |
|
604 <St_XmlOnly>. { |
|
605 g_token->verb+=yytext; |
|
606 } |
|
607 <St_Verbatim>{CMD}"endverbatim" { |
|
608 g_token->verb=stripEmptyLines(g_token->verb); |
|
609 return RetVal_OK; |
|
610 } |
|
611 <St_Verbatim>[^\\@\n]+ | |
|
612 <St_Verbatim>\n | |
|
613 <St_Verbatim>. { /* Verbatim text */ |
|
614 g_token->verb+=yytext; |
|
615 } |
|
616 <St_Dot>{CMD}"enddot" { |
|
617 return RetVal_OK; |
|
618 } |
|
619 <St_Dot>[^\\@\n]+ | |
|
620 <St_Dot>\n | |
|
621 <St_Dot>. { /* dot text */ |
|
622 g_token->verb+=yytext; |
|
623 } |
|
624 <St_Msc>{CMD}"endmsc" { |
|
625 return RetVal_OK; |
|
626 } |
|
627 <St_Msc>[^\\@\n]+ | |
|
628 <St_Msc>\n | |
|
629 <St_Msc>. { /* msc text */ |
|
630 g_token->verb+=yytext; |
|
631 } |
|
632 <St_Title>"\"" { // quoted title |
|
633 BEGIN(St_TitleQ); |
|
634 } |
|
635 <St_Title>[ \t]+ { |
|
636 g_token->chars=yytext; |
|
637 return TK_WHITESPACE; |
|
638 } |
|
639 <St_Title>. { // non-quoted title |
|
640 unput(*yytext); |
|
641 BEGIN(St_TitleN); |
|
642 } |
|
643 <St_Title>\n { |
|
644 unput(*yytext); |
|
645 return 0; |
|
646 } |
|
647 <St_TitleN>"&"{ID}";" { /* symbol */ |
|
648 g_token->name = yytext; |
|
649 return TK_SYMBOL; |
|
650 } |
|
651 <St_TitleN>{HTMLTAG} { |
|
652 } |
|
653 <St_TitleN>{SPCMD1} | |
|
654 <St_TitleN>{SPCMD2} { /* special command */ |
|
655 g_token->name = yytext+1; |
|
656 g_token->paramDir=TokenInfo::Unspecified; |
|
657 return TK_COMMAND; |
|
658 } |
|
659 <St_TitleN>{WORD1} | |
|
660 <St_TitleN>{WORD2} { /* word */ |
|
661 if (yytext[0]=='%') // strip % if present |
|
662 g_token->name = &yytext[1]; |
|
663 else |
|
664 g_token->name = yytext; |
|
665 return TK_WORD; |
|
666 } |
|
667 <St_TitleN>[ \t]+ { |
|
668 g_token->chars=yytext; |
|
669 return TK_WHITESPACE; |
|
670 } |
|
671 <St_TitleN>\n { /* new line => end of title */ |
|
672 unput(*yytext); |
|
673 return 0; |
|
674 } |
|
675 <St_TitleQ>"&"{ID}";" { /* symbol */ |
|
676 g_token->name = yytext; |
|
677 return TK_SYMBOL; |
|
678 } |
|
679 <St_TitleQ>{SPCMD1} | |
|
680 <St_TitleQ>{SPCMD2} { /* special command */ |
|
681 g_token->name = yytext+1; |
|
682 g_token->paramDir=TokenInfo::Unspecified; |
|
683 return TK_COMMAND; |
|
684 } |
|
685 <St_TitleQ>{WORD1NQ} | |
|
686 <St_TitleQ>{WORD2NQ} { /* word */ |
|
687 g_token->name = yytext; |
|
688 return TK_WORD; |
|
689 } |
|
690 <St_TitleQ>[ \t]+ { |
|
691 g_token->chars=yytext; |
|
692 return TK_WHITESPACE; |
|
693 } |
|
694 <St_TitleQ>"\"" { /* closing quote => end of title */ |
|
695 BEGIN(St_TitleA); |
|
696 return 0; |
|
697 } |
|
698 <St_TitleQ>\n { /* new line => end of title */ |
|
699 unput(*yytext); |
|
700 return 0; |
|
701 } |
|
702 <St_TitleA>{BLANK}*{ID}{BLANK}*"="{BLANK}* { // title attribute |
|
703 g_token->name = yytext; |
|
704 g_token->name = g_token->name.left( |
|
705 g_token->name.find('=')).stripWhiteSpace(); |
|
706 BEGIN(St_TitleV); |
|
707 } |
|
708 <St_TitleV>[^ \t\r\n]+ { // attribute value |
|
709 g_token->chars = yytext; |
|
710 BEGIN(St_TitleN); |
|
711 return TK_WORD; |
|
712 } |
|
713 <St_TitleV,St_TitleA>. { |
|
714 unput(*yytext); |
|
715 return 0; |
|
716 } |
|
717 <St_TitleV,St_TitleA>\n { |
|
718 return 0; |
|
719 } |
|
720 |
|
721 <St_Ref>{REFWORD} { // label to refer to |
|
722 g_token->name=yytext; |
|
723 return TK_WORD; |
|
724 } |
|
725 <St_Ref>{BLANK} { // white space |
|
726 unput(' '); |
|
727 return 0; |
|
728 } |
|
729 <St_Ref>{WS}+"\""{WS}* { // white space following by quoted string |
|
730 BEGIN(St_Ref2); |
|
731 } |
|
732 <St_Ref>\n { // new line |
|
733 unput(*yytext); |
|
734 return 0; |
|
735 } |
|
736 <St_Ref>. { // any other character |
|
737 unput(*yytext); |
|
738 return 0; |
|
739 } |
|
740 <St_IntRef>[A-Z_a-z0-9.:/#\-\+\(\)]+ { |
|
741 g_token->name = yytext; |
|
742 return TK_WORD; |
|
743 } |
|
744 <St_IntRef>{BLANK}+"\"" { |
|
745 BEGIN(St_Ref2); |
|
746 } |
|
747 <St_Ref2>"&"{ID}";" { /* symbol */ |
|
748 g_token->name = yytext; |
|
749 return TK_SYMBOL; |
|
750 } |
|
751 <St_Ref2>{SPCMD1} | |
|
752 <St_Ref2>{SPCMD2} { /* special command */ |
|
753 g_token->name = yytext+1; |
|
754 g_token->paramDir=TokenInfo::Unspecified; |
|
755 return TK_COMMAND; |
|
756 } |
|
757 <St_Ref2>{WORD1NQ} | |
|
758 <St_Ref2>{WORD2NQ} { |
|
759 /* word */ |
|
760 g_token->name = yytext; |
|
761 return TK_WORD; |
|
762 } |
|
763 <St_Ref2>[ \t]+ { |
|
764 g_token->chars=yytext; |
|
765 return TK_WHITESPACE; |
|
766 } |
|
767 <St_Ref2>"\""|\n { /* " or \n => end of title */ |
|
768 return 0; |
|
769 } |
|
770 <St_XRefItem>{ID} { |
|
771 g_token->name=yytext; |
|
772 } |
|
773 <St_XRefItem>" " { |
|
774 BEGIN(St_XRefItem2); |
|
775 } |
|
776 <St_XRefItem2>[0-9]+"." { |
|
777 QString numStr=yytext; |
|
778 numStr=numStr.left(yyleng-1); |
|
779 g_token->id=numStr.toInt(); |
|
780 return RetVal_OK; |
|
781 } |
|
782 <St_Para,St_Title,St_Ref2>"<!--" { /* html style comment block */ |
|
783 g_commentState = YY_START; |
|
784 BEGIN(St_Comment); |
|
785 } |
|
786 <St_Param>"\""[^\n\"]+"\"" { |
|
787 g_token->name = yytext+1; |
|
788 g_token->name = g_token->name.left(yyleng-2); |
|
789 return TK_WORD; |
|
790 } |
|
791 <St_Param>[^ \t\n,]+ { |
|
792 g_token->name = yytext; |
|
793 return TK_WORD; |
|
794 } |
|
795 <St_Param>{WS}*","{WS}* /* param separator */ |
|
796 <St_Param>{WS} { |
|
797 g_token->chars=yytext; |
|
798 return TK_WHITESPACE; |
|
799 } |
|
800 <St_File>{FILEMASK} { |
|
801 g_token->name = yytext; |
|
802 return TK_WORD; |
|
803 } |
|
804 <St_File>"\""[^\n\"]+"\"" { |
|
805 QString text=yytext; |
|
806 g_token->name = text.mid(1,text.length()-2); |
|
807 return TK_WORD; |
|
808 } |
|
809 <St_Pattern>[^\r\n]+ { |
|
810 g_token->name = yytext; |
|
811 g_token->name = g_token->name.stripWhiteSpace(); |
|
812 return TK_WORD; |
|
813 } |
|
814 <St_Link>{LINKMASK}|{REFWORD} { |
|
815 g_token->name = yytext; |
|
816 return TK_WORD; |
|
817 } |
|
818 <St_Comment>"-->" { /* end of html comment */ |
|
819 BEGIN(g_commentState); |
|
820 } |
|
821 <St_Comment>[^-\n]+ /* inside html comment */ |
|
822 <St_Comment>. /* inside html comment */ |
|
823 |
|
824 /* State for skipping title (all chars until the end of the line) */ |
|
825 |
|
826 <St_SkipTitle>. |
|
827 <St_SkipTitle>\n { return 0; } |
|
828 |
|
829 /* State for the pass used to find the anchors and sections */ |
|
830 |
|
831 <St_Sections>[^\n@\\]+ |
|
832 <St_Sections>"@@"|"\\\\" |
|
833 <St_Sections>{CMD}"anchor"{BLANK}+ { |
|
834 g_secType = SectionInfo::Anchor; |
|
835 BEGIN(St_SecLabel1); |
|
836 } |
|
837 <St_Sections>{CMD}"section"{BLANK}+ { |
|
838 g_secType = SectionInfo::Section; |
|
839 BEGIN(St_SecLabel2); |
|
840 } |
|
841 <St_Sections>{CMD}"subsection"{BLANK}+ { |
|
842 g_secType = SectionInfo::Subsection; |
|
843 BEGIN(St_SecLabel2); |
|
844 } |
|
845 <St_Sections>{CMD}"subsubsection"{BLANK}+ { |
|
846 g_secType = SectionInfo::Subsubsection; |
|
847 BEGIN(St_SecLabel2); |
|
848 } |
|
849 <St_Sections>{CMD}"paragraph"{BLANK}+ { |
|
850 g_secType = SectionInfo::Paragraph; |
|
851 BEGIN(St_SecLabel2); |
|
852 } |
|
853 <St_Sections>{CMD}"verbatim"/[^a-z_A-Z0-9] { |
|
854 g_endMarker="endverbatim"; |
|
855 BEGIN(St_SecSkip); |
|
856 } |
|
857 <St_Sections>{CMD}"dot"/[^a-z_A-Z0-9] { |
|
858 g_endMarker="enddot"; |
|
859 BEGIN(St_SecSkip); |
|
860 } |
|
861 <St_Sections>{CMD}"msc"/[^a-z_A-Z0-9] { |
|
862 g_endMarker="endmsc"; |
|
863 BEGIN(St_SecSkip); |
|
864 } |
|
865 <St_Sections>{CMD}"htmlonly"/[^a-z_A-Z0-9] { |
|
866 g_endMarker="endhtmlonly"; |
|
867 BEGIN(St_SecSkip); |
|
868 } |
|
869 <St_Sections>{CMD}"latexonly"/[^a-z_A-Z0-9] { |
|
870 g_endMarker="endlatexonly"; |
|
871 BEGIN(St_SecSkip); |
|
872 } |
|
873 <St_Sections>{CMD}"xmlonly"/[^a-z_A-Z0-9] { |
|
874 g_endMarker="endxmlonly"; |
|
875 BEGIN(St_SecSkip); |
|
876 } |
|
877 <St_Sections>{CMD}"code"/[^a-z_A-Z0-9] { |
|
878 g_endMarker="endcode"; |
|
879 BEGIN(St_SecSkip); |
|
880 } |
|
881 <St_Sections>"<!--" { |
|
882 g_endMarker="-->"; |
|
883 BEGIN(St_SecSkip); |
|
884 } |
|
885 <St_SecSkip>{CMD}{ID} { |
|
886 if (strcmp(yytext+1,g_endMarker)==0) |
|
887 { |
|
888 BEGIN(St_Sections); |
|
889 } |
|
890 } |
|
891 <St_SecSkip>"-->" { |
|
892 if (strcmp(yytext,g_endMarker)==0) |
|
893 { |
|
894 BEGIN(St_Sections); |
|
895 } |
|
896 } |
|
897 <St_SecSkip>[^a-z_A-Z0-9\-\\\@]+ |
|
898 <St_SecSkip>. |
|
899 <St_SecSkip>\n |
|
900 <St_Sections>. |
|
901 <St_Sections>\n |
|
902 <St_SecLabel1>{LABELID} { |
|
903 g_secLabel = yytext; |
|
904 processSection(); |
|
905 BEGIN(St_Sections); |
|
906 } |
|
907 <St_SecLabel2>{LABELID}{BLANK}+ | |
|
908 <St_SecLabel2>{LABELID} { |
|
909 g_secLabel = yytext; |
|
910 g_secLabel = g_secLabel.stripWhiteSpace(); |
|
911 BEGIN(St_SecTitle); |
|
912 } |
|
913 <St_SecTitle>[^\n]+ | |
|
914 <St_SecTitle>[^\n]*\n { |
|
915 g_secTitle = yytext; |
|
916 g_secTitle = g_secTitle.stripWhiteSpace(); |
|
917 processSection(); |
|
918 BEGIN(St_Sections); |
|
919 } |
|
920 <St_SecTitle,St_SecLabel1,St_SecLabel2>. { |
|
921 warn(g_fileName,yylineno,"Error: Unexpected character `%s' while looking for section label or title",yytext); |
|
922 } |
|
923 |
|
924 /* Generic rules that work for all states */ |
|
925 <*>\n { |
|
926 warn(g_fileName,yylineno,"Error: Unexpected new line character"); |
|
927 } |
|
928 <*>[\\@<>&$#%~"] { /* unescaped special character */ |
|
929 //warn(g_fileName,yylineno,"Warning: Unexpected character `%s', assuming command \\%s was meant.",yytext,yytext); |
|
930 g_token->name = yytext; |
|
931 return TK_COMMAND; |
|
932 } |
|
933 <*>. { |
|
934 warn(g_fileName,yylineno,"Error: Unexpected character `%s'",yytext); |
|
935 } |
|
936 %% |
|
937 |
|
938 //-------------------------------------------------------------------------- |
|
939 |
|
940 void doctokenizerYYFindSections(const char *input,Definition *d, |
|
941 MemberGroup *mg,const char *fileName) |
|
942 { |
|
943 if (input==0) return; |
|
944 g_inputString = input; |
|
945 //printf("parsing --->`%s'<---\n",input); |
|
946 g_inputPos = 0; |
|
947 g_definition = d; |
|
948 g_memberGroup = mg; |
|
949 g_fileName = fileName; |
|
950 BEGIN(St_Sections); |
|
951 doctokenizerYYlineno = 1; |
|
952 doctokenizerYYlex(); |
|
953 } |
|
954 |
|
955 void doctokenizerYYinit(const char *input,const char *fileName) |
|
956 { |
|
957 g_inputString = input; |
|
958 g_inputPos = 0; |
|
959 g_fileName = fileName; |
|
960 g_insidePre = FALSE; |
|
961 BEGIN(St_Para); |
|
962 } |
|
963 |
|
964 void doctokenizerYYsetStatePara() |
|
965 { |
|
966 BEGIN(St_Para); |
|
967 } |
|
968 |
|
969 void doctokenizerYYsetStateTitle() |
|
970 { |
|
971 BEGIN(St_Title); |
|
972 } |
|
973 |
|
974 void doctokenizerYYsetStateTitleAttrValue() |
|
975 { |
|
976 BEGIN(St_TitleV); |
|
977 } |
|
978 |
|
979 void doctokenizerYYsetStateCode() |
|
980 { |
|
981 g_token->verb=""; |
|
982 BEGIN(St_Code); |
|
983 } |
|
984 |
|
985 void doctokenizerYYsetStateXmlCode() |
|
986 { |
|
987 g_token->verb=""; |
|
988 BEGIN(St_XmlCode); |
|
989 } |
|
990 |
|
991 void doctokenizerYYsetStateHtmlOnly() |
|
992 { |
|
993 g_token->verb=""; |
|
994 BEGIN(St_HtmlOnly); |
|
995 } |
|
996 |
|
997 void doctokenizerYYsetStateManOnly() |
|
998 { |
|
999 g_token->verb=""; |
|
1000 BEGIN(St_ManOnly); |
|
1001 } |
|
1002 |
|
1003 void doctokenizerYYsetStateXmlOnly() |
|
1004 { |
|
1005 g_token->verb=""; |
|
1006 BEGIN(St_XmlOnly); |
|
1007 } |
|
1008 |
|
1009 void doctokenizerYYsetStateLatexOnly() |
|
1010 { |
|
1011 g_token->verb=""; |
|
1012 BEGIN(St_LatexOnly); |
|
1013 } |
|
1014 |
|
1015 void doctokenizerYYsetStateVerbatim() |
|
1016 { |
|
1017 g_token->verb=""; |
|
1018 BEGIN(St_Verbatim); |
|
1019 } |
|
1020 |
|
1021 void doctokenizerYYsetStateDot() |
|
1022 { |
|
1023 g_token->verb=""; |
|
1024 BEGIN(St_Dot); |
|
1025 } |
|
1026 |
|
1027 void doctokenizerYYsetStateMsc() |
|
1028 { |
|
1029 g_token->verb=""; |
|
1030 BEGIN(St_Msc); |
|
1031 } |
|
1032 |
|
1033 void doctokenizerYYsetStateParam() |
|
1034 { |
|
1035 BEGIN(St_Param); |
|
1036 } |
|
1037 |
|
1038 void doctokenizerYYsetStateXRefItem() |
|
1039 { |
|
1040 BEGIN(St_XRefItem); |
|
1041 } |
|
1042 |
|
1043 void doctokenizerYYsetStateFile() |
|
1044 { |
|
1045 BEGIN(St_File); |
|
1046 } |
|
1047 |
|
1048 void doctokenizerYYsetStatePattern() |
|
1049 { |
|
1050 BEGIN(St_Pattern); |
|
1051 } |
|
1052 |
|
1053 void doctokenizerYYsetStateLink() |
|
1054 { |
|
1055 BEGIN(St_Link); |
|
1056 } |
|
1057 |
|
1058 void doctokenizerYYsetStateRef() |
|
1059 { |
|
1060 BEGIN(St_Ref); |
|
1061 } |
|
1062 |
|
1063 void doctokenizerYYsetStateInternalRef() |
|
1064 { |
|
1065 BEGIN(St_IntRef); |
|
1066 } |
|
1067 |
|
1068 void doctokenizerYYsetStateText() |
|
1069 { |
|
1070 BEGIN(St_Text); |
|
1071 } |
|
1072 |
|
1073 void doctokenizerYYsetStateSkipTitle() |
|
1074 { |
|
1075 BEGIN(St_SkipTitle); |
|
1076 } |
|
1077 |
|
1078 void doctokenizerYYcleanup() |
|
1079 { |
|
1080 yy_delete_buffer( YY_CURRENT_BUFFER ); |
|
1081 } |
|
1082 |
|
1083 void doctokenizerYYsetInsidePre(bool b) |
|
1084 { |
|
1085 g_insidePre = b; |
|
1086 } |
|
1087 |
|
1088 void doctokenizerYYpushBackHtmlTag(const char *tag) |
|
1089 { |
|
1090 QCString tagName = tag; |
|
1091 int i,l = tagName.length(); |
|
1092 unput('>'); |
|
1093 for (i=l-1;i>=0;i--) |
|
1094 { |
|
1095 unput(tag[i]); |
|
1096 } |
|
1097 unput('<'); |
|
1098 } |
|
1099 |
|
1100 #if !defined(YY_FLEX_SUBMINOR_VERSION) |
|
1101 extern "C" { // some bogus code to keep the compiler happy |
|
1102 void doctokenizerYYdummy() { yy_flex_realloc(0,0); } |
|
1103 } |
|
1104 #endif |
|
1105 |