737 {CMD}{CMD}[a-z_A-Z]+{B}* {
739 }
740<Comment>{CMD}{CMD}"~"[a-z_A-Z]* { // escaped command
742 }
743<Comment>{MAILADDR} { // mail address
745 }
746<Comment>"\""[^"\n]*"\"" { // quoted text
748 }
749<Comment>("\\"[a-z_A-Z]+)+"\\" { // directory (or chain of commands!)
751 }
752<Comment>"<"{DETAILEDHTML}{ATTR}">" { // HTML command that ends a brief description
754 size_t spacePos = htmlOpenTag.find(' ');
756 DString htmlTagName = htmlOpenTag.
mid(1,spacePos-1);
757
758 yyextra->htmlContextStack.emplace_back(htmlTagName,yyextra->inContext);
760 {
762 }
763
764 REJECT;
765 }
766<Comment>"</"{DETAILEDHTML}">" { // HTML command that ends a brief description
768 DString htmlTagName = htmlCloseTag.
mid(2,htmlCloseTag.length()-3);
769
770 if (!yyextra->htmlContextStack.empty() &&
771 yyextra->htmlContextStack.back().tagName==htmlTagName)
772 {
774 {
775
777 }
778 yyextra->htmlContextStack.pop_back();
779 }
780 REJECT;
781 }
782<Comment>"<"{DETAILEDHTMLOPT}">" { // HTML <code> command that ends a brief description
783
784 if (yyextra->current->lang==SrcLangExt::CSharp)
785 {
786 yyextra->CScode=true;
789 }
790 else
791 {
792
793 REJECT;
794 }
795 }
796<Comment>"<"{DETAILEDHTMLOPTEND}">" { // HTML command that ends a brief description
797 if (yyextra->CScode)
798 {
800 yyextra->CScode=false;
801 }
802 else
803 {
804 yyextra->CScode=false;
805
806 REJECT;
807 }
808 }
809<Comment>"<"{DETAILEDHTMLOPT}{ATTR}">" { // HTML <code> command that ends a brief description
810
811 if (yyextra->current->lang==SrcLangExt::CSharp)
812 {
814 }
815
816 REJECT;
817 }
818<Comment>"<"{DETAILS}{ATTR}">" { // start of a HTML style details description
819 yyextra->htmlDetailsStack.push_back(0);
820 yyextra->htmlContextStack.emplace_back("details",yyextra->inContext);
822 {
824 }
826 }
827<Comment>"</"{DETAILS}">" { // end of a HTML style details description
828 if (!yyextra->htmlDetailsStack.empty())
829 {
830 yyextra->htmlDetailsStack.pop_back();
831 }
832 if (!yyextra->htmlContextStack.empty() &&
833 yyextra->htmlContextStack.back().tagName=="details")
834 {
836 {
837
839 }
840 yyextra->htmlContextStack.pop_back();
841 }
843 }
844<Comment>"<"{AHTML} { // potential start of HTML anchor, see issue 9200
845 yyextra->htmlAnchorStr = yytext;
846 yyextra->htmlAnchor = false;
847 BEGIN(HtmlA);
848 }
849<HtmlA>{ANCHTML} { // only labels that can be converted to doxygen anchor
850 yyextra->htmlAnchorStr += yytext;
852 size_t s=tag.find("=");
853 char c=tag[s+1];
855 if (c=='\'' || c=='"')
856 {
857 size_t e=tag.find(c,s+2);
859 {
860 id=tag.mid(s+2,e-s-2);
862 }
863 }
864 else
865 {
866 id=tag.mid(s+1);
868 }
869 if (!id.empty() && !yyextra->htmlAnchor)
870 {
871
875 yyextra->htmlAnchor = true;
876 }
877 }
878<HtmlA>("\""[^\n\"]*"\""|"'"[^\n']*"'") {
879 yyextra->htmlAnchorStr += yytext;
880 }
881<HtmlA>">"|"/>" {
882 if (!yyextra->htmlAnchor)
883 {
884 addOutput(yyscanner,yyextra->htmlAnchorStr);
886 }
887 else
888 {
889 if (yyleng == 1)
890 {
892 }
893 }
894 BEGIN(Comment);
895 }
896<HtmlA>{DOCNL} { // newline
897 yyextra->htmlAnchorStr += yytext;
898 if (*yytext == '\n') yyextra->lineNr++;
899 }
900<HtmlA>. { // catch-all for anything else
901 yyextra->htmlAnchorStr += yytext;
902 }
903<Comment>"<"{SUMMARY}">" { // start of a .NET XML style brief description
904 if (yyextra->htmlDetailsStack.empty())
905 {
907 }
908 else
909 {
911 }
912 }
913<Comment>"<"{REMARKS}">" { // start of a .NET XML style detailed description
916 }
917<Comment>"</"{SUMMARY}">" { // start of a .NET XML style detailed description
918 if (!yyextra->htmlDetailsStack.empty())
919 {
921 }
922 else
923 {
925 }
926 }
927<Comment>"</"{REMARKS}">" { // end of a brief or detailed description
930 }
931<Comment>"<"{CAPTION}{ATTR}">" {
933 size_t s=tag.find("id=");
935 {
936 char c=tag[s+3];
937 if (c=='\'' || c=='"')
938 {
939 size_t e=tag.find(c,s+4);
941 {
944 }
945 }
946 }
948 }
949<Comment>"<"{PRE}{ATTR}">" {
950 yyextra->insidePre=true;
952 }
953<Comment>"</"{PRE}">" {
954 yyextra->insidePre=false;
956 }
957<Comment>{RCSTAG} { // RCS tag which end a brief description
959 REJECT;
960 }
961<Comment>"<!--" {
962 BEGIN(HtmlComment);
963 }
964<Comment>"<!\[CDATA\[" {
965 BEGIN(CdataSection);
966 }
967<Comment>{B}*{CMD}"endinternal"{B}* {
969 if (!yyextra->inInternalDocs)
970 warn(yyextra->fileName,yyextra->lineNr,
971 "found \\endinternal without matching \\internal"
972 );
973 yyextra->inInternalDocs = false;
974 }
975<Comment>{B}*"\\ilinebr "{B}* { // preserve spacing around \\ilinebr
977 }
978<Comment>(\n|"\\ilinebr ")/({B}*(\n|{IFILELINE}?"\\ilinebr "))+ { // at least one blank line (or blank line command)
980 {
982 }
983 else
984 {
985 REJECT;
986 }
987 }
988<Comment>{B}*{CMD}[a-z_A-Z]+"{"[^}]*"}"{B}* |
989<Comment>{B}*{CMD}[a-z_A-Z]+{B}* { // potentially interesting command
990
992 size_t idx = fullMatch.
find(
'{');
993
994 if ((idx !=
DString::npos) && (idx > 1) && (yytext[idx-1] ==
'f') && (yytext[idx-2] ==
'\\' || yytext[idx-2] ==
'@')) REJECT;
1000 {
1002 }
1003 else
1004 {
1008 }
1010
1012 {
1013 int i=0;
1014 while (yytext[i]==' ' || yytext[i]=='\t') i++;
1015 yyextra->spaceBeforeCmd = fullMatch.
left(i);
1018 !(yyextra->inContext==
OutputXRef && cmdName==
"parblock"))
1019 {
1020 yyextra->briefEndsAtDot=false;
1022
1024 }
1025
1026 if (it->second.handler && it->second.handler(yyscanner, cmdName, optList))
1027 {
1028
1029
1030
1031 yyextra->parseMore=true;
std::vector< std::string > StringVector
StringVector split(const std::string &s, const std::string &delimiter)
split input string s by string delimiter delimiter.
1032
1033 yyextra->inputPosition=yyextra->prevPosition + (int)(yy_bp - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf);
1035 }
1036 else if (it->second.handler==nullptr)
1037 {
1038
1039
1041 }
1042 }
1043 else
1044 {
1046 }
1047 }
1048<Comment>{B}*({CMD}{CMD})"f"[$\[{] { // escaped formula command
1050 }
1051<Comment>{B}*{CMD}"~"[a-z_A-Z-]* { // language switch command
1053 if (!langId.
empty() &&
1055 {
1057 {
1058 warn(yyextra->fileName,yyextra->lineNr,
1060 }
1061 BEGIN(SkipLang);
1062 }
1063 }
#define Config_getEnumAsString(name)
#define Config_isAvailableEnum(name, value)
int dstricmp(const char *s1, const char *s2)
1064<Comment>{B}*{CMD}"f{"[^}\n]+"}"("{"?) { // start of a formula with custom environment
1066 yyextra->formulaText="";
1067 yyextra->formulaPreText="\\begin";
1068 yyextra->formulaPostText="";
1070 if (yyextra->formulaEnv.at(yyextra->formulaEnv.length()-1)=='{')
1071 {
1072
1073 yyextra->formulaEnv=yyextra->formulaEnv.left(yyextra->formulaEnv.length()-1);
1074 }
1075 yyextra->formulaPreText+=yyextra->formulaEnv;
1076 yyextra->formulaNewLines=0;
1077 BEGIN(ReadFormulaLong);
1078 }
1079<Comment>{B}*{CMD}"f$" { // start of a inline formula
1080 yyextra->formulaText="";
1081 yyextra->formulaPreText="$";
1082 yyextra->formulaPostText="";
1083 yyextra->formulaNewLines=0;
1084 BEGIN(ReadFormulaShort);
1085 }
1086<Comment>{B}*{CMD}"f(" { // start of a inline formula
1087 yyextra->formulaText="";
1088 yyextra->formulaPreText="";
1089 yyextra->formulaPostText="";
1090 yyextra->formulaNewLines=0;
1091 BEGIN(ReadFormulaRound);
1092 }
1093<Comment>{B}*{CMD}"f[" { // start of a block formula
1095 yyextra->formulaText="";
1096 yyextra->formulaPreText="\\[";
1097 yyextra->formulaPostText="";
1098 yyextra->formulaNewLines=0;
1099 BEGIN(ReadFormulaLong);
1100 }
1101<Comment>{B}*{CMD}"{" { // begin of a group
1102
1103 yyextra->docGroup.open(yyextra->current,yyextra->fileName,yyextra->lineNr);
1104 }
1105<Comment>{B}*{CMD}"}" { // end of a group
1106
1107 yyextra->docGroup.close(yyextra->current,yyextra->fileName,yyextra->lineNr,true);
1108 yyextra->docGroup.clearHeader();
1109 yyextra->parseMore=true;
1110 yyextra->needNewEntry = true;
1111 yyextra->inputPosition=yyextra->prevPosition + (int)(yy_bp - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf) + (int)strlen(yytext);
1113 }
1114<Comment>{B}*{CMD}[$@\\&~<>#%] { // escaped character
1116 }
1117<Comment>[a-z_A-Z]+ { // normal word
1119 }
1120<Comment>^{B}*"."{Bopt}/\n { // explicit end autolist: e.g " ."
1122 }
1123<Comment>^{B}*[1-9][0-9]*"."{B}+ |
1124<Comment>^{B}*[*+]{B}+ { // start of autolist
1125 if (!yyextra->markdownSupport)
1126 {
1127 REJECT;
1128 }
1129 else
1130 {
1132 {
1133 yyextra->briefEndsAtDot=false;
1135 }
1137 }
1138 }
1139<Comment>^{B}*"-"{B}+ { // start of autolist
1141 {
1142 yyextra->briefEndsAtDot=false;
1144 }
1146 }
1147<Comment>^{B}*([\-:|]{B}*)*("--"|"---")({B}*[\-:|])*{Bopt}/\n { // horizontal line (dashed)
1149 }
1150<Comment>{CMD}"---" { // escaped mdash
1152 }
1153<Comment>{CMD}"--" { // escaped ndash
1155 }
1156<Comment>"---" { // mdash
1157 addOutput(yyscanner,yyextra->insidePre || yyextra->markdownSupport ? yytext :
"—");
1158 }
1159<Comment>"--" { // ndash
1160 addOutput(yyscanner,yyextra->insidePre || yyextra->markdownSupport ? yytext :
"–");
1161 }
1162<Comment>"-#"{B}+ { // numbered item
1164 {
1165 yyextra->briefEndsAtDot=false;
1167 }
1169 }
1170<Comment>[?!][a-z_A-Z0-9\(\)=<] |
1171<Comment>("."+)[a-z_A-Z0-9\)] { // . at start or in the middle of a word, or ellipsis
1172
1174 }
1175<Comment>{CMD}[\.?!] { // we have to be a bit careful with the special commands
1176
1178 }
1179<Comment>".\\"[ \t] { // . with escaped space.
1182 }
1183<Comment>"."[,:;] { // . with some puntuations such as "e.g.," or "e.g.:"
1185 }
1186<Comment>"...\\"[ \t] { // ellipsis with escaped space.
1188 }
1189<Comment>"..."/[^\.] { // ellipsis
1191 }
1192<Comment>".."[\.]?/[^ \t\n] { // internal ellipsis
1194 }
1195<Comment>(\n|"\\ilinebr ")({B}*(\n|"\\ilinebr "))+ { // at least one blank line (or blank line command)
1197 {
1198
1200 yy_size_t i;
1201 for (i=0;i<(yy_size_t)yyleng;)
1202 {
1203 if (yytext[i]==
'\n')
addOutput(yyscanner,
'\n'),i++;
1204 else if (strncmp(yytext+i,
"\\ilinebr ",9)==0)
addOutput(yyscanner,
"\\ilinebr "),i+=9;
1205 else i++;
1206 }
1207 }
1209 {
1210 yy_size_t i;
1211 for (i=0;i<(yy_size_t)yyleng;)
1212 {
1213 if (yytext[i]==
'\n')
addOutput(yyscanner,
'\n'),i++;
1214 else if (strncmp(yytext+i,
"\\ilinebr ",9)==0)
addOutput(yyscanner,
"\\ilinebr "),i+=9;
1215 else i++;
1216 }
1218 }
1219 else
1220 {
1221
1223 }
1225 }
1226<Comment>"."[?!] |
1227<Comment>[\.?!] { // potential end of a JavaDoc style comment
1229 if (yyextra->briefEndsAtDot)
1230 {
1232 yyextra->briefEndsAtDot=false;
1233 }
1234 }
1235<Comment>{DOCNL} { // newline
1237 if (*yytext == '\n') yyextra->lineNr++;
1238 }
1239<Comment>"<"[/]?{TABLEDEL}">" { // In case in xrefitem type some special handling is required
1241 {
1244 }
1245 else
1246 {
1247 REJECT;
1248 }
1249 }
1250<Comment>. { // catch-all for anything else
1252 }
1253
1254
1255
1256
1257<HtmlComment>"---"[!]?">"{B}* {
1258 warn(yyextra->fileName,yyextra->lineNr,
1259 "incorrect HTML end comment --->"
1260 );
1261 }
1262<HtmlComment>"--"[!]?">"{B}* { BEGIN( Comment ); }
1263<HtmlComment>{DOCNL} {
1264 if (*yytext=='\n')
1265 {
1266 yyextra->lineNr++;
1268 }
1269 }
1270<HtmlComment>[^\\\n\-]+ { // ignore unimportant characters
1271 }
1272<HtmlComment>. { // ignore every else
1273 }
1274
1275<CdataSection>"\]\]>" {
1276 BEGIN( Comment );
1277 }
1278<CdataSection>{DOCNL} {
1280 if (*yytext=='\n') yyextra->lineNr++;
1281 }
1282<CdataSection>[<>&] { // the special XML characters for iwhich the CDATA section is especially used
1285 }
1286<CdataSection>[^\\\n\]<>&]+ {
1288 }
1289<CdataSection>. {
1291 }
1292
1293
1294
1295<ReadFormulaShort,ReadFormulaShortSection>{CMD}"f$" { // end of inline formula
1296 yyextra->formulaPostText+="$";
1299 if (YY_START == ReadFormulaShort)
1300 {
1301 BEGIN(Comment);
1302 }
1303 else
1304 {
1305 yyextra->sectionTitle+= " "+form;
1306 BEGIN(SectionTitle);
1307 }
1308 }
1309<ReadFormulaRound,ReadFormulaRoundSection>{CMD}"f)" { // end of inline formula
1312 if (YY_START == ReadFormulaRound)
1313 {
1314 BEGIN(Comment);
1315 }
1316 else
1317 {
1318 yyextra->sectionTitle+= " "+form;
1319 BEGIN(SectionTitle);
1320 }
1321 }
1322<ReadFormulaLong>{CMD}"f]" { // end of block formula
1323 yyextra->formulaPostText+="\\]";
1325 BEGIN(Comment);
1326 }
1327<ReadFormulaLong>{CMD}"f}" { // end of custom env formula
1328 yyextra->formulaPostText+="\\end";
1329 yyextra->formulaPostText+=yyextra->formulaEnv;
1331 BEGIN(Comment);
1332 }
1333<ReadFormulaLong,ReadFormulaShort,ReadFormulaShortSection,ReadFormulaRound,ReadFormulaRoundSection>[^\\@\n]+ { // any non-special character
1334 yyextra->formulaText+=yytext;
1335 }
1336<ReadFormulaLong,ReadFormulaShort,ReadFormulaShortSection,ReadFormulaRound,ReadFormulaRoundSection>\n { // new line
1337 yyextra->formulaNewLines++;
1338 yyextra->formulaText+=*yytext;
1339 yyextra->lineNr++;
1340 addIline(yyscanner,yyextra->lineNr);
1341 }
1342<ReadFormulaLong,ReadFormulaShort,ReadFormulaShortSection,ReadFormulaRound,ReadFormulaRoundSection>. { // any other character
1343 yyextra->formulaText+=*yytext;
1344 }
1345
1346
1347
1348<EnumDocArg1>{SCOPEID} { // handle argument
1350 yyextra->current->name = yytext;
1351 BEGIN( Comment );
1352 }
1353<EnumDocArg1>{LC} { // line continuation
1354 yyextra->lineNr++;
1356 }
1357<EnumDocArg1>{DOCNL} { // missing argument
1358 warn(yyextra->fileName,yyextra->lineNr,
1359 "missing argument after '\\enum'."
1360 );
1362 BEGIN( Comment );
1363 }
1364<EnumDocArg1>. { // ignore other stuff
1365 }
1366
1367
1368
1369<NameSpaceDocArg1>{SCOPENAME} { // handle argument
1373 BEGIN( Comment );
1374 }
DString substitute(const DString &s, const DString &src, const DString &dst)
substitute all occurrences of src in s by dst
DString removeRedundantWhiteSpace(const DString &s)
1375<NameSpaceDocArg1>{LC} { // line continuation
1376 yyextra->lineNr++;
1378 }
1379<NameSpaceDocArg1>{DOCNL} { // missing argument
1380 warn(yyextra->fileName,yyextra->lineNr,
1381 "missing argument after '\\namespace'."
1382 );
1384 BEGIN( Comment );
1385 }
1386<NameSpaceDocArg1>. { // ignore other stuff
1387 }
1388
1389
1390
1391<PackageDocArg1>{ID}("."{ID})* { // handle argument
1392 yyextra->current->name = yytext;
1393 BEGIN( Comment );
1394 }
1395<PackageDocArg1>{LC} { // line continuation
1396 yyextra->lineNr++;
1398 }
1399<PackageDocArg1>{DOCNL} { // missing argument
1400 warn(yyextra->fileName,yyextra->lineNr,
1401 "missing argument after \\package."
1402 );
1404
1405
1406 BEGIN( Comment );
1407 }
1408<PackageDocArg1>. { // ignore other stuff
1409 }
1410
1411
1412
1413<ConceptDocArg1>{SCOPEID} { // handle argument
1415 yyextra->current->name = yytext;
1416 BEGIN( Comment );
1417 }
1418<ConceptDocArg1>{LC} { // line continuation
1419 yyextra->lineNr++;
1421 }
1422<ConceptDocArg1>{DOCNL} { // missing argument
1423 warn(yyextra->fileName,yyextra->lineNr,
1424 "missing argument after '\\concept'."
1425 );
1427 BEGIN( Comment );
1428 }
1429<ConceptDocArg1>. { // ignore other stuff
1430 }
1431
1432
1433<ModuleDocArg1>{MODULE_ID} { // handle argument
1435 yyextra->current->name = yytext;
1436 BEGIN( Comment );
1437 }
1438<ModuleDocArg1>{LC} { // line continuation
1439 yyextra->lineNr++;
1441 }
1442<ModuleDocArg1>{DOCNL} { // missing argument
1443 warn(yyextra->fileName,yyextra->lineNr,
1444 "missing argument after '\\module'."
1445 );
1447 BEGIN( Comment );
1448 }
1449<ModuleDocArg1>. { // ignore other stuff
1450 }
1451
1452
1453
1454<ClassDocArg1>{SCOPENAME}{TMPLSPEC} {
1458 BEGIN( ClassDocArg2 );
1459 }
1460<ClassDocArg1>{SCOPENAME} { // first argument
1463 yyextra->current->name =
substitute(yytext,
".",
"::");
1464 if (yyextra->current->section.isProtocolDoc())
1465 {
1466 yyextra->current->name+="-p";
1467 }
1468
1469 BEGIN( ClassDocArg2 );
1470 }
1471<CategoryDocArg1>{SCOPENAME}{B}*"("[^\)]+")" {
1474 yyextra->current->name =
substitute(yytext,
".",
"::");
1475 BEGIN( ClassDocArg2 );
1476 }
1477<ClassDocArg1,CategoryDocArg1>{LC} { // line continuation
1478 yyextra->lineNr++;
1480 }
1481<ClassDocArg1,CategoryDocArg1>{DOCNL} {
1482 warn(yyextra->fileName,yyextra->lineNr,
1483 "missing argument after '\\{}'.",yyextra->currentCmd
1484 );
1486 BEGIN( Comment );
1487 }
1488<ClassDocArg1,CategoryDocArg1>. { // ignore other stuff
1489 }
1490
1491<ClassDocArg2>{DOCNL} {
1493 BEGIN( Comment );
1494 }
1495<ClassDocArg2>{FILE}|"<>" { // second argument; include file
1496 yyextra->current->includeFile = yytext;
1497 BEGIN( ClassDocArg3 );
1498 }
1499<ClassDocArg2>{LC} { // line continuation
1500 yyextra->lineNr++;
1502 }
1503<ClassDocArg2>. { // ignore other stuff
1504 }
1505
1506<ClassDocArg3>[<"]?{FILE}?[">]? { // third argument; include file name
1507 yyextra->current->includeName = yytext;
1508 BEGIN( Comment );
1509 }
1510<ClassDocArg3>{LC} { // line continuation
1511 yyextra->lineNr++;
1513 }
1514<ClassDocArg3>{DOCNL} {
1515
1517 BEGIN( Comment );
1518 }
1519<ClassDocArg3>. { // ignore other stuff
1520 }
1521
1522
1523
1524<GroupDocArg1>{LABELID}(".html"|".xhtml")? { // group name
1525 yyextra->current->name = yytext;
1526
1527
1528
1529 if (yyextra->current->name.endsWith(".html"))
1530 {
1531 yyextra->current->name=yyextra->current->name.left(yyextra->current->name.length()-5);
1532 }
1533 else if (yyextra->current->name.endsWith(".xhtml"))
1534 {
1535 yyextra->current->name=yyextra->current->name.left(yyextra->current->name.length()-6);
1536 }
1537 yyextra->current->type.clear();
1538 BEGIN(GroupDocArg2);
1539 }
1540<GroupDocArg1>"\\"{B}*"\n" { // line continuation
1541 yyextra->lineNr++;
1543 }
1544<GroupDocArg1>{DOCNL} { // missing argument!
1545 warn(yyextra->fileName,yyextra->lineNr,
1546 "missing group name after {}",
1547 yyextra->current->groupDocCmd()
1548 );
1549
1550
1552 BEGIN( Comment );
1553 }
1554<GroupDocArg1>. { // ignore other stuff
1555 }
1556<GroupDocArg2>"\\"{B}*"\n" { // line continuation
1557 yyextra->lineNr++;
1559 }
1560<GroupDocArg2>[^\n\\]+ { // title (stored in type)
1561 yyextra->current->type += yytext;
1562 }
1563<GroupDocArg2>{DOCNL}+ {
1564 yyextra->current->type = yyextra->current->type.stripWhiteSpace();
1566 yyextra->current->type.empty()
1567 )
1568 {
1569 warn(yyextra->fileName,yyextra->lineNr,
1570 "missing title after "
1571 "\\defgroup {}", yyextra->current->name
1572 );
1573 }
1575 int extraLineNr = 0;
1577 {
1578 for (int i = 0; i < yyleng; i++)
1579 {
1580 if (yytext[i]=='\n') extraLineNr++;
1581 }
1582 }
1583
1584
1586 {
1587 addOutput(yyscanner,
" \\ifile \""+ yyextra->fileName);
1588 addOutput(yyscanner,
"\" \\iline " +
DString().setNum(yyextra->lineNr + extraLineNr) +
" \\ilinebr ");
1589 }
1590 BEGIN( Comment );
1591 }
1592<GroupDocArg2>. { // title (stored in type)
1593 yyextra->current->type += yytext;
1594 }
1595
1596
1597
1598<PageDocArg1>[^\n]*"\\ilinebr @ianchor"\{[^\]\n]*\}{B}{FILE} { // special case where the Markdown processor has rewritten
1599
1600
1602 size_t start = text.
find(
'{');
1603 size_t end = text.
find(
'}',start+1);
1604 yyextra->current->name = text.
mid(
end+2);
1605 size_t istart = yyextra->current->name.
find(
"\\ilinebr");
1607 {
1608 DString rest = yyextra->current->name.
mid(istart);
1610 yyextra->current->name = yyextra->current->name.left(istart);
1611 }
1612 yyextra->current->args = text.
mid(start+1,
end-start-1);
1613
1614 BEGIN( PageDocArg2 );
1615 }
DirIterator end(const DirIterator &) noexcept
1616<PageDocArg1>{FILE} { // first argument; page name
1618 yyextra->current->args = "";
1619 BEGIN( PageDocArg2 );
1620 }
1621<PageDocArg1>{LC} { yyextra->lineNr++;
1623 }
1624<PageDocArg1>{DOCNL} {
1625 warn(yyextra->fileName,yyextra->lineNr,
1626 "missing argument after \\page."
1627 );
1629
1630
1631 BEGIN( Comment );
1632 }
1633<PageDocArg1>. { // ignore other stuff
1634 }
1635<PageDocArg2>{DOCNL} { // second argument; page title
1637
1638
1639 addOutput(yyscanner,
" \\ifile \""+ yyextra->fileName);
1640 addOutput(yyscanner,
"\" \\iline " +
DString().setNum(yyextra->lineNr) +
" \\ilinebr ");
1641 BEGIN( Comment );
1642 }
1643<PageDocArg2>{CMD}[<>] {
1644
1648 yyextra->current->args += tmp;
1649 }
1650<PageDocArg2>. {
1651 yyextra->current->args += yytext;
1652 }
1653
1654<ParamArg1>{ID}/{B}*"," {
1656 }
1657<ParamArg1>"," {
1659 }
1660<ParamArg1>{DOCNL} {
1661 if (*yytext=='\n') yyextra->lineNr++;
1663 }
1664<ParamArg1>{ID} {
1666 BEGIN( Comment );
1667 }
1668<ParamArg1>. {
1669 unput(yytext[0]);
1670 BEGIN( Comment );
1671 }
1672
1673
1674
1675<FileDocArg1>{DOCNL} { // no file name specified
1677
1678
1679 BEGIN( Comment );
1680 }
1681<FileDocArg1>{FILE} { // first argument; name
1683 BEGIN( Comment );
1684 }
1685<FileDocArg1>{LC} { yyextra->lineNr++;
1687 }
1688<FileDocArg1>. { // ignore other stuff
1689 }
1690
1691
1692
1693<XRefItemParam1>{LABELID} { // first argument
1694 yyextra->newXRefItemKey=yytext;
1696 BEGIN(XRefItemParam2);
1697 }
1698<XRefItemParam1>{LC} { // line continuation
1699 yyextra->lineNr++;
1701 }
1702<XRefItemParam1>{DOCNL} { // missing arguments
1703 warn(yyextra->fileName,yyextra->lineNr,
1704 "Missing first argument of \\xrefitem"
1705 );
1706 if (*yytext=='\n') yyextra->lineNr++;
1709 BEGIN( Comment );
1710 }
1711<XRefItemParam1>. { // ignore other stuff
1712 }
1713
1714<XRefItemParam2>"\""[^\n\"]*"\"" { // second argument
1716 BEGIN(XRefItemParam3);
1717 }
1718<XRefItemParam2>{LC} { // line continuation
1719 yyextra->lineNr++;
1721 }
1722<XRefItemParam2>{DOCNL} { // missing argument
1723 warn(yyextra->fileName,yyextra->lineNr,
1724 "Missing second argument of \\xrefitem"
1725 );
1726 if (*yytext=='\n') yyextra->lineNr++;
1729 BEGIN( Comment );
1730 }
1731<XRefItemParam2>. { // ignore other stuff
1732 }
1733
1734<XRefItemParam3>"\""[^\n\"]*"\"" { // third argument
1737 BEGIN( Comment );
1738 }
1739<XRefItemParam2,XRefItemParam3>{LC} { // line continuation
1740 yyextra->lineNr++;
1742 }
1743<XRefItemParam3>{DOCNL} { // missing argument
1744 warn(yyextra->fileName,yyextra->lineNr,
1745 "Missing third argument of \\xrefitem"
1746 );
1747 if (*yytext=='\n') yyextra->lineNr++;
1750 BEGIN( Comment );
1751 }
1752<XRefItemParam3>. { // ignore other stuff
1753 }
1754
1755
1756
1757
1758<RelatesParam1>({ID}("::"|"."))*{ID} { // argument
1759 yyextra->current->relates = yytext;
1760
1761
1762
1763
1764 BEGIN( Comment );
1765 }
1766<RelatesParam1>{LC} { // line continuation
1767 yyextra->lineNr++;
1769 }
1770<RelatesParam1>{DOCNL} { // missing argument
1771 warn(yyextra->fileName,yyextra->lineNr,
1772 "Missing argument of '\\{}' command",yyextra->currentCmd
1773 );
1775
1776
1777 BEGIN( Comment );
1778 }
1779<RelatesParam1>. { // ignore other stuff
1780 }
1781
1782
1783
1784<Qualifier>{LABELID} { // unquoted version, simple label
1785 yyextra->current->qualifiers.emplace_back(yytext);
1786 BEGIN( Comment );
1787 }
1788<Qualifier>"\""[^\"]*"\"" { // quotes version, add without quotes
1789 std::string inp(yytext);
1790 yyextra->current->qualifiers.push_back(inp.substr(1,yyleng-2));
1791 BEGIN( Comment );
1792 }
1793<Qualifier>{DOCNL} { // missing argument
1794 warn(yyextra->fileName,yyextra->lineNr,
1795 "Missing argument of '\\{}' command",yyextra->currentCmd
1796 );
1798 BEGIN( Comment );
1799 }
1800<Qualifier>. {
1801 warn(yyextra->fileName,yyextra->lineNr,
1802 "Argument of '\\{}' command should be quoted",yyextra->currentCmd
1803 );
1805 BEGIN( Comment );
1806 }
1807
1808<ILine>{LINENR}/[\\@\n\.] |
1809<ILine>{LINENR}{B} {
1810 bool ok = false;
1812 if (!ok)
1813 {
1814 warn(yyextra->fileName,yyextra->lineNr,
"Invalid line number '{}' for iline command",yytext);
1815 }
1816 else
1817 {
1818 yyextra->lineNr = nr;
1819 }
1821 if (YY_START == ILine)
1822 {
1823 BEGIN(Comment);
1824 }
1825 else
1826 {
1827 yyextra->sectionTitle+=yytext;
1828 BEGIN(SectionTitle);
1829 }
1830 }
int toInt(bool *ok=nullptr, int base=10) const
1831<ILine,ILineSection>. {
1833 if (YY_START == ILine)
1834 {
1835 BEGIN(Comment);
1836 }
1837 else
1838 {
1839 yyextra->sectionTitle+=yytext;
1840 BEGIN(SectionTitle);
1841 }
1842 }
1843
1844
1845<IRaise>{B}*[0-9]+/[\\@\n\.] |
1846<IRaise>{B}*[0-9]+{B} {
1847 bool ok = false;
1849 if (!ok)
1850 {
1851 warn(yyextra->fileName,yyextra->lineNr,
"Invalid level '{}' for iraise command",yytext);
1852 }
1853 else
1854 {
1855 yyextra->raiseLevel = nr;
1856 }
1857 BEGIN(Comment);
1858 }
1859<IRaise>. {
1860 unput(yytext[0]);
1861 BEGIN(Comment);
1862 }
1863
1864
1865<IRaisePrefix>{B}*"\""({LABELID})?"\"" {
1867 yyextra->raisePrefix = text.stripWhiteSpace().mid(1,text.length()-2);
1869 BEGIN(Comment);
1870 }
1871<IRaisePrefix>. {
1872 unput(yytext[0]);
1873 BEGIN(Comment);
1874 }
1875
1876
1877
1878
1879<IFile,IFileSection>{FILE} {
1882 if (yytext[0] == '\"') yyextra->fileName = text.mid(1,text.length()-2);
1883 else yyextra->fileName = yytext;
1884 if (YY_START == IFile)
1885 {
1886 BEGIN(Comment);
1887 }
1888 else
1889 {
1890 yyextra->sectionTitle+=yytext;
1891 BEGIN(SectionTitle);
1892 }
1893 }
1894
1895<LinkSection>[^\\@\n]* {
1896 yyextra->sectionTitle+=yytext;
1897 }
1898<LinkSection>{CMD}{CMD} {
1899 yyextra->sectionTitle+=yytext;
1900 }
1901<LinkSection>{DOCNL} {
1903 if (*yytext == '\n') yyextra->lineNr++;
1904 yyextra->sectionTitle+=yytext;
1905 }
1906<LinkSection>{CMD}"endlink" {
1907 yyextra->sectionTitle+=yytext;
1908 BEGIN(SectionTitle);
1909 }
1910<LinkSection>. {
1911 yyextra->sectionTitle+=yytext;
1912 }
1913<LinkSection><<EOF>> {
1914 warn(yyextra->fileName,yyextra->lineNr,
1915 "reached end of comment while inside a '\\link' command, missing '\\endlink' command"
1916 );
1918 }
1919
1920
1921<LineParam>{CMD}{CMD} { // escaped command
1923 }
1924<LineParam>{DOCNL} { // end of argument
1925
1926
1928 BEGIN( Comment );
1929 }
1930<LineParam>{LC} { // line continuation
1931 yyextra->lineNr++;
1933 }
1934<LineParam>({CMD}{CMD}){ID} { // escaped command
1936 }
1937<LineParam>. { // ignore other stuff
1939 }
1940
1941
1942
1943<SectionLabel>{LABELID} {
1944 yyextra->sectionLabel+=yytext;
1945 }
1946<SectionLabel>{CMD}"lineinfo"("{}")? {
1948 }
1949<SectionLabel>{CMD}"fileinfo"("{"[^}]*"}")? {
1950 FileInfo fi(yyextra->fileName.str());
1951 bool hasOption = false;
1953 if (yytext[yyleng-1] == '}')
1954 {
1959 for (const auto &opt_ : optList)
1960 {
1962 std::string opt = optStripped.
lower().
str();
1964 if (!result.
empty())
1965 {
1966 if (hasOption)
1967 {
1968 warn(yyextra->fileName,yyextra->lineNr,
"Multiple options specified with \\fileinfo, discarding '{}'", optStripped);
1969 }
1970 else
1971 {
1972 label = result;
1973 }
1974 hasOption = true;
1975 }
1976 else
1977 {
1978 warn(yyextra->fileName,yyextra->lineNr,
"Unknown option specified with \\fileinfo: '{}'", optStripped);
1979 }
1980 }
1981 }
1982 if (!hasOption)
1983 {
1985 {
1987 }
1988 else
1989 {
1990 label=yyextra->fileName;
1991 }
1992 }
1994 yyextra->sectionLabel+=label;
1995 }
1996<SectionLabel>{DOCNL} {
1997 yyextra->sectionTitle.clear();
1998 if (yyextra->sectionLabel.empty())
1999 {
2000 warn(yyextra->fileName,yyextra->lineNr,
2001 "\\section command has no label"
2002 );
2003 }
2004 else
2005 {
2006 yyextra->sectionLabel=yyextra->raisePrefix+yyextra->sectionLabel;
2007 addOutput(yyscanner,yyextra->sectionLabel.data());
2009 }
2010 if (*yytext=='\n') yyextra->lineNr++;
2012 BEGIN( Comment );
2013 }
2014<SectionLabel>. { // invalid character for section label
2015 if (yyextra->sectionLabel.empty())
2016 {
2017 warn(yyextra->fileName,yyextra->lineNr,
2018 "Invalid or missing section label"
2019 );
2020 BEGIN(Comment);
2021 }
2022 else
2023 {
2024 yyextra->sectionLabel=yyextra->raisePrefix+yyextra->sectionLabel;
2025 addOutput(yyscanner,yyextra->sectionLabel.data());
2026 yyextra->sectionTitle.clear();
2028 BEGIN(SectionTitle);
2029 }
2030 }
2031<SectionTitle>{STAopt}/"\n" { // end of section title
2034 BEGIN( Comment );
2035 }
2036<SectionTitle>{STopt}"\\\\ilinebr" { // escaped end of section title
2037 yyextra->sectionTitle+=yytext;
2038 }
2039<SectionTitle>{STopt}/"\\ilinebr" { // end of section title
2042 BEGIN( Comment );
2043 }
2044<SectionTitle>{B}*{CMD}"f$" {
2045 yyextra->formulaText="";
2046 yyextra->formulaPreText="$";
2047 yyextra->formulaPostText="";
2048 yyextra->formulaNewLines=0;
2049 BEGIN(ReadFormulaShortSection);
2050 }
2051<SectionTitle>{B}*{CMD}"f(" { // start of a inline formula
2052 yyextra->formulaText="";
2053 yyextra->formulaPreText="";
2054 yyextra->formulaPostText="";
2055 yyextra->formulaNewLines=0;
2056 BEGIN(ReadFormulaRoundSection);
2057 }
2058<SectionTitle>{B}*{CMD}"~"[a-z_A-Z-]* | // language switch command
2059<SectionTitle>{B}*{CMD}"f"[\[{] { // block formula
2063 warn(yyextra->fileName,yyextra->lineNr,
2064 "'\\{}' command is not allowed in section title, ending section title.",
2066 );
2068 BEGIN(Comment);
2069 }
2070<SectionTitle>{LC} { // line continuation
2071 yyextra->lineNr++;
2073 }
2074<SectionTitle>[^\n@\\]* { // any character without special meaning
2075 yyextra->sectionTitle+=yytext;
2077 }
2078<SectionTitle>{B}*{CMD}{CMD} {
2079 yyextra->sectionTitle+=yytext;
2081 }
2082<SectionTitle>{B}*{CMD}[a-z_A-Z]+"{"[^}]*"}"{B}* |
2083<SectionTitle>{B}*{CMD}[a-z_A-Z]+{B}* { // handling command in section title
2085 size_t idx = fullMatch.
find(
'{');
2086
2087 if ((idx !=
DString::npos) && (idx > 1) && (yytext[idx-1] ==
'f') && (yytext[idx-2] ==
'\\' || yytext[idx-2] ==
'@')) REJECT;
2093 {
2095 }
2096 else
2097 {
2101 }
2104 {
2105 switch (it->second.sectionHandling)
2106 {
2108 {
2109 int i=0;
2110 while (yytext[i]==' ' || yytext[i]=='\t') i++;
2111 yyextra->sectionTitle+=fullMatch.
left(i);
2112 yyextra->sectionTitle+='@';
2113 yyextra->sectionTitle+=fullMatch.
mid(i);
2117 warn(yyextra->fileName,yyextra->lineNr,
2118 "'\\{}' command is not allowed in section title, escaping command.",cmdName
2119 );
2120 }
2121 break;
2123 {
2126 warn(yyextra->fileName,yyextra->lineNr,
2127 "'\\{}' command is not allowed in section title, ending section title.",cmdName
2128 );
2130 BEGIN(Comment);
2131 }
2132 break;
2134 {
2135 if (cmdName == "fileinfo")
2136 {
2137 int i=0;
2138 while (yytext[i]==' ' || yytext[i]=='\t') i++;
2139 yyextra->sectionTitle+=fullMatch.
left(i);
2143 {
2144 yyextra->sectionTitle+=fullMatch.
mid(i+9);
2146 }
2147 else
2148 {
2149 yyextra->sectionTitle+=fullMatch.
mid(idxEnd+1);
2151 }
2152 }
2153 else if (cmdName == "lineinfo")
2154 {
2155 int i=0;
2156 while (yytext[i]==' ' || yytext[i]=='\t') i++;
2157 yyextra->sectionTitle+=fullMatch.
left(i);
2159 yyextra->sectionTitle+=' ';
2160 yyextra->sectionTitle+=fullMatch.
mid(i+9);
2165 }
2166 else if (cmdName == "raisewarning")
2167 {
2168 yyextra->raiseWarning = "";
2169 BEGIN(RaiseWarningSection);
2170 }
2171 else if (cmdName == "noop")
2172 {
2174 BEGIN(Noop);
2175 }
2176 else if (cmdName == "cite")
2177 {
2178 yyextra->sectionTitle+=yytext;
2180 BEGIN(CiteLabelSection);
2181 }
2182 else if (cmdName == "iline")
2183 {
2184 yyextra->sectionTitle+=yytext;
2186 BEGIN(ILineSection);
2187 }
2188 else if (cmdName == "ifile")
2189 {
2190 yyextra->sectionTitle+=yytext;
2192 BEGIN(IFileSection);
2193 }
2194 else if ((cmdName == "anchor") || (cmdName == "ianchor"))
2195 {
2197 if (optList.empty())
2198 {
2199 yyextra -> anchorTitle = "";
2200 }
2201 else
2202 {
2204 yyextra -> anchorTitle =
join(optList,
" ");
2205 }
2207 BEGIN(AnchorLabelSection);
2208 }
2209 else if (cmdName == "link")
2210 {
2211 yyextra->sectionTitle+=yytext;
2212 BEGIN(LinkSection);
2213 }
2214 else
2215 {
2216 yyextra->sectionTitle+=yytext;
2217 warn(yyextra->fileName,yyextra->lineNr,
2218 "internal error '\\{}' command is to be replaced in section title.",cmdName
2219 );
2220 }
2221 }
2222 break;
2224 {
2225 yyextra->sectionTitle+=yytext;
2227 }
2228 break;
2229 }
2230 }
2231 else
2232 {
2233 yyextra->sectionTitle+=yytext;
2235 }
2236 }
2237<SectionTitle>. { // anything else
2238 yyextra->sectionTitle+=yytext;
2240 }
2241
2242
2243
2244<SubpageLabel>{FILE} { // first argument
2246
2247
2248 yyextra->current->extends.emplace_back(yytext,Protection::Public,Specifier::Normal);
2249 BEGIN(SubpageTitle);
2250 }
2251<SubpageLabel>{DOCNL} { // missing argument
2252 warn(yyextra->fileName,yyextra->lineNr,
2253 "\\subpage command has no label"
2254 );
2255 if (*yytext=='\n') yyextra->lineNr++;
2257 BEGIN( Comment );
2258 }
2259<SubpageLabel>. {
2260 unput(yytext[0]);
2261 BEGIN( Comment );
2262 }
2263<SubpageTitle>{DOCNL} { // no title, end command
2265 BEGIN( Comment );
2266 }
2267<SubpageTitle>[ \t]*"\""[^\"\n]*"\"" { // add title, end of command
2269 BEGIN( Comment );
2270 }
2271<SubpageTitle>. { // no title, end of command
2272 unput(*yytext);
2273 BEGIN( Comment );
2274 }
2275
2276
2277
2278<AnchorLabel,AnchorLabelSection>{LABELID} { // found argument
2279 DString lbl = yyextra->raisePrefix+yytext;
2280 addAnchor(yyscanner,lbl, yyextra->anchorTitle);
2282 if (YY_START == AnchorLabel)
2283 {
2284 BEGIN(Comment);
2285 }
2286 else
2287 {
2288 BEGIN(SectionTitle);
2289 }
2290 }
2291<AnchorLabel,AnchorLabelSection>{DOCNL} { // missing argument
2292 warn(yyextra->fileName,yyextra->lineNr,
2293 "\\anchor command has no label"
2294 );
2295 if (*yytext=='\n') yyextra->lineNr++;
2297 if (YY_START == AnchorLabel)
2298 {
2299 BEGIN(Comment);
2300 }
2301 else
2302 {
2303 BEGIN(SectionTitle);
2304 }
2305 }
2306<AnchorLabel,AnchorLabelSection>. { // invalid character for anchor label
2307 warn(yyextra->fileName,yyextra->lineNr,
2308 "Invalid or missing anchor label"
2309 );
2311 if (YY_START == AnchorLabel)
2312 {
2313 BEGIN(Comment);
2314 }
2315 else
2316 {
2317 BEGIN(SectionTitle);
2318 }
2319 }
2320
2321
2322
2323<RequirementLabel>{REQID} { // found argument
2324 yyextra->current->name = yytext;
2325 yyextra->current->type.clear();
2326 BEGIN( RequirementTitle );
2327 }
2328<SatisfiesLabel>{REQID} { // found argument
2329 yyextra->reqId = yytext;
2330 yyextra->reqTitle.clear();
2331 BEGIN( SatisfiesTitle );
2332 }
2333<VerifiesLabel>{REQID} { // found argument
2334 yyextra->reqId = yytext;
2335 yyextra->reqTitle.clear();
2336 BEGIN( VerifiesTitle );
2337 }
2338<RequirementLabel,SatisfiesLabel,VerifiesLabel>"\\"{B}*"\n" { // line continuation
2339 yyextra->lineNr++;
2341 }
2342<RequirementLabel,SatisfiesLabel,VerifiesLabel>{DOCNL} { // missing argument
2343 warn(yyextra->fileName,yyextra->lineNr,
2344 "missing requirement ID after \\requirement command"
2345 );
2347 BEGIN( Comment );
2348 }
2349<RequirementLabel,SatisfiesLabel,VerifiesLabel>. { // invalid character for requirement label
2350 }
2351
2352<RequirementTitle,SatisfiesTitle,VerifiesTitle>"\\"{B}*"\n" { // line continuation
2353 yyextra->lineNr++;
2355 }
2356<RequirementTitle>[^\n\\]+ { // title (stored in type)
2357 yyextra->current->type += yytext;
2358 }
2359<SatisfiesTitle,VerifiesTitle>[^\n\\@]+ { // title (stored in type)
2360 yyextra->reqTitle += yytext;
2361 }
2362<RequirementTitle>({CMD}("verifies"|"satisfies"|"requirement"){B}+)|{DOCNL}+ {
2363 yyextra->current->type = yyextra->current->type.stripWhiteSpace();
2366 BEGIN( Comment );
2367 }
2368<SatisfiesTitle>({CMD}("verifies"|"satisfies"|"requirement"){B}+)|{DOCNL}+ {
2369 yyextra->reqTitle = yyextra->reqTitle.stripWhiteSpace();
2371 if (yyextra->current->section.isRequirementDoc())
2372 {
2373 warn(yyextra->fileName,yyextra->lineNr,
2374 "@satisfies command is not allowed in documentation of a requirement. Put in at the place where the requirement is implemented."
2375 );
2376 }
2377 else
2378 {
2380 yyextra->reqId,
2381 yyextra->reqTitle,
2382 yyextra->fileName,
2383 yyextra->lineNr);
2384 }
2385 BEGIN( Comment );
2386 }
2387<VerifiesTitle>({CMD}("verifies"|"satisfies"|"requirement"){B}+)|{DOCNL}+ {
2388 yyextra->reqTitle = yyextra->reqTitle.stripWhiteSpace();
2390 if (yyextra->current->section.isRequirementDoc())
2391 {
2392 warn(yyextra->fileName,yyextra->lineNr,
2393 "@verifies command is not allowed in documentation of a requirement. Put in at the place where the requirement is tested."
2394 );
2395 }
2396 else
2397 {
2399 yyextra->reqId,
2400 yyextra->reqTitle,
2401 yyextra->fileName,
2402 yyextra->lineNr);
2403 }
2404 BEGIN( Comment );
2405 }
2406<RequirementTitle>. { // title (stored in type)
2407 yyextra->current->type += yytext;
2408 }
2409<SatisfiesTitle,VerifiesTitle>. { // title (stored in reqTitle)
2410 yyextra->reqTitle += yytext;
2411 }
2412
2413
2414
2415
2416<FormatBlock>{CMD}("endverbatim"|"endiverbatim"|"endiliteral"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endrtfonly"|"endmanonly"|"enddot"|"endcode"|"endicode"|"endmsc"|"endmermaid")/{NW} { // possible ends
2418 if (&yytext[4]==yyextra->blockName)
2419 {
2420 BEGIN(Comment);
2421 }
2422 }
2423<FormatBlock>{CMD}"enduml" {
2425 if (yyextra->blockName=="startuml")
2426 {
2427 BEGIN(Comment);
2428 }
2429 }
2430<FormatBlock>[^ \@\*\/\\\n]* { // some word
2432 }
2433<FormatBlock>{DOCNL} { // new line
2434 if (*yytext=='\n') yyextra->lineNr++;
2436 }
2437<FormatBlock>{CCS} { // start of a C-comment
2438 if (!(yyextra->blockName=="code" || yyextra->blockName=="verbatim" ||
2439 yyextra->blockName=="icode" || yyextra->blockName=="iverbatim"||
2440 yyextra->blockName=="iliteral"
2441 )
2442 ) yyextra->commentCount++;
2444 }
2445<FormatBlock>{CCE} { // end of a C-comment
2447 if (!(yyextra->blockName=="code" || yyextra->blockName=="verbatim" ||
2448 yyextra->blockName=="icode" || yyextra->blockName=="iverbatim"||
2449 yyextra->blockName=="iliteral"
2450 )
2451 )
2452 {
2453 yyextra->commentCount--;
2454 if (yyextra->commentCount<0)
2455 {
2456 DString endTag =
"end"+yyextra->blockName;
2457 if (yyextra->blockName=="startuml") endTag="enduml";
2458 warn(yyextra->fileName,yyextra->lineNr,
2459 "found */ without matching /* while inside a \\{} block! Perhaps a missing \\{}?",
2460 yyextra->blockName,endTag);
2461 }
2462 }
2463 }
2464<FormatBlock>. {
2466 }
2467<FormatBlock><<EOF>> {
2468 DString endTag =
"end"+yyextra->blockName;
2469 if (yyextra->blockName=="startuml") endTag="enduml";
2470 warn(yyextra->fileName,yyextra->lineNr,
2471 "reached end of comment while inside a \\{} block; check for missing \\{} tag!",
2472 yyextra->blockName,endTag
2473 );
2475 }
2476
2477
2478
2479<GuardParam>{B}*"(" {
2480 yyextra->guardExpr=yytext;
2481 yyextra->roundCount=1;
2482 BEGIN(GuardExpr);
2483 }
2484<GuardExpr>[^()]* {
2485 yyextra->guardExpr+=yytext;
2487 }
2488<GuardExpr>"(" {
2489 yyextra->guardExpr+=yytext;
2490 yyextra->roundCount++;
2491 }
2492<GuardExpr>")" {
2493 yyextra->guardExpr+=yytext;
2494 yyextra->roundCount--;
2495 if (yyextra->roundCount==0)
2496 {
2498 }
2499 }
2500<GuardExpr>\n {
2501 warn(yyextra->fileName,yyextra->lineNr,
2502 "invalid expression '{}' for yyextra->guards",yyextra->guardExpr);
2503 unput(*yytext);
2504 BEGIN(GuardParam);
2505 }
2506<GuardParam>{B}*{CMD}doxyconfig{B}+{DOXYCFG} {
2508 }
2509<GuardParam>{B}*[a-z_A-Z0-9.\-]+({B}*{CMD}doxyconfig{B}+{DOXYCFG})? { // parameter of if/ifnot yyextra->guards
2511 }
2512<GuardParam>{DOCNL} { // end of argument
2513
2514
2518 }
2519<GuardParam>{LC} { // line continuation
2520 yyextra->lineNr++;
2522 }
2523<GuardParam>. { // empty condition
2524 unput(*yytext);
2526 }
2527<GuardParamEnd>{B}*{DOCNL} {
2529 yyextra->spaceBeforeIf.clear();
2531 BEGIN(Comment);
2532 }
2533<GuardParamEnd>{B}* {
2534 if (!yyextra->spaceBeforeIf.empty())
2535 {
2536 addOutput(yyscanner,yyextra->spaceBeforeIf);
2537 }
2538 yyextra->spaceBeforeIf.clear();
2540 BEGIN(Comment);
2541 }
2542<GuardParamEnd>. {
2543 unput(*yytext);
2545 BEGIN(Comment);
2546 }
2547
2548
2549
2550<SkipGuardedSection>{CMD}"ifnot"/{NW} {
2552 yyextra->guards->emplace(false);
2553 BEGIN( GuardParam );
2554 }
2555<SkipGuardedSection>{CMD}"if"/{NW} {
2557 yyextra->guards->emplace(false);
2558 BEGIN( GuardParam );
2559 }
2560<SkipGuardedSection>{CMD}"endif"/{NW} {
2561 if (yyextra->guards->empty())
2562 {
2563 warn(yyextra->fileName,yyextra->lineNr,
2564 "found \\endif without matching start command");
2565 BEGIN( Comment );
2566 }
2567 else
2568 {
2569 yyextra->guards->pop();
2570 if (yyextra->guards->empty())
2571 {
2572 BEGIN( GuardParamEnd );
2573 }
2574 else
2575 {
2576 if (yyextra->guards->top().isEnabled())
2577 {
2578 BEGIN( GuardParamEnd );
2579 }
2580 else
2581 {
2582 BEGIN( SkipGuardedSection );
2583 }
2584 }
2585 }
2586 }
2587<SkipGuardedSection>{CMD}"else"/{NW} {
2588 if (yyextra->guards->empty())
2589 {
2590 warn(yyextra->fileName,yyextra->lineNr,
2591 "found \\else without matching start command");
2592 }
2593 else if (yyextra->guards->top().hasElse())
2594 {
2595 warn(yyextra->fileName,yyextra->lineNr,
2596 "found multiple \\else commands in same \\if construct");
2597 yyextra->guards->top().setEnabled(false);
2598 BEGIN( SkipGuardedSection );
2599 }
2600 else if (!yyextra->guards->top().parentVisible())
2601 {
2602 yyextra->guards->top().setEnabled(false);
2603 BEGIN( SkipGuardedSection );
2604 }
2605 else
2606 {
2607 yyextra->spaceBeforeIf = yyextra->spaceBeforeCmd;
2608 yyextra->guards->top().setElse();
2609 if (!yyextra->guards->top().parentVisible())
2610 {
2611 yyextra->guards->top().setEnabled(false);
2612 BEGIN( SkipGuardedSection );
2613 }
2614 else if (yyextra->guards->top().isEnabledFound())
2615 {
2616 yyextra->guards->top().setEnabled(false);
2617 BEGIN( SkipGuardedSection );
2618 }
2619 else
2620 {
2621 yyextra->guards->top().setEnabled(true);
2622 BEGIN( GuardParamEnd );
2623 }
2624 }
2625 }
2626<SkipGuardedSection>{CMD}"elseif"/{NW} {
2627 if (yyextra->guards->empty())
2628 {
2629 warn(yyextra->fileName,yyextra->lineNr,
2630 "found \\elseif without matching start command");
2631 }
2632 else if (yyextra->guards->top().hasElse())
2633 {
2634 warn(yyextra->fileName,yyextra->lineNr,
2635 "found \\elseif command after \\else command was given in \\if construct");
2637 yyextra->spaceBeforeIf = yyextra->spaceBeforeCmd;
2638 yyextra->guards->top().setEnabled(false);
2639 BEGIN( GuardParam );
2640 }
2641 else
2642 {
2644 yyextra->spaceBeforeIf = yyextra->spaceBeforeCmd;
2645 yyextra->guards->top().setEnabled(false);
2646 BEGIN( GuardParam );
2647 }
2648 }
2649<SkipGuardedSection>{DOCNL} { // skip line
2650 if (*yytext=='\n') yyextra->lineNr++;
2651
2652 }
2653<SkipGuardedSection>[^ \\@\n]+ { // skip non-special characters
2654 }
2655<SkipGuardedSection>{CMD}{CMD} |
2656<SkipGuardedSection>. { // any other character
2657 }
2658
2659
2660
2661
2662<SkipInternal>{DOCNL} { // skip line
2663 if (*yytext=='\n') yyextra->lineNr++;
2665 }
2666<SkipInternal>{CMD}"if"/[ \t] {
2667 yyextra->condCount++;
2668 }
2669<SkipInternal>{CMD}"ifnot"/[ \t] {
2670 yyextra->condCount++;
2671 }
2672<SkipInternal>{CMD}/"endif" {
2673 yyextra->condCount--;
2674 if (yyextra->condCount<0)
2675 {
2676 unput('\\');
2677 BEGIN(Comment);
2678 }
2679 }
2680<SkipInternal>{CMD}/"section"[ \t] {
2681 if (yyextra->sectionLevel>0)
2682 {
2683 unput('\\');
2684 BEGIN(Comment);
2685 }
2686 }
2687<SkipInternal>{CMD}/"subsection"[ \t] {
2688 if (yyextra->sectionLevel>1)
2689 {
2690 unput('\\');
2691 BEGIN(Comment);
2692 }
2693 }
2694<SkipInternal>{CMD}/"subsubsection"[ \t] {
2695 if (yyextra->sectionLevel>2)
2696 {
2697 unput('\\');
2698 BEGIN(Comment);
2699 }
2700 }
2701<SkipInternal>{CMD}/"paragraph"[ \t] {
2702 if (yyextra->sectionLevel>3)
2703 {
2704 unput('\\');
2705 BEGIN(Comment);
2706 }
2707 }
2708<SkipInternal>{CMD}/"subparagraph"[ \t] {
2709 if (yyextra->sectionLevel>4)
2710 {
2711 unput('\\');
2712 BEGIN(Comment);
2713 }
2714 }
2715<SkipInternal>{CMD}/"subsubparagraph"[ \t] {
2716 if (yyextra->sectionLevel>5)
2717 {
2718 unput('\\');
2719 BEGIN(Comment);
2720 }
2721 }
2722<SkipInternal>{CMD}"endinternal"[ \t]* {
2723 BEGIN(Comment);
2724 }
2725<SkipInternal>[^ \\@\n]+ { // skip non-special characters
2726 }
2727<SkipInternal>. { // any other character
2728 }
2729
2730
2731
2732
2733<NameParam>{DOCNL} { // end of argument
2734
2735
2737 BEGIN( Comment );
2738 }
2739<NameParam>{LC} { // line continuation
2740 yyextra->lineNr++;
2742 yyextra->docGroup.appendHeader(' ');
2743 }
2744<NameParam>. { // ignore other stuff
2745 yyextra->docGroup.appendHeader(*yytext);
2746 yyextra->current->name+=*yytext;
2747 }
2748
2749
2750<Noop>{DOCNL} { // end of argument
2751 if (*yytext=='\n')
2752 {
2753 yyextra->lineNr++;
2755 }
2756 BEGIN( Comment );
2757 }
2758<Noop>. { // ignore other stuff
2759 }
2760
2761<RaiseWarning,RaiseWarningSection>{DOCNL} { // end of argument
2763 "{}",yyextra->raiseWarning);
2764 yyextra->raiseWarning = "";
2765 if (*yytext=='\n') yyextra->lineNr++;
2767 if (YY_START == RaiseWarning)
2768 {
2769 BEGIN(Comment);
2770 }
2771 else
2772 {
2773 yyextra->sectionTitle+=yytext;
2774 BEGIN(SectionTitle);
2775 }
2776 }
#define warn_doc_error(file, line, fmt,...)
2777<RaiseWarning,RaiseWarningSection>. { // ignore other stuff
2778 yyextra->raiseWarning += yytext;
2779 }
2780
2781
2782<InGroupParam>{LABELID} { // group id
2783 yyextra->current->groups.emplace_back(
2785 );
2786 yyextra->inGroupParamFound=true;
2787 }
@ GROUPING_INGROUP
membership in group was defined by @ingroup
2788<InGroupParam>{DOCNL} { // missing argument
2789 if (!yyextra->inGroupParamFound)
2790 {
2791 warn(yyextra->fileName,yyextra->lineNr,
2792 "Missing group name for \\ingroup command"
2793 );
2794 }
2795
2796
2798 BEGIN( Comment );
2799 }
2800<InGroupParam>{LC} { // line continuation
2801 yyextra->lineNr++;
2803 }
2804<InGroupParam>. { // ignore other stuff
2806 }
2807
2808
2809
2810<FnParam>{DOCNL} { // end of argument
2811 if (yyextra->braceCount==0)
2812 {
2813 if (yyextra->functionProto.stripWhiteSpace().empty())
2814 {
2815 warn(yyextra->fileName,yyextra->lineNr,
2816 "missing argument after '\\{}'.",yyextra->currentCmd
2817 );
2818 }
2819 else
2820 {
2822 yyextra->langParser->parsePrototype(yyextra->functionProto);
2823 }
2825 BEGIN( Comment );
2826 }
2827 }
2828<FnParam>{LC} { // line continuation
2829 yyextra->lineNr++;
2830 yyextra->functionProto+=' ';
2831 }
2832<FnParam>[^@\\\n()]+ { // non-special characters
2833 yyextra->functionProto+=yytext;
2834 }
2835<FnParam>"(" {
2836 yyextra->functionProto+=yytext;
2837 yyextra->braceCount++;
2838 }
2839<FnParam>")" {
2840 yyextra->functionProto+=yytext;
2841 yyextra->braceCount--;
2842 }
2843<FnParam>. { // add other stuff
2844 yyextra->functionProto+=*yytext;
2845 }
2846
2847
2848
2849
2850
2851<OverloadParam>{DOCNL} { // end of argument
2852 if (*yytext=='\n') yyextra->lineNr++;
2853 if (yyextra->functionProto.stripWhiteSpace().empty())
2854 {
2857 }
2858 else
2859 {
2861 yyextra->langParser->parsePrototype(yyextra->functionProto);
2862 }
2863 BEGIN( Comment );
2864 }
virtual DString trOverloadText()=0
2865<OverloadParam>{LC} { // line continuation
2866 yyextra->lineNr++;
2867 yyextra->functionProto+=' ';
2868 }
2869<OverloadParam>. { // add other stuff
2870 yyextra->functionProto+=*yytext;
2871 }
2872
2873
2874
2875<InheritParam>({ID}("::"|"."))*{ID} { // found argument
2876 yyextra->current->extends.emplace_back(
2878 );
2879 BEGIN( Comment );
2880 }
2881<InheritParam>{DOCNL} { // missing argument
2882 warn(yyextra->fileName,yyextra->lineNr,
2883 "\\inherit command has no argument"
2884 );
2885 if (*yytext=='\n') yyextra->lineNr++;
2887 BEGIN( Comment );
2888 }
2889<InheritParam>. { // invalid character for anchor label
2890 warn(yyextra->fileName,yyextra->lineNr,
2891 "Invalid or missing name for \\inherit command"
2892 );
2893 BEGIN(Comment);
2894 }
2895
2896
2897
2898<ExtendsParam>({ID}("::"|"."))*{ID} { // found argument
2899 yyextra->current->extends.emplace_back(
2901 );
2902 BEGIN( Comment );
2903 }
2904<ExtendsParam>{DOCNL} { // missing argument
2905 warn(yyextra->fileName,yyextra->lineNr,
2906 "'\\{}' command has no argument",yyextra->currentCmd
2907 );
2908
2909
2911 BEGIN( Comment );
2912 }
2913<ExtendsParam>. { // ignore other stuff
2914 }
2915
2916
2917
2918<SkipLang>{CMD}"~"[a-zA-Z-]* { /* language switch */
2921 {
2922 warn(yyextra->fileName,yyextra->lineNr,
2924 }
2925 else if (langId.empty() ||
2927 {
2928 BEGIN(Comment);
2929 }
2930 }
2931<SkipLang>[^*@\\\n]* { /* any character not a *, @, backslash or new line */
2932 }
2933<SkipLang>{DOCNL} { /* new line in verbatim block */
2934 if (*yytext=='\n') yyextra->lineNr++;
2935 }
2936<SkipLang>. { /* any other character */
2937 }
2938
2939
2940
2941<CiteLabel,CiteLabelSection>{CITEID} { // found argument
2944 if (YY_START == CiteLabel)
2945 {
2946 BEGIN(Comment);
2947 }
2948 else
2949 {
2950 yyextra->sectionTitle+=yytext;
2951 BEGIN(SectionTitle);
2952 }
2953 }
2954<CiteLabel,CiteLabelSection>{DOCNL} { // missing argument
2955 warn(yyextra->fileName,yyextra->lineNr,
2956 "\\cite command has no label"
2957 );
2958
2959
2960 if (YY_START == CiteLabel)
2961 {
2963 BEGIN(Comment);
2964 }
2965 else
2966 {
2967 yyextra->sectionTitle+=yytext;
2969 BEGIN(SectionTitle);
2970 }
2971 }
2972<CiteLabel,CiteLabelSection>. { // invalid character for cite label
2973 warn(yyextra->fileName,yyextra->lineNr,
2974 "Invalid or missing cite label"
2975 );
2976 if (YY_START == CiteLabel)
2977 {
2978 BEGIN(Comment);
2979 }
2980 else
2981 {
2982 yyextra->sectionTitle+=yytext;
2983 BEGIN(SectionTitle);
2984 }
2985 }
2986
2987
2988
2989<CopyDoc><<EOF>> {
2991 addOutput(yyscanner,
" \\ilinebr\\ilinebr\\copydetails ");
2992 addOutput(yyscanner,yyextra->copyDocArg);
2994 BEGIN(Comment);
2995 }
2996<CopyDoc>"<"[/]?{TABLEDEL}">" {
2997 if (yyextra->braceCount==0)
2998 {
3000 addOutput(yyscanner,
" \\ilinebr\\ilinebr\\copydetails ");
3001 addOutput(yyscanner,yyextra->copyDocArg);
3003 BEGIN(Comment);
3004 }
3005 }
3006<CopyDoc>{DOCNL} {
3007 if (*yytext=='\n') yyextra->lineNr++;
3008 if (yyextra->braceCount==0)
3009 {
3011 addOutput(yyscanner,
" \\ilinebr\\ilinebr\\copydetails ");
3012 addOutput(yyscanner,yyextra->copyDocArg);
3014 BEGIN(Comment);
3015 }
3016 }
3017<CopyDoc>{LC} { // line continuation
3018 yyextra->lineNr++;
3019 }
3020<CopyDoc>[^@\\\n()<]+ { // non-special characters
3021 yyextra->copyDocArg+=yytext;
3023 }
3024<CopyDoc>"(" {
3025 yyextra->copyDocArg+=yytext;
3027 yyextra->braceCount++;
3028 }
3029<CopyDoc>")" {
3030 yyextra->copyDocArg+=yytext;
3032 yyextra->braceCount--;
3033 }
3034<CopyDoc>. {
3035 yyextra->copyDocArg+=yytext;
3037 }
3038
3039
3040<*>. { fprintf(stderr,"Lex scanner %s %sdefault rule for state %s: #%s#\n", __FILE__,!yyextra->fileName.empty() ? ("(" + yyextra->fileName +") ").data(): "",stateToString(YY_START),yytext);}
3041<*>\n { fprintf(stderr,"Lex scanner %s %sdefault rule newline for state %s.\n", __FILE__, !yyextra->fileName.empty() ? ("(" + yyextra->fileName +") ").data(): "",stateToString(YY_START));}
3042 */
3043
3044%%