1 /******************************************************************************
6 * Copyright (C) 1997-2014 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.
30 #include "doctokenizer.h"
31 #include "cmdmapper.h"
35 #include "membergroup.h"
36 #include "definition.h"
40 #define YY_NEVER_INTERACTIVE 1
43 //--------------------------------------------------------------------------
45 // context for tokenizer phase
46 static int g_commentState;
47 TokenInfo *g_token = 0;
48 static int g_inputPos = 0;
49 static const char *g_inputString;
50 static QCString g_fileName;
51 static bool g_insidePre;
53 // context for section finding phase
54 static Definition *g_definition;
55 static MemberGroup *g_memberGroup;
56 static QCString g_secLabel;
57 static QCString g_secTitle;
58 static SectionInfo::SectionType g_secType;
59 static QCString g_endMarker;
60 static int g_autoListLevel;
62 struct DocLexerContext
68 const char *inputString;
69 YY_BUFFER_STATE state;
72 static QStack<DocLexerContext> g_lexerStack;
74 //--------------------------------------------------------------------------
76 void doctokenizerYYpushContext()
78 DocLexerContext *ctx = new DocLexerContext;
80 ctx->autoListLevel = g_autoListLevel;
82 ctx->inputPos = g_inputPos;
83 ctx->inputString = g_inputString;
84 ctx->state = YY_CURRENT_BUFFER;
85 g_lexerStack.push(ctx);
86 yy_switch_to_buffer(yy_create_buffer(doctokenizerYYin, YY_BUF_SIZE));
89 bool doctokenizerYYpopContext()
91 if (g_lexerStack.isEmpty()) return FALSE;
92 DocLexerContext *ctx = g_lexerStack.pop();
93 g_autoListLevel = ctx->autoListLevel;
94 g_inputPos = ctx->inputPos;
95 g_inputString = ctx->inputString;
96 yy_delete_buffer(YY_CURRENT_BUFFER);
97 yy_switch_to_buffer(ctx->state);
104 //--------------------------------------------------------------------------
106 const char *tokToString(int token)
110 case 0: return "TK_EOF";
111 case TK_WORD: return "TK_WORD";
112 case TK_LNKWORD: return "TK_LNKWORD";
113 case TK_WHITESPACE: return "TK_WHITESPACE";
114 case TK_LISTITEM: return "TK_LISTITEM";
115 case TK_ENDLIST: return "TK_ENDLIST";
116 case TK_COMMAND: return "TK_COMMAND";
117 case TK_HTMLTAG: return "TK_HTMLTAG";
118 case TK_SYMBOL: return "TK_SYMBOL";
119 case TK_NEWPARA: return "TK_NEWPARA";
120 case TK_RCSTAG: return "TK_RCSTAG";
121 case TK_URL: return "TK_URL";
126 static int computeIndent(const char *str,int length)
130 static int tabSize=Config_getInt("TAB_SIZE");
131 for (i=0;i<length;i++)
135 indent+=tabSize - (indent%tabSize);
137 else if (str[i]=='\n')
149 //--------------------------------------------------------------------------
151 static void processSection()
153 //printf("%s: found section/anchor with name `%s'\n",g_fileName.data(),g_secLabel.data());
157 file = g_memberGroup->parent()->getOutputFileBase();
159 else if (g_definition)
161 file = g_definition->getOutputFileBase();
165 warn(g_fileName,yylineno,"Found section/anchor %s without context\n",g_secLabel.data());
168 if ((si=Doxygen::sectionDict->find(g_secLabel)))
171 //si = new SectionInfo(file,g_secLabel,g_secTitle,g_secType);
172 //Doxygen::sectionDict.insert(g_secLabel,si);
176 static void handleHtmlTag()
178 QCString tagText=yytext;
179 g_token->attribs.clear();
180 g_token->endTag = FALSE;
181 g_token->emptyTag = FALSE;
185 if (tagText.at(1)=='/')
187 g_token->endTag = TRUE;
191 // Parse the name portion
192 int i = startNamePos;
193 for (i=startNamePos; i < (int)yyleng; i++)
195 // Check for valid HTML/XML name chars (including namespaces)
196 char c = tagText.at(i);
197 if (!(isalnum(c) || c=='-' || c=='_' || c==':')) break;
199 g_token->name = tagText.mid(startNamePos,i-startNamePos);
201 // Parse the attributes. Each attribute is a name, value pair
202 // The result is stored in g_token->attribs.
203 int startName,endName,startAttrib,endAttrib;
204 while (i<(int)yyleng)
206 char c=tagText.at(i);
208 while (i<(int)yyleng && isspace(c)) { c=tagText.at(++i); }
209 // check for end of the tag
211 // Check for XML style "empty" tag.
214 g_token->emptyTag = TRUE;
218 // search for end of name
219 while (i<(int)yyleng && !isspace(c) && c!='=') { c=tagText.at(++i); }
222 opt.name = tagText.mid(startName,endName-startName).lower();
224 while (i<(int)yyleng && isspace(c)) { c=tagText.at(++i); }
225 if (tagText.at(i)=='=') // option has value
229 while (i<(int)yyleng && isspace(c)) { c=tagText.at(++i); }
230 if (tagText.at(i)=='\'') // option '...'
235 // search for matching quote
236 while (i<(int)yyleng && c!='\'') { c=tagText.at(++i); }
238 if (i<(int)yyleng) c=tagText.at(++i);
240 else if (tagText.at(i)=='"') // option "..."
244 // search for matching quote
245 while (i<(int)yyleng && c!='"') { c=tagText.at(++i); }
247 if (i<(int)yyleng) c=tagText.at(++i);
249 else // value without any quotes
252 // search for separator or end symbol
253 while (i<(int)yyleng && !isspace(c) && c!='>') { c=tagText.at(++i); }
255 if (i<(int)yyleng) c=tagText.at(++i);
257 opt.value = tagText.mid(startAttrib,endAttrib-startAttrib);
259 else // start next option
262 //printf("=====> Adding option name=<%s> value=<%s>\n",
263 // opt.name.data(),opt.value.data());
264 g_token->attribs.append(&opt);
268 static QCString stripEmptyLines(const QCString &s)
270 if (s.isEmpty()) return QCString();
273 // skip leading empty lines
277 while ((c=s[p]) && (c==' ' || c=='\t')) p++;
287 // skip trailing empty lines
289 if (p>=start && s.at(p)=='\n') p--;
293 while ((c=s[p]) && (c==' ' || c=='\t')) p--;
304 //printf("stripEmptyLines(%d-%d)\n",start,end);
305 return s.mid(start,end-start);
308 //--------------------------------------------------------------------------
311 #define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
313 static int yyread(char *buf,int max_size)
316 const char *src=g_inputString+g_inputPos;
317 while ( c < max_size && *src ) *buf++ = *src++, c++;
322 //--------------------------------------------------------------------------
323 #define REAL_YY_DECL int doctokenizerYYlex (void)
324 #define YY_DECL static int local_doctokinizer(void)
325 #define LOCAL_YY_DECL local_doctokinizer()
333 ID "$"?[a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]*
334 LABELID [a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF\-]*
335 PHPTYPE [\\:a-z_A-Z0-9\x80-\xFF\-]+
336 CITEID [a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF\-:/]*
337 MAILADR ("mailto:")?[a-z_A-Z0-9.+-]+"@"[a-z_A-Z0-9-]+("."[a-z_A-Z0-9\-]+)+[a-z_A-Z0-9\-]+
338 OPTSTARS ("//"{BLANK}*)?"*"*{BLANK}*
339 LISTITEM {BLANK}*[-]("#")?{WS}
340 MLISTITEM {BLANK}*[+*]{WS}
341 OLISTITEM {BLANK}*[1-9][0-9]*"."{BLANK}
342 ENDLIST {BLANK}*"."{BLANK}*\n
343 ATTRNAME [a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF\-]*
344 ATTRIB {ATTRNAME}{WS}*("="{WS}*(("\""[^\"]*"\"")|("'"[^\']*"'")|[^ \t\r\n'"><]+))?
345 URLCHAR [a-z_A-Z0-9\!\~\,\:\;\'\$\?\@\&\%\#\.\-\+\/\=]
346 URLMASK ({URLCHAR}+([({]{URLCHAR}*[)}])?)+
347 FILESCHAR [a-z_A-Z0-9\\:\\\/\-\+@&#]
348 FILEECHAR [a-z_A-Z0-9\-\+@&#]
349 HFILEMASK ("."{FILESCHAR}*{FILEECHAR}+)*
350 FILEMASK ({FILESCHAR}*{FILEECHAR}+("."{FILESCHAR}*{FILEECHAR}+)*)|{HFILEMASK}
351 LINKMASK [^ \t\n\r\\@<&${}]+("("[^\n)]*")")?({BLANK}*("const"|"volatile"){BLANK}+)?
352 VERBATIM "verbatim"{BLANK}*
353 SPCMD1 {CMD}([a-z_A-Z][a-z_A-Z0-9]*|{VERBATIM}|"--"|"---")
354 SPCMD2 {CMD}[\\@<>&$#%~".|]
355 SPCMD3 {CMD}form#[0-9]+
357 INOUT "inout"|"in"|"out"|("in"{BLANK}*","{BLANK}*"out")|("out"{BLANK}*","{BLANK}*"in")
358 PARAMIO {CMD}param{BLANK}*"["{BLANK}*{INOUT}{BLANK}*"]"
359 TEMPCHAR [a-z_A-Z0-9.,: \t\*\&\(\)\[\]]
360 FUNCCHAR [a-z_A-Z0-9,:\<\> \t\^\*\&\[\]]
361 FUNCPART {FUNCCHAR}*("("{FUNCCHAR}*")"{FUNCCHAR}*)?
362 SCOPESEP "::"|"#"|"."
363 TEMPLPART "<"{TEMPCHAR}*">"
364 ANONNS "anonymous_namespace{"[^}]*"}"
365 SCOPEPRE (({ID}{TEMPLPART}?)|{ANONNS}){SCOPESEP}
366 SCOPEKEYS ":"({ID}":")*
367 SCOPECPP {SCOPEPRE}*(~)?{ID}{TEMPLPART}?
368 SCOPEOBJC {SCOPEPRE}?{ID}{SCOPEKEYS}?
369 SCOPEMASK {SCOPECPP}|{SCOPEOBJC}
370 FUNCARG "("{FUNCPART}")"({BLANK}*("volatile"|"const"){BLANK})?
371 OPNEW {BLANK}+"new"({BLANK}*"[]")?
372 OPDEL {BLANK}+"delete"({BLANK}*"[]")?
373 OPNORM {OPNEW}|{OPDEL}|"+"|"-"|"*"|"/"|"%"|"^"|"&"|"|"|"~"|"!"|"="|"<"|">"|"+="|"-="|"*="|"/="|"%="|"^="|"&="|"|="|"<<"|">>"|"<<="|">>="|"=="|"!="|"<="|">="|"&&"|"||"|"++"|"--"|","|"->*"|"->"|"[]"|"()"
374 OPCAST {BLANK}+[^<(\r\n.,][^(\r\n.,]*
375 OPMASK ({BLANK}*{OPNORM}{FUNCARG})
376 OPMASKOPT ({BLANK}*{OPNORM}{FUNCARG}?)|({OPCAST}{FUNCARG})
377 LNKWORD1 ("::"|"#")?{SCOPEMASK}
378 CVSPEC {BLANK}*("const"|"volatile")
379 LNKWORD2 (({SCOPEPRE}*"operator"{OPMASK})|({SCOPEPRE}"operator"{OPMASKOPT})|(("::"|"#"){SCOPEPRE}*"operator"{OPMASKOPT})){CVSPEC}?
380 LNKWORD3 ([0-9a-z_A-Z\-]+("/"|"\\"))*[0-9a-z_A-Z\-]+("."[0-9a-z_A-Z]+)+
381 CHARWORDQ [^ \t\n\r\\@<>()\[\]:;\?{}&%$#,."=']
382 ESCWORD ("%"{ID}(("::"|"."){ID})*)|("%'")
383 WORD1 {ESCWORD}|{CHARWORDQ}+|"{"|"}"|"'\"'"|("\""[^"\n]*\n?[^"\n]*"\"")
384 WORD2 "."|","|"("|")"|"["|"]"|":"|";"|"\?"|"="|"'"
385 WORD1NQ {ESCWORD}|{CHARWORDQ}+|"{"|"}"
386 WORD2NQ "."|","|"("|")"|"["|"]"|":"|";"|"\?"|"="|"'"
387 HTMLTAG "<"(("/")?){ID}({WS}+{ATTRIB})*{WS}*(("/")?)">"
388 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"
389 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"
390 HTMLKEYW {HTMLKEYL}|{HTMLKEYU}
391 REFWORD2 ("#"|"::")?((({ID}{TEMPLPART}?)|{ANONNS})("."|"#"|"::"|"-"|"/"))*({ID}{TEMPLPART}?(":")?){FUNCARG}?
392 REFWORD3 ({ID}":")*{ID}":"?
393 REFWORD {LABELID}|{REFWORD2}|{REFWORD3}|{LNKWORD2}
440 <St_Para>\r /* skip carriage return */
441 <St_Para>^{LISTITEM} { /* list item */
442 QCString text=yytext;
443 int dashPos = text.findRev('-');
444 g_token->isEnumList = text.at(dashPos+1)=='#';
446 g_token->indent = computeIndent(yytext,dashPos);
449 <St_Para>^{MLISTITEM} { /* list item */
450 if (!Doxygen::markdownSupport || g_insidePre)
456 QCString text=yytext;
457 static QRegExp re("[*+]");
458 int listPos = text.findRev(re);
459 g_token->isEnumList = FALSE;
461 g_token->indent = computeIndent(yytext,listPos);
465 <St_Para>^{OLISTITEM} { /* numbered list item */
466 if (!Doxygen::markdownSupport || g_insidePre)
472 QCString text=yytext;
473 static QRegExp re("[1-9]");
474 int digitPos = text.find(re);
475 int dotPos = text.find('.',digitPos);
476 g_token->isEnumList = TRUE;
477 g_token->id = atoi(QCString(yytext).mid(digitPos,dotPos-digitPos));
478 g_token->indent = computeIndent(yytext,digitPos);
482 <St_Para>{BLANK}*\n{LISTITEM} { /* list item on next line */
483 QCString text=yytext;
484 text=text.right(text.length()-text.find('\n')-1);
485 int dashPos = text.findRev('-');
486 g_token->isEnumList = text.at(dashPos+1)=='#';
488 g_token->indent = computeIndent(text,dashPos);
491 <St_Para>{BLANK}*\n{MLISTITEM} { /* list item on next line */
492 if (!Doxygen::markdownSupport || g_insidePre)
498 QCString text=yytext;
499 static QRegExp re("[*+]");
500 text=text.right(text.length()-text.find('\n')-1);
501 int markPos = text.findRev(re);
502 g_token->isEnumList = FALSE;
504 g_token->indent = computeIndent(text,markPos);
508 <St_Para>{BLANK}*\n{OLISTITEM} { /* list item on next line */
509 if (!Doxygen::markdownSupport || g_insidePre)
515 QCString text=yytext;
516 int nl=text.findRev('\n');
517 int len=text.length();
518 text=text.right(len-nl-1);
519 static QRegExp re("[1-9]");
520 int digitPos = text.find(re);
521 int dotPos = text.find('.',digitPos);
522 g_token->isEnumList = TRUE;
523 g_token->id = atoi(QCString(text).mid(digitPos,dotPos-digitPos));
524 g_token->indent = computeIndent(text,digitPos);
528 <St_Para>^{ENDLIST} { /* end list */
529 int dotPos = QCString(yytext).findRev('.');
530 g_token->indent = computeIndent(yytext,dotPos);
533 <St_Para>{BLANK}*\n{ENDLIST} { /* end list on next line */
534 QCString text=yytext;
535 text=text.right(text.length()-text.find('\n')-1);
536 int dotPos = text.findRev('.');
537 g_token->indent = computeIndent(text,dotPos);
540 <St_Para>"{"{BLANK}*"@link" {
541 g_token->name = "javalink";
544 <St_Para>"{"{BLANK}*"@inheritDoc"{BLANK}*"}" {
545 g_token->name = "inheritdoc";
548 <St_Para>"@_fakenl" { // artificial new line
552 g_token->name = "form";
554 g_token->id = QCString(yytext).right((int)yyleng-6).toInt(&ok);
558 <St_Para>{CMD}"n"\n { /* \n followed by real newline */
560 g_token->name = yytext+1;
561 g_token->name = g_token->name.stripWhiteSpace();
562 g_token->paramDir=TokenInfo::Unspecified;
567 <St_Para>{SPCMD4} { /* special command */
568 g_token->name = yytext+1;
569 g_token->name = g_token->name.stripWhiteSpace();
570 g_token->paramDir=TokenInfo::Unspecified;
573 <St_Para>{PARAMIO} { /* param [in,out] command */
574 g_token->name = "param";
576 bool isIn = s.find("in")!=-1;
577 bool isOut = s.find("out")!=-1;
582 g_token->paramDir=TokenInfo::InOut;
586 g_token->paramDir=TokenInfo::In;
591 g_token->paramDir=TokenInfo::Out;
595 g_token->paramDir=TokenInfo::Unspecified;
599 <St_Para>("http:"|"https:"|"ftp:"|"file:"|"news:"){URLMASK}/\. { // URL.
600 g_token->name=yytext;
601 g_token->isEMailAddr=FALSE;
604 <St_Para>("http:"|"https:"|"ftp:"|"file:"|"news:"){URLMASK} { // URL
605 g_token->name=yytext;
606 g_token->isEMailAddr=FALSE;
609 <St_Para>"<"("http:"|"https:"|"ftp:"|"file:"|"news:"){URLMASK}">" { // URL
610 g_token->name=yytext;
611 g_token->name = g_token->name.mid(1,g_token->name.length()-2);
612 g_token->isEMailAddr=FALSE;
615 <St_Para>{MAILADR} { // Mail address
616 g_token->name=yytext;
617 g_token->name.stripPrefix("mailto:");
618 g_token->isEMailAddr=TRUE;
621 <St_Para>"<"{MAILADR}">" { // Mail address
622 g_token->name=yytext;
623 g_token->name = g_token->name.mid(1,g_token->name.length()-2);
624 g_token->name.stripPrefix("mailto:");
625 g_token->isEMailAddr=TRUE;
628 <St_Para>"$"{ID}":"[^\n$]+"$" { /* RCS tag */
629 QCString tagName(yytext+1);
630 int index=tagName.find(':');
631 g_token->name = tagName.left(index);
632 int text_begin = index+2;
633 int text_end = tagName.length()-1;
634 if (tagName[text_begin-1]==':') /* check for Subversion fixed-length keyword */
637 if (tagName[text_end-1]=='#')
640 g_token->text = tagName.mid(text_begin,text_end-text_begin);
643 <St_Para,St_HtmlOnly>"$("{ID}")" { /* environment variable */
644 QCString name = &yytext[2];
645 name = name.left(name.length()-1);
646 QCString value = portable_getenv(name);
647 for (int i=value.length()-1;i>=0;i--) unput(value.at(i));
649 <St_Para>{HTMLTAG} { /* html tag */
653 <St_Para,St_Text>"&"{ID}";" { /* special symbol */
654 g_token->name = yytext;
658 /********* patterns for linkable words ******************/
660 <St_Para>{ID}/"<"{HTMLKEYW}">" { /* this rule is to prevent opening html
661 * tag to be recognized as a templated classes
663 g_token->name = yytext;
666 <St_Para>{LNKWORD1}/"<br>" | // prevent <br> html tag to be parsed as template arguments
667 <St_Para>{LNKWORD1} |
668 <St_Para>{LNKWORD1}{FUNCARG} |
669 <St_Para>{LNKWORD2} |
670 <St_Para>{LNKWORD3} {
671 g_token->name = yytext;
674 <St_Para>{LNKWORD1}{FUNCARG}{CVSPEC}[^a-z_A-Z0-9] {
675 g_token->name = yytext;
676 g_token->name = g_token->name.left(g_token->name.length()-1);
677 unput(yytext[(int)yyleng-1]);
680 /********* patterns for normal words ******************/
682 <St_Para,St_Text>{WORD1} |
683 <St_Para,St_Text>{WORD2} { /* function call */
684 if (yytext[0]=='%') // strip % if present
685 g_token->name = &yytext[1];
687 g_token->name = yytext;
690 /* the following is dummy code to please the
691 * compiler, removing this results in a warning
696 <St_Text>({ID}".")+{ID} {
697 g_token->name = yytext;
700 <St_Para,St_Text>"operator"/{BLANK}*"<"[a-zA-Z_0-9]+">" { // Special case: word "operator" followed by a HTML command
701 // avoid interpretation as "operator <"
702 g_token->name = yytext;
706 /*******************************************************/
708 <St_Para,St_Text>{BLANK}+ |
709 <St_Para,St_Text>{BLANK}*\n{BLANK}* { /* white space */
710 g_token->chars=yytext;
711 return TK_WHITESPACE;
713 <St_Text>[\\@<>&$#%~] {
714 g_token->name = yytext;
717 <St_Para>({BLANK}*\n)+{BLANK}*\n/{LISTITEM} { /* skip trailing paragraph followed by new list item */
718 if (g_insidePre || g_autoListLevel==0)
723 <St_Para>({BLANK}*\n)+{BLANK}*\n/{MLISTITEM} { /* skip trailing paragraph followed by new list item */
724 if (!Doxygen::markdownSupport || g_insidePre || g_autoListLevel==0)
729 <St_Para>({BLANK}*\n)+{BLANK}*\n/{OLISTITEM} { /* skip trailing paragraph followed by new list item */
730 if (!Doxygen::markdownSupport || g_insidePre || g_autoListLevel==0)
735 <St_Para>({BLANK}*\n)+{BLANK}*\n{BLANK}* {
736 g_token->indent=computeIndent(yytext,(int)yyleng);
738 // put back the indentation (needed for list items)
739 for (i=0;i<g_token->indent;i++)
743 // tell flex that after putting the last indent
744 // back we are at the beginning of the line
745 YY_CURRENT_BUFFER->yy_at_bol=1;
746 // start of a new paragraph
749 <St_CodeOpt>{BLANK}*"{"(".")?{LABELID}"}" {
750 g_token->name = yytext;
751 int i=g_token->name.find('{'); /* } to keep vi happy */
752 g_token->name = g_token->name.mid(i+1,g_token->name.length()-i-2);
760 <St_Code>{WS}*{CMD}"endcode" {
763 <St_XmlCode>{WS}*"</code>" {
766 <St_Code,St_XmlCode>[^\\@\n<]+ |
767 <St_Code,St_XmlCode>\n |
768 <St_Code,St_XmlCode>. {
769 g_token->verb+=yytext;
771 <St_HtmlOnlyOption>" [block]" { // the space is added in commentscan.l
772 g_token->name="block";
775 <St_HtmlOnlyOption>.|\n {
779 <St_HtmlOnly>{CMD}"endhtmlonly" {
782 <St_HtmlOnly>[^\\@\n$]+ |
785 g_token->verb+=yytext;
787 <St_ManOnly>{CMD}"endmanonly" {
790 <St_ManOnly>[^\\@\n$]+ |
793 g_token->verb+=yytext;
795 <St_RtfOnly>{CMD}"endrtfonly" {
798 <St_RtfOnly>[^\\@\n$]+ |
801 g_token->verb+=yytext;
803 <St_LatexOnly>{CMD}"endlatexonly" {
806 <St_LatexOnly>[^\\@\n]+ |
809 g_token->verb+=yytext;
811 <St_XmlOnly>{CMD}"endxmlonly" {
814 <St_XmlOnly>[^\\@\n]+ |
817 g_token->verb+=yytext;
819 <St_DbOnly>{CMD}"enddocbookonly" {
822 <St_DbOnly>[^\\@\n]+ |
825 g_token->verb+=yytext;
827 <St_Verbatim>{CMD}"endverbatim" {
828 g_token->verb=stripEmptyLines(g_token->verb);
831 <St_Verbatim>[^\\@\n]+ |
833 <St_Verbatim>. { /* Verbatim text */
834 g_token->verb+=yytext;
836 <St_Dot>{CMD}"enddot" {
841 <St_Dot>. { /* dot text */
842 g_token->verb+=yytext;
844 <St_Msc>{CMD}("endmsc"|"endvhdlflow") {
849 <St_Msc>. { /* msc text */
850 g_token->verb+=yytext;
852 <St_Title>"\"" { // quoted title
856 g_token->chars=yytext;
857 return TK_WHITESPACE;
859 <St_Title>. { // non-quoted title
867 <St_TitleN>"&"{ID}";" { /* symbol */
868 g_token->name = yytext;
871 <St_TitleN>{HTMLTAG} {
873 <St_TitleN>{SPCMD1} |
874 <St_TitleN>{SPCMD2} { /* special command */
875 g_token->name = yytext+1;
876 g_token->paramDir=TokenInfo::Unspecified;
880 <St_TitleN>{WORD2} { /* word */
881 if (yytext[0]=='%') // strip % if present
882 g_token->name = &yytext[1];
884 g_token->name = yytext;
888 g_token->chars=yytext;
889 return TK_WHITESPACE;
891 <St_TitleN>\n { /* new line => end of title */
895 <St_TitleQ>"&"{ID}";" { /* symbol */
896 g_token->name = yytext;
899 <St_TitleQ>{SPCMD1} |
900 <St_TitleQ>{SPCMD2} { /* special command */
901 g_token->name = yytext+1;
902 g_token->paramDir=TokenInfo::Unspecified;
905 <St_TitleQ>{WORD1NQ} |
906 <St_TitleQ>{WORD2NQ} { /* word */
907 g_token->name = yytext;
911 g_token->chars=yytext;
912 return TK_WHITESPACE;
914 <St_TitleQ>"\"" { /* closing quote => end of title */
918 <St_TitleQ>\n { /* new line => end of title */
922 <St_TitleA>{BLANK}*{ID}{BLANK}*"="{BLANK}* { // title attribute
923 g_token->name = yytext;
924 g_token->name = g_token->name.left(
925 g_token->name.find('=')).stripWhiteSpace();
928 <St_TitleV>[^ \t\r\n]+ { // attribute value
929 g_token->chars = yytext;
933 <St_TitleV,St_TitleA>. {
937 <St_TitleV,St_TitleA>\n {
941 <St_Anchor>{LABELID}{WS}? { // anchor
942 g_token->name = QCString(yytext).stripWhiteSpace();
949 <St_Cite>{CITEID} { // label to cite
950 g_token->name=yytext;
953 <St_Cite>{BLANK} { // white space
957 <St_Cite>\n { // new line
961 <St_Cite>. { // any other character
965 <St_Ref>{REFWORD} { // label to refer to
966 g_token->name=yytext;
969 <St_Ref>{BLANK} { // white space
973 <St_Ref>{WS}+"\""{WS}* { // white space following by quoted string
976 <St_Ref>\n { // new line
980 <St_Ref>. { // any other character
984 <St_IntRef>[A-Z_a-z0-9.:/#\-\+\(\)]+ {
985 g_token->name = yytext;
988 <St_IntRef>{BLANK}+"\"" {
991 <St_Ref2>"&"{ID}";" { /* symbol */
992 g_token->name = yytext;
996 <St_Ref2>{SPCMD2} { /* special command */
997 g_token->name = yytext+1;
998 g_token->paramDir=TokenInfo::Unspecified;
1001 <St_Ref2>{WORD1NQ} |
1002 <St_Ref2>{WORD2NQ} {
1004 g_token->name = yytext;
1008 g_token->chars=yytext;
1009 return TK_WHITESPACE;
1011 <St_Ref2>"\""|\n { /* " or \n => end of title */
1014 <St_XRefItem>{LABELID} {
1015 g_token->name=yytext;
1018 BEGIN(St_XRefItem2);
1020 <St_XRefItem2>[0-9]+"." {
1021 QCString numStr=yytext;
1022 numStr=numStr.left((int)yyleng-1);
1023 g_token->id=numStr.toInt();
1026 <St_Para,St_Title,St_Ref2>"<!--" { /* html style comment block */
1027 g_commentState = YY_START;
1030 <St_Param>"\""[^\n\"]+"\"" {
1031 g_token->name = yytext+1;
1032 g_token->name = g_token->name.left((int)yyleng-2);
1035 <St_Param>({PHPTYPE}{BLANK}*"|"{BLANK}*)*{PHPTYPE}{WS}+("&")?"$"{LABELID} {
1036 QCString params = yytext;
1037 int j = params.find('&');
1038 int i = params.find('$');
1039 if (j<i && j!=-1) i=j;
1040 QCString types = params.left(i).stripWhiteSpace();
1041 g_token->name = types+"#"+params.mid(i);
1044 <St_Param>[^ \t\n,@\\]+ {
1045 g_token->name = yytext;
1046 if (g_token->name.at(yyleng-1)==':')
1048 g_token->name=g_token->name.left(yyleng-1);
1052 <St_Param>{WS}*","{WS}* /* param separator */
1054 g_token->chars=yytext;
1055 return TK_WHITESPACE;
1057 <St_File>{FILEMASK} {
1058 g_token->name = yytext;
1061 <St_File>"\""[^\n\"]+"\"" {
1062 QCString text=yytext;
1063 g_token->name = text.mid(1,text.length()-2);
1066 <St_Pattern>[^\r\n]+ {
1067 g_token->name = yytext;
1068 g_token->name = g_token->name.stripWhiteSpace();
1071 <St_Link>{LINKMASK}|{REFWORD} {
1072 g_token->name = yytext;
1075 <St_Comment>"-->" { /* end of html comment */
1076 BEGIN(g_commentState);
1078 <St_Comment>[^-\n]+ /* inside html comment */
1079 <St_Comment>. /* inside html comment */
1081 /* State for skipping title (all chars until the end of the line) */
1084 <St_SkipTitle>\n { return 0; }
1086 /* State for the pass used to find the anchors and sections */
1088 <St_Sections>[^\n@\\]+
1089 <St_Sections>"@@"|"\\\\"
1090 <St_Sections>{CMD}"anchor"{BLANK}+ {
1091 g_secType = SectionInfo::Anchor;
1092 BEGIN(St_SecLabel1);
1094 <St_Sections>{CMD}"section"{BLANK}+ {
1095 g_secType = SectionInfo::Section;
1096 BEGIN(St_SecLabel2);
1098 <St_Sections>{CMD}"subsection"{BLANK}+ {
1099 g_secType = SectionInfo::Subsection;
1100 BEGIN(St_SecLabel2);
1102 <St_Sections>{CMD}"subsubsection"{BLANK}+ {
1103 g_secType = SectionInfo::Subsubsection;
1104 BEGIN(St_SecLabel2);
1106 <St_Sections>{CMD}"paragraph"{BLANK}+ {
1107 g_secType = SectionInfo::Paragraph;
1108 BEGIN(St_SecLabel2);
1110 <St_Sections>{CMD}"verbatim"/[^a-z_A-Z0-9] {
1111 g_endMarker="endverbatim";
1114 <St_Sections>{CMD}"dot"/[^a-z_A-Z0-9] {
1115 g_endMarker="enddot";
1118 <St_Sections>{CMD}"msc"/[^a-z_A-Z0-9] {
1119 g_endMarker="endmsc";
1122 <St_Sections>{CMD}"htmlonly"/[^a-z_A-Z0-9] {
1123 g_endMarker="endhtmlonly";
1126 <St_Sections>{CMD}"latexonly"/[^a-z_A-Z0-9] {
1127 g_endMarker="endlatexonly";
1130 <St_Sections>{CMD}"xmlonly"/[^a-z_A-Z0-9] {
1131 g_endMarker="endxmlonly";
1134 <St_Sections>{CMD}"docbookonly"/[^a-z_A-Z0-9] {
1135 g_endMarker="enddocbookonly";
1138 <St_Sections>{CMD}"code"/[^a-z_A-Z0-9] {
1139 g_endMarker="endcode";
1142 <St_Sections>"<!--" {
1146 <St_SecSkip>{CMD}{ID} {
1147 if (qstrcmp(yytext+1,g_endMarker)==0)
1153 if (qstrcmp(yytext,g_endMarker)==0)
1158 <St_SecSkip>[^a-z_A-Z0-9\-\\\@]+
1163 <St_SecLabel1>{LABELID} {
1164 g_secLabel = yytext;
1168 <St_SecLabel2>{LABELID}{BLANK}+ |
1169 <St_SecLabel2>{LABELID} {
1170 g_secLabel = yytext;
1171 g_secLabel = g_secLabel.stripWhiteSpace();
1174 <St_SecTitle>[^\n]+ |
1175 <St_SecTitle>[^\n]*\n {
1176 g_secTitle = yytext;
1177 g_secTitle = g_secTitle.stripWhiteSpace();
1181 <St_SecTitle,St_SecLabel1,St_SecLabel2>. {
1182 warn(g_fileName,yylineno,"Unexpected character `%s' while looking for section label or title",yytext);
1185 <St_Snippet>[^\n]+ |
1186 <St_Snippet>[^\n]*\n {
1187 g_token->name = yytext;
1188 g_token->name = g_token->name.stripWhiteSpace();
1192 /* Generic rules that work for all states */
1194 warn(g_fileName,yylineno,"Unexpected new line character");
1196 <*>[\\@<>&$#%~"=] { /* unescaped special character */
1197 //warn(g_fileName,yylineno,"Unexpected character `%s', assuming command \\%s was meant.",yytext,yytext);
1198 g_token->name = yytext;
1202 warn(g_fileName,yylineno,"Unexpected character `%s'",yytext);
1206 //--------------------------------------------------------------------------
1208 void doctokenizerYYFindSections(const char *input,Definition *d,
1209 MemberGroup *mg,const char *fileName)
1211 if (input==0) return;
1212 printlex(yy_flex_debug, TRUE, __FILE__, fileName);
1213 g_inputString = input;
1214 //printf("parsing --->`%s'<---\n",input);
1218 g_fileName = fileName;
1220 doctokenizerYYlineno = 1;
1221 doctokenizerYYlex();
1222 printlex(yy_flex_debug, FALSE, __FILE__, fileName);
1225 void doctokenizerYYinit(const char *input,const char *fileName)
1227 g_autoListLevel = 0;
1228 g_inputString = input;
1230 g_fileName = fileName;
1231 g_insidePre = FALSE;
1235 void doctokenizerYYsetStatePara()
1240 void doctokenizerYYsetStateTitle()
1245 void doctokenizerYYsetStateTitleAttrValue()
1250 void doctokenizerYYsetStateCode()
1257 void doctokenizerYYsetStateXmlCode()
1264 void doctokenizerYYsetStateHtmlOnly()
1268 BEGIN(St_HtmlOnlyOption);
1271 void doctokenizerYYsetStateManOnly()
1277 void doctokenizerYYsetStateRtfOnly()
1283 void doctokenizerYYsetStateXmlOnly()
1289 void doctokenizerYYsetStateDbOnly()
1295 void doctokenizerYYsetStateLatexOnly()
1298 BEGIN(St_LatexOnly);
1301 void doctokenizerYYsetStateVerbatim()
1307 void doctokenizerYYsetStateDot()
1313 void doctokenizerYYsetStateMsc()
1319 void doctokenizerYYsetStateParam()
1324 void doctokenizerYYsetStateXRefItem()
1329 void doctokenizerYYsetStateFile()
1334 void doctokenizerYYsetStatePattern()
1339 void doctokenizerYYsetStateLink()
1344 void doctokenizerYYsetStateCite()
1349 void doctokenizerYYsetStateRef()
1354 void doctokenizerYYsetStateInternalRef()
1359 void doctokenizerYYsetStateText()
1364 void doctokenizerYYsetStateSkipTitle()
1366 BEGIN(St_SkipTitle);
1369 void doctokenizerYYsetStateAnchor()
1374 void doctokenizerYYsetStateSnippet()
1379 void doctokenizerYYcleanup()
1381 yy_delete_buffer( YY_CURRENT_BUFFER );
1384 void doctokenizerYYsetInsidePre(bool b)
1389 void doctokenizerYYpushBackHtmlTag(const char *tag)
1391 QCString tagName = tag;
1392 int i,l = tagName.length();
1394 for (i=l-1;i>=0;i--)
1401 void doctokenizerYYstartAutoList()
1406 void doctokenizerYYendAutoList()
1413 printlex(yy_flex_debug, TRUE, __FILE__, g_fileName);
1414 int retval = LOCAL_YY_DECL;
1415 printlex(yy_flex_debug, FALSE, __FILE__, g_fileName);
1418 #if !defined(YY_FLEX_SUBMINOR_VERSION)
1419 extern "C" { // some bogus code to keep the compiler happy
1420 void doctokenizerYYdummy() { yy_flex_realloc(0,0); }