tree.cpp 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  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.has_value());
  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. // Not every token that can produce a virtual node will, so we only check that
  40. // the number of nodes is in a range.
  41. int32_t num_nodes = size();
  42. if (!has_errors() && num_nodes > tokens_->expected_max_parse_tree_size()) {
  43. return Error(llvm::formatv(
  44. "Tree has {0} nodes and no errors, but "
  45. "Lex::TokenizedBuffer expected up to {1} nodes for {2} tokens.",
  46. num_nodes, tokens_->expected_max_parse_tree_size(), tokens_->size()));
  47. }
  48. if (!has_errors() && num_nodes < tokens_->size()) {
  49. return Error(
  50. llvm::formatv("Tree has {0} nodes and no errors, but expected at least "
  51. "{1} nodes to match the number of tokens.",
  52. num_nodes, tokens_->size()));
  53. }
  54. #ifndef NDEBUG
  55. TreeAndSubtrees subtrees(*tokens_, *this);
  56. CARBON_RETURN_IF_ERROR(subtrees.Verify());
  57. #endif // NDEBUG
  58. return Success();
  59. }
  60. auto Tree::CollectMemUsage(MemUsage& mem_usage, llvm::StringRef label) const
  61. -> void {
  62. mem_usage.Collect(MemUsage::ConcatLabel(label, "node_impls_"), node_impls_);
  63. mem_usage.Collect(MemUsage::ConcatLabel(label, "imports_"), imports_);
  64. }
  65. auto Tree::PostorderIterator::MakeRange(NodeId begin, NodeId end)
  66. -> llvm::iterator_range<PostorderIterator> {
  67. CARBON_CHECK(begin.has_value() && end.has_value());
  68. return llvm::iterator_range<PostorderIterator>(
  69. PostorderIterator(begin), PostorderIterator(NodeId(end.index + 1)));
  70. }
  71. auto Tree::PostorderIterator::Print(llvm::raw_ostream& output) const -> void {
  72. output << node_;
  73. }
  74. } // namespace Carbon::Parse