diff --git a/testtokenize.cpp b/testtokenize.cpp index 912555cc9..dfa9f333b 100644 --- a/testtokenize.cpp +++ b/testtokenize.cpp @@ -50,7 +50,9 @@ private: TEST_CASE( multi_compare ); - TEST_CASE( match1 ); + TEST_CASE( match1 ); + + TEST_CASE( match2 ); TEST_CASE( varid1 ); } @@ -263,6 +265,68 @@ private: } } + void match2() + { + { + const std::string code(""); + + // tokenize.. + Tokenizer tokenizer; + std::istringstream istr(code); + tokenizer.tokenize(istr, "test.cpp"); + + // Match.. + ASSERT_EQUALS( true, TOKEN::Match(tokenizer.tokens(), "!!else") ); + } + + { + const std::string code("if ;"); + + // tokenize.. + Tokenizer tokenizer; + std::istringstream istr(code); + tokenizer.tokenize(istr, "test.cpp"); + + // Match.. + ASSERT_EQUALS( true, TOKEN::Match(tokenizer.tokens(), "if ; !!else") ); + } + + { + const std::string code("if ; something"); + + // tokenize.. + Tokenizer tokenizer; + std::istringstream istr(code); + tokenizer.tokenize(istr, "test.cpp"); + + // Match.. + ASSERT_EQUALS( true, TOKEN::Match(tokenizer.tokens(), "if ; !!else") ); + } + + { + const std::string code("else"); + + // tokenize.. + Tokenizer tokenizer; + std::istringstream istr(code); + tokenizer.tokenize(istr, "test.cpp"); + + // Match.. + ASSERT_EQUALS( false, TOKEN::Match(tokenizer.tokens(), "!!else") ); + } + + { + const std::string code("if ; else"); + + // tokenize.. + Tokenizer tokenizer; + std::istringstream istr(code); + tokenizer.tokenize(istr, "test.cpp"); + + // Match.. + ASSERT_EQUALS( false, TOKEN::Match(tokenizer.tokens(), "if ; !!else") ); + } + } void varid1() { diff --git a/token.cpp b/token.cpp index 75806a088..ad4d5eb8d 100644 --- a/token.cpp +++ b/token.cpp @@ -141,19 +141,24 @@ int TOKEN::multiCompare( const char *needle, const char *haystack ) return -1; } - - + bool TOKEN::Match(const TOKEN *tok, const char pattern[], const char *varname1[], const char *varname2[], unsigned int varid) { - if (!tok) - return false; - const char *p = pattern; - while (*p) - { + while ( *p ) + { // Skip spaces in pattern.. while ( *p == ' ' ) p++; + + if (!tok) + { + // If we have no tokens, pattern "!!else" should return true + if( isNotPattern( p ) ) + return true; + else + return false; + } // Extract token from pattern.. // TODO: Refactor this so there can't be buffer overflows @@ -252,19 +257,32 @@ bool TOKEN::Match(const TOKEN *tok, const char pattern[], const char *varname1[] // No match return false; } + } + + // Parse "not" options. Token can be anything except the given one + else if( isNotPattern( str ) ) + { + if( strcmp( tok->aaaa(), &(str[2]) ) == 0 ) + return false; } else if (str != tok->_str) return false; tok = tok->next(); - if (!tok && *p) - return false; } // The end of the pattern has been reached and nothing wrong has been found return true; } + +bool TOKEN::isNotPattern( const char *pattern ) +{ + if( pattern && strlen(pattern) > 2 && pattern[0] == '!' && pattern[1] == '!' ) + return true; + else + return false; +} bool TOKEN::isName() const { diff --git a/token.h b/token.h index f71c472b0..a08ba3a88 100644 --- a/token.h +++ b/token.h @@ -74,7 +74,8 @@ public: * "%varid%" Match with parameter varid * "[abc]" Any of the characters 'a' or 'b' or 'c' * "int|void|char" Any of the strings, int, void or char - * "int|void|char|" Any of the strings, int, void or char or empty string + * "int|void|char|" Any of the strings, int, void or char or empty string + * "!!else" No tokens or any token that is not "else". * "someRandomText" If token contains "someRandomText". * * The patterns can be also combined to compare to multiple tokens at once @@ -158,7 +159,18 @@ public: private: void next( TOKEN *next ); - void previous( TOKEN *previous ); + void previous( TOKEN *previous ); + + /** + * Return true if pattern is e.g. "!!else". + * See Match() for more info. + * + * @param pattern Pattern to match, e.g. "if ; !!else" + * @return true if pattern starts with "!!" and contains 3 + * or more characters. + */ + static bool isNotPattern( const char *pattern ); + std::string _str; char * _cstr; bool _isName;