AST: Improved handling of unary operators

This commit is contained in:
Daniel Marjamäki 2012-12-16 08:41:04 +01:00
parent 6732f05b95
commit 1ad9c933ec
3 changed files with 37 additions and 10 deletions

View File

@ -1051,16 +1051,27 @@ std::string Token::stringifyList(bool varid) const
void Token::astOperand1(Token *tok) void Token::astOperand1(Token *tok)
{ {
// unary operand -> goto parent operator
while (tok->_astParent && !tok->_astParent->_astOperand2)
tok = tok->_astParent;
// there is a parent.. relink
if (tok->_astParent) { if (tok->_astParent) {
tok->_astParent->_astOperand2 = this; tok->_astParent->_astOperand2 = this;
_astParent = tok->_astParent; _astParent = tok->_astParent;
} }
tok->_astParent = this; tok->_astParent = this;
_astOperand1 = tok; _astOperand1 = tok;
} }
void Token::astOperand2(Token *tok) void Token::astOperand2(Token *tok)
{ {
// unary operand -> goto parent operator
while (tok->_astParent && !tok->_astParent->_astOperand2)
tok = tok->_astParent;
// there is a parent.. relink
if (tok->_astParent) { if (tok->_astParent) {
tok->_astParent->_astOperand1 = this; tok->_astParent->_astOperand1 = this;
_astParent = tok->_astParent; _astParent = tok->_astParent;
@ -1076,7 +1087,7 @@ void Token::astHandleParenthesis()
innerTop = innerTop->_astParent; innerTop = innerTop->_astParent;
if (_astParent) { if (_astParent) {
if (_str == "(") if (_str == "(" && _astParent->_astOperand2 != NULL)
_astParent->_astOperand2 = innerTop; _astParent->_astOperand2 = innerTop;
else else
_astParent->_astOperand1 = innerTop; _astParent->_astOperand1 = innerTop;

View File

@ -360,7 +360,7 @@ void TokenList::createAst()
for (unsigned int i = 0; i < sizeof(operators) / sizeof(*operators); ++i) { for (unsigned int i = 0; i < sizeof(operators) / sizeof(*operators); ++i) {
// TODO: extract operators to std::set - that should be faster // TODO: extract operators to std::set - that should be faster
if (*operators[i] == '>') { if (*operators[i] == '>') { // Unary operators, parse from right to left
const std::string op(1+operators[i]); const std::string op(1+operators[i]);
Token *tok = _front; Token *tok = _front;
while (tok->next()) while (tok->next())
@ -371,12 +371,16 @@ void TokenList::createAst()
tok->astOperand1(tok->next()); tok->astOperand1(tok->next());
} }
} }
} else { } else { // parse from left to right
const std::string op(operators[i]); const std::string op(operators[i]);
for (Token *tok = _front; tok; tok = tok->next()) { for (Token *tok = _front; tok; tok = tok->next()) {
if (tok->astOperand1()==NULL && op.find(" "+tok->str()+" ")!=std::string::npos) { if (tok->astOperand1()==NULL && op.find(" "+tok->str()+" ")!=std::string::npos) {
tok->astOperand1(tok->previous()); if (tok->str() != "++" && tok->str() != "--") {
tok->astOperand2(tok->next()); tok->astOperand1(tok->previous());
tok->astOperand2(tok->next());
} else if (tok->previous() && !tok->previous()->isOp()) {
tok->astOperand1(tok->previous());
}
} }
} }
} }

View File

@ -465,6 +465,8 @@ private:
TEST_CASE(astpar); TEST_CASE(astpar);
TEST_CASE(astbrackets); TEST_CASE(astbrackets);
TEST_CASE(astunaryop); TEST_CASE(astunaryop);
TEST_CASE(astfunction);
TEST_CASE(asttemplate);
} }
std::string tokenizeAndStringify(const char code[], bool simplify = false, bool expand = true, Settings::PlatformType platform = Settings::Unspecified, const char* filename = "test.cpp", bool cpp11 = true) { std::string tokenizeAndStringify(const char code[], bool simplify = false, bool expand = true, Settings::PlatformType platform = Settings::Unspecified, const char* filename = "test.cpp", bool cpp11 = true) {
@ -7642,25 +7644,35 @@ private:
return tokenList.front()->astTop()->astString(); return tokenList.front()->astTop()->astString();
} }
void astexpr() { void astexpr() { // simple expressions with arithmetical ops
ASSERT_EQUALS("123++", testAst("1+2+3")); ASSERT_EQUALS("123++", testAst("1+2+3"));
ASSERT_EQUALS("12*3+", testAst("1*2+3")); ASSERT_EQUALS("12*3+", testAst("1*2+3"));
ASSERT_EQUALS("123*+", testAst("1+2*3")); ASSERT_EQUALS("123*+", testAst("1+2*3"));
ASSERT_EQUALS("12*34*+", testAst("1*2+3*4")); ASSERT_EQUALS("12*34*+", testAst("1*2+3*4"));
} }
void astpar() { void astpar() { // parentheses
ASSERT_EQUALS("12+3*", testAst("(1+2)*3")); ASSERT_EQUALS("12+3*", testAst("(1+2)*3"));
ASSERT_EQUALS("123+*", testAst("1*(2+3)")); ASSERT_EQUALS("123+*", testAst("1*(2+3)"));
ASSERT_EQUALS("123+*4*", testAst("1*(2+3)*4")); ASSERT_EQUALS("123+*4*", testAst("1*(2+3)*4"));
} }
void astbrackets() { void astbrackets() { // []
ASSERT_EQUALS("123+[4+", testAst("1[2+3]+4")); ASSERT_EQUALS("123+[4+", testAst("1[2+3]+4"));
} }
void astunaryop() { void astunaryop() { // unary operators
ASSERT_EQUALS("12-+", testAst("1+-2")); ASSERT_EQUALS("1a--+", testAst("1 + --a"));
ASSERT_EQUALS("1a--+", testAst("1 + a--"));
ASSERT_EQUALS("ab+!", testAst("!(a+b)"));
}
void astfunction() { // function calls
TODO_ASSERT_EQUALS("1f+2+", "1f+", testAst("1+f()+2"));
}
void asttemplate() { // uninstantiated templates will have <,>,etc.. how do we handle them?
//ASSERT_EQUALS("", testAst("a<int>()==3"));
} }
}; };