From 7aa485a94d8e21cbda6a48ba141ae0b5fcb591a0 Mon Sep 17 00:00:00 2001 From: olegator Date: Fri, 18 Mar 2011 12:27:58 +0000 Subject: Special !< comments in case of line continuations. Track column numbers and use it with stored information of !< comment after module variable and subprogram parameter. Create procedure for new line, where clean prepass comments. --- src/fortranscanner.l | 147 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 106 insertions(+), 41 deletions(-) diff --git a/src/fortranscanner.l b/src/fortranscanner.l index df0b700..4983738 100644 --- a/src/fortranscanner.l +++ b/src/fortranscanner.l @@ -34,6 +34,8 @@ * with separate rule?: It seems it is often necessary, because we may parse something like * "functionA" or "MyInterface". So constructs like `(^|[ \t])interface({BS_}{ID})?/[ \t\n]' * are desired. + * + * - Must track yyLineNr when using REJECT, unput() or similar commands. */ %{ @@ -139,6 +141,7 @@ int include_stack_ptr = 0; static QFile inputFile; static QCString yyFileName; static int yyLineNr = 1 ; +static int yyColNr = 0 ; static Entry* current_root = 0 ; static Entry* global_root = 0 ; static Entry* file_root = 0 ; @@ -184,7 +187,7 @@ static void addCurrentEntry(); static void addModule(const char *name, bool isModule=FALSE); static void addSubprogram(const char *text); static void addInterface(QCString name, InterfaceType type); -static Argument *addFortranParameter(const QCString &type,const QCString &name, const QCString docs); +static Argument *getParameter(const QCString &name); static void scanner_abort(); static void startScope(Entry *scope); @@ -199,10 +202,14 @@ static void pushBuffer(QCString &buffer); static void popBuffer(); //static void extractPrefix(QCString& text); static QCString extractFromParens(const QCString name); +static CommentInPrepass* locatePrepassComment(int from, int to); +static void updateVariablePrepassComment(int from, int to); +static void newLine(); //----------------------------------------------------------------------------- #undef YY_INPUT #define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size); +#define YY_USER_ACTION yyColNr+=yyleng; //----------------------------------------------------------------------------- %} @@ -301,9 +308,12 @@ PREFIX (RECURSIVE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,2}(RECURSIVE|PURE|ELEMENTA // Only take input after initial ampersand inputStringPrepass+=(const char*)(yytext+(indexStart+1)); + //printf("BUFFER:%s\n", (const char*)inputStringPrepass); pushBuffer(inputStringPrepass); + yyColNr = 0; yy_pop_state(); } else { // simple line + yyColNr = 0; REJECT; } @@ -337,7 +347,7 @@ PREFIX (RECURSIVE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,2}(RECURSIVE|PURE|ELEMENTA initializer+=yytext; } \"|\' { // string ends with next quote without previous backspace - if (yytext[0]!=stringStartSymbol) REJECT; // single vs double quote + if (yytext[0]!=stringStartSymbol) { yyColNr -= yyleng; REJECT; } // single vs double quote if (yy_top_state() == Initialization || yy_top_state() == ArrayInitializer) initializer+=yytext; @@ -348,7 +358,7 @@ PREFIX (RECURSIVE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,2}(RECURSIVE|PURE|ELEMENTA initializer+=yytext; } <*>\"|\' { /* string starts */ - if (YY_START == StrIgnore) REJECT; // ignore in simple comments + if (YY_START == StrIgnore) { yyColNr -= yyleng; REJECT; }; // ignore in simple comments yy_push_state(YY_START); if (yy_top_state() == Initialization || yy_top_state() == ArrayInitializer) @@ -359,7 +369,7 @@ PREFIX (RECURSIVE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,2}(RECURSIVE|PURE|ELEMENTA /*------ ignore simple comment (not documentation comments) */ -<*>"!"/[^<>\n] { if (YY_START == String) REJECT; // "!" is ignored in strings +<*>"!"/[^<>\n] { if (YY_START == String) { yyColNr -= yyleng; REJECT; } // "!" is ignored in strings // skip comment line (without docu comments "!>" "!<" ) /* ignore further "!" and ignore comments in Strings */ if ((YY_START != StrIgnore) && (YY_START != String)) @@ -411,6 +421,7 @@ PREFIX (RECURSIVE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,2}(RECURSIVE|PURE|ELEMENTA current->lang = SrcLangExt_F90; } "\n" { + yyColNr -= 1; unput(*yytext); yy_pop_state(); } @@ -463,7 +474,8 @@ PREFIX (RECURSIVE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,2}(RECURSIVE|PURE|ELEMENTA moduleProcedures.append(current); addCurrentEntry(); } -"\n" { unput(*yytext); +"\n" { yyColNr -= 1; + unput(*yytext); yy_pop_state(); } . {} @@ -596,7 +608,7 @@ private { } "\n" { currentModifiers = SymbolModifiers(); - yyLineNr++; yyLineNr+=lineCountPrepass; lineCountPrepass=0; + newLine(); docBlock.resize(0); } } @@ -655,6 +667,7 @@ private { } else { + yyColNr -= yyleng; REJECT; } } @@ -679,12 +692,14 @@ private { QChar chr = yytext[yyleng-1]; if (chr.isLetter() || chr.isDigit() || (chr == '_')) { + yyColNr -= yyleng; REJECT; } else { QCString tmp = yytext; tmp = tmp.left(tmp.length() - 1); + yyColNr -= 1; unput(yytext[yyleng-1]); currentModifiers |= (tmp); } @@ -694,12 +709,13 @@ private { } . { /* unknown attribute, consider variable name */ //cout<<"start variables, unput "<<*yytext<{BS} {} +{BS} { } {ID} { /* parse variable declaration */ //cout << "5=========> got variable: " << argType << "::" << yytext << endl; /* work around for bug in QCString.replace (QCString works) */ @@ -721,8 +737,16 @@ private { } else if (!argType.isEmpty()) { // deklaration of parameter list: add type for corr. parameter - parameter= addFortranParameter(argType,argName,docBlock); - if (parameter) v_type= V_PARAMETER; + parameter = getParameter(argName); + if (parameter) { + v_type= V_PARAMETER; + if (!argType.isNull()) + parameter->type=argType.stripWhiteSpace(); + if (!docBlock.isNull()) { + parameter->docs += "\n"; + parameter->docs += docBlock; + } + } // save, it may be function return type modifiers[current_root][name.lower()].type = argType; // any accumulated doc for argument should be emptied, @@ -738,7 +762,10 @@ private { attr += yytext; modifiers[current_root][name] |= attr; } -{COMMA} {} +{COMMA} { //printf("COMMA: %d<=..<=%d\n", yyColNr-yyleng, yyColNr); + // locate !< comment + updateVariablePrepassComment(yyColNr-yyleng, yyColNr); + } {BS}"=" { yy_push_state(YY_START); initializer=""; initializerScope = initializerArrayScope = 0; @@ -746,7 +773,7 @@ private { } "\n" { currentModifiers = SymbolModifiers(); yy_pop_state(); // end variable deklaration list - yyLineNr++; yyLineNr+=lineCountPrepass; lineCountPrepass=0; + newLine(); docBlock.resize(0); } ";".*"\n" { currentModifiers = SymbolModifiers(); @@ -777,6 +804,7 @@ private { } {COMMA} { if (initializerScope == 0) { + updateVariablePrepassComment(yyColNr-yyleng, yyColNr); yy_pop_state(); // end initialization if (v_type == V_VARIABLE) last_entry->initializer= initializer; } @@ -786,6 +814,7 @@ private { "\n"|"!" { //| yy_pop_state(); // end initialization if (v_type == V_VARIABLE) last_entry->initializer= initializer; + yyColNr -= 1; unput(*yytext); } . { initializer+=yytext; } @@ -837,26 +866,36 @@ private { BEGIN(Parameterlist); } -{ARGS} { +"(" { current->args = "("; } +")" { + current->args += ")"; + current->args = removeRedundantWhiteSpace(current->args); + addCurrentEntry(); + startScope(last_entry); + BEGIN(SubprogBody); + } +{COMMA}|{BS} { current->args += yytext; + CommentInPrepass *c = locatePrepassComment(yyColNr-yyleng, yyColNr); + if (c!=NULL) { + if(current->argList->count()>0) { + current->argList->at(current->argList->count()-1)->docs = c->str; + } + } + } +{ID} { //current->type not yet available - QCString arglist= yytext; - //cout << "3=========> got parameterlist " << yytext << endl; - //yyLineNr+= arglist.contains('\n'); - //static QRegExp re("&[^\n]*\n"); - //arglist = arglist.replace(re,""); - //cout << "3=========> got parameterlist " << arglist << endl; - current->args = arglist; - current->args = removeRedundantWhiteSpace(current->args); - stringToArgumentList(current->args, current->argList); - addCurrentEntry(); - - startScope(last_entry); - BEGIN(SubprogBody); + QCString param = yytext; + // std::cout << "3=========> got parameter " << param << std::endl; + current->args += param; + Argument *arg = new Argument; + arg->name = param; + arg->type = ""; + current->argList->append(arg); } {NOARGS} { - yyLineNr++; yyLineNr+=lineCountPrepass; lineCountPrepass=0; + newLine(); //printf("3=========> without parameterlist \n"); - stringToArgumentList("", current->argList); + //current->argList = ; addCurrentEntry(); startScope(last_entry); BEGIN(SubprogBody); @@ -914,10 +953,11 @@ private { } "\n"{BS}"!"(">"|"!"+) { // comment block (next line is also comment line) docBlock+="\n"; // \n is necessary for lists - yyLineNr++; yyLineNr+=lineCountPrepass; lineCountPrepass=0; + newLine(); } "\n" { // comment block ends at the end of this line //cout <<"3=========> comment block : "<< docBlock << endl; + yyColNr -= 1; unput(*yytext); handleCommentBlock(docBlock,TRUE); yy_pop_state(); @@ -926,7 +966,7 @@ private { /*------------------------------------------------------------------------------------------------*/ <*>"\n" { - yyLineNr++; yyLineNr+=lineCountPrepass; lineCountPrepass=0; + newLine(); //if (debugStr.stripWhiteSpace().length() > 0) cout << "ignored text: " << debugStr << " state: " <column; + //printf("Candidate %d\n", c); + if (c>=from && c<=to) { + // comment for previous variable or parameter + return comments.at(i); + } + } + return NULL; +} + +static void updateVariablePrepassComment(int from, int to) { + CommentInPrepass *c = locatePrepassComment(from, to); + if (c!=NULL && v_type == V_VARIABLE) { + last_entry->brief = c->str; + } else if (c!=NULL && v_type == V_PARAMETER) { + Argument *parameter = getParameter(argName); + if (parameter) parameter->docs = c->str; + } +} + static int getAmpersandAtTheStart(const char *buf, int length) { for(int i=0; iargList==0) return 0; ArgumentListIterator ali(*current_root->argList); Argument *a; for (ali.toFirst();(a=ali.current());++ali) { - if (a->type.lower()==name.lower()) + if (a->name.lower()==name.lower()) { ret=a; -//cout << "addParameter found: " << type << " , " << name << endl; - a->type=type.stripWhiteSpace(); - a->name=name.stripWhiteSpace(); - if (!docs.isNull()) - a->docs = docs; + //printf("parameter found: %s\n",(const char*)name); break; } } // for -- cgit v0.12