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)
Represents an unstructured piece of information, about an entity found in the sources.
Abstract interface for outline parsers.
This is an alternative implementation of QCString.
std::vector< std::shared_ptr< Entry > > EntryList
static int getAmpersandAtTheStart(const char *buf, int length)
static const char * directionParam[]
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 QCString extractFromParens(const QCString &name)
static int computeIndent(const char *s)
static void startCommentBlock(yyscan_t yyscanner, bool)
static void pushBlockState(yyscan_t yyscanner, const QCString &text)
static void startScope(yyscan_t yyscanner, Entry *scope)
static void addModule(yyscan_t yyscanner, const QCString &name=QCString(), bool isModule=FALSE)
static int getAmpOrExclAtTheEnd(const char *buf, int length, char ch)
static const CommentInPrepass * locatePrepassComment(yyscan_t yyscanner, int from, int to)
static bool endScope(yyscan_t yyscanner, Entry *scope, bool isGlobalRoot=FALSE)
static int yyread(yyscan_t yyscanner, char *buf, int max_size)
static const char * stateToString(int state)
static void popBuffer(yyscan_t yyscanner)
static void copyEntry(std::shared_ptr< Entry > dest, const std::shared_ptr< Entry > &src)
used to copy entry to an interface module procedure
static Argument * getParameter(yyscan_t yyscanner, const QCString &name)
static void subrHandleCommentBlock(yyscan_t yyscanner, const QCString &doc, bool brief)
Handle parameter description as defined after the declaration of the parameter.
static const char * directionStrs[]
static void subrHandleCommentBlockResult(yyscan_t yyscanner, const QCString &doc, bool brief)
Handle result description as defined after the declaration of the parameter.
static void scanner_abort(yyscan_t yyscanner)
static void pop_state(yyscan_t yyscanner)
static void resolveTypeBoundProcedures(Entry *scope)
static void updateVariablePrepassComment(yyscan_t yyscanner, int from, int to)
static void handleCommentBlock(yyscan_t yyscanner, const QCString &doc, bool brief)
static void pushBuffer(yyscan_t yyscanner, const QCString &buffer)
static void addSubprogram(yyscan_t yyscanner, const QCString &text)
static QCString extractBind(const QCString &name)
static void addInterface(yyscan_t yyscanner, QCString name, InterfaceType type)
static const char * getLexerFILE()
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(QCString str, int lineNr)
Holds yyextra->modifiers (ie attributes) for one symbol (variable, function, etc).
QCString type
This is only used with function return value.
SymbolModifiers & operator|=(const SymbolModifiers &mdfs)
std::map< Entry *, std::map< std::string, SymbolModifiers > > modifiers
Holds program scope->symbol name->symbol modifiers.
QCString inputStringSemi
Input string after command separator ';'.
QCString inputStringPrepass
Input string for prepass of line cont. '&'.
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
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.
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=
QCString();
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);
static void pop_state(yyscan_t yyscanner)
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());
size_t length() const
Returns the length of the string, not counting the 0-terminator.
QCString stripWhiteSpace() const
returns a copy of this string with leading and trailing whitespace removed
QCString right(size_t len) const
static void startScope(yyscan_t yyscanner)
start scope
569<InterfaceBody>^{BS}end{BS}interface({BS_}{ID})? {
573 yyextra->last_entry->parent()->endBodyLine = yyextra->lineNr - 1;
static void endScope(yyscan_t yyscanner)
end scope
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()] |=
QCString(
"public");
748 else if( yyextra->current->protection == Protection::Private )
750 yyextra->modifiers[yyextra->current_root][yyextra->current->name.lower().str()] |=
QCString(
"private");
754 startScope(yyscanner,yyextra->last_entry.get());
759<TypedefBodyContains>{
760^{BS}PROCEDURE{ARGS}? {
QCString simplifyWhiteSpace() const
return a copy of this string with leading and trailing whitespace removed and multiple whitespace cha...
764 yyextra->current->spec.setFinal(
true);
779 yyextra->modifiers[yyextra->current_root][name.
lower().
str()] |= yyextra->currentModifiers;
780 yyextra->current->section = EntryType::makeFunction();
781 yyextra->current->name = name;
783 if (yyextra->current->type.find(
'(') != -1)
789 yyextra->current->args = name.
lower();
791 yyextra->current->fileName = yyextra->fileName;
792 yyextra->current->bodyLine = yyextra->lineNr;
793 yyextra->current->startLine = yyextra->lineNr;
const std::string & str() const
798 int 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;
int find(char c, int index=0, bool cs=TRUE) const
QCString & remove(size_t index, size_t len)
QCString 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 =
"@";
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);
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.isEmpty() && !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.isEmpty())
1054 if (!yyextra->docBlock.isEmpty())
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 int 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.isEmpty())
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();
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"+
QCString(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"+
QCString(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());
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$",
QCString(yytext).lower());
1314 BEGIN(Parameterlist);
QCString substitute(const QCString &s, const QCString &src, const QCString &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());
QCString removeRedundantWhiteSpace(const QCString &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)
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();
QCString stripIndentation(const QCString &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} {
1486 warn(yyextra->fileName,yyextra->lineNr,
"Invalid line number '{}' for iline command",yytext);
1490 yyextra->lineNr = nr;
1492 yyextra->docBlock += yytext;
int toInt(bool *ok=nullptr, int base=10) const
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"|"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;
QCString 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"|"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} {
1655 BEGIN(PrototypeArgs);
1658"("|")"|","|{BS_} { yyextra->current->args += yytext; }
1659{ID} { yyextra->current->args += yytext;
1662 yyextra->current->argList.push_back(a);
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())
2200 procMap.emplace(name.
str(), cf);
2206 for (
const auto& ce1: yyextra->moduleProcedures)
2208 if (procMap.find(ce1->name.str())!=procMap.end())
2210 std::shared_ptr<Entry> proc = procMap[ce1->name.str()];
2214 yyextra->moduleProcedures.clear();
2221 int start = extracted.
find(
"(");
2224 extracted.
remove(0, start+1);
2229 size_t length = extracted.
length();
2241 if (parensPart.
length() == 1)
2256 return "bind(C, name=" + parensPart +
")";
2293 if (mdfString.
find(
"dimension")==0)
2297 else if (mdfString.
contains(
"intent"))
2301 bool isout = tmp.
contains(
"out")!=0;
2306 else if (mdfString==
"public")
2310 else if (mdfString==
"private")
2314 else if (mdfString==
"protected")
2318 else if (mdfString==
"optional")
2322 else if (mdfString==
"allocatable")
2326 else if (mdfString==
"external")
2330 else if (mdfString==
"intrinsic")
2334 else if (mdfString==
"parameter")
2338 else if (mdfString==
"pointer")
2342 else if (mdfString==
"target")
2346 else if (mdfString==
"save")
2350 else if (mdfString==
"nopass")
2354 else if (mdfString==
"deferred")
2358 else if (mdfString==
"non_overridable")
2362 else if (mdfString==
"contiguous")
2366 else if (mdfString==
"volatile")
2370 else if (mdfString==
"value")
2374 else if (mdfString.
contains(
"pass"))
2408 if ((!byTypeName && arg.
name.
lower() == cname) ||
2409 (byTypeName && arg.
type.
lower() == cname)
2424 if (!typeName.
isEmpty()) typeName +=
", ";
2429 if (!typeName.
isEmpty()) typeName +=
", ";
2434 if (!typeName.
isEmpty()) typeName +=
", ";
2435 typeName +=
"optional";
2439 if (!typeName.
isEmpty()) typeName +=
", ";
2440 typeName +=
"allocatable";
2444 if (!typeName.
contains(
"external"))
2446 if (!typeName.
isEmpty()) typeName +=
", ";
2447 typeName +=
"external";
2452 if (!typeName.
isEmpty()) typeName +=
", ";
2453 typeName +=
"intrinsic";
2457 if (!typeName.
isEmpty()) typeName +=
", ";
2458 typeName +=
"parameter";
2462 if (!typeName.
isEmpty()) typeName +=
", ";
2463 typeName +=
"pointer";
2467 if (!typeName.
isEmpty()) typeName +=
", ";
2468 typeName +=
"target";
2472 if (!typeName.
isEmpty()) typeName +=
", ";
2477 if (!typeName.
isEmpty()) typeName +=
", ";
2478 typeName +=
"deferred";
2482 if (!typeName.
isEmpty()) typeName +=
", ";
2483 typeName +=
"non_overridable";
2487 if (!typeName.
isEmpty()) typeName +=
", ";
2488 typeName +=
"nopass";
2492 if (!typeName.
isEmpty()) typeName +=
", ";
2495 typeName +=
"(" + mdfs.
passVar +
")";
2499 if (!typeName.
isEmpty()) typeName +=
", ";
2504 if (!typeName.
isEmpty()) typeName +=
", ";
2505 typeName +=
"public";
2509 if (!typeName.
isEmpty()) typeName +=
", ";
2510 typeName +=
"private";
2514 if (!typeName.
isEmpty()) typeName +=
", ";
2515 typeName +=
"protected";
2519 if (!typeName.
isEmpty()) typeName +=
", ";
2520 typeName +=
"contiguous";
2524 if (!typeName.
isEmpty()) typeName +=
", ";
2525 typeName +=
"volatile";
2529 if (!typeName.
isEmpty()) typeName +=
", ";
2530 typeName +=
"value";
2553 ent->
spec.setFinal(
true);
2557 ent->
virt = Specifier::Pure;
2566 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
2568 yyextra->current_root= scope;
2570 yyextra->modifiers.emplace(scope, std::map<std::string,SymbolModifiers>());
2573 yyextra->current = std::make_shared<Entry>();
2582 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
2583 if (yyextra->global_scope == scope)
2585 yyextra->global_scope =
nullptr;
2593 if (yyextra->current_root->parent() || isGlobalRoot)
2595 yyextra->current_root= yyextra->current_root->parent();
2599 fprintf(stderr,
"parse error in end <scopename>\n");
2605 yyextra->current = std::make_shared<Entry>();
2609 std::map<std::string,SymbolModifiers>& mdfsMap = yyextra->modifiers[scope];
2611 if (scope->
section.isFunction())
2614 for (
const auto &kv : mdfsMap)
2628 if (yyextra->modifiers[scope].find(returnName.
str())!=yyextra->modifiers[scope].end())
2630 scope->
type = yyextra->modifiers[scope][returnName.
str()].type;
2635 if (scope->
section.isClass() && scope->
spec.isInterface())
2642 for (
const auto &ce : scope->
children())
2644 if (!ce->section.isFunction())
2658 arg->
type =
"external " + ce->type +
"(";
2659 for (
unsigned int i=0; i<ce->argList.size(); i++)
2665 const Argument &subarg = ce->argList.at(i);
2673 yyextra->modifiers.erase(scope);
2679 if (!scope->
section.isFunction())
2682 for (
const auto &ce : scope->
children())
2684 if (!ce->section.isVariable() && !ce->section.isFunction() && !ce->section.isClass())
2688 if (mdfsMap.find(ce->name.lower().str())!=mdfsMap.end())
2692 if (ce->section.isVariable() || ce->section.isFunction())
2694 int end = ce->name.findRev(
":");
2696 ce->name.remove(0,
end+1);
2702 yyextra->modifiers.erase(scope);
2716 bool procMapCreated =
false;
2717 std::unordered_map<std::string,std::shared_ptr<Entry>> procMap;
2720 bool interfMapCreated =
false;
2721 std::unordered_map<std::string,std::shared_ptr<Entry>> interfMap;
2724 for (
const auto &ce: scope->
children())
2726 if (!ce->section.isClass())
2730 std::unordered_map<std::string,std::shared_ptr<Entry>> methodMap;
2731 for (
auto &ct: ce->children())
2733 if (!ct->section.isFunction())
2736 if (ct->type==
"generic")
2739 if (ct->virt==Specifier::Pure)
2743 if (!procMapCreated)
2745 for (
const auto &cf: scope->
children())
2747 if (cf->section.isFunction())
2749 procMap.emplace(cf->name.str(), cf);
2752 procMapCreated =
true;
2757 if (procMap.find(implName.
str())!=procMap.end())
2759 std::shared_ptr<Entry> proc = procMap[implName.
str()];
2760 ct->args = proc->args;
2762 if (ct->brief.isEmpty())
2764 ct->brief = proc->brief;
2765 ct->briefLine = proc->briefLine;
2766 ct->briefFile = proc->briefFile;
2768 if (ct->doc.isEmpty())
2770 ct->doc = proc->doc;
2771 ct->docLine = proc->docLine;
2772 ct->docFile = proc->docFile;
2774 methodMap.emplace(ct->name.str(), ct);
2779 for (
auto &ct: ce->children())
2781 if (!ct->section.isFunction())
2784 if (ct->virt != Specifier::Pure)
2788 if (!interfMapCreated)
2790 for(
const auto &cf: scope->
children())
2792 if (cf->section.isClass() && cf->spec.isInterface() && cf->type==
"abstract")
2794 std::shared_ptr<Entry> ci = cf->children().front();
2795 interfMap.emplace(ci->name.str(), ci);
2798 interfMapCreated =
true;
2803 if (interfMap.find(implName.
str())!= interfMap.end() )
2805 std::shared_ptr<Entry> proc = interfMap[implName.
str()];
2806 ct->args = proc->args;
2808 if (ct->brief.isEmpty())
2810 ct->brief = proc->brief;
2811 ct->briefLine = proc->briefLine;
2812 ct->briefFile = proc->briefFile;
2814 if (ct->doc.isEmpty())
2816 ct->doc = proc->doc;
2817 ct->docLine = proc->docLine;
2818 ct->docFile = proc->docFile;
2821 methodMap.emplace(ct->name.str(), ct);
2827 for (
auto &ct: ce->children())
2829 if (!ct->section.isFunction())
2832 if (ct->type!=
"generic")
2837 if (methodMap.find(methodName.
str()) != methodMap.end())
2839 std::shared_ptr<Entry> method = methodMap[methodName.
str()];
2840 ct->args = method->args;
2842 if (ct->brief.isEmpty())
2844 ct->brief = method->brief;
2845 ct->briefLine = method->briefLine;
2846 ct->briefFile = method->briefFile;
2848 if (ct->doc.isEmpty())
2850 ct->doc = method->doc;
2851 ct->docLine = method->docLine;
2852 ct->docFile = method->docFile;
2862 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
2864 while ( c < max_size && yyextra->inputString[yyextra->inputPosition] )
2866 *buf = yyextra->inputString[yyextra->inputPosition++] ;
2874 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
2875 yyextra->last_entry.reset();
2880 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
2881 if (yyextra->typeMode)
2883 yyextra->current->protection = yyextra->typeProtection;
2885 else if (yyextra->current_root && yyextra->current_root->section.isClass() && yyextra->current_root->spec.isInterface())
2887 yyextra->current->protection = Protection::Public;
2889 else if (yyextra->current_root && yyextra->current_root->section.isFunction())
2891 yyextra->current->protection = Protection::Private;
2895 yyextra->current->protection = yyextra->defaultProtection;
2897 yyextra->current->mtype = MethodTypes::Method;
2898 yyextra->current->virt = Specifier::Normal;
2899 yyextra->current->isStatic =
false;
2900 yyextra->current->lang = SrcLangExt::Fortran;
2901 yyextra->commentScanner.initGroupInfo(yyextra->current.get());
2909 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
2910 if (case_insens) yyextra->current->name = yyextra->current->name.lower();
2912 yyextra->last_entry = yyextra->current;
2913 yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current);
2919 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
2920 DBG_CTX((stderr,
"0=========> got module %s\n",
qPrint(name)));
2923 yyextra->current->section = EntryType::makeNamespace();
2925 yyextra->current->section = EntryType::makeFunction();
2929 yyextra->current->name = name;
2933 QCString fname = yyextra->fileName;
2936 if (yyextra->mainPrograms) fname +=
"__" +
QCString().
setNum(yyextra->mainPrograms);
2937 yyextra->mainPrograms++;
2939 yyextra->current->name =
substitute(fname,
".",
"_");
2941 yyextra->current->type =
"program";
2942 yyextra->current->fileName = yyextra->fileName;
2943 yyextra->current->bodyLine = yyextra->lineNr;
2944 yyextra->current->startLine = yyextra->lineNr;
2945 yyextra->current->protection = Protection::Public ;
2947 startScope(yyscanner,yyextra->last_entry.get());
2953 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
2954 DBG_CTX((stderr,
"1=========> got subprog, type: %s\n",
qPrint(text)));
2955 yyextra->subrCurrent.push_back(yyextra->current);
2956 yyextra->current->section = EntryType::makeFunction();
2958 yyextra->functionLine = (subtype.
find(
"function") != -1);
2959 yyextra->current->type +=
" " + subtype;
2963 yyextra->current->virt = Specifier::Virtual;
2965 yyextra->current->fileName = yyextra->fileName;
2966 yyextra->current->bodyLine = yyextra->lineNr;
2967 yyextra->current->startLine = yyextra->lineNr;
2968 yyextra->current->args.
clear();
2969 yyextra->current->argList.clear();
2971 yyextra->docBlock.clear();
2980 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
2981 if (YY_START == Start)
2985 yy_push_state(ModuleBody,yyscanner);
2988 yyextra->current->section = EntryType::makeClass();
2989 yyextra->current->spec =
TypeSpecifier().setInterface(
true);
2990 yyextra->current->name = name;
2995 yyextra->current->type =
"abstract";
2999 yyextra->current->type =
"generic";
3005 yyextra->current->type =
"";
3009 if ((yyextra->current_root) &&
3010 (yyextra->current_root->section.isClass() ||
3011 yyextra->current_root->section.isNamespace()))
3013 yyextra->current->name= yyextra->current_root->name +
"::" + yyextra->current->name;
3016 yyextra->current->fileName = yyextra->fileName;
3017 yyextra->current->bodyLine = yyextra->lineNr;
3018 yyextra->current->startLine = yyextra->lineNr;
3029 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
3032 for (
Argument &a:yyextra->current_root->argList)
3047 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
3050 yyextra->current->briefFile = yyextra->fileName;
3051 yyextra->current->briefLine = yyextra->lineNr;
3055 yyextra->current->docFile = yyextra->fileName;
3056 yyextra->current->docLine = yyextra->lineNr;
3064 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
3066 if (yyextra->docBlockInBody && hideInBodyDocs)
3068 yyextra->docBlockInBody =
FALSE;
3071 DBG_CTX((stderr,
"call parseCommentBlock [%s]\n",
qPrint(doc)));
3072 int lineNr = brief ? yyextra->current->briefLine : yyextra->current->docLine;
3074 bool needsEntry =
FALSE;
3075 Markdown markdown(yyextra->fileName,lineNr);
3079 while (yyextra->commentScanner.parseCommentBlock(
3080 yyextra->thisParser,
3081 yyextra->docBlockInBody ? yyextra->subrCurrent.back().get() : yyextra->current.get(),
3085 yyextra->docBlockInBody ?
FALSE : brief,
3086 yyextra->docBlockInBody ?
FALSE : yyextra->docBlockJavaStyle,
3087 yyextra->docBlockInBody,
3088 yyextra->defaultProtection,
3095 DBG_CTX((stderr,
"parseCommentBlock position=%d [%s] needsEntry=%d\n",position,doc.
data()+position,needsEntry));
3098 DBG_CTX((stderr,
"parseCommentBlock position=%d [%s] needsEntry=%d\n",position,doc.
data()+position,needsEntry));
3101 yyextra->docBlockInBody =
FALSE;
3108 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
3112 std::shared_ptr<Entry> tmp_entry = yyextra->current;
3113 yyextra->current = yyextra->subrCurrent.back();
3116 yyextra->current->inbodyDocs =
"";
3125 int dir1 = yyextra->modifiers[yyextra->current_root][yyextra->argName.lower().str()].direction;
3140 yyextra->argName +
" " + loc_doc,brief);
3146 warn(yyextra->fileName,yyextra->lineNr,
"Routine: {}{} inconsistency between intent attribute and documentation for parameter {}:",
3147 yyextra->current->name,yyextra->current->args,yyextra->argName);
3149 yyextra->argName +
" " + loc_doc,brief);
3162 yyextra->current = tmp_entry;
3166 yyextra->argName +
" " + loc_doc,brief);
3170 warn(yyextra->fileName,yyextra->lineNr,
"Routine: {}{} inconsistency between intent attribute and documentation for parameter {}:",
3171 yyextra->current->name,yyextra->current->args,yyextra->argName);
3173 yyextra->argName +
" " + loc_doc,brief);
3187 yyextra->argName +
" " + loc_doc,brief);
3192 warn(yyextra->fileName,yyextra->lineNr,
"Routine: {}{} inconsistency between intent attribute and documentation for parameter {}:",
3193 yyextra->current->name,yyextra->current->args,yyextra->argName);
3195 yyextra->argName +
" " + loc_doc,brief);
3202 yyextra->argName +
" " + loc_doc,brief);
3206 yyextra->current = tmp_entry;
3212 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
3216 std::shared_ptr<Entry> tmp_entry = yyextra->current;
3217 yyextra->current = yyextra->subrCurrent.back();
3220 yyextra->current->inbodyDocs =
"";
3236 yyextra->current = std::move(tmp_entry);
3244 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
3245 char *tmpBuf =
nullptr;
3248 if (fileBuf==
nullptr || fileBuf[0]==
'\0')
return;
3250 yyextra->defaultProtection = Protection::Public;
3251 yyextra->inputString = fileBuf;
3252 yyextra->inputPosition = 0;
3253 yyextra->inputStringPrepass =
nullptr;
3254 yyextra->inputPositionPrepass = 0;
3257 yyextra->current_root = rt.get();
3258 yyextra->global_root = rt;
3262 if (yyextra->isFixedForm)
3264 yyextra->fixedCommentAfter =
Config_getInt(FORTRAN_COMMENT_AFTER);
3265 msg(
"Prepassing fixed form of {}\n", fileName);
3271 yyextra->inputString =
prepassFixedForm(fileBuf,
nullptr,yyextra->fixedCommentAfter);
3280 else if (yyextra->inputString[strlen(fileBuf)-1] !=
'\n')
3282 tmpBuf = (
char *)malloc(strlen(fileBuf)+2);
3283 strcpy(tmpBuf,fileBuf);
3284 tmpBuf[strlen(fileBuf)]=
'\n';
3285 tmpBuf[strlen(fileBuf)+1]=
'\000';
3286 yyextra->inputString = tmpBuf;
3289 yyextra->lineNr= 1 ;
3290 yyextra->fileName = fileName;
3291 msg(
"Parsing file {}...\n",yyextra->fileName);
3293 yyextra->global_scope = rt.get();
3296 yyextra->commentScanner.enterFile(yyextra->fileName,yyextra->lineNr);
3299 yyextra->current = std::make_shared<Entry>();
3300 yyextra->current->lang = SrcLangExt::Fortran;
3301 yyextra->current->name = yyextra->fileName;
3302 yyextra->current->section = EntryType::makeSource();
3303 yyextra->file_root = yyextra->current;
3304 yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current);
3305 yyextra->current->lang = SrcLangExt::Fortran;
3307 fortranscannerYYrestart(
nullptr, yyscanner );
3312 fortranscannerYYlex(yyscanner);
3313 yyextra->commentScanner.leaveFile(yyextra->fileName,yyextra->lineNr);
3315 if (yyextra->global_scope && yyextra->global_scope !=
INVALID_ENTRY)
3322 rt->program.str(std::string());
3324 yyextra->moduleProcedures.clear();
3327 free((
char*)tmpBuf);
3328 yyextra->inputString=
nullptr;
3330 if (yyextra->isFixedForm)
3332 free((
char*)yyextra->inputString);
3333 yyextra->inputString=
nullptr;
3355 :
p(std::make_unique<
Private>(format))
3361 fortranscannerYYlex_destroy(
p->yyscanner);
3365 const char *fileBuf,
3366 const std::shared_ptr<Entry> &root,
3369 struct yyguts_t *yyg = (
struct yyguts_t*)
p->yyscanner;
3370 yyextra->thisParser =
this;
3379 return extension!=extension.
lower();
3384 struct yyguts_t *yyg = (
struct yyguts_t*)
p->yyscanner;
3386 yyextra->parsingPrototype =
TRUE;
3388 fortranscannerYYlex(
p->yyscanner);
3389 yyextra->parsingPrototype =
FALSE;
3397 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
3398 fprintf(stderr,
"********************************************************************\n");
3399 if (yyextra->blockLineNr == -1)
3401 fprintf(stderr,
"Error in file %s line: %d, state: %d(%s)\n",
3406 fprintf(stderr,
"Error in file %s line: %d, state: %d(%s), starting command: '%s' probable line reference: %d\n",
3407 qPrint(yyextra->fileName),yyextra->lineNr,YY_START,
stateToString(YY_START),
qPrint(yyextra->blockString),yyextra->blockLineNr);
3409 fprintf(stderr,
"********************************************************************\n");
3412 while (!yyextra->blockStack.empty()) yyextra->blockStack.pop();
3416 for (
const auto &ce : yyextra->global_root->children())
3418 if (ce == yyextra->file_root) start=
TRUE;
3419 if (start) ce->reset();
3423 (void)yy_top_state(yyscanner);
3431 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
3432 if ( yyg->yy_start_stack_ptr <= 0 )
3433 warn(yyextra->fileName,yyextra->lineNr,
"Unexpected statement '{}'",yytext );
3435 yy_pop_state(yyscanner);
3440 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
3441 yyextra->blockString = text;
3442 yyextra->blockLineNr = yyextra->lineNr;
3443 yyextra->blockStack.emplace(yyextra->blockString,yyextra->blockLineNr);
3448 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
3449 if (yyextra->blockStack.empty())
3451 warn(yyextra->fileName,yyextra->lineNr,
"Internal inconsistency: empty stack while attempting popBlockState");
3455 yyextra->blockStack.pop();
3457 if (yyextra->blockStack.empty())
3459 yyextra->blockString.clear();
3460 yyextra->blockLineNr=-1;
3464 yyextra->blockString=yyextra->blockStack.top().blockString;
3465 yyextra->blockLineNr=yyextra->blockStack.top().blockLineNr;
3470#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...
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 QCString &extension) const override
Returns TRUE if the language identified by extension needs the C preprocessor to be run before feed t...
std::unique_ptr< Private > p
void parsePrototype(const QCString &text) override
Callback function called by the comment block scanner.
~FortranOutlineParser() override
FortranOutlineParser(FortranFormat format=FortranFormat::Unknown)
void parseInput(const QCString &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.
Helper class to process markdown formatted text.
QCString process(const QCString &input, int &startNewlines, bool fromParseInput=false)
QCString & prepend(const char *s)
bool startsWith(const char *s) const
QCString mid(size_t index, size_t len=static_cast< size_t >(-1)) const
bool isEmpty() const
Returns TRUE iff the string is empty.
QCString & setNum(short n)
QCString & append(char c)
int findRev(char c, int index=-1, bool cs=TRUE) const
const char * data() const
Returns a pointer to the contents of the string in the form of a 0-terminated C string.
int contains(char c, bool cs=TRUE) const
bool stripPrefix(const QCString &prefix)
Wrapper class for a number of boolean properties.
static const char * stateToString(int state)
#define Config_getInt(name)
DirIterator end(const DirIterator &) noexcept
const char * prepassFixedForm(const char *contents, int *hasContLine, int fixedCommentAfter)
const char * prepassFixedForm(const char *contents, int *hasContLine, int fixedCommentAfter)
static void parseMain(yyscan_t yyscanner, const QCString &fileName, const char *fileBuf, const std::shared_ptr< Entry > &rt, FortranFormat format)
static void initParser(yyscan_t yyscanner)
static QCString applyModifiers(QCString typeName, const SymbolModifiers &mdfs)
static Argument * findArgument(Entry *subprog, QCString name, bool byTypeName=FALSE)
static void insertCharacter(char *contents, int length, int pos, char c)
fortranscannerYY_state extra
Private(FortranFormat fmt)
bool recognizeFixedForm(const QCString &contents, FortranFormat format)