diff --git a/lib/tokenlist.cpp b/lib/tokenlist.cpp index a275e105a..dbd0530dc 100644 --- a/lib/tokenlist.cpp +++ b/lib/tokenlist.cpp @@ -686,72 +686,92 @@ static void compileExpression(Token *&tok, std::stack &op) compileComma(tok,op); } +static Token * createAstAtToken(Token *tok) +{ + if (Token::simpleMatch(tok,"for (")) { + Token *tok2 = tok->tokAt(2); + Token *init1 = 0; + const Token * const endPar = tok->next()->link(); + while (tok2 && tok2 != endPar && tok2->str() != ";") { + if (tok2->str() == "<" && tok2->link()) { + tok2 = tok2->link(); + if (!tok2) + break; + } else if (Token::Match(tok2, "%var% %op%|(|[|.|=|:|::") || Token::Match(tok2->previous(), "[;{}] %cop%|(")) { + init1 = tok2; + std::stack operands; + compileExpression(tok2, operands); + if (tok2->str() == ";" || tok2->str() == ")") + break; + init1 = 0; + } + tok2 = tok2->next(); + } + if (!tok2 || tok2->str() != ";") { + if (tok2 == endPar && init1) { + tok->next()->astOperand2(init1); + tok->next()->astOperand1(tok); + } + return tok2; + } + + Token * const init = init1 ? init1 : tok2; + + Token * const semicolon1 = tok2; + tok2 = tok2->next(); + std::stack operands2; + compileExpression(tok2, operands2); + + Token * const semicolon2 = tok2; + tok2 = tok2->next(); + std::stack operands3; + compileExpression(tok2, operands3); + + if (init != semicolon1) + semicolon1->astOperand1(const_cast(init->astTop())); + tok2 = semicolon1->next(); + while (tok2 != semicolon2 && !tok2->isName() && !tok2->isNumber()) + tok2 = tok2->next(); + if (tok2 != semicolon2) + semicolon2->astOperand1(const_cast(tok2->astTop())); + tok2 = tok->linkAt(1); + while (tok2 != semicolon2 && !tok2->isName() && !tok2->isNumber()) + tok2 = tok2->previous(); + if (tok2 != semicolon2) + semicolon2->astOperand2(const_cast(tok2->astTop())); + + semicolon1->astOperand2(semicolon2); + tok->next()->astOperand1(tok); + tok->next()->astOperand2(semicolon1); + + return tok->linkAt(1); + } + + if (tok->str() == "return" || !tok->previous() || Token::Match(tok, "%var% %op%|(|[|.|=|::") || Token::Match(tok->previous(), "[;{}] %cop%|( !!{")) { + std::stack operands; + Token * const tok1 = tok; + compileExpression(tok, operands); + Token * const endToken = tok; + + // Compile inner expressions inside inner ({..}) + for (tok = tok1; tok && tok != endToken; tok = tok ? tok->next() : NULL) { + if (!Token::simpleMatch(tok, "( {")) + continue; + const Token * const endToken2 = tok->linkAt(1); + for (; tok && tok != endToken && tok != endToken2; tok = tok ? tok->next() : NULL) + tok = createAstAtToken(tok); + } + + return endToken ? endToken->previous() : NULL; + } + + return tok; +} + void TokenList::createAst() { for (Token *tok = _front; tok; tok = tok ? tok->next() : NULL) { - if (Token::simpleMatch(tok,"for (")) { - Token *tok2 = tok->tokAt(2); - Token *init1 = 0; - const Token * const endPar = tok->next()->link(); - while (tok2 && tok2 != endPar && tok2->str() != ";") { - if (tok2->str() == "<" && tok2->link()) { - tok2 = tok2->link(); - if (!tok2) - break; - } else if (Token::Match(tok2, "%var% %op%|(|[|.|=|:|::") || Token::Match(tok2->previous(), "[;{}] %cop%|(")) { - init1 = tok2; - std::stack operands; - compileExpression(tok2, operands); - if (tok2->str() == ";" || tok2->str() == ")") - break; - init1 = 0; - } - tok2 = tok2->next(); - } - if (!tok2 || tok2->str() != ";") { - if (tok2 == endPar && init1) { - tok->next()->astOperand2(init1); - tok->next()->astOperand1(tok); - } - tok = tok2; - continue; - } - - Token * const init = init1 ? init1 : tok2; - - Token * const semicolon1 = tok2; - tok2 = tok2->next(); - std::stack operands2; - compileExpression(tok2, operands2); - - Token * const semicolon2 = tok2; - tok2 = tok2->next(); - std::stack operands3; - compileExpression(tok2, operands3); - - if (init != semicolon1) - semicolon1->astOperand1(const_cast(init->astTop())); - tok2 = semicolon1->next(); - while (tok2 != semicolon2 && !tok2->isName() && !tok2->isNumber()) - tok2 = tok2->next(); - if (tok2 != semicolon2) - semicolon2->astOperand1(const_cast(tok2->astTop())); - tok2 = tok->linkAt(1); - while (tok2 != semicolon2 && !tok2->isName() && !tok2->isNumber()) - tok2 = tok2->previous(); - if (tok2 != semicolon2) - semicolon2->astOperand2(const_cast(tok2->astTop())); - - semicolon1->astOperand2(semicolon2); - tok->next()->astOperand1(tok); - tok->next()->astOperand2(semicolon1); - - tok = tok->linkAt(1); - } - if (tok->str() == "return" || !tok->previous() || Token::Match(tok, "%var% %op%|(|[|.|=|::") || Token::Match(tok->previous(), "[;{}] %cop%|(")) { - std::stack operands; - compileExpression(tok, operands); - } + tok = createAstAtToken(tok); } } diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index cf877860b..aaef4073a 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -10065,13 +10065,18 @@ private: // Create AST.. tokenList.createAst(); + // Return stringified AST + std::string ret; + std::set astTop; for (const Token *tok = tokenList.front(); tok; tok = tok->next()) { - if (tok->astOperand1()) - return tok->astTop()->astString(); + if (tok->astOperand1() && astTop.find(tok->astTop()) == astTop.end()) { + astTop.insert(tok->astTop()); + if (!ret.empty()) + ret = ret + " "; + ret += tok->astTop()->astString(); + } } - - // No AST found - return ""; + return ret; } void astexpr() const { // simple expressions with arithmetical ops @@ -10108,6 +10113,11 @@ private: TODO_ASSERT_EQUALS("fori1=current0=,iNUM<=i++;;(", "fori1=current0=,i,etc.. ASSERT_EQUALS("a(3==", testAst("a()==3")); - ASSERT_EQUALS("ab(==", testAst("a == b(); f();")); + ASSERT_EQUALS("ab(== f(", testAst("a == b(); f();")); } };