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
63#include <unordered_map>
64#include <unordered_set>
80#define DBG_CTX(x) do { } while(0)
83#define YY_NO_UNISTD_H 1
140 "",
"intent(in)",
"intent(out)",
"intent(inout)"
144 "",
"[in]",
"[out]",
"[in,out]"
216 std::map<Entry*,std::map<std::string,SymbolModifiers> >
modifiers;
249static void copyEntry(std::shared_ptr<Entry> dest,
const std::shared_ptr<Entry> &src);
266#define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size);
271#define YY_USER_ACTION yyextra->colNr+=(int)yyleng;
272#define INVALID_ENTRY ((Entry*)0x8)
This class contains the information about the argument of a function or template.
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.
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 int yyread(yyscan_t yyscanner, char *buf, int max_size)
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 const char * getLexerFILE()
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)
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.
284ID [a-z_A-Z%]+{IDSYM}*
285ID_ [a-z_A-Z%]*{IDSYM}*
286OPERATOR_ID (operator{BS}"("{BS}(\.[a-z_A-Z]+\.|"="|"/="|"//"|"=="|"<"|"<="|">"|">="|"+"|"*"|"**"|"/"|"-"){BS}")")
287SUBPROG (subroutine|function)
291BT_ ([ \t]+|[ \t]*"(")
294ARGS_L1a [^()]*"("[^)]*")"[^)]*
295ARGS_L1 ("("{ARGS_L1a}*")")
296ARGS_L2 "("({ARGS_L0}|[^()]|{ARGS_L1a}|{ARGS_L1})*")"
297ARGS {BS}({ARGS_L0}|{ARGS_L1}|{ARGS_L2})
304NUM_TYPE (complex|integer|logical|real)
305LOG_OPER (\.and\.|\.eq\.|\.eqv\.|\.ge\.|\.gt\.|\.le\.|\.lt\.|\.ne\.|\.neqv\.|\.or\.|\.not\.)
307CHAR (CHARACTER{ARGS}?|CHARACTER{BS}"*"({BS}[0-9]+|{ARGS}))
308TYPE_SPEC (({NUM_TYPE}({BS}"*"{BS}[0-9]+)?)|({NUM_TYPE}{KIND})|DOUBLE{BS}COMPLEX|DOUBLE{BS}PRECISION|ENUMERATOR|{CHAR}|TYPE{ARGS}|CLASS{ARGS}|PROCEDURE{ARGS}?)
310INTENT_SPEC intent{BS}"("{BS}(in|out|in{BS}out){BS}")"
311ATTR_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)
312LANGUAGE_BIND_SPEC BIND{BS}"("{BS}C{BS}((,{BS}NAME{BS}"="{BS}"\""(.*)"\""{BS})|(,{BS}NAME{BS}"="{BS}"'"(.*)"'"{BS}))?")"
314ATTR_STMT {ATTR_SPEC}|DIMENSION
315EXTERNAL_STMT (EXTERNAL)
318PREFIX ((NON_)?RECURSIVE{BS_}|IMPURE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,4}((NON_)?RECURSIVE|IMPURE|PURE|ELEMENTAL)?
319SCOPENAME ({ID}{BS}"::"{BS})*
321LINENR {B}*[1-9][0-9]*
322FILEICHAR [a-z_A-Z0-9\x80-\xFF\\:\\\/\-\+=&#@~]
323FILEECHAR [a-z_A-Z0-9\x80-\xFF\-\+=&#@~]
324FILECHARS {FILEICHAR}*{FILEECHAR}+
325HFILEMASK {FILEICHAR}*("."{FILEICHAR}+)+{FILECHARS}*
326VFILEMASK {FILECHARS}("."{FILECHARS})*
327FILEMASK {VFILEMASK}|{HFILEMASK}
341%x SubprogBodyContains
355%x TypedefBodyContains
381<Prepass>^{BS}[&]*{BS}!.*\n {
382 yyextra->lineCountPrepass ++;
385 yyextra->lineCountPrepass ++;
388 yyextra->functionLine =
false;
390 DBG_CTX((stderr,
"---%s", yytext));
394 if (indexEnd>=0 && yytext[indexEnd]!=
'&')
401 if (YY_START == Prepass)
405 yyextra->inputStringPrepass+=(
const char*)(yytext+(indexStart+1));
408 pushBuffer(yyscanner,yyextra->inputStringPrepass);
420 if (YY_START != Prepass)
422 yyextra->comments.clear();
423 yyextra->inputStringPrepass=
DString();
424 yy_push_state(Prepass,yyscanner);
427 size_t length = yyextra->inputStringPrepass.length();
430 yyextra->inputStringPrepass+=(
const char*)(yytext+(indexStart+1));
431 yyextra->lineCountPrepass ++;
434 truncatePrepass(yyscanner,
static_cast<int>(length) + indexEnd - indexStart - 1);
441 if (yytext[0]!=yyextra->stringStartSymbol)
443 yyextra->colNr -= (int)yyleng;
446 if (yy_top_state(yyscanner) == Initialization ||
447 yy_top_state(yyscanner) == ArrayInitializer)
449 yyextra->initializer+=yytext;
453<String>[\x80-\xFF]* |
454<String>. {
if (yy_top_state(yyscanner) == Initialization ||
455 yy_top_state(yyscanner) == ArrayInitializer)
457 yyextra->initializer+=yytext;
461 if (YY_START == StrIgnore)
462 { yyextra->colNr -= (int)yyleng;
465 yy_push_state(YY_START,yyscanner);
466 if (yy_top_state(yyscanner) == Initialization ||
467 yy_top_state(yyscanner) == ArrayInitializer)
469 yyextra->initializer+=yytext;
471 yyextra->stringStartSymbol=yytext[0];
477<*>"!"/([^<>\n]|"<ff>"|"<FF>") {
if (YY_START == String || YY_START == DocCopyBlock)
478 { yyextra->colNr -= (int)yyleng;
483 if ((YY_START != StrIgnore) && (YY_START != String))
485 yy_push_state(YY_START,yyscanner);
487 yyextra->debugStr=
"*!";
488 DBG_CTX((stderr,
"start comment %d\n",yyextra->lineNr));
492 DBG_CTX((stderr,
"end comment %d %s\n",yyextra->lineNr,
qPrint(yyextra->debugStr)));
const char * qPrint(const char *s)
494<StrIgnore>[\x80-\xFF]* |
495<StrIgnore>. { yyextra->debugStr+=yytext; }
500<Start,ModuleBody,SubprogBody>"use"{BS_} {
501 if (YY_START == Start)
505 yy_push_state(ModuleBody,yyscanner);
507 yy_push_state(Use,yyscanner);
510 DBG_CTX((stderr,
"using dir %s\n",yytext));
511 yyextra->current->name=yytext;
512 yyextra->current->name=yyextra->current->name.lower();
513 yyextra->current->fileName = yyextra->fileName;
514 yyextra->current->section=EntryType::makeUsingDir();
515 yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current);
516 yyextra->current->lang = SrcLangExt::Fortran;
520 yyextra->useModuleName=yytext;
521 yyextra->useModuleName=yyextra->useModuleName.lower();
523<Use>,{BS}"ONLY" { BEGIN(UseOnly);
527 yyextra->current->name= yyextra->useModuleName+
"::"+yytext;
528 yyextra->current->name=yyextra->current->name.lower();
529 yyextra->current->fileName = yyextra->fileName;
530 yyextra->current->section=EntryType::makeUsingDecl();
531 yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current);
532 yyextra->current->lang = SrcLangExt::Fortran;
541<Start,ModuleBody,SubprogBody>{
542^{BS}interface{IDSYM}+ { }
544 yy_push_state(InterfaceBody,yyscanner);
549^{BS}abstract{BS_}interface { yyextra->ifType =
IF_ABSTRACT;
550 yy_push_state(InterfaceBody,yyscanner);
555^{BS}interface{BS_}{ID}{ARGS}? { yyextra->ifType =
IF_GENERIC;
556 yyextra->current->bodyLine = yyextra->lineNr + yyextra->lineCountPrepass + 1;
557 yy_push_state(InterfaceBody,yyscanner);
563 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
567<InterfaceBody>^{BS}end{BS}interface({BS_}{ID})? {
571 yyextra->last_entry->parent()->endBodyLine = yyextra->lineNr - 1;
580<InterfaceBody>module{BS}procedure { yy_push_state(YY_START,yyscanner);
581 BEGIN(ModuleProcedure);
587 startScope(yyscanner,yyextra->last_entry.get());
590 yyextra->current->section = EntryType::makeFunction();
591 yyextra->current->name = name;
592 yyextra->moduleProcedures.
push_back(yyextra->current);
595<ModuleProcedure>"\n" { yyextra->colNr -= 1;
602<Start>^{BS}{CONTAINS}/({BS}|\n|!|;) {
603 if (YY_START == Start)
606 yy_push_state(ModuleBodyContains,yyscanner);
609<ModuleBody>^{BS}{CONTAINS}/({BS}|\n|!|;) { BEGIN(ModuleBodyContains); }
610<SubprogBody>^{BS}{CONTAINS}/({BS}|\n|!|;) { BEGIN(SubprogBodyContains); }
611<TypedefBody>^{BS}{CONTAINS}/({BS}|\n|!|;) { BEGIN(TypedefBodyContains); }
614<Start>block{BS}data{BS}{ID_} {
616 yy_push_state(BlockData,yyscanner);
617 yyextra->defaultProtection = Protection::Public;
619<Start>module|program{BS_} {
621 if (yytext[0]==
'm' || yytext[0]==
'M')
623 yy_push_state(Module,yyscanner);
627 yy_push_state(Program,yyscanner);
629 yyextra->defaultProtection = Protection::Public;
631<BlockData>^{BS}"end"({BS}(block{BS}data)({BS_}{ID})?)?{BS}/(\n|!|;) {
634 yyextra->defaultProtection = Protection::Public;
637<Start,ModuleBody,ModuleBodyContains>"end"({BS}(module|program)({BS_}{ID})?)?{BS}/(\n|!|;) {
639 if (!
endScope(yyscanner,yyextra->current_root))
643 yyextra->defaultProtection = Protection::Public;
644 if (yyextra->global_scope)
648 yy_push_state(Start,yyscanner);
657 yy_push_state(Start,yyscanner);
675<ModuleBody,TypedefBody,TypedefBodyContains>private/{BS}(\n|"!") {
676 yyextra->defaultProtection = Protection::Private;
677 yyextra->current->protection = yyextra->defaultProtection ;
679<ModuleBody,TypedefBody,TypedefBodyContains>public/{BS}(\n|"!") {
680 yyextra->defaultProtection = Protection::Public;
681 yyextra->current->protection = yyextra->defaultProtection ;
686<ModuleBody>^{BS}type{BS}"=" {}
687<Start,ModuleBody>^{BS}type/[^a-z0-9_] {
688 if (YY_START == Start)
692 yy_push_state(ModuleBody,yyscanner);
695 yy_push_state(Typedef,yyscanner);
696 yyextra->current->protection = Protection::Package;
697 yyextra->typeProtection = Protection::Public;
698 yyextra->typeMode =
true;
706 yyextra->current->spec.setAbstractClass(
true);
710 yyextra->current->extends.emplace_back(basename, Protection::Public, Specifier::Normal);
713 yyextra->current->protection = Protection::Public;
716 yyextra->current->protection = Protection::Private;
718{LANGUAGE_BIND_SPEC} {
722 yyextra->current->section = EntryType::makeClass();
723 yyextra->current->spec.setStruct(
true);
724 yyextra->current->name = yytext;
725 yyextra->current->fileName = yyextra->fileName;
726 yyextra->current->bodyLine = yyextra->lineNr;
727 yyextra->current->startLine = yyextra->lineNr;
730 if (yyextra->current_root &&
731 (yyextra->current_root->section.isClass() ||
732 yyextra->current_root->section.isNamespace()))
734 yyextra->current->name = yyextra->current_root->name +
"::" + yyextra->current->name;
738 if( yyextra->current->protection == Protection::Package )
740 yyextra->current->protection = yyextra->defaultProtection;
742 else if( yyextra->current->protection == Protection::Public )
744 yyextra->modifiers[yyextra->current_root][yyextra->current->name.lower().str()] |=
DString(
"public");
746 else if( yyextra->current->protection == Protection::Private )
748 yyextra->modifiers[yyextra->current_root][yyextra->current->name.lower().str()] |=
DString(
"private");
752 startScope(yyscanner,yyextra->last_entry.get());
757<TypedefBodyContains>{
758^{BS}PROCEDURE{ARGS}? {
DString simplifyWhiteSpace() const
return a copy of this string with leading and trailing whitespace removed and multiple internal white...
762 yyextra->current->spec.setFinal(
true);
777 yyextra->modifiers[yyextra->current_root][name.
lower().
str()] |= yyextra->currentModifiers;
778 yyextra->current->section = EntryType::makeFunction();
779 yyextra->current->name = name;
787 yyextra->current->args = name.
lower();
789 yyextra->current->fileName = yyextra->fileName;
790 yyextra->current->bodyLine = yyextra->lineNr;
791 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
796 size_t i = tmp.
find(
"=>");
802 if (yyextra->last_entry->type ==
"generic")
810 copyEntry(yyextra->current, yyextra->last_entry);
811 yyextra->current->name = yyextra->last_entry->name;
812 yyextra->current->section = EntryType::makeFunction();
821 yyextra->last_entry->args = tmp;
DString & remove(size_t index, size_t len)
size_t find(char c, size_t pos=0) const
DString left(size_t len) const
826 yyextra->docBlock.clear();
831<TypedefBody,TypedefBodyContains>{
832^{BS}"end"{BS}"type"({BS_}{ID})?{BS}/(\n|!|;) {
833 yyextra->last_entry->parent()->endBodyLine = yyextra->lineNr;
834 if (!
endScope(yyscanner,yyextra->current_root))
838 yyextra->typeMode =
false;
841^{BS}"end"{BS}/(\n|!|;) {
842 warn(yyextra->fileName,yyextra->lineNr,
"Found 'END' instead of 'END TYPE'");
843 yyextra->last_entry->parent()->endBodyLine = yyextra->lineNr;
844 if (!
endScope(yyscanner,yyextra->current_root))
848 yyextra->typeMode =
false;
#define warn(file, line, fmt,...)
855<SubprogBody,SubprogBodyContains>^{BS}[0-9]*{BS}"end"({BS}{SUBPROG}({BS_}{ID})?)?{BS}/(\n|!|;) {
863 endScope(yyscanner,yyextra->current_root);
864 yyextra->last_entry->endBodyLine = yyextra->lineNr - 1;
866 yyextra->current_root->endBodyLine = yyextra->lineNr - 1;
868 if (!
endScope(yyscanner,yyextra->current_root))
872 yyextra->subrCurrent.pop_back();
881<Start,ModuleBody,TypedefBody,SubprogBody,FEnum>{
882^{BS}{TYPE_SPEC}/{SEPARATE} {
883 yyextra->last_enum.reset();
884 if (YY_START == FEnum)
886 yyextra->argType =
"@";
892 yyextra->current->bodyLine = yyextra->lineNr + 1;
893 yyextra->current->endBodyLine = yyextra->lineNr + yyextra->lineCountPrepass;
895 if (YY_START == Start)
899 yy_push_state(ModuleBody,yyscanner);
901 yy_push_state(AttributeList,yyscanner);
903{EXTERNAL_STMT}/({BS}"::"|{BS_}{ID}) {
905 if (YY_START == Start)
909 yy_push_state(ModuleBody,yyscanner);
914 yy_push_state(AttributeList,yyscanner);
916{ATTR_STMT}/{BS_}{ID} |
917{ATTR_STMT}/{BS}"::" {
919 DBG_CTX((stderr,
"5=========> Attribute statement: %s\n", yytext));
920 if (YY_START == Start)
924 yy_push_state(ModuleBody,yyscanner);
929 yy_push_state(YY_START,yyscanner);
930 BEGIN( AttributeList ) ;
933 if (YY_START == Start)
937 yy_push_state(ModuleBody,yyscanner);
945 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...
948^{BS}"type"{BS_}"is"/{BT_} {}
950^{BS}"class"{BS_}"is"/{BT_} {}
951^{BS}"class"{BS_}"default" {}
956{LANGUAGE_BIND_SPEC} {
957 yyextra->currentModifiers |= yytext;
961 char chr = yytext[(int)yyleng-1];
964 yyextra->colNr -= (int)yyleng;
972 unput(yytext[(
int)yyleng-1]);
973 yyextra->currentModifiers |= (tmp);
size_t length() const
Returns the length of the string, not counting the 0-terminator.
bool isId(int c)
Returns true if c is a valid character for an identifier.
988<FVariable>{OPERATOR_ID} {
992 int currentState = YY_START;
994 int outerState = YY_START;
995 yy_push_state(currentState,yyscanner);
996 if( outerState == Start || outerState == ModuleBody )
998 if ((yyextra->current_root) &&
999 (yyextra->current_root->section.isClass() ||
1000 yyextra->current_root->section.isNamespace()))
1002 name = yyextra->current_root->name +
"::" + name;
1006 yyextra->modifiers[yyextra->current_root][name.
str()] |= yyextra->currentModifiers;
1012 name = name.
lower();
1014 if ((yyextra->current_root) && yyextra->current_root->section.isNamespace())
1016 name = yyextra->current_root->name +
"::" + name;
1019 yyextra->modifiers[yyextra->current_root][name.
lower().
str()] |= yyextra->currentModifiers;
1020 yyextra->argName= name;
1023 if (!yyextra->argType.empty() && !yyextra->current_root->section.isFunction())
1026 yyextra->current->section = EntryType::makeVariable();
1027 yyextra->current->name = yyextra->argName;
1028 yyextra->current->type = yyextra->argType;
1029 yyextra->current->fileName = yyextra->fileName;
1030 yyextra->current->bodyLine = yyextra->lineNr;
1031 yyextra->current->startLine = yyextra->lineNr;
1032 if (yyextra->argType ==
"@")
1034 yyextra->current_root->copyToSubEntry(yyextra->current);
1036 yyextra->last_enum = yyextra->current;
1037 yyextra->current_root->parent()->moveToSubEntryAndRefresh(yyextra->current);
1045 else if (!yyextra->argType.empty())
1052 if (!yyextra->docBlock.empty())
1060 yyextra->modifiers[yyextra->current_root][name.
lower().
str()].type = yyextra->argType;
1064 if ((yyextra->current_root->name.lower() == yyextra->argName.lower()) ||
1065 (yyextra->modifiers[yyextra->current_root->parent()][yyextra->current_root->name.lower().str()].returnName.lower() == yyextra->argName.lower()))
1067 size_t strt = yyextra->current_root->type.find(
"function");
1076 if ((yyextra->current_root->type.length() - strt - strlen(
"function"))!= 0)
1078 rght = yyextra->current_root->type.
right(yyextra->current_root->type.length() - strt - (
int)strlen(
"function")).
stripWhiteSpace();
1080 yyextra->current_root->type = lft;
1083 if (yyextra->current_root->type.length() > 0) yyextra->current_root->type +=
" ";
1084 yyextra->current_root->type += rght;
1086 if (yyextra->argType.stripWhiteSpace().length() > 0)
1088 if (yyextra->current_root->type.length() > 0) yyextra->current_root->type +=
" ";
1089 yyextra->current_root->type += yyextra->argType.stripWhiteSpace();
1091 if (yyextra->current_root->type.length() > 0) yyextra->current_root->type +=
" ";
1092 yyextra->current_root->type +=
"function";
1093 if (!yyextra->docBlock.empty())
1100 yyextra->current_root->type +=
" " + yyextra->argType.stripWhiteSpace();
1102 yyextra->current_root->type = yyextra->current_root->type.
stripWhiteSpace();
1103 yyextra->modifiers[yyextra->current_root][name.
lower().
str()].type = yyextra->current_root->type;
1107 yyextra->modifiers[yyextra->current_root][name.
lower().
str()].type = yyextra->argType;
1113 yyextra->current->doc.clear();
1114 yyextra->current->brief.clear();
DString right(size_t len) const
1118 DString name(yyextra->argName);
1121 yyextra->modifiers[yyextra->current_root][name.
lower().
str()] |= attr;
1128 yy_push_state(YY_START,yyscanner);
1129 yyextra->initializer=
"=";
1130 yyextra->initializerScope = yyextra->initializerArrayScope = 0;
1131 BEGIN(Initialization);
1136 yyextra->docBlock.clear();
1140 yyextra->docBlock.clear();
1141 yyextra->inputStringSemi =
" \n"+
DString(yytext+1);
1143 pushBuffer(yyscanner,yyextra->inputStringSemi);
1146 if (YY_START == FVariable) REJECT;
1147 if (YY_START == String) REJECT;
1148 if (YY_START == StrIgnore) REJECT;
1149 if (YY_START == DocBlock) REJECT;
1150 yyextra->inputStringSemi =
" \n"+
DString(yytext+1);
1152 pushBuffer(yyscanner,yyextra->inputStringSemi);
1155<Initialization,ArrayInitializer>"[" |
1156<Initialization,ArrayInitializer>"(/" { yyextra->initializer+=yytext;
1157 yyextra->initializerArrayScope++;
1158 BEGIN(ArrayInitializer);
1160<ArrayInitializer>"]" |
1161<ArrayInitializer>"/)" { yyextra->initializer+=yytext;
1162 yyextra->initializerArrayScope--;
1163 if (yyextra->initializerArrayScope<=0)
1165 yyextra->initializerArrayScope = 0;
1166 BEGIN(Initialization);
1169<ArrayInitializer>. { yyextra->initializer+=yytext; }
1170<Initialization>"(" { yyextra->initializerScope++;
1171 yyextra->initializer+=yytext;
1173<Initialization>")" { yyextra->initializerScope--;
1174 yyextra->initializer+=yytext;
1176<Initialization>{COMMA} {
if (yyextra->initializerScope == 0)
1180 if (yyextra->last_enum)
1182 yyextra->last_enum->initializer.str(yyextra->initializer.str());
1186 if (yyextra->vtype ==
V_VARIABLE) yyextra->last_entry->initializer.str(yyextra->initializer.str());
1191 yyextra->initializer+=
", ";
1194<Initialization>"\n"|"!" {
1196 if (yyextra->last_enum)
1198 yyextra->last_enum->initializer.str(yyextra->initializer.str());
1202 if (yyextra->vtype ==
V_VARIABLE) yyextra->last_entry->initializer.str(yyextra->initializer.str());
1204 yyextra->colNr -= 1;
1207<Initialization>. { yyextra->initializer+=yytext; }
1209<*>{BS}"enum"{BS}","{BS}"bind"{BS}"("{BS}"c"{BS}")"{BS} {
1210 if (YY_START == Start)
1214 yy_push_state(ModuleBody,yyscanner);
1217 yy_push_state(FEnum,yyscanner);
1218 yyextra->current->protection = yyextra->defaultProtection;
1219 yyextra->typeProtection = yyextra->defaultProtection;
1220 yyextra->typeMode =
true;
1222 yyextra->current->spec.setStruct(
true);
1223 yyextra->current->name.clear();
1224 yyextra->current->args.clear();
1225 yyextra->current->name.sprintf(
"@%d",yyextra->anonCount++);
1227 yyextra->current->section = EntryType::makeEnum();
1228 yyextra->current->fileName = yyextra->fileName;
1229 yyextra->current->startLine = yyextra->lineNr;
1230 yyextra->current->bodyLine = yyextra->lineNr;
1231 if ((yyextra->current_root) &&
1232 (yyextra->current_root->section.isClass() ||
1233 yyextra->current_root->section.isNamespace()))
1235 yyextra->current->name = yyextra->current_root->name +
"::" + yyextra->current->name;
1239 startScope(yyscanner,yyextra->last_entry.get());
1242<FEnum>"end"{BS}"enum" {
1243 yyextra->last_entry->parent()->endBodyLine = yyextra->lineNr;
1244 if (!
endScope(yyscanner,yyextra->current_root))
1248 yyextra->typeMode =
false;
1254<Start,ModuleBody,SubprogBody,InterfaceBody,ModuleBodyContains,SubprogBodyContains>^{BS}({PREFIX}{BS_})?{TYPE_SPEC}{BS}({PREFIX}{BS_})?/{SUBPROG}{BS_} {
1257 addInterface(yyscanner,
"$interface$", yyextra->ifType);
1258 startScope(yyscanner,yyextra->last_entry.get());
1263 yy_push_state(SubprogPrefix,yyscanner);
1266<SubprogPrefix>{BS}{SUBPROG}{BS_} {
1273 yyextra->current->bodyLine = yyextra->lineNr + yyextra->lineCountPrepass + 1;
1274 yyextra->current->startLine = yyextra->lineNr;
1277<Start,ModuleBody,SubprogBody,InterfaceBody,ModuleBodyContains,SubprogBodyContains>^{BS}({PREFIX}{BS_})?{SUBPROG}{BS_} {
1282 addInterface(yyscanner,
"$interface$", yyextra->ifType);
1283 startScope(yyscanner,yyextra->last_entry.get());
1288 yy_push_state(Subprog,yyscanner);
1289 yyextra->current->bodyLine = yyextra->lineNr + yyextra->lineCountPrepass + 1;
1290 yyextra->current->startLine = yyextra->lineNr;
1294<Subprog>{ID} { yyextra->current->name = yytext;
1298 if ((yyextra->current_root) &&
1299 (yyextra->current_root->section.isClass() ||
1300 yyextra->current_root->section.isNamespace()))
1302 yyextra->current->name= yyextra->current_root->name +
"::" + yyextra->current->name;
1304 yyextra->modifiers[yyextra->current_root][yyextra->current->name.lower().str()].returnName = std::move(returnName);
1309 yyextra->current_root->name,
"$interface$",
DString(yytext).lower());
1312 BEGIN(Parameterlist);
DString substitute(const DString &s, const DString &src, const DString &dst)
substitute all occurrences of src in s by dst
1314<Parameterlist>"(" { yyextra->current->args =
"("; }
1316 yyextra->current->args +=
")";
1319 startScope(yyscanner,yyextra->last_entry.get());
DString removeRedundantWhiteSpace(const DString &s)
1322<Parameterlist>{COMMA}|{BS} { yyextra->current->args += yytext;
1326 if (!yyextra->current->argList.empty())
1328 yyextra->current->argList.back().docs = c->
str;
1332<Parameterlist>{ID} {
1336 yyextra->current->args += param;
1340 yyextra->current->argList.
push_back(arg);
1342<Parameterlist>{NOARGS} {
1346 startScope(yyscanner,yyextra->last_entry.get());
1349<SubprogBody>result{BS}\({BS}{ID} {
1350 if (yyextra->functionLine)
1353 result= result.
mid(result.
find(
'(')+1);
1355 yyextra->modifiers[yyextra->current_root->parent()][yyextra->current_root->name.lower().str()].returnName = result;
1362<FVariable,SubprogBody,ModuleBody,TypedefBody,TypedefBodyContains>"!<" {
1365 yyextra->current->docLine = yyextra->lineNr;
1366 yyextra->docBlockJavaStyle =
false;
1367 yyextra->docBlock.clear();
1370 yy_push_state(DocBackLine,yyscanner);
1375 if (YY_START == String)
1377 yyextra->colNr -= (int)yyleng;
1382 if ((YY_START != StrIgnore) && (YY_START != String))
1384 yy_push_state(YY_START,yyscanner);
1386 yyextra->debugStr=
"*!";
#define Config_getBool(name)
1391 yyextra->docBlock+=yytext;
1393<DocBackLine>"\n"{BS}"!"("<"|"!"+) {
1394 yyextra->docBlock+=
"\n";
1399 yyextra->colNr -= 1;
1403 std::shared_ptr<Entry> tmp_entry = yyextra->current;
1405 if (yyextra->last_enum)
1407 yyextra->current = yyextra->last_enum;
1411 yyextra->current = yyextra->last_entry;
1415 yyextra->current = std::move(tmp_entry);
1421 else if (yyextra->vtype ==
V_RESULT)
1426 yyextra->docBlock.clear();
DString stripIndentation(const DString &s, bool skipFirstLine)
1429<Start,SubprogBody,ModuleBody,TypedefBody,InterfaceBody,ModuleBodyContains,SubprogBodyContains,TypedefBodyContains,FEnum>^{BS} {
1432<Start,SubprogBody,ModuleBody,TypedefBody,InterfaceBody,ModuleBodyContains,SubprogBodyContains,TypedefBodyContains,FEnum>"!>" {
1433 yy_push_state(YY_START,yyscanner);
1434 yyextra->current->docLine = yyextra->lineNr;
1435 yyextra->docBlockJavaStyle =
false;
1436 if (YY_START==SubprogBody) yyextra->docBlockInBody =
true;
1437 yyextra->docBlock.clear();
1445<DocBlock>({CMD}{CMD}){ID}/[^a-z_A-Z0-9] {
1446 yyextra->docBlock += yytext;
1448<DocBlock>{CMD}("f$"|"f["|"f{"|"f(") {
1449 yyextra->docBlock += yytext;
1450 yyextra->docBlockName=&yytext[1];
1451 if (yyextra->docBlockName.at(1)==
'[')
1453 yyextra->docBlockName.at(1)=
']';
1455 if (yyextra->docBlockName.at(1)==
'{')
1457 yyextra->docBlockName.at(1)=
'}';
1459 if (yyextra->docBlockName.at(1)==
'(')
1461 yyextra->docBlockName.at(1)=
')';
1463 yyextra->fencedSize=0;
1465 BEGIN(DocCopyBlock);
1467<DocBlock>{CMD}"ifile"{B}+"\""[^\n\"]+"\"" {
1468 yyextra->fileName = &yytext[6];
1469 yyextra->fileName = yyextra->fileName.stripWhiteSpace();
1470 yyextra->fileName = yyextra->fileName.mid(1,yyextra->fileName.length()-2);
1471 yyextra->docBlock += yytext;
1473<DocBlock>{CMD}"ifile"{B}+{FILEMASK} {
1474 yyextra->fileName = &yytext[6];
1475 yyextra->fileName = yyextra->fileName.stripWhiteSpace();
1476 yyextra->docBlock += yytext;
1478<DocBlock>{CMD}"iline"{LINENR}/[\n\.] |
1479<DocBlock>{CMD}"iline"{LINENR}{B} {
1484 warn(yyextra->fileName,yyextra->lineNr,
"Invalid line number '{}' for iline command",yytext);
1488 yyextra->lineNr = nr;
1490 yyextra->docBlock += yytext;
int toInt(bool *ok=nullptr, int base=10) const
1492<DocBlock>{B}*"<"{PRE}">" {
1493 yyextra->docBlock += yytext;
1494 yyextra->docBlockName=
"<pre>";
1495 yyextra->fencedSize=0;
1497 BEGIN(DocCopyBlock);
1499<DocBlock>{B}*"<"<CODE>">" {
1500 yyextra->docBlock += yytext;
1501 yyextra->docBlockName=
"<code>";
1502 yyextra->fencedSize=0;
1504 BEGIN(DocCopyBlock);
1506<DocBlock>{CMD}"startuml"/[^a-z_A-Z0-9\-] {
1507 yyextra->docBlock += yytext;
1508 yyextra->docBlockName=
"uml";
1509 yyextra->fencedSize=0;
1511 BEGIN(DocCopyBlock);
1513<DocBlock>{CMD}("verbatim"|"iliteral"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"rtfonly"|"docbookonly"|"dot"|"msc"|"mermaid"|"code")/[^a-z_A-Z0-9\-] {
1514 yyextra->docBlock += yytext;
1515 yyextra->docBlockName=&yytext[1];
1516 yyextra->fencedSize=0;
1518 BEGIN(DocCopyBlock);
1520<DocBlock>"~~~"[~]* {
1522 yyextra->docBlock += pat;
1523 yyextra->docBlockName=
"~~~";
1524 yyextra->fencedSize=pat.
length();
1526 BEGIN(DocCopyBlock);
1528<DocBlock>"```"[`]*/(".")?[a-zA-Z0-9#_-]+ |
1529<DocBlock>"```"[`]*/"{"[^}]+"}" |
1530<DocBlock>"```"[`]* {
1532 yyextra->docBlock += pat;
1533 yyextra->docBlockName=
"```";
1534 yyextra->fencedSize=pat.
length();
1536 BEGIN(DocCopyBlock);
1538<DocBlock>"\\ilinebr "{BS} {
1540 int extraSpaces = std::max(0,
static_cast<int>(yyleng-9-yyextra->curIndent-2));
1541 indent.
fill(
' ',extraSpaces);
1543 yyextra->docBlock +=
"\\ilinebr ";
1544 yyextra->docBlock += indent;
DString fill(char c, size_t len)
Fills a string with a predefined character.
1547<DocBlock>[^@*`~\/\\\n]+ {
1548 yyextra->docBlock += yytext;
1550<DocBlock>"\n"{BS}"!"(">"|"!"+) {
1551 yyextra->docBlock+=
"\n";
1556 yyextra->colNr -= 1;
1562 yyextra->docBlock += *yytext;
1567<DocCopyBlock>"</"{PRE}">" {
1568 yyextra->docBlock += yytext;
1569 if (yyextra->docBlockName==
"<pre>")
1571 yyextra->docBlockName=
"";
1576<DocCopyBlock>"</"{CODE}">" {
1577 yyextra->docBlock += yytext;
1578 if (yyextra->docBlockName==
"<code>")
1580 yyextra->docBlockName=
"";
1585<DocCopyBlock>{CMD}("f$"|"f]"|"f}"|"f)") {
1586 yyextra->docBlock += yytext;
1587 if (yyextra->docBlockName==&yytext[1])
1589 yyextra->docBlockName=
"";
1594<DocCopyBlock>{CMD}("endverbatim"|"endiliteral"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endmanonly"|"endrtfonly"|"enddot"|"endmsc"|"endmermaid"|"enduml"|"endcode")/[^a-z_A-Z0-9] {
1595 yyextra->docBlock += yytext;
1596 if (&yytext[4]==yyextra->docBlockName)
1598 yyextra->docBlockName=
"";
1604<DocCopyBlock>^{B}*{COMM} {
1605 if (yyextra->docBlockName==
"verbatim")
1613 yyextra->docBlock += indent;
1616<DocCopyBlock>"~~~"[~]* {
1618 yyextra->docBlock += pat;
1619 if (yyextra->docBlockName ==
"~~~" && yyextra->fencedSize==pat.
length())
1625<DocCopyBlock>"```"[`]* {
1627 yyextra->docBlock += pat;
1628 if (yyextra->docBlockName ==
"```" && yyextra->fencedSize==pat.
length())
1635<DocCopyBlock>[^<@/\*\]!`~"\$\\\n]+ {
1636 yyextra->docBlock += yytext;
1639 yyextra->docBlock += *yytext;
1643 yyextra->docBlock += *yytext;
1647<Prototype>{BS}{SUBPROG}{BS_} {
1648 BEGIN(PrototypeSubprog);
1650<Prototype,PrototypeSubprog>{BS}{SCOPENAME}?{BS}{ID} {
1653 BEGIN(PrototypeArgs);
1656"("|")"|","|{BS_} { yyextra->current->args += yytext; }
1657{ID} { yyextra->current->args += yytext;
1669 yyextra->debugStr=
"";
1676 if (yyextra->parsingPrototype)
1680 else if ( yyextra->includeStackPtr <= 0 )
1682 if (YY_START!=INITIAL && YY_START!=Start)
1684 DBG_CTX((stderr,
"==== Error: EOF reached in wrong state (end missing)"));
1709 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
1711 yyextra->lineNr+=yyextra->lineCountPrepass;
1712 yyextra->lineCountPrepass=0;
1713 yyextra->comments.clear();
1724 if (c==
'\t') col+=tabSize-(col%tabSize);
1725 else if (c==
'\n') col=0;
1733 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
1735 for (
const auto &cip : yyextra->comments)
1739 if (c>=from && c<=to)
1750 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
1754 yyextra->last_entry->brief = c->
str;
1759 if (parameter) parameter->
docs = c->
str;
1765 for(
int i=0; i<length; i++)
1785 int parseState = Start;
1786 char quoteSymbol = 0;
1788 int commentIndex = -1;
1790 if (ch !=
'\0') parseState = String;
1792 for(
int i=0; i<length && parseState!=Comment; i++)
1796 if (parseState==String)
1798 if (buf[i]==
'\\') i++;
1807 if (buf[i]==quoteSymbol)
1813 else if (parseState==Start)
1815 parseState = String;
1816 quoteSymbol = buf[i];
1822 if (parseState==Start)
1824 parseState = Comment;
1843 return commentIndex;
1851 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
1852 size_t length = yyextra->inputStringPrepass.length();
1853 for (
size_t i=index+1; i<length; i++) {
1854 if (yyextra->inputStringPrepass[i]==
'!' && i<length-1 && yyextra->inputStringPrepass[i+1]==
'<') {
1855 yyextra->comments.emplace_back(index, yyextra->inputStringPrepass.right(length-i-2));
1858 yyextra->inputStringPrepass.resize(index);
1865 for(
int i=length; i>pos; i--)
1866 contents[i]=contents[i-1];
1876 int prevLineLength=0;
1877 int prevLineAmpOrExclIndex=-1;
1879 char prevQuote =
'\0';
1880 char thisQuote =
'\0';
1881 bool emptyLabel=
true;
1882 bool commented=
false;
1883 bool inSingle=
false;
1884 bool inDouble=
false;
1885 bool inBackslash=
false;
1886 bool fullCommentLine=
true;
1887 bool artificialComment=
false;
1889 int newContentsSize = (int)strlen(contents)+3;
1890 char* newContents = (
char*)malloc(newContentsSize);
1895 sizCont = strlen(contents);
1896 for(
size_t i=0;i<sizCont;i++) {
1898 char c = contents[i];
1899 if (artificialComment && c !=
'\n')
1901 if (c ==
'!' && spaces)
1903 newContents[j++] = c;
1904 artificialComment =
false;
1909 else if (c ==
' ' || c ==
'\t')
continue;
1919 if (j>=newContentsSize-3) {
1920 newContents = (
char*)realloc(newContents, newContentsSize+1000);
1921 newContentsSize = newContentsSize+1000;
1926 if (!fullCommentLine)
1928 prevLineLength=column;
1929 prevLineAmpOrExclIndex=
getAmpOrExclAtTheEnd(&contents[i-prevLineLength+1], prevLineLength,prevQuote);
1930 if (prevLineAmpOrExclIndex == -1) prevLineAmpOrExclIndex = column - 1;
1933 prevLineAmpOrExclIndex = -1;
1939 prevLineLength+=column;
1943 hasContLine[curLine - 1] = 1;
1946 artificialComment=
false;
1948 fullCommentLine=
true;
1953 prevQuote = thisQuote;
1966 newContents[j]=
'\000';
1967 newContentsSize = (int)strlen(newContents);
1968 if (newContents[newContentsSize - 1] !=
'\n')
1971 newContents = (
char*)realloc(newContents, newContentsSize+2);
1972 newContents[newContentsSize] =
'\n';
1973 newContents[newContentsSize + 1] =
'\000';
1979 if ((column <= fixedCommentAfter) && (column!=6) && !commented)
1982 fullCommentLine=
false;
1986 inBackslash = !inBackslash;
1993 inSingle = !inSingle;
1994 if (inSingle) thisQuote = c;
1995 else thisQuote =
'\0';
2003 inDouble = !inDouble;
2004 if (inDouble) thisQuote = c;
2005 else thisQuote =
'\0';
2010 inBackslash =
false;
2017 if ((column <= fixedCommentAfter) && (column!=6))
2025 else if ((c ==
'!') && !inDouble && !inSingle)
2032 if (!commented) fullCommentLine=
false;
2039 if (!commented && (column < 6) && ((c -
'0') >= 0) && ((c -
'0') <= 9))
2043 else if (column==6 && emptyLabel)
2045 if (!commented) fullCommentLine=
false;
2050 if (prevLineAmpOrExclIndex==-1)
2059 if (curLine != 1)
insertCharacter(newContents, j+1, (j+1)-6-prevLineLength+prevLineAmpOrExclIndex+skipped,
'&');
2065 hasContLine[curLine - 1] = 1;
2074 else if ((column > fixedCommentAfter) && !commented)
2085 artificialComment =
true;
2097 if (!commented) fullCommentLine=
false;
2113 newContents = (
char*)realloc(newContents, 2);
2114 newContents[0] =
'\n';
2115 newContents[1] =
'\000';
2117 else if (newContents[j] ==
'\n')
2119 newContents = (
char*)realloc(newContents, j+2);
2120 newContents[j + 1] =
'\000';
2124 newContents = (
char*)realloc(newContents, j+3);
2125 newContents[j + 1] =
'\n';
2126 newContents[j + 2] =
'\000';
2135 static const std::unordered_set<std::string> fortran_C_keywords = {
2136 "character",
"call",
"close",
"common",
"continue",
2137 "case",
"contains",
"cycle",
"class",
"codimension",
2138 "concurrent",
"contiguous",
"critical"
2141 if (*contents !=
'c' && *contents !=
'C')
return false;
2143 const char *c = contents;
2145 while (*c && *c !=
' ') {keyword += *c; c++;}
2146 keyword = keyword.
lower();
2148 return (fortran_C_keywords.find(keyword.
str()) != fortran_C_keywords.end());
2155 bool skipLine=
false;
2161 size_t sizCont = contents.
length();
2162 for (
size_t i=0;i<sizCont;i++)
2166 switch(contents.
at(i))
2173 column += tabSize-1;
2190 if (column==1)
return true;
2191 if (skipLine)
break;
2194 if (column!=6) skipLine=
true;
2197 if (skipLine)
break;
2198 if (column>=7)
return true;
2221 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
2222 if (yyextra->includeStackCnt <= yyextra->includeStackPtr)
2224 yyextra->includeStackCnt++;
2225 yyextra->includeStack = (YY_BUFFER_STATE *)realloc(yyextra->includeStack, yyextra->includeStackCnt *
sizeof(YY_BUFFER_STATE));
2227 yyextra->includeStack[yyextra->includeStackPtr++] = YY_CURRENT_BUFFER;
2228 yy_switch_to_buffer(yy_scan_string(buffer.
data(),yyscanner),yyscanner);
2235 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
2237 yyextra->includeStackPtr --;
2238 yy_delete_buffer( YY_CURRENT_BUFFER, yyscanner );
2239 yy_switch_to_buffer( yyextra->includeStack[yyextra->includeStackPtr], yyscanner );
2243static void copyEntry(std::shared_ptr<Entry> dest,
const std::shared_ptr<Entry> &src)
2245 dest->type = src->type;
2246 dest->fileName = src->fileName;
2247 dest->startLine = src->startLine;
2248 dest->bodyLine = src->bodyLine;
2249 dest->endBodyLine = src->endBodyLine;
2250 dest->args = src->args;
2251 dest->argList = src->argList;
2252 dest->doc = src->doc;
2253 dest->docLine = src->docLine;
2254 dest->docFile = src->docFile;
2255 dest->brief = src->brief;
2256 dest->briefLine= src->briefLine;
2257 dest->briefFile= src->briefFile;
2267 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
2268 if (yyextra->moduleProcedures.empty())
return;
2271 std::map<std::string,std::shared_ptr<Entry>> procMap;
2273 for (
const auto& cf: current_root->
children())
2275 if (!cf->section.isFunction())
2284 procMap.emplace(name.
str(), cf);
2290 for (
const auto& ce1: yyextra->moduleProcedures)
2292 if (procMap.find(ce1->name.str())!=procMap.end())
2294 std::shared_ptr<Entry> proc = procMap[ce1->name.str()];
2298 yyextra->moduleProcedures.clear();
2307 extracted.
remove(0, start+1);
2311 size_t length = extracted.
length();
2323 if (parensPart.
length() == 1)
2338 return "bind(C, name=" + parensPart +
")";
2379 else if (mdfString.
contains(
"intent"))
2388 else if (mdfString==
"public")
2392 else if (mdfString==
"private")
2396 else if (mdfString==
"protected")
2400 else if (mdfString==
"optional")
2404 else if (mdfString==
"allocatable")
2408 else if (mdfString==
"external")
2412 else if (mdfString==
"intrinsic")
2416 else if (mdfString==
"parameter")
2420 else if (mdfString==
"pointer")
2424 else if (mdfString==
"target")
2428 else if (mdfString==
"save")
2432 else if (mdfString==
"nopass")
2436 else if (mdfString==
"deferred")
2440 else if (mdfString==
"non_overridable")
2444 else if (mdfString==
"contiguous")
2448 else if (mdfString==
"volatile")
2450 newMdf.
volat =
true;
2452 else if (mdfString==
"value")
2454 newMdf.
value =
true;
2456 else if (mdfString.
contains(
"pass"))
2490 if ((!byTypeName && arg.
name.
lower() == cname) ||
2491 (byTypeName && arg.
type.
lower() == cname)
2506 if (!typeName.
empty()) typeName +=
", ";
2511 if (!typeName.
empty()) typeName +=
", ";
2516 if (!typeName.
empty()) typeName +=
", ";
2517 typeName +=
"optional";
2521 if (!typeName.
empty()) typeName +=
", ";
2522 typeName +=
"allocatable";
2526 if (!typeName.
contains(
"external"))
2528 if (!typeName.
empty()) typeName +=
", ";
2529 typeName +=
"external";
2534 if (!typeName.
empty()) typeName +=
", ";
2535 typeName +=
"intrinsic";
2539 if (!typeName.
empty()) typeName +=
", ";
2540 typeName +=
"parameter";
2544 if (!typeName.
empty()) typeName +=
", ";
2545 typeName +=
"pointer";
2549 if (!typeName.
empty()) typeName +=
", ";
2550 typeName +=
"target";
2554 if (!typeName.
empty()) typeName +=
", ";
2559 if (!typeName.
empty()) typeName +=
", ";
2560 typeName +=
"deferred";
2564 if (!typeName.
empty()) typeName +=
", ";
2565 typeName +=
"non_overridable";
2569 if (!typeName.
empty()) typeName +=
", ";
2570 typeName +=
"nopass";
2574 if (!typeName.
empty()) typeName +=
", ";
2577 typeName +=
"(" + mdfs.
passVar +
")";
2581 if (!typeName.
empty()) typeName +=
", ";
2586 if (!typeName.
empty()) typeName +=
", ";
2587 typeName +=
"public";
2591 if (!typeName.
empty()) typeName +=
", ";
2592 typeName +=
"private";
2596 if (!typeName.
empty()) typeName +=
", ";
2597 typeName +=
"protected";
2601 if (!typeName.
empty()) typeName +=
", ";
2602 typeName +=
"contiguous";
2606 if (!typeName.
empty()) typeName +=
", ";
2607 typeName +=
"volatile";
2611 if (!typeName.
empty()) typeName +=
", ";
2612 typeName +=
"value";
2635 ent->
spec.setFinal(
true);
2639 ent->
virt = Specifier::Pure;
2648 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
2650 yyextra->current_root= scope;
2652 yyextra->modifiers.emplace(scope, std::map<std::string,SymbolModifiers>());
2655 yyextra->current = std::make_shared<Entry>();
2664 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
2665 if (yyextra->global_scope == scope)
2667 yyextra->global_scope =
nullptr;
2675 if (yyextra->current_root->parent() || isGlobalRoot)
2677 yyextra->current_root= yyextra->current_root->parent();
2681 fprintf(stderr,
"parse error in end <scopename>\n");
2687 yyextra->current = std::make_shared<Entry>();
2691 std::map<std::string,SymbolModifiers>& mdfsMap = yyextra->modifiers[scope];
2693 if (scope->
section.isFunction())
2696 for (
const auto &kv : mdfsMap)
2710 if (yyextra->modifiers[scope].find(returnName.
str())!=yyextra->modifiers[scope].end())
2712 scope->
type = yyextra->modifiers[scope][returnName.
str()].type;
2717 if (scope->
section.isClass() && scope->
spec.isInterface())
2724 for (
const auto &ce : scope->
children())
2726 if (!ce->section.isFunction())
2736 arg->
type =
"external " + ce->type +
"(";
2737 for (
size_t i=0; i<ce->argList.size(); i++)
2743 const Argument &subarg = ce->argList.at(i);
2751 yyextra->modifiers.erase(scope);
2757 if (!scope->
section.isFunction())
2760 for (
const auto &ce : scope->
children())
2762 if (!ce->section.isVariable() && !ce->section.isFunction() && !ce->section.isClass())
2766 if (mdfsMap.find(ce->name.lower().str())!=mdfsMap.end())
2770 if (ce->section.isVariable() || ce->section.isFunction())
2778 yyextra->modifiers.erase(scope);
2792 bool procMapCreated =
false;
2793 std::unordered_map<std::string,std::shared_ptr<Entry>> procMap;
2796 bool interfMapCreated =
false;
2797 std::unordered_map<std::string,std::shared_ptr<Entry>> interfMap;
2800 for (
const auto &ce: scope->
children())
2802 if (!ce->section.isClass())
2806 std::unordered_map<std::string,std::shared_ptr<Entry>> methodMap;
2807 for (
auto &ct: ce->children())
2809 if (!ct->section.isFunction())
2812 if (ct->type==
"generic")
2815 if (ct->virt==Specifier::Pure)
2819 if (!procMapCreated)
2821 for (
const auto &cf: scope->
children())
2823 if (cf->section.isFunction())
2825 procMap.emplace(cf->name.str(), cf);
2828 procMapCreated =
true;
2833 if (procMap.find(implName.
str())!=procMap.end())
2835 std::shared_ptr<Entry> proc = procMap[implName.
str()];
2836 ct->args = proc->args;
2838 if (ct->brief.empty())
2840 ct->brief = proc->brief;
2841 ct->briefLine = proc->briefLine;
2842 ct->briefFile = proc->briefFile;
2844 if (ct->doc.empty())
2846 ct->doc = proc->doc;
2847 ct->docLine = proc->docLine;
2848 ct->docFile = proc->docFile;
2850 methodMap.emplace(ct->name.str(), ct);
2855 for (
auto &ct: ce->children())
2857 if (!ct->section.isFunction())
2860 if (ct->virt != Specifier::Pure)
2864 if (!interfMapCreated)
2866 for(
const auto &cf: scope->
children())
2868 if (cf->section.isClass() && cf->spec.isInterface() && cf->type==
"abstract")
2870 std::shared_ptr<Entry> ci = cf->children().front();
2871 interfMap.emplace(ci->name.str(), ci);
2874 interfMapCreated =
true;
2879 if (interfMap.find(implName.
str())!= interfMap.end() )
2881 std::shared_ptr<Entry> proc = interfMap[implName.
str()];
2882 ct->args = proc->args;
2884 if (ct->brief.empty())
2886 ct->brief = proc->brief;
2887 ct->briefLine = proc->briefLine;
2888 ct->briefFile = proc->briefFile;
2890 if (ct->doc.empty())
2892 ct->doc = proc->doc;
2893 ct->docLine = proc->docLine;
2894 ct->docFile = proc->docFile;
2897 methodMap.emplace(ct->name.str(), ct);
2903 for (
auto &ct: ce->children())
2905 if (!ct->section.isFunction())
2908 if (ct->type!=
"generic")
2912 DString methodName = ct->args;
2913 if (methodMap.find(methodName.
str()) != methodMap.end())
2915 std::shared_ptr<Entry> method = methodMap[methodName.
str()];
2916 ct->args = method->args;
2918 if (ct->brief.empty())
2920 ct->brief = method->brief;
2921 ct->briefLine = method->briefLine;
2922 ct->briefFile = method->briefFile;
2924 if (ct->doc.empty())
2926 ct->doc = method->doc;
2927 ct->docLine = method->docLine;
2928 ct->docFile = method->docFile;
2938 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
2940 while ( c < max_size && yyextra->inputString[yyextra->inputPosition] )
2942 *buf = yyextra->inputString[yyextra->inputPosition++] ;
2950 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
2951 yyextra->last_entry.reset();
2956 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
2957 if (yyextra->typeMode)
2959 yyextra->current->protection = yyextra->typeProtection;
2961 else if (yyextra->current_root && yyextra->current_root->section.isClass() && yyextra->current_root->spec.isInterface())
2963 yyextra->current->protection = Protection::Public;
2965 else if (yyextra->current_root && yyextra->current_root->section.isFunction())
2967 yyextra->current->protection = Protection::Private;
2971 yyextra->current->protection = yyextra->defaultProtection;
2973 yyextra->current->mtype = MethodTypes::Method;
2974 yyextra->current->virt = Specifier::Normal;
2975 yyextra->current->isStatic =
false;
2976 yyextra->current->lang = SrcLangExt::Fortran;
2977 yyextra->commentScanner.initGroupInfo(yyextra->current.get());
2985 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
2986 if (case_insens) yyextra->current->name = yyextra->current->name.lower();
2988 yyextra->last_entry = yyextra->current;
2989 yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current);
2995 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
2996 DBG_CTX((stderr,
"0=========> got module %s\n",
qPrint(name)));
2999 yyextra->current->section = EntryType::makeNamespace();
3001 yyextra->current->section = EntryType::makeFunction();
3005 yyextra->current->name = name;
3009 DString fname = yyextra->fileName;
3010 size_t index1 = fname.
rfind(
'/');
3011 size_t index2 = fname.
rfind(
'\\');
3015 if (yyextra->mainPrograms) fname +=
"__" +
DString().
setNum(yyextra->mainPrograms);
3016 yyextra->mainPrograms++;
3018 yyextra->current->name =
substitute(fname,
".",
"_");
3020 yyextra->current->type =
"program";
3021 yyextra->current->fileName = yyextra->fileName;
3022 yyextra->current->bodyLine = yyextra->lineNr;
3023 yyextra->current->startLine = yyextra->lineNr;
3024 yyextra->current->protection = Protection::Public ;
3026 startScope(yyscanner,yyextra->last_entry.get());
3032 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
3033 DBG_CTX((stderr,
"1=========> got subprog, type: %s\n",
qPrint(text)));
3034 yyextra->subrCurrent.push_back(yyextra->current);
3035 yyextra->current->section = EntryType::makeFunction();
3038 yyextra->current->type +=
" " + subtype;
3042 yyextra->current->virt = Specifier::Virtual;
3044 yyextra->current->fileName = yyextra->fileName;
3045 yyextra->current->bodyLine = yyextra->lineNr;
3046 yyextra->current->startLine = yyextra->lineNr;
3047 yyextra->current->args.
clear();
3048 yyextra->current->argList.clear();
3050 yyextra->docBlock.clear();
3059 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
3060 if (YY_START == Start)
3064 yy_push_state(ModuleBody,yyscanner);
3067 yyextra->current->section = EntryType::makeClass();
3068 yyextra->current->spec =
TypeSpecifier().setInterface(
true);
3069 yyextra->current->name = name;
3074 yyextra->current->type =
"abstract";
3078 yyextra->current->type =
"generic";
3084 yyextra->current->type =
"";
3088 if ((yyextra->current_root) &&
3089 (yyextra->current_root->section.isClass() ||
3090 yyextra->current_root->section.isNamespace()))
3092 yyextra->current->name= yyextra->current_root->name +
"::" + yyextra->current->name;
3095 yyextra->current->fileName = yyextra->fileName;
3096 yyextra->current->bodyLine = yyextra->lineNr;
3097 yyextra->current->startLine = yyextra->lineNr;
3108 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
3111 for (
Argument &a:yyextra->current_root->argList)
3126 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
3129 yyextra->current->briefFile = yyextra->fileName;
3130 yyextra->current->briefLine = yyextra->lineNr;
3134 yyextra->current->docFile = yyextra->fileName;
3135 yyextra->current->docLine = yyextra->lineNr;
3143 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
3145 if (yyextra->docBlockInBody && hideInBodyDocs)
3147 yyextra->docBlockInBody =
false;
3150 DBG_CTX((stderr,
"call parseCommentBlock [%s]\n",
qPrint(doc)));
3151 int lineNr = brief ? yyextra->current->briefLine : yyextra->current->docLine;
3153 bool needsEntry =
false;
3154 Markdown markdown(yyextra->fileName,lineNr);
3158 while (yyextra->commentScanner.parseCommentBlock(
3159 yyextra->thisParser,
3160 yyextra->docBlockInBody ? yyextra->subrCurrent.back().get() : yyextra->current.get(),
3164 yyextra->docBlockInBody ?
false : brief,
3165 yyextra->docBlockInBody ?
false : yyextra->docBlockJavaStyle,
3166 yyextra->docBlockInBody,
3167 yyextra->defaultProtection,
3174 DBG_CTX((stderr,
"parseCommentBlock position=%d [%s] needsEntry=%d\n",position,doc.
data()+position,needsEntry));
3177 DBG_CTX((stderr,
"parseCommentBlock position=%d [%s] needsEntry=%d\n",position,doc.
data()+position,needsEntry));
3180 yyextra->docBlockInBody =
false;
3187 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
3191 std::shared_ptr<Entry> tmp_entry = yyextra->current;
3192 yyextra->current = yyextra->subrCurrent.
back();
3195 yyextra->current->inbodyDocs =
"";
3203 int dir1 = yyextra->modifiers[yyextra->current_root][yyextra->argName.lower().str()].direction;
3215 if (!loc_doc.
empty() && (loc_doc.
lower() != yyextra->argName.
lower()))
3218 yyextra->argName +
" " + loc_doc,brief);
3224 warn(yyextra->fileName,yyextra->lineNr,
"Routine: {}{} inconsistency between intent attribute and documentation for parameter {}:",
3225 yyextra->current->name,yyextra->current->args,yyextra->argName);
3227 yyextra->argName +
" " + loc_doc,brief);
3240 yyextra->current = tmp_entry;
3244 yyextra->argName +
" " + loc_doc,brief);
3248 warn(yyextra->fileName,yyextra->lineNr,
"Routine: {}{} inconsistency between intent attribute and documentation for parameter {}:",
3249 yyextra->current->name,yyextra->current->args,yyextra->argName);
3251 yyextra->argName +
" " + loc_doc,brief);
3262 if (!loc_doc.
empty() && (loc_doc.
lower() != yyextra->argName.
lower()))
3265 yyextra->argName +
" " + loc_doc,brief);
3270 warn(yyextra->fileName,yyextra->lineNr,
"Routine: {}{} inconsistency between intent attribute and documentation for parameter {}:",
3271 yyextra->current->name,yyextra->current->args,yyextra->argName);
3273 yyextra->argName +
" " + loc_doc,brief);
3277 else if (!loc_doc.
empty() && (loc_doc.
lower() != yyextra->argName.
lower()))
3280 yyextra->argName +
" " + loc_doc,brief);
3284 yyextra->current = tmp_entry;
3290 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
3294 std::shared_ptr<Entry> tmp_entry = yyextra->current;
3295 yyextra->current = yyextra->subrCurrent.
back();
3298 yyextra->current->inbodyDocs =
"";
3307 if (!loc_doc.
empty() && (loc_doc.
lower() != yyextra->argName.
lower()))
3313 yyextra->current = std::move(tmp_entry);
3321 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
3322 char *tmpBuf =
nullptr;
3325 if (fileBuf==
nullptr || fileBuf[0]==
'\0')
return;
3327 yyextra->defaultProtection = Protection::Public;
3328 yyextra->inputString = fileBuf;
3329 yyextra->inputPosition = 0;
3330 yyextra->inputStringPrepass =
nullptr;
3331 yyextra->inputPositionPrepass = 0;
3334 yyextra->current_root = rt.get();
3335 yyextra->global_root = rt;
3339 if (yyextra->isFixedForm)
3341 yyextra->fixedCommentAfter =
Config_getInt(FORTRAN_COMMENT_AFTER);
3342 msg(
"Prepassing fixed form of {}\n", fileName);
3348 yyextra->inputString =
prepassFixedForm(fileBuf,
nullptr,yyextra->fixedCommentAfter);
3357 else if (yyextra->inputString[strlen(fileBuf)-1] !=
'\n')
3359 tmpBuf = (
char *)malloc(strlen(fileBuf)+2);
3360 strcpy(tmpBuf,fileBuf);
3361 tmpBuf[strlen(fileBuf)]=
'\n';
3362 tmpBuf[strlen(fileBuf)+1]=
'\000';
3363 yyextra->inputString = tmpBuf;
3366 yyextra->lineNr= 1 ;
3367 yyextra->fileName = fileName;
3368 msg(
"Parsing file {}...\n",yyextra->fileName);
3370 yyextra->global_scope = rt.get();
3373 yyextra->commentScanner.enterFile(yyextra->fileName,yyextra->lineNr);
3376 yyextra->current = std::make_shared<Entry>();
3377 yyextra->current->lang = SrcLangExt::Fortran;
3378 yyextra->current->name = yyextra->fileName;
3379 yyextra->current->section = EntryType::makeSource();
3380 yyextra->file_root = yyextra->current;
3381 yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current);
3382 yyextra->current->lang = SrcLangExt::Fortran;
3384 fortranscannerYYrestart(
nullptr, yyscanner );
3389 fortranscannerYYlex(yyscanner);
3390 yyextra->commentScanner.leaveFile(yyextra->fileName,yyextra->lineNr);
3392 if (yyextra->global_scope && yyextra->global_scope !=
INVALID_ENTRY)
3394 endScope(yyscanner,yyextra->current_root,
true);
3399 rt->program.str(std::string());
3401 yyextra->moduleProcedures.clear();
3404 free((
char*)tmpBuf);
3405 yyextra->inputString=
nullptr;
3407 if (yyextra->isFixedForm)
3409 free((
char*)yyextra->inputString);
3410 yyextra->inputString=
nullptr;
3443 const char *fileBuf,
3444 const std::shared_ptr<Entry> &root,
3447 struct yyguts_t *yyg = (
struct yyguts_t*)
p->yyscanner;
3448 yyextra->thisParser =
this;
3457 return extension!=extension.
lower();
3462 struct yyguts_t *yyg = (
struct yyguts_t*)
p->yyscanner;
3464 yyextra->parsingPrototype =
true;
3466 fortranscannerYYlex(
p->yyscanner);
3467 yyextra->parsingPrototype =
false;
3475 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
3476 fprintf(stderr,
"********************************************************************\n");
3477 if (yyextra->blockLineNr == -1)
3479 fprintf(stderr,
"Error in file %s line: %d, state: %d(%s)\n",
3484 fprintf(stderr,
"Error in file %s line: %d, state: %d(%s), starting command: '%s' probable line reference: %d\n",
3485 qPrint(yyextra->fileName),yyextra->lineNr,YY_START,
stateToString(YY_START),
qPrint(yyextra->blockString),yyextra->blockLineNr);
3487 fprintf(stderr,
"********************************************************************\n");
3490 while (!yyextra->blockStack.empty()) yyextra->blockStack.pop();
3494 for (
const auto &ce : yyextra->global_root->children())
3496 if (ce == yyextra->file_root) start=
true;
3497 if (start) ce->reset();
3501 (void)yy_top_state(yyscanner);
3509 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
3510 if ( yyg->yy_start_stack_ptr <= 0 )
3511 warn(yyextra->fileName,yyextra->lineNr,
"Unexpected statement '{}'",yytext );
3513 yy_pop_state(yyscanner);
3518 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
3519 yyextra->blockString = text;
3520 yyextra->blockLineNr = yyextra->lineNr;
3521 yyextra->blockStack.emplace(yyextra->blockString,yyextra->blockLineNr);
3526 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
3527 if (yyextra->blockStack.empty())
3529 warn(yyextra->fileName,yyextra->lineNr,
"Internal inconsistency: empty stack while attempting popBlockState");
3533 yyextra->blockStack.pop();
3535 if (yyextra->blockStack.empty())
3537 yyextra->blockString.clear();
3538 yyextra->blockLineNr=-1;
3542 yyextra->blockString=yyextra->blockStack.top().blockString;
3543 yyextra->blockLineNr=yyextra->blockStack.top().blockLineNr;
3548#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()).
char & at(size_t i)
Returns a reference to the character at index i.
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)
static ParserManager * parserManager
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)
DString getParserName(const DString &extension)
Gets the name of the parser associated with given extension.
Wrapper class for a number of boolean properties.
#define Config_getInt(name)
DirIterator end(const DirIterator &) noexcept
const char * prepassFixedForm(const char *contents, int *hasContLine, int fixedCommentAfter)
bool recognizeFixedForm(const DString &contents, FortranFormat format)
FortranFormat convertFileNameFortranParserCode(const DString &fn)
static DString applyModifiers(DString typeName, const SymbolModifiers &mdfs)
const char * prepassFixedForm(const char *contents, int *hasContLine, int fixedCommentAfter)
static void initParser(yyscan_t yyscanner)
bool recognizeFixedForm(const DString &contents, FortranFormat format)
static void insertCharacter(char *contents, int length, int pos, char c)
static Argument * findArgument(Entry *subprog, DString name, bool byTypeName=false)
static bool keyWordsFortranC(const char *contents)
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)
DString getFileNameExtension(const DString &fn)