381 {BS}[&]*{BS}!.*\n {
382 yyextra->lineCountPrepass ++;
383 }
384<Prepass>^{BS}\n { /* skip empty lines */
385 yyextra->lineCountPrepass ++;
386 }
387<*>^.*\n { // prepass: look for line continuations
388 yyextra->functionLine = false;
389
390 DBG_CTX((stderr,
"---%s", yytext));
391
394 if (indexEnd>=0 && yytext[indexEnd]!='&')
395 {
396 indexEnd=-1;
397 }
static int getAmpersandAtTheStart(const char *buf, int length)
398
399 if (indexEnd<0)
400 {
401 if (YY_START == Prepass)
402 {
403
404
405 yyextra->inputStringPrepass+=(const char*)(yytext+(indexStart+1));
406
407
408 pushBuffer(yyscanner,yyextra->inputStringPrepass);
409 yyextra->colNr = 0;
411 }
412 else
413 {
414 yyextra->colNr = 0;
415 REJECT;
416 }
417 }
418 else
419 {
420 if (YY_START != Prepass)
421 {
422 yyextra->comments.clear();
423 yyextra->inputStringPrepass=
DString();
424 yy_push_state(Prepass,yyscanner);
425 }
static void pushBuffer(yyscan_t yyscanner, const DString &buffer)
static void pop_state(yyscan_t yyscanner)
426
427 size_t length = yyextra->inputStringPrepass.length();
428
429
430 yyextra->inputStringPrepass+=(const char*)(yytext+(indexStart+1));
431 yyextra->lineCountPrepass ++;
432
433
434 truncatePrepass(yyscanner,
static_cast<int>(length) + indexEnd - indexStart - 1);
435 }
436 }
static void truncatePrepass(yyscan_t yyscanner, int index)
437
438
439
440<String>\"|\' { // string ends with next quote without previous backspace
441 if (yytext[0]!=yyextra->stringStartSymbol)
442 {
443 yyextra->colNr -= (int)yyleng;
444 REJECT;
445 }
446 if (yy_top_state(yyscanner) == Initialization ||
447 yy_top_state(yyscanner) == ArrayInitializer)
448 {
449 yyextra->initializer+=yytext;
450 }
452 }
453<String>[\x80-\xFF]* |
454<String>. { if (yy_top_state(yyscanner) == Initialization ||
455 yy_top_state(yyscanner) == ArrayInitializer)
456 {
457 yyextra->initializer+=yytext;
458 }
459 }
460<*>\"|\' { /* string starts */
461 if (YY_START == StrIgnore)
462 { yyextra->colNr -= (int)yyleng;
463 REJECT;
464 };
465 yy_push_state(YY_START,yyscanner);
466 if (yy_top_state(yyscanner) == Initialization ||
467 yy_top_state(yyscanner) == ArrayInitializer)
468 {
469 yyextra->initializer+=yytext;
470 }
471 yyextra->stringStartSymbol=yytext[0];
472 BEGIN(String);
473 }
474
475
476
477<*>"!"/([^<>\n]|"<ff>"|"<FF>") { if (YY_START == String || YY_START == DocCopyBlock)
478 { yyextra->colNr -= (int)yyleng;
479 REJECT;
480 }
481
482
483 if ((YY_START != StrIgnore) && (YY_START != String))
484 {
485 yy_push_state(YY_START,yyscanner);
486 BEGIN(StrIgnore);
487 yyextra->debugStr="*!";
488 DBG_CTX((stderr,
"start comment %d\n",yyextra->lineNr));
489 }
490 }
491<StrIgnore>.?/\n { pop_state(yyscanner); // comment ends with endline character
492 DBG_CTX((stderr,
"end comment %d %s\n",yyextra->lineNr,
qPrint(yyextra->debugStr)));
493 }
494<StrIgnore>[\x80-\xFF]* |
495<StrIgnore>. { yyextra->debugStr+=yytext; }
496
497
498
499
500<Start,ModuleBody,SubprogBody>"use"{BS_} {
501 if (YY_START == Start)
502 {
505 yy_push_state(ModuleBody,yyscanner);
506 }
507 yy_push_state(Use,yyscanner);
508 }
509<Use>{ID} {
510 DBG_CTX((stderr,
"using dir %s\n",yytext));
511 yyextra->current->name=yytext;
512 yyextra->current->name=yyextra->current->name.lower();
513 yyextra->current->fileName = yyextra->fileName;
514 yyextra->current->section=EntryType::makeUsingDir();
515 yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current);
516 yyextra->current->lang = SrcLangExt::Fortran;
518 }
519<Use>{ID}/, {
520 yyextra->useModuleName=yytext;
521 yyextra->useModuleName=yyextra->useModuleName.lower();
522 }
523<Use>,{BS}"ONLY" { BEGIN(UseOnly);
524 }
525<UseOnly>{BS},{BS} {}
526<UseOnly>{ID} {
527 yyextra->current->name= yyextra->useModuleName+"::"+yytext;
528 yyextra->current->name=yyextra->current->name.lower();
529 yyextra->current->fileName = yyextra->fileName;
530 yyextra->current->section=EntryType::makeUsingDecl();
531 yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current);
532 yyextra->current->lang = SrcLangExt::Fortran;
533 }
534<Use,UseOnly>"\n" {
535 yyextra->colNr -= 1;
536 unput(*yytext);
538 }
539
540
541<Start,ModuleBody,SubprogBody>{
542^{BS}interface{IDSYM}+ { /* variable with interface prefix */ }
543^{BS}interface { yyextra->ifType = IF_SPECIFIC;
544 yy_push_state(InterfaceBody,yyscanner);
545
546
547 }
548
549^{BS}abstract{BS_}interface { yyextra->ifType = IF_ABSTRACT;
550 yy_push_state(InterfaceBody,yyscanner);
551
552
553 }
554
555^{BS}interface{BS_}{ID}{ARGS}? { yyextra->ifType = IF_GENERIC;
556 yyextra->current->bodyLine = yyextra->lineNr + yyextra->lineCountPrepass + 1;
557 yy_push_state(InterfaceBody,yyscanner);
558
559
563 startScope(yyscanner,yyextra->last_entry.get());
564 }
static void addInterface(yyscan_t yyscanner, DString name, InterfaceType type)
565}
566
567<InterfaceBody>^{BS}end{BS}interface({BS_}{ID})? {
568
570 {
571 yyextra->last_entry->parent()->endBodyLine = yyextra->lineNr - 1;
572 }
574 {
576 }
579 }
580<InterfaceBody>module{BS}procedure { yy_push_state(YY_START,yyscanner);
581 BEGIN(ModuleProcedure);
582 }
583<ModuleProcedure>{ID} { DString name = DString(yytext).lower();
585 {
587 startScope(yyscanner,yyextra->last_entry.get());
588 }
589
590 yyextra->current->section = EntryType::makeFunction();
591 yyextra->current->name = name;
592 yyextra->moduleProcedures.
push_back(yyextra->current);
594 }
595<ModuleProcedure>"\n" { yyextra->colNr -= 1;
596 unput(*yytext);
598 }
599<InterfaceBody>. {}
600
601
602<Start>^{BS}{CONTAINS}/({BS}|\n|!|;) {
603 if (YY_START == Start)
604 {
606 yy_push_state(ModuleBodyContains,yyscanner);
607 }
608 }
609<ModuleBody>^{BS}{CONTAINS}/({BS}|\n|!|;) { BEGIN(ModuleBodyContains); }
610<SubprogBody>^{BS}{CONTAINS}/({BS}|\n|!|;) { BEGIN(SubprogBodyContains); }
611<TypedefBody>^{BS}{CONTAINS}/({BS}|\n|!|;) { BEGIN(TypedefBodyContains); }
612
613
614<Start>block{BS}data{BS}{ID_} { //
616 yy_push_state(BlockData,yyscanner);
617 yyextra->defaultProtection = Protection::Public;
618 }
619<Start>module|program{BS_} { //
621 if (yytext[0]=='m' || yytext[0]=='M')
622 {
623 yy_push_state(Module,yyscanner);
624 }
625 else
626 {
627 yy_push_state(Program,yyscanner);
628 }
629 yyextra->defaultProtection = Protection::Public;
630 }
631<BlockData>^{BS}"end"({BS}(block{BS}data)({BS_}{ID})?)?{BS}/(\n|!|;) { // end block data
632
633
634 yyextra->defaultProtection = Protection::Public;
636 }
637<Start,ModuleBody,ModuleBodyContains>"end"({BS}(module|program)({BS_}{ID})?)?{BS}/(\n|!|;) { // end module
639 if (!
endScope(yyscanner,yyextra->current_root))
640 {
642 }
643 yyextra->defaultProtection = Protection::Public;
644 if (yyextra->global_scope)
645 {
647 {
648 yy_push_state(Start,yyscanner);
649 }
650 else
651 {
653 }
654 }
655 else
656 {
657 yy_push_state(Start,yyscanner);
659 }
661 }
static void resolveModuleProcedures(yyscan_t yyscanner, Entry *current_root)
fill empty interface module procedures with info from corresponding module subprogs
static void popBlockState(yyscan_t yyscanner)
662<Module>{ID} {
665 BEGIN(ModuleBody);
666 }
667<Program>{ID} {
670 BEGIN(ModuleBody);
671 }
672
673
674
675<ModuleBody,TypedefBody,TypedefBodyContains>private/{BS}(\n|"!") {
676 yyextra->defaultProtection = Protection::Private;
677 yyextra->current->protection = yyextra->defaultProtection ;
678 }
679<ModuleBody,TypedefBody,TypedefBodyContains>public/{BS}(\n|"!") {
680 yyextra->defaultProtection = Protection::Public;
681 yyextra->current->protection = yyextra->defaultProtection ;
682 }
683
684
685
686<ModuleBody>^{BS}type{BS}"=" {}
687<Start,ModuleBody>^{BS}type/[^a-z0-9_] {
688 if (YY_START == Start)
689 {
692 yy_push_state(ModuleBody,yyscanner);
693 }
694
695 yy_push_state(Typedef,yyscanner);
696 yyextra->current->protection = Protection::Package;
697 yyextra->typeProtection = Protection::Public;
698 yyextra->typeMode = true;
699 }
700<Typedef>{
701{COMMA} {}
702
703{BS}"::"{BS} {}
704
705abstract {
706 yyextra->current->spec.setAbstractClass(true);
707 }
708extends{ARGS} {
710 yyextra->current->extends.emplace_back(basename, Protection::Public, Specifier::Normal);
711 }
712public {
713 yyextra->current->protection = Protection::Public;
714 }
715private {
716 yyextra->current->protection = Protection::Private;
717 }
718{LANGUAGE_BIND_SPEC} {
719
720 }
721{ID} { /* type name found */
722 yyextra->current->section = EntryType::makeClass();
723 yyextra->current->spec.setStruct(true);
724 yyextra->current->name = yytext;
725 yyextra->current->fileName = yyextra->fileName;
726 yyextra->current->bodyLine = yyextra->lineNr;
727 yyextra->current->startLine = yyextra->lineNr;
728
729
730 if (yyextra->current_root &&
731 (yyextra->current_root->section.isClass() ||
732 yyextra->current_root->section.isNamespace()))
733 {
734 yyextra->current->name = yyextra->current_root->name + "::" + yyextra->current->name;
735 }
736
737
738 if( yyextra->current->protection == Protection::Package )
739 {
740 yyextra->current->protection = yyextra->defaultProtection;
741 }
742 else if( yyextra->current->protection == Protection::Public )
743 {
744 yyextra->modifiers[yyextra->current_root][yyextra->current->name.lower().str()] |=
DString(
"public");
745 }
746 else if( yyextra->current->protection == Protection::Private )
747 {
748 yyextra->modifiers[yyextra->current_root][yyextra->current->name.lower().str()] |=
DString(
"private");
749 }
750
752 startScope(yyscanner,yyextra->last_entry.get());
753 BEGIN(TypedefBody);
754 }
755}
756
757<TypedefBodyContains>{ /* Type Bound Procedures */
758^{BS}PROCEDURE{ARGS}? {
760 }
DString simplifyWhiteSpace() const
return a copy of this string with leading and trailing whitespace removed and multiple internal white...
761^{BS}final {
762 yyextra->current->spec.setFinal(true);
764 }
765^{BS}generic {
767 }
768{COMMA} {
769 }
770{ATTR_SPEC} {
772 }
773{BS}"::"{BS} {
774 }
775{ID} {
777 yyextra->modifiers[yyextra->current_root][name.
lower().
str()] |= yyextra->currentModifiers;
778 yyextra->current->section = EntryType::makeFunction();
779 yyextra->current->name = name;
780
782 {
784 }
785 else
786 {
787 yyextra->current->args = name.
lower();
788 }
789 yyextra->current->fileName = yyextra->fileName;
790 yyextra->current->bodyLine = yyextra->lineNr;
791 yyextra->current->startLine = yyextra->lineNr;
793 }
794{BS}"=>"[^(\n|\!)]* { /* Specific bindings come after the ID. */
796 size_t i = tmp.
find(
"=>");
798 {
800 }
802 if (yyextra->last_entry->type == "generic")
803 {
804
805
806
809 {
810 copyEntry(yyextra->current, yyextra->last_entry);
811 yyextra->current->name = yyextra->last_entry->name;
812 yyextra->current->section = EntryType::makeFunction();
814
818 }
819 }
820
821 yyextra->last_entry->args = tmp;
822 }
DString left(size_t len) const
823"\n" {
826 yyextra->docBlock.clear();
827 }
static void newLine(yyscan_t yyscanner)
Holds yyextra->modifiers (ie attributes) for one symbol (variable, function, etc).
828}
829
830
831<TypedefBody,TypedefBodyContains>{
832^{BS}"end"{BS}"type"({BS_}{ID})?{BS}/(\n|!|;) { /* end type definition */
833 yyextra->last_entry->parent()->endBodyLine = yyextra->lineNr;
834 if (!
endScope(yyscanner,yyextra->current_root))
835 {
837 }
838 yyextra->typeMode = false;
840 }
841^{BS}"end"{BS}/(\n|!|;) { /* incorrect end type definition */
842 warn(yyextra->fileName,yyextra->lineNr,
"Found 'END' instead of 'END TYPE'");
843 yyextra->last_entry->parent()->endBodyLine = yyextra->lineNr;
844 if (!
endScope(yyscanner,yyextra->current_root))
845 {
847 }
848 yyextra->typeMode = false;
850 }
851}
852
853
854
855<SubprogBody,SubprogBodyContains>^{BS}[0-9]*{BS}"end"({BS}{SUBPROG}({BS_}{ID})?)?{BS}/(\n|!|;) {
856
857
858
859
860
862 {
863 endScope(yyscanner,yyextra->current_root);
864 yyextra->last_entry->endBodyLine = yyextra->lineNr - 1;
865 }
866 yyextra->current_root->endBodyLine = yyextra->lineNr - 1;
867
868 if (!
endScope(yyscanner,yyextra->current_root))
869 {
871 }
872 yyextra->subrCurrent.pop_back();
876 }
877<BlockData>{
878{ID} {
879 }
880}
881<Start,ModuleBody,TypedefBody,SubprogBody,FEnum>{
882^{BS}{TYPE_SPEC}/{SEPARATE} {
883 yyextra->last_enum.reset();
884 if (YY_START == FEnum)
885 {
886 yyextra->argType = "@";
887 }
888 else
889 {
891 }
892 yyextra->current->bodyLine = yyextra->lineNr + 1;
893 yyextra->current->endBodyLine = yyextra->lineNr + yyextra->lineCountPrepass;
894
895 if (YY_START == Start)
896 {
899 yy_push_state(ModuleBody,yyscanner);
900 }
901 yy_push_state(AttributeList,yyscanner);
902 }
903{EXTERNAL_STMT}/({BS}"::"|{BS_}{ID}) {
904
905 if (YY_START == Start)
906 {
909 yy_push_state(ModuleBody,yyscanner);
910 }
914 yy_push_state(AttributeList,yyscanner);
915 }
916{ATTR_STMT}/{BS_}{ID} |
917{ATTR_STMT}/{BS}"::" {
918
919 DBG_CTX((stderr,
"5=========> Attribute statement: %s\n", yytext));
920 if (YY_START == Start)
921 {
924 yy_push_state(ModuleBody,yyscanner);
925 }
928 yyextra->argType="";
929 yy_push_state(YY_START,yyscanner);
930 BEGIN( AttributeList ) ;
931 }
932"common" {
933 if (YY_START == Start)
934 {
937 yy_push_state(ModuleBody,yyscanner);
938 }
939 }
940{ID} {
942 {
945 yy_push_state(ModuleBody,yyscanner);
946 }
947 }
std::string_view stripWhiteSpace(std::string_view s)
Given a string view s, returns a new, narrower view on that string, skipping over any leading or trai...
948^{BS}"type"{BS_}"is"/{BT_} {}
949^{BS}"type"{BS}"=" {}
950^{BS}"class"{BS_}"is"/{BT_} {}
951^{BS}"class"{BS_}"default" {}
952}
953<AttributeList>{
954{COMMA} {}
955{BS} {}
956{LANGUAGE_BIND_SPEC} {
957 yyextra->currentModifiers |= yytext;
958 }
959{ATTR_SPEC}. { /* update yyextra->current yyextra->modifiers when it is an ATTR_SPEC and not a variable name */
960
961 char chr = yytext[(int)yyleng-1];
963 {
964 yyextra->colNr -= (int)yyleng;
965 REJECT;
966 }
967 else
968 {
971 yyextra->colNr -= 1;
972 unput(yytext[(int)yyleng-1]);
973 yyextra->currentModifiers |= (tmp);
974 }
975 }
bool isId(char c)
Returns true if c is a valid character for an identifier.
976"::" { /* end attribute list */
977 BEGIN( FVariable );
978 }
979. { /* unknown attribute, consider variable name */
980
981 yyextra->colNr -= 1;
982 unput(*yytext);
983 BEGIN( FVariable );
984 }
985}
986
987<FVariable>{BS} {}
988<FVariable>{OPERATOR_ID} { /* parse operator access statements "public :: operator(==)" */
990
991
992 int currentState = YY_START;
994 int outerState = YY_START;
995 yy_push_state(currentState,yyscanner);
996 if( outerState == Start || outerState == ModuleBody )
997 {
998 if ((yyextra->current_root) &&
999 (yyextra->current_root->section.isClass() ||
1000 yyextra->current_root->section.isNamespace()))
1001 {
1002 name = yyextra->current_root->name + "::" + name;
1003 }
1004 }
1005
1006 yyextra->modifiers[yyextra->current_root][name.
str()] |= yyextra->currentModifiers;
1007 }
1008<FVariable>{ID} { /* parse variable declaration */
1009
1010
1012 name = name.
lower();
1013
1014 if ((yyextra->current_root) && yyextra->current_root->section.isNamespace())
1015 {
1016 name = yyextra->current_root->name + "::" + name;
1017 }
1018
1019 yyextra->modifiers[yyextra->current_root][name.
lower().
str()] |= yyextra->currentModifiers;
1020 yyextra->argName= name;
1021
1023 if (!yyextra->argType.empty() && !yyextra->current_root->section.isFunction())
1024 {
1026 yyextra->current->section = EntryType::makeVariable();
1027 yyextra->current->name = yyextra->argName;
1028 yyextra->current->type = yyextra->argType;
1029 yyextra->current->fileName = yyextra->fileName;
1030 yyextra->current->bodyLine = yyextra->lineNr;
1031 yyextra->current->startLine = yyextra->lineNr;
1032 if (yyextra->argType == "@")
1033 {
1034 yyextra->current_root->copyToSubEntry(yyextra->current);
1035
1036 yyextra->last_enum = yyextra->current;
1037 yyextra->current_root->parent()->moveToSubEntryAndRefresh(yyextra->current);
1039 }
1040 else
1041 {
1043 }
1044 }
1045 else if (!yyextra->argType.empty())
1046 {
1048 if (parameter)
1049 {
1052 if (!yyextra->docBlock.empty())
1053 {
1055 }
1056 }
1057
1058 if (parameter)
1059 {
1060 yyextra->modifiers[yyextra->current_root][name.
lower().
str()].type = yyextra->argType;
1061 }
1062 else
1063 {
1064 if ((yyextra->current_root->name.lower() == yyextra->argName.lower()) ||
1065 (yyextra->modifiers[yyextra->current_root->parent()][yyextra->current_root->name.lower().str()].returnName.lower() == yyextra->argName.lower()))
1066 {
1067 size_t strt = yyextra->current_root->type.find("function");
1071 {
1073 lft = "";
1074 rght = "";
1076 if ((yyextra->current_root->type.length() - strt - strlen("function"))!= 0)
1077 {
1078 rght = yyextra->current_root->type.
right(yyextra->current_root->type.length() - strt - (
int)strlen(
"function")).
stripWhiteSpace();
1079 }
1080 yyextra->current_root->type = lft;
1082 {
1083 if (yyextra->current_root->type.length() > 0) yyextra->current_root->type += " ";
1084 yyextra->current_root->type += rght;
1085 }
1086 if (yyextra->argType.stripWhiteSpace().length() > 0)
1087 {
1088 if (yyextra->current_root->type.length() > 0) yyextra->current_root->type += " ";
1089 yyextra->current_root->type += yyextra->argType.stripWhiteSpace();
1090 }
1091 if (yyextra->current_root->type.length() > 0) yyextra->current_root->type += " ";
1092 yyextra->current_root->type += "function";
1093 if (!yyextra->docBlock.empty())
1094 {
1096 }
1097 }
1098 else
1099 {
1100 yyextra->current_root->type += " " + yyextra->argType.stripWhiteSpace();
1101 }
1102 yyextra->current_root->type = yyextra->current_root->type.
stripWhiteSpace();
1103 yyextra->modifiers[yyextra->current_root][name.
lower().
str()].type = yyextra->current_root->type;
1104 }
1105 else
1106 {
1107 yyextra->modifiers[yyextra->current_root][name.
lower().
str()].type = yyextra->argType;
1108 }
1109 }
1110
1111
1112
1113 yyextra->current->doc.clear();
1114 yyextra->current->brief.clear();
1115 }
1116 }
DString right(size_t len) const
static void subrHandleCommentBlockResult(yyscan_t yyscanner, const DString &doc, bool brief)
Handle result description as defined after the declaration of the parameter.
static void subrHandleCommentBlock(yyscan_t yyscanner, const DString &doc, bool brief)
Handle parameter description as defined after the declaration of the parameter.
1117<FVariable>{ARGS} { /* dimension of the previous entry. */
1118 DString name(yyextra->argName);
1120 attr += yytext;
1121 yyextra->modifiers[yyextra->current_root][name.
lower().
str()] |= attr;
1122 }
1123<FVariable>{COMMA} { //printf("COMMA: %d<=..<=%d\n", yyextra->colNr-(int)yyleng, yyextra->colNr);
1124
1126 }
static void updateVariablePrepassComment(yyscan_t yyscanner, int from, int to)
1127<FVariable>{BS}"=" {
1128 yy_push_state(YY_START,yyscanner);
1129 yyextra->initializer="=";
1130 yyextra->initializerScope = yyextra->initializerArrayScope = 0;
1131 BEGIN(Initialization);
1132 }
1133<FVariable>"\n" { yyextra->currentModifiers = SymbolModifiers();
1136 yyextra->docBlock.clear();
1137 }
1138<FVariable>";".*"\n" { yyextra->currentModifiers = SymbolModifiers();
1140 yyextra->docBlock.clear();
1141 yyextra->inputStringSemi =
" \n"+
DString(yytext+1);
1142 yyextra->lineNr--;
1143 pushBuffer(yyscanner,yyextra->inputStringSemi);
1144 }
1145<*>";".*"\n" {
1146 if (YY_START == FVariable) REJECT;
1147 if (YY_START == String) REJECT;
1148 if (YY_START == StrIgnore) REJECT;
1149 if (YY_START == DocBlock) REJECT;
1150 yyextra->inputStringSemi =
" \n"+
DString(yytext+1);
1151 yyextra->lineNr--;
1152 pushBuffer(yyscanner,yyextra->inputStringSemi);
1153 }
1154
1155<Initialization,ArrayInitializer>"[" |
1156<Initialization,ArrayInitializer>"(/" { yyextra->initializer+=yytext;
1157 yyextra->initializerArrayScope++;
1158 BEGIN(ArrayInitializer);
1159 }
1160<ArrayInitializer>"]" |
1161<ArrayInitializer>"/)" { yyextra->initializer+=yytext;
1162 yyextra->initializerArrayScope--;
1163 if (yyextra->initializerArrayScope<=0)
1164 {
1165 yyextra->initializerArrayScope = 0;
1166 BEGIN(Initialization);
1167 }
1168 }
1169<ArrayInitializer>. { yyextra->initializer+=yytext; }
1170<Initialization>"(" { yyextra->initializerScope++;
1171 yyextra->initializer+=yytext;
1172 }
1173<Initialization>")" { yyextra->initializerScope--;
1174 yyextra->initializer+=yytext;
1175 }
1176<Initialization>{COMMA} { if (yyextra->initializerScope == 0)
1177 {
1180 if (yyextra->last_enum)
1181 {
1182 yyextra->last_enum->initializer.str(yyextra->initializer.str());
1183 }
1184 else
1185 {
1186 if (yyextra->vtype ==
V_VARIABLE) yyextra->last_entry->initializer.str(yyextra->initializer.str());
1187 }
1188 }
1189 else
1190 {
1191 yyextra->initializer+=", ";
1192 }
1193 }
1194<Initialization>"\n"|"!" { //|
1196 if (yyextra->last_enum)
1197 {
1198 yyextra->last_enum->initializer.str(yyextra->initializer.str());
1199 }
1200 else
1201 {
1202 if (yyextra->vtype ==
V_VARIABLE) yyextra->last_entry->initializer.str(yyextra->initializer.str());
1203 }
1204 yyextra->colNr -= 1;
1205 unput(*yytext);
1206 }
1207<Initialization>. { yyextra->initializer+=yytext; }
1208
1209<*>{BS}"enum"{BS}","{BS}"bind"{BS}"("{BS}"c"{BS}")"{BS} {
1210 if (YY_START == Start)
1211 {
1214 yy_push_state(ModuleBody,yyscanner);
1215 }
1216
1217 yy_push_state(FEnum,yyscanner);
1218 yyextra->current->protection = yyextra->defaultProtection;
1219 yyextra->typeProtection = yyextra->defaultProtection;
1220 yyextra->typeMode = true;
1221
1222 yyextra->current->spec.setStruct(true);
1223 yyextra->current->name.clear();
1224 yyextra->current->args.clear();
1225 yyextra->current->name.sprintf("@%d",yyextra->anonCount++);
1226
1227 yyextra->current->section = EntryType::makeEnum();
1228 yyextra->current->fileName = yyextra->fileName;
1229 yyextra->current->startLine = yyextra->lineNr;
1230 yyextra->current->bodyLine = yyextra->lineNr;
1231 if ((yyextra->current_root) &&
1232 (yyextra->current_root->section.isClass() ||
1233 yyextra->current_root->section.isNamespace()))
1234 {
1235 yyextra->current->name = yyextra->current_root->name + "::" + yyextra->current->name;
1236 }
1237
1239 startScope(yyscanner,yyextra->last_entry.get());
1240 BEGIN( FEnum ) ;
1241 }
1242<FEnum>"end"{BS}"enum" {
1243 yyextra->last_entry->parent()->endBodyLine = yyextra->lineNr;
1244 if (!
endScope(yyscanner,yyextra->current_root))
1245 {
1247 }
1248 yyextra->typeMode = false;
1250 }
1251
1252
1253
1254<Start,ModuleBody,SubprogBody,InterfaceBody,ModuleBodyContains,SubprogBodyContains>^{BS}({PREFIX}{BS_})?{TYPE_SPEC}{BS}({PREFIX}{BS_})?/{SUBPROG}{BS_} {
1256 {
1257 addInterface(yyscanner,
"$interface$", yyextra->ifType);
1258 startScope(yyscanner,yyextra->last_entry.get());
1259 }
1260
1261
1263 yy_push_state(SubprogPrefix,yyscanner);
1264 }
1265
1266<SubprogPrefix>{BS}{SUBPROG}{BS_} {
1267
1272 BEGIN(Subprog);
1273 yyextra->current->bodyLine = yyextra->lineNr + yyextra->lineCountPrepass + 1;
1274 yyextra->current->startLine = yyextra->lineNr;
1275 }
static void addSubprogram(yyscan_t yyscanner, const DString &text)
1276
1277<Start,ModuleBody,SubprogBody,InterfaceBody,ModuleBodyContains,SubprogBodyContains>^{BS}({PREFIX}{BS_})?{SUBPROG}{BS_} {
1278
1281 {
1282 addInterface(yyscanner,
"$interface$", yyextra->ifType);
1283 startScope(yyscanner,yyextra->last_entry.get());
1284 }
1285
1288 yy_push_state(Subprog,yyscanner);
1289 yyextra->current->bodyLine = yyextra->lineNr + yyextra->lineCountPrepass + 1;
1290 yyextra->current->startLine = yyextra->lineNr;
1291 }
1292
1293<Subprog>{BS} { /* ignore white space */ }
1294<Subprog>{ID} { yyextra->current->name = yytext;
1295
1297
1298 if ((yyextra->current_root) &&
1299 (yyextra->current_root->section.isClass() ||
1300 yyextra->current_root->section.isNamespace()))
1301 {
1302 yyextra->current->name= yyextra->current_root->name + "::" + yyextra->current->name;
1303 }
1304 yyextra->modifiers[yyextra->current_root][yyextra->current->name.lower().str()].returnName = std::move(returnName);
1305
1307 {
1309 yyextra->current_root->name,
"$interface$",
DString(yytext).lower());
1310 }
1311
1312 BEGIN(Parameterlist);
1313 }
1314<Parameterlist>"(" { yyextra->current->args = "("; }
1315<Parameterlist>")" {
1316 yyextra->current->args += ")";
1319 startScope(yyscanner,yyextra->last_entry.get());
1320 BEGIN(SubprogBody);
1321 }
DString removeRedundantWhiteSpace(const DString &s)
1322<Parameterlist>{COMMA}|{BS} { yyextra->current->args += yytext;
1324 if (c)
1325 {
1326 if (!yyextra->current->argList.empty())
1327 {
1328 yyextra->current->argList.back().docs = c->
str;
1329 }
1330 }
1331 }
1332<Parameterlist>{ID} {
1333
1335
1336 yyextra->current->args += param;
1340 yyextra->current->argList.
push_back(arg);
1341 }
1342<Parameterlist>{NOARGS} {
1344
1346 startScope(yyscanner,yyextra->last_entry.get());
1347 BEGIN(SubprogBody);
1348 }
1349<SubprogBody>result{BS}\({BS}{ID} {
1350 if (yyextra->functionLine)
1351 {
1353 result= result.
mid(result.
find(
'(')+1);
1355 yyextra->modifiers[yyextra->current_root->parent()][yyextra->current_root->name.lower().str()].returnName = result;
1356 }
1357
1358 }
1359
1360
1361
1362<FVariable,SubprogBody,ModuleBody,TypedefBody,TypedefBodyContains>"!<" { /* backward docu comment */
1364 {
1365 yyextra->current->docLine = yyextra->lineNr;
1366 yyextra->docBlockJavaStyle = false;
1367 yyextra->docBlock.clear();
1370 yy_push_state(DocBackLine,yyscanner);
1371 }
1372 else
1373 {
1374
1375 if (YY_START == String)
1376 {
1377 yyextra->colNr -= (int)yyleng;
1378 REJECT;
1379 }
1380
1381
1382 if ((YY_START != StrIgnore) && (YY_START != String))
1383 {
1384 yy_push_state(YY_START,yyscanner);
1385 BEGIN(StrIgnore);
1386 yyextra->debugStr="*!";
1387 }
1388 }
1389 }
static void startCommentBlock(yyscan_t yyscanner, bool)
1390<DocBackLine>.* { // contents of yyextra->current comment line
1391 yyextra->docBlock+=yytext;
1392 }
1393<DocBackLine>"\n"{BS}"!"("<"|"!"+) { // comment block (next line is also comment line)
1394 yyextra->docBlock+="\n";
1396 }
1397<DocBackLine>"\n" { // comment block ends at the end of this line
1398
1399 yyextra->colNr -= 1;
1400 unput(*yytext);
1402 {
1403 std::shared_ptr<Entry> tmp_entry = yyextra->current;
1404
1405 if (yyextra->last_enum)
1406 {
1407 yyextra->current = yyextra->last_enum;
1408 }
1409 else
1410 {
1411 yyextra->current = yyextra->last_entry;
1412 }
1414
1415 yyextra->current = std::move(tmp_entry);
1416 }
1418 {
1420 }
1421 else if (yyextra->vtype ==
V_RESULT)
1422 {
1424 }
1426 yyextra->docBlock.clear();
1427 }
1428
1429<Start,SubprogBody,ModuleBody,TypedefBody,InterfaceBody,ModuleBodyContains,SubprogBodyContains,TypedefBodyContains,FEnum>^{BS} {
1431 }
static int computeIndent(const char *s)
1432<Start,SubprogBody,ModuleBody,TypedefBody,InterfaceBody,ModuleBodyContains,SubprogBodyContains,TypedefBodyContains,FEnum>"!>" {
1433 yy_push_state(YY_START,yyscanner);
1434 yyextra->current->docLine = yyextra->lineNr;
1435 yyextra->docBlockJavaStyle = false;
1436 if (YY_START==SubprogBody) yyextra->docBlockInBody = true;
1437 yyextra->docBlock.clear();
1440 BEGIN(DocBlock);
1441
1442 }
1443
1444
1445<DocBlock>({CMD}{CMD}){ID}/[^a-z_A-Z0-9] { // escaped command
1446 yyextra->docBlock += yytext;
1447 }
1448<DocBlock>{CMD}("f$"|"f["|"f{"|"f(") {
1449 yyextra->docBlock += yytext;
1450 yyextra->docBlockName=&yytext[1];
1451 if (yyextra->docBlockName.at(1)=='[')
1452 {
1453 yyextra->docBlockName.at(1)=']';
1454 }
1455 if (yyextra->docBlockName.at(1)=='{')
1456 {
1457 yyextra->docBlockName.at(1)='}';
1458 }
1459 if (yyextra->docBlockName.at(1)=='(')
1460 {
1461 yyextra->docBlockName.at(1)=')';
1462 }
1463 yyextra->fencedSize=0;
1465 BEGIN(DocCopyBlock);
1466 }
1467<DocBlock>{CMD}"ifile"{B}+"\""[^\n\"]+"\"" {
1468 yyextra->fileName = &yytext[6];
1469 yyextra->fileName = yyextra->fileName.stripWhiteSpace();
1470 yyextra->fileName = yyextra->fileName.mid(1,yyextra->fileName.length()-2);
1471 yyextra->docBlock += yytext;
1472 }
1473<DocBlock>{CMD}"ifile"{B}+{FILEMASK} {
1474 yyextra->fileName = &yytext[6];
1475 yyextra->fileName = yyextra->fileName.stripWhiteSpace();
1476 yyextra->docBlock += yytext;
1477 }
1478<DocBlock>{CMD}"iline"{LINENR}/[\n\.] |
1479<DocBlock>{CMD}"iline"{LINENR}{B} {
1480 bool ok = false;
1482 if (!ok)
1483 {
1484 warn(yyextra->fileName,yyextra->lineNr,
"Invalid line number '{}' for iline command",yytext);
1485 }
1486 else
1487 {
1488 yyextra->lineNr = nr;
1489 }
1490 yyextra->docBlock += yytext;
1491 }
int toInt(bool *ok=nullptr, int base=10) const
1492<DocBlock>{B}*"<"{PRE}">" {
1493 yyextra->docBlock += yytext;
1494 yyextra->docBlockName="<pre>";
1495 yyextra->fencedSize=0;
1497 BEGIN(DocCopyBlock);
1498 }
1499<DocBlock>{B}*"<"<CODE>">" {
1500 yyextra->docBlock += yytext;
1501 yyextra->docBlockName="<code>";
1502 yyextra->fencedSize=0;
1504 BEGIN(DocCopyBlock);
1505 }
1506<DocBlock>{CMD}"startuml"/[^a-z_A-Z0-9\-] { // verbatim command
1507 yyextra->docBlock += yytext;
1508 yyextra->docBlockName="uml";
1509 yyextra->fencedSize=0;
1511 BEGIN(DocCopyBlock);
1512 }
1513<DocBlock>{CMD}("verbatim"|"iliteral"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"rtfonly"|"docbookonly"|"dot"|"msc"|"mermaid"|"code")/[^a-z_A-Z0-9\-] { // verbatim command
1514 yyextra->docBlock += yytext;
1515 yyextra->docBlockName=&yytext[1];
1516 yyextra->fencedSize=0;
1518 BEGIN(DocCopyBlock);
1519 }
1520<DocBlock>"~~~"[~]* {
1522 yyextra->docBlock += pat;
1523 yyextra->docBlockName="~~~";
1524 yyextra->fencedSize=pat.
length();
1526 BEGIN(DocCopyBlock);
1527 }
1528<DocBlock>"```"[`]*/(".")?[a-zA-Z0-9#_-]+ |
1529<DocBlock>"```"[`]*/"{"[^}]+"}" |
1530<DocBlock>"```"[`]* {
1532 yyextra->docBlock += pat;
1533 yyextra->docBlockName="```";
1534 yyextra->fencedSize=pat.
length();
1536 BEGIN(DocCopyBlock);
1537 }
1538<DocBlock>"\\ilinebr "{BS} {
1540 int extraSpaces = std::max(0,static_cast<int>(yyleng-9-yyextra->curIndent-2));
1541 indent.
fill(
' ',extraSpaces);
1542
1543 yyextra->docBlock += "\\ilinebr ";
1544 yyextra->docBlock += indent;
1545 }
DString fill(char c, size_t len)
Fills a string with a predefined character.
1546
1547<DocBlock>[^@*`~\/\\\n]+ { // any character that isn't special
1548 yyextra->docBlock += yytext;
1549 }
1550<DocBlock>"\n"{BS}"!"(">"|"!"+) { // comment block (next line is also comment line)
1551 yyextra->docBlock+="\n";
1553 }
1554<DocBlock>"\n" { // comment block ends at the end of this line
1555
1556 yyextra->colNr -= 1;
1557 unput(*yytext);
1560 }
1561<DocBlock>. { // command block
1562 yyextra->docBlock += *yytext;
1563 }
1564
1565
1566
1567<DocCopyBlock>"</"{PRE}">" { // end of a <pre> block
1568 yyextra->docBlock += yytext;
1569 if (yyextra->docBlockName=="<pre>")
1570 {
1571 yyextra->docBlockName="";
1573 BEGIN(DocBlock);
1574 }
1575 }
1576<DocCopyBlock>"</"{CODE}">" { // end of a <code> block
1577 yyextra->docBlock += yytext;
1578 if (yyextra->docBlockName=="<code>")
1579 {
1580 yyextra->docBlockName="";
1582 BEGIN(DocBlock);
1583 }
1584 }
1585<DocCopyBlock>{CMD}("f$"|"f]"|"f}"|"f)") {
1586 yyextra->docBlock += yytext;
1587 if (yyextra->docBlockName==&yytext[1])
1588 {
1589 yyextra->docBlockName="";
1591 BEGIN(DocBlock);
1592 }
1593 }
1594<DocCopyBlock>{CMD}("endverbatim"|"endiliteral"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endmanonly"|"endrtfonly"|"enddot"|"endmsc"|"endmermaid"|"enduml"|"endcode")/[^a-z_A-Z0-9] { // end of verbatim block
1595 yyextra->docBlock += yytext;
1596 if (&yytext[4]==yyextra->docBlockName)
1597 {
1598 yyextra->docBlockName="";
1600 BEGIN(DocBlock);
1601 }
1602 }
1603
1604<DocCopyBlock>^{B}*{COMM} { // start of a comment line, just ingnore the comment indicator and leading whitespace
1605 }
1606<DocCopyBlock>"~~~"[~]* {
1608 yyextra->docBlock += pat;
1609 if (yyextra->docBlockName ==
"~~~" && yyextra->fencedSize==pat.
length())
1610 {
1612 BEGIN(DocBlock);
1613 }
1614 }
1615<DocCopyBlock>"```"[`]* {
1617 yyextra->docBlock += pat;
1618 if (yyextra->docBlockName ==
"```" && yyextra->fencedSize==pat.
length())
1619 {
1621 BEGIN(DocBlock);
1622 }
1623 }
1624
1625<DocCopyBlock>[^<@/\*\]!`~"\$\\\n]+ { // any character that is not special
1626 yyextra->docBlock += yytext;
1627 }
1628<DocCopyBlock>\n { // newline
1629 yyextra->docBlock += *yytext;
1631 }
1632<DocCopyBlock>. { // any other character
1633 yyextra->docBlock += *yytext;
1634 }
1635
1636
1637<Prototype>{BS}{SUBPROG}{BS_} {
1638 BEGIN(PrototypeSubprog);
1639 }
1640<Prototype,PrototypeSubprog>{BS}{SCOPENAME}?{BS}{ID} {
1643 BEGIN(PrototypeArgs);
1644 }
1645<PrototypeArgs>{
1646"("|")"|","|{BS_} { yyextra->current->args += yytext; }
1647{ID} { yyextra->current->args += yytext;
1651 }
1652}
1653
1654
1655
1656<*>"\n" {
1658
1659 yyextra->debugStr="";
1660 }
1661
1662
1663
1664
1665<*><<EOF>> {
1666 if (yyextra->parsingPrototype)
1667 {
1669 }
1670 else if ( yyextra->includeStackPtr <= 0 )
1671 {
1672 if (YY_START!=INITIAL && YY_START!=Start)
1673 {
1674 DBG_CTX((stderr,
"==== Error: EOF reached in wrong state (end missing)"));
1676 }
1678 }
1679 else
1680 {
1682 }
1683 }
static void popBuffer(yyscan_t yyscanner)
1684<*>{LOG_OPER} { // Fortran logical comparison keywords
1685 }
1686<*>. {
1687
1688
1689 }
1690
1691
1692
1693
1694%%