40%option never-interactive
41%option case-insensitive
42%option prefix="fortranscannerYY"
44%option extra-type="struct fortranscannerYY_state *"
48#define YY_TYPEDEF_YY_SCANNER_T
82#define DBG_CTX(x) do { } while(0)
85#define YY_NO_UNISTD_H 1
142 "",
"intent(in)",
"intent(out)",
"intent(inout)"
146 "",
"[in]",
"[out]",
"[in,out]"
218 std::map<Entry*,std::map<std::string,SymbolModifiers> >
modifiers;
251static void copyEntry(std::shared_ptr<Entry> dest,
const std::shared_ptr<Entry> &src);
268#define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size);
273#define YY_USER_ACTION yyextra->colNr+=(int)yyleng;
274#define INVALID_ENTRY ((Entry*)0x8)
A String class for use with Doxygen wrapping std::string and adding some additional functionality off...
Represents an unstructured piece of information, about an entity found in the sources.
Abstract interface for outline parsers.
static const char * getLexerFILE()
std::vector< std::shared_ptr< Entry > > EntryList
static int getAmpersandAtTheStart(const char *buf, int length)
static const char * directionParam[]
static DString extractFromParens(const DString &name)
static void resolveModuleProcedures(yyscan_t yyscanner, Entry *current_root)
fill empty interface module procedures with info from corresponding module subprogs
static void newLine(yyscan_t yyscanner)
static void popBlockState(yyscan_t yyscanner)
static void addCurrentEntry(yyscan_t yyscanner, bool case_insens)
adds yyextra->current entry to yyextra->current_root and creates new yyextra->current
static void pushBuffer(yyscan_t yyscanner, const DString &buffer)
static int computeIndent(const char *s)
static void addSubprogram(yyscan_t yyscanner, const DString &text)
static void startCommentBlock(yyscan_t yyscanner, bool)
static void addModule(yyscan_t yyscanner, const DString &name=DString(), bool isModule=false)
static void startScope(yyscan_t yyscanner, Entry *scope)
static int getAmpOrExclAtTheEnd(const char *buf, int length, char ch)
static const CommentInPrepass * locatePrepassComment(yyscan_t yyscanner, int from, int to)
static void subrHandleCommentBlockResult(yyscan_t yyscanner, const DString &doc, bool brief)
Handle result description as defined after the declaration of the parameter.
static const char * stateToString(int state)
static void popBuffer(yyscan_t yyscanner)
static void addInterface(yyscan_t yyscanner, DString name, InterfaceType type)
static void copyEntry(std::shared_ptr< Entry > dest, const std::shared_ptr< Entry > &src)
used to copy entry to an interface module procedure
static const char * directionStrs[]
static void scanner_abort(yyscan_t yyscanner)
static void pushBlockState(yyscan_t yyscanner, const DString &text)
static void pop_state(yyscan_t yyscanner)
static void resolveTypeBoundProcedures(Entry *scope)
static DString extractBind(const DString &name)
static void updateVariablePrepassComment(yyscan_t yyscanner, int from, int to)
static Argument * getParameter(yyscan_t yyscanner, const DString &name)
static void subrHandleCommentBlock(yyscan_t yyscanner, const DString &doc, bool brief)
Handle parameter description as defined after the declaration of the parameter.
static bool endScope(yyscan_t yyscanner, Entry *scope, bool isGlobalRoot=false)
static void handleCommentBlock(yyscan_t yyscanner, const DString &doc, bool brief)
static void truncatePrepass(yyscan_t yyscanner, int index)
static void initEntry(yyscan_t yyscanner)
This class contains the information about the argument of a function or template.
BlockState(DString str, int lineNr)
Holds yyextra->modifiers (ie attributes) for one symbol (variable, function, etc).
SymbolModifiers & operator|=(const SymbolModifiers &mdfs)
DString type
This is only used with function return value.
DString inputStringPrepass
Input string for prepass of line cont. '&'.
std::map< Entry *, std::map< std::string, SymbolModifiers > > modifiers
Holds program scope->symbol name->symbol modifiers.
YY_BUFFER_STATE * includeStack
std::shared_ptr< Entry > last_enum
OutlineParserInterface * thisParser
SymbolModifiers currentModifiers
Accumulated modifiers of current statement, eg variable declaration.
unsigned int inputPositionPrepass
std::shared_ptr< Entry > global_root
std::vector< CommentInPrepass > comments
DString inputStringSemi
Input string after command separator ';'.
EntryList moduleProcedures
CommentScanner commentScanner
int initializerArrayScope
std::stack< BlockState > blockStack
std::shared_ptr< Entry > last_entry
Protection defaultProtection
Protection typeProtection
int mainPrograms
counter for the number of main programs in this file
std::shared_ptr< Entry > current
std::shared_ptr< Entry > file_root
A bunch of utility functions.
static int yyread(yyscan_t yyscanner, char *buf, int max_size)
286ID [a-z_A-Z%]+{IDSYM}*
287ID_ [a-z_A-Z%]*{IDSYM}*
288OPERATOR_ID (operator{BS}"("{BS}(\.[a-z_A-Z]+\.|"="|"/="|"//"|"=="|"<"|"<="|">"|">="|"+"|"*"|"**"|"/"|"-"){BS}")")
289SUBPROG (subroutine|function)
293BT_ ([ \t]+|[ \t]*"(")
296ARGS_L1a [^()]*"("[^)]*")"[^)]*
297ARGS_L1 ("("{ARGS_L1a}*")")
298ARGS_L2 "("({ARGS_L0}|[^()]|{ARGS_L1a}|{ARGS_L1})*")"
299ARGS {BS}({ARGS_L0}|{ARGS_L1}|{ARGS_L2})
306NUM_TYPE (complex|integer|logical|real)
307LOG_OPER (\.and\.|\.eq\.|\.eqv\.|\.ge\.|\.gt\.|\.le\.|\.lt\.|\.ne\.|\.neqv\.|\.or\.|\.not\.)
309CHAR (CHARACTER{ARGS}?|CHARACTER{BS}"*"({BS}[0-9]+|{ARGS}))
310TYPE_SPEC (({NUM_TYPE}({BS}"*"{BS}[0-9]+)?)|({NUM_TYPE}{KIND})|DOUBLE{BS}COMPLEX|DOUBLE{BS}PRECISION|ENUMERATOR|{CHAR}|TYPE{ARGS}|CLASS{ARGS}|PROCEDURE{ARGS}?)
312INTENT_SPEC intent{BS}"("{BS}(in|out|in{BS}out){BS}")"
313ATTR_SPEC (EXTERNAL|ALLOCATABLE|DIMENSION{ARGS}|{INTENT_SPEC}|INTRINSIC|OPTIONAL|PARAMETER|POINTER|PROTECTED|PRIVATE|PUBLIC|SAVE|TARGET|NOPASS|PASS{ARGS}?|DEFERRED|NON_OVERRIDABLE|CONTIGUOUS|VOLATILE|VALUE)
314LANGUAGE_BIND_SPEC BIND{BS}"("{BS}C{BS}((,{BS}NAME{BS}"="{BS}"\""(.*)"\""{BS})|(,{BS}NAME{BS}"="{BS}"'"(.*)"'"{BS}))?")"
316ATTR_STMT {ATTR_SPEC}|DIMENSION
317EXTERNAL_STMT (EXTERNAL)
320PREFIX ((NON_)?RECURSIVE{BS_}|IMPURE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,4}((NON_)?RECURSIVE|IMPURE|PURE|ELEMENTAL)?
321SCOPENAME ({ID}{BS}"::"{BS})*
323LINENR {B}*[1-9][0-9]*
324FILEICHAR [a-z_A-Z0-9\x80-\xFF\\:\\\/\-\+=&#@~]
325FILEECHAR [a-z_A-Z0-9\x80-\xFF\-\+=&#@~]
326FILECHARS {FILEICHAR}*{FILEECHAR}+
327HFILEMASK {FILEICHAR}*("."{FILEICHAR}+)+{FILECHARS}*
328VFILEMASK {FILECHARS}("."{FILECHARS})*
329FILEMASK {VFILEMASK}|{HFILEMASK}
343%x SubprogBodyContains
357%x TypedefBodyContains
383<Prepass>^{BS}[&]*{BS}!.*\n {
384 yyextra->lineCountPrepass ++;
387 yyextra->lineCountPrepass ++;
390 yyextra->functionLine =
false;
392 DBG_CTX((stderr,
"---%s", yytext));
396 if (indexEnd>=0 && yytext[indexEnd]!=
'&')
403 if (YY_START == Prepass)
407 yyextra->inputStringPrepass+=(
const char*)(yytext+(indexStart+1));
410 pushBuffer(yyscanner,yyextra->inputStringPrepass);
422 if (YY_START != Prepass)
424 yyextra->comments.clear();
425 yyextra->inputStringPrepass=
DString();
426 yy_push_state(Prepass,yyscanner);
429 size_t length = yyextra->inputStringPrepass.length();
432 yyextra->inputStringPrepass+=(
const char*)(yytext+(indexStart+1));
433 yyextra->lineCountPrepass ++;
436 truncatePrepass(yyscanner,
static_cast<int>(length) + indexEnd - indexStart - 1);
443 if (yytext[0]!=yyextra->stringStartSymbol)
445 yyextra->colNr -= (int)yyleng;
448 if (yy_top_state(yyscanner) == Initialization ||
449 yy_top_state(yyscanner) == ArrayInitializer)
451 yyextra->initializer+=yytext;
455<String>[\x80-\xFF]* |
456<String>. {
if (yy_top_state(yyscanner) == Initialization ||
457 yy_top_state(yyscanner) == ArrayInitializer)
459 yyextra->initializer+=yytext;
463 if (YY_START == StrIgnore)
464 { yyextra->colNr -= (int)yyleng;
467 yy_push_state(YY_START,yyscanner);
468 if (yy_top_state(yyscanner) == Initialization ||
469 yy_top_state(yyscanner) == ArrayInitializer)
471 yyextra->initializer+=yytext;
473 yyextra->stringStartSymbol=yytext[0];
479<*>"!"/([^<>\n]|"<ff>"|"<FF>") {
if (YY_START == String || YY_START == DocCopyBlock)
480 { yyextra->colNr -= (int)yyleng;
485 if ((YY_START != StrIgnore) && (YY_START != String))
487 yy_push_state(YY_START,yyscanner);
489 yyextra->debugStr=
"*!";
490 DBG_CTX((stderr,
"start comment %d\n",yyextra->lineNr));
494 DBG_CTX((stderr,
"end comment %d %s\n",yyextra->lineNr,
qPrint(yyextra->debugStr)));
const char * qPrint(const char *s)
496<StrIgnore>[\x80-\xFF]* |
497<StrIgnore>. { yyextra->debugStr+=yytext; }
502<Start,ModuleBody,SubprogBody>"use"{BS_} {
503 if (YY_START == Start)
507 yy_push_state(ModuleBody,yyscanner);
509 yy_push_state(Use,yyscanner);
512 DBG_CTX((stderr,
"using dir %s\n",yytext));
513 yyextra->current->name=yytext;
514 yyextra->current->name=yyextra->current->name.lower();
515 yyextra->current->fileName = yyextra->fileName;
516 yyextra->current->section=EntryType::makeUsingDir();
517 yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current);
518 yyextra->current->lang = SrcLangExt::Fortran;
522 yyextra->useModuleName=yytext;
523 yyextra->useModuleName=yyextra->useModuleName.lower();
525<Use>,{BS}"ONLY" { BEGIN(UseOnly);
529 yyextra->current->name= yyextra->useModuleName+
"::"+yytext;
530 yyextra->current->name=yyextra->current->name.lower();
531 yyextra->current->fileName = yyextra->fileName;
532 yyextra->current->section=EntryType::makeUsingDecl();
533 yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current);
534 yyextra->current->lang = SrcLangExt::Fortran;
543<Start,ModuleBody,SubprogBody>{
544^{BS}interface{IDSYM}+ { }
546 yy_push_state(InterfaceBody,yyscanner);
551^{BS}abstract{BS_}interface { yyextra->ifType =
IF_ABSTRACT;
552 yy_push_state(InterfaceBody,yyscanner);
557^{BS}interface{BS_}{ID}{ARGS}? { yyextra->ifType =
IF_GENERIC;
558 yyextra->current->bodyLine = yyextra->lineNr + yyextra->lineCountPrepass + 1;
559 yy_push_state(InterfaceBody,yyscanner);
565 startScope(yyscanner,yyextra->last_entry.get());
DString mid(size_t index, size_t len=npos) const
DString stripWhiteSpace() const
returns a copy of this string with leading and trailing whitespace removed
569<InterfaceBody>^{BS}end{BS}interface({BS_}{ID})? {
573 yyextra->last_entry->parent()->endBodyLine = yyextra->lineNr - 1;
582<InterfaceBody>module{BS}procedure { yy_push_state(YY_START,yyscanner);
583 BEGIN(ModuleProcedure);
589 startScope(yyscanner,yyextra->last_entry.get());
592 yyextra->current->section = EntryType::makeFunction();
593 yyextra->current->name = name;
594 yyextra->moduleProcedures.
push_back(yyextra->current);
597<ModuleProcedure>"\n" { yyextra->colNr -= 1;
604<Start>^{BS}{CONTAINS}/({BS}|\n|!|;) {
605 if (YY_START == Start)
608 yy_push_state(ModuleBodyContains,yyscanner);
611<ModuleBody>^{BS}{CONTAINS}/({BS}|\n|!|;) { BEGIN(ModuleBodyContains); }
612<SubprogBody>^{BS}{CONTAINS}/({BS}|\n|!|;) { BEGIN(SubprogBodyContains); }
613<TypedefBody>^{BS}{CONTAINS}/({BS}|\n|!|;) { BEGIN(TypedefBodyContains); }
616<Start>block{BS}data{BS}{ID_} {
618 yy_push_state(BlockData,yyscanner);
619 yyextra->defaultProtection = Protection::Public;
621<Start>module|program{BS_} {
623 if (yytext[0]==
'm' || yytext[0]==
'M')
625 yy_push_state(Module,yyscanner);
629 yy_push_state(Program,yyscanner);
631 yyextra->defaultProtection = Protection::Public;
633<BlockData>^{BS}"end"({BS}(block{BS}data)({BS_}{ID})?)?{BS}/(\n|!|;) {
636 yyextra->defaultProtection = Protection::Public;
639<Start,ModuleBody,ModuleBodyContains>"end"({BS}(module|program)({BS_}{ID})?)?{BS}/(\n|!|;) {
641 if (!
endScope(yyscanner,yyextra->current_root))
645 yyextra->defaultProtection = Protection::Public;
646 if (yyextra->global_scope)
650 yy_push_state(Start,yyscanner);
659 yy_push_state(Start,yyscanner);
677<ModuleBody,TypedefBody,TypedefBodyContains>private/{BS}(\n|"!") {
678 yyextra->defaultProtection = Protection::Private;
679 yyextra->current->protection = yyextra->defaultProtection ;
681<ModuleBody,TypedefBody,TypedefBodyContains>public/{BS}(\n|"!") {
682 yyextra->defaultProtection = Protection::Public;
683 yyextra->current->protection = yyextra->defaultProtection ;
688<ModuleBody>^{BS}type{BS}"=" {}
689<Start,ModuleBody>^{BS}type/[^a-z0-9_] {
690 if (YY_START == Start)
694 yy_push_state(ModuleBody,yyscanner);
697 yy_push_state(Typedef,yyscanner);
698 yyextra->current->protection = Protection::Package;
699 yyextra->typeProtection = Protection::Public;
700 yyextra->typeMode =
true;
708 yyextra->current->spec.setAbstractClass(
true);
712 yyextra->current->extends.emplace_back(basename, Protection::Public, Specifier::Normal);
715 yyextra->current->protection = Protection::Public;
718 yyextra->current->protection = Protection::Private;
720{LANGUAGE_BIND_SPEC} {
724 yyextra->current->section = EntryType::makeClass();
725 yyextra->current->spec.setStruct(
true);
726 yyextra->current->name = yytext;
727 yyextra->current->fileName = yyextra->fileName;
728 yyextra->current->bodyLine = yyextra->lineNr;
729 yyextra->current->startLine = yyextra->lineNr;
732 if (yyextra->current_root &&
733 (yyextra->current_root->section.isClass() ||
734 yyextra->current_root->section.isNamespace()))
736 yyextra->current->name = yyextra->current_root->name +
"::" + yyextra->current->name;
740 if( yyextra->current->protection == Protection::Package )
742 yyextra->current->protection = yyextra->defaultProtection;
744 else if( yyextra->current->protection == Protection::Public )
746 yyextra->modifiers[yyextra->current_root][yyextra->current->name.lower().str()] |=
DString(
"public");
748 else if( yyextra->current->protection == Protection::Private )
750 yyextra->modifiers[yyextra->current_root][yyextra->current->name.lower().str()] |=
DString(
"private");
754 startScope(yyscanner,yyextra->last_entry.get());
759<TypedefBodyContains>{
760^{BS}PROCEDURE{ARGS}? {
761 yyextra->current->type =
DString(yytext).simplifyWhiteSpace().lower();
764 yyextra->current->spec.setFinal(
true);
765 yyextra->current->type =
DString(yytext).simplifyWhiteSpace();
768 yyextra->current->type =
DString(yytext).simplifyWhiteSpace();
773 yyextra->currentModifiers |=
DString(yytext).stripWhiteSpace();
779 yyextra->modifiers[yyextra->current_root][name.
lower().
str()] |= yyextra->currentModifiers;
780 yyextra->current->section = EntryType::makeFunction();
781 yyextra->current->name = name;
789 yyextra->current->args = name.
lower();
791 yyextra->current->fileName = yyextra->fileName;
792 yyextra->current->bodyLine = yyextra->lineNr;
793 yyextra->current->startLine = yyextra->lineNr;
static constexpr size_t npos
value used to indicate 'not found' or 'to the end of the string', matching std::string::npos
const std::string & str() const
798 size_t i = tmp.
find(
"=>");
804 if (yyextra->last_entry->type ==
"generic")
812 copyEntry(yyextra->current, yyextra->last_entry);
813 yyextra->current->name = yyextra->last_entry->name;
814 yyextra->current->section = EntryType::makeFunction();
823 yyextra->last_entry->args = tmp;
DString simplifyWhiteSpace() const
return a copy of this string with leading and trailing whitespace removed and multiple whitespace cha...
DString & remove(size_t index, size_t len)
size_t find(char c, size_t pos=0) const
DString left(size_t len) const
828 yyextra->docBlock.clear();
833<TypedefBody,TypedefBodyContains>{
834^{BS}"end"{BS}"type"({BS_}{ID})?{BS}/(\n|!|;) {
835 yyextra->last_entry->parent()->endBodyLine = yyextra->lineNr;
836 if (!
endScope(yyscanner,yyextra->current_root))
840 yyextra->typeMode =
false;
843^{BS}"end"{BS}/(\n|!|;) {
844 warn(yyextra->fileName,yyextra->lineNr,
"Found 'END' instead of 'END TYPE'");
845 yyextra->last_entry->parent()->endBodyLine = yyextra->lineNr;
846 if (!
endScope(yyscanner,yyextra->current_root))
850 yyextra->typeMode =
false;
#define warn(file, line, fmt,...)
857<SubprogBody,SubprogBodyContains>^{BS}[0-9]*{BS}"end"({BS}{SUBPROG}({BS_}{ID})?)?{BS}/(\n|!|;) {
865 endScope(yyscanner,yyextra->current_root);
866 yyextra->last_entry->endBodyLine = yyextra->lineNr - 1;
868 yyextra->current_root->endBodyLine = yyextra->lineNr - 1;
870 if (!
endScope(yyscanner,yyextra->current_root))
874 yyextra->subrCurrent.pop_back();
883<Start,ModuleBody,TypedefBody,SubprogBody,FEnum>{
884^{BS}{TYPE_SPEC}/{SEPARATE} {
885 yyextra->last_enum.reset();
886 if (YY_START == FEnum)
888 yyextra->argType =
"@";
892 yyextra->argType =
DString(yytext).simplifyWhiteSpace().lower();
894 yyextra->current->bodyLine = yyextra->lineNr + 1;
895 yyextra->current->endBodyLine = yyextra->lineNr + yyextra->lineCountPrepass;
897 if (YY_START == Start)
901 yy_push_state(ModuleBody,yyscanner);
903 yy_push_state(AttributeList,yyscanner);
905{EXTERNAL_STMT}/({BS}"::"|{BS_}{ID}) {
907 if (YY_START == Start)
911 yy_push_state(ModuleBody,yyscanner);
916 yy_push_state(AttributeList,yyscanner);
918{ATTR_STMT}/{BS_}{ID} |
919{ATTR_STMT}/{BS}"::" {
921 DBG_CTX((stderr,
"5=========> Attribute statement: %s\n", yytext));
922 if (YY_START == Start)
926 yy_push_state(ModuleBody,yyscanner);
931 yy_push_state(YY_START,yyscanner);
932 BEGIN( AttributeList ) ;
935 if (YY_START == Start)
939 yy_push_state(ModuleBody,yyscanner);
947 yy_push_state(ModuleBody,yyscanner);
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...
950^{BS}"type"{BS_}"is"/{BT_} {}
952^{BS}"class"{BS_}"is"/{BT_} {}
953^{BS}"class"{BS_}"default" {}
958{LANGUAGE_BIND_SPEC} {
959 yyextra->currentModifiers |= yytext;
963 char chr = yytext[(int)yyleng-1];
966 yyextra->colNr -= (int)yyleng;
974 unput(yytext[(
int)yyleng-1]);
975 yyextra->currentModifiers |= (tmp);
size_t length() const
Returns the length of the string, not counting the 0-terminator.
990<FVariable>{OPERATOR_ID} {
994 int currentState = YY_START;
996 int outerState = YY_START;
997 yy_push_state(currentState,yyscanner);
998 if( outerState == Start || outerState == ModuleBody )
1000 if ((yyextra->current_root) &&
1001 (yyextra->current_root->section.isClass() ||
1002 yyextra->current_root->section.isNamespace()))
1004 name = yyextra->current_root->name +
"::" + name;
1008 yyextra->modifiers[yyextra->current_root][name.
str()] |= yyextra->currentModifiers;
1014 name = name.
lower();
1016 if ((yyextra->current_root) && yyextra->current_root->section.isNamespace())
1018 name = yyextra->current_root->name +
"::" + name;
1021 yyextra->modifiers[yyextra->current_root][name.
lower().
str()] |= yyextra->currentModifiers;
1022 yyextra->argName= name;
1025 if (!yyextra->argType.empty() && !yyextra->current_root->section.isFunction())
1028 yyextra->current->section = EntryType::makeVariable();
1029 yyextra->current->name = yyextra->argName;
1030 yyextra->current->type = yyextra->argType;
1031 yyextra->current->fileName = yyextra->fileName;
1032 yyextra->current->bodyLine = yyextra->lineNr;
1033 yyextra->current->startLine = yyextra->lineNr;
1034 if (yyextra->argType ==
"@")
1036 yyextra->current_root->copyToSubEntry(yyextra->current);
1038 yyextra->last_enum = yyextra->current;
1039 yyextra->current_root->parent()->moveToSubEntryAndRefresh(yyextra->current);
1047 else if (!yyextra->argType.empty())
1054 if (!yyextra->docBlock.empty())
1062 yyextra->modifiers[yyextra->current_root][name.
lower().
str()].type = yyextra->argType;
1066 if ((yyextra->current_root->name.lower() == yyextra->argName.lower()) ||
1067 (yyextra->modifiers[yyextra->current_root->parent()][yyextra->current_root->name.lower().str()].returnName.lower() == yyextra->argName.lower()))
1069 size_t strt = yyextra->current_root->type.find(
"function");
1078 if ((yyextra->current_root->type.length() - strt - strlen(
"function"))!= 0)
1080 rght = yyextra->current_root->type.
right(yyextra->current_root->type.length() - strt - (
int)strlen(
"function")).
stripWhiteSpace();
1082 yyextra->current_root->type = lft;
1085 if (yyextra->current_root->type.length() > 0) yyextra->current_root->type +=
" ";
1086 yyextra->current_root->type += rght;
1088 if (yyextra->argType.stripWhiteSpace().length() > 0)
1090 if (yyextra->current_root->type.length() > 0) yyextra->current_root->type +=
" ";
1091 yyextra->current_root->type += yyextra->argType.stripWhiteSpace();
1093 if (yyextra->current_root->type.length() > 0) yyextra->current_root->type +=
" ";
1094 yyextra->current_root->type +=
"function";
1095 if (!yyextra->docBlock.empty())
1102 yyextra->current_root->type +=
" " + yyextra->argType.stripWhiteSpace();
1104 yyextra->current_root->type = yyextra->current_root->type.
stripWhiteSpace();
1105 yyextra->modifiers[yyextra->current_root][name.
lower().
str()].type = yyextra->current_root->type;
1109 yyextra->modifiers[yyextra->current_root][name.
lower().
str()].type = yyextra->argType;
1115 yyextra->current->doc.clear();
1116 yyextra->current->brief.clear();
DString right(size_t len) const
1120 DString name(yyextra->argName);
1123 yyextra->modifiers[yyextra->current_root][name.
lower().
str()] |= attr;
1130 yy_push_state(YY_START,yyscanner);
1131 yyextra->initializer=
"=";
1132 yyextra->initializerScope = yyextra->initializerArrayScope = 0;
1133 BEGIN(Initialization);
1138 yyextra->docBlock.clear();
1142 yyextra->docBlock.clear();
1143 yyextra->inputStringSemi =
" \n"+
DString(yytext+1);
1145 pushBuffer(yyscanner,yyextra->inputStringSemi);
1148 if (YY_START == FVariable) REJECT;
1149 if (YY_START == String) REJECT;
1150 if (YY_START == StrIgnore) REJECT;
1151 if (YY_START == DocBlock) REJECT;
1152 yyextra->inputStringSemi =
" \n"+
DString(yytext+1);
1154 pushBuffer(yyscanner,yyextra->inputStringSemi);
1157<Initialization,ArrayInitializer>"[" |
1158<Initialization,ArrayInitializer>"(/" { yyextra->initializer+=yytext;
1159 yyextra->initializerArrayScope++;
1160 BEGIN(ArrayInitializer);
1162<ArrayInitializer>"]" |
1163<ArrayInitializer>"/)" { yyextra->initializer+=yytext;
1164 yyextra->initializerArrayScope--;
1165 if (yyextra->initializerArrayScope<=0)
1167 yyextra->initializerArrayScope = 0;
1168 BEGIN(Initialization);
1171<ArrayInitializer>. { yyextra->initializer+=yytext; }
1172<Initialization>"(" { yyextra->initializerScope++;
1173 yyextra->initializer+=yytext;
1175<Initialization>")" { yyextra->initializerScope--;
1176 yyextra->initializer+=yytext;
1178<Initialization>{COMMA} {
if (yyextra->initializerScope == 0)
1182 if (yyextra->last_enum)
1184 yyextra->last_enum->initializer.str(yyextra->initializer.str());
1188 if (yyextra->vtype ==
V_VARIABLE) yyextra->last_entry->initializer.str(yyextra->initializer.str());
1193 yyextra->initializer+=
", ";
1196<Initialization>"\n"|"!" {
1198 if (yyextra->last_enum)
1200 yyextra->last_enum->initializer.str(yyextra->initializer.str());
1204 if (yyextra->vtype ==
V_VARIABLE) yyextra->last_entry->initializer.str(yyextra->initializer.str());
1206 yyextra->colNr -= 1;
1209<Initialization>. { yyextra->initializer+=yytext; }
1211<*>{BS}"enum"{BS}","{BS}"bind"{BS}"("{BS}"c"{BS}")"{BS} {
1212 if (YY_START == Start)
1216 yy_push_state(ModuleBody,yyscanner);
1219 yy_push_state(FEnum,yyscanner);
1220 yyextra->current->protection = yyextra->defaultProtection;
1221 yyextra->typeProtection = yyextra->defaultProtection;
1222 yyextra->typeMode =
true;
1224 yyextra->current->spec.setStruct(
true);
1225 yyextra->current->name.clear();
1226 yyextra->current->args.clear();
1227 yyextra->current->name.sprintf(
"@%d",yyextra->anonCount++);
1229 yyextra->current->section = EntryType::makeEnum();
1230 yyextra->current->fileName = yyextra->fileName;
1231 yyextra->current->startLine = yyextra->lineNr;
1232 yyextra->current->bodyLine = yyextra->lineNr;
1233 if ((yyextra->current_root) &&
1234 (yyextra->current_root->section.isClass() ||
1235 yyextra->current_root->section.isNamespace()))
1237 yyextra->current->name = yyextra->current_root->name +
"::" + yyextra->current->name;
1241 startScope(yyscanner,yyextra->last_entry.get());
1244<FEnum>"end"{BS}"enum" {
1245 yyextra->last_entry->parent()->endBodyLine = yyextra->lineNr;
1246 if (!
endScope(yyscanner,yyextra->current_root))
1250 yyextra->typeMode =
false;
1256<Start,ModuleBody,SubprogBody,InterfaceBody,ModuleBodyContains,SubprogBodyContains>^{BS}({PREFIX}{BS_})?{TYPE_SPEC}{BS}({PREFIX}{BS_})?/{SUBPROG}{BS_} {
1259 addInterface(yyscanner,
"$interface$", yyextra->ifType);
1260 startScope(yyscanner,yyextra->last_entry.get());
1264 yyextra->current->type =
DString(yytext).stripWhiteSpace().lower();
1265 yy_push_state(SubprogPrefix,yyscanner);
1268<SubprogPrefix>{BS}{SUBPROG}{BS_} {
1275 yyextra->current->bodyLine = yyextra->lineNr + yyextra->lineCountPrepass + 1;
1276 yyextra->current->startLine = yyextra->lineNr;
1279<Start,ModuleBody,SubprogBody,InterfaceBody,ModuleBodyContains,SubprogBodyContains>^{BS}({PREFIX}{BS_})?{SUBPROG}{BS_} {
1284 addInterface(yyscanner,
"$interface$", yyextra->ifType);
1285 startScope(yyscanner,yyextra->last_entry.get());
1290 yy_push_state(Subprog,yyscanner);
1291 yyextra->current->bodyLine = yyextra->lineNr + yyextra->lineCountPrepass + 1;
1292 yyextra->current->startLine = yyextra->lineNr;
1296<Subprog>{ID} { yyextra->current->name = yytext;
1300 if ((yyextra->current_root) &&
1301 (yyextra->current_root->section.isClass() ||
1302 yyextra->current_root->section.isNamespace()))
1304 yyextra->current->name= yyextra->current_root->name +
"::" + yyextra->current->name;
1306 yyextra->modifiers[yyextra->current_root][yyextra->current->name.lower().str()].returnName = std::move(returnName);
1311 yyextra->current_root->name,
"$interface$",
DString(yytext).lower());
1314 BEGIN(Parameterlist);
DString substitute(const DString &s, const DString &src, const DString &dst)
substitute all occurrences of src in s by dst
1316<Parameterlist>"(" { yyextra->current->args =
"("; }
1318 yyextra->current->args +=
")";
1321 startScope(yyscanner,yyextra->last_entry.get());
DString removeRedundantWhiteSpace(const DString &s)
1324<Parameterlist>{COMMA}|{BS} { yyextra->current->args += yytext;
1328 if (!yyextra->current->argList.empty())
1330 yyextra->current->argList.back().docs = c->
str;
1334<Parameterlist>{ID} {
1338 yyextra->current->args += param;
1342 yyextra->current->argList.
push_back(arg);
1344<Parameterlist>{NOARGS} {
1348 startScope(yyscanner,yyextra->last_entry.get());
1351<SubprogBody>result{BS}\({BS}{ID} {
1352 if (yyextra->functionLine)
1355 result= result.
mid(result.
find(
'(')+1);
1357 yyextra->modifiers[yyextra->current_root->parent()][yyextra->current_root->name.lower().str()].returnName = result;
1364<FVariable,SubprogBody,ModuleBody,TypedefBody,TypedefBodyContains>"!<" {
1367 yyextra->current->docLine = yyextra->lineNr;
1368 yyextra->docBlockJavaStyle =
false;
1369 yyextra->docBlock.clear();
1372 yy_push_state(DocBackLine,yyscanner);
1377 if (YY_START == String)
1379 yyextra->colNr -= (int)yyleng;
1384 if ((YY_START != StrIgnore) && (YY_START != String))
1386 yy_push_state(YY_START,yyscanner);
1388 yyextra->debugStr=
"*!";
#define Config_getBool(name)
1393 yyextra->docBlock+=yytext;
1395<DocBackLine>"\n"{BS}"!"("<"|"!"+) {
1396 yyextra->docBlock+=
"\n";
1401 yyextra->colNr -= 1;
1405 std::shared_ptr<Entry> tmp_entry = yyextra->current;
1407 if (yyextra->last_enum)
1409 yyextra->current = yyextra->last_enum;
1413 yyextra->current = yyextra->last_entry;
1417 yyextra->current = std::move(tmp_entry);
1423 else if (yyextra->vtype ==
V_RESULT)
1428 yyextra->docBlock.clear();
DString stripIndentation(const DString &s, bool skipFirstLine)
1431<Start,SubprogBody,ModuleBody,TypedefBody,InterfaceBody,ModuleBodyContains,SubprogBodyContains,TypedefBodyContains,FEnum>^{BS} {
1434<Start,SubprogBody,ModuleBody,TypedefBody,InterfaceBody,ModuleBodyContains,SubprogBodyContains,TypedefBodyContains,FEnum>"!>" {
1435 yy_push_state(YY_START,yyscanner);
1436 yyextra->current->docLine = yyextra->lineNr;
1437 yyextra->docBlockJavaStyle =
false;
1438 if (YY_START==SubprogBody) yyextra->docBlockInBody =
true;
1439 yyextra->docBlock.clear();
1447<DocBlock>({CMD}{CMD}){ID}/[^a-z_A-Z0-9] {
1448 yyextra->docBlock += yytext;
1450<DocBlock>{CMD}("f$"|"f["|"f{"|"f(") {
1451 yyextra->docBlock += yytext;
1452 yyextra->docBlockName=&yytext[1];
1453 if (yyextra->docBlockName.at(1)==
'[')
1455 yyextra->docBlockName.at(1)=
']';
1457 if (yyextra->docBlockName.at(1)==
'{')
1459 yyextra->docBlockName.at(1)=
'}';
1461 if (yyextra->docBlockName.at(1)==
'(')
1463 yyextra->docBlockName.at(1)=
')';
1465 yyextra->fencedSize=0;
1467 BEGIN(DocCopyBlock);
1469<DocBlock>{CMD}"ifile"{B}+"\""[^\n\"]+"\"" {
1470 yyextra->fileName = &yytext[6];
1471 yyextra->fileName = yyextra->fileName.stripWhiteSpace();
1472 yyextra->fileName = yyextra->fileName.mid(1,yyextra->fileName.length()-2);
1473 yyextra->docBlock += yytext;
1475<DocBlock>{CMD}"ifile"{B}+{FILEMASK} {
1476 yyextra->fileName = &yytext[6];
1477 yyextra->fileName = yyextra->fileName.stripWhiteSpace();
1478 yyextra->docBlock += yytext;
1480<DocBlock>{CMD}"iline"{LINENR}/[\n\.] |
1481<DocBlock>{CMD}"iline"{LINENR}{B} {
1483 int nr =
DString(&yytext[6]).toInt(&ok);
1486 warn(yyextra->fileName,yyextra->lineNr,
"Invalid line number '{}' for iline command",yytext);
1490 yyextra->lineNr = nr;
1492 yyextra->docBlock += yytext;
1494<DocBlock>{B}*"<"{PRE}">" {
1495 yyextra->docBlock += yytext;
1496 yyextra->docBlockName=
"<pre>";
1497 yyextra->fencedSize=0;
1499 BEGIN(DocCopyBlock);
1501<DocBlock>{B}*"<"<CODE>">" {
1502 yyextra->docBlock += yytext;
1503 yyextra->docBlockName=
"<code>";
1504 yyextra->fencedSize=0;
1506 BEGIN(DocCopyBlock);
1508<DocBlock>{CMD}"startuml"/[^a-z_A-Z0-9\-] {
1509 yyextra->docBlock += yytext;
1510 yyextra->docBlockName=
"uml";
1511 yyextra->fencedSize=0;
1513 BEGIN(DocCopyBlock);
1515<DocBlock>{CMD}("verbatim"|"iliteral"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"rtfonly"|"docbookonly"|"dot"|"msc"|"mermaid"|"code")/[^a-z_A-Z0-9\-] {
1516 yyextra->docBlock += yytext;
1517 yyextra->docBlockName=&yytext[1];
1518 yyextra->fencedSize=0;
1520 BEGIN(DocCopyBlock);
1522<DocBlock>"~~~"[~]* {
1524 yyextra->docBlock += pat;
1525 yyextra->docBlockName=
"~~~";
1526 yyextra->fencedSize=pat.
length();
1528 BEGIN(DocCopyBlock);
1530<DocBlock>"```"[`]*/(".")?[a-zA-Z0-9#_-]+ |
1531<DocBlock>"```"[`]*/"{"[^}]+"}" |
1532<DocBlock>"```"[`]* {
1534 yyextra->docBlock += pat;
1535 yyextra->docBlockName=
"```";
1536 yyextra->fencedSize=pat.
length();
1538 BEGIN(DocCopyBlock);
1540<DocBlock>"\\ilinebr "{BS} {
1542 int extraSpaces = std::max(0,
static_cast<int>(yyleng-9-yyextra->curIndent-2));
1543 indent.
fill(
' ',extraSpaces);
1545 yyextra->docBlock +=
"\\ilinebr ";
1546 yyextra->docBlock += indent;
DString fill(char c, int len=-1)
Fills a string with a predefined character.
1549<DocBlock>[^@*`~\/\\\n]+ {
1550 yyextra->docBlock += yytext;
1552<DocBlock>"\n"{BS}"!"(">"|"!"+) {
1553 yyextra->docBlock+=
"\n";
1558 yyextra->colNr -= 1;
1564 yyextra->docBlock += *yytext;
1569<DocCopyBlock>"</"{PRE}">" {
1570 yyextra->docBlock += yytext;
1571 if (yyextra->docBlockName==
"<pre>")
1573 yyextra->docBlockName=
"";
1578<DocCopyBlock>"</"{CODE}">" {
1579 yyextra->docBlock += yytext;
1580 if (yyextra->docBlockName==
"<code>")
1582 yyextra->docBlockName=
"";
1587<DocCopyBlock>{CMD}("f$"|"f]"|"f}"|"f)") {
1588 yyextra->docBlock += yytext;
1589 if (yyextra->docBlockName==&yytext[1])
1591 yyextra->docBlockName=
"";
1596<DocCopyBlock>{CMD}("endverbatim"|"endiliteral"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endmanonly"|"endrtfonly"|"enddot"|"endmsc"|"endmermaid"|"enduml"|"endcode")/[^a-z_A-Z0-9] {
1597 yyextra->docBlock += yytext;
1598 if (&yytext[4]==yyextra->docBlockName)
1600 yyextra->docBlockName=
"";
1606<DocCopyBlock>^{B}*{COMM} {
1607 if (yyextra->docBlockName==
"verbatim")
1615 yyextra->docBlock += indent;
1618<DocCopyBlock>"~~~"[~]* {
1620 yyextra->docBlock += pat;
1621 if (yyextra->docBlockName ==
"~~~" && yyextra->fencedSize==pat.
length())
1627<DocCopyBlock>"```"[`]* {
1629 yyextra->docBlock += pat;
1630 if (yyextra->docBlockName ==
"```" && yyextra->fencedSize==pat.
length())
1637<DocCopyBlock>[^<@/\*\]!`~"\$\\\n]+ {
1638 yyextra->docBlock += yytext;
1641 yyextra->docBlock += *yytext;
1645 yyextra->docBlock += *yytext;
1649<Prototype>{BS}{SUBPROG}{BS_} {
1650 BEGIN(PrototypeSubprog);
1652<Prototype,PrototypeSubprog>{BS}{SCOPENAME}?{BS}{ID} {
1653 yyextra->current->name =
DString(yytext).lower();
1654 yyextra->current->name.stripWhiteSpace();
1655 BEGIN(PrototypeArgs);
1658"("|")"|","|{BS_} { yyextra->current->args += yytext; }
1659{ID} { yyextra->current->args += yytext;
1671 yyextra->debugStr=
"";
1678 if (yyextra->parsingPrototype)
1682 else if ( yyextra->includeStackPtr <= 0 )
1684 if (YY_START!=INITIAL && YY_START!=Start)
1686 DBG_CTX((stderr,
"==== Error: EOF reached in wrong state (end missing)"));
1711 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
1713 yyextra->lineNr+=yyextra->lineCountPrepass;
1714 yyextra->lineCountPrepass=0;
1715 yyextra->comments.clear();
1726 if (c==
'\t') col+=tabSize-(col%tabSize);
1727 else if (c==
'\n') col=0;
1735 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
1737 for (
const auto &cip : yyextra->comments)
1741 if (c>=from && c<=to)
1752 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
1756 yyextra->last_entry->brief = c->
str;
1761 if (parameter) parameter->
docs = c->
str;
1767 for(
int i=0; i<length; i++)
1787 int parseState = Start;
1788 char quoteSymbol = 0;
1790 int commentIndex = -1;
1792 if (ch !=
'\0') parseState = String;
1794 for(
int i=0; i<length && parseState!=Comment; i++)
1798 if (parseState==String)
1800 if (buf[i]==
'\\') i++;
1809 if (buf[i]==quoteSymbol)
1815 else if (parseState==Start)
1817 parseState = String;
1818 quoteSymbol = buf[i];
1824 if (parseState==Start)
1826 parseState = Comment;
1845 return commentIndex;
1853 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
1854 size_t length = yyextra->inputStringPrepass.length();
1855 for (
size_t i=index+1; i<length; i++) {
1856 if (yyextra->inputStringPrepass[i]==
'!' && i<length-1 && yyextra->inputStringPrepass[i+1]==
'<') {
1857 yyextra->comments.emplace_back(index, yyextra->inputStringPrepass.right(length-i-2));
1860 yyextra->inputStringPrepass.resize(index);
1867 for(
int i=length; i>pos; i--)
1868 contents[i]=contents[i-1];
1878 int prevLineLength=0;
1879 int prevLineAmpOrExclIndex=-1;
1881 char prevQuote =
'\0';
1882 char thisQuote =
'\0';
1883 bool emptyLabel=
true;
1884 bool commented=
false;
1885 bool inSingle=
false;
1886 bool inDouble=
false;
1887 bool inBackslash=
false;
1888 bool fullCommentLine=
true;
1889 bool artificialComment=
false;
1891 int newContentsSize = (int)strlen(contents)+3;
1892 char* newContents = (
char*)malloc(newContentsSize);
1897 sizCont = strlen(contents);
1898 for(
size_t i=0;i<sizCont;i++) {
1900 char c = contents[i];
1901 if (artificialComment && c !=
'\n')
1903 if (c ==
'!' && spaces)
1905 newContents[j++] = c;
1906 artificialComment =
false;
1911 else if (c ==
' ' || c ==
'\t')
continue;
1921 if (j>=newContentsSize-3) {
1922 newContents = (
char*)realloc(newContents, newContentsSize+1000);
1923 newContentsSize = newContentsSize+1000;
1928 if (!fullCommentLine)
1930 prevLineLength=column;
1931 prevLineAmpOrExclIndex=
getAmpOrExclAtTheEnd(&contents[i-prevLineLength+1], prevLineLength,prevQuote);
1932 if (prevLineAmpOrExclIndex == -1) prevLineAmpOrExclIndex = column - 1;
1935 prevLineAmpOrExclIndex = -1;
1941 prevLineLength+=column;
1945 hasContLine[curLine - 1] = 1;
1948 artificialComment=
false;
1950 fullCommentLine=
true;
1955 prevQuote = thisQuote;
1968 newContents[j]=
'\000';
1969 newContentsSize = (int)strlen(newContents);
1970 if (newContents[newContentsSize - 1] !=
'\n')
1973 newContents = (
char*)realloc(newContents, newContentsSize+2);
1974 newContents[newContentsSize] =
'\n';
1975 newContents[newContentsSize + 1] =
'\000';
1981 if ((column <= fixedCommentAfter) && (column!=6) && !commented)
1984 fullCommentLine=
false;
1988 inBackslash = !inBackslash;
1995 inSingle = !inSingle;
1996 if (inSingle) thisQuote = c;
1997 else thisQuote =
'\0';
2005 inDouble = !inDouble;
2006 if (inDouble) thisQuote = c;
2007 else thisQuote =
'\0';
2012 inBackslash =
false;
2019 if ((column <= fixedCommentAfter) && (column!=6))
2027 else if ((c ==
'!') && !inDouble && !inSingle)
2034 if (!commented) fullCommentLine=
false;
2041 if (!commented && (column < 6) && ((c -
'0') >= 0) && ((c -
'0') <= 9))
2045 else if (column==6 && emptyLabel)
2047 if (!commented) fullCommentLine=
false;
2052 if (prevLineAmpOrExclIndex==-1)
2061 if (curLine != 1)
insertCharacter(newContents, j+1, (j+1)-6-prevLineLength+prevLineAmpOrExclIndex+skipped,
'&');
2067 hasContLine[curLine - 1] = 1;
2076 else if ((column > fixedCommentAfter) && !commented)
2087 artificialComment =
true;
2099 if (!commented) fullCommentLine=
false;
2115 newContents = (
char*)realloc(newContents, 2);
2116 newContents[0] =
'\n';
2117 newContents[1] =
'\000';
2119 else if (newContents[j] ==
'\n')
2121 newContents = (
char*)realloc(newContents, j+2);
2122 newContents[j + 1] =
'\000';
2126 newContents = (
char*)realloc(newContents, j+3);
2127 newContents[j + 1] =
'\n';
2128 newContents[j + 2] =
'\000';
2135 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
2136 if (yyextra->includeStackCnt <= yyextra->includeStackPtr)
2138 yyextra->includeStackCnt++;
2139 yyextra->includeStack = (YY_BUFFER_STATE *)realloc(yyextra->includeStack, yyextra->includeStackCnt *
sizeof(YY_BUFFER_STATE));
2141 yyextra->includeStack[yyextra->includeStackPtr++] = YY_CURRENT_BUFFER;
2142 yy_switch_to_buffer(yy_scan_string(buffer.
data(),yyscanner),yyscanner);
2149 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
2151 yyextra->includeStackPtr --;
2152 yy_delete_buffer( YY_CURRENT_BUFFER, yyscanner );
2153 yy_switch_to_buffer( yyextra->includeStack[yyextra->includeStackPtr], yyscanner );
2157static void copyEntry(std::shared_ptr<Entry> dest,
const std::shared_ptr<Entry> &src)
2159 dest->type = src->type;
2160 dest->fileName = src->fileName;
2161 dest->startLine = src->startLine;
2162 dest->bodyLine = src->bodyLine;
2163 dest->endBodyLine = src->endBodyLine;
2164 dest->args = src->args;
2165 dest->argList = src->argList;
2166 dest->doc = src->doc;
2167 dest->docLine = src->docLine;
2168 dest->docFile = src->docFile;
2169 dest->brief = src->brief;
2170 dest->briefLine= src->briefLine;
2171 dest->briefFile= src->briefFile;
2181 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
2182 if (yyextra->moduleProcedures.empty())
return;
2185 std::map<std::string,std::shared_ptr<Entry>> procMap;
2187 for (
const auto& cf: current_root->
children())
2189 if (!cf->section.isFunction())
2198 procMap.emplace(name.
str(), cf);
2204 for (
const auto& ce1: yyextra->moduleProcedures)
2206 if (procMap.find(ce1->name.str())!=procMap.end())
2208 std::shared_ptr<Entry> proc = procMap[ce1->name.str()];
2212 yyextra->moduleProcedures.clear();
2221 extracted.
remove(0, start+1);
2225 size_t length = extracted.
length();
2237 if (parensPart.
length() == 1)
2252 return "bind(C, name=" + parensPart +
")";
2293 else if (mdfString.
contains(
"intent"))
2302 else if (mdfString==
"public")
2306 else if (mdfString==
"private")
2310 else if (mdfString==
"protected")
2314 else if (mdfString==
"optional")
2318 else if (mdfString==
"allocatable")
2322 else if (mdfString==
"external")
2326 else if (mdfString==
"intrinsic")
2330 else if (mdfString==
"parameter")
2334 else if (mdfString==
"pointer")
2338 else if (mdfString==
"target")
2342 else if (mdfString==
"save")
2346 else if (mdfString==
"nopass")
2350 else if (mdfString==
"deferred")
2354 else if (mdfString==
"non_overridable")
2358 else if (mdfString==
"contiguous")
2362 else if (mdfString==
"volatile")
2364 newMdf.
volat =
true;
2366 else if (mdfString==
"value")
2368 newMdf.
value =
true;
2370 else if (mdfString.
contains(
"pass"))
2404 if ((!byTypeName && arg.
name.
lower() == cname) ||
2405 (byTypeName && arg.
type.
lower() == cname)
2420 if (!typeName.
empty()) typeName +=
", ";
2425 if (!typeName.
empty()) typeName +=
", ";
2430 if (!typeName.
empty()) typeName +=
", ";
2431 typeName +=
"optional";
2435 if (!typeName.
empty()) typeName +=
", ";
2436 typeName +=
"allocatable";
2440 if (!typeName.
contains(
"external"))
2442 if (!typeName.
empty()) typeName +=
", ";
2443 typeName +=
"external";
2448 if (!typeName.
empty()) typeName +=
", ";
2449 typeName +=
"intrinsic";
2453 if (!typeName.
empty()) typeName +=
", ";
2454 typeName +=
"parameter";
2458 if (!typeName.
empty()) typeName +=
", ";
2459 typeName +=
"pointer";
2463 if (!typeName.
empty()) typeName +=
", ";
2464 typeName +=
"target";
2468 if (!typeName.
empty()) typeName +=
", ";
2473 if (!typeName.
empty()) typeName +=
", ";
2474 typeName +=
"deferred";
2478 if (!typeName.
empty()) typeName +=
", ";
2479 typeName +=
"non_overridable";
2483 if (!typeName.
empty()) typeName +=
", ";
2484 typeName +=
"nopass";
2488 if (!typeName.
empty()) typeName +=
", ";
2491 typeName +=
"(" + mdfs.
passVar +
")";
2495 if (!typeName.
empty()) typeName +=
", ";
2500 if (!typeName.
empty()) typeName +=
", ";
2501 typeName +=
"public";
2505 if (!typeName.
empty()) typeName +=
", ";
2506 typeName +=
"private";
2510 if (!typeName.
empty()) typeName +=
", ";
2511 typeName +=
"protected";
2515 if (!typeName.
empty()) typeName +=
", ";
2516 typeName +=
"contiguous";
2520 if (!typeName.
empty()) typeName +=
", ";
2521 typeName +=
"volatile";
2525 if (!typeName.
empty()) typeName +=
", ";
2526 typeName +=
"value";
2549 ent->
spec.setFinal(
true);
2553 ent->
virt = Specifier::Pure;
2562 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
2564 yyextra->current_root= scope;
2566 yyextra->modifiers.emplace(scope, std::map<std::string,SymbolModifiers>());
2569 yyextra->current = std::make_shared<Entry>();
2578 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
2579 if (yyextra->global_scope == scope)
2581 yyextra->global_scope =
nullptr;
2589 if (yyextra->current_root->parent() || isGlobalRoot)
2591 yyextra->current_root= yyextra->current_root->parent();
2595 fprintf(stderr,
"parse error in end <scopename>\n");
2601 yyextra->current = std::make_shared<Entry>();
2605 std::map<std::string,SymbolModifiers>& mdfsMap = yyextra->modifiers[scope];
2607 if (scope->
section.isFunction())
2610 for (
const auto &kv : mdfsMap)
2624 if (yyextra->modifiers[scope].find(returnName.
str())!=yyextra->modifiers[scope].end())
2626 scope->
type = yyextra->modifiers[scope][returnName.
str()].type;
2631 if (scope->
section.isClass() && scope->
spec.isInterface())
2638 for (
const auto &ce : scope->
children())
2640 if (!ce->section.isFunction())
2650 arg->
type =
"external " + ce->type +
"(";
2651 for (
size_t i=0; i<ce->argList.size(); i++)
2657 const Argument &subarg = ce->argList.at(i);
2665 yyextra->modifiers.erase(scope);
2671 if (!scope->
section.isFunction())
2674 for (
const auto &ce : scope->
children())
2676 if (!ce->section.isVariable() && !ce->section.isFunction() && !ce->section.isClass())
2680 if (mdfsMap.find(ce->name.lower().str())!=mdfsMap.end())
2684 if (ce->section.isVariable() || ce->section.isFunction())
2692 yyextra->modifiers.erase(scope);
2706 bool procMapCreated =
false;
2707 std::unordered_map<std::string,std::shared_ptr<Entry>> procMap;
2710 bool interfMapCreated =
false;
2711 std::unordered_map<std::string,std::shared_ptr<Entry>> interfMap;
2714 for (
const auto &ce: scope->
children())
2716 if (!ce->section.isClass())
2720 std::unordered_map<std::string,std::shared_ptr<Entry>> methodMap;
2721 for (
auto &ct: ce->children())
2723 if (!ct->section.isFunction())
2726 if (ct->type==
"generic")
2729 if (ct->virt==Specifier::Pure)
2733 if (!procMapCreated)
2735 for (
const auto &cf: scope->
children())
2737 if (cf->section.isFunction())
2739 procMap.emplace(cf->name.str(), cf);
2742 procMapCreated =
true;
2747 if (procMap.find(implName.
str())!=procMap.end())
2749 std::shared_ptr<Entry> proc = procMap[implName.
str()];
2750 ct->args = proc->args;
2752 if (ct->brief.empty())
2754 ct->brief = proc->brief;
2755 ct->briefLine = proc->briefLine;
2756 ct->briefFile = proc->briefFile;
2758 if (ct->doc.empty())
2760 ct->doc = proc->doc;
2761 ct->docLine = proc->docLine;
2762 ct->docFile = proc->docFile;
2764 methodMap.emplace(ct->name.str(), ct);
2769 for (
auto &ct: ce->children())
2771 if (!ct->section.isFunction())
2774 if (ct->virt != Specifier::Pure)
2778 if (!interfMapCreated)
2780 for(
const auto &cf: scope->
children())
2782 if (cf->section.isClass() && cf->spec.isInterface() && cf->type==
"abstract")
2784 std::shared_ptr<Entry> ci = cf->children().front();
2785 interfMap.emplace(ci->name.str(), ci);
2788 interfMapCreated =
true;
2793 if (interfMap.find(implName.
str())!= interfMap.end() )
2795 std::shared_ptr<Entry> proc = interfMap[implName.
str()];
2796 ct->args = proc->args;
2798 if (ct->brief.empty())
2800 ct->brief = proc->brief;
2801 ct->briefLine = proc->briefLine;
2802 ct->briefFile = proc->briefFile;
2804 if (ct->doc.empty())
2806 ct->doc = proc->doc;
2807 ct->docLine = proc->docLine;
2808 ct->docFile = proc->docFile;
2811 methodMap.emplace(ct->name.str(), ct);
2817 for (
auto &ct: ce->children())
2819 if (!ct->section.isFunction())
2822 if (ct->type!=
"generic")
2826 DString methodName = ct->args;
2827 if (methodMap.find(methodName.
str()) != methodMap.end())
2829 std::shared_ptr<Entry> method = methodMap[methodName.
str()];
2830 ct->args = method->args;
2832 if (ct->brief.empty())
2834 ct->brief = method->brief;
2835 ct->briefLine = method->briefLine;
2836 ct->briefFile = method->briefFile;
2838 if (ct->doc.empty())
2840 ct->doc = method->doc;
2841 ct->docLine = method->docLine;
2842 ct->docFile = method->docFile;
2852 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
2854 while ( c < max_size && yyextra->inputString[yyextra->inputPosition] )
2856 *buf = yyextra->inputString[yyextra->inputPosition++] ;
2864 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
2865 yyextra->last_entry.reset();
2870 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
2871 if (yyextra->typeMode)
2873 yyextra->current->protection = yyextra->typeProtection;
2875 else if (yyextra->current_root && yyextra->current_root->section.isClass() && yyextra->current_root->spec.isInterface())
2877 yyextra->current->protection = Protection::Public;
2879 else if (yyextra->current_root && yyextra->current_root->section.isFunction())
2881 yyextra->current->protection = Protection::Private;
2885 yyextra->current->protection = yyextra->defaultProtection;
2887 yyextra->current->mtype = MethodTypes::Method;
2888 yyextra->current->virt = Specifier::Normal;
2889 yyextra->current->isStatic =
false;
2890 yyextra->current->lang = SrcLangExt::Fortran;
2891 yyextra->commentScanner.initGroupInfo(yyextra->current.get());
2899 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
2900 if (case_insens) yyextra->current->name = yyextra->current->name.lower();
2902 yyextra->last_entry = yyextra->current;
2903 yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current);
2909 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
2910 DBG_CTX((stderr,
"0=========> got module %s\n",
qPrint(name)));
2913 yyextra->current->section = EntryType::makeNamespace();
2915 yyextra->current->section = EntryType::makeFunction();
2919 yyextra->current->name = name;
2923 DString fname = yyextra->fileName;
2924 size_t index1 = fname.
rfind(
'/');
2925 size_t index2 = fname.
rfind(
'\\');
2929 if (yyextra->mainPrograms) fname +=
"__" +
DString().
setNum(yyextra->mainPrograms);
2930 yyextra->mainPrograms++;
2932 yyextra->current->name =
substitute(fname,
".",
"_");
2934 yyextra->current->type =
"program";
2935 yyextra->current->fileName = yyextra->fileName;
2936 yyextra->current->bodyLine = yyextra->lineNr;
2937 yyextra->current->startLine = yyextra->lineNr;
2938 yyextra->current->protection = Protection::Public ;
2940 startScope(yyscanner,yyextra->last_entry.get());
2946 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
2947 DBG_CTX((stderr,
"1=========> got subprog, type: %s\n",
qPrint(text)));
2948 yyextra->subrCurrent.push_back(yyextra->current);
2949 yyextra->current->section = EntryType::makeFunction();
2952 yyextra->current->type +=
" " + subtype;
2956 yyextra->current->virt = Specifier::Virtual;
2958 yyextra->current->fileName = yyextra->fileName;
2959 yyextra->current->bodyLine = yyextra->lineNr;
2960 yyextra->current->startLine = yyextra->lineNr;
2961 yyextra->current->args.
clear();
2962 yyextra->current->argList.clear();
2964 yyextra->docBlock.clear();
2973 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
2974 if (YY_START == Start)
2978 yy_push_state(ModuleBody,yyscanner);
2981 yyextra->current->section = EntryType::makeClass();
2982 yyextra->current->spec =
TypeSpecifier().setInterface(
true);
2983 yyextra->current->name = name;
2988 yyextra->current->type =
"abstract";
2992 yyextra->current->type =
"generic";
2998 yyextra->current->type =
"";
3002 if ((yyextra->current_root) &&
3003 (yyextra->current_root->section.isClass() ||
3004 yyextra->current_root->section.isNamespace()))
3006 yyextra->current->name= yyextra->current_root->name +
"::" + yyextra->current->name;
3009 yyextra->current->fileName = yyextra->fileName;
3010 yyextra->current->bodyLine = yyextra->lineNr;
3011 yyextra->current->startLine = yyextra->lineNr;
3022 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
3025 for (
Argument &a:yyextra->current_root->argList)
3040 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
3043 yyextra->current->briefFile = yyextra->fileName;
3044 yyextra->current->briefLine = yyextra->lineNr;
3048 yyextra->current->docFile = yyextra->fileName;
3049 yyextra->current->docLine = yyextra->lineNr;
3057 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
3059 if (yyextra->docBlockInBody && hideInBodyDocs)
3061 yyextra->docBlockInBody =
false;
3064 DBG_CTX((stderr,
"call parseCommentBlock [%s]\n",
qPrint(doc)));
3065 int lineNr = brief ? yyextra->current->briefLine : yyextra->current->docLine;
3067 bool needsEntry =
false;
3068 Markdown markdown(yyextra->fileName,lineNr);
3072 while (yyextra->commentScanner.parseCommentBlock(
3073 yyextra->thisParser,
3074 yyextra->docBlockInBody ? yyextra->subrCurrent.back().get() : yyextra->current.get(),
3078 yyextra->docBlockInBody ?
false : brief,
3079 yyextra->docBlockInBody ?
false : yyextra->docBlockJavaStyle,
3080 yyextra->docBlockInBody,
3081 yyextra->defaultProtection,
3088 DBG_CTX((stderr,
"parseCommentBlock position=%d [%s] needsEntry=%d\n",position,doc.
data()+position,needsEntry));
3091 DBG_CTX((stderr,
"parseCommentBlock position=%d [%s] needsEntry=%d\n",position,doc.
data()+position,needsEntry));
3094 yyextra->docBlockInBody =
false;
3101 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
3105 std::shared_ptr<Entry> tmp_entry = yyextra->current;
3106 yyextra->current = yyextra->subrCurrent.
back();
3109 yyextra->current->inbodyDocs =
"";
3117 int dir1 = yyextra->modifiers[yyextra->current_root][yyextra->argName.lower().str()].direction;
3129 if (!loc_doc.
empty() && (loc_doc.
lower() != yyextra->argName.
lower()))
3132 yyextra->argName +
" " + loc_doc,brief);
3138 warn(yyextra->fileName,yyextra->lineNr,
"Routine: {}{} inconsistency between intent attribute and documentation for parameter {}:",
3139 yyextra->current->name,yyextra->current->args,yyextra->argName);
3141 yyextra->argName +
" " + loc_doc,brief);
3154 yyextra->current = tmp_entry;
3158 yyextra->argName +
" " + loc_doc,brief);
3162 warn(yyextra->fileName,yyextra->lineNr,
"Routine: {}{} inconsistency between intent attribute and documentation for parameter {}:",
3163 yyextra->current->name,yyextra->current->args,yyextra->argName);
3165 yyextra->argName +
" " + loc_doc,brief);
3176 if (!loc_doc.
empty() && (loc_doc.
lower() != yyextra->argName.
lower()))
3179 yyextra->argName +
" " + loc_doc,brief);
3184 warn(yyextra->fileName,yyextra->lineNr,
"Routine: {}{} inconsistency between intent attribute and documentation for parameter {}:",
3185 yyextra->current->name,yyextra->current->args,yyextra->argName);
3187 yyextra->argName +
" " + loc_doc,brief);
3191 else if (!loc_doc.
empty() && (loc_doc.
lower() != yyextra->argName.
lower()))
3194 yyextra->argName +
" " + loc_doc,brief);
3198 yyextra->current = tmp_entry;
3204 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
3208 std::shared_ptr<Entry> tmp_entry = yyextra->current;
3209 yyextra->current = yyextra->subrCurrent.
back();
3212 yyextra->current->inbodyDocs =
"";
3221 if (!loc_doc.
empty() && (loc_doc.
lower() != yyextra->argName.
lower()))
3227 yyextra->current = std::move(tmp_entry);
3235 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
3236 char *tmpBuf =
nullptr;
3239 if (fileBuf==
nullptr || fileBuf[0]==
'\0')
return;
3241 yyextra->defaultProtection = Protection::Public;
3242 yyextra->inputString = fileBuf;
3243 yyextra->inputPosition = 0;
3244 yyextra->inputStringPrepass =
nullptr;
3245 yyextra->inputPositionPrepass = 0;
3248 yyextra->current_root = rt.get();
3249 yyextra->global_root = rt;
3253 if (yyextra->isFixedForm)
3255 yyextra->fixedCommentAfter =
Config_getInt(FORTRAN_COMMENT_AFTER);
3256 msg(
"Prepassing fixed form of {}\n", fileName);
3262 yyextra->inputString =
prepassFixedForm(fileBuf,
nullptr,yyextra->fixedCommentAfter);
3271 else if (yyextra->inputString[strlen(fileBuf)-1] !=
'\n')
3273 tmpBuf = (
char *)malloc(strlen(fileBuf)+2);
3274 strcpy(tmpBuf,fileBuf);
3275 tmpBuf[strlen(fileBuf)]=
'\n';
3276 tmpBuf[strlen(fileBuf)+1]=
'\000';
3277 yyextra->inputString = tmpBuf;
3280 yyextra->lineNr= 1 ;
3281 yyextra->fileName = fileName;
3282 msg(
"Parsing file {}...\n",yyextra->fileName);
3284 yyextra->global_scope = rt.get();
3287 yyextra->commentScanner.enterFile(yyextra->fileName,yyextra->lineNr);
3290 yyextra->current = std::make_shared<Entry>();
3291 yyextra->current->lang = SrcLangExt::Fortran;
3292 yyextra->current->name = yyextra->fileName;
3293 yyextra->current->section = EntryType::makeSource();
3294 yyextra->file_root = yyextra->current;
3295 yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current);
3296 yyextra->current->lang = SrcLangExt::Fortran;
3298 fortranscannerYYrestart(
nullptr, yyscanner );
3303 fortranscannerYYlex(yyscanner);
3304 yyextra->commentScanner.leaveFile(yyextra->fileName,yyextra->lineNr);
3306 if (yyextra->global_scope && yyextra->global_scope !=
INVALID_ENTRY)
3308 endScope(yyscanner,yyextra->current_root,
true);
3313 rt->program.str(std::string());
3315 yyextra->moduleProcedures.clear();
3318 free((
char*)tmpBuf);
3319 yyextra->inputString=
nullptr;
3321 if (yyextra->isFixedForm)
3323 free((
char*)yyextra->inputString);
3324 yyextra->inputString=
nullptr;
3352 fortranscannerYYlex_destroy(
p->yyscanner);
3356 const char *fileBuf,
3357 const std::shared_ptr<Entry> &root,
3360 struct yyguts_t *yyg = (
struct yyguts_t*)
p->yyscanner;
3361 yyextra->thisParser =
this;
3370 return extension!=extension.
lower();
3375 struct yyguts_t *yyg = (
struct yyguts_t*)
p->yyscanner;
3377 yyextra->parsingPrototype =
true;
3379 fortranscannerYYlex(
p->yyscanner);
3380 yyextra->parsingPrototype =
false;
3388 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
3389 fprintf(stderr,
"********************************************************************\n");
3390 if (yyextra->blockLineNr == -1)
3392 fprintf(stderr,
"Error in file %s line: %d, state: %d(%s)\n",
3397 fprintf(stderr,
"Error in file %s line: %d, state: %d(%s), starting command: '%s' probable line reference: %d\n",
3398 qPrint(yyextra->fileName),yyextra->lineNr,YY_START,
stateToString(YY_START),
qPrint(yyextra->blockString),yyextra->blockLineNr);
3400 fprintf(stderr,
"********************************************************************\n");
3403 while (!yyextra->blockStack.empty()) yyextra->blockStack.pop();
3407 for (
const auto &ce : yyextra->global_root->children())
3409 if (ce == yyextra->file_root) start=
true;
3410 if (start) ce->reset();
3414 (void)yy_top_state(yyscanner);
3422 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
3423 if ( yyg->yy_start_stack_ptr <= 0 )
3424 warn(yyextra->fileName,yyextra->lineNr,
"Unexpected statement '{}'",yytext );
3426 yy_pop_state(yyscanner);
3431 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
3432 yyextra->blockString = text;
3433 yyextra->blockLineNr = yyextra->lineNr;
3434 yyextra->blockStack.emplace(yyextra->blockString,yyextra->blockLineNr);
3439 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
3440 if (yyextra->blockStack.empty())
3442 warn(yyextra->fileName,yyextra->lineNr,
"Internal inconsistency: empty stack while attempting popBlockState");
3446 yyextra->blockStack.pop();
3448 if (yyextra->blockStack.empty())
3450 yyextra->blockString.clear();
3451 yyextra->blockLineNr=-1;
3455 yyextra->blockString=yyextra->blockStack.top().blockString;
3456 yyextra->blockLineNr=yyextra->blockStack.top().blockLineNr;
3461#include "fortranscanner.l.h"
This class represents an function or template argument list.
Clang parser object for a single translation unit, which consists of a source file and the directly o...
DString & setNum(short n)
size_t rfind(char c, size_t pos=npos) const
bool empty() const
Returns true iff the string is empty (std::string compatible alias for isEmpty()).
DString & prepend(const char *s)
int contains(char c, bool cs=true) const
char & back()
Returns a reference to the last character.
bool stripPrefix(const DString &prefix)
const char * data() const
Returns a pointer to the contents of the string in the form of a 0-terminated C string.
bool startsWith(const char *s) const
static bool isFlagSet(const DebugMask mask)
static void print(DebugMask mask, int prio, fmt::format_string< Args... > fmt, Args &&... args)
const std::vector< std::shared_ptr< Entry > > & children() const
ArgumentList argList
member arguments as a list
EntryType section
entry type (see Sections);
Specifier virt
virtualness of the entry
Protection protection
class protection
TypeSpecifier spec
class/member specifiers
void removeSubEntry(const Entry *e)
bool needsPreprocessing(const DString &extension) const override
Returns true if the language identified by extension needs the C preprocessor to be run before feed t...
void parseInput(const DString &fileName, const char *fileBuf, const std::shared_ptr< Entry > &root, ClangTUParser *clangParser) override
Parses a single input file with the goal to build an Entry tree.
std::unique_ptr< Private > p
~FortranOutlineParser() override
FortranOutlineParser(FortranFormat format=FortranFormat::Unknown)
void parsePrototype(const DString &text) override
Callback function called by the comment block scanner.
Helper class to process markdown formatted text.
DString process(const DString &input, int &startNewlines, bool fromParseInput=false)
constexpr TypeSpecifier() noexcept
#define Config_getInt(name)
DirIterator end(const DirIterator &) noexcept
const char * prepassFixedForm(const char *contents, int *hasContLine, int fixedCommentAfter)
static DString applyModifiers(DString typeName, const SymbolModifiers &mdfs)
static void initParser(yyscan_t yyscanner)
static void insertCharacter(char *contents, int length, int pos, char c)
static Argument * findArgument(Entry *subprog, DString name, bool byTypeName=false)
static void parseMain(yyscan_t yyscanner, const DString &fileName, const char *fileBuf, const std::shared_ptr< Entry > &rt, FortranFormat format)
fortranscannerYY_state extra
Private(FortranFormat fmt)
bool recognizeFixedForm(const DString &contents, FortranFormat format)