AST: Parse ternary and assignment operators as right-to-left and on the same precedence level
This commit is contained in:
parent
70dfb55f21
commit
a3bb8bf39c
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue