AST: Parse ternary and assignment operators as right-to-left and on the same precedence level

This commit is contained in:
PKEuS 2014-05-11 13:39:28 +02:00
parent 70dfb55f21
commit a3bb8bf39c
2 changed files with 16 additions and 24 deletions

View File

@ -408,11 +408,11 @@ static void compileBinOp(Token *&tok, void (*f)(Token *&, std::stack<Token*> &,
Token *binop = tok;
tok = tok->next();
if (tok)
f(tok,op, depth);
f(tok, op, depth);
// Assignment operators are executed in right-to-left order
if (binop->isAssignmentOp() && tok && tok->isAssignmentOp())
compileBinOp(tok,f,op,depth);
// Assignment and ternary operators are executed in right-to-left order
if ((binop->isAssignmentOp() || Token::Match(binop, "[:?]")) && tok && (tok->isAssignmentOp() || Token::Match(tok, "[:?]")))
compileBinOp(tok, f, op, depth);
// TODO: Should we check if op is empty.
// * Is it better to add assertion that it isn't?
@ -702,32 +702,24 @@ static void compileLogicOr(Token *&tok, std::stack<Token*> &op, unsigned int dep
}
}
static void compileTernaryOp(Token *&tok, std::stack<Token*> &op, unsigned int depth)
static void compileAssignTernary(Token *&tok, std::stack<Token*> &op, unsigned int depth)
{
compileLogicOr(tok,op, depth);
compileLogicOr(tok, op, depth);
while (tok) {
if (Token::Match(tok, "[?:]")) {
// TODO: http://en.cppreference.com/w/cpp/language/operator_precedence says:
// "The expression in the middle of the conditional operator (between ? and :) is parsed as if parenthesized: its precedence relative to ?: is ignored."
if (tok->isAssignmentOp() || Token::Match(tok, "[?:]")) {
compileBinOp(tok, compileLogicOr, op, depth);
} else break;
}
}
static void compileAssign(Token *&tok, std::stack<Token*> &op, unsigned int depth)
{
compileTernaryOp(tok,op, depth);
while (tok) {
if (tok->isAssignmentOp()) {
compileBinOp(tok, compileTernaryOp, op, depth);
} else break;
}
}
static void compileComma(Token *&tok, std::stack<Token*> &op, unsigned int depth)
{
compileAssign(tok,op, depth);
compileAssignTernary(tok, op, depth);
while (tok) {
if (tok->str() == ",") {
compileBinOp(tok, compileAssign, op, depth);
compileBinOp(tok, compileAssignTernary, op, depth);
} else break;
}
}

View File

@ -10408,7 +10408,7 @@ private:
ASSERT_EQUALS("'X''a'>", testAst("('X' > 'a')"));
ASSERT_EQUALS("'X''a'>", testAst("(L'X' > L'a')"));
ASSERT_EQUALS("a0>bc/?d:", testAst("(a>0) ? (b/(c)) : d;"));
ASSERT_EQUALS("a0>bc/d:?", testAst("(a>0) ? (b/(c)) : d;"));
ASSERT_EQUALS("abc/+d+", testAst("a + (b/(c)) + d;"));
ASSERT_EQUALS("absizeofd(ef.+(=", testAst("a = b(sizeof(c d) + e.f)"));
@ -10462,7 +10462,7 @@ private:
ASSERT_EQUALS("a1(2+=",testAst("a=(t*)1+2;"));
ASSERT_EQUALS("a1(2+=",testAst("a=(t&)1+2;"));
ASSERT_EQUALS("ab::r&c(=", testAst("a::b& r = (a::b&)c;")); // #5261
ASSERT_EQUALS("ab1?0:=", testAst("a=(b)?1:0;"));
ASSERT_EQUALS("ab10:?=", testAst("a=(b)?1:0;"));
// ({..})
ASSERT_EQUALS("a{+d+ bc+", testAst("a+({b+c;})+d"));
@ -10493,11 +10493,11 @@ private:
ASSERT_EQUALS("c5[--*", testAst("*c[5]--;"));
// Unary :: operator
ASSERT_EQUALS("abc?d12,(::e/:=",testAst("a = b ? c : ::d(1,2) / e;"));
ASSERT_EQUALS("abcd12,(::e/:?=",testAst("a = b ? c : ::d(1,2) / e;"));
// how is "--" handled here:
ASSERT_EQUALS("ab4<<c--+?1:", testAst("a ? (b << 4) + --c : 1"));
ASSERT_EQUALS("ab4<<c--+?1:", testAst("a ? (b << 4) + c-- : 1"));
ASSERT_EQUALS("ab4<<c--+1:?", testAst("a ? (b << 4) + --c : 1"));
ASSERT_EQUALS("ab4<<c--+1:?", testAst("a ? (b << 4) + c-- : 1"));
}
void astfunction() const { // function calls