tree.cpp 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. #include "toolchain/parse/tree.h"
  5. #include "common/check.h"
  6. #include "common/error.h"
  7. #include "llvm/ADT/Sequence.h"
  8. #include "llvm/ADT/SmallVector.h"
  9. #include "toolchain/lex/tokenized_buffer.h"
  10. #include "toolchain/parse/node_kind.h"
  11. #include "toolchain/parse/tree_and_subtrees.h"
  12. #include "toolchain/parse/typed_nodes.h"
  13. namespace Carbon::Parse {
  14. auto Tree::postorder() const -> llvm::iterator_range<PostorderIterator> {
  15. return llvm::iterator_range<PostorderIterator>(
  16. PostorderIterator(NodeId(0)),
  17. PostorderIterator(NodeId(node_impls_.size())));
  18. }
  19. auto Tree::node_token(NodeId n) const -> Lex::TokenIndex {
  20. CARBON_CHECK(n.is_valid());
  21. return node_impls_[n.index].token;
  22. }
  23. auto Tree::Print(llvm::raw_ostream& output) const -> void {
  24. TreeAndSubtrees(*tokens_, *this).Print(output);
  25. }
  26. auto Tree::Verify() const -> ErrorOr<Success> {
  27. llvm::SmallVector<NodeId> nodes;
  28. // Traverse the tree in postorder.
  29. for (NodeId n : postorder()) {
  30. if (node_has_error(n) && !has_errors()) {
  31. return Error(llvm::formatv(
  32. "Node {0} has errors, but the tree is not marked as having any.", n));
  33. }
  34. if (node_kind(n) == NodeKind::Placeholder) {
  35. return Error(llvm::formatv(
  36. "Node {0} is a placeholder node that wasn't replaced.", n));
  37. }
  38. }
  39. if (!has_errors() &&
  40. static_cast<int32_t>(size()) != tokens_->expected_parse_tree_size()) {
  41. return Error(llvm::formatv(
  42. "Tree has {0} nodes and no errors, but "
  43. "Lex::TokenizedBuffer expected {1} nodes for {2} tokens.",
  44. size(), tokens_->expected_parse_tree_size(), tokens_->size()));
  45. }
  46. #ifndef NDEBUG
  47. TreeAndSubtrees subtrees(*tokens_, *this);
  48. CARBON_RETURN_IF_ERROR(subtrees.Verify());
  49. #endif // NDEBUG
  50. return Success();
  51. }
  52. auto Tree::CollectMemUsage(MemUsage& mem_usage, llvm::StringRef label) const
  53. -> void {
  54. mem_usage.Add(MemUsage::ConcatLabel(label, "node_impls_"), node_impls_);
  55. mem_usage.Add(MemUsage::ConcatLabel(label, "imports_"), imports_);
  56. }
  57. auto Tree::PostorderIterator::MakeRange(NodeId begin, NodeId end)
  58. -> llvm::iterator_range<PostorderIterator> {
  59. CARBON_CHECK(begin.is_valid() && end.is_valid());
  60. return llvm::iterator_range<PostorderIterator>(
  61. PostorderIterator(begin), PostorderIterator(NodeId(end.index + 1)));
  62. }
  63. auto Tree::PostorderIterator::Print(llvm::raw_ostream& output) const -> void {
  64. output << node_;
  65. }
  66. } // namespace Carbon::Parse