1 /******************************************************************************
6 * Copyright (C) 1997-2015 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.
19 %option never-interactive
20 %option prefix="doctokenizerYY"
22 %option extra-type="struct doctokenizerYY_state *"
25 // forward declare yyscan_t to improve type safety
26 #define YY_TYPEDEF_YY_SCANNER_T
28 typedef yyguts_t *yyscan_t;
38 #include "doctokenizer.h"
39 #include "cmdmapper.h"
43 #include "membergroup.h"
44 #include "definition.h"
51 #define YY_NO_UNISTD_H 1
53 #define USE_STATE2STRING 0
55 #define TK_COMMAND_SEL() (yytext[0] == '@' ? TK_COMMAND_AT : TK_COMMAND_BS)
57 //--------------------------------------------------------------------------
59 struct DocLexerContext
61 DocLexerContext(TokenInfo *tk,int r,int lvl,yy_size_t pos,const char *s,YY_BUFFER_STATE bs)
62 : token(tk), rule(r), autoListLevel(lvl), inputPos(pos), inputString(s), state(bs) {}
67 const char *inputString;
68 YY_BUFFER_STATE state;
71 struct doctokenizerYY_state
74 // context for tokenizer phase
77 yy_size_t inputPos = 0;
78 const char *inputString = 0;
80 bool insidePre = false;
82 bool markdownSupport=TRUE;
84 // context for section finding phase
85 const Definition *definition = 0;
91 std::stack< std::unique_ptr<DocLexerContext> > lexerStack;
96 #define lineCount(s,len) do { for(int i=0;i<(int)len;i++) if (s[i]=='\n') yyextra->yyLineNr++; } while(0)
100 static const char *stateToString(int state);
104 static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size);
105 static void handleHtmlTag(yyscan_t yyscanner,const char *text);
106 static void processSection(yyscan_t yyscanner);
108 //--------------------------------------------------------------------------
110 QCString extractPartAfterNewLine(const QCString &text)
112 int nl1 = text.find('\n');
113 int nl2 = text.find("\\ilinebr");
114 if (nl1!=-1 && nl1<nl2)
116 return text.mid(nl1+1);
120 if (text.at(nl2+8)==' ') nl2++; // skip space after \\ilinebr
121 return text.mid(nl2+8);
126 //--------------------------------------------------------------------------
128 const char *DocTokenizer::tokToString(int token)
132 case 0: return "TK_EOF";
133 case TK_WORD: return "TK_WORD";
134 case TK_LNKWORD: return "TK_LNKWORD";
135 case TK_WHITESPACE: return "TK_WHITESPACE";
136 case TK_LISTITEM: return "TK_LISTITEM";
137 case TK_ENDLIST: return "TK_ENDLIST";
138 case TK_COMMAND_AT: return "TK_COMMAND_AT";
139 case TK_HTMLTAG: return "TK_HTMLTAG";
140 case TK_SYMBOL: return "TK_SYMBOL";
141 case TK_NEWPARA: return "TK_NEWPARA";
142 case TK_RCSTAG: return "TK_RCSTAG";
143 case TK_URL: return "TK_URL";
144 case TK_COMMAND_BS: return "TK_COMMAND_BS";
149 const char *DocTokenizer::retvalToString(int retval)
153 case RetVal_OK: return "RetVal_OK";
154 case RetVal_SimpleSec: return "RetVal_SimpleSec";
155 case RetVal_ListItem: return "RetVal_ListItem";
156 case RetVal_Section: return "RetVal_Section";
157 case RetVal_Subsection: return "RetVal_Subsection";
158 case RetVal_Subsubsection: return "RetVal_Subsubsection";
159 case RetVal_Paragraph: return "RetVal_Paragraph";
160 case RetVal_SubParagraph: return "RetVal_SubParagraph";
161 case RetVal_EndList: return "RetVal_EndList";
162 case RetVal_EndPre: return "RetVal_EndPre";
163 case RetVal_DescData: return "RetVal_DescData";
164 case RetVal_DescTitle : return "RetVal_DescTitle";
165 case RetVal_EndDesc: return "RetVal_EndDesc";
166 case RetVal_TableRow: return "RetVal_TableRow";
167 case RetVal_TableCell: return "RetVal_TableCell";
168 case RetVal_TableHCell: return "RetVal_TableHCell";
169 case RetVal_EndTable: return "RetVal_EndTable";
170 case RetVal_Internal: return "RetVal_Internal";
175 static int computeIndent(const char *str,size_t length)
177 if (str==0 || length==std::string::npos) return 0;
180 static int tabSize=Config_getInt(TAB_SIZE);
181 for (i=0;i<length;i++)
185 indent+=tabSize - (indent%tabSize);
187 else if (str[i]=='\n')
199 //--------------------------------------------------------------------------
201 static QCString stripEmptyLines(const QCString &s)
203 if (s.isEmpty()) return QCString();
206 // skip leading empty lines
210 while ((c=s[p]) && (c==' ' || c=='\t')) p++;
220 // skip trailing empty lines
222 if (p>=start && s.at(p)=='\n') p--;
226 while ((c=s[p]) && (c==' ' || c=='\t')) p--;
237 //printf("stripEmptyLines(%d-%d)\n",start,end);
238 return s.mid(start,end-start);
241 #define unput_string(yytext,yyleng) do { for (int i=(int)yyleng-1;i>=0;i--) unput(yytext[i]); } while(0)
242 //--------------------------------------------------------------------------
245 #define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size);
247 //--------------------------------------------------------------------------
248 //#define REAL_YY_DECL int doctokenizerYYlex (void)
249 //#define YY_DECL static int local_doctokenizer(void)
250 //#define LOCAL_YY_DECL local_doctokenizer()
259 ID [$a-z_A-Z\x80-\xFF][$a-z_A-Z0-9\x80-\xFF]*
260 LABELID [a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF\-]*
261 PHPTYPE [\\:a-z_A-Z0-9\x80-\xFF\-]+
262 CITESCHAR [a-z_A-Z0-9\x80-\xFF\-\?]
263 CITEECHAR [a-z_A-Z0-9\x80-\xFF\-\+:\/\?]
264 CITEID {CITESCHAR}{CITEECHAR}*("."{CITESCHAR}{CITEECHAR}*)*|"\""{CITESCHAR}{CITEECHAR}*("."{CITESCHAR}{CITEECHAR}*)*"\""
265 MAILADDR ("mailto:")?[a-z_A-Z0-9.+-]+"@"[a-z_A-Z0-9-]+("."[a-z_A-Z0-9\-]+)+[a-z_A-Z0-9\-]+
266 MAILWS [\t a-z_A-Z0-9+-]
267 MAILADDR2 {MAILWS}+{BLANK}+("at"|"AT"|"_at_"|"_AT_"){BLANK}+{MAILWS}+("dot"|"DOT"|"_dot_"|"_DOT_"){BLANK}+{MAILWS}+
268 OPTSTARS ("/""/"{BLANK}*)?"*"*{BLANK}*
269 LISTITEM {BLANK}*[-]("#")?{WS}
270 MLISTITEM {BLANK}*[+*]{WS}
271 OLISTITEM {BLANK}*[1-9][0-9]*"."{BLANK}
272 ENDLIST {BLANK}*"."{BLANK}*\n
273 ATTRNAME [a-z_A-Z\x80-\xFF][:a-z_A-Z0-9\x80-\xFF\-]*
274 ATTRIB {ATTRNAME}{WS}*("="{WS}*(("\""[^\"]*"\"")|("'"[^\']*"'")|[^ \t\r\n'"><]+))?
275 URLCHAR [a-z_A-Z0-9\!\~\,\:\;\'\$\?\@\&\%\#\.\-\+\/\=\x80-\xFF]
276 URLMASK ({URLCHAR}+([({]{URLCHAR}*[)}])?)+
277 URLPROTOCOL ("http:"|"https:"|"ftp:"|"ftps:"|"sftp:"|"file:"|"news:"|"irc:"|"ircs:")
278 FILEICHAR [a-z_A-Z0-9\\:\\\/\-\+&#@]
279 FILEECHAR [a-z_A-Z0-9\-\+&#@]
280 FILECHARS {FILEICHAR}*{FILEECHAR}+
281 HFILEMASK {FILEICHAR}*("."{FILEICHAR}+)+{FILECHARS}*
282 VFILEMASK {FILECHARS}("."{FILECHARS})*
283 FILEMASK {VFILEMASK}|{HFILEMASK}
284 LINKMASK [^ \t\n\r\\@<&${}]+("("[^\n)]*")")?({BLANK}*("const"|"volatile"){BLANK}+)?
285 VERBATIM "verbatim"{BLANK}*
286 SPCMD1 {CMD}([a-z_A-Z][a-z_A-Z0-9]*|{VERBATIM}|"--"|"---")
287 SPCMD2 {CMD}[\\@<>&$#%~".+=|-]
288 SPCMD3 {CMD}_form#[0-9]+
291 INOUT "in"|"out"|("in"{BLANK}*","?{BLANK}*"out")|("out"{BLANK}*","?{BLANK}*"in")
292 PARAMIO {CMD}param{BLANK}*"["{BLANK}*{INOUT}{BLANK}*"]"
294 TEMPCHAR [a-z_A-Z0-9.,: \t\*\&\(\)\[\]]
295 FUNCCHAR [a-z_A-Z0-9,:<> \t\^\*\&\[\]]|{VARARGS}
296 FUNCPART {FUNCCHAR}*("("{FUNCCHAR}*")"{FUNCCHAR}*)?
297 SCOPESEP "::"|"#"|"."
298 TEMPLPART "<"{TEMPCHAR}*("<"{TEMPCHAR}*("<"{TEMPCHAR}*">")?">")?">"
299 ANONNS "anonymous_namespace{"[^}]*"}"
300 SCOPEPRE (({ID}{TEMPLPART}?)|{ANONNS}){SCOPESEP}
301 SCOPEKEYS ":"({ID}":")*
302 SCOPECPP {SCOPEPRE}*(~)?{ID}{TEMPLPART}?
303 SCOPEOBJC {SCOPEPRE}?{ID}{SCOPEKEYS}?
304 SCOPEMASK {SCOPECPP}|{SCOPEOBJC}
305 FUNCARG "("{FUNCPART}")"({BLANK}*("volatile"|"const"){BLANK})?
306 FUNCARG2 "("{FUNCPART}")"({BLANK}*("volatile"|"const"))?
307 OPNEW {BLANK}+"new"({BLANK}*"[]")?
308 OPDEL {BLANK}+"delete"({BLANK}*"[]")?
309 OPNORM {OPNEW}|{OPDEL}|"+"|"-"|"*"|"/"|"%"|"^"|"&"|"|"|"~"|"!"|"="|"<"|">"|"+="|"-="|"*="|"/="|"%="|"^="|"&="|"|="|"<<"|">>"|"<<="|">>="|"=="|"!="|"<="|">="|"&&"|"||"|"++"|"--"|","|"->*"|"->"|"[]"|"()"|"<=>"
310 OPCAST {BLANK}+[^<(\r\n.,][^(\r\n.,]*
311 OPMASK ({BLANK}*{OPNORM}{FUNCARG})
312 OPMASKOPT ({BLANK}*{OPNORM}{FUNCARG}?)|({OPCAST}{FUNCARG})
313 OPMASKOP2 ({BLANK}*{OPNORM}{FUNCARG2}?)|({OPCAST}{FUNCARG2})
314 LNKWORD1 ("::"|"#")?{SCOPEMASK}
315 CVSPEC {BLANK}*("const"|"volatile")
316 LNKWORD2 (({SCOPEPRE}*"operator"{OPMASK})|({SCOPEPRE}"operator"{OPMASKOPT})|(("::"|"#"){SCOPEPRE}*"operator"{OPMASKOPT})){CVSPEC}?
317 LNKWORD3 ([0-9a-z_A-Z\-]+("/"|"\\"))*[0-9a-z_A-Z\-]+("."[0-9a-z_A-Z]+)+
318 CHARWORDQ [^ \t\n\r\\@<>()\[\]:;\?{}&%$#,."=']
319 ESCWORD ("%"{ID}(("::"|"."){ID})*)|("%'")
320 CHARWORDQ1 [^ \-+0-9\t\n\r\\@<>()\[\]:;\?{}&%$#,."=']
321 WORD1 {ESCWORD}|{CHARWORDQ1}{CHARWORDQ}*|"{"|"}"|"'\"'"|("\""([^"\n]*\n?)*[^"\n]*"\"")
322 WORD2 "."|","|"("|")"|"["|"]"|"::"|":"|";"|"\?"|"="|"'"
323 WORD1NQ {ESCWORD}|{CHARWORDQ}+|"{"|"}"
324 WORD2NQ "."|","|"("|")"|"["|"]"|"::"|":"|";"|"\?"|"="|"'"
325 CAPTION [cC][aA][pP][tT][iI][oO][nN]
326 HTMLTAG "<"(("/")?){ID}({WS}+{ATTRIB})*{WS}*(("/")?)">"
327 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"|"strike"|"u"|"del"|"ins"|"s"
328 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"|"STRIKE"|"U"|"DEL"|"INS"|"S"
329 HTMLKEYW {HTMLKEYL}|{HTMLKEYU}
330 REFWORD2_PRE ("#"|"::")?((({ID}{TEMPLPART}?)|{ANONNS})("."|"#"|"::"|"-"|"/"))*({ID}{TEMPLPART}?(":")?)
331 REFWORD2 {REFWORD2_PRE}{FUNCARG2}?
332 REFWORD2_NOCV {REFWORD2_PRE}("("{FUNCPART}")")?
333 REFWORD3 ({ID}":")*{ID}":"?
334 REFWORD4_NOCV (({SCOPEPRE}*"operator"{OPMASKOP2})|(("::"|"#"){SCOPEPRE}*"operator"{OPMASKOP2}))
335 REFWORD4 {REFWORD4_NOCV}{CVSPEC}?
336 REFWORD {FILEMASK}|{LABELID}|{REFWORD2}|{REFWORD3}|{REFWORD4}
337 REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV}
338 RCSID "$"("Author"|"Date"|"Header"|"Id"|"Locker"|"Log"|"Name"|"RCSfile"|"Revision"|"Source"|"State")":"[^:\n$][^\n$]*"$"
339 LINENR {BLANK}*[1-9][0-9]*
393 <St_Para>\r /* skip carriage return */
394 <St_Para>^{LISTITEM} { /* list item */
395 lineCount(yytext,yyleng);
396 QCString text(yytext);
397 uint dashPos = static_cast<uint>(text.findRev('-'));
398 assert(dashPos!=static_cast<uint>(-1));
399 yyextra->token->isEnumList = text.at(dashPos+1)=='#';
400 yyextra->token->id = -1;
401 yyextra->token->indent = computeIndent(yytext,dashPos);
404 <St_Para>^{MLISTITEM} { /* list item */
405 if (!yyextra->markdownSupport || yyextra->insidePre)
411 lineCount(yytext,yyleng);
412 std::string text(yytext);
413 static const reg::Ex re(R"([*+][^*+]*$)"); // find last + or *
415 reg::search(text,match,re);
416 size_t listPos = match.position();
417 assert(listPos!=std::string::npos);
418 yyextra->token->isEnumList = FALSE;
419 yyextra->token->id = -1;
420 yyextra->token->indent = computeIndent(yytext,listPos);
424 <St_Para>^{OLISTITEM} { /* numbered list item */
425 if (!yyextra->markdownSupport || yyextra->insidePre)
431 std::string text(yytext);
432 static const reg::Ex re(R"(\d+)");
434 reg::search(text,match,re);
435 size_t markPos = match.position();
436 assert(markPos!=std::string::npos);
437 yyextra->token->isEnumList = true;
439 int id = QCString(match.str()).toInt(&ok);
440 yyextra->token->id = ok ? id : -1;
443 warn(yyextra->fileName,yyextra->yyLineNr,"Invalid number for list item '%s' ",match.str().c_str());
445 yyextra->token->indent = computeIndent(yytext,markPos);
449 <St_Para>{BLANK}*(\n|"\\ilinebr"){LISTITEM} { /* list item on next line */
450 lineCount(yytext,yyleng);
451 QCString text=extractPartAfterNewLine(QCString(yytext));
452 uint dashPos = static_cast<uint>(text.findRev('-'));
453 assert(dashPos!=static_cast<uint>(-1));
454 yyextra->token->isEnumList = text.at(dashPos+1)=='#';
455 yyextra->token->id = -1;
456 yyextra->token->indent = computeIndent(text.data(),dashPos);
459 <St_Para>{BLANK}*(\n|"\\ilinebr"){MLISTITEM} { /* list item on next line */
460 if (!yyextra->markdownSupport || yyextra->insidePre)
466 lineCount(yytext,yyleng);
467 std::string text=extractPartAfterNewLine(QCString(yytext)).str();
468 static const reg::Ex re(R"([*+][^*+]*$)"); // find last + or *
470 reg::search(text,match,re);
471 size_t markPos = match.position();
472 assert(markPos!=std::string::npos);
473 yyextra->token->isEnumList = FALSE;
474 yyextra->token->id = -1;
475 yyextra->token->indent = computeIndent(text.c_str(),markPos);
479 <St_Para>{BLANK}*(\n|"\\ilinebr"){OLISTITEM} { /* list item on next line */
480 if (!yyextra->markdownSupport || yyextra->insidePre)
486 lineCount(yytext,yyleng);
487 std::string text=extractPartAfterNewLine(QCString(yytext)).str();
488 static const reg::Ex re(R"(\d+)");
490 reg::search(text,match,re);
491 size_t markPos = match.position();
492 assert(markPos!=std::string::npos);
493 yyextra->token->isEnumList = true;
495 int id = QCString(match.str()).toInt(&ok);
496 yyextra->token->id = ok ? id : -1;
499 warn(yyextra->fileName,yyextra->yyLineNr,"Invalid number for list item '%s' ",match.str().c_str());
501 yyextra->token->indent = computeIndent(text.c_str(),markPos);
505 <St_Para>^{ENDLIST} { /* end list */
506 lineCount(yytext,yyleng);
507 size_t dotPos = static_cast<size_t>(QCString(yytext).findRev('.'));
508 yyextra->token->indent = computeIndent(yytext,dotPos);
511 <St_Para>{BLANK}*(\n|"\\ilinebr"){ENDLIST} { /* end list on next line */
512 lineCount(yytext,yyleng);
513 QCString text=extractPartAfterNewLine(QCString(yytext));
514 size_t dotPos = static_cast<size_t>(text.findRev('.'));
515 yyextra->token->indent = computeIndent(text.data(),dotPos);
518 <St_Para>"{"{BLANK}*"@link"/{WS}+ {
519 yyextra->token->name = "javalink";
520 return TK_COMMAND_AT;
522 <St_Para>"{"{BLANK}*"@inheritDoc"{BLANK}*"}" {
523 yyextra->token->name = "inheritdoc";
524 return TK_COMMAND_AT;
526 <St_Para>"@_fakenl" { // artificial new line
527 //yyextra->yyLineNr++;
530 yyextra->token->name = "_form";
532 yyextra->token->id = QCString(yytext).right((int)yyleng-7).toInt(&ok);
534 return TK_COMMAND_SEL();
536 <St_Para>{CMD}"n"\n { /* \n followed by real newline */
537 lineCount(yytext,yyleng);
538 //yyextra->yyLineNr++;
539 yyextra->token->name = yytext+1;
540 yyextra->token->name = yyextra->token->name.stripWhiteSpace();
541 yyextra->token->paramDir=TokenInfo::Unspecified;
542 return TK_COMMAND_SEL();
544 <St_Para>"\\ilinebr" {
549 <St_Para>{SPCMD4} { /* special command */
550 yyextra->token->name = yytext+1;
551 yyextra->token->name = yyextra->token->name.stripWhiteSpace();
552 yyextra->token->paramDir=TokenInfo::Unspecified;
553 return TK_COMMAND_SEL();
555 <St_Para>{PARAMIO} { /* param [in,out] command */
556 yyextra->token->name = "param";
558 bool isIn = s.find("in")!=-1;
559 bool isOut = s.find("out")!=-1;
564 yyextra->token->paramDir=TokenInfo::InOut;
568 yyextra->token->paramDir=TokenInfo::In;
573 yyextra->token->paramDir=TokenInfo::Out;
577 yyextra->token->paramDir=TokenInfo::Unspecified;
579 return TK_COMMAND_SEL();
581 <St_Para>{URLPROTOCOL}{URLMASK}/[,\.] { // URL, or URL.
582 yyextra->token->name=yytext;
583 yyextra->token->isEMailAddr=FALSE;
586 <St_Para>{URLPROTOCOL}{URLMASK} { // URL
587 yyextra->token->name=yytext;
588 yyextra->token->isEMailAddr=FALSE;
591 <St_Para>"<"{URLPROTOCOL}{URLMASK}">" { // URL
592 yyextra->token->name=yytext;
593 yyextra->token->name = yyextra->token->name.mid(1,yyextra->token->name.length()-2);
594 yyextra->token->isEMailAddr=FALSE;
597 <St_Para>{MAILADDR} { // Mail address
598 yyextra->token->name=yytext;
599 yyextra->token->name.stripPrefix("mailto:");
600 yyextra->token->isEMailAddr=TRUE;
603 <St_Para>"<"{MAILADDR}">" { // Mail address
604 yyextra->token->name=yytext;
605 yyextra->token->name = yyextra->token->name.mid(1,yyextra->token->name.length()-2);
606 yyextra->token->name.stripPrefix("mailto:");
607 yyextra->token->isEMailAddr=TRUE;
610 <St_Para>"<"{MAILADDR2}">" { // anti spam mail address
611 yyextra->token->name=yytext;
614 <St_Para>{RCSID} { /* RCS tag */
615 QCString tagName(yytext+1);
616 int index=tagName.find(':');
617 if (index<0) index=0; // should never happen
618 yyextra->token->name = tagName.left(index);
619 int text_begin = index+2;
620 int text_end = tagName.length()-1;
621 if (tagName[text_begin-1]==':') /* check for Subversion fixed-length keyword */
624 if (tagName[text_end-1]=='#')
627 yyextra->token->text = tagName.mid(text_begin,text_end-text_begin);
630 <St_Para,St_HtmlOnly,St_ManOnly,St_LatexOnly,St_RtfOnly,St_XmlOnly,St_DbOnly>"$("{ID}")" | /* environment variable */
631 <St_Para,St_HtmlOnly,St_ManOnly,St_LatexOnly,St_RtfOnly,St_XmlOnly,St_DbOnly>"$("{ID}"("{ID}"))" { /* environment variable */
632 QCString name(&yytext[2]);
633 name = name.left(name.length()-1);
634 QCString value = Portable::getenv(name);
635 for (int i=value.length()-1;i>=0;i--) unput(value.at(i));
637 <St_Para>{HTMLTAG} { /* html tag */
638 lineCount(yytext,yyleng);
639 handleHtmlTag(yyscanner,yytext);
642 <St_Para,St_Text>"&"{ID}";" { /* special symbol */
643 yyextra->token->name = yytext;
647 /********* patterns for linkable words ******************/
649 <St_Para>{ID}/"<"{HTMLKEYW}">" { /* this rule is to prevent opening html
650 * tag to be recognized as a templated classes
652 yyextra->token->name = yytext;
655 <St_Para>{LNKWORD1}/"<br>" | // prevent <br> html tag to be parsed as template arguments
656 <St_Para>{LNKWORD1} |
657 <St_Para>{LNKWORD1}{FUNCARG} |
658 <St_Para>{LNKWORD2} |
659 <St_Para>{LNKWORD3} {
660 yyextra->token->name = yytext;
663 <St_Para>{LNKWORD1}{FUNCARG}{CVSPEC}[^a-z_A-Z0-9] {
664 yyextra->token->name = yytext;
665 yyextra->token->name = yyextra->token->name.left(yyextra->token->name.length()-1);
666 unput(yytext[(int)yyleng-1]);
669 /********* patterns for normal words ******************/
671 <St_Para,St_Text>[\-+0-9] |
672 <St_Para,St_Text>{WORD1} |
673 <St_Para,St_Text>{WORD2} { /* function call */
674 if (QCString(yytext).find("\\ilinebr")!=-1) REJECT; // see issue #8311
675 lineCount(yytext,yyleng);
676 if (yytext[0]=='%') // strip % if present
677 yyextra->token->name = &yytext[1];
679 yyextra->token->name = yytext;
682 <St_Text>({ID}".")+{ID} {
683 yyextra->token->name = yytext;
686 <St_Para,St_Text>"operator"/{BLANK}*"<"[a-zA-Z_0-9]+">" { // Special case: word "operator" followed by a HTML command
687 // avoid interpretation as "operator <"
688 yyextra->token->name = yytext;
692 /*******************************************************/
694 <St_Para,St_Text>{BLANK}+ |
695 <St_Para,St_Text>{BLANK}*\n{BLANK}* { /* white space */
696 lineCount(yytext,yyleng);
697 yyextra->token->chars=yytext;
698 return TK_WHITESPACE;
700 <St_Text>[\\@<>&$#%~] {
701 yyextra->token->name = yytext;
702 return TK_COMMAND_SEL();
704 <St_Para>({BLANK}*\n)+{BLANK}*\n/{LISTITEM} { /* skip trailing paragraph followed by new list item */
705 if (yyextra->insidePre || yyextra->autoListLevel==0)
709 lineCount(yytext,yyleng);
711 <St_Para>({BLANK}*\n)+{BLANK}*\n/{MLISTITEM} { /* skip trailing paragraph followed by new list item */
712 if (!yyextra->markdownSupport || yyextra->insidePre || yyextra->autoListLevel==0)
716 lineCount(yytext,yyleng);
718 <St_Para>({BLANK}*\n)+{BLANK}*\n/{OLISTITEM} { /* skip trailing paragraph followed by new list item */
719 if (!yyextra->markdownSupport || yyextra->insidePre || yyextra->autoListLevel==0)
723 lineCount(yytext,yyleng);
725 <St_Para,St_Param>({BLANK}*(\n|"\\ilinebr"))+{BLANK}*(\n|"\\ilinebr"){BLANK}* {
726 lineCount(yytext,yyleng);
727 if (yyextra->insidePre)
729 yyextra->token->chars=yytext;
730 return TK_WHITESPACE;
734 yyextra->token->indent=computeIndent(yytext,yyleng);
736 // put back the indentation (needed for list items)
737 for (i=0;i<yyextra->token->indent;i++)
741 // tell flex that after putting the last indent
742 // back we are at the beginning of the line
743 YY_CURRENT_BUFFER->yy_at_bol=1;
744 // start of a new paragraph
748 <St_CodeOpt>{BLANK}*"{"(".")?{LABELID}"}" {
749 yyextra->token->name = yytext;
750 int i=yyextra->token->name.find('{'); /* } to keep vi happy */
751 yyextra->token->name = yyextra->token->name.mid(i+1,yyextra->token->name.length()-i-2);
754 <St_CodeOpt>"\\ilinebr" |
757 unput_string(yytext,yyleng);
760 <St_Code>{WS}*{CMD}"endcode" {
761 lineCount(yytext,yyleng);
764 <St_XmlCode>{WS}*"</code>" {
765 lineCount(yytext,yyleng);
768 <St_Code,St_XmlCode>[^\\@\n<]+ |
769 <St_Code,St_XmlCode>\n |
770 <St_Code,St_XmlCode>. {
771 lineCount(yytext,yyleng);
772 yyextra->token->verb+=yytext;
774 <St_HtmlOnlyOption>" [block]" { // the space is added in commentscan.l
775 yyextra->token->name="block";
778 <St_HtmlOnlyOption>.|\n {
782 <St_HtmlOnlyOption>"\\ilinebr" {
783 unput_string(yytext,yyleng);
786 <St_HtmlOnly>{CMD}"endhtmlonly" {
789 <St_HtmlOnly>[^\\@\n$]+ |
792 lineCount(yytext,yyleng);
793 yyextra->token->verb+=yytext;
795 <St_ManOnly>{CMD}"endmanonly" {
798 <St_ManOnly>[^\\@\n$]+ |
801 lineCount(yytext,yyleng);
802 yyextra->token->verb+=yytext;
804 <St_RtfOnly>{CMD}"endrtfonly" {
807 <St_RtfOnly>[^\\@\n$]+ |
810 lineCount(yytext,yyleng);
811 yyextra->token->verb+=yytext;
813 <St_LatexOnly>{CMD}"endlatexonly" {
816 <St_LatexOnly>[^\\@\n]+ |
819 lineCount(yytext,yyleng);
820 yyextra->token->verb+=yytext;
822 <St_XmlOnly>{CMD}"endxmlonly" {
825 <St_XmlOnly>[^\\@\n]+ |
828 lineCount(yytext,yyleng);
829 yyextra->token->verb+=yytext;
831 <St_DbOnly>{CMD}"enddocbookonly" {
834 <St_DbOnly>[^\\@\n]+ |
837 lineCount(yytext,yyleng);
838 yyextra->token->verb+=yytext;
840 <St_Verbatim>{CMD}"endverbatim" {
841 yyextra->token->verb=stripEmptyLines(yyextra->token->verb);
844 <St_Verbatim>[^\\@\n]+ |
846 <St_Verbatim>. { /* Verbatim text */
847 lineCount(yytext,yyleng);
848 yyextra->token->verb+=yytext;
850 <St_Dot>{CMD}"enddot" {
855 <St_Dot>. { /* dot text */
856 lineCount(yytext,yyleng);
857 yyextra->token->verb+=yytext;
859 <St_Msc>{CMD}("endmsc") {
864 <St_Msc>. { /* msc text */
865 lineCount(yytext,yyleng);
866 yyextra->token->verb+=yytext;
868 <St_PlantUMLOpt>{BLANK}*"{"[a-zA-Z_,:0-9\. ]*"}" { // case 1: options present
869 yyextra->token->sectionId = QCString(yytext).stripWhiteSpace();
872 <St_PlantUMLOpt>{BLANK}*{FILEMASK}{BLANK}+/{ID}"=" { // case 2: plain file name specified followed by an attribute
873 yyextra->token->sectionId = QCString(yytext).stripWhiteSpace();
876 <St_PlantUMLOpt>{BLANK}*{FILEMASK}{BLANK}+/"\"" { // case 3: plain file name specified followed by a quoted title
877 yyextra->token->sectionId = QCString(yytext).stripWhiteSpace();
880 <St_PlantUMLOpt>{BLANK}*{FILEMASK}{BLANKopt}/\n { // case 4: plain file name specified without title or attributes
881 yyextra->token->sectionId = QCString(yytext).stripWhiteSpace();
884 <St_PlantUMLOpt>{BLANK}*{FILEMASK}{BLANKopt}/"\\ilinebr" { // case 5: plain file name specified without title or attributes
885 yyextra->token->sectionId = QCString(yytext).stripWhiteSpace();
888 <St_PlantUMLOpt>"\\ilinebr" |
889 <St_PlantUMLOpt>"\n" |
891 yyextra->token->sectionId = "";
892 unput_string(yytext,yyleng);
895 <St_PlantUML>{CMD}"enduml" {
898 <St_PlantUML>[^\\@\n]+ |
900 <St_PlantUML>. { /* plantuml text */
901 lineCount(yytext,yyleng);
902 yyextra->token->verb+=yytext;
904 <St_Title>"\"" { // quoted title
908 yyextra->token->chars=yytext;
909 return TK_WHITESPACE;
911 <St_Title>. { // non-quoted title
919 <St_Title>"\\ilinebr" {
920 unput_string(yytext,yyleng);
923 <St_TitleN>"&"{ID}";" { /* symbol */
924 yyextra->token->name = yytext;
927 <St_TitleN>{HTMLTAG} {
928 lineCount(yytext,yyleng);
930 <St_TitleN>\n { /* new line => end of title */
934 <St_TitleN>"\\ilinebr" { /* new line => end of title */
935 unput_string(yytext,yyleng);
938 <St_TitleN>{SPCMD1} |
939 <St_TitleN>{SPCMD2} { /* special command */
940 yyextra->token->name = yytext+1;
941 yyextra->token->paramDir=TokenInfo::Unspecified;
942 return TK_COMMAND_SEL();
944 <St_TitleN>{ID}"=" { /* attribute */
945 if (yytext[0]=='%') // strip % if present
946 yyextra->token->name = &yytext[1];
948 yyextra->token->name = yytext;
951 <St_TitleN>[\-+0-9] |
953 <St_TitleN>{WORD2} { /* word */
954 if (QCString(yytext).find("\\ilinebr")!=-1) REJECT; // see issue #8311
955 lineCount(yytext,yyleng);
956 if (yytext[0]=='%') // strip % if present
957 yyextra->token->name = &yytext[1];
959 yyextra->token->name = yytext;
963 yyextra->token->chars=yytext;
964 return TK_WHITESPACE;
966 <St_TitleQ>"&"{ID}";" { /* symbol */
967 yyextra->token->name = yytext;
970 <St_TitleQ>(\n|"\\ilinebr") { /* new line => end of title */
971 unput_string(yytext,yyleng);
974 <St_TitleQ>{SPCMD1} |
975 <St_TitleQ>{SPCMD2} { /* special command */
976 yyextra->token->name = yytext+1;
977 yyextra->token->paramDir=TokenInfo::Unspecified;
978 return TK_COMMAND_SEL();
980 <St_TitleQ>{WORD1NQ} |
981 <St_TitleQ>{WORD2NQ} { /* word */
982 yyextra->token->name = yytext;
986 yyextra->token->chars=yytext;
987 return TK_WHITESPACE;
989 <St_TitleQ>"\"" { /* closing quote => end of title */
993 <St_TitleA>{BLANK}*{ID}{BLANK}*"="{BLANK}* { // title attribute
994 yyextra->token->name = yytext;
995 int pos = yyextra->token->name.find('=');
996 if (pos<0) pos=0; // should never happen
997 yyextra->token->name = yyextra->token->name.left(pos).stripWhiteSpace();
1000 <St_TitleV>[^ \t\r\n]+ { // attribute value
1001 lineCount(yytext,yyleng);
1002 yyextra->token->chars = yytext;
1006 <St_TitleV,St_TitleA>. {
1010 <St_TitleV,St_TitleA>(\n|"\\ilinebr") {
1011 unput_string(yytext,yyleng);
1015 <St_Anchor>{LABELID}{WS}? { // anchor
1016 lineCount(yytext,yyleng);
1017 yyextra->token->name = QCString(yytext).stripWhiteSpace();
1024 <St_Cite>{CITEID} { // label to cite
1025 if (yytext[0] =='"')
1027 yyextra->token->name=yytext+1;
1028 yyextra->token->name=yyextra->token->name.left(static_cast<uint>(yyleng)-2);
1032 yyextra->token->name=yytext;
1036 <St_Cite>{BLANK} { // white space
1040 <St_Cite>(\n|"\\ilinebr") { // new line
1041 unput_string(yytext,yyleng);
1044 <St_Cite>. { // any other character
1048 <St_Ref>{REFWORD_NOCV}/{BLANK}("const")[a-z_A-Z0-9] { // see bug776988
1049 yyextra->token->name=yytext;
1052 <St_Ref>{REFWORD_NOCV}/{BLANK}("volatile")[a-z_A-Z0-9] { // see bug776988
1053 yyextra->token->name=yytext;
1056 <St_Ref>{REFWORD} { // label to refer to
1057 yyextra->token->name=yytext;
1060 <St_Ref>{BLANK} { // white space
1064 <St_Ref>{WS}+"\""{WS}* { // white space following by quoted string
1065 lineCount(yytext,yyleng);
1068 <St_Ref>(\n|"\\ilinebr") { // new line
1069 unput_string(yytext,yyleng);
1072 <St_Ref>. { // any other character
1076 <St_IntRef>[A-Z_a-z0-9.:/#\-\+\(\)]+ {
1077 yyextra->token->name = yytext;
1080 <St_IntRef>{BLANK}+"\"" {
1083 <St_SetScope>({SCOPEMASK}|{ANONNS}){BLANK}|{FILEMASK} {
1084 yyextra->token->name = yytext;
1085 yyextra->token->name = yyextra->token->name.stripWhiteSpace();
1088 <St_SetScope>{SCOPEMASK}"<" {
1089 yyextra->token->name = yytext;
1090 yyextra->token->name = yyextra->token->name.stripWhiteSpace();
1091 yyextra->sharpCount=1;
1092 BEGIN(St_SetScopeEnd);
1094 <St_SetScope>{BLANK} {
1096 <St_SetScopeEnd>"<" {
1097 yyextra->token->name += yytext;
1098 yyextra->sharpCount++;
1100 <St_SetScopeEnd>">" {
1101 yyextra->token->name += yytext;
1102 yyextra->sharpCount--;
1103 if (yyextra->sharpCount<=0)
1109 yyextra->token->name += yytext;
1111 <St_Ref2>"&"{ID}";" { /* symbol */
1112 yyextra->token->name = yytext;
1115 <St_Ref2>"\""|\n|"\\ilinebr" { /* " or \n => end of title */
1116 lineCount(yytext,yyleng);
1120 <St_Ref2>{SPCMD2} { /* special command */
1121 yyextra->token->name = yytext+1;
1122 yyextra->token->paramDir=TokenInfo::Unspecified;
1123 return TK_COMMAND_SEL();
1125 <St_Ref2>{WORD1NQ} |
1126 <St_Ref2>{WORD2NQ} {
1128 yyextra->token->name = yytext;
1132 yyextra->token->chars=yytext;
1133 return TK_WHITESPACE;
1135 <St_XRefItem>{LABELID} {
1136 yyextra->token->name=yytext;
1139 BEGIN(St_XRefItem2);
1141 <St_XRefItem2>[0-9]+"." {
1142 QCString numStr(yytext);
1143 numStr=numStr.left((int)yyleng-1);
1144 yyextra->token->id=numStr.toInt();
1147 <St_Para,St_Title,St_Ref2>"<!--" { /* html style comment block */
1148 yyextra->commentState = YY_START;
1151 <St_Param>"\""[^\n\"]+"\"" {
1152 yyextra->token->name = yytext+1;
1153 yyextra->token->name = yyextra->token->name.left((int)yyleng-2);
1156 <St_Param>({PHPTYPE}{BLANK}*("["{BLANK}*"]")*{BLANK}*"|"{BLANK}*)*{PHPTYPE}{BLANK}*("["{BLANK}*"]")*{WS}+("&")?"$"{LABELID} {
1157 lineCount(yytext,yyleng);
1158 QCString params(yytext);
1159 int j = params.find('&');
1160 int i = params.find('$');
1161 if (i<0) i=0; // should never happen
1162 if (j<i && j>=0) i=j;
1163 QCString types = params.left(i).stripWhiteSpace();
1164 yyextra->token->name = types+"#"+params.mid(i);
1167 <St_Param>[^ \t\n,@\\]+ {
1168 yyextra->token->name = yytext;
1169 if (yyextra->token->name.at(static_cast<uint>(yyleng)-1)==':')
1171 yyextra->token->name=yyextra->token->name.left(static_cast<uint>(yyleng)-1);
1175 <St_Param>{WS}*","{WS}* /* param separator */
1177 lineCount(yytext,yyleng);
1178 yyextra->token->chars=yytext;
1179 return TK_WHITESPACE;
1182 yyextra->token->name+=yytext;
1184 <St_Options>{WS}*":"{WS}* {
1185 lineCount(yytext,yyleng);
1186 yyextra->token->name+=":";
1188 <St_Options>{WS}*","{WS}* |
1189 <St_Options>{WS} { /* option separator */
1190 lineCount(yytext,yyleng);
1191 yyextra->token->name+=",";
1197 yyextra->token->name+=yytext;
1202 <St_Emoji>[:0-9_a-z+-]+ {
1203 yyextra->token->name=yytext;
1209 <St_Iline>{LINENR}/[\n\.] |
1210 <St_Iline>{LINENR}{BLANK} {
1212 int nr = QCString(yytext).toInt(&ok);
1215 warn(yyextra->fileName,yyextra->yyLineNr,"Invalid line number '%s' for iline command",yytext);
1219 yyextra->yyLineNr = nr;
1226 <St_File>{FILEMASK} {
1227 yyextra->token->name = yytext;
1230 <St_File>"\""[^\n\"]+"\"" {
1231 QCString text(yytext);
1232 yyextra->token->name = text.mid(1,text.length()-2);
1235 <St_Pattern>[^\\\r\n]+ {
1236 yyextra->token->name += yytext;
1238 <St_Pattern>"\\ilinebr" {
1239 yyextra->token->name = yyextra->token->name.stripWhiteSpace();
1243 lineCount(yytext,yyleng);
1244 yyextra->token->name = yyextra->token->name.stripWhiteSpace();
1248 yyextra->token->name += yytext;
1250 <St_Link>{LINKMASK}|{REFWORD} {
1251 yyextra->token->name = yytext;
1254 <St_Comment>"-->" { /* end of html comment */
1255 BEGIN(yyextra->commentState);
1257 <St_Comment>[^-]+ /* inside html comment */
1258 <St_Comment>. /* inside html comment */
1260 /* State for skipping title (all chars until the end of the line) */
1263 <St_SkipTitle>(\n|"\\ilinebr") {
1264 lineCount(yytext,yyleng);
1268 /* State for the pass used to find the anchors and sections */
1270 <St_Sections>[^\n@\<]+
1271 <St_Sections>{CMD}("<"|{CMD})
1272 <St_Sections>"<"{CAPTION}({WS}+{ATTRIB})*">" {
1273 lineCount(yytext,yyleng);
1274 QCString tag(yytext);
1275 int s=tag.find("id=");
1276 if (s!=-1) // command has id attribute
1279 if (c=='\'' || c=='"') // valid start
1281 int e=tag.find(c,s+4);
1282 if (e!=-1) // found matching end
1284 yyextra->secType = SectionType::Table;
1285 yyextra->secLabel=tag.mid(s+4,e-s-4); // extract id
1286 processSection(yyscanner);
1291 <St_Sections>{CMD}"anchor"{BLANK}+ {
1292 yyextra->secType = SectionType::Anchor;
1293 BEGIN(St_SecLabel1);
1295 <St_Sections>{CMD}"section"{BLANK}+ {
1296 yyextra->secType = SectionType::Section;
1297 BEGIN(St_SecLabel2);
1299 <St_Sections>{CMD}"subsection"{BLANK}+ {
1300 yyextra->secType = SectionType::Subsection;
1301 BEGIN(St_SecLabel2);
1303 <St_Sections>{CMD}"subsubsection"{BLANK}+ {
1304 yyextra->secType = SectionType::Subsubsection;
1305 BEGIN(St_SecLabel2);
1307 <St_Sections>{CMD}"paragraph"{BLANK}+ {
1308 yyextra->secType = SectionType::Paragraph;
1309 BEGIN(St_SecLabel2);
1311 <St_Sections>{CMD}"verbatim"/[^a-z_A-Z0-9] {
1312 yyextra->endMarker="endverbatim";
1315 <St_Sections>{CMD}"dot"/[^a-z_A-Z0-9] {
1316 yyextra->endMarker="enddot";
1319 <St_Sections>{CMD}"msc"/[^a-z_A-Z0-9] {
1320 yyextra->endMarker="endmsc";
1323 <St_Sections>{CMD}"startuml"/[^a-z_A-Z0-9] {
1324 yyextra->endMarker="enduml";
1327 <St_Sections>{CMD}"htmlonly"/[^a-z_A-Z0-9] {
1328 yyextra->endMarker="endhtmlonly";
1331 <St_Sections>{CMD}"latexonly"/[^a-z_A-Z0-9] {
1332 yyextra->endMarker="endlatexonly";
1335 <St_Sections>{CMD}"manonly"/[^a-z_A-Z0-9] {
1336 yyextra->endMarker="endmanonly";
1339 <St_Sections>{CMD}"rtfonly"/[^a-z_A-Z0-9] {
1340 yyextra->endMarker="endrtfonly";
1343 <St_Sections>{CMD}"xmlonly"/[^a-z_A-Z0-9] {
1344 yyextra->endMarker="endxmlonly";
1347 <St_Sections>{CMD}"docbookonly"/[^a-z_A-Z0-9] {
1348 yyextra->endMarker="enddocbookonly";
1351 <St_Sections>{CMD}"code"/[^a-z_A-Z0-9] {
1352 yyextra->endMarker="endcode";
1355 <St_Sections>"<!--" {
1356 yyextra->endMarker="-->";
1359 <St_SecSkip>{CMD}{ID} {
1360 if (yyextra->endMarker==yytext+1)
1366 if (yyextra->endMarker==yytext)
1371 <St_SecSkip>[^a-z_A-Z0-9\-\\\@]+
1373 <St_SecSkip>(\n|"\\ilinebr")
1375 <St_Sections>(\n|"\\ilinebr")
1376 <St_SecLabel1>{LABELID} {
1377 lineCount(yytext,yyleng);
1378 yyextra->secLabel = yytext;
1379 processSection(yyscanner);
1382 <St_SecLabel2>{LABELID}{BLANK}+ |
1383 <St_SecLabel2>{LABELID} {
1384 yyextra->secLabel = yytext;
1385 yyextra->secLabel = yyextra->secLabel.stripWhiteSpace();
1388 <St_SecTitle>[^\n]+ |
1389 <St_SecTitle>[^\n]*\n {
1390 lineCount(yytext,yyleng);
1391 yyextra->secTitle = yytext;
1392 yyextra->secTitle = yyextra->secTitle.stripWhiteSpace();
1393 if (yyextra->secTitle.right(8)=="\\ilinebr")
1395 yyextra->secTitle.left(yyextra->secTitle.length()-8);
1397 processSection(yyscanner);
1400 <St_SecTitle,St_SecLabel1,St_SecLabel2>. {
1401 warn(yyextra->fileName,yyextra->yyLineNr,"Unexpected character '%s' while looking for section label or title",yytext);
1404 <St_Snippet>[^\\\n]+ {
1405 yyextra->token->name += yytext;
1408 yyextra->token->name += yytext;
1410 <St_Snippet>(\n|"\\ilinebr") {
1411 unput_string(yytext,yyleng);
1412 yyextra->token->name = yyextra->token->name.stripWhiteSpace();
1416 /* Generic rules that work for all states */
1418 lineCount(yytext,yyleng);
1419 warn(yyextra->fileName,yyextra->yyLineNr,"Unexpected new line character");
1423 <*>[\\@<>&$#%~"=] { /* unescaped special character */
1424 //warn(yyextra->fileName,yyextra->yyLineNr,"Unexpected character '%s', assuming command \\%s was meant.",yytext,yytext);
1425 yyextra->token->name = yytext;
1426 return TK_COMMAND_SEL();
1429 warn(yyextra->fileName,yyextra->yyLineNr,"Unexpected character '%s'",yytext);
1433 //--------------------------------------------------------------------------
1435 static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size)
1437 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1439 const char *p = yyextra->inputString + yyextra->inputPos;
1440 while ( c < max_size && *p ) { *buf++ = *p++; c++; }
1441 yyextra->inputPos+=c;
1445 static void processSection(yyscan_t yyscanner)
1447 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1448 //printf("%s: found section/anchor with name '%s'\n",qPrint(g_fileName),qPrint(g_secLabel));
1450 if (yyextra->definition)
1452 file = yyextra->definition->getOutputFileBase();
1456 warn(yyextra->fileName,yyextra->yyLineNr,"Found section/anchor %s without context\n",qPrint(yyextra->secLabel));
1458 SectionInfo *si = SectionManager::instance().find(yyextra->secLabel);
1461 si->setFileName(file);
1462 si->setType(yyextra->secType);
1466 static void handleHtmlTag(yyscan_t yyscanner,const char *text)
1468 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1470 QCString tagText(text);
1471 yyextra->token->attribs.clear();
1472 yyextra->token->endTag = FALSE;
1473 yyextra->token->emptyTag = FALSE;
1475 // Check for end tag
1477 if (tagText.at(1)=='/')
1479 yyextra->token->endTag = TRUE;
1483 // Parse the name portion
1484 int i = startNamePos;
1485 for (i=startNamePos; i < (int)yyleng; i++)
1487 // Check for valid HTML/XML name chars (including namespaces)
1488 char c = tagText.at(i);
1489 if (!(isalnum(c) || c=='-' || c=='_' || c==':')) break;
1491 yyextra->token->name = tagText.mid(startNamePos,i-startNamePos);
1493 // Parse the attributes. Each attribute is a name, value pair
1494 // The result is stored in yyextra->token->attribs.
1495 int startName,endName,startAttrib,endAttrib;
1496 int startAttribList = i;
1497 while (i<(int)yyleng)
1499 char c=tagText.at(i);
1501 while (i<(int)yyleng && isspace((uchar)c)) { c=tagText.at(++i); }
1502 // check for end of the tag
1503 if (c == '>') break;
1504 // Check for XML style "empty" tag.
1507 yyextra->token->emptyTag = TRUE;
1511 // search for end of name
1512 while (i<(int)yyleng && !isspace((uchar)c) && c!='=' && c!= '>') { c=tagText.at(++i); }
1515 opt.name = tagText.mid(startName,endName-startName).lower();
1517 while (i<(int)yyleng && isspace((uchar)c)) { c=tagText.at(++i); }
1518 if (tagText.at(i)=='=') // option has value
1522 while (i<(int)yyleng && isspace((uchar)c)) { c=tagText.at(++i); }
1523 if (tagText.at(i)=='\'') // option '...'
1528 // search for matching quote
1529 while (i<(int)yyleng && c!='\'') { c=tagText.at(++i); }
1531 if (i<(int)yyleng) { c=tagText.at(++i);}
1533 else if (tagText.at(i)=='"') // option "..."
1537 // search for matching quote
1538 while (i<(int)yyleng && c!='"') { c=tagText.at(++i); }
1540 if (i<(int)yyleng) { c=tagText.at(++i);}
1542 else // value without any quotes
1545 // search for separator or end symbol
1546 while (i<(int)yyleng && !isspace((uchar)c) && c!='>') { c=tagText.at(++i); }
1548 if (i<(int)yyleng) { c=tagText.at(++i);}
1550 opt.value = tagText.mid(startAttrib,endAttrib-startAttrib);
1551 if (opt.name == "align") opt.value = opt.value.lower();
1552 else if (opt.name == "valign")
1554 opt.value = opt.value.lower();
1555 if (opt.value == "center") opt.value="middle";
1558 else // start next option
1561 //printf("=====> Adding option name=<%s> value=<%s>\n",
1562 // qPrint(opt.name),qPrint(opt.value));
1563 yyextra->token->attribs.push_back(opt);
1565 yyextra->token->attribsStr = tagText.mid(startAttribList,i-startAttribList);
1568 struct DocTokenizer::Private
1571 doctokenizerYY_state extra;
1575 void DocTokenizer::pushContext()
1577 yyscan_t yyscanner = p->yyscanner;
1578 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1579 //printf("DocTokenizer::pushContext() stack=%zu\n",yyextra->lexerStack.size());
1580 yyextra->lexerStack.push(
1581 std::make_unique<DocLexerContext>(
1582 yyextra->token,YY_START,
1583 yyextra->autoListLevel,
1585 yyextra->inputString,
1586 YY_CURRENT_BUFFER));
1587 yy_switch_to_buffer(yy_create_buffer(0, YY_BUF_SIZE, yyscanner), yyscanner);
1590 bool DocTokenizer::popContext()
1592 yyscan_t yyscanner = p->yyscanner;
1593 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1594 //printf("DocTokenizer::popContext() stack=%zu\n",yyextra->lexerStack.size());
1595 if (yyextra->lexerStack.empty()) return FALSE;
1596 const auto &ctx = yyextra->lexerStack.top();
1597 yyextra->autoListLevel = ctx->autoListLevel;
1598 yyextra->inputPos = ctx->inputPos;
1599 yyextra->inputString = ctx->inputString;
1601 yy_delete_buffer(YY_CURRENT_BUFFER, yyscanner);
1602 yy_switch_to_buffer(ctx->state, yyscanner);
1605 yyextra->lexerStack.pop();
1610 DocTokenizer::DocTokenizer() : p(std::make_unique<Private>())
1612 //printf("%p:DocTokenizer::DocTokenizer()\n",(void*)this);
1613 doctokenizerYYlex_init_extra(&p->extra,&p->yyscanner);
1615 doctokenizerYYset_debug(1,p->yyscanner);
1619 DocTokenizer::~DocTokenizer()
1621 //printf("%p:DocTokenizer::~DocTokenizer()\n",(void*)this);
1622 doctokenizerYYlex_destroy(p->yyscanner);
1625 int DocTokenizer::lex()
1627 return doctokenizerYYlex(p->yyscanner);
1630 void DocTokenizer::findSections(const QCString &input,const Definition *d,
1631 const QCString &fileName)
1633 yyscan_t yyscanner = p->yyscanner;
1634 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1636 if (input.isEmpty()) return;
1637 printlex(yy_flex_debug, TRUE, __FILE__, qPrint(fileName));
1638 yyextra->inputString = input.data();
1639 //printf("parsing --->'%s'<---\n",input);
1640 yyextra->inputPos = 0;
1641 yyextra->definition = d;
1642 yyextra->fileName = fileName;
1644 yyextra->yyLineNr = 1;
1645 doctokenizerYYlex(yyscanner);
1646 printlex(yy_flex_debug, FALSE, __FILE__, qPrint(fileName));
1649 void DocTokenizer::init(const char *input,const QCString &fileName,bool markdownSupport)
1651 yyscan_t yyscanner = p->yyscanner;
1652 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1653 yyextra->autoListLevel = 0;
1654 yyextra->inputString = input;
1655 yyextra->inputPos = 0;
1656 yyextra->fileName = fileName;
1657 yyextra->insidePre = FALSE;
1658 yyextra->markdownSupport = markdownSupport;
1662 TokenInfo *DocTokenizer::newToken()
1664 yyscan_t yyscanner = p->yyscanner;
1665 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1666 return yyextra->token = new TokenInfo;
1669 void DocTokenizer::replaceToken(TokenInfo *newToken)
1671 yyscan_t yyscanner = p->yyscanner;
1672 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1673 delete yyextra->token;
1674 yyextra->token = newToken;
1677 void DocTokenizer::setStatePara()
1679 yyscan_t yyscanner = p->yyscanner;
1680 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1684 void DocTokenizer::setStateTitle()
1686 yyscan_t yyscanner = p->yyscanner;
1687 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1691 void DocTokenizer::setStateTitleAttrValue()
1693 yyscan_t yyscanner = p->yyscanner;
1694 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1698 void DocTokenizer::setStateCode()
1700 yyscan_t yyscanner = p->yyscanner;
1701 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1702 yyextra->token->verb="";
1703 yyextra->token->name="";
1707 void DocTokenizer::setStateXmlCode()
1709 yyscan_t yyscanner = p->yyscanner;
1710 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1711 yyextra->token->verb="";
1712 yyextra->token->name="";
1716 void DocTokenizer::setStateHtmlOnly()
1718 yyscan_t yyscanner = p->yyscanner;
1719 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1720 yyextra->token->verb="";
1721 yyextra->token->name="";
1722 BEGIN(St_HtmlOnlyOption);
1725 void DocTokenizer::setStateManOnly()
1727 yyscan_t yyscanner = p->yyscanner;
1728 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1729 yyextra->token->verb="";
1733 void DocTokenizer::setStateRtfOnly()
1735 yyscan_t yyscanner = p->yyscanner;
1736 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1737 yyextra->token->verb="";
1741 void DocTokenizer::setStateXmlOnly()
1743 yyscan_t yyscanner = p->yyscanner;
1744 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1745 yyextra->token->verb="";
1749 void DocTokenizer::setStateDbOnly()
1751 yyscan_t yyscanner = p->yyscanner;
1752 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1753 yyextra->token->verb="";
1757 void DocTokenizer::setStateLatexOnly()
1759 yyscan_t yyscanner = p->yyscanner;
1760 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1761 yyextra->token->verb="";
1762 BEGIN(St_LatexOnly);
1765 void DocTokenizer::setStateVerbatim()
1767 yyscan_t yyscanner = p->yyscanner;
1768 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1769 yyextra->token->verb="";
1773 void DocTokenizer::setStateDot()
1775 yyscan_t yyscanner = p->yyscanner;
1776 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1777 yyextra->token->verb="";
1781 void DocTokenizer::setStateMsc()
1783 yyscan_t yyscanner = p->yyscanner;
1784 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1785 yyextra->token->verb="";
1789 void DocTokenizer::setStatePlantUMLOpt()
1791 yyscan_t yyscanner = p->yyscanner;
1792 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1793 yyextra->token->verb="";
1794 yyextra->token->sectionId="";
1795 BEGIN(St_PlantUMLOpt);
1798 void DocTokenizer::setStatePlantUML()
1800 yyscan_t yyscanner = p->yyscanner;
1801 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1802 yyextra->token->verb="";
1806 void DocTokenizer::setStateParam()
1808 yyscan_t yyscanner = p->yyscanner;
1809 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1813 void DocTokenizer::setStateXRefItem()
1815 yyscan_t yyscanner = p->yyscanner;
1816 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1820 void DocTokenizer::setStateFile()
1822 yyscan_t yyscanner = p->yyscanner;
1823 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1827 void DocTokenizer::setStatePattern()
1829 yyscan_t yyscanner = p->yyscanner;
1830 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1831 yyextra->token->name = "";
1835 void DocTokenizer::setStateLink()
1837 yyscan_t yyscanner = p->yyscanner;
1838 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1842 void DocTokenizer::setStateCite()
1844 yyscan_t yyscanner = p->yyscanner;
1845 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1849 void DocTokenizer::setStateRef()
1851 yyscan_t yyscanner = p->yyscanner;
1852 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1856 void DocTokenizer::setStateInternalRef()
1858 yyscan_t yyscanner = p->yyscanner;
1859 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1863 void DocTokenizer::setStateText()
1865 yyscan_t yyscanner = p->yyscanner;
1866 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1870 void DocTokenizer::setStateSkipTitle()
1872 yyscan_t yyscanner = p->yyscanner;
1873 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1874 BEGIN(St_SkipTitle);
1877 void DocTokenizer::setStateAnchor()
1879 yyscan_t yyscanner = p->yyscanner;
1880 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1884 void DocTokenizer::setStateSnippet()
1886 yyscan_t yyscanner = p->yyscanner;
1887 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1888 yyextra->token->name="";
1892 void DocTokenizer::setStateSetScope()
1894 yyscan_t yyscanner = p->yyscanner;
1895 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1899 void DocTokenizer::setStateOptions()
1901 yyscan_t yyscanner = p->yyscanner;
1902 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1903 yyextra->token->name="";
1907 void DocTokenizer::setStateBlock()
1909 yyscan_t yyscanner = p->yyscanner;
1910 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1911 yyextra->token->name="";
1915 void DocTokenizer::setStateEmoji()
1917 yyscan_t yyscanner = p->yyscanner;
1918 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1919 yyextra->token->name="";
1923 void DocTokenizer::setStateIline()
1925 yyscan_t yyscanner = p->yyscanner;
1926 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1930 void DocTokenizer::cleanup()
1932 yyscan_t yyscanner = p->yyscanner;
1933 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1934 yy_delete_buffer( YY_CURRENT_BUFFER, yyscanner );
1937 void DocTokenizer::setInsidePre(bool b)
1939 yyscan_t yyscanner = p->yyscanner;
1940 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1941 yyextra->insidePre = b;
1944 void DocTokenizer::pushBackHtmlTag(const QCString &tag)
1946 yyscan_t yyscanner = p->yyscanner;
1947 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1948 QCString tagName = tag;
1949 int i,l = tagName.length();
1951 for (i=l-1;i>=0;i--)
1958 void DocTokenizer::startAutoList()
1960 yyscan_t yyscanner = p->yyscanner;
1961 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1962 yyextra->autoListLevel++;
1965 void DocTokenizer::endAutoList()
1967 yyscan_t yyscanner = p->yyscanner;
1968 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1969 yyextra->autoListLevel--;
1974 // printlex(yy_flex_debug, TRUE, __FILE__, g_fileName);
1975 // int retval = LOCAL_YY_DECL;
1976 // printlex(yy_flex_debug, FALSE, __FILE__, g_fileName);
1980 void DocTokenizer::setLineNr(int lineno)
1982 yyscan_t yyscanner = p->yyscanner;
1983 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1984 yyextra->yyLineNr = lineno;
1987 int DocTokenizer::getLineNr(void)
1989 yyscan_t yyscanner = p->yyscanner;
1990 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1991 return yyextra->yyLineNr;
1994 #if USE_STATE2STRING
1995 #include "doctokenizer.l.h"