| 499 | } |
| 500 | |
| 501 | std::string LuaSyntaxTree::GetDebugView() { |
| 502 | std::string debugView; |
| 503 | debugView.append("{ Lua Syntax Tree }\n"); |
| 504 | |
| 505 | auto root = GetRootNode(); |
| 506 | std::stack<LuaSyntaxNode> traverseStack; |
| 507 | std::size_t indent = 1; |
| 508 | traverseStack.push(root); |
| 509 | // 非递归深度优先遍历 |
| 510 | while (!traverseStack.empty()) { |
| 511 | LuaSyntaxNode node = traverseStack.top(); |
| 512 | if (node.IsNode(*this)) { |
| 513 | traverseStack.top() = LuaSyntaxNode(0); |
| 514 | auto children = node.GetChildren(*this); |
| 515 | for (auto rIt = children.rbegin(); rIt != children.rend(); rIt++) { |
| 516 | traverseStack.push(*rIt); |
| 517 | } |
| 518 | debugView.resize(debugView.size() + indent, '\t'); |
| 519 | debugView.append(util::format("{{ Node, index: {}, SyntaxKind: {} }}\n", |
| 520 | node.GetIndex(), |
| 521 | detail::debug::GetSyntaxKindDebugName(node.GetSyntaxKind(*this)))); |
| 522 | indent++; |
| 523 | } else if (node.IsToken(*this)) { |
| 524 | traverseStack.pop(); |
| 525 | debugView.resize(debugView.size() + indent, '\t'); |
| 526 | debugView.append(util::format("{{ Token, index: {}, TokenKind: {} }}\n", |
| 527 | node.GetIndex(), |
| 528 | node.GetText(*this))); |
| 529 | } else { |
| 530 | traverseStack.pop(); |
| 531 | indent--; |
| 532 | } |
| 533 | } |
| 534 | return debugView; |
| 535 | } |
| 536 | |
| 537 | bool LuaSyntaxTree::HasError() const { |
| 538 | return !_errors.empty(); |