From a3bb8bf39c7bb9ff91fcbe395979afb6eb47383d Mon Sep 17 00:00:00 2001 From: PKEuS Date: Sun, 11 May 2014 13:39:28 +0200 Subject: [PATCH] AST: Parse ternary and assignment operators as right-to-left and on the same precedence level --- lib/tokenlist.cpp | 30 +++++++++++------------------- test/testtokenize.cpp | 10 +++++----- 2 files changed, 16 insertions(+), 24 deletions(-) diff --git a/lib/tokenlist.cpp b/lib/tokenlist.cpp index 82ecdb135..680b65fa0 100644 --- a/lib/tokenlist.cpp +++ b/lib/tokenlist.cpp @@ -408,11 +408,11 @@ static void compileBinOp(Token *&tok, void (*f)(Token *&, std::stack &, 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 &op, unsigned int dep } } -static void compileTernaryOp(Token *&tok, std::stack &op, unsigned int depth) +static void compileAssignTernary(Token *&tok, std::stack &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 &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 &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; } } diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index a1acfc6ed..73fc1d380 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -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<