From f5ffd481a44fa5eae225ce728d1777070c4143e1 Mon Sep 17 00:00:00 2001 From: albert-github Date: Sat, 17 Feb 2018 18:32:47 +0100 Subject: Implementation Fortran ENUM / ENUMERATION All ENUMs are anonymous as they don't have a name defined in the Fortran standard. --- src/fortrancode.l | 90 +++++++++++++++++++++++++++--------------- src/fortranscanner.l | 109 ++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 153 insertions(+), 46 deletions(-) diff --git a/src/fortrancode.l b/src/fortrancode.l index 501b492..28caef2 100644 --- a/src/fortrancode.l +++ b/src/fortrancode.l @@ -684,7 +684,7 @@ NUM_TYPE (complex|integer|logical|real) LOG_OPER (\.and\.|\.eq\.|\.eqv\.|\.ge\.|\.gt\.|\.le\.|\.lt\.|\.ne\.|\.neqv\.|\.or\.|\.not\.) KIND {ARGS} CHAR (CHARACTER{ARGS}?|CHARACTER{BS}"*"({BS}[0-9]+|{ARGS})) -TYPE_SPEC (({NUM_TYPE}({BS}"*"{BS}[0-9]+)?)|({NUM_TYPE}{KIND})|DOUBLE{BS}COMPLEX|DOUBLE{BS}PRECISION|{CHAR}|TYPE|CLASS|PROCEDURE) +TYPE_SPEC (({NUM_TYPE}({BS}"*"{BS}[0-9]+)?)|({NUM_TYPE}{KIND})|DOUBLE{BS}COMPLEX|DOUBLE{BS}PRECISION|{CHAR}|TYPE|CLASS|PROCEDURE|ENUMERATOR) INTENT_SPEC intent{BS}"("{BS}(in|out|in{BS}out){BS}")" ATTR_SPEC (IMPLICIT|ALLOCATABLE|DIMENSION{ARGS}|EXTERNAL|{INTENT_SPEC}|INTRINSIC|OPTIONAL|PARAMETER|POINTER|PROTECTED|PRIVATE|PUBLIC|SAVE|TARGET|RECURSIVE|PURE|IMPURE|ELEMENTAL|VALUE|NOPASS|DEFERRED|CONTIGUOUS|VOLATILE) @@ -695,6 +695,7 @@ FLOW (DO|SELECT|CASE|SELECT{BS}(CASE|TYPE)|WHERE|IF|THEN|ELSE|WHILE|FORALL| COMMANDS (FORMAT|CONTAINS|MODULE{BS_}PROCEDURE|WRITE|READ|ALLOCATE|ALLOCATED|ASSOCIATED|PRESENT|DEALLOCATE|NULLIFY|SIZE|INQUIRE|OPEN|CLOSE|FLUSH|DATA|COMMON) IGNORE (CALL) PREFIX (RECURSIVE{BS_}|IMPURE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,3}(RECURSIVE|IMPURE|PURE|ELEMENTAL)? +LANGUAGE_BIND_SPEC BIND{BS}"("{BS}C{BS}(,{BS}NAME{BS}"="{BS}"\""(.*)"\""{BS})?")" /* | */ @@ -775,12 +776,12 @@ PREFIX (RECURSIVE{BS_}|IMPURE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,3}(RECURSIVE|I BEGIN(Use); } "ONLY" { // TODO: rename - startFontClass("keywordtype"); - codifyLines(yytext); - endFontClass(); + startFontClass("keywordtype"); + codifyLines(yytext); + endFontClass(); yy_push_state(YY_START); - BEGIN(UseOnly); - } + BEGIN(UseOnly); + } {ID} { QCString tmp = yytext; tmp = tmp.lower(); @@ -835,15 +836,29 @@ PREFIX (RECURSIVE{BS_}|IMPURE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,3}(RECURSIVE|I BEGIN(ClassName); if (!qstricmp(yytext,"module")) currentModule="module"; } +("enum")/{BS_}|{BS}{COMMA}{BS}{LANGUAGE_BIND_SPEC}|\n { // + startScope(); + startFontClass("keyword"); + codifyLines(yytext); + endFontClass(); + yy_push_state(YY_START); + BEGIN(ClassName); + currentClass="class"; + } +<*>{LANGUAGE_BIND_SPEC} { // + startFontClass("keyword"); + codifyLines(yytext); + endFontClass(); + } ("type")/{BS_}|({COMMA}({ACCESS_SPEC}|ABSTRACT|EXTENDS))|\n { // - startScope(); - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); + startScope(); + startFontClass("keyword"); + codifyLines(yytext); + endFontClass(); yy_push_state(YY_START); - BEGIN(ClassName); - currentClass="class"; - } + BEGIN(ClassName); + currentClass="class"; + } {ID} { if (currentModule == "module") { @@ -853,22 +868,26 @@ PREFIX (RECURSIVE{BS_}|IMPURE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,3}(RECURSIVE|I generateLink(*g_code,yytext); yy_pop_state(); } -({ACCESS_SPEC}|ABSTRACT|EXTENDS)/[,:( ] { //| variable deklaration +({ACCESS_SPEC}|ABSTRACT|EXTENDS)/[,:( ] { //| variable declaration startFontClass("keyword"); g_code->codify(yytext); endFontClass(); } \n { // interface may be without name yy_pop_state(); - YY_FTN_REJECT; - } + YY_FTN_REJECT; + } +^{BS}"end"({BS_}"enum").* { // just reset currentClass, rest is done in following rule + currentClass=0; + YY_FTN_REJECT; + } ^{BS}"end"({BS_}"type").* { // just reset currentClass, rest is done in following rule currentClass=0; - YY_FTN_REJECT; + YY_FTN_REJECT; } ^{BS}"end"({BS_}"module").* { // just reset currentModule, rest is done in following rule currentModule=0; - YY_FTN_REJECT; + YY_FTN_REJECT; } /*-------- subprog definition -------------------------------------*/ ({PREFIX}{BS_})?{TYPE_SPEC}{BS_}({PREFIX}{BS_})?{BS}/{SUBPROG}{BS_} { // TYPE_SPEC is for old function style function result @@ -901,7 +920,7 @@ PREFIX (RECURSIVE{BS_}|IMPURE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,3}(RECURSIVE|I yy_pop_state(); YY_FTN_RESET } -^{BS}"end"{BS}("block"{BS}"data"|{SUBPROG}|"module"|"program"|"type"|"interface")?{BS} { // Fortran subroutine or function ends +^{BS}"end"{BS}("block"{BS}"data"|{SUBPROG}|"module"|"program"|"enum"|"type"|"interface")?{BS} { // Fortran subroutine or function ends //cout << "===> end function " << yytext << endl; endScope(); startFontClass("keyword"); @@ -914,7 +933,7 @@ PREFIX (RECURSIVE{BS_}|IMPURE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,3}(RECURSIVE|I generateLink(*g_code,yytext); yy_pop_state(); } -^{BS}"end"{BS}("block"{BS}"data"|{SUBPROG}|"module"|"program"|"type"|"interface"){BS}/(\n|!) { // Fortran subroutine or function ends +^{BS}"end"{BS}("block"{BS}"data"|{SUBPROG}|"module"|"program"|"enum"|"type"|"interface"){BS}/(\n|!) { // Fortran subroutine or function ends //cout << "===> end function " << yytext << endl; endScope(); startFontClass("keyword"); @@ -934,7 +953,7 @@ PREFIX (RECURSIVE{BS_}|IMPURE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,3}(RECURSIVE|I g_code->codify(yytext); endFontClass(); } -({TYPE_SPEC}|{ATTR_SPEC})/[,:( ] { //| variable deklaration +({TYPE_SPEC}|{ATTR_SPEC})/[,:( ] { //| variable declaration startFontClass("keywordtype"); g_code->codify(yytext); endFontClass(); @@ -947,7 +966,7 @@ PREFIX (RECURSIVE{BS_}|IMPURE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,3}(RECURSIVE|I endFontClass(); } else if (g_currentMemberDef && ((g_currentMemberDef->isFunction() && (g_currentMemberDef->typeString() != QCString("subroutine"))) || - g_currentMemberDef->isVariable())) + g_currentMemberDef->isVariable() || g_currentMemberDef->isEnumValue())) { generateLink(*g_code, yytext); } @@ -956,15 +975,15 @@ PREFIX (RECURSIVE{BS_}|IMPURE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,3}(RECURSIVE|I g_code->codify(yytext); addLocalVar(yytext); } - } -{BS}("=>"|"="){BS} { // Procedure binding - BEGIN(DeclarationBinding); - g_code->codify(yytext); - } -{ID} { // Type bound procedure link + } +{BS}("=>"|"="){BS} { // Procedure binding + BEGIN(DeclarationBinding); + g_code->codify(yytext); + } +{ID} { // Type bound procedure link generateLink(*g_code, yytext); yy_pop_state(); - } + } [(] { // start of array specification bracketCount++; g_code->codify(yytext); @@ -1029,11 +1048,20 @@ PREFIX (RECURSIVE{BS_}|IMPURE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,3}(RECURSIVE|I // fixed form continuation line YY_FTN_REJECT; } + else if (QCString(yytext).stripWhiteSpace().lower() == "type") + { + yy_push_state(YY_START); + BEGIN(Declaration); + startFontClass("keywordtype"); + g_code->codify(QCString(yytext).stripWhiteSpace()); + endFontClass(); + g_code->codify(yytext + 4); + } else { - g_insideBody=TRUE; + g_insideBody=TRUE; generateLink(*g_code, yytext); - g_insideBody=FALSE; + g_insideBody=FALSE; } } diff --git a/src/fortranscanner.l b/src/fortranscanner.l index 85b6de9..d4a94c7 100644 --- a/src/fortranscanner.l +++ b/src/fortranscanner.l @@ -164,6 +164,7 @@ static Entry* global_root = 0 ; static Entry* file_root = 0 ; static Entry* current = 0 ; static Entry* last_entry = 0 ; +static Entry* last_enum = 0 ; static ScanVar v_type = V_IGNORE; // type of parsed variable static QList moduleProcedures; // list of all interfaces which contain unresolved // module procedures @@ -198,6 +199,7 @@ static SymbolModifiers currentModifiers; //! Holds program scope->symbol name->symbol modifiers. static QMap > modifiers; +static int anonCount = 0 ; //----------------------------------------------------------------------------- static int yyread(char *buf,int max_size); @@ -226,6 +228,7 @@ static QCString extractFromParens(const QCString name); static CommentInPrepass* locatePrepassComment(int from, int to); static void updateVariablePrepassComment(int from, int to); static void newLine(); +static void initEntry(); //----------------------------------------------------------------------------- #undef YY_INPUT @@ -260,7 +263,7 @@ NUM_TYPE (complex|integer|logical|real) LOG_OPER (\.and\.|\.eq\.|\.eqv\.|\.ge\.|\.gt\.|\.le\.|\.lt\.|\.ne\.|\.neqv\.|\.or\.|\.not\.) KIND {ARGS} CHAR (CHARACTER{ARGS}?|CHARACTER{BS}"*"({BS}[0-9]+|{ARGS})) -TYPE_SPEC (({NUM_TYPE}({BS}"*"{BS}[0-9]+)?)|({NUM_TYPE}{KIND})|DOUBLE{BS}COMPLEX|DOUBLE{BS}PRECISION|{CHAR}|TYPE{ARGS}|CLASS{ARGS}|PROCEDURE{ARGS}?) +TYPE_SPEC (({NUM_TYPE}({BS}"*"{BS}[0-9]+)?)|({NUM_TYPE}{KIND})|DOUBLE{BS}COMPLEX|DOUBLE{BS}PRECISION|ENUMERATOR|{CHAR}|TYPE{ARGS}|CLASS{ARGS}|PROCEDURE{ARGS}?) INTENT_SPEC intent{BS}"("{BS}(in|out|in{BS}out){BS}")" ATTR_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) @@ -297,6 +300,7 @@ SCOPENAME ({ID}{BS}"::"{BS})* %x Variable %x Initialization %x ArrayInitializer +%x Enum %x Typedef %x TypedefBody %x TypedefBodyContains @@ -711,8 +715,17 @@ private { {ID} { } } -{ +{ ^{BS}{TYPE_SPEC}/{SEPARATE} { + last_enum = 0; + if (YY_START == Enum) + { + argType = "@"; // enum marker + } + else + { + argType = QCString(yytext).simplifyWhiteSpace().lower(); + } current->bodyLine = yyLineNr + 1; current->endBodyLine = yyLineNr + lineCountPrepass; /* variable declaration starts */ @@ -721,7 +734,6 @@ private { addModule(NULL); yy_push_state(ModuleBody); //anon program } - argType = QCString(yytext).simplifyWhiteSpace().lower(); yy_push_state(AttributeList); } /* Dimitri: macro expansion should already be done during preprocessing not here! @@ -817,17 +829,30 @@ private { modifiers[current_root][name.lower()] |= currentModifiers; argName= name; - v_type= V_IGNORE; - if (!argType.isEmpty() && current_root->section!=Entry::FUNCTION_SEC) - { // new variable entry - v_type = V_VARIABLE; + v_type= V_IGNORE; + if (!argType.isEmpty() && current_root->section!=Entry::FUNCTION_SEC) + { // new variable entry + v_type = V_VARIABLE; current->section = Entry::VARIABLE_SEC; - current->name = argName; - current->type = argType; - current->fileName = yyFileName; - current->bodyLine = yyLineNr; // used for source reference + current->name = argName; + current->type = argType; + current->fileName = yyFileName; + current->bodyLine = yyLineNr; // used for source reference current->startLine = yyLineNr; - addCurrentEntry(1); + if (argType == "@") + { + current_root->addSubEntry(current); + current = new Entry(*current); + // add to the scope surrounding the enum (copy!) + current_root->parent()->addSubEntry(current); + last_enum = current; + current = new Entry ; + initEntry(); + } + else + { + addCurrentEntry(1); + } } else if (!argType.isEmpty()) { // declaration of parameter list: add type for corr. parameter @@ -963,19 +988,72 @@ private { { updateVariablePrepassComment(yyColNr-(int)yyleng, yyColNr); yy_pop_state(); // end initialization - if (v_type == V_VARIABLE) last_entry->initializer= initializer; + if (last_enum) + { + last_enum->initializer= initializer; + } + else + { + if (v_type == V_VARIABLE) last_entry->initializer= initializer; + } } else initializer+=", "; } "\n"|"!" { //| yy_pop_state(); // end initialization - if (v_type == V_VARIABLE) last_entry->initializer= initializer; + if (last_enum) + { + last_enum->initializer= initializer; + } + else + { + if (v_type == V_VARIABLE) last_entry->initializer= initializer; + } yyColNr -= 1; unput(*yytext); } . { initializer+=yytext; } +<*>{BS}"enum"{BS}","{BS}"bind"{BS}"("{BS}"c"{BS}")"{BS} { + if(YY_START == Start) + { + addModule(NULL); + yy_push_state(ModuleBody); //anon program + } + + yy_push_state(Enum); + current->protection = defaultProtection; + typeProtection = defaultProtection; + typeMode = true; + + current->spec |= Entry::Struct; + current->name.resize(0); + current->args.resize(0); + current->name.sprintf("@%d",anonCount++); + + current->section = Entry::ENUM_SEC; + current->fileName = yyFileName; + current->startLine = yyLineNr; + current->bodyLine = yyLineNr; + if ((current_root) && + (current_root->section == Entry::CLASS_SEC + || current_root->section == Entry::NAMESPACE_SEC)) + { + current->name = current_root->name + "::" + current->name; + } + + addCurrentEntry(1); + startScope(last_entry); + BEGIN( Enum ) ; + } +"end"{BS}"enum" { + last_entry->parent()->endBodyLine = yyLineNr; + if (!endScope(current_root)) + yyterminate(); + typeMode = false; + yy_pop_state(); + } /*------ fortran subroutine/function handling ------------------------------------------------------------*/ /* Start is initial condition */ @@ -1117,6 +1195,7 @@ private { { Entry *tmp_entry = current; current = last_entry; // temporarily switch to the previous entry + if (last_enum) current = last_enum; handleCommentBlock(docBlock,TRUE); current=tmp_entry; } @@ -1132,7 +1211,7 @@ private { docBlock.resize(0); } -"!>" { +"!>" { yy_push_state(YY_START); current->docLine = yyLineNr; docBlockJavaStyle = FALSE; -- cgit v0.12