| 1410 | } |
| 1411 | |
| 1412 | static void compileAssignTernary(Token *&tok, AST_state& state) |
| 1413 | { |
| 1414 | compileLogicOr(tok, state); |
| 1415 | while (tok) { |
| 1416 | if (tok->isAssignmentOp()) { |
| 1417 | state.assign++; |
| 1418 | const Token *tok1 = tok->next(); |
| 1419 | compileBinOp(tok, state, compileAssignTernary); |
| 1420 | if (Token::simpleMatch(tok1, "{") && tok == tok1->link() && tok->next()) |
| 1421 | tok = tok->next(); |
| 1422 | if (state.assign > 0) |
| 1423 | state.assign--; |
| 1424 | } else if (tok->str() == "?") { |
| 1425 | // http://en.cppreference.com/w/cpp/language/operator_precedence says about ternary operator: |
| 1426 | // "The expression in the middle of the conditional operator (between ? and :) is parsed as if parenthesized: its precedence relative to ?: is ignored." |
| 1427 | // Hence, we rely on Tokenizer::prepareTernaryOpForAST() to add such parentheses where necessary. |
| 1428 | const bool stopAtColon = state.stopAtColon; |
| 1429 | state.stopAtColon = false; |
| 1430 | if (tok->strAt(1) == ":") { |
| 1431 | state.op.push(nullptr); |
| 1432 | } |
| 1433 | const int assign = state.assign; |
| 1434 | state.assign = 0; |
| 1435 | compileBinOp(tok, state, compileAssignTernary); |
| 1436 | state.assign = assign; |
| 1437 | state.stopAtColon = stopAtColon; |
| 1438 | } else if (tok->str() == ":") { |
| 1439 | if (state.depth == 1U && state.inCase) { |
| 1440 | state.inCase = false; |
| 1441 | tok = tok->next(); |
| 1442 | break; |
| 1443 | } |
| 1444 | if (state.stopAtColon) |
| 1445 | break; |
| 1446 | if (state.assign > 0) |
| 1447 | break; |
| 1448 | compileBinOp(tok, state, compileAssignTernary); |
| 1449 | } else break; |
| 1450 | } |
| 1451 | } |
| 1452 | |
| 1453 | static void compileComma(Token *&tok, AST_state& state) |
| 1454 | { |
no test coverage detected