Fixed ticket 184 (Tokenizer - Simplification: Split up variable declarations)

This commit is contained in:
Daniel Marjamäki 2009-03-18 20:32:05 +01:00
parent 2fb4c52728
commit f37dd4f143
3 changed files with 154 additions and 143 deletions

View File

@ -478,6 +478,8 @@ void Tokenizer::tokenize(std::istream &code, const char FileName[])
}
}
simplifyVarDecl();
// Handle templates..
for (Token *tok = _tokens; tok; tok = tok->next())
{
@ -1109,116 +1111,8 @@ void Tokenizer::simplifyTokenList()
}
}
// Split up variable declarations if possible..
for (Token *tok = _tokens; tok; tok = tok->next())
{
if (! Token::Match(tok, "[{};]"))
continue;
Token *type0 = tok->next();
if (!Token::Match(type0, "%type%"))
continue;
if (Token::Match(type0, "else|return"))
continue;
Token *tok2 = NULL;
unsigned int typelen = 0;
if (Token::Match(type0, "%type% %var% ,|="))
{
if (type0->next()->str() != "operator")
{
tok2 = type0->tokAt(2); // The ',' or '=' token
typelen = 1;
}
}
else if (Token::Match(type0, "%type% * %var% ,|="))
{
if (type0->next()->next()->str() != "operator")
{
tok2 = type0->tokAt(3); // The ',' token
typelen = 1;
}
}
else if (Token::Match(type0, "%type% %var% [ %num% ] ,"))
{
tok2 = type0->tokAt(5); // The ',' token
typelen = 1;
}
else if (Token::Match(type0, "%type% * %var% [ %num% ] ,"))
{
tok2 = type0->tokAt(6); // The ',' token
typelen = 1;
}
else if (Token::Match(type0, "struct %type% %var% ,|="))
{
tok2 = type0->tokAt(3);
typelen = 2;
}
else if (Token::Match(type0, "struct %type% * %var% ,|="))
{
tok2 = type0->tokAt(4);
typelen = 2;
}
if (tok2)
{
if (tok2->str() == ",")
{
tok2->str(";");
InsertTokens(tok2, type0, typelen);
}
else
{
Token *eq = tok2;
int parlevel = 0;
while (tok2)
{
if (strchr("{(", tok2->aaaa0()))
{
++parlevel;
}
else if (strchr("})", tok2->aaaa0()))
{
if (parlevel < 0)
break;
--parlevel;
}
else if (parlevel == 0 && strchr(";,", tok2->aaaa0()))
{
// "type var =" => "type var; var ="
Token *VarTok = type0->tokAt(typelen);
if (VarTok->aaaa0() == '*')
VarTok = VarTok->next();
InsertTokens(eq, VarTok, 2);
eq->str(";");
// "= x, " => "= x; type "
if (tok2->str() == ",")
{
tok2->str(";");
InsertTokens(tok2, type0, typelen);
}
break;
}
tok2 = tok2->next();
}
}
}
}
// Simplify variable declarations
simplifyVarDecl();
// In case variable declarations have been updated...
setVarId();
@ -1787,6 +1681,131 @@ static void incdec(std::string &value, const std::string &op)
}
bool Tokenizer::simplifyVarDecl()
{
// Split up variable declarations..
// "int a=4;" => "int a; a=4;"
bool ret = false;
for (Token *tok = _tokens; tok; tok = tok->next())
{
if (tok->previous() && !Token::Match(tok->previous(), "[{};)]"))
continue;
Token *type0 = tok;
if (!Token::Match(type0, "%type%"))
continue;
if (Token::Match(type0, "else|return"))
continue;
bool isconst = false;
Token *tok2 = type0;
unsigned int typelen = 1;
while (Token::Match(tok2, "%type% %type% *| %var%"))
{
if (tok2->str() == "const")
isconst = true;
tok2 = tok2->next();
++typelen;
}
// Don't split up const declaration..
if (isconst && Token::Match(tok2, "%type% %var% ="))
continue;
if (Token::Match(tok2, "%type% %var% ,|="))
{
if (tok2->next()->str() != "operator")
tok2 = tok2->tokAt(2); // The ',' or '=' token
else
tok2 = NULL;
}
else if (Token::Match(tok2, "%type% * %var% ,|="))
{
if (tok2->next()->next()->str() != "operator")
tok2 = tok2->tokAt(3); // The ',' token
else
tok2 = NULL;
}
else if (Token::Match(tok2, "%type% %var% [ %num% ] ,"))
{
tok2 = tok2->tokAt(5); // The ',' token
}
else if (Token::Match(tok2, "%type% * %var% [ %num% ] ,"))
{
tok2 = tok2->tokAt(6); // The ',' token
}
else
{
tok2 = NULL;
typelen = 0;
}
if (tok2)
{
ret = true;
if (tok2->str() == ",")
{
tok2->str(";");
InsertTokens(tok2, type0, typelen);
}
else
{
Token *eq = tok2;
int parlevel = 0;
while (tok2)
{
if (strchr("{(", tok2->aaaa0()))
{
++parlevel;
}
else if (strchr("})", tok2->aaaa0()))
{
if (parlevel < 0)
break;
--parlevel;
}
else if (parlevel == 0 && strchr(";,", tok2->aaaa0()))
{
// "type var =" => "type var; var ="
Token *VarTok = type0->tokAt(typelen);
if (VarTok->aaaa0() == '*')
VarTok = VarTok->next();
InsertTokens(eq, VarTok, 2);
eq->str(";");
// "= x, " => "= x; type "
if (tok2->str() == ",")
{
tok2->str(";");
InsertTokens(tok2, type0, typelen);
}
break;
}
tok2 = tok2->next();
}
}
}
}
return ret;
}
bool Tokenizer::simplifyKnownVariables()
{
bool ret = false;

View File

@ -89,6 +89,12 @@ public:
static const Token *FindClassFunction(const Token *tok, const char classname[], const char funcname[], int &indentlevel);
/**
* Simplify variable declarations
*/
bool simplifyVarDecl();
protected:
/** Add braces to an if-block

View File

@ -125,8 +125,8 @@ private:
TEST_CASE(findClassFunction1);
// Ticket 184 TEST_CASE(vardecl1);
// Ticket 184 TEST_CASE(vardecl2);
TEST_CASE(vardecl1);
TEST_CASE(vardecl2);
}
@ -409,7 +409,7 @@ private:
std::ostringstream ostr;
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next())
ostr << " " << tok->str();
ASSERT_EQUALS(std::string(" char * foo ( ) { char * str = malloc ( 10 ) ; if ( somecondition ) { for ( ; ; ) { } } return str ; }"), ostr.str());
ASSERT_EQUALS(std::string(" char * foo ( ) { char * str ; str = malloc ( 10 ) ; if ( somecondition ) { for ( ; ; ) { } } return str ; }"), ostr.str());
}
void ifAddBraces5()
@ -457,7 +457,7 @@ private:
std::ostringstream ostr;
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next())
ostr << " " << tok->str();
ASSERT_EQUALS(std::string(" void f ( ) { int a = 10 ; if ( 10 ) ; }"), ostr.str());
ASSERT_EQUALS(std::string(" void f ( ) { int a ; a = 10 ; if ( 10 ) ; }"), ostr.str());
}
void simplifyKnownVariables2()
@ -480,7 +480,7 @@ private:
std::ostringstream ostr;
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next())
ostr << " " << tok->str();
ASSERT_EQUALS(std::string(" void f ( ) { int a = 10 ; a = g ( ) ; if ( a ) ; }"), ostr.str());
ASSERT_EQUALS(std::string(" void f ( ) { int a ; a = 10 ; a = g ( ) ; if ( a ) ; }"), ostr.str());
}
void simplifyKnownVariables3()
@ -506,7 +506,7 @@ private:
std::ostringstream ostr;
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next())
ostr << " " << tok->str();
ASSERT_EQUALS(std::string(" void f ( ) { int a = 4 ; while ( true ) { break ; a = 10 ; } if ( a ) ; }"), ostr.str());
ASSERT_EQUALS(std::string(" void f ( ) { int a ; a = 4 ; while ( true ) { break ; a = 10 ; } if ( a ) ; }"), ostr.str());
}
void simplifyKnownVariables4()
@ -528,7 +528,7 @@ private:
std::ostringstream ostr;
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next())
ostr << " " << tok->str();
ASSERT_EQUALS(std::string(" void f ( ) { int a = 4 ; if ( g ( a ) ) ; }"), ostr.str());
ASSERT_EQUALS(std::string(" void f ( ) { int a ; a = 4 ; if ( g ( a ) ) ; }"), ostr.str());
}
void simplifyKnownVariables5()
@ -550,7 +550,7 @@ private:
std::ostringstream ostr;
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next())
ostr << " " << tok->str();
ASSERT_EQUALS(std::string(" void f ( ) { int a = 4 ; if ( a = 5 ) ; }"), ostr.str());
ASSERT_EQUALS(std::string(" void f ( ) { int a ; a = 4 ; if ( a = 5 ) ; }"), ostr.str());
}
void simplifyKnownVariables6()
@ -573,7 +573,7 @@ private:
std::ostringstream ostr;
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next())
ostr << " " << tok->str();
ASSERT_EQUALS(std::string(" void f ( ) { char str [ 2 ] ; int a = 4 ; str [ 4 ] = 0 ; }"), ostr.str());
ASSERT_EQUALS(std::string(" void f ( ) { char str [ 2 ] ; int a ; a = 4 ; str [ 4 ] = 0 ; }"), ostr.str());
}
void simplifyKnownVariables7()
@ -595,7 +595,7 @@ private:
std::ostringstream ostr;
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next())
ostr << " " << tok->str();
ASSERT_EQUALS(std::string(" void foo ( ) { int i = 24 ; abc [ 22 ] = 1 ; abc [ 24 ] = 2 ; }"), ostr.str());
ASSERT_EQUALS(std::string(" void foo ( ) { int i ; i = 24 ; abc [ 22 ] = 1 ; abc [ 24 ] = 2 ; }"), ostr.str());
}
void simplifyKnownVariables8()
@ -617,7 +617,7 @@ private:
std::ostringstream ostr;
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next())
ostr << " " << tok->str();
ASSERT_EQUALS(std::string(" void foo ( ) { int i = 23 ; ; abc [ 23 ] = 0 ; }"), ostr.str());
ASSERT_EQUALS(std::string(" void foo ( ) { int i ; i = 23 ; ; abc [ 23 ] = 0 ; }"), ostr.str());
}
@ -779,10 +779,10 @@ private:
// result..
const std::string actual(tokenizer.tokens()->stringifyList(true));
const std::string expected("\n\n##file 0\n"
"1: static int i@1 = 1 ;\n"
"1: static int i@1 ; i@1 = 1 ;\n"
"2: void f ( )\n"
"3: {\n"
"4: int i@2 = 2 ;\n"
"4: int i@2 ; i@2 = 2 ;\n"
"5: for ( int i@3 = 0 ; i@3 < 10 ; ++ i@3 )\n"
"6: i@3 = 3 ;\n"
"7: i@2 = 4 ;\n"
@ -1220,7 +1220,7 @@ private:
std::ostringstream ostr;
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next())
ostr << " " << tok->str();
ASSERT_EQUALS(std::string(" void f ( ) { double a = 4.2 ; float b = 4.2f ; double c = 4.2e+10 ; double d = 4.2e-10 ; int e = 4 + 2 ; }"), ostr.str());
ASSERT_EQUALS(std::string(" void f ( ) { double a ; a = 4.2 ; float b ; b = 4.2f ; double c ; c = 4.2e+10 ; double d ; d = 4.2e-10 ; int e ; e = 4 + 2 ; }"), ostr.str());
}
void tokenize_strings()
@ -1244,7 +1244,7 @@ private:
std::ostringstream ostr;
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next())
ostr << " " << tok->str();
ASSERT_EQUALS(std::string(" void f ( ) { const char * a = { \"hello more world\" } ; }"), ostr.str());
ASSERT_EQUALS(std::string(" void f ( ) { const char * a ; a = { \"hello more world\" } ; }"), ostr.str());
}
void simplify_constants()
@ -1331,32 +1331,18 @@ private:
{
const char code[] = "unsigned int a, b;";
// tokenize..
Tokenizer tokenizer;
std::istringstream istr(code);
tokenizer.tokenize(istr, "test.cpp");
const std::string actual(tokenizeAndStringify(code));
std::ostringstream ostr;
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next())
ostr << " " << tok->str();
ASSERT_EQUALS(" unsigned int a ; unsigned int b ;", ostr.str());
ASSERT_EQUALS("unsigned int a ; unsigned int b ;", actual);
}
void vardecl2()
{
const char code[] = "void foo(a,b) unsigned int a, b; { }";
// tokenize..
Tokenizer tokenizer;
std::istringstream istr(code);
tokenizer.tokenize(istr, "test.cpp");
const std::string actual(tokenizeAndStringify(code));
std::ostringstream ostr;
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next())
ostr << " " << tok->str();
ASSERT_EQUALS(" void foo ( a , b ) unsigned int a ; unsigned int b ; { }", ostr.str());
ASSERT_EQUALS("void foo ( a , b ) unsigned int a ; unsigned int b ; { }", actual);
}
};