Commit d5f047ac authored by Dimitri van Heesch's avatar Dimitri van Heesch

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.
parent 712ab49d
...@@ -34,6 +34,8 @@ ...@@ -34,6 +34,8 @@
* with separate rule?: It seems it is often necessary, because we may parse something like * 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]' * "functionA" or "MyInterface". So constructs like `(^|[ \t])interface({BS_}{ID})?/[ \t\n]'
* are desired. * are desired.
*
* - Must track yyLineNr when using REJECT, unput() or similar commands.
*/ */
%{ %{
...@@ -139,6 +141,7 @@ int include_stack_ptr = 0; ...@@ -139,6 +141,7 @@ int include_stack_ptr = 0;
static QFile inputFile; static QFile inputFile;
static QCString yyFileName; static QCString yyFileName;
static int yyLineNr = 1 ; static int yyLineNr = 1 ;
static int yyColNr = 0 ;
static Entry* current_root = 0 ; static Entry* current_root = 0 ;
static Entry* global_root = 0 ; static Entry* global_root = 0 ;
static Entry* file_root = 0 ; static Entry* file_root = 0 ;
...@@ -184,7 +187,7 @@ static void addCurrentEntry(); ...@@ -184,7 +187,7 @@ static void addCurrentEntry();
static void addModule(const char *name, bool isModule=FALSE); static void addModule(const char *name, bool isModule=FALSE);
static void addSubprogram(const char *text); static void addSubprogram(const char *text);
static void addInterface(QCString name, InterfaceType type); 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 scanner_abort();
static void startScope(Entry *scope); static void startScope(Entry *scope);
...@@ -199,10 +202,14 @@ static void pushBuffer(QCString &buffer); ...@@ -199,10 +202,14 @@ static void pushBuffer(QCString &buffer);
static void popBuffer(); static void popBuffer();
//static void extractPrefix(QCString& text); //static void extractPrefix(QCString& text);
static QCString extractFromParens(const QCString name); 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 #undef YY_INPUT
#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size); #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 ...@@ -301,9 +308,12 @@ PREFIX (RECURSIVE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,2}(RECURSIVE|PURE|ELEMENTA
// Only take input after initial ampersand // Only take input after initial ampersand
inputStringPrepass+=(const char*)(yytext+(indexStart+1)); inputStringPrepass+=(const char*)(yytext+(indexStart+1));
//printf("BUFFER:%s\n", (const char*)inputStringPrepass);
pushBuffer(inputStringPrepass); pushBuffer(inputStringPrepass);
yyColNr = 0;
yy_pop_state(); yy_pop_state();
} else { // simple line } else { // simple line
yyColNr = 0;
REJECT; REJECT;
} }
...@@ -337,7 +347,7 @@ PREFIX (RECURSIVE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,2}(RECURSIVE|PURE|ELEMENTA ...@@ -337,7 +347,7 @@ PREFIX (RECURSIVE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,2}(RECURSIVE|PURE|ELEMENTA
initializer+=yytext; initializer+=yytext;
} }
<String>\"|\' { // string ends with next quote without previous backspace <String>\"|\' { // 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 if (yy_top_state() == Initialization
|| yy_top_state() == ArrayInitializer) || yy_top_state() == ArrayInitializer)
initializer+=yytext; initializer+=yytext;
...@@ -348,7 +358,7 @@ PREFIX (RECURSIVE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,2}(RECURSIVE|PURE|ELEMENTA ...@@ -348,7 +358,7 @@ PREFIX (RECURSIVE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,2}(RECURSIVE|PURE|ELEMENTA
initializer+=yytext; initializer+=yytext;
} }
<*>\"|\' { /* string starts */ <*>\"|\' { /* 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); yy_push_state(YY_START);
if (yy_top_state() == Initialization if (yy_top_state() == Initialization
|| yy_top_state() == ArrayInitializer) || yy_top_state() == ArrayInitializer)
...@@ -359,7 +369,7 @@ PREFIX (RECURSIVE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,2}(RECURSIVE|PURE|ELEMENTA ...@@ -359,7 +369,7 @@ PREFIX (RECURSIVE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,2}(RECURSIVE|PURE|ELEMENTA
/*------ ignore simple comment (not documentation comments) */ /*------ 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 "!>" "!<" ) // skip comment line (without docu comments "!>" "!<" )
/* ignore further "!" and ignore comments in Strings */ /* ignore further "!" and ignore comments in Strings */
if ((YY_START != StrIgnore) && (YY_START != String)) if ((YY_START != StrIgnore) && (YY_START != String))
...@@ -411,6 +421,7 @@ PREFIX (RECURSIVE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,2}(RECURSIVE|PURE|ELEMENTA ...@@ -411,6 +421,7 @@ PREFIX (RECURSIVE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,2}(RECURSIVE|PURE|ELEMENTA
current->lang = SrcLangExt_F90; current->lang = SrcLangExt_F90;
} }
<Use,UseOnly>"\n" { <Use,UseOnly>"\n" {
yyColNr -= 1;
unput(*yytext); unput(*yytext);
yy_pop_state(); yy_pop_state();
} }
...@@ -463,7 +474,8 @@ PREFIX (RECURSIVE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,2}(RECURSIVE|PURE|ELEMENTA ...@@ -463,7 +474,8 @@ PREFIX (RECURSIVE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,2}(RECURSIVE|PURE|ELEMENTA
moduleProcedures.append(current); moduleProcedures.append(current);
addCurrentEntry(); addCurrentEntry();
} }
<ModuleProcedure>"\n" { unput(*yytext); <ModuleProcedure>"\n" { yyColNr -= 1;
unput(*yytext);
yy_pop_state(); yy_pop_state();
} }
<InterfaceBody>. {} <InterfaceBody>. {}
...@@ -596,7 +608,7 @@ private { ...@@ -596,7 +608,7 @@ private {
} }
"\n" { "\n" {
currentModifiers = SymbolModifiers(); currentModifiers = SymbolModifiers();
yyLineNr++; yyLineNr+=lineCountPrepass; lineCountPrepass=0; newLine();
docBlock.resize(0); docBlock.resize(0);
} }
} }
...@@ -655,6 +667,7 @@ private { ...@@ -655,6 +667,7 @@ private {
} }
else else
{ {
yyColNr -= yyleng;
REJECT; REJECT;
} }
} }
...@@ -679,12 +692,14 @@ private { ...@@ -679,12 +692,14 @@ private {
QChar chr = yytext[yyleng-1]; QChar chr = yytext[yyleng-1];
if (chr.isLetter() || chr.isDigit() || (chr == '_')) if (chr.isLetter() || chr.isDigit() || (chr == '_'))
{ {
yyColNr -= yyleng;
REJECT; REJECT;
} }
else else
{ {
QCString tmp = yytext; QCString tmp = yytext;
tmp = tmp.left(tmp.length() - 1); tmp = tmp.left(tmp.length() - 1);
yyColNr -= 1;
unput(yytext[yyleng-1]); unput(yytext[yyleng-1]);
currentModifiers |= (tmp); currentModifiers |= (tmp);
} }
...@@ -694,12 +709,13 @@ private { ...@@ -694,12 +709,13 @@ private {
} }
. { /* unknown attribute, consider variable name */ . { /* unknown attribute, consider variable name */
//cout<<"start variables, unput "<<*yytext<<endl; //cout<<"start variables, unput "<<*yytext<<endl;
yyColNr -= 1;
unput(*yytext); unput(*yytext);
BEGIN( Variable ); BEGIN( Variable );
} }
} }
<Variable>{BS} {} <Variable>{BS} { }
<Variable>{ID} { /* parse variable declaration */ <Variable>{ID} { /* parse variable declaration */
//cout << "5=========> got variable: " << argType << "::" << yytext << endl; //cout << "5=========> got variable: " << argType << "::" << yytext << endl;
/* work around for bug in QCString.replace (QCString works) */ /* work around for bug in QCString.replace (QCString works) */
...@@ -721,8 +737,16 @@ private { ...@@ -721,8 +737,16 @@ private {
} }
else if (!argType.isEmpty()) else if (!argType.isEmpty())
{ // deklaration of parameter list: add type for corr. parameter { // deklaration of parameter list: add type for corr. parameter
parameter= addFortranParameter(argType,argName,docBlock); parameter = getParameter(argName);
if (parameter) v_type= V_PARAMETER; 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 // save, it may be function return type
modifiers[current_root][name.lower()].type = argType; modifiers[current_root][name.lower()].type = argType;
// any accumulated doc for argument should be emptied, // any accumulated doc for argument should be emptied,
...@@ -738,7 +762,10 @@ private { ...@@ -738,7 +762,10 @@ private {
attr += yytext; attr += yytext;
modifiers[current_root][name] |= attr; modifiers[current_root][name] |= attr;
} }
<Variable>{COMMA} {} <Variable>{COMMA} { //printf("COMMA: %d<=..<=%d\n", yyColNr-yyleng, yyColNr);
// locate !< comment
updateVariablePrepassComment(yyColNr-yyleng, yyColNr);
}
<Variable>{BS}"=" { yy_push_state(YY_START); <Variable>{BS}"=" { yy_push_state(YY_START);
initializer=""; initializer="";
initializerScope = initializerArrayScope = 0; initializerScope = initializerArrayScope = 0;
...@@ -746,7 +773,7 @@ private { ...@@ -746,7 +773,7 @@ private {
} }
<Variable>"\n" { currentModifiers = SymbolModifiers(); <Variable>"\n" { currentModifiers = SymbolModifiers();
yy_pop_state(); // end variable deklaration list yy_pop_state(); // end variable deklaration list
yyLineNr++; yyLineNr+=lineCountPrepass; lineCountPrepass=0; newLine();
docBlock.resize(0); docBlock.resize(0);
} }
<Variable>";".*"\n" { currentModifiers = SymbolModifiers(); <Variable>";".*"\n" { currentModifiers = SymbolModifiers();
...@@ -777,6 +804,7 @@ private { ...@@ -777,6 +804,7 @@ private {
} }
<Initialization>{COMMA} { if (initializerScope == 0) <Initialization>{COMMA} { if (initializerScope == 0)
{ {
updateVariablePrepassComment(yyColNr-yyleng, yyColNr);
yy_pop_state(); // end initialization yy_pop_state(); // end initialization
if (v_type == V_VARIABLE) last_entry->initializer= initializer; if (v_type == V_VARIABLE) last_entry->initializer= initializer;
} }
...@@ -786,6 +814,7 @@ private { ...@@ -786,6 +814,7 @@ private {
<Initialization>"\n"|"!" { //| <Initialization>"\n"|"!" { //|
yy_pop_state(); // end initialization yy_pop_state(); // end initialization
if (v_type == V_VARIABLE) last_entry->initializer= initializer; if (v_type == V_VARIABLE) last_entry->initializer= initializer;
yyColNr -= 1;
unput(*yytext); unput(*yytext);
} }
<Initialization>. { initializer+=yytext; } <Initialization>. { initializer+=yytext; }
...@@ -837,26 +866,36 @@ private { ...@@ -837,26 +866,36 @@ private {
BEGIN(Parameterlist); BEGIN(Parameterlist);
} }
<Parameterlist>{ARGS} { <Parameterlist>"(" { current->args = "("; }
<Parameterlist>")" {
current->args += ")";
current->args = removeRedundantWhiteSpace(current->args);
addCurrentEntry();
startScope(last_entry);
BEGIN(SubprogBody);
}
<Parameterlist>{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;
}
}
}
<Parameterlist>{ID} {
//current->type not yet available //current->type not yet available
QCString arglist= yytext; QCString param = yytext;
//cout << "3=========> got parameterlist " << yytext << endl; // std::cout << "3=========> got parameter " << param << std::endl;
//yyLineNr+= arglist.contains('\n'); current->args += param;
//static QRegExp re("&[^\n]*\n"); Argument *arg = new Argument;
//arglist = arglist.replace(re,""); arg->name = param;
//cout << "3=========> got parameterlist " << arglist << endl; arg->type = "";
current->args = arglist; current->argList->append(arg);
current->args = removeRedundantWhiteSpace(current->args);
stringToArgumentList(current->args, current->argList);
addCurrentEntry();
startScope(last_entry);
BEGIN(SubprogBody);
} }
<Parameterlist>{NOARGS} { <Parameterlist>{NOARGS} {
yyLineNr++; yyLineNr+=lineCountPrepass; lineCountPrepass=0; newLine();
//printf("3=========> without parameterlist \n"); //printf("3=========> without parameterlist \n");
stringToArgumentList("", current->argList); //current->argList = ;
addCurrentEntry(); addCurrentEntry();
startScope(last_entry); startScope(last_entry);
BEGIN(SubprogBody); BEGIN(SubprogBody);
...@@ -914,10 +953,11 @@ private { ...@@ -914,10 +953,11 @@ private {
} }
<DocBlock>"\n"{BS}"!"(">"|"!"+) { // comment block (next line is also comment line) <DocBlock>"\n"{BS}"!"(">"|"!"+) { // comment block (next line is also comment line)
docBlock+="\n"; // \n is necessary for lists docBlock+="\n"; // \n is necessary for lists
yyLineNr++; yyLineNr+=lineCountPrepass; lineCountPrepass=0; newLine();
} }
<DocBlock>"\n" { // comment block ends at the end of this line <DocBlock>"\n" { // comment block ends at the end of this line
//cout <<"3=========> comment block : "<< docBlock << endl; //cout <<"3=========> comment block : "<< docBlock << endl;
yyColNr -= 1;
unput(*yytext); unput(*yytext);
handleCommentBlock(docBlock,TRUE); handleCommentBlock(docBlock,TRUE);
yy_pop_state(); yy_pop_state();
...@@ -926,7 +966,7 @@ private { ...@@ -926,7 +966,7 @@ private {
/*------------------------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------------------------*/
<*>"\n" { <*>"\n" {
yyLineNr++; yyLineNr+=lineCountPrepass; lineCountPrepass=0; newLine();
//if (debugStr.stripWhiteSpace().length() > 0) cout << "ignored text: " << debugStr << " state: " <<YY_START << endl; //if (debugStr.stripWhiteSpace().length() > 0) cout << "ignored text: " << debugStr << " state: " <<YY_START << endl;
debugStr=""; debugStr="";
} }
...@@ -979,6 +1019,36 @@ static void extractPrefix(QCString &text) ...@@ -979,6 +1019,36 @@ static void extractPrefix(QCString &text)
} }
#endif #endif
static void newLine() {
yyLineNr++;
yyLineNr+=lineCountPrepass;
lineCountPrepass=0;
comments.clear();
}
static CommentInPrepass* locatePrepassComment(int from, int to) {
//printf("Locate %d-%d\n", from, to);
for(uint i=0; i<comments.count(); i++) { // todo: optimize
int c = comments.at(i)->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) static int getAmpersandAtTheStart(const char *buf, int length)
{ {
for(int i=0; i<length; i++) { for(int i=0; i<length; i++) {
...@@ -1065,9 +1135,8 @@ void truncatePrepass(int index) ...@@ -1065,9 +1135,8 @@ void truncatePrepass(int index)
{ {
int length = inputStringPrepass.length(); int length = inputStringPrepass.length();
for (int i=index+1; i<length; i++) { for (int i=index+1; i<length; i++) {
if (inputStringPrepass[i]=='!') { // save comment if (inputStringPrepass[i]=='!' && i<length-1 && inputStringPrepass[i+1]=='<') { // save comment
//printf("-----SAVE----- %d:%s", i, (const char*)inputStringPrepass.right(length-i)); struct CommentInPrepass *c=new CommentInPrepass(index, inputStringPrepass.right(length-i-2));
struct CommentInPrepass *c=new CommentInPrepass(index, inputStringPrepass.right(length-i));
comments.append(c); comments.append(c);
} }
} }
...@@ -1776,25 +1845,21 @@ static void addInterface(QCString name, InterfaceType type) ...@@ -1776,25 +1845,21 @@ static void addInterface(QCString name, InterfaceType type)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/*! Update the argument \a name with additional \a type info. /*! Get the argument \a name.
*/ */
static Argument *addFortranParameter(const QCString &type,const QCString &name, const QCString docs) static Argument* getParameter(const QCString &name)
{ {
//cout<<"addFortranParameter(): "<<name<<" DOCS:"<<(docs.isNull()?QCString("null"):docs)<<endl; // std::cout<<"addFortranParameter(): "<<name<<" DOCS:"<<(docs.isNull()?QCString("null"):docs)<<std::endl;
Argument *ret = 0; Argument *ret = 0;
if (current_root->argList==0) return 0; if (current_root->argList==0) return 0;
ArgumentListIterator ali(*current_root->argList); ArgumentListIterator ali(*current_root->argList);
Argument *a; Argument *a;
for (ali.toFirst();(a=ali.current());++ali) for (ali.toFirst();(a=ali.current());++ali)
{ {
if (a->type.lower()==name.lower()) if (a->name.lower()==name.lower())
{ {
ret=a; ret=a;
//cout << "addParameter found: " << type << " , " << name << endl; //printf("parameter found: %s\n",(const char*)name);
a->type=type.stripWhiteSpace();
a->name=name.stripWhiteSpace();
if (!docs.isNull())
a->docs = docs;
break; break;
} }
} // for } // for
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment