| 175 | |
| 176 | template<class T, class F, REQUIRES("T must be a Token class", std::is_convertible<T*, const Token*> )> |
| 177 | Progress traverseRecursive(T* tok, const F &f, bool traverseUnknown, unsigned int recursion=0) { |
| 178 | if (!tok) |
| 179 | return Progress::Continue; |
| 180 | if (recursion > 10000) |
| 181 | return Progress::Skip; |
| 182 | T* firstOp = tok->astOperand1(); |
| 183 | T* secondOp = tok->astOperand2(); |
| 184 | // Evaluate: |
| 185 | // 1. RHS of assignment before LHS |
| 186 | // 2. Unary op before operand |
| 187 | // 3. Function arguments before function call |
| 188 | if (tok->isAssignmentOp() || !secondOp || isFunctionCall(tok)) |
| 189 | std::swap(firstOp, secondOp); |
| 190 | if (firstOp && traverseRecursive(firstOp, f, traverseUnknown, recursion+1) == Progress::Break) |
| 191 | return Break(); |
| 192 | const Progress p = tok->isAssignmentOp() ? Progress::Continue : traverseTok(tok, f, traverseUnknown); |
| 193 | if (p == Progress::Break) |
| 194 | return Break(); |
| 195 | if (p == Progress::Continue && secondOp && traverseRecursive(secondOp, f, traverseUnknown, recursion+1) == Progress::Break) |
| 196 | return Break(); |
| 197 | if (tok->isAssignmentOp() && traverseTok(tok, f, traverseUnknown) == Progress::Break) |
| 198 | return Break(); |
| 199 | return Progress::Continue; |
| 200 | } |
| 201 | |
| 202 | template<class T, class F, REQUIRES("T must be a Token class", std::is_convertible<T*, const Token*> )> |
| 203 | Progress traverseConditional(T* tok, F f, bool traverseUnknown) { |
no test coverage detected