38%option never-interactive
39%option case-insensitive
40%option prefix="fortranscannerYY"
42%option extra-type="struct fortranscannerYY_state *"
46#define YY_TYPEDEF_YY_SCANNER_T
79#define DBG_CTX(x) do { } while(0)
82#define YY_NO_UNISTD_H 1
133 "",
"intent(in)",
"intent(out)",
"intent(inout)"
137 "",
"[in]",
"[out]",
"[in,out]"
208 std::map<Entry*,std::map<std::string,SymbolModifiers> >
modifiers;
239static void copyEntry(std::shared_ptr<Entry> dest,
const std::shared_ptr<Entry> &src);
256#define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size);
259static inline const char *
getLexerFILE() {
return __FILE__;}
261#define YY_USER_ACTION yyextra->colNr+=(int)yyleng;
262#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.
static int yyread(yyscan_t yyscanner, char *buf, int max_size)
static const char * stateToString(int state)
static const char * getLexerFILE()
std::vector< std::shared_ptr< Entry > > EntryList
static void startScope(yyscan_t yyscanner)
start scope
static void endScope(yyscan_t yyscanner)
end scope
static void pop_state(yyscan_t yyscanner)
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 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 void startCommentBlock(yyscan_t yyscanner, bool)
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 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 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 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.
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::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.
274ID [a-z_A-Z%]+{IDSYM}*
275ID_ [a-z_A-Z%]*{IDSYM}*
276OPERATOR_ID (operator{BS}"("{BS}(\.[a-z_A-Z]+\.|"="|"/="|"//"|"=="|"<"|"<="|">"|">="|"+"|"*"|"**"|"/"|"-"){BS}")")
277SUBPROG (subroutine|function)
281BT_ ([ \t]+|[ \t]*"(")
284ARGS_L1a [^()]*"("[^)]*")"[^)]*
285ARGS_L1 ("("{ARGS_L1a}*")")
286ARGS_L2 "("({ARGS_L0}|[^()]|{ARGS_L1a}|{ARGS_L1})*")"
287ARGS {BS}({ARGS_L0}|{ARGS_L1}|{ARGS_L2})
294NUM_TYPE (complex|integer|logical|real)
295LOG_OPER (\.and\.|\.eq\.|\.eqv\.|\.ge\.|\.gt\.|\.le\.|\.lt\.|\.ne\.|\.neqv\.|\.or\.|\.not\.)
297CHAR (CHARACTER{ARGS}?|CHARACTER{BS}"*"({BS}[0-9]+|{ARGS}))
298TYPE_SPEC (({NUM_TYPE}({BS}"*"{BS}[0-9]+)?)|({NUM_TYPE}{KIND})|DOUBLE{BS}COMPLEX|DOUBLE{BS}PRECISION|ENUMERATOR|{CHAR}|TYPE{ARGS}|CLASS{ARGS}|PROCEDURE{ARGS}?)
300INTENT_SPEC intent{BS}"("{BS}(in|out|in{BS}out){BS}")"
301ATTR_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)
302LANGUAGE_BIND_SPEC BIND{BS}"("{BS}C{BS}((,{BS}NAME{BS}"="{BS}"\""(.*)"\""{BS})|(,{BS}NAME{BS}"="{BS}"'"(.*)"'"{BS}))?")"
304ATTR_STMT {ATTR_SPEC}|DIMENSION
305EXTERNAL_STMT (EXTERNAL)
308PREFIX ((NON_)?RECURSIVE{BS_}|IMPURE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,4}((NON_)?RECURSIVE|IMPURE|PURE|ELEMENTAL)?
309SCOPENAME ({ID}{BS}"::"{BS})*
311LINENR {B}*[1-9][0-9]*
312FILEICHAR [a-z_A-Z0-9\x80-\xFF\\:\\\/\-\+=&#@~]
313FILEECHAR [a-z_A-Z0-9\x80-\xFF\-\+=&#@~]
314FILECHARS {FILEICHAR}*{FILEECHAR}+
315HFILEMASK {FILEICHAR}*("."{FILEICHAR}+)+{FILECHARS}*
316VFILEMASK {FILECHARS}("."{FILECHARS})*
317FILEMASK {VFILEMASK}|{HFILEMASK}
331%x SubprogBodyContains
345%x TypedefBodyContains
371<Prepass>^{BS}[&]*{BS}!.*\n {
372 yyextra->lineCountPrepass ++;
375 yyextra->lineCountPrepass ++;
378 yyextra->functionLine =
FALSE;
380 DBG_CTX((stderr,
"---%s", yytext));
384 if (indexEnd>=0 && yytext[indexEnd]!=
'&')
391 if (YY_START == Prepass)
395 yyextra->inputStringPrepass+=(
const char*)(yytext+(indexStart+1));
398 pushBuffer(yyscanner,yyextra->inputStringPrepass);
410 if (YY_START != Prepass)
412 yyextra->comments.clear();
413 yyextra->inputStringPrepass=
QCString();
414 yy_push_state(Prepass,yyscanner);
417 size_t length = yyextra->inputStringPrepass.length();
420 yyextra->inputStringPrepass+=(
const char*)(yytext+(indexStart+1));
421 yyextra->lineCountPrepass ++;
424 truncatePrepass(yyscanner,
static_cast<int>(length) + indexEnd - indexStart - 1);
431 if (yytext[0]!=yyextra->stringStartSymbol)
433 yyextra->colNr -= (int)yyleng;
436 if (yy_top_state(yyscanner) == Initialization ||
437 yy_top_state(yyscanner) == ArrayInitializer)
439 yyextra->initializer+=yytext;
443<String>[\x80-\xFF]* |
444<String>. {
if (yy_top_state(yyscanner) == Initialization ||
445 yy_top_state(yyscanner) == ArrayInitializer)
447 yyextra->initializer+=yytext;
451 if (YY_START == StrIgnore)
452 { yyextra->colNr -= (int)yyleng;
455 yy_push_state(YY_START,yyscanner);
456 if (yy_top_state(yyscanner) == Initialization ||
457 yy_top_state(yyscanner) == ArrayInitializer)
459 yyextra->initializer+=yytext;
461 yyextra->stringStartSymbol=yytext[0];
467<*>"!"/([^<>\n]|"<ff>"|"<FF>") {
if (YY_START == String || YY_START == DocCopyBlock)
468 { yyextra->colNr -= (int)yyleng;
473 if ((YY_START != StrIgnore) && (YY_START != String))
475 yy_push_state(YY_START,yyscanner);
477 yyextra->debugStr=
"*!";
478 DBG_CTX((stderr,
"start comment %d\n",yyextra->lineNr));
482 DBG_CTX((stderr,
"end comment %d %s\n",yyextra->lineNr,
qPrint(yyextra->debugStr)));
const char * qPrint(const char *s)
484<StrIgnore>[\x80-\xFF]* |
485<StrIgnore>. { yyextra->debugStr+=yytext; }
490<Start,ModuleBody,SubprogBody>"use"{BS_} {
491 if (YY_START == Start)
494 yy_push_state(ModuleBody,yyscanner);
496 yy_push_state(Use,yyscanner);
499 DBG_CTX((stderr,
"using dir %s\n",yytext));
500 yyextra->current->name=yytext;
501 yyextra->current->name=yyextra->current->name.lower();
502 yyextra->current->fileName = yyextra->fileName;
503 yyextra->current->section=EntryType::makeUsingDir();
504 yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current);
505 yyextra->current->lang = SrcLangExt::Fortran;
509 yyextra->useModuleName=yytext;
510 yyextra->useModuleName=yyextra->useModuleName.lower();
512<Use>,{BS}"ONLY" { BEGIN(UseOnly);
516 yyextra->current->name= yyextra->useModuleName+
"::"+yytext;
517 yyextra->current->name=yyextra->current->name.lower();
518 yyextra->current->fileName = yyextra->fileName;
519 yyextra->current->section=EntryType::makeUsingDecl();
520 yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current);
521 yyextra->current->lang = SrcLangExt::Fortran;
530<Start,ModuleBody,SubprogBody>{
531^{BS}interface{IDSYM}+ { }
533 yy_push_state(InterfaceBody,yyscanner);
538^{BS}abstract{BS_}interface { yyextra->ifType =
IF_ABSTRACT;
539 yy_push_state(InterfaceBody,yyscanner);
544^{BS}interface{BS_}{ID}{ARGS}? { yyextra->ifType =
IF_GENERIC;
545 yyextra->current->bodyLine = yyextra->lineNr + yyextra->lineCountPrepass + 1;
546 yy_push_state(InterfaceBody,yyscanner);
552 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
556<InterfaceBody>^{BS}end{BS}interface({BS_}{ID})? {
560 yyextra->last_entry->parent()->endBodyLine = yyextra->lineNr - 1;
569<InterfaceBody>module{BS}procedure { yy_push_state(YY_START,yyscanner);
570 BEGIN(ModuleProcedure);
576 startScope(yyscanner,yyextra->last_entry.get());
579 yyextra->current->section = EntryType::makeFunction();
580 yyextra->current->name = name;
581 yyextra->moduleProcedures.push_back(yyextra->current);
584<ModuleProcedure>"\n" { yyextra->colNr -= 1;
591<Start>^{BS}{CONTAINS}/({BS}|\n|!|;) {
592 if (YY_START == Start)
595 yy_push_state(ModuleBodyContains,yyscanner);
598<ModuleBody>^{BS}{CONTAINS}/({BS}|\n|!|;) { BEGIN(ModuleBodyContains); }
599<SubprogBody>^{BS}{CONTAINS}/({BS}|\n|!|;) { BEGIN(SubprogBodyContains); }
600<TypedefBody>^{BS}{CONTAINS}/({BS}|\n|!|;) { BEGIN(TypedefBodyContains); }
603<Start>block{BS}data{BS}{ID_} {
605 yy_push_state(BlockData,yyscanner);
606 yyextra->defaultProtection = Protection::Public;
608<Start>module|program{BS_} {
610 if (yytext[0]==
'm' || yytext[0]==
'M')
612 yy_push_state(
Module,yyscanner);
616 yy_push_state(Program,yyscanner);
618 yyextra->defaultProtection = Protection::Public;
620<BlockData>^{BS}"end"({BS}(block{BS}data)({BS_}{ID})?)?{BS}/(\n|!|;) {
623 yyextra->defaultProtection = Protection::Public;
626<Start,ModuleBody,ModuleBodyContains>"end"({BS}(module|program)({BS_}{ID})?)?{BS}/(\n|!|;) {
628 if (!
endScope(yyscanner,yyextra->current_root))
632 yyextra->defaultProtection = Protection::Public;
633 if (yyextra->global_scope)
637 yy_push_state(Start,yyscanner);
646 yy_push_state(Start,yyscanner);
661<ModuleBody,TypedefBody,TypedefBodyContains>private/{BS}(\n|"!") {
662 yyextra->defaultProtection = Protection::Private;
663 yyextra->current->protection = yyextra->defaultProtection ;
665<ModuleBody,TypedefBody,TypedefBodyContains>public/{BS}(\n|"!") {
666 yyextra->defaultProtection = Protection::Public;
667 yyextra->current->protection = yyextra->defaultProtection ;
672<ModuleBody>^{BS}type{BS}"=" {}
673<Start,ModuleBody>^{BS}type/[^a-z0-9_] {
674 if (YY_START == Start)
677 yy_push_state(ModuleBody,yyscanner);
680 yy_push_state(
Typedef,yyscanner);
681 yyextra->current->protection = Protection::Package;
682 yyextra->typeProtection = Protection::Public;
683 yyextra->typeMode =
true;
691 yyextra->current->spec.setAbstractClass(
true);
695 yyextra->current->extends.emplace_back(basename, Protection::Public, Specifier::Normal);
698 yyextra->current->protection = Protection::Public;
701 yyextra->current->protection = Protection::Private;
703{LANGUAGE_BIND_SPEC} {
707 yyextra->current->section = EntryType::makeClass();
708 yyextra->current->spec.setStruct(
true);
709 yyextra->current->name = yytext;
710 yyextra->current->fileName = yyextra->fileName;
711 yyextra->current->bodyLine = yyextra->lineNr;
712 yyextra->current->startLine = yyextra->lineNr;
715 if (yyextra->current_root &&
716 (yyextra->current_root->section.isClass() ||
717 yyextra->current_root->section.isNamespace()))
719 yyextra->current->name = yyextra->current_root->name +
"::" + yyextra->current->name;
723 if( yyextra->current->protection == Protection::Package )
725 yyextra->current->protection = yyextra->defaultProtection;
727 else if( yyextra->current->protection == Protection::Public )
729 yyextra->modifiers[yyextra->current_root][yyextra->current->name.lower().str()] |=
QCString(
"public");
731 else if( yyextra->current->protection == Protection::Private )
733 yyextra->modifiers[yyextra->current_root][yyextra->current->name.lower().str()] |=
QCString(
"private");
737 startScope(yyscanner,yyextra->last_entry.get());
742<TypedefBodyContains>{
743^{BS}PROCEDURE{ARGS}? {
QCString simplifyWhiteSpace() const
return a copy of this string with leading and trailing whitespace removed and multiple whitespace cha...
747 yyextra->current->spec.setFinal(
true);
762 yyextra->modifiers[yyextra->current_root][name.
lower().
str()] |= yyextra->currentModifiers;
763 yyextra->current->section = EntryType::makeFunction();
764 yyextra->current->name = name;
766 if (yyextra->current->type.find(
'(') != -1)
772 yyextra->current->args = name.
lower();
774 yyextra->current->fileName = yyextra->fileName;
775 yyextra->current->bodyLine = yyextra->lineNr;
776 yyextra->current->startLine = yyextra->lineNr;
const std::string & str() const
781 int i = tmp.
find(
"=>");
787 if (yyextra->last_entry->type ==
"generic")
795 copyEntry(yyextra->current, yyextra->last_entry);
796 yyextra->current->name = yyextra->last_entry->name;
797 yyextra->current->section = EntryType::makeFunction();
806 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
811 yyextra->docBlock.clear();
816<TypedefBody,TypedefBodyContains>{
817^{BS}"end"{BS}"type"({BS_}{ID})?{BS}/(\n|!|;) {
818 yyextra->last_entry->parent()->endBodyLine = yyextra->lineNr;
819 if (!
endScope(yyscanner,yyextra->current_root))
823 yyextra->typeMode =
false;
826^{BS}"end"{BS}/(\n|!|;) {
827 warn(yyextra->fileName,yyextra->lineNr,
"Found 'END' instead of 'END TYPE'");
828 yyextra->last_entry->parent()->endBodyLine = yyextra->lineNr;
829 if (!
endScope(yyscanner,yyextra->current_root))
833 yyextra->typeMode =
false;
#define warn(file, line, fmt,...)
840<SubprogBody,SubprogBodyContains>^{BS}[0-9]*{BS}"end"({BS}{SUBPROG}({BS_}{ID})?)?{BS}/(\n|!|;) {
848 endScope(yyscanner,yyextra->current_root);
849 yyextra->last_entry->endBodyLine = yyextra->lineNr - 1;
851 yyextra->current_root->endBodyLine = yyextra->lineNr - 1;
853 if (!
endScope(yyscanner,yyextra->current_root))
857 yyextra->subrCurrent.pop_back();
865<Start,ModuleBody,TypedefBody,SubprogBody,FEnum>{
866^{BS}{TYPE_SPEC}/{SEPARATE} {
867 yyextra->last_enum.reset();
868 if (YY_START == FEnum)
870 yyextra->argType =
"@";
876 yyextra->current->bodyLine = yyextra->lineNr + 1;
877 yyextra->current->endBodyLine = yyextra->lineNr + yyextra->lineCountPrepass;
879 if (YY_START == Start)
882 yy_push_state(ModuleBody,yyscanner);
884 yy_push_state(AttributeList,yyscanner);
886{EXTERNAL_STMT}/({BS}"::"|{BS_}{ID}) {
888 if (YY_START == Start)
891 yy_push_state(ModuleBody,yyscanner);
896 yy_push_state(AttributeList,yyscanner);
898{ATTR_STMT}/{BS_}{ID} |
899{ATTR_STMT}/{BS}"::" {
901 DBG_CTX((stderr,
"5=========> Attribute statement: %s\n", yytext));
902 if (YY_START == Start)
905 yy_push_state(ModuleBody,yyscanner);
910 yy_push_state(YY_START,yyscanner);
911 BEGIN( AttributeList ) ;
914 if (YY_START == Start)
917 yy_push_state(ModuleBody,yyscanner);
924 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...
927^{BS}"type"{BS_}"is"/{BT_} {}
929^{BS}"class"{BS_}"is"/{BT_} {}
930^{BS}"class"{BS_}"default" {}
935{LANGUAGE_BIND_SPEC} {
936 yyextra->currentModifiers |= yytext;
940 char chr = yytext[(int)yyleng-1];
943 yyextra->colNr -= (int)yyleng;
951 unput(yytext[(
int)yyleng-1]);
952 yyextra->currentModifiers |= (tmp);
967<FVariable>{OPERATOR_ID} {
971 int currentState = YY_START;
973 int outerState = YY_START;
974 yy_push_state(currentState,yyscanner);
975 if( outerState == Start || outerState == ModuleBody )
977 if ((yyextra->current_root) &&
978 (yyextra->current_root->section.isClass() ||
979 yyextra->current_root->section.isNamespace()))
981 name = yyextra->current_root->name +
"::" + name;
985 yyextra->modifiers[yyextra->current_root][name.
str()] |= yyextra->currentModifiers;
993 if ((yyextra->current_root) && yyextra->current_root->section.isNamespace())
995 name = yyextra->current_root->name +
"::" + name;
998 yyextra->modifiers[yyextra->current_root][name.
lower().
str()] |= yyextra->currentModifiers;
999 yyextra->argName= name;
1002 if (!yyextra->argType.isEmpty() && !yyextra->current_root->section.isFunction())
1005 yyextra->current->section = EntryType::makeVariable();
1006 yyextra->current->name = yyextra->argName;
1007 yyextra->current->type = yyextra->argType;
1008 yyextra->current->fileName = yyextra->fileName;
1009 yyextra->current->bodyLine = yyextra->lineNr;
1010 yyextra->current->startLine = yyextra->lineNr;
1011 if (yyextra->argType ==
"@")
1013 yyextra->current_root->copyToSubEntry(yyextra->current);
1015 yyextra->last_enum = yyextra->current;
1016 yyextra->current_root->parent()->moveToSubEntryAndRefresh(yyextra->current);
1024 else if (!yyextra->argType.isEmpty())
1031 if (!yyextra->docBlock.isEmpty())
1039 yyextra->modifiers[yyextra->current_root][name.
lower().
str()].type = yyextra->argType;
1043 if ((yyextra->current_root->name.lower() == yyextra->argName.lower()) ||
1044 (yyextra->modifiers[yyextra->current_root->parent()][yyextra->current_root->name.lower().str()].returnName.lower() == yyextra->argName.lower()))
1046 int strt = yyextra->current_root->type.find(
"function");
1055 if ((yyextra->current_root->type.length() - strt - strlen(
"function"))!= 0)
1057 rght = yyextra->current_root->type.
right(yyextra->current_root->type.length() - strt - (
int)strlen(
"function")).
stripWhiteSpace();
1059 yyextra->current_root->type = lft;
1062 if (yyextra->current_root->type.length() > 0) yyextra->current_root->type +=
" ";
1063 yyextra->current_root->type += rght;
1065 if (yyextra->argType.stripWhiteSpace().length() > 0)
1067 if (yyextra->current_root->type.length() > 0) yyextra->current_root->type +=
" ";
1068 yyextra->current_root->type += yyextra->argType.stripWhiteSpace();
1070 if (yyextra->current_root->type.length() > 0) yyextra->current_root->type +=
" ";
1071 yyextra->current_root->type +=
"function";
1072 if (!yyextra->docBlock.isEmpty())
1079 yyextra->current_root->type +=
" " + yyextra->argType.stripWhiteSpace();
1081 yyextra->current_root->type = yyextra->current_root->type.
stripWhiteSpace();
1082 yyextra->modifiers[yyextra->current_root][name.
lower().
str()].type = yyextra->current_root->type;
1086 yyextra->modifiers[yyextra->current_root][name.
lower().
str()].type = yyextra->argType;
1092 yyextra->current->doc.clear();
1093 yyextra->current->brief.clear();
1100 yyextra->modifiers[yyextra->current_root][name.
lower().
str()] |= attr;
1107 yy_push_state(YY_START,yyscanner);
1108 yyextra->initializer=
"=";
1109 yyextra->initializerScope = yyextra->initializerArrayScope = 0;
1110 BEGIN(Initialization);
1115 yyextra->docBlock.clear();
1119 yyextra->docBlock.clear();
1120 yyextra->inputStringSemi =
" \n"+
QCString(yytext+1);
1122 pushBuffer(yyscanner,yyextra->inputStringSemi);
1125 if (YY_START == FVariable) REJECT;
1126 if (YY_START == String) REJECT;
1127 if (YY_START == StrIgnore) REJECT;
1128 if (YY_START == DocBlock) REJECT;
1129 yyextra->inputStringSemi =
" \n"+
QCString(yytext+1);
1131 pushBuffer(yyscanner,yyextra->inputStringSemi);
1134<Initialization,ArrayInitializer>"[" |
1135<Initialization,ArrayInitializer>"(/" { yyextra->initializer+=yytext;
1136 yyextra->initializerArrayScope++;
1137 BEGIN(ArrayInitializer);
1139<ArrayInitializer>"]" |
1140<ArrayInitializer>"/)" { yyextra->initializer+=yytext;
1141 yyextra->initializerArrayScope--;
1142 if (yyextra->initializerArrayScope<=0)
1144 yyextra->initializerArrayScope = 0;
1145 BEGIN(Initialization);
1148<ArrayInitializer>. { yyextra->initializer+=yytext; }
1149<Initialization>"(" { yyextra->initializerScope++;
1150 yyextra->initializer+=yytext;
1152<Initialization>")" { yyextra->initializerScope--;
1153 yyextra->initializer+=yytext;
1155<Initialization>{COMMA} {
if (yyextra->initializerScope == 0)
1159 if (yyextra->last_enum)
1161 yyextra->last_enum->initializer.str(yyextra->initializer.str());
1165 if (yyextra->vtype ==
V_VARIABLE) yyextra->last_entry->initializer.str(yyextra->initializer.str());
1170 yyextra->initializer+=
", ";
1173<Initialization>"\n"|"!" {
1175 if (yyextra->last_enum)
1177 yyextra->last_enum->initializer.str(yyextra->initializer.str());
1181 if (yyextra->vtype ==
V_VARIABLE) yyextra->last_entry->initializer.str(yyextra->initializer.str());
1183 yyextra->colNr -= 1;
1186<Initialization>. { yyextra->initializer+=yytext; }
1188<*>{BS}"enum"{BS}","{BS}"bind"{BS}"("{BS}"c"{BS}")"{BS} {
1189 if (YY_START == Start)
1192 yy_push_state(ModuleBody,yyscanner);
1195 yy_push_state(FEnum,yyscanner);
1196 yyextra->current->protection = yyextra->defaultProtection;
1197 yyextra->typeProtection = yyextra->defaultProtection;
1198 yyextra->typeMode =
true;
1200 yyextra->current->spec.setStruct(
true);
1201 yyextra->current->name.clear();
1202 yyextra->current->args.clear();
1203 yyextra->current->name.sprintf(
"@%d",yyextra->anonCount++);
1205 yyextra->current->section = EntryType::makeEnum();
1206 yyextra->current->fileName = yyextra->fileName;
1207 yyextra->current->startLine = yyextra->lineNr;
1208 yyextra->current->bodyLine = yyextra->lineNr;
1209 if ((yyextra->current_root) &&
1210 (yyextra->current_root->section.isClass() ||
1211 yyextra->current_root->section.isNamespace()))
1213 yyextra->current->name = yyextra->current_root->name +
"::" + yyextra->current->name;
1217 startScope(yyscanner,yyextra->last_entry.get());
1220<FEnum>"end"{BS}"enum" {
1221 yyextra->last_entry->parent()->endBodyLine = yyextra->lineNr;
1222 if (!
endScope(yyscanner,yyextra->current_root))
1226 yyextra->typeMode =
false;
1232<Start,ModuleBody,SubprogBody,InterfaceBody,ModuleBodyContains,SubprogBodyContains>^{BS}({PREFIX}{BS_})?{TYPE_SPEC}{BS}({PREFIX}{BS_})?/{SUBPROG}{BS_} {
1235 addInterface(yyscanner,
"$interface$", yyextra->ifType);
1236 startScope(yyscanner,yyextra->last_entry.get());
1241 yy_push_state(SubprogPrefix,yyscanner);
1244<SubprogPrefix>{BS}{SUBPROG}{BS_} {
1251 yyextra->current->bodyLine = yyextra->lineNr + yyextra->lineCountPrepass + 1;
1252 yyextra->current->startLine = yyextra->lineNr;
1255<Start,ModuleBody,SubprogBody,InterfaceBody,ModuleBodyContains,SubprogBodyContains>^{BS}({PREFIX}{BS_})?{SUBPROG}{BS_} {
1260 addInterface(yyscanner,
"$interface$", yyextra->ifType);
1261 startScope(yyscanner,yyextra->last_entry.get());
1266 yy_push_state(Subprog,yyscanner);
1267 yyextra->current->bodyLine = yyextra->lineNr + yyextra->lineCountPrepass + 1;
1268 yyextra->current->startLine = yyextra->lineNr;
1272<Subprog>{ID} { yyextra->current->name = yytext;
1276 if ((yyextra->current_root) &&
1277 (yyextra->current_root->section.isClass() ||
1278 yyextra->current_root->section.isNamespace()))
1280 yyextra->current->name= yyextra->current_root->name +
"::" + yyextra->current->name;
1282 yyextra->modifiers[yyextra->current_root][yyextra->current->name.lower().str()].returnName = std::move(returnName);
1287 yyextra->current_root->name,
"$interface$",
QCString(yytext).lower());
1290 BEGIN(Parameterlist);
QCString substitute(const QCString &s, const QCString &src, const QCString &dst)
substitute all occurrences of src in s by dst
1292<Parameterlist>"(" { yyextra->current->args =
"("; }
1294 yyextra->current->args +=
")";
1297 startScope(yyscanner,yyextra->last_entry.get());
QCString removeRedundantWhiteSpace(const QCString &s)
1300<Parameterlist>{COMMA}|{BS} { yyextra->current->args += yytext;
1304 if (!yyextra->current->argList.empty())
1306 yyextra->current->argList.back().docs = c->
str;
1310<Parameterlist>{ID} {
1314 yyextra->current->args += param;
1318 yyextra->current->argList.push_back(arg);
1320<Parameterlist>{NOARGS} {
1324 startScope(yyscanner,yyextra->last_entry.get());
1327<SubprogBody>result{BS}\({BS}{ID} {
1328 if (yyextra->functionLine)
1333 yyextra->modifiers[yyextra->current_root->parent()][yyextra->current_root->name.lower().str()].returnName = result;
1340<FVariable,SubprogBody,ModuleBody,TypedefBody,TypedefBodyContains>"!<" {
1343 yyextra->current->docLine = yyextra->lineNr;
1344 yyextra->docBlockJavaStyle =
FALSE;
1345 yyextra->docBlock.clear();
1348 yy_push_state(DocBackLine,yyscanner);
1353 if (YY_START == String)
1355 yyextra->colNr -= (int)yyleng;
1360 if ((YY_START != StrIgnore) && (YY_START != String))
1362 yy_push_state(YY_START,yyscanner);
1364 yyextra->debugStr=
"*!";
#define Config_getBool(name)
1369 yyextra->docBlock+=yytext;
1371<DocBackLine>"\n"{BS}"!"("<"|"!"+) {
1372 yyextra->docBlock+=
"\n";
1377 yyextra->colNr -= 1;
1381 std::shared_ptr<Entry> tmp_entry = yyextra->current;
1383 if (yyextra->last_enum)
1385 yyextra->current = yyextra->last_enum;
1389 yyextra->current = yyextra->last_entry;
1393 yyextra->current = std::move(tmp_entry);
1399 else if (yyextra->vtype ==
V_RESULT)
1404 yyextra->docBlock.clear();
QCString stripIndentation(const QCString &s, bool skipFirstLine)
1407<Start,SubprogBody,ModuleBody,TypedefBody,InterfaceBody,ModuleBodyContains,SubprogBodyContains,TypedefBodyContains,FEnum>^{BS} {
1410<Start,SubprogBody,ModuleBody,TypedefBody,InterfaceBody,ModuleBodyContains,SubprogBodyContains,TypedefBodyContains,FEnum>"!>" {
1411 yy_push_state(YY_START,yyscanner);
1412 yyextra->current->docLine = yyextra->lineNr;
1413 yyextra->docBlockJavaStyle =
FALSE;
1414 if (YY_START==SubprogBody) yyextra->docBlockInBody =
TRUE;
1415 yyextra->docBlock.clear();
1423<DocBlock>({CMD}{CMD}){ID}/[^a-z_A-Z0-9] {
1424 yyextra->docBlock += yytext;
1426<DocBlock>{CMD}("f$"|"f["|"f{"|"f(") {
1427 yyextra->docBlock += yytext;
1428 yyextra->docBlockName=&yytext[1];
1429 if (yyextra->docBlockName.at(1)==
'[')
1431 yyextra->docBlockName.at(1)=
']';
1433 if (yyextra->docBlockName.at(1)==
'{')
1435 yyextra->docBlockName.at(1)=
'}';
1437 if (yyextra->docBlockName.at(1)==
'(')
1439 yyextra->docBlockName.at(1)=
')';
1441 yyextra->fencedSize=0;
1442 yyextra->blockString=yytext;
1443 yyextra->blockLineNr=yyextra->lineNr;
1444 BEGIN(DocCopyBlock);
1446<DocBlock>{CMD}"ifile"{B}+"\""[^\n\"]+"\"" {
1447 yyextra->fileName = &yytext[6];
1448 yyextra->fileName = yyextra->fileName.stripWhiteSpace();
1449 yyextra->fileName = yyextra->fileName.mid(1,yyextra->fileName.length()-2);
1450 yyextra->docBlock += yytext;
1452<DocBlock>{CMD}"ifile"{B}+{FILEMASK} {
1453 yyextra->fileName = &yytext[6];
1454 yyextra->fileName = yyextra->fileName.stripWhiteSpace();
1455 yyextra->docBlock += yytext;
1457<DocBlock>{CMD}"iline"{LINENR}/[\n\.] |
1458<DocBlock>{CMD}"iline"{LINENR}{B} {
1463 warn(yyextra->fileName,yyextra->lineNr,
"Invalid line number '{}' for iline command",yytext);
1467 yyextra->lineNr = nr;
1469 yyextra->docBlock += yytext;
int toInt(bool *ok=nullptr, int base=10) const
1471<DocBlock>{B}*"<"{PRE}">" {
1472 yyextra->docBlock += yytext;
1473 yyextra->docBlockName=
"<pre>";
1474 yyextra->fencedSize=0;
1475 yyextra->blockString=yytext;
1476 yyextra->blockLineNr=yyextra->lineNr;
1477 BEGIN(DocCopyBlock);
1479<DocBlock>{B}*"<"<CODE>">" {
1480 yyextra->docBlock += yytext;
1481 yyextra->docBlockName=
"<code>";
1482 yyextra->fencedSize=0;
1483 yyextra->blockString=yytext;
1484 yyextra->blockLineNr=yyextra->lineNr;
1485 BEGIN(DocCopyBlock);
1487<DocBlock>{CMD}"startuml"/[^a-z_A-Z0-9\-] {
1488 yyextra->docBlock += yytext;
1489 yyextra->docBlockName=
"uml";
1490 yyextra->fencedSize=0;
1491 yyextra->blockString=yytext;
1492 yyextra->blockLineNr=yyextra->lineNr;
1493 BEGIN(DocCopyBlock);
1495<DocBlock>{CMD}("verbatim"|"iliteral"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"rtfonly"|"docbookonly"|"dot"|"msc"|"code")/[^a-z_A-Z0-9\-] {
1496 yyextra->docBlock += yytext;
1497 yyextra->docBlockName=&yytext[1];
1498 yyextra->fencedSize=0;
1499 yyextra->blockString=yytext;
1500 yyextra->blockLineNr=yyextra->lineNr;
1501 BEGIN(DocCopyBlock);
1503<DocBlock>"~~~"[~]* {
1505 yyextra->docBlock += pat;
1506 yyextra->docBlockName=
"~~~";
1507 yyextra->fencedSize=pat.
length();
1508 yyextra->blockString=yytext;
1509 yyextra->blockLineNr=yyextra->lineNr;
1510 BEGIN(DocCopyBlock);
1512<DocBlock>"```"[`]*/(".")?[a-zA-Z0-9#_-]+ |
1513<DocBlock>"```"[`]*/"{"[^}]+"}" |
1514<DocBlock>"```"[`]* {
1516 yyextra->docBlock += pat;
1517 yyextra->docBlockName=
"```";
1518 yyextra->fencedSize=pat.
length();
1519 yyextra->blockString=yytext;
1520 yyextra->blockLineNr=yyextra->lineNr;
1521 BEGIN(DocCopyBlock);
1523<DocBlock>"\\ilinebr "{BS} {
1525 int extraSpaces = std::max(0,
static_cast<int>(yyleng-9-yyextra->curIndent-2));
1526 indent.
fill(
' ',extraSpaces);
1528 yyextra->docBlock +=
"\\ilinebr ";
1529 yyextra->docBlock += indent;
QCString fill(char c, int len=-1)
Fills a string with a predefined character.
1532<DocBlock>[^@*`~\/\\\n]+ {
1533 yyextra->docBlock += yytext;
1535<DocBlock>"\n"{BS}"!"(">"|"!"+) {
1536 yyextra->docBlock+=
"\n";
1541 yyextra->colNr -= 1;
1547 yyextra->docBlock += *yytext;
1552<DocCopyBlock>"</"{PRE}">" {
1553 yyextra->docBlock += yytext;
1554 if (yyextra->docBlockName==
"<pre>")
1556 yyextra->docBlockName=
"";
1557 yyextra->blockString.clear();
1558 yyextra->blockLineNr=-1;
1562<DocCopyBlock>"</"{CODE}">" {
1563 yyextra->docBlock += yytext;
1564 if (yyextra->docBlockName==
"<code>")
1566 yyextra->docBlockName=
"";
1567 yyextra->blockString.clear();
1568 yyextra->blockLineNr=-1;
1572<DocCopyBlock>{CMD}("f$"|"f]"|"f}"|"f)") {
1573 yyextra->docBlock += yytext;
1574 if (yyextra->docBlockName==&yytext[1])
1576 yyextra->docBlockName=
"";
1577 yyextra->blockString.clear();
1578 yyextra->blockLineNr=-1;
1582<DocCopyBlock>{CMD}("endverbatim"|"endiliteral"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endmanonly"|"endrtfonly"|"enddot"|"endmsc"|"enduml"|"endcode")/[^a-z_A-Z0-9] {
1583 yyextra->docBlock += yytext;
1584 if (&yytext[4]==yyextra->docBlockName)
1586 yyextra->docBlockName=
"";
1587 yyextra->blockString.clear();
1588 yyextra->blockLineNr=-1;
1593<DocCopyBlock>^{B}*{COMM} {
1594 if (yyextra->docBlockName==
"verbatim")
1602 yyextra->docBlock += indent;
1605<DocCopyBlock>"~~~"[~]* {
1607 yyextra->docBlock += pat;
1608 if (yyextra->docBlockName ==
"~~~" && yyextra->fencedSize==pat.
length())
1610 yyextra->blockString.clear();
1611 yyextra->blockLineNr=-1;
1615<DocCopyBlock>"```"[`]* {
1617 yyextra->docBlock += pat;
1618 if (yyextra->docBlockName ==
"```" && yyextra->fencedSize==pat.
length())
1620 yyextra->blockString.clear();
1621 yyextra->blockLineNr=-1;
1626<DocCopyBlock>[^<@/\*\]!`~"\$\\\n]+ {
1627 yyextra->docBlock += yytext;
1630 yyextra->docBlock += *yytext;
1634 yyextra->docBlock += *yytext;
1638<Prototype>{BS}{SUBPROG}{BS_} {
1639 BEGIN(PrototypeSubprog);
1641<Prototype,PrototypeSubprog>{BS}{SCOPENAME}?{BS}{ID} {
1644 BEGIN(PrototypeArgs);
1647"("|")"|","|{BS_} { yyextra->current->args += yytext; }
1648{ID} { yyextra->current->args += yytext;
1651 yyextra->current->argList.push_back(a);
1660 yyextra->debugStr=
"";
1667 if (yyextra->parsingPrototype)
1671 else if ( yyextra->includeStackPtr <= 0 )
1673 if (YY_START!=INITIAL && YY_START!=Start)
1675 DBG_CTX((stderr,
"==== Error: EOF reached in wrong state (end missing)"));
1700 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
1702 yyextra->lineNr+=yyextra->lineCountPrepass;
1703 yyextra->lineCountPrepass=0;
1704 yyextra->comments.clear();
1715 if (c==
'\t') col+=tabSize-(col%tabSize);
1716 else if (c==
'\n') col=0;
1724 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
1726 for (
const auto &cip : yyextra->comments)
1730 if (c>=from && c<=to)
1741 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
1745 yyextra->last_entry->brief = c->
str;
1750 if (parameter) parameter->
docs = c->
str;
1756 for(
int i=0; i<length; i++)
1776 int parseState = Start;
1777 char quoteSymbol = 0;
1779 int commentIndex = -1;
1781 if (ch !=
'\0') parseState = String;
1783 for(
int i=0; i<length && parseState!=Comment; i++)
1787 if (parseState==String)
1789 if (buf[i]==
'\\') i++;
1798 if (buf[i]==quoteSymbol)
1804 else if (parseState==Start)
1806 parseState = String;
1807 quoteSymbol = buf[i];
1813 if (parseState==Start)
1815 parseState = Comment;
1834 return commentIndex;
1842 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
1843 size_t length = yyextra->inputStringPrepass.length();
1844 for (
size_t i=index+1; i<length; i++) {
1845 if (yyextra->inputStringPrepass[i]==
'!' && i<length-1 && yyextra->inputStringPrepass[i+1]==
'<') {
1846 yyextra->comments.emplace_back(index, yyextra->inputStringPrepass.right(length-i-2));
1849 yyextra->inputStringPrepass.resize(index);
1853static void insertCharacter(
char *contents,
int length,
int pos,
char c)
1856 for(
int i=length; i>pos; i--)
1857 contents[i]=contents[i-1];
1864const char*
prepassFixedForm(
const char* contents,
int *hasContLine,
int fixedCommentAfter)
1867 int prevLineLength=0;
1868 int prevLineAmpOrExclIndex=-1;
1870 char prevQuote =
'\0';
1871 char thisQuote =
'\0';
1872 bool emptyLabel=
TRUE;
1873 bool commented=
FALSE;
1874 bool inSingle=
FALSE;
1875 bool inDouble=
FALSE;
1876 bool inBackslash=
FALSE;
1877 bool fullCommentLine=
TRUE;
1878 bool artificialComment=
FALSE;
1880 int newContentsSize = (int)strlen(contents)+3;
1881 char* newContents = (
char*)malloc(newContentsSize);
1886 sizCont = strlen(contents);
1887 for(
size_t i=0;i<sizCont;i++) {
1889 char c = contents[i];
1890 if (artificialComment && c !=
'\n')
1892 if (c ==
'!' && spaces)
1894 newContents[j++] = c;
1895 artificialComment =
FALSE;
1900 else if (c ==
' ' || c ==
'\t')
continue;
1910 if (j>=newContentsSize-3) {
1911 newContents = (
char*)realloc(newContents, newContentsSize+1000);
1912 newContentsSize = newContentsSize+1000;
1917 if (!fullCommentLine)
1919 prevLineLength=column;
1920 prevLineAmpOrExclIndex=
getAmpOrExclAtTheEnd(&contents[i-prevLineLength+1], prevLineLength,prevQuote);
1921 if (prevLineAmpOrExclIndex == -1) prevLineAmpOrExclIndex = column - 1;
1924 prevLineAmpOrExclIndex = -1;
1930 prevLineLength+=column;
1934 hasContLine[curLine - 1] = 1;
1937 artificialComment=
FALSE;
1939 fullCommentLine=
TRUE;
1944 prevQuote = thisQuote;
1957 newContents[j]=
'\000';
1958 newContentsSize = (int)strlen(newContents);
1959 if (newContents[newContentsSize - 1] !=
'\n')
1962 newContents = (
char*)realloc(newContents, newContentsSize+2);
1963 newContents[newContentsSize] =
'\n';
1964 newContents[newContentsSize + 1] =
'\000';
1970 if ((column <= fixedCommentAfter) && (column!=6) && !commented)
1973 fullCommentLine=
FALSE;
1977 inBackslash = !inBackslash;
1984 inSingle = !inSingle;
1985 if (inSingle) thisQuote = c;
1986 else thisQuote =
'\0';
1994 inDouble = !inDouble;
1995 if (inDouble) thisQuote = c;
1996 else thisQuote =
'\0';
2001 inBackslash =
FALSE;
2008 if ((column <= fixedCommentAfter) && (column!=6))
2016 else if ((c ==
'!') && !inDouble && !inSingle)
2023 if (!commented) fullCommentLine=
FALSE;
2030 if (!commented && (column < 6) && ((c -
'0') >= 0) && ((c -
'0') <= 9))
2034 else if (column==6 && emptyLabel)
2036 if (!commented) fullCommentLine=
FALSE;
2041 if (prevLineAmpOrExclIndex==-1)
2050 if (curLine != 1)
insertCharacter(newContents, j+1, (j+1)-6-prevLineLength+prevLineAmpOrExclIndex+skipped,
'&');
2056 hasContLine[curLine - 1] = 1;
2065 else if ((column > fixedCommentAfter) && !commented)
2076 artificialComment =
TRUE;
2088 if (!commented) fullCommentLine=
FALSE;
2104 newContents = (
char*)realloc(newContents, 2);
2105 newContents[0] =
'\n';
2106 newContents[1] =
'\000';
2108 else if (newContents[j] ==
'\n')
2110 newContents = (
char*)realloc(newContents, j+2);
2111 newContents[j + 1] =
'\000';
2115 newContents = (
char*)realloc(newContents, j+3);
2116 newContents[j + 1] =
'\n';
2117 newContents[j + 2] =
'\000';
2124 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
2125 if (yyextra->includeStackCnt <= yyextra->includeStackPtr)
2127 yyextra->includeStackCnt++;
2128 yyextra->includeStack = (YY_BUFFER_STATE *)realloc(yyextra->includeStack, yyextra->includeStackCnt *
sizeof(YY_BUFFER_STATE));
2130 yyextra->includeStack[yyextra->includeStackPtr++] = YY_CURRENT_BUFFER;
2131 yy_switch_to_buffer(yy_scan_string(buffer.
data(),yyscanner),yyscanner);
2138 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
2140 yyextra->includeStackPtr --;
2141 yy_delete_buffer( YY_CURRENT_BUFFER, yyscanner );
2142 yy_switch_to_buffer( yyextra->includeStack[yyextra->includeStackPtr], yyscanner );
2146static void copyEntry(std::shared_ptr<Entry> dest,
const std::shared_ptr<Entry> &src)
2148 dest->type = src->type;
2149 dest->fileName = src->fileName;
2150 dest->startLine = src->startLine;
2151 dest->bodyLine = src->bodyLine;
2152 dest->endBodyLine = src->endBodyLine;
2153 dest->args = src->args;
2154 dest->argList = src->argList;
2155 dest->doc = src->doc;
2156 dest->docLine = src->docLine;
2157 dest->docFile = src->docFile;
2158 dest->brief = src->brief;
2159 dest->briefLine= src->briefLine;
2160 dest->briefFile= src->briefFile;
2170 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
2171 if (yyextra->moduleProcedures.empty())
return;
2174 std::map<std::string,std::shared_ptr<Entry>> procMap;
2176 for (
const auto& cf: current_root->
children())
2178 if (!cf->section.isFunction())
2189 procMap.emplace(name.
str(), cf);
2195 for (
const auto& ce1: yyextra->moduleProcedures)
2197 if (procMap.find(ce1->name.str())!=procMap.end())
2199 std::shared_ptr<Entry> proc = procMap[ce1->name.str()];
2203 yyextra->moduleProcedures.clear();
2210 int start = extracted.
find(
"(");
2213 extracted.
remove(0, start+1);
2218 size_t length = extracted.
length();
2230 if (parensPart.
length() == 1)
2245 return "bind(C, name=" + parensPart +
")";
2282 if (mdfString.
find(
"dimension")==0)
2286 else if (mdfString.
contains(
"intent"))
2290 bool isout = tmp.
contains(
"out")!=0;
2295 else if (mdfString==
"public")
2299 else if (mdfString==
"private")
2303 else if (mdfString==
"protected")
2307 else if (mdfString==
"optional")
2311 else if (mdfString==
"allocatable")
2315 else if (mdfString==
"external")
2319 else if (mdfString==
"intrinsic")
2323 else if (mdfString==
"parameter")
2327 else if (mdfString==
"pointer")
2331 else if (mdfString==
"target")
2335 else if (mdfString==
"save")
2339 else if (mdfString==
"nopass")
2343 else if (mdfString==
"deferred")
2347 else if (mdfString==
"non_overridable")
2351 else if (mdfString==
"contiguous")
2355 else if (mdfString==
"volatile")
2359 else if (mdfString==
"value")
2363 else if (mdfString.
contains(
"pass"))
2397 if ((!byTypeName && arg.
name.
lower() == cname) ||
2398 (byTypeName && arg.
type.
lower() == cname)
2413 if (!typeName.
isEmpty()) typeName +=
", ";
2418 if (!typeName.
isEmpty()) typeName +=
", ";
2423 if (!typeName.
isEmpty()) typeName +=
", ";
2424 typeName +=
"optional";
2428 if (!typeName.
isEmpty()) typeName +=
", ";
2429 typeName +=
"allocatable";
2433 if (!typeName.
contains(
"external"))
2435 if (!typeName.
isEmpty()) typeName +=
", ";
2436 typeName +=
"external";
2441 if (!typeName.
isEmpty()) typeName +=
", ";
2442 typeName +=
"intrinsic";
2446 if (!typeName.
isEmpty()) typeName +=
", ";
2447 typeName +=
"parameter";
2451 if (!typeName.
isEmpty()) typeName +=
", ";
2452 typeName +=
"pointer";
2456 if (!typeName.
isEmpty()) typeName +=
", ";
2457 typeName +=
"target";
2461 if (!typeName.
isEmpty()) typeName +=
", ";
2466 if (!typeName.
isEmpty()) typeName +=
", ";
2467 typeName +=
"deferred";
2471 if (!typeName.
isEmpty()) typeName +=
", ";
2472 typeName +=
"non_overridable";
2476 if (!typeName.
isEmpty()) typeName +=
", ";
2477 typeName +=
"nopass";
2481 if (!typeName.
isEmpty()) typeName +=
", ";
2484 typeName +=
"(" + mdfs.
passVar +
")";
2488 if (!typeName.
isEmpty()) typeName +=
", ";
2493 if (!typeName.
isEmpty()) typeName +=
", ";
2494 typeName +=
"public";
2498 if (!typeName.
isEmpty()) typeName +=
", ";
2499 typeName +=
"private";
2503 if (!typeName.
isEmpty()) typeName +=
", ";
2504 typeName +=
"protected";
2508 if (!typeName.
isEmpty()) typeName +=
", ";
2509 typeName +=
"contiguous";
2513 if (!typeName.
isEmpty()) typeName +=
", ";
2514 typeName +=
"volatile";
2518 if (!typeName.
isEmpty()) typeName +=
", ";
2519 typeName +=
"value";
2542 ent->
spec.setFinal(
true);
2546 ent->
virt = Specifier::Pure;
2555 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
2557 yyextra->current_root= scope;
2559 yyextra->modifiers.emplace(scope, std::map<std::string,SymbolModifiers>());
2562 yyextra->current = std::make_shared<Entry>();
2571 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
2572 if (yyextra->global_scope == scope)
2574 yyextra->global_scope =
nullptr;
2582 if (yyextra->current_root->parent() || isGlobalRoot)
2584 yyextra->current_root= yyextra->current_root->parent();
2588 fprintf(stderr,
"parse error in end <scopename>\n");
2594 yyextra->current = std::make_shared<Entry>();
2598 std::map<std::string,SymbolModifiers>& mdfsMap = yyextra->modifiers[scope];
2600 if (scope->
section.isFunction())
2603 for (
const auto &kv : mdfsMap)
2617 if (yyextra->modifiers[scope].find(returnName.
str())!=yyextra->modifiers[scope].end())
2619 scope->
type = yyextra->modifiers[scope][returnName.
str()].type;
2624 if (scope->
section.isClass() && scope->
spec.isInterface())
2631 for (
const auto &ce : scope->
children())
2633 if (!ce->section.isFunction())
2647 arg->
type =
"external " + ce->type +
"(";
2648 for (
unsigned int i=0; i<ce->argList.size(); i++)
2654 const Argument &subarg = ce->argList.at(i);
2662 yyextra->modifiers.erase(scope);
2668 if (!scope->
section.isFunction())
2671 for (
const auto &ce : scope->
children())
2673 if (!ce->section.isVariable() && !ce->section.isFunction() && !ce->section.isClass())
2677 if (mdfsMap.find(ce->name.lower().str())!=mdfsMap.end())
2681 if (ce->section.isVariable() || ce->section.isFunction())
2683 int end = ce->name.findRev(
":");
2685 ce->name.remove(0,
end+1);
2691 yyextra->modifiers.erase(scope);
2705 bool procMapCreated =
false;
2706 std::unordered_map<std::string,std::shared_ptr<Entry>> procMap;
2709 bool interfMapCreated =
false;
2710 std::unordered_map<std::string,std::shared_ptr<Entry>> interfMap;
2713 for (
const auto &ce: scope->
children())
2715 if (!ce->section.isClass())
2719 std::unordered_map<std::string,std::shared_ptr<Entry>> methodMap;
2720 for (
auto &ct: ce->children())
2722 if (!ct->section.isFunction())
2725 if (ct->type==
"generic")
2728 if (ct->virt==Specifier::Pure)
2732 if (!procMapCreated)
2734 for (
const auto &cf: scope->
children())
2736 if (cf->section.isFunction())
2738 procMap.emplace(cf->name.str(), cf);
2741 procMapCreated =
true;
2746 if (procMap.find(implName.
str())!=procMap.end())
2748 std::shared_ptr<Entry> proc = procMap[implName.
str()];
2749 ct->args = proc->args;
2751 if (ct->brief.isEmpty())
2753 ct->brief = proc->brief;
2754 ct->briefLine = proc->briefLine;
2755 ct->briefFile = proc->briefFile;
2757 if (ct->doc.isEmpty())
2759 ct->doc = proc->doc;
2760 ct->docLine = proc->docLine;
2761 ct->docFile = proc->docFile;
2763 methodMap.emplace(ct->name.str(), ct);
2768 for (
auto &ct: ce->children())
2770 if (!ct->section.isFunction())
2773 if (ct->virt != Specifier::Pure)
2777 if (!interfMapCreated)
2779 for(
const auto &cf: scope->
children())
2781 if (cf->section.isClass() && cf->spec.isInterface() && cf->type==
"abstract")
2783 std::shared_ptr<Entry> ci = cf->children().front();
2784 interfMap.emplace(ci->name.str(), ci);
2787 interfMapCreated =
true;
2792 if (interfMap.find(implName.
str())!= interfMap.end() )
2794 std::shared_ptr<Entry> proc = interfMap[implName.
str()];
2795 ct->args = proc->args;
2797 if (ct->brief.isEmpty())
2799 ct->brief = proc->brief;
2800 ct->briefLine = proc->briefLine;
2801 ct->briefFile = proc->briefFile;
2803 if (ct->doc.isEmpty())
2805 ct->doc = proc->doc;
2806 ct->docLine = proc->docLine;
2807 ct->docFile = proc->docFile;
2810 methodMap.emplace(ct->name.str(), ct);
2816 for (
auto &ct: ce->children())
2818 if (!ct->section.isFunction())
2821 if (ct->type!=
"generic")
2826 if (methodMap.find(methodName.
str()) != methodMap.end())
2828 std::shared_ptr<Entry> method = methodMap[methodName.
str()];
2829 ct->args = method->args;
2831 if (ct->brief.isEmpty())
2833 ct->brief = method->brief;
2834 ct->briefLine = method->briefLine;
2835 ct->briefFile = method->briefFile;
2837 if (ct->doc.isEmpty())
2839 ct->doc = method->doc;
2840 ct->docLine = method->docLine;
2841 ct->docFile = method->docFile;
2851 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
2853 while ( c < max_size && yyextra->inputString[yyextra->inputPosition] )
2855 *buf = yyextra->inputString[yyextra->inputPosition++] ;
2863 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
2864 yyextra->last_entry.reset();
2869 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
2870 if (yyextra->typeMode)
2872 yyextra->current->protection = yyextra->typeProtection;
2874 else if (yyextra->current_root && yyextra->current_root->section.isClass() && yyextra->current_root->spec.isInterface())
2876 yyextra->current->protection = Protection::Public;
2878 else if (yyextra->current_root && yyextra->current_root->section.isFunction())
2880 yyextra->current->protection = Protection::Private;
2884 yyextra->current->protection = yyextra->defaultProtection;
2886 yyextra->current->mtype = MethodTypes::Method;
2887 yyextra->current->virt = Specifier::Normal;
2888 yyextra->current->isStatic =
false;
2889 yyextra->current->lang = SrcLangExt::Fortran;
2890 yyextra->commentScanner.initGroupInfo(yyextra->current.get());
2898 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
2899 if (case_insens) yyextra->current->name = yyextra->current->name.lower();
2901 yyextra->last_entry = yyextra->current;
2902 yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current);
2908 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
2909 DBG_CTX((stderr,
"0=========> got module %s\n",
qPrint(name)));
2912 yyextra->current->section = EntryType::makeNamespace();
2914 yyextra->current->section = EntryType::makeFunction();
2918 yyextra->current->name = name;
2922 QCString fname = yyextra->fileName;
2925 if (yyextra->mainPrograms) fname +=
"__" +
QCString().
setNum(yyextra->mainPrograms);
2926 yyextra->mainPrograms++;
2928 yyextra->current->name =
substitute(fname,
".",
"_");
2930 yyextra->current->type =
"program";
2931 yyextra->current->fileName = yyextra->fileName;
2932 yyextra->current->bodyLine = yyextra->lineNr;
2933 yyextra->current->startLine = yyextra->lineNr;
2934 yyextra->current->protection = Protection::Public ;
2936 startScope(yyscanner,yyextra->last_entry.get());
2942 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
2943 DBG_CTX((stderr,
"1=========> got subprog, type: %s\n",
qPrint(text)));
2944 yyextra->subrCurrent.push_back(yyextra->current);
2945 yyextra->current->section = EntryType::makeFunction();
2947 yyextra->functionLine = (subtype.
find(
"function") != -1);
2948 yyextra->current->type +=
" " + subtype;
2952 yyextra->current->virt = Specifier::Virtual;
2954 yyextra->current->fileName = yyextra->fileName;
2955 yyextra->current->bodyLine = yyextra->lineNr;
2956 yyextra->current->startLine = yyextra->lineNr;
2957 yyextra->current->args.
clear();
2958 yyextra->current->argList.clear();
2959 yyextra->docBlock.clear();
2968 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
2969 if (YY_START == Start)
2972 yy_push_state(ModuleBody,yyscanner);
2975 yyextra->current->section = EntryType::makeClass();
2976 yyextra->current->spec =
TypeSpecifier().setInterface(
true);
2977 yyextra->current->name = name;
2982 yyextra->current->type =
"abstract";
2986 yyextra->current->type =
"generic";
2992 yyextra->current->type =
"";
2996 if ((yyextra->current_root) &&
2997 (yyextra->current_root->section.isClass() ||
2998 yyextra->current_root->section.isNamespace()))
3000 yyextra->current->name= yyextra->current_root->name +
"::" + yyextra->current->name;
3003 yyextra->current->fileName = yyextra->fileName;
3004 yyextra->current->bodyLine = yyextra->lineNr;
3005 yyextra->current->startLine = yyextra->lineNr;
3016 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
3019 for (
Argument &a:yyextra->current_root->argList)
3034 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
3037 yyextra->current->briefFile = yyextra->fileName;
3038 yyextra->current->briefLine = yyextra->lineNr;
3042 yyextra->current->docFile = yyextra->fileName;
3043 yyextra->current->docLine = yyextra->lineNr;
3051 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
3053 if (yyextra->docBlockInBody && hideInBodyDocs)
3055 yyextra->docBlockInBody =
FALSE;
3058 DBG_CTX((stderr,
"call parseCommentBlock [%s]\n",
qPrint(doc)));
3059 int lineNr = brief ? yyextra->current->briefLine : yyextra->current->docLine;
3061 bool needsEntry =
FALSE;
3062 Markdown markdown(yyextra->fileName,lineNr);
3065 QCString processedDoc =
Config_getBool(MARKDOWN_SUPPORT) ? markdown.process(strippedDoc,lineNr) : strippedDoc;
3066 while (yyextra->commentScanner.parseCommentBlock(
3067 yyextra->thisParser,
3068 yyextra->docBlockInBody ? yyextra->subrCurrent.back().get() : yyextra->current.get(),
3072 yyextra->docBlockInBody ?
FALSE : brief,
3073 yyextra->docBlockInBody ?
FALSE : yyextra->docBlockJavaStyle,
3074 yyextra->docBlockInBody,
3075 yyextra->defaultProtection,
3082 DBG_CTX((stderr,
"parseCommentBlock position=%d [%s] needsEntry=%d\n",position,doc.
data()+position,needsEntry));
3085 DBG_CTX((stderr,
"parseCommentBlock position=%d [%s] needsEntry=%d\n",position,doc.
data()+position,needsEntry));
3088 yyextra->docBlockInBody =
FALSE;
3095 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
3099 std::shared_ptr<Entry> tmp_entry = yyextra->current;
3100 yyextra->current = yyextra->subrCurrent.back();
3103 yyextra->current->inbodyDocs =
"";
3112 int dir1 = yyextra->modifiers[yyextra->current_root][yyextra->argName.lower().str()].direction;
3127 yyextra->argName +
" " + loc_doc,brief);
3133 warn(yyextra->fileName,yyextra->lineNr,
"Routine: {}{} inconsistency between intent attribute and documentation for parameter {}:",
3134 yyextra->current->name,yyextra->current->args,yyextra->argName);
3136 yyextra->argName +
" " + loc_doc,brief);
3149 yyextra->current = tmp_entry;
3153 yyextra->argName +
" " + loc_doc,brief);
3157 warn(yyextra->fileName,yyextra->lineNr,
"Routine: {}{} inconsistency between intent attribute and documentation for parameter {}:",
3158 yyextra->current->name,yyextra->current->args,yyextra->argName);
3160 yyextra->argName +
" " + loc_doc,brief);
3174 yyextra->argName +
" " + loc_doc,brief);
3179 warn(yyextra->fileName,yyextra->lineNr,
"Routine: {}{} inconsistency between intent attribute and documentation for parameter {}:",
3180 yyextra->current->name,yyextra->current->args,yyextra->argName);
3182 yyextra->argName +
" " + loc_doc,brief);
3189 yyextra->argName +
" " + loc_doc,brief);
3193 yyextra->current = tmp_entry;
3199 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
3203 std::shared_ptr<Entry> tmp_entry = yyextra->current;
3204 yyextra->current = yyextra->subrCurrent.back();
3207 yyextra->current->inbodyDocs =
"";
3223 yyextra->current = std::move(tmp_entry);
3231 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
3232 char *tmpBuf =
nullptr;
3235 if (fileBuf==
nullptr || fileBuf[0]==
'\0')
return;
3237 yyextra->defaultProtection = Protection::Public;
3238 yyextra->inputString = fileBuf;
3239 yyextra->inputPosition = 0;
3240 yyextra->inputStringPrepass =
nullptr;
3241 yyextra->inputPositionPrepass = 0;
3244 yyextra->current_root = rt.get();
3245 yyextra->global_root = rt;
3249 if (yyextra->isFixedForm)
3251 yyextra->fixedCommentAfter =
Config_getInt(FORTRAN_COMMENT_AFTER);
3252 msg(
"Prepassing fixed form of {}\n", fileName);
3258 yyextra->inputString =
prepassFixedForm(fileBuf,
nullptr,yyextra->fixedCommentAfter);
3267 else if (yyextra->inputString[strlen(fileBuf)-1] !=
'\n')
3269 tmpBuf = (
char *)malloc(strlen(fileBuf)+2);
3270 strcpy(tmpBuf,fileBuf);
3271 tmpBuf[strlen(fileBuf)]=
'\n';
3272 tmpBuf[strlen(fileBuf)+1]=
'\000';
3273 yyextra->inputString = tmpBuf;
3276 yyextra->lineNr= 1 ;
3277 yyextra->fileName = fileName;
3278 msg(
"Parsing file {}...\n",yyextra->fileName);
3280 yyextra->global_scope = rt.get();
3283 yyextra->commentScanner.enterFile(yyextra->fileName,yyextra->lineNr);
3286 yyextra->current = std::make_shared<Entry>();
3287 yyextra->current->lang = SrcLangExt::Fortran;
3288 yyextra->current->name = yyextra->fileName;
3289 yyextra->current->section = EntryType::makeSource();
3290 yyextra->file_root = yyextra->current;
3291 yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current);
3292 yyextra->current->lang = SrcLangExt::Fortran;
3294 fortranscannerYYrestart(
nullptr, yyscanner );
3299 fortranscannerYYlex(yyscanner);
3300 yyextra->commentScanner.leaveFile(yyextra->fileName,yyextra->lineNr);
3302 if (yyextra->global_scope && yyextra->global_scope !=
INVALID_ENTRY)
3309 rt->program.str(std::string());
3311 yyextra->moduleProcedures.clear();
3314 free((
char*)tmpBuf);
3315 yyextra->inputString=
nullptr;
3317 if (yyextra->isFixedForm)
3319 free((
char*)yyextra->inputString);
3320 yyextra->inputString=
nullptr;
3342 : p(std::make_unique<Private>(format))
3348 fortranscannerYYlex_destroy(
p->yyscanner);
3352 const char *fileBuf,
3353 const std::shared_ptr<Entry> &root,
3356 struct yyguts_t *yyg = (
struct yyguts_t*)
p->yyscanner;
3357 yyextra->thisParser =
this;
3371 struct yyguts_t *yyg = (
struct yyguts_t*)
p->yyscanner;
3373 yyextra->parsingPrototype =
TRUE;
3375 fortranscannerYYlex(
p->yyscanner);
3376 yyextra->parsingPrototype =
FALSE;
3384 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
3385 fprintf(stderr,
"********************************************************************\n");
3386 if (yyextra->blockLineNr == -1)
3388 fprintf(stderr,
"Error in file %s line: %d, state: %d(%s)\n",
3393 fprintf(stderr,
"Error in file %s line: %d, state: %d(%s), starting command: '%s' probable line reference: %d\n",
3394 qPrint(yyextra->fileName),yyextra->lineNr,YY_START,
stateToString(YY_START),
qPrint(yyextra->blockString),yyextra->blockLineNr);
3396 fprintf(stderr,
"********************************************************************\n");
3400 for (
const auto &ce : yyextra->global_root->children())
3402 if (ce == yyextra->file_root) start=
TRUE;
3403 if (start) ce->reset();
3407 (void)yy_top_state(yyscanner);
3415 struct yyguts_t *yyg = (
struct yyguts_t*)yyscanner;
3416 if ( yyg->yy_start_stack_ptr <= 0 )
3417 warn(yyextra->fileName,yyextra->lineNr,
"Unexpected statement '{}'",yytext );
3419 yy_pop_state(yyscanner);
3423#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 & 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.
#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 void startScope(yyscan_t yyscanner, Entry *scope)
static QCString applyModifiers(QCString typeName, const SymbolModifiers &mdfs)
static bool endScope(yyscan_t yyscanner, Entry *scope, bool isGlobalRoot=FALSE)
static int yyread(yyscan_t yyscanner, char *buf, int max_size)
static Argument * findArgument(Entry *subprog, QCString name, bool byTypeName=FALSE)
static void insertCharacter(char *contents, int length, int pos, char c)
static void pop_state(yyscan_t yyscanner)
fortranscannerYY_state extra
Private(FortranFormat fmt)
bool recognizeFixedForm(const QCString &contents, FortranFormat format)