1 /******************************************************************************
6 * Copyright (C) 1997-2012 by Dimitri van Heesch.
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.
14 * Documents produced by Doxygen are derivative works derived from the
15 * input used in their production; they are not affected by this license.
28 #include "doctokenizer.h"
29 #include "cmdmapper.h"
33 #include "membergroup.h"
34 #include "definition.h"
38 #define YY_NEVER_INTERACTIVE 1
41 //--------------------------------------------------------------------------
43 // context for tokenizer phase
44 static int g_commentState;
45 TokenInfo *g_token = 0;
46 static int g_inputPos = 0;
47 static const char *g_inputString;
48 static QCString g_fileName;
49 static bool g_insidePre;
51 // context for section finding phase
52 static Definition *g_definition;
53 static MemberGroup *g_memberGroup;
54 static QCString g_secLabel;
55 static QCString g_secTitle;
56 static SectionInfo::SectionType g_secType;
57 static QCString g_endMarker;
59 struct DocLexerContext
64 const char *inputString;
65 YY_BUFFER_STATE state;
68 static QStack<DocLexerContext> g_lexerStack;
70 //--------------------------------------------------------------------------
72 void doctokenizerYYpushContext()
74 DocLexerContext *ctx = new DocLexerContext;
77 ctx->inputPos = g_inputPos;
78 ctx->inputString = g_inputString;
79 ctx->state = YY_CURRENT_BUFFER;
80 g_lexerStack.push(ctx);
81 yy_switch_to_buffer(yy_create_buffer(doctokenizerYYin, YY_BUF_SIZE));
84 bool doctokenizerYYpopContext()
86 if (g_lexerStack.isEmpty()) return FALSE;
87 DocLexerContext *ctx = g_lexerStack.pop();
88 g_inputPos = ctx->inputPos;
89 g_inputString = ctx->inputString;
90 yy_delete_buffer(YY_CURRENT_BUFFER);
91 yy_switch_to_buffer(ctx->state);
98 //--------------------------------------------------------------------------
100 const char *tokToString(int token)
104 case 0: return "TK_EOF";
105 case TK_WORD: return "TK_WORD";
106 case TK_LNKWORD: return "TK_LNKWORD";
107 case TK_WHITESPACE: return "TK_WHITESPACE";
108 case TK_LISTITEM: return "TK_LISTITEM";
109 case TK_ENDLIST: return "TK_ENDLIST";
110 case TK_COMMAND: return "TK_COMMAND";
111 case TK_HTMLTAG: return "TK_HTMLTAG";
112 case TK_SYMBOL: return "TK_SYMBOL";
113 case TK_NEWPARA: return "TK_NEWPARA";
114 case TK_RCSTAG: return "TK_RCSTAG";
115 case TK_URL: return "TK_URL";
120 static int computeIndent(const char *str,int length)
124 static int tabSize=Config_getInt("TAB_SIZE");
125 for (i=0;i<length;i++)
129 indent+=tabSize - (indent%tabSize);
131 else if (str[i]=='\n')
143 //--------------------------------------------------------------------------
145 static void processSection()
147 //printf("%s: found section/anchor with name `%s'\n",g_fileName.data(),g_secLabel.data());
151 file = g_memberGroup->parent()->getOutputFileBase();
153 else if (g_definition)
155 file = g_definition->getOutputFileBase();
159 warn(g_fileName,yylineno,"Found section/anchor %s without context\n",g_secLabel.data());
162 if ((si=Doxygen::sectionDict.find(g_secLabel)))
165 //si = new SectionInfo(file,g_secLabel,g_secTitle,g_secType);
166 //Doxygen::sectionDict.insert(g_secLabel,si);
170 static void handleHtmlTag()
172 QCString tagText=yytext;
173 g_token->attribs.clear();
174 g_token->endTag = FALSE;
175 g_token->emptyTag = FALSE;
179 if (tagText.at(1)=='/')
181 g_token->endTag = TRUE;
185 // Parse the name portion
186 int i = startNamePos;
187 for (i=startNamePos; i < (int)yyleng; i++)
189 // Check for valid HTML/XML name chars (including namespaces)
190 char c = tagText.at(i);
191 if (!(isalnum(c) || c=='-' || c=='_' || c==':')) break;
193 g_token->name = tagText.mid(startNamePos,i-startNamePos);
195 // Parse the attributes. Each attribute is a name, value pair
196 // The result is stored in g_token->attribs.
197 int startName,endName,startAttrib,endAttrib;
198 while (i<(int)yyleng)
200 char c=tagText.at(i);
202 while (i<(int)yyleng && isspace(c)) { c=tagText.at(++i); }
203 // check for end of the tag
205 // Check for XML style "empty" tag.
208 g_token->emptyTag = TRUE;
212 // search for end of name
213 while (i<(int)yyleng && !isspace(c) && c!='=') { c=tagText.at(++i); }
216 opt.name = tagText.mid(startName,endName-startName).lower();
218 while (i<(int)yyleng && isspace(c)) { c=tagText.at(++i); }
219 if (tagText.at(i)=='=') // option has value
223 while (i<(int)yyleng && isspace(c)) { c=tagText.at(++i); }
224 if (tagText.at(i)=='\'') // option '...'
229 // search for matching quote
230 while (i<(int)yyleng && c!='\'') { c=tagText.at(++i); }
232 if (i<(int)yyleng) c=tagText.at(++i);
234 else if (tagText.at(i)=='"') // option "..."
238 // search for matching quote
239 while (i<(int)yyleng && c!='"') { c=tagText.at(++i); }
241 if (i<(int)yyleng) c=tagText.at(++i);
243 else // value without any quotes
246 // search for separator or end symbol
247 while (i<(int)yyleng && !isspace(c) && c!='>') { c=tagText.at(++i); }
249 if (i<(int)yyleng) c=tagText.at(++i);
251 opt.value = tagText.mid(startAttrib,endAttrib-startAttrib);
253 else // start next option
256 //printf("=====> Adding option name=<%s> value=<%s>\n",
257 // opt.name.data(),opt.value.data());
258 g_token->attribs.append(&opt);
262 static QCString stripEmptyLines(const QCString &s)
264 if (s.isEmpty()) return QCString();
267 // skip leading empty lines
271 while ((c=s[p]) && (c==' ' || c=='\t')) p++;
281 // skip trailing empty lines
283 if (p>=start && s.at(p)=='\n') p--;
287 while ((c=s[p]) && (c==' ' || c=='\t')) p--;
298 //printf("stripEmptyLines(%d-%d)\n",start,end);
299 return s.mid(start,end-start);
302 //--------------------------------------------------------------------------
305 #define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
307 static int yyread(char *buf,int max_size)
310 const char *src=g_inputString+g_inputPos;
311 while ( c < max_size && *src ) *buf++ = *src++, c++;
316 //--------------------------------------------------------------------------
324 ID "$"?[a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]*
325 LABELID [a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF\-]*
326 PHPTYPE [\\:a-z_A-Z0-9\x80-\xFF\-]+
327 CITEID [a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF\-:/]*
328 MAILADR ("mailto:")?[a-z_A-Z0-9.+-]+"@"[a-z_A-Z0-9-]+("."[a-z_A-Z0-9\-]+)+[a-z_A-Z0-9\-]+
329 OPTSTARS ("//"{BLANK}*)?"*"*{BLANK}*
330 LISTITEM {BLANK}*[-]("#")?{WS}
331 MLISTITEM {BLANK}*[+*]{WS}
332 OLISTITEM {BLANK}*[1-9][0-9]*"."{BLANK}
333 ENDLIST {BLANK}*"."{BLANK}*\n
334 ATTRIB {ID}{WS}*("="{WS}*(("\""[^\"]*"\"")|("'"[^\']*"'")|[^ \t\r\n'"><]+))?
335 URLCHAR [a-z_A-Z0-9\!\~\,\:\;\'\$\?\@\&\%\#\.\-\+\/\=]
336 URLMASK ({URLCHAR}+([({]{URLCHAR}*[)}])?)+
337 FILESCHAR [a-z_A-Z0-9\\:\\\/\-\+]
338 FILEECHAR [a-z_A-Z0-9\-\+]
339 HFILEMASK ("."{FILESCHAR}*{FILEECHAR}+)*
340 FILEMASK ({FILESCHAR}*{FILEECHAR}+("."{FILESCHAR}*{FILEECHAR}+)*)|{HFILEMASK}
341 LINKMASK [^ \t\n\r\\@<&${}]+("("[^\n)]*")")?({BLANK}*("const"|"volatile"){BLANK}+)?
342 VERBATIM "verbatim"{BLANK}*
343 SPCMD1 {CMD}([a-z_A-Z][a-z_A-Z0-9]*|{VERBATIM})
344 SPCMD2 {CMD}[\\@<>&$#%~".|]
345 SPCMD3 {CMD}form#[0-9]+
347 INOUT "in"|"out"|("in"{BLANK}*","{BLANK}*"out")|("out"{BLANK}*","{BLANK}*"in")
348 PARAMIO {CMD}param{BLANK}*"["{BLANK}*{INOUT}{BLANK}*"]"
349 TEMPCHAR [a-z_A-Z0-9,: \t\*\&]
350 FUNCCHAR [a-z_A-Z0-9,:\<\> \t\*\&\[\]]
351 SCOPESEP "::"|"#"|"."
352 TEMPLPART "<"{TEMPCHAR}*">"
353 SCOPEPRE {ID}{TEMPLPART}?{SCOPESEP}
354 SCOPEKEYS ":"({ID}":")*
355 SCOPECPP {SCOPEPRE}*(~)?{ID}("<"{TEMPCHAR}*">")?
356 SCOPEOBJC {SCOPEPRE}?{ID}{SCOPEKEYS}?
357 SCOPEMASK {SCOPECPP}|{SCOPEOBJC}
358 FUNCARG "("{FUNCCHAR}*")"({BLANK}*("volatile"|"const"){BLANK})?
359 OPNEW {BLANK}+"new"({BLANK}*"[]")?
360 OPDEL {BLANK}+"delete"({BLANK}*"[]")?
361 OPNORM {OPNEW}|{OPDEL}|"+"|"-"|"*"|"/"|"%"|"^"|"&"|"|"|"~"|"!"|"="|"<"|">"|"+="|"-="|"*="|"/="|"%="|"^="|"&="|"|="|"<<"|">>"|"<<="|">>="|"=="|"!="|"<="|">="|"&&"|"||"|"++"|"--"|","|"->*"|"->"|"[]"|"()"
362 OPCAST {BLANK}+[^<(\r\n.,][^(\r\n.,]*
363 OPMASK ({BLANK}*{OPNORM}{FUNCARG})
364 OPMASKOPT ({BLANK}*{OPNORM}{FUNCARG}?)|({OPCAST}{FUNCARG})
365 LNKWORD1 ("::"|"#")?{SCOPEMASK}
366 CVSPEC {BLANK}*("const"|"volatile")
367 LNKWORD2 (({SCOPEPRE}*"operator"{OPMASK})|({SCOPEPRE}"operator"{OPMASKOPT})|(("::"|"#"){SCOPEPRE}*"operator"{OPMASKOPT})){CVSPEC}?
368 LNKWORD3 ([0-9a-z_A-Z\-]+("/"|"\\"))*[0-9a-z_A-Z\-]+("."[0-9a-z_A-Z]+)+
369 CHARWORDQ [^ \t\n\r\\@<>()\[\]:;\?{}&%$#,."=']
370 ESCWORD ("%"{ID}(("::"|"."){ID})*)|("%'")
371 WORD1 {ESCWORD}|{CHARWORDQ}+|"{"|"}"|"'\"'"|("\""[^"\n]*\n?[^"\n]*"\"")
372 WORD2 "."|","|"("|")"|"["|"]"|":"|";"|"\?"|"="|"'"
373 WORD1NQ {ESCWORD}|{CHARWORDQ}+|"{"|"}"
374 WORD2NQ "."|","|"("|")"|"["|"]"|":"|";"|"\?"|"="|"'"
375 HTMLTAG "<"(("/")?){ID}({WS}+{ATTRIB})*{WS}*(("/")?)">"
376 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"
377 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"
378 HTMLKEYW {HTMLKEYL}|{HTMLKEYU}
379 REFWORD2 ("#"|"::")?({ID}{TEMPLPART}?("."|"#"|"::"|"-"|"/"))*({ID}(":")?){FUNCARG}?
380 REFWORD3 ({ID}":")*{ID}":"?
381 REFWORD {LABELID}|{REFWORD2}|{REFWORD3}
426 <St_Para>\r /* skip carriage return */
427 <St_Para>^{LISTITEM} { /* list item */
428 QCString text=yytext;
429 int dashPos = text.findRev('-');
430 g_token->isEnumList = text.at(dashPos+1)=='#';
432 g_token->indent = computeIndent(yytext,dashPos);
435 <St_Para>^{MLISTITEM} { /* list item */
436 if (!Doxygen::markdownSupport || g_insidePre)
442 QCString text=yytext;
443 static QRegExp re("[*+]");
444 int listPos = text.findRev(re);
445 g_token->isEnumList = FALSE;
447 g_token->indent = computeIndent(yytext,listPos);
451 <St_Para>^{OLISTITEM} { /* numbered list item */
452 if (!Doxygen::markdownSupport || g_insidePre)
458 QCString text=yytext;
459 static QRegExp re("[1-9]");
460 int digitPos = text.find(re);
461 int dotPos = text.find('.',digitPos);
462 g_token->isEnumList = TRUE;
463 g_token->id = atoi(QCString(yytext).mid(digitPos,dotPos-digitPos));
464 g_token->indent = computeIndent(yytext,digitPos);
468 <St_Para>{BLANK}*\n{LISTITEM} { /* list item on next line */
469 QCString text=yytext;
470 text=text.right(text.length()-text.find('\n')-1);
471 int dashPos = text.findRev('-');
472 g_token->isEnumList = text.at(dashPos+1)=='#';
474 g_token->indent = computeIndent(text,dashPos);
477 <St_Para>{BLANK}*\n{MLISTITEM} { /* list item on next line */
478 if (!Doxygen::markdownSupport || g_insidePre)
484 QCString text=yytext;
485 static QRegExp re("[*+]");
486 text=text.right(text.length()-text.find('\n')-1);
487 int markPos = text.findRev(re);
488 g_token->isEnumList = FALSE;
490 g_token->indent = computeIndent(text,markPos);
494 <St_Para>{BLANK}*\n{OLISTITEM} { /* list item on next line */
495 if (!Doxygen::markdownSupport || g_insidePre)
501 QCString text=yytext;
502 int nl=text.findRev('\n');
503 int len=text.length();
504 text=text.right(len-nl-1);
505 static QRegExp re("[1-9]");
506 int digitPos = text.find(re);
507 int dotPos = text.find('.',digitPos);
508 g_token->isEnumList = TRUE;
509 g_token->id = atoi(QCString(text).mid(digitPos,dotPos-digitPos));
510 g_token->indent = computeIndent(text,digitPos);
514 <St_Para>^{ENDLIST} { /* end list */
515 int dotPos = QCString(yytext).findRev('.');
516 g_token->indent = computeIndent(yytext,dotPos);
519 <St_Para>{BLANK}*\n{ENDLIST} { /* end list on next line */
520 QCString text=yytext;
521 text=text.right(text.length()-text.find('\n')-1);
522 int dotPos = text.findRev('.');
523 g_token->indent = computeIndent(text,dotPos);
526 <St_Para>"{"{BLANK}*"@link" {
527 g_token->name = "javalink";
530 <St_Para>"{"{BLANK}*"@inheritDoc"{BLANK}*"}" {
531 g_token->name = "inheritdoc";
534 <St_Para>"@_fakenl" { // artificial new line
538 g_token->name = "form";
540 g_token->id = QCString(yytext).right((int)yyleng-6).toInt(&ok);
546 <St_Para>{SPCMD4} { /* special command */
547 g_token->name = yytext+1;
548 g_token->name = g_token->name.stripWhiteSpace();
549 g_token->paramDir=TokenInfo::Unspecified;
552 <St_Para>{PARAMIO} { /* param [in,out] command */
553 g_token->name = "param";
555 bool isIn = s.find("in")!=-1;
556 bool isOut = s.find("out")!=-1;
561 g_token->paramDir=TokenInfo::InOut;
565 g_token->paramDir=TokenInfo::In;
570 g_token->paramDir=TokenInfo::Out;
574 g_token->paramDir=TokenInfo::Unspecified;
578 <St_Para>("http:"|"https:"|"ftp:"|"file:"|"news:"){URLMASK}/\. { // URL.
579 g_token->name=yytext;
580 g_token->isEMailAddr=FALSE;
583 <St_Para>("http:"|"https:"|"ftp:"|"file:"|"news:"){URLMASK} { // URL
584 g_token->name=yytext;
585 g_token->isEMailAddr=FALSE;
588 <St_Para>"<"("http:"|"https:"|"ftp:"|"file:"|"news:"){URLMASK}">" { // URL
589 g_token->name=yytext;
590 g_token->name = g_token->name.mid(1,g_token->name.length()-2);
591 g_token->isEMailAddr=FALSE;
594 <St_Para>{MAILADR} { // Mail address
595 g_token->name=yytext;
596 g_token->name.stripPrefix("mailto:");
597 g_token->isEMailAddr=TRUE;
600 <St_Para>"<"{MAILADR}">" { // Mail address
601 g_token->name=yytext;
602 g_token->name = g_token->name.mid(1,g_token->name.length()-2);
603 g_token->name.stripPrefix("mailto:");
604 g_token->isEMailAddr=TRUE;
607 <St_Para>"$"{ID}":"[^\n$]+"$" { /* RCS tag */
608 QCString tagName(yytext+1);
609 int index=tagName.find(':');
610 g_token->name = tagName.left(index+1);
611 g_token->text = tagName.mid(index+2,tagName.length()-index-3);
614 <St_Para,St_HtmlOnly>"$("{ID}")" { /* environment variable */
615 QCString name = &yytext[2];
616 name = name.left(name.length()-1);
617 QCString value = portable_getenv(name);
618 for (int i=value.length()-1;i>=0;i--) unput(value.at(i));
620 <St_Para>{HTMLTAG} { /* html tag */
624 <St_Para,St_Text>"&"{ID}";" { /* special symbol */
625 g_token->name = yytext;
629 /********* patterns for linkable words ******************/
631 <St_Para>{ID}/"<"{HTMLKEYW}">" { /* this rule is to prevent opening html
632 * tag to be recognized as a templated classes
634 g_token->name = yytext;
637 <St_Para>{LNKWORD1}/"<br>" | // prevent <br> html tag to be parsed as template arguments
638 <St_Para>{LNKWORD1} |
639 <St_Para>{LNKWORD1}{FUNCARG} |
640 <St_Para>{LNKWORD2} |
641 <St_Para>{LNKWORD3} {
642 g_token->name = yytext;
645 <St_Para>{LNKWORD1}{FUNCARG}{CVSPEC}[^a-z_A-Z0-9] {
646 g_token->name = yytext;
647 g_token->name = g_token->name.left(g_token->name.length()-1);
648 unput(yytext[(int)yyleng-1]);
651 /********* patterns for normal words ******************/
653 <St_Para,St_Text>{WORD1} |
654 <St_Para,St_Text>{WORD2} { /* function call */
655 if (yytext[0]=='%') // strip % if present
656 g_token->name = &yytext[1];
658 g_token->name = yytext;
661 /* the following is dummy code to please the
662 * compiler, removing this results in a warning
667 <St_Text>({ID}".")+{ID} {
668 g_token->name = yytext;
671 <St_Para,St_Text>"operator"/{BLANK}*"<"[a-zA-Z_0-9]+">" { // Special case: word "operator" followed by a HTML command
672 // avoid interpretation as "operator <"
673 g_token->name = yytext;
677 /*******************************************************/
679 <St_Para,St_Text>{BLANK}+ |
680 <St_Para,St_Text>{BLANK}*\n{BLANK}* { /* white space */
681 g_token->chars=yytext;
682 return TK_WHITESPACE;
684 <St_Text>[\\@<>&$#%~] {
685 g_token->name = yytext;
688 <St_Para>({BLANK}*\n)+{BLANK}*\n{BLANK}* {
689 // g_insidePre was always FALSE, so the next section
690 // was never executed, now g_insidePre is set properly
691 // again, so the section is commented out to keep the
695 // /* Inside a <pre>..</pre> blank lines are treated
698 // g_token->chars=yytext;
699 // return TK_WHITESPACE;
701 //else // found end of a paragraph
703 g_token->indent=computeIndent(yytext,(int)yyleng);
705 // put back the indentation (needed for list items)
706 for (i=0;i<g_token->indent;i++)
710 // tell flex that after putting the last indent
711 // back we are at the beginning of the line
712 YY_CURRENT_BUFFER->yy_at_bol=1;
713 // start of a new paragraph
717 <St_CodeOpt>{BLANK}*"{"(".")?{LABELID}"}" {
718 g_token->name = yytext;
719 int i=g_token->name.find('{');
720 g_token->name = g_token->name.mid(i+1,g_token->name.length()-i-2);
728 <St_Code>{WS}*{CMD}"endcode" {
731 <St_XmlCode>{WS}*"</code>" {
734 <St_Code,St_XmlCode>[^\\@\n<]+ |
735 <St_Code,St_XmlCode>\n |
736 <St_Code,St_XmlCode>. {
737 g_token->verb+=yytext;
739 <St_HtmlOnly>{CMD}"endhtmlonly" {
742 <St_HtmlOnly>[^\\@\n$]+ |
745 g_token->verb+=yytext;
747 <St_ManOnly>{CMD}"endmanonly" {
750 <St_ManOnly>[^\\@\n$]+ |
753 g_token->verb+=yytext;
755 <St_RtfOnly>{CMD}"endrtfonly" {
758 <St_RtfOnly>[^\\@\n$]+ |
761 g_token->verb+=yytext;
763 <St_LatexOnly>{CMD}"endlatexonly" {
766 <St_LatexOnly>[^\\@\n]+ |
769 g_token->verb+=yytext;
771 <St_XmlOnly>{CMD}"endxmlonly" {
774 <St_XmlOnly>[^\\@\n]+ |
777 g_token->verb+=yytext;
779 <St_Verbatim>{CMD}"endverbatim" {
780 g_token->verb=stripEmptyLines(g_token->verb);
783 <St_Verbatim>[^\\@\n]+ |
785 <St_Verbatim>. { /* Verbatim text */
786 g_token->verb+=yytext;
788 <St_Dot>{CMD}"enddot" {
793 <St_Dot>. { /* dot text */
794 g_token->verb+=yytext;
796 <St_Msc>{CMD}"endmsc" {
801 <St_Msc>. { /* msc text */
802 g_token->verb+=yytext;
804 <St_Title>"\"" { // quoted title
808 g_token->chars=yytext;
809 return TK_WHITESPACE;
811 <St_Title>. { // non-quoted title
819 <St_TitleN>"&"{ID}";" { /* symbol */
820 g_token->name = yytext;
823 <St_TitleN>{HTMLTAG} {
825 <St_TitleN>{SPCMD1} |
826 <St_TitleN>{SPCMD2} { /* special command */
827 g_token->name = yytext+1;
828 g_token->paramDir=TokenInfo::Unspecified;
832 <St_TitleN>{WORD2} { /* word */
833 if (yytext[0]=='%') // strip % if present
834 g_token->name = &yytext[1];
836 g_token->name = yytext;
840 g_token->chars=yytext;
841 return TK_WHITESPACE;
843 <St_TitleN>\n { /* new line => end of title */
847 <St_TitleQ>"&"{ID}";" { /* symbol */
848 g_token->name = yytext;
851 <St_TitleQ>{SPCMD1} |
852 <St_TitleQ>{SPCMD2} { /* special command */
853 g_token->name = yytext+1;
854 g_token->paramDir=TokenInfo::Unspecified;
857 <St_TitleQ>{WORD1NQ} |
858 <St_TitleQ>{WORD2NQ} { /* word */
859 g_token->name = yytext;
863 g_token->chars=yytext;
864 return TK_WHITESPACE;
866 <St_TitleQ>"\"" { /* closing quote => end of title */
870 <St_TitleQ>\n { /* new line => end of title */
874 <St_TitleA>{BLANK}*{ID}{BLANK}*"="{BLANK}* { // title attribute
875 g_token->name = yytext;
876 g_token->name = g_token->name.left(
877 g_token->name.find('=')).stripWhiteSpace();
880 <St_TitleV>[^ \t\r\n]+ { // attribute value
881 g_token->chars = yytext;
885 <St_TitleV,St_TitleA>. {
889 <St_TitleV,St_TitleA>\n {
893 <St_Anchor>{LABELID}{WS}? { // anchor
894 g_token->name = QCString(yytext).stripWhiteSpace();
901 <St_Cite>{CITEID} { // label to cite
902 g_token->name=yytext;
905 <St_Cite>{BLANK} { // white space
909 <St_Cite>\n { // new line
913 <St_Cite>. { // any other character
917 <St_Ref>{REFWORD} { // label to refer to
918 g_token->name=yytext;
921 <St_Ref>{BLANK} { // white space
925 <St_Ref>{WS}+"\""{WS}* { // white space following by quoted string
928 <St_Ref>\n { // new line
932 <St_Ref>. { // any other character
936 <St_IntRef>[A-Z_a-z0-9.:/#\-\+\(\)]+ {
937 g_token->name = yytext;
940 <St_IntRef>{BLANK}+"\"" {
943 <St_Ref2>"&"{ID}";" { /* symbol */
944 g_token->name = yytext;
948 <St_Ref2>{SPCMD2} { /* special command */
949 g_token->name = yytext+1;
950 g_token->paramDir=TokenInfo::Unspecified;
956 g_token->name = yytext;
960 g_token->chars=yytext;
961 return TK_WHITESPACE;
963 <St_Ref2>"\""|\n { /* " or \n => end of title */
966 <St_XRefItem>{LABELID} {
967 g_token->name=yytext;
972 <St_XRefItem2>[0-9]+"." {
973 QCString numStr=yytext;
974 numStr=numStr.left((int)yyleng-1);
975 g_token->id=numStr.toInt();
978 <St_Para,St_Title,St_Ref2>"<!--" { /* html style comment block */
979 g_commentState = YY_START;
982 <St_Param>"\""[^\n\"]+"\"" {
983 g_token->name = yytext+1;
984 g_token->name = g_token->name.left((int)yyleng-2);
987 <St_Param>({PHPTYPE}{BLANK}*"|"{BLANK}*)*{PHPTYPE}{WS}+("&")?"$"{LABELID} {
988 QCString params = yytext;
989 int j = params.find('&');
990 int i = params.find('$');
991 if (j<i && j!=-1) i=j;
992 QCString types = params.left(i).stripWhiteSpace();
993 g_token->name = types+"#"+params.mid(i);
996 <St_Param>[^ \t\n,]+ {
997 g_token->name = yytext;
1000 <St_Param>{WS}*","{WS}* /* param separator */
1002 g_token->chars=yytext;
1003 return TK_WHITESPACE;
1005 <St_File>{FILEMASK} {
1006 g_token->name = yytext;
1009 <St_File>"\""[^\n\"]+"\"" {
1010 QCString text=yytext;
1011 g_token->name = text.mid(1,text.length()-2);
1014 <St_Pattern>[^\r\n]+ {
1015 g_token->name = yytext;
1016 g_token->name = g_token->name.stripWhiteSpace();
1019 <St_Link>{LINKMASK}|{REFWORD} {
1020 g_token->name = yytext;
1023 <St_Comment>"-->" { /* end of html comment */
1024 BEGIN(g_commentState);
1026 <St_Comment>[^-\n]+ /* inside html comment */
1027 <St_Comment>. /* inside html comment */
1029 /* State for skipping title (all chars until the end of the line) */
1032 <St_SkipTitle>\n { return 0; }
1034 /* State for the pass used to find the anchors and sections */
1036 <St_Sections>[^\n@\\]+
1037 <St_Sections>"@@"|"\\\\"
1038 <St_Sections>{CMD}"anchor"{BLANK}+ {
1039 g_secType = SectionInfo::Anchor;
1040 BEGIN(St_SecLabel1);
1042 <St_Sections>{CMD}"section"{BLANK}+ {
1043 g_secType = SectionInfo::Section;
1044 BEGIN(St_SecLabel2);
1046 <St_Sections>{CMD}"subsection"{BLANK}+ {
1047 g_secType = SectionInfo::Subsection;
1048 BEGIN(St_SecLabel2);
1050 <St_Sections>{CMD}"subsubsection"{BLANK}+ {
1051 g_secType = SectionInfo::Subsubsection;
1052 BEGIN(St_SecLabel2);
1054 <St_Sections>{CMD}"paragraph"{BLANK}+ {
1055 g_secType = SectionInfo::Paragraph;
1056 BEGIN(St_SecLabel2);
1058 <St_Sections>{CMD}"verbatim"/[^a-z_A-Z0-9] {
1059 g_endMarker="endverbatim";
1062 <St_Sections>{CMD}"dot"/[^a-z_A-Z0-9] {
1063 g_endMarker="enddot";
1066 <St_Sections>{CMD}"msc"/[^a-z_A-Z0-9] {
1067 g_endMarker="endmsc";
1070 <St_Sections>{CMD}"htmlonly"/[^a-z_A-Z0-9] {
1071 g_endMarker="endhtmlonly";
1074 <St_Sections>{CMD}"latexonly"/[^a-z_A-Z0-9] {
1075 g_endMarker="endlatexonly";
1078 <St_Sections>{CMD}"xmlonly"/[^a-z_A-Z0-9] {
1079 g_endMarker="endxmlonly";
1082 <St_Sections>{CMD}"code"/[^a-z_A-Z0-9] {
1083 g_endMarker="endcode";
1086 <St_Sections>"<!--" {
1090 <St_SecSkip>{CMD}{ID} {
1091 if (strcmp(yytext+1,g_endMarker)==0)
1097 if (strcmp(yytext,g_endMarker)==0)
1102 <St_SecSkip>[^a-z_A-Z0-9\-\\\@]+
1107 <St_SecLabel1>{LABELID} {
1108 g_secLabel = yytext;
1112 <St_SecLabel2>{LABELID}{BLANK}+ |
1113 <St_SecLabel2>{LABELID} {
1114 g_secLabel = yytext;
1115 g_secLabel = g_secLabel.stripWhiteSpace();
1118 <St_SecTitle>[^\n]+ |
1119 <St_SecTitle>[^\n]*\n {
1120 g_secTitle = yytext;
1121 g_secTitle = g_secTitle.stripWhiteSpace();
1125 <St_SecTitle,St_SecLabel1,St_SecLabel2>. {
1126 warn(g_fileName,yylineno,"warning: Unexpected character `%s' while looking for section label or title",yytext);
1129 <St_Snippet>[^\n]+ |
1130 <St_Snippet>[^\n]*\n {
1131 g_token->name = yytext;
1132 g_token->name = g_token->name.stripWhiteSpace();
1136 /* Generic rules that work for all states */
1138 warn(g_fileName,yylineno,"warning: Unexpected new line character");
1140 <*>[\\@<>&$#%~"=] { /* unescaped special character */
1141 //warn(g_fileName,yylineno,"warning: Unexpected character `%s', assuming command \\%s was meant.",yytext,yytext);
1142 g_token->name = yytext;
1146 warn(g_fileName,yylineno,"warning: Unexpected character `%s'",yytext);
1150 //--------------------------------------------------------------------------
1152 void doctokenizerYYFindSections(const char *input,Definition *d,
1153 MemberGroup *mg,const char *fileName)
1155 if (input==0) return;
1156 g_inputString = input;
1157 //printf("parsing --->`%s'<---\n",input);
1161 g_fileName = fileName;
1163 doctokenizerYYlineno = 1;
1164 doctokenizerYYlex();
1167 void doctokenizerYYinit(const char *input,const char *fileName)
1169 g_inputString = input;
1171 g_fileName = fileName;
1172 g_insidePre = FALSE;
1176 void doctokenizerYYsetStatePara()
1181 void doctokenizerYYsetStateTitle()
1186 void doctokenizerYYsetStateTitleAttrValue()
1191 void doctokenizerYYsetStateCode()
1198 void doctokenizerYYsetStateXmlCode()
1205 void doctokenizerYYsetStateHtmlOnly()
1211 void doctokenizerYYsetStateManOnly()
1217 void doctokenizerYYsetStateRtfOnly()
1223 void doctokenizerYYsetStateXmlOnly()
1229 void doctokenizerYYsetStateLatexOnly()
1232 BEGIN(St_LatexOnly);
1235 void doctokenizerYYsetStateVerbatim()
1241 void doctokenizerYYsetStateDot()
1247 void doctokenizerYYsetStateMsc()
1253 void doctokenizerYYsetStateParam()
1258 void doctokenizerYYsetStateXRefItem()
1263 void doctokenizerYYsetStateFile()
1268 void doctokenizerYYsetStatePattern()
1273 void doctokenizerYYsetStateLink()
1278 void doctokenizerYYsetStateCite()
1283 void doctokenizerYYsetStateRef()
1288 void doctokenizerYYsetStateInternalRef()
1293 void doctokenizerYYsetStateText()
1298 void doctokenizerYYsetStateSkipTitle()
1300 BEGIN(St_SkipTitle);
1303 void doctokenizerYYsetStateAnchor()
1308 void doctokenizerYYsetStateSnippet()
1313 void doctokenizerYYcleanup()
1315 yy_delete_buffer( YY_CURRENT_BUFFER );
1318 void doctokenizerYYsetInsidePre(bool b)
1323 void doctokenizerYYpushBackHtmlTag(const char *tag)
1325 QCString tagName = tag;
1326 int i,l = tagName.length();
1328 for (i=l-1;i>=0;i--)
1335 #if !defined(YY_FLEX_SUBMINOR_VERSION)
1336 extern "C" { // some bogus code to keep the compiler happy
1337 void doctokenizerYYdummy() { yy_flex_realloc(0,0); }