From f58de06c0dbd506573620d8f2873923a8697c925 Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Mon, 17 Aug 2026 17:39:42 +0000 Subject: [PATCH] parse, lex: Decompose AST extraction and forward-declare dump types (#7645) - Enhance toolchain/parse/node_kind.def with category x-macros (CARBON_PARSE_NODE_KIND_DECLARATION, CARBON_PARSE_NODE_KIND_EXPRESSION, CARBON_PARSE_NODE_KIND_PATTERN, CARBON_PARSE_NODE_KIND_STATEMENT) that default to CARBON_PARSE_NODE_KIND, keeping node_kind.def as the single source of truth without manual expansion divergence. - Decompose the monolithic toolchain/parse/extract.cpp translation unit into separate compilation units for declarations, expressions, patterns, and statements by expanding respective category x-macros. - Forward-declare Tree and TokenizedBuffer in parse and lex dump headers to reduce header inclusion depth. Assisted-by: Antigravity with Gemini --- toolchain/lex/BUILD | 3 +- toolchain/lex/dump.cpp | 1 + toolchain/lex/dump.h | 6 +- toolchain/parse/BUILD | 10 +- toolchain/parse/dump.cpp | 1 + toolchain/parse/dump.h | 7 +- toolchain/parse/extract.cpp | 334 +-------------- toolchain/parse/extract.h | 326 +++++++++++++++ toolchain/parse/extract_declarations.cpp | 17 + toolchain/parse/extract_expressions.cpp | 17 + toolchain/parse/extract_patterns.cpp | 17 + toolchain/parse/extract_statements.cpp | 17 + toolchain/parse/node_kind.def | 494 +++++++++++++---------- toolchain/parse/node_kind.h | 1 + 14 files changed, 698 insertions(+), 553 deletions(-) create mode 100644 toolchain/parse/extract.h create mode 100644 toolchain/parse/extract_declarations.cpp create mode 100644 toolchain/parse/extract_expressions.cpp create mode 100644 toolchain/parse/extract_patterns.cpp create mode 100644 toolchain/parse/extract_statements.cpp diff --git a/toolchain/lex/BUILD b/toolchain/lex/BUILD index ca913c4d076f..00baa0d0cb8e 100644 --- a/toolchain/lex/BUILD +++ b/toolchain/lex/BUILD @@ -186,7 +186,6 @@ cc_library( hdrs = ["lex.h"], deps = [ ":character_set", - ":dump", ":helpers", ":numeric_literal", ":string_literal", @@ -210,8 +209,8 @@ cc_library( srcs = ["dump.cpp"], hdrs = ["dump.h"], deps = [ + ":token_index", ":tokenized_buffer", - "//common:ostream", "//common:raw_string_ostream", ], # Always link dump methods. diff --git a/toolchain/lex/dump.cpp b/toolchain/lex/dump.cpp index e386afa9263f..66cc53d8ad3a 100644 --- a/toolchain/lex/dump.cpp +++ b/toolchain/lex/dump.cpp @@ -9,6 +9,7 @@ #include #include "common/raw_string_ostream.h" +#include "toolchain/lex/tokenized_buffer.h" namespace Carbon::Lex { diff --git a/toolchain/lex/dump.h b/toolchain/lex/dump.h index 70827d813745..081b5bd87c6e 100644 --- a/toolchain/lex/dump.h +++ b/toolchain/lex/dump.h @@ -19,10 +19,14 @@ #ifndef NDEBUG -#include "toolchain/lex/tokenized_buffer.h" +#include + +#include "toolchain/lex/token_index.h" namespace Carbon::Lex { +class TokenizedBuffer; + auto Dump(const TokenizedBuffer& tokens, TokenIndex token) -> std::string; } // namespace Carbon::Lex diff --git a/toolchain/parse/BUILD b/toolchain/parse/BUILD index b80189e64d98..b13a0a01751b 100644 --- a/toolchain/parse/BUILD +++ b/toolchain/parse/BUILD @@ -124,10 +124,11 @@ cc_library( hdrs = ["dump.h"], deps = [ ":context", + ":node_kind", ":tree", - "//common:ostream", "//common:raw_string_ostream", "//toolchain/lex:dump", + "//toolchain/lex:token_index", ], # Always link dump methods. alwayslink = 1, @@ -145,14 +146,20 @@ cc_library( name = "tree", srcs = [ "extract.cpp", + "extract_declarations.cpp", + "extract_expressions.cpp", + "extract_patterns.cpp", + "extract_statements.cpp", "tree.cpp", "tree_and_subtrees.cpp", ], hdrs = [ + "extract.h", "tree.h", "tree_and_subtrees.h", ], deps = [ + ":node_category", ":node_kind", "//common:check", "//common:error", @@ -162,6 +169,7 @@ cc_library( "//toolchain/base:fixed_size_value_store", "//toolchain/base:value_store", "//toolchain/lex:token_index", + "//toolchain/lex:token_kind", "//toolchain/lex:tokenized_buffer", "@llvm-project//llvm:Support", ], diff --git a/toolchain/parse/dump.cpp b/toolchain/parse/dump.cpp index acf2537b1526..fc5df23ff1e1 100644 --- a/toolchain/parse/dump.cpp +++ b/toolchain/parse/dump.cpp @@ -11,6 +11,7 @@ #include "common/raw_string_ostream.h" #include "toolchain/lex/dump.h" #include "toolchain/parse/context.h" +#include "toolchain/parse/tree.h" namespace Carbon::Parse { diff --git a/toolchain/parse/dump.h b/toolchain/parse/dump.h index 33c8baeaaf0b..598d668c4901 100644 --- a/toolchain/parse/dump.h +++ b/toolchain/parse/dump.h @@ -19,10 +19,15 @@ #ifndef NDEBUG -#include "toolchain/parse/tree.h" +#include + +#include "toolchain/lex/token_index.h" +#include "toolchain/parse/node_ids.h" namespace Carbon::Parse { +class Tree; + auto Dump(const Tree& tree, Lex::TokenIndex token) -> std::string; auto Dump(const Tree& tree, NodeId node_id) -> std::string; diff --git a/toolchain/parse/extract.cpp b/toolchain/parse/extract.cpp index faba878cfe74..564ae48e5de2 100644 --- a/toolchain/parse/extract.cpp +++ b/toolchain/parse/extract.cpp @@ -2,143 +2,19 @@ // Exceptions. See /LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +#include "toolchain/parse/extract.h" + #include #include -#include -#include -#include "common/error.h" #include "common/find.h" -#include "common/struct_reflection.h" -#include "llvm/Support/TypeName.h" -#include "toolchain/parse/tree.h" -#include "toolchain/parse/tree_and_subtrees.h" -#include "toolchain/parse/typed_nodes.h" +#include "llvm/ADT/StringExtras.h" +#include "toolchain/lex/token_kind.h" +#include "toolchain/parse/node_category.h" +#include "toolchain/parse/node_kind.h" namespace Carbon::Parse { -namespace { -// Implementation of the process of extracting a typed node structure from the -// parse tree. The extraction process uses the class `Extractable`, defined -// below, to extract individual fields of type `T`. -class NodeExtractor { - public: - struct CheckpointState { - TreeAndSubtrees::SiblingIterator it; - }; - - NodeExtractor(const TreeAndSubtrees* tree, const Lex::TokenizedBuffer* tokens, - ErrorBuilder* trace, NodeId node_id, - llvm::iterator_range children) - : tree_(tree), - tokens_(tokens), - trace_(trace), - node_id_(node_id), - it_(children.begin()), - end_(children.end()) {} - - auto at_end() const -> bool { return it_ == end_; } - auto kind() const -> NodeKind { return tree_->tree().node_kind(*it_); } - auto has_token() const -> bool { return node_id_.has_value(); } - auto token() const -> Lex::TokenIndex { - return tree_->tree().node_token(node_id_); - } - auto token_kind() const -> Lex::TokenKind { - return tokens_->GetKind(token()); - } - auto trace() const -> ErrorBuilder* { return trace_; } - - // Saves a checkpoint of our current position so we can return later if - // extraction of a child node fails. - auto Checkpoint() const -> CheckpointState { return {.it = it_}; } - auto RestoreCheckpoint(CheckpointState checkpoint) -> void { - it_ = checkpoint.it; - } - - // Determines whether the current position matches the specified node kind. If - // not, produces a suitable trace message. - auto MatchesNodeIdForKind(NodeKind kind) const -> bool; - - // Determines whether the current position matches the specified node - // category. If not, produces a suitable trace message. - auto MatchesNodeIdInCategory(NodeCategory category) const -> bool; - - // Determines whether the current position matches any of the specified node - // kinds. If not, produces a suitable trace message. - auto MatchesNodeIdOneOf(std::initializer_list kinds) const -> bool; - - // Determines whether the token corresponding to the enclosing node is of the - // specified kind. If not, produces a suitable trace message. - auto MatchesTokenKind(Lex::TokenKind expected_kind) const -> bool; - - // Extracts the next node from the tree. - auto ExtractNode() -> NodeId { return *it_++; } - - // Extracts a tuple-like type `T` by extracting its components and then - // assembling a `T` value. - template - auto ExtractTupleLikeType(std::index_sequence /*indices*/, - std::tuple* /*type*/) -> std::optional; - - // Split out trace logic. The noinline saves a few seconds on compilation. - // TODO: Switch format to `llvm::StringLiteral` if - // `llvm::StringLiteral::c_str` is added. - template - [[clang::noinline]] auto MaybeTrace(const char* format, ArgT... args) const - -> void { - if (trace_) { - *trace_ << llvm::formatv(format, args...); - } - } - - auto tree() -> const Tree& { return tree_->tree(); } - - private: - const TreeAndSubtrees* tree_; - const Lex::TokenizedBuffer* tokens_; - ErrorBuilder* trace_; - NodeId node_id_; - TreeAndSubtrees::SiblingIterator it_; - TreeAndSubtrees::SiblingIterator end_; -}; -} // namespace - -namespace { -// A trait type that should be specialized by types that can be extracted -// from a parse tree. A specialization should provide the following API: -// -// ```cpp -// template<> -// struct Extractable { -// // Extract a value of this type from the sequence of nodes starting at -// // `it`, and increment `it` past this type. Returns `std::nullopt` if -// // the tree is malformed. If `trace != nullptr`, writes what actions -// // were taken to `*trace`. -// static auto Extract(NodeExtractor* extractor) -> std::optional; -// }; -// ``` -// -// Note that `TreeAndSubtrees::SiblingIterator`s iterate in reverse order -// through the children of a node. -// -// This class is only in this file. -template -struct Extractable; -} // namespace - -// Extract a `NodeId` as a single child. -template <> -struct Extractable { - static auto Extract(NodeExtractor& extractor) -> std::optional { - if (extractor.at_end()) { - extractor.MaybeTrace("NodeId error: no more children\n"); - return std::nullopt; - } - extractor.MaybeTrace("NodeId: {0} consumed\n", extractor.kind()); - return extractor.ExtractNode(); - } -}; - auto NodeExtractor::MatchesNodeIdForKind(NodeKind expected_kind) const -> bool { if (at_end()) { MaybeTrace("NodeIdForKind error: no more children, expected {0}\n", @@ -153,20 +29,6 @@ auto NodeExtractor::MatchesNodeIdForKind(NodeKind expected_kind) const -> bool { return true; } -// Extract a `FooId`, which is the same as `NodeIdForKind`, -// as a single required child. -template -struct Extractable> { - static auto Extract(NodeExtractor& extractor) - -> std::optional> { - if (extractor.MatchesNodeIdForKind(Kind)) { - return extractor.tree().As>(extractor.ExtractNode()); - } else { - return std::nullopt; - } - } -}; - auto NodeExtractor::MatchesNodeIdInCategory(NodeCategory category) const -> bool { if (at_end()) { @@ -181,20 +43,6 @@ auto NodeExtractor::MatchesNodeIdInCategory(NodeCategory category) const return true; } -// Extract a `NodeIdInCategory` as a single child. -template -struct Extractable> { - static auto Extract(NodeExtractor& extractor) - -> std::optional> { - if (extractor.MatchesNodeIdInCategory(Category)) { - return extractor.tree().As>( - extractor.ExtractNode()); - } else { - return std::nullopt; - } - } -}; - auto NodeExtractor::MatchesNodeIdOneOf( std::initializer_list kinds) const -> bool { auto trace_kinds = [&] { @@ -227,80 +75,6 @@ auto NodeExtractor::MatchesNodeIdOneOf( return true; } -// Extract a `NodeIdOneOf` as a single required child. -template -struct Extractable> { - static auto Extract(NodeExtractor& extractor) - -> std::optional> { - if (extractor.MatchesNodeIdOneOf({T::Kind...})) { - return extractor.tree().As>(extractor.ExtractNode()); - } else { - return std::nullopt; - } - } -}; - -// Extract a `NodeIdNot` as a single required child. -// Note: this is only instantiated once, so no need to create a helper function. -template -struct Extractable> { - static auto Extract(NodeExtractor& extractor) -> std::optional> { - // This converts NodeKind::Definition to NodeKind. - constexpr NodeKind Kind = T::Kind; - if (extractor.at_end()) { - extractor.MaybeTrace("NodeIdNot {0} error: no more children\n", Kind); - return std::nullopt; - } else if (extractor.kind() == Kind) { - extractor.MaybeTrace("NodeIdNot error: unexpected {0}\n", Kind); - return std::nullopt; - } - extractor.MaybeTrace("NodeIdNot {0}: {1} consumed\n", Kind, - extractor.kind()); - return NodeIdNot(extractor.ExtractNode()); - } -}; - -// Extract an `llvm::SmallVector` by extracting `T`s until we can't. -template -struct Extractable> { - static auto Extract(NodeExtractor& extractor) - -> std::optional> { - extractor.MaybeTrace("Vector: begin\n"); - llvm::SmallVector result; - while (!extractor.at_end()) { - auto checkpoint = extractor.Checkpoint(); - auto item = Extractable::Extract(extractor); - if (!item.has_value()) { - extractor.RestoreCheckpoint(checkpoint); - break; - } - result.push_back(*item); - } - std::reverse(result.begin(), result.end()); - extractor.MaybeTrace("Vector: end\n"); - return result; - } -}; - -// Extract an `optional` from a list of child nodes by attempting to extract -// a `T`, and extracting nothing if that fails. -template -struct Extractable> { - static auto Extract(NodeExtractor& extractor) - -> std::optional> { - extractor.MaybeTrace("Optional {0}: begin\n", llvm::getTypeName()); - auto checkpoint = extractor.Checkpoint(); - std::optional value = Extractable::Extract(extractor); - if (value) { - extractor.MaybeTrace("Optional {0}: found\n", llvm::getTypeName()); - } else { - extractor.MaybeTrace("Optional {0}: missing\n", llvm::getTypeName()); - extractor.RestoreCheckpoint(checkpoint); - } - return value; - } -}; - auto NodeExtractor::MatchesTokenKind(Lex::TokenKind expected_kind) const -> bool { if (!node_id_.has_value()) { @@ -318,101 +92,11 @@ auto NodeExtractor::MatchesTokenKind(Lex::TokenKind expected_kind) const return true; } -// Extract the token corresponding to a node. -template -struct Extractable> { - static auto Extract(NodeExtractor& extractor) - -> std::optional> { - if (extractor.MatchesTokenKind(Kind)) { - return static_cast>(extractor.token()); - } else { - return std::nullopt; - } - } -}; - -// Extract the token corresponding to a node. -template <> -struct Extractable { - static auto Extract(NodeExtractor& extractor) - -> std::optional { - if (!extractor.has_token()) { - extractor.MaybeTrace("Token expected but processing root node\n"); - return std::nullopt; - } - return extractor.token(); - } -}; - -template -auto NodeExtractor::ExtractTupleLikeType( - std::index_sequence /*indices*/, std::tuple* /*type*/) - -> std::optional { - std::tuple...> fields; - MaybeTrace("Aggregate {0}: begin\n", llvm::getTypeName()); - // Use a fold over the `=` operator to parse fields from right to left. - [[maybe_unused]] int unused; - bool ok = true; - static_cast( - ((ok && (ok = (std::get(fields) = Extractable::Extract(*this)) - .has_value()), - unused) = ... = 0)); - if (!ok) { - MaybeTrace("Aggregate {0}: error\n", llvm::getTypeName()); - return std::nullopt; - } - - MaybeTrace("Aggregate {0}: success\n", llvm::getTypeName()); - return T{std::move(std::get(fields).value())...}; -} - -namespace { -// Extract the fields of a simple aggregate type. -template -struct Extractable { - static_assert(std::is_aggregate_v, "Unsupported child type"); - static auto ExtractImpl(NodeExtractor& extractor) -> std::optional { - // Compute the corresponding tuple type. - using TupleType = decltype(StructReflection::AsTuple(std::declval())); - return extractor.ExtractTupleLikeType( - std::make_index_sequence>(), - static_cast(nullptr)); - } - - static auto Extract(NodeExtractor& extractor) -> std::optional { - static_assert(!HasKindMember, "Missing Id suffix"); - return ExtractImpl(extractor); - } -}; -} // namespace - -template -auto TreeAndSubtrees::TryExtractNodeFromChildren( +// Instantiate for `File`, which is the root container type. +template auto TreeAndSubtrees::TryExtractNodeFromChildren( NodeId node_id, llvm::iterator_range children, - ErrorBuilder* trace) const -> std::optional { - NodeExtractor extractor(this, tokens_, trace, node_id, children); - auto result = Extractable::ExtractImpl(extractor); - if (!extractor.at_end()) { - if (trace) { - *trace << "Error: " << tree_->node_kind(extractor.ExtractNode()) - << " node left unconsumed."; - } - return std::nullopt; - } - return result; -} - -// Manually instantiate Tree::TryExtractNodeFromChildren -#define CARBON_PARSE_NODE_KIND(KindName) \ - template auto TreeAndSubtrees::TryExtractNodeFromChildren( \ - NodeId node_id, \ - llvm::iterator_range children, \ - ErrorBuilder * trace) const -> std::optional; - -// Also instantiate for `File`, even though it isn't a parse node. -CARBON_PARSE_NODE_KIND(File) -#include "toolchain/parse/node_kind.def" + ErrorBuilder* trace) const -> std::optional; auto TreeAndSubtrees::ExtractFile() const -> File { return ExtractNodeFromChildren(NodeId::None, roots()); diff --git a/toolchain/parse/extract.h b/toolchain/parse/extract.h new file mode 100644 index 000000000000..821b3e1ce8c5 --- /dev/null +++ b/toolchain/parse/extract.h @@ -0,0 +1,326 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef CARBON_TOOLCHAIN_PARSE_EXTRACT_H_ +#define CARBON_TOOLCHAIN_PARSE_EXTRACT_H_ + +#include +#include +#include +#include + +#include "common/error.h" +#include "common/find.h" +#include "common/struct_reflection.h" +#include "llvm/Support/TypeName.h" +#include "toolchain/parse/tree.h" +#include "toolchain/parse/tree_and_subtrees.h" +#include "toolchain/parse/typed_nodes.h" + +namespace Carbon::Parse { + +// Implementation of the process of extracting a typed node structure from the +// parse tree. The extraction process uses the class `Extractable`, defined +// below, to extract individual fields of type `T`. +class NodeExtractor { + public: + struct CheckpointState { + TreeAndSubtrees::SiblingIterator it; + }; + + NodeExtractor(const TreeAndSubtrees* tree, const Lex::TokenizedBuffer* tokens, + ErrorBuilder* trace, NodeId node_id, + llvm::iterator_range children) + : tree_(tree), + tokens_(tokens), + trace_(trace), + node_id_(node_id), + it_(children.begin()), + end_(children.end()) {} + + auto at_end() const -> bool { return it_ == end_; } + auto kind() const -> NodeKind { return tree_->tree().node_kind(*it_); } + auto has_token() const -> bool { return node_id_.has_value(); } + auto token() const -> Lex::TokenIndex { + return tree_->tree().node_token(node_id_); + } + auto token_kind() const -> Lex::TokenKind { + return tokens_->GetKind(token()); + } + auto trace() const -> ErrorBuilder* { return trace_; } + + // Saves a checkpoint of our current position so we can return later if + // extraction of a child node fails. + auto Checkpoint() const -> CheckpointState { return {.it = it_}; } + auto RestoreCheckpoint(CheckpointState checkpoint) -> void { + it_ = checkpoint.it; + } + + // Determines whether the current position matches the specified node kind. If + // not, produces a suitable trace message. + auto MatchesNodeIdForKind(NodeKind kind) const -> bool; + + // Determines whether the current position matches the specified node + // category. If not, produces a suitable trace message. + auto MatchesNodeIdInCategory(NodeCategory category) const -> bool; + + // Determines whether the current position matches any of the specified node + // kinds. If not, produces a suitable trace message. + auto MatchesNodeIdOneOf(std::initializer_list kinds) const -> bool; + + // Determines whether the token corresponding to the enclosing node is of the + // specified kind. If not, produces a suitable trace message. + auto MatchesTokenKind(Lex::TokenKind expected_kind) const -> bool; + + // Extracts the next node from the tree. + auto ExtractNode() -> NodeId { return *it_++; } + + // Extracts a tuple-like type `T` by extracting its components and then + // assembling a `T` value. + template + auto ExtractTupleLikeType(std::index_sequence /*indices*/, + std::tuple* /*type*/) -> std::optional; + + // Split out trace logic. The noinline saves a few seconds on compilation. + // TODO: Switch format to `llvm::StringLiteral` if + // `llvm::StringLiteral::c_str` is added. + template + [[clang::noinline]] auto MaybeTrace(const char* format, ArgT... args) const + -> void { + if (trace_) { + *trace_ << llvm::formatv(format, args...); + } + } + + auto tree() -> const Tree& { return tree_->tree(); } + + private: + const TreeAndSubtrees* tree_; + const Lex::TokenizedBuffer* tokens_; + ErrorBuilder* trace_; + NodeId node_id_; + TreeAndSubtrees::SiblingIterator it_; + TreeAndSubtrees::SiblingIterator end_; +}; + +// A trait type that should be specialized by types that can be extracted +// from a parse tree. A specialization should provide the following API: +// +// ```cpp +// template<> +// struct Extractable { +// // Extract a value of this type from the sequence of nodes starting at +// // `it`, and increment `it` past this type. Returns `std::nullopt` if +// // the tree is malformed. If `trace != nullptr`, writes what actions +// // were taken to `*trace`. +// static auto Extract(NodeExtractor* extractor) -> std::optional; +// }; +// ``` +// +// Note that `TreeAndSubtrees::SiblingIterator`s iterate in reverse order +// through the children of a node. +template +struct Extractable; + +// Extract a `NodeId` as a single child. +template <> +struct Extractable { + static auto Extract(NodeExtractor& extractor) -> std::optional { + if (extractor.at_end()) { + extractor.MaybeTrace("NodeId error: no more children\n"); + return std::nullopt; + } + extractor.MaybeTrace("NodeId: {0} consumed\n", extractor.kind()); + return extractor.ExtractNode(); + } +}; + +// Extract a `FooId`, which is the same as `NodeIdForKind`, +// as a single required child. +template +struct Extractable> { + static auto Extract(NodeExtractor& extractor) + -> std::optional> { + if (extractor.MatchesNodeIdForKind(Kind)) { + return extractor.tree().As>(extractor.ExtractNode()); + } else { + return std::nullopt; + } + } +}; + +// Extract a `NodeIdInCategory` as a single child. +template +struct Extractable> { + static auto Extract(NodeExtractor& extractor) + -> std::optional> { + if (extractor.MatchesNodeIdInCategory(Category)) { + return extractor.tree().As>( + extractor.ExtractNode()); + } else { + return std::nullopt; + } + } +}; + +// Extract a `NodeIdOneOf` as a single required child. +template +struct Extractable> { + static auto Extract(NodeExtractor& extractor) + -> std::optional> { + if (extractor.MatchesNodeIdOneOf({T::Kind...})) { + return extractor.tree().As>(extractor.ExtractNode()); + } else { + return std::nullopt; + } + } +}; + +// Extract a `NodeIdNot` as a single required child. +// Note: this is only instantiated once, so no need to create a helper function. +template +struct Extractable> { + static auto Extract(NodeExtractor& extractor) -> std::optional> { + // This converts NodeKind::Definition to NodeKind. + constexpr NodeKind Kind = T::Kind; + if (extractor.at_end()) { + extractor.MaybeTrace("NodeIdNot {0} error: no more children\n", Kind); + return std::nullopt; + } else if (extractor.kind() == Kind) { + extractor.MaybeTrace("NodeIdNot error: unexpected {0}\n", Kind); + return std::nullopt; + } + extractor.MaybeTrace("NodeIdNot {0}: {1} consumed\n", Kind, + extractor.kind()); + return NodeIdNot(extractor.ExtractNode()); + } +}; + +// Extract an `llvm::SmallVector` by extracting `T`s until we can't. +template +struct Extractable> { + static auto Extract(NodeExtractor& extractor) + -> std::optional> { + extractor.MaybeTrace("Vector: begin\n"); + llvm::SmallVector result; + while (!extractor.at_end()) { + auto checkpoint = extractor.Checkpoint(); + auto item = Extractable::Extract(extractor); + if (!item.has_value()) { + extractor.RestoreCheckpoint(checkpoint); + break; + } + result.push_back(*item); + } + std::reverse(result.begin(), result.end()); + extractor.MaybeTrace("Vector: end\n"); + return result; + } +}; + +// Extract an `optional` from a list of child nodes by attempting to extract +// a `T`, and extracting nothing if that fails. +template +struct Extractable> { + static auto Extract(NodeExtractor& extractor) + -> std::optional> { + extractor.MaybeTrace("Optional {0}: begin\n", llvm::getTypeName()); + auto checkpoint = extractor.Checkpoint(); + std::optional value = Extractable::Extract(extractor); + if (value) { + extractor.MaybeTrace("Optional {0}: found\n", llvm::getTypeName()); + } else { + extractor.MaybeTrace("Optional {0}: missing\n", llvm::getTypeName()); + extractor.RestoreCheckpoint(checkpoint); + } + return value; + } +}; + +// Extract the token corresponding to a node. +template +struct Extractable> { + static auto Extract(NodeExtractor& extractor) + -> std::optional> { + if (extractor.MatchesTokenKind(Kind)) { + return static_cast>(extractor.token()); + } else { + return std::nullopt; + } + } +}; + +// Extract the token corresponding to a node. +template <> +struct Extractable { + static auto Extract(NodeExtractor& extractor) + -> std::optional { + if (!extractor.has_token()) { + extractor.MaybeTrace("Token expected but processing root node\n"); + return std::nullopt; + } + return extractor.token(); + } +}; + +template +auto NodeExtractor::ExtractTupleLikeType( + std::index_sequence /*indices*/, std::tuple* /*type*/) + -> std::optional { + std::tuple...> fields; + MaybeTrace("Aggregate {0}: begin\n", llvm::getTypeName()); + // Use a fold over the `=` operator to parse fields from right to left. + [[maybe_unused]] int unused; + bool ok = true; + static_cast( + ((ok && (ok = (std::get(fields) = Extractable::Extract(*this)) + .has_value()), + unused) = ... = 0)); + if (!ok) { + MaybeTrace("Aggregate {0}: error\n", llvm::getTypeName()); + return std::nullopt; + } + + MaybeTrace("Aggregate {0}: success\n", llvm::getTypeName()); + return T{std::move(std::get(fields).value())...}; +} + +// Extract the fields of a simple aggregate type. +template +struct Extractable { + static_assert(std::is_aggregate_v, "Unsupported child type"); + static auto ExtractImpl(NodeExtractor& extractor) -> std::optional { + // Compute the corresponding tuple type. + using TupleType = decltype(StructReflection::AsTuple(std::declval())); + return extractor.ExtractTupleLikeType( + std::make_index_sequence>(), + static_cast(nullptr)); + } + + static auto Extract(NodeExtractor& extractor) -> std::optional { + static_assert(!HasKindMember, "Missing Id suffix"); + return ExtractImpl(extractor); + } +}; + +template +auto TreeAndSubtrees::TryExtractNodeFromChildren( + NodeId node_id, + llvm::iterator_range children, + ErrorBuilder* trace) const -> std::optional { + NodeExtractor extractor(this, tokens_, trace, node_id, children); + auto result = Extractable::ExtractImpl(extractor); + if (!extractor.at_end()) { + if (trace) { + *trace << "Error: " << tree_->node_kind(extractor.ExtractNode()) + << " node left unconsumed."; + } + return std::nullopt; + } + return result; +} + +} // namespace Carbon::Parse + +#endif // CARBON_TOOLCHAIN_PARSE_EXTRACT_H_ diff --git a/toolchain/parse/extract_declarations.cpp b/toolchain/parse/extract_declarations.cpp new file mode 100644 index 000000000000..69fb1a5d1ff9 --- /dev/null +++ b/toolchain/parse/extract_declarations.cpp @@ -0,0 +1,17 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include "toolchain/parse/extract.h" + +namespace Carbon::Parse { + +#define CARBON_PARSE_NODE_KIND(KindName) +#define CARBON_PARSE_NODE_KIND_DECLARATION(KindName) \ + template auto TreeAndSubtrees::TryExtractNodeFromChildren( \ + NodeId node_id, \ + llvm::iterator_range children, \ + ErrorBuilder * trace) const -> std::optional; +#include "toolchain/parse/node_kind.def" + +} // namespace Carbon::Parse diff --git a/toolchain/parse/extract_expressions.cpp b/toolchain/parse/extract_expressions.cpp new file mode 100644 index 000000000000..84d539301008 --- /dev/null +++ b/toolchain/parse/extract_expressions.cpp @@ -0,0 +1,17 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include "toolchain/parse/extract.h" + +namespace Carbon::Parse { + +#define CARBON_PARSE_NODE_KIND(KindName) +#define CARBON_PARSE_NODE_KIND_EXPRESSION(KindName) \ + template auto TreeAndSubtrees::TryExtractNodeFromChildren( \ + NodeId node_id, \ + llvm::iterator_range children, \ + ErrorBuilder * trace) const -> std::optional; +#include "toolchain/parse/node_kind.def" + +} // namespace Carbon::Parse diff --git a/toolchain/parse/extract_patterns.cpp b/toolchain/parse/extract_patterns.cpp new file mode 100644 index 000000000000..4d91d16944d6 --- /dev/null +++ b/toolchain/parse/extract_patterns.cpp @@ -0,0 +1,17 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include "toolchain/parse/extract.h" + +namespace Carbon::Parse { + +#define CARBON_PARSE_NODE_KIND(KindName) +#define CARBON_PARSE_NODE_KIND_PATTERN(KindName) \ + template auto TreeAndSubtrees::TryExtractNodeFromChildren( \ + NodeId node_id, \ + llvm::iterator_range children, \ + ErrorBuilder * trace) const -> std::optional; +#include "toolchain/parse/node_kind.def" + +} // namespace Carbon::Parse diff --git a/toolchain/parse/extract_statements.cpp b/toolchain/parse/extract_statements.cpp new file mode 100644 index 000000000000..b01711f826b0 --- /dev/null +++ b/toolchain/parse/extract_statements.cpp @@ -0,0 +1,17 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include "toolchain/parse/extract.h" + +namespace Carbon::Parse { + +#define CARBON_PARSE_NODE_KIND(KindName) +#define CARBON_PARSE_NODE_KIND_STATEMENT(KindName) \ + template auto TreeAndSubtrees::TryExtractNodeFromChildren( \ + NodeId node_id, \ + llvm::iterator_range children, \ + ErrorBuilder * trace) const -> std::optional; +#include "toolchain/parse/node_kind.def" + +} // namespace Carbon::Parse diff --git a/toolchain/parse/node_kind.def b/toolchain/parse/node_kind.def index 320d3af476a3..735d7c5bad8e 100644 --- a/toolchain/parse/node_kind.def +++ b/toolchain/parse/node_kind.def @@ -2,8 +2,8 @@ // Exceptions. See /LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // -// This is an X-macro header. It does not use `#include` guards, and instead is -// designed to be `#include`ed after the x-macro is defined in order for its +// This is an X-macro header. It does not use guards, and instead is +// designed to be ed after the x-macro is defined in order for its // inclusion to expand to the desired output. Macro definitions are cleaned up // at the end of this file. // @@ -11,6 +11,14 @@ // - CARBON_PARSE_NODE_KIND(Name) // Used as a fallback if other macros are missing. Also, used directly // when none of the below category-oriented macros apply. +// - CARBON_PARSE_NODE_KIND_DECLARATION(Name) +// Defines a parse node for a declaration or namespace structure. +// - CARBON_PARSE_NODE_KIND_EXPRESSION(Name) +// Defines a parse node for an expression, literal, or operator. +// - CARBON_PARSE_NODE_KIND_PATTERN(Name) +// Defines a parse node for a pattern, parameter list, binding, or modifier. +// - CARBON_PARSE_NODE_KIND_STATEMENT(Name) +// Defines a parse node for a statement or control-flow construct. // - CARBON_PARSE_NODE_KIND_PREFIX_OPERATOR(Name) // Defines a parse node for a prefix operator, with the Name as token. // - CARBON_PARSE_NODE_KIND_INFIX_OPERATOR(Name) @@ -36,32 +44,68 @@ // This is expected to be used with something like: // -// // Use x-macros to handle modifier cases. +// // Use x-macros to handle declaration cases. +// #define CARBON_PARSE_NODE_KIND(Name) +// #define CARBON_PARSE_NODE_KIND_DECLARATION(Name) +#ifndef CARBON_PARSE_NODE_KIND_DECLARATION +#define CARBON_PARSE_NODE_KIND_DECLARATION(Name) CARBON_PARSE_NODE_KIND(Name) +#endif + +// This is expected to be used with something like: +// +// // Use x-macros to handle expression cases. +// #define CARBON_PARSE_NODE_KIND(Name) +// #define CARBON_PARSE_NODE_KIND_EXPRESSION(Name) +#ifndef CARBON_PARSE_NODE_KIND_EXPRESSION +#define CARBON_PARSE_NODE_KIND_EXPRESSION(Name) CARBON_PARSE_NODE_KIND(Name) +#endif + +// This is expected to be used with something like: +// +// // Use x-macros to handle pattern cases. +// #define CARBON_PARSE_NODE_KIND(Name) +// #define CARBON_PARSE_NODE_KIND_PATTERN(Name) +#ifndef CARBON_PARSE_NODE_KIND_PATTERN +#define CARBON_PARSE_NODE_KIND_PATTERN(Name) CARBON_PARSE_NODE_KIND(Name) +#endif + +// This is expected to be used with something like: +// +// // Use x-macros to handle statement cases. +// #define CARBON_PARSE_NODE_KIND(Name) +// #define CARBON_PARSE_NODE_KIND_STATEMENT(Name) +#ifndef CARBON_PARSE_NODE_KIND_STATEMENT +#define CARBON_PARSE_NODE_KIND_STATEMENT(Name) CARBON_PARSE_NODE_KIND(Name) +#endif + +// This is expected to be used with something like: +// +// // Use x-macros to handle prefix operator cases. // #define CARBON_PARSE_NODE_KIND(Name) // #define CARBON_PARSE_NODE_KIND_PREFIX_OPERATOR(Name) #ifndef CARBON_PARSE_NODE_KIND_PREFIX_OPERATOR #define CARBON_PARSE_NODE_KIND_PREFIX_OPERATOR(Name) \ - CARBON_PARSE_NODE_KIND(PrefixOperator##Name) + CARBON_PARSE_NODE_KIND_EXPRESSION(PrefixOperator##Name) #endif // This is expected to be used with something like: // -// // Use x-macros to handle modifier cases. +// // Use x-macros to handle infix operator cases. // #define CARBON_PARSE_NODE_KIND(Name) // #define CARBON_PARSE_NODE_KIND_INFIX_OPERATOR(Name) #ifndef CARBON_PARSE_NODE_KIND_INFIX_OPERATOR #define CARBON_PARSE_NODE_KIND_INFIX_OPERATOR(Name) \ - CARBON_PARSE_NODE_KIND(InfixOperator##Name) + CARBON_PARSE_NODE_KIND_EXPRESSION(InfixOperator##Name) #endif // This is expected to be used with something like: // -// // Use x-macros to handle modifier cases. +// // Use x-macros to handle postfix operator cases. // #define CARBON_PARSE_NODE_KIND(Name) // #define CARBON_PARSE_NODE_KIND_POSTFIX_OPERATOR(Name) #ifndef CARBON_PARSE_NODE_KIND_POSTFIX_OPERATOR #define CARBON_PARSE_NODE_KIND_POSTFIX_OPERATOR(Name) \ - CARBON_PARSE_NODE_KIND(PostfixOperator##Name) + CARBON_PARSE_NODE_KIND_EXPRESSION(PostfixOperator##Name) #endif // This is expected to be used with something like: @@ -71,7 +115,7 @@ // #define CARBON_PARSE_NODE_KIND_TOKEN_LITERAL(Name, LexTokenKind) #ifndef CARBON_PARSE_NODE_KIND_TOKEN_LITERAL #define CARBON_PARSE_NODE_KIND_TOKEN_LITERAL(Name, LexTokenKind) \ - CARBON_PARSE_NODE_KIND(Name) + CARBON_PARSE_NODE_KIND_EXPRESSION(Name) #endif // This is expected to be used with something like: @@ -81,189 +125,189 @@ // #define CARBON_PARSE_NODE_KIND_TOKEN_MODIFIER(Name) #ifndef CARBON_PARSE_NODE_KIND_TOKEN_MODIFIER #define CARBON_PARSE_NODE_KIND_TOKEN_MODIFIER(Name) \ - CARBON_PARSE_NODE_KIND(Name##Modifier) + CARBON_PARSE_NODE_KIND_PATTERN(Name##Modifier) #endif -CARBON_PARSE_NODE_KIND(FileStart) -CARBON_PARSE_NODE_KIND(FileEnd) +CARBON_PARSE_NODE_KIND_DECLARATION(FileStart) +CARBON_PARSE_NODE_KIND_DECLARATION(FileEnd) -CARBON_PARSE_NODE_KIND(InvalidParse) -CARBON_PARSE_NODE_KIND(InvalidParseStart) -CARBON_PARSE_NODE_KIND(InvalidParseSubtree) +CARBON_PARSE_NODE_KIND_DECLARATION(InvalidParse) +CARBON_PARSE_NODE_KIND_DECLARATION(InvalidParseStart) +CARBON_PARSE_NODE_KIND_DECLARATION(InvalidParseSubtree) -CARBON_PARSE_NODE_KIND(Placeholder) +CARBON_PARSE_NODE_KIND_DECLARATION(Placeholder) -CARBON_PARSE_NODE_KIND(EmptyDecl) +CARBON_PARSE_NODE_KIND_DECLARATION(EmptyDecl) -CARBON_PARSE_NODE_KIND(IdentifierNameNotBeforeSignature) -CARBON_PARSE_NODE_KIND(IdentifierNameMaybeBeforeSignature) +CARBON_PARSE_NODE_KIND_DECLARATION(IdentifierNameNotBeforeSignature) +CARBON_PARSE_NODE_KIND_DECLARATION(IdentifierNameMaybeBeforeSignature) -CARBON_PARSE_NODE_KIND(IdentifierNameExpr) +CARBON_PARSE_NODE_KIND_DECLARATION(IdentifierNameExpr) -CARBON_PARSE_NODE_KIND(SelfValueName) -CARBON_PARSE_NODE_KIND(SelfValueNameExpr) -CARBON_PARSE_NODE_KIND(SelfTypeNameExpr) +CARBON_PARSE_NODE_KIND_DECLARATION(SelfValueName) +CARBON_PARSE_NODE_KIND_DECLARATION(SelfValueNameExpr) +CARBON_PARSE_NODE_KIND_DECLARATION(SelfTypeNameExpr) -CARBON_PARSE_NODE_KIND(UnderscoreName) +CARBON_PARSE_NODE_KIND_DECLARATION(UnderscoreName) -CARBON_PARSE_NODE_KIND(BaseName) -CARBON_PARSE_NODE_KIND(PackageExpr) -CARBON_PARSE_NODE_KIND(CoreNameExpr) -CARBON_PARSE_NODE_KIND(CppNameExpr) -CARBON_PARSE_NODE_KIND(IdentifierPackageName) -CARBON_PARSE_NODE_KIND(CorePackageName) -CARBON_PARSE_NODE_KIND(CppPackageName) -CARBON_PARSE_NODE_KIND(LibraryName) +CARBON_PARSE_NODE_KIND_DECLARATION(BaseName) +CARBON_PARSE_NODE_KIND_DECLARATION(PackageExpr) +CARBON_PARSE_NODE_KIND_DECLARATION(CoreNameExpr) +CARBON_PARSE_NODE_KIND_DECLARATION(CppNameExpr) +CARBON_PARSE_NODE_KIND_DECLARATION(IdentifierPackageName) +CARBON_PARSE_NODE_KIND_DECLARATION(CorePackageName) +CARBON_PARSE_NODE_KIND_DECLARATION(CppPackageName) +CARBON_PARSE_NODE_KIND_DECLARATION(LibraryName) -CARBON_PARSE_NODE_KIND(PackageIntroducer) -CARBON_PARSE_NODE_KIND(PackageDecl) +CARBON_PARSE_NODE_KIND_DECLARATION(PackageIntroducer) +CARBON_PARSE_NODE_KIND_DECLARATION(PackageDecl) -CARBON_PARSE_NODE_KIND(ImportIntroducer) -CARBON_PARSE_NODE_KIND(ImportDecl) +CARBON_PARSE_NODE_KIND_DECLARATION(ImportIntroducer) +CARBON_PARSE_NODE_KIND_DECLARATION(ImportDecl) -CARBON_PARSE_NODE_KIND(DefaultLibrary) -CARBON_PARSE_NODE_KIND(LibraryIntroducer) -CARBON_PARSE_NODE_KIND(LibraryDecl) +CARBON_PARSE_NODE_KIND_DECLARATION(DefaultLibrary) +CARBON_PARSE_NODE_KIND_DECLARATION(LibraryIntroducer) +CARBON_PARSE_NODE_KIND_DECLARATION(LibraryDecl) -CARBON_PARSE_NODE_KIND(LibrarySpecifier) +CARBON_PARSE_NODE_KIND_DECLARATION(LibrarySpecifier) -CARBON_PARSE_NODE_KIND(InlineImportSpecifier) -CARBON_PARSE_NODE_KIND(InlineImportBody) +CARBON_PARSE_NODE_KIND_DECLARATION(InlineImportSpecifier) +CARBON_PARSE_NODE_KIND_DECLARATION(InlineImportBody) -CARBON_PARSE_NODE_KIND(InlineIntroducer) -CARBON_PARSE_NODE_KIND(InlineCppDecl) +CARBON_PARSE_NODE_KIND_DECLARATION(InlineIntroducer) +CARBON_PARSE_NODE_KIND_DECLARATION(InlineCppDecl) -CARBON_PARSE_NODE_KIND(IdentifierNameQualifierWithParams) -CARBON_PARSE_NODE_KIND(IdentifierNameQualifierWithoutParams) +CARBON_PARSE_NODE_KIND_DECLARATION(IdentifierNameQualifierWithParams) +CARBON_PARSE_NODE_KIND_DECLARATION(IdentifierNameQualifierWithoutParams) -CARBON_PARSE_NODE_KIND(ExportIntroducer) -CARBON_PARSE_NODE_KIND(ExportDecl) +CARBON_PARSE_NODE_KIND_DECLARATION(ExportIntroducer) +CARBON_PARSE_NODE_KIND_DECLARATION(ExportDecl) -CARBON_PARSE_NODE_KIND(NamespaceStart) -CARBON_PARSE_NODE_KIND(Namespace) +CARBON_PARSE_NODE_KIND_DECLARATION(NamespaceStart) +CARBON_PARSE_NODE_KIND_DECLARATION(Namespace) -CARBON_PARSE_NODE_KIND(MatchFirstIntroducer) -CARBON_PARSE_NODE_KIND(MatchFirstDefinitionStart) -CARBON_PARSE_NODE_KIND(MatchFirst) +CARBON_PARSE_NODE_KIND_STATEMENT(MatchFirstIntroducer) +CARBON_PARSE_NODE_KIND_STATEMENT(MatchFirstDefinitionStart) +CARBON_PARSE_NODE_KIND_STATEMENT(MatchFirst) -CARBON_PARSE_NODE_KIND(CodeBlockStart) -CARBON_PARSE_NODE_KIND(CodeBlock) +CARBON_PARSE_NODE_KIND_STATEMENT(CodeBlockStart) +CARBON_PARSE_NODE_KIND_STATEMENT(CodeBlock) -CARBON_PARSE_NODE_KIND(FunctionIntroducer) -CARBON_PARSE_NODE_KIND(LambdaIntroducer) -CARBON_PARSE_NODE_KIND(ReturnType) -CARBON_PARSE_NODE_KIND(ReturnForm) -CARBON_PARSE_NODE_KIND(FunctionDefinitionStart) -CARBON_PARSE_NODE_KIND(FunctionDefinition) -CARBON_PARSE_NODE_KIND(FunctionTerseDefinition) -CARBON_PARSE_NODE_KIND(FunctionDecl) -CARBON_PARSE_NODE_KIND(Lambda) -CARBON_PARSE_NODE_KIND(TerseBodyArrow) -CARBON_PARSE_NODE_KIND(BuiltinFunctionDefinitionStart) -CARBON_PARSE_NODE_KIND(BuiltinName) -CARBON_PARSE_NODE_KIND(BuiltinFunctionDefinition) +CARBON_PARSE_NODE_KIND_DECLARATION(FunctionIntroducer) +CARBON_PARSE_NODE_KIND_DECLARATION(LambdaIntroducer) +CARBON_PARSE_NODE_KIND_DECLARATION(ReturnType) +CARBON_PARSE_NODE_KIND_DECLARATION(ReturnForm) +CARBON_PARSE_NODE_KIND_DECLARATION(FunctionDefinitionStart) +CARBON_PARSE_NODE_KIND_DECLARATION(FunctionDefinition) +CARBON_PARSE_NODE_KIND_DECLARATION(FunctionTerseDefinition) +CARBON_PARSE_NODE_KIND_DECLARATION(FunctionDecl) +CARBON_PARSE_NODE_KIND_DECLARATION(Lambda) +CARBON_PARSE_NODE_KIND_DECLARATION(TerseBodyArrow) +CARBON_PARSE_NODE_KIND_DECLARATION(BuiltinFunctionDefinitionStart) +CARBON_PARSE_NODE_KIND_DECLARATION(BuiltinName) +CARBON_PARSE_NODE_KIND_DECLARATION(BuiltinFunctionDefinition) -CARBON_PARSE_NODE_KIND(AliasIntroducer) -CARBON_PARSE_NODE_KIND(AliasInitializer) -CARBON_PARSE_NODE_KIND(Alias) +CARBON_PARSE_NODE_KIND_DECLARATION(AliasIntroducer) +CARBON_PARSE_NODE_KIND_DECLARATION(AliasInitializer) +CARBON_PARSE_NODE_KIND_DECLARATION(Alias) -CARBON_PARSE_NODE_KIND(TuplePatternStart) -CARBON_PARSE_NODE_KIND(PatternListComma) -CARBON_PARSE_NODE_KIND(ParenPattern) -CARBON_PARSE_NODE_KIND(TuplePattern) +CARBON_PARSE_NODE_KIND_PATTERN(TuplePatternStart) +CARBON_PARSE_NODE_KIND_PATTERN(PatternListComma) +CARBON_PARSE_NODE_KIND_PATTERN(ParenPattern) +CARBON_PARSE_NODE_KIND_PATTERN(TuplePattern) -CARBON_PARSE_NODE_KIND(StructPatternStart) -CARBON_PARSE_NODE_KIND(StructPatternDesignatedField) -CARBON_PARSE_NODE_KIND(StructPattern) +CARBON_PARSE_NODE_KIND_PATTERN(StructPatternStart) +CARBON_PARSE_NODE_KIND_PATTERN(StructPatternDesignatedField) +CARBON_PARSE_NODE_KIND_PATTERN(StructPattern) -CARBON_PARSE_NODE_KIND(ExplicitParamListStart) -CARBON_PARSE_NODE_KIND(ExplicitParamList) -CARBON_PARSE_NODE_KIND(ImplicitParamListStart) -CARBON_PARSE_NODE_KIND(ImplicitParamList) +CARBON_PARSE_NODE_KIND_PATTERN(ExplicitParamListStart) +CARBON_PARSE_NODE_KIND_PATTERN(ExplicitParamList) +CARBON_PARSE_NODE_KIND_PATTERN(ImplicitParamListStart) +CARBON_PARSE_NODE_KIND_PATTERN(ImplicitParamList) -CARBON_PARSE_NODE_KIND(ArrayExprOpenParen) -CARBON_PARSE_NODE_KIND(ArrayExprKeyword) -CARBON_PARSE_NODE_KIND(ArrayExprComma) -CARBON_PARSE_NODE_KIND(ArrayExpr) +CARBON_PARSE_NODE_KIND_EXPRESSION(ArrayExprOpenParen) +CARBON_PARSE_NODE_KIND_EXPRESSION(ArrayExprKeyword) +CARBON_PARSE_NODE_KIND_EXPRESSION(ArrayExprComma) +CARBON_PARSE_NODE_KIND_EXPRESSION(ArrayExpr) -CARBON_PARSE_NODE_KIND(RefBindingName) -CARBON_PARSE_NODE_KIND(RuntimeBindingName) -CARBON_PARSE_NODE_KIND(UnusedPattern) -CARBON_PARSE_NODE_KIND(BindingPatternTypeStart) -CARBON_PARSE_NODE_KIND(LetBindingPattern) -CARBON_PARSE_NODE_KIND(SelfBindingPattern) -CARBON_PARSE_NODE_KIND(AssociatedConstantNameAndType) -CARBON_PARSE_NODE_KIND(VarBindingPattern) -CARBON_PARSE_NODE_KIND(FormBindingPattern) -CARBON_PARSE_NODE_KIND(TemplateBindingName) -CARBON_PARSE_NODE_KIND(CompileTimeBindingPatternTypeStart) -CARBON_PARSE_NODE_KIND(CompileTimeBindingPattern) +CARBON_PARSE_NODE_KIND_PATTERN(RefBindingName) +CARBON_PARSE_NODE_KIND_PATTERN(RuntimeBindingName) +CARBON_PARSE_NODE_KIND_PATTERN(UnusedPattern) +CARBON_PARSE_NODE_KIND_PATTERN(BindingPatternTypeStart) +CARBON_PARSE_NODE_KIND_PATTERN(LetBindingPattern) +CARBON_PARSE_NODE_KIND_PATTERN(SelfBindingPattern) +CARBON_PARSE_NODE_KIND_PATTERN(AssociatedConstantNameAndType) +CARBON_PARSE_NODE_KIND_PATTERN(VarBindingPattern) +CARBON_PARSE_NODE_KIND_PATTERN(FormBindingPattern) +CARBON_PARSE_NODE_KIND_PATTERN(TemplateBindingName) +CARBON_PARSE_NODE_KIND_PATTERN(CompileTimeBindingPatternTypeStart) +CARBON_PARSE_NODE_KIND_PATTERN(CompileTimeBindingPattern) -CARBON_PARSE_NODE_KIND(LetIntroducer) -CARBON_PARSE_NODE_KIND(LetInitializer) -CARBON_PARSE_NODE_KIND(LetDecl) +CARBON_PARSE_NODE_KIND_DECLARATION(LetIntroducer) +CARBON_PARSE_NODE_KIND_DECLARATION(LetInitializer) +CARBON_PARSE_NODE_KIND_DECLARATION(LetDecl) -CARBON_PARSE_NODE_KIND(AssociatedConstantIntroducer) -CARBON_PARSE_NODE_KIND(AssociatedConstantInitializer) -CARBON_PARSE_NODE_KIND(AssociatedConstantDecl) +CARBON_PARSE_NODE_KIND_DECLARATION(AssociatedConstantIntroducer) +CARBON_PARSE_NODE_KIND_DECLARATION(AssociatedConstantInitializer) +CARBON_PARSE_NODE_KIND_DECLARATION(AssociatedConstantDecl) -CARBON_PARSE_NODE_KIND(VariableIntroducer) -CARBON_PARSE_NODE_KIND(ReturnedModifier) -CARBON_PARSE_NODE_KIND(VariableInitializer) -CARBON_PARSE_NODE_KIND(VariableDecl) -CARBON_PARSE_NODE_KIND(VariablePattern) +CARBON_PARSE_NODE_KIND_DECLARATION(VariableIntroducer) +CARBON_PARSE_NODE_KIND_PATTERN(ReturnedModifier) +CARBON_PARSE_NODE_KIND_DECLARATION(VariableInitializer) +CARBON_PARSE_NODE_KIND_DECLARATION(VariableDecl) +CARBON_PARSE_NODE_KIND_PATTERN(VariablePattern) -CARBON_PARSE_NODE_KIND(ExprStatement) +CARBON_PARSE_NODE_KIND_STATEMENT(ExprStatement) -CARBON_PARSE_NODE_KIND(BreakStatementStart) -CARBON_PARSE_NODE_KIND(BreakStatement) +CARBON_PARSE_NODE_KIND_STATEMENT(BreakStatementStart) +CARBON_PARSE_NODE_KIND_STATEMENT(BreakStatement) -CARBON_PARSE_NODE_KIND(ContinueStatementStart) -CARBON_PARSE_NODE_KIND(ContinueStatement) +CARBON_PARSE_NODE_KIND_STATEMENT(ContinueStatementStart) +CARBON_PARSE_NODE_KIND_STATEMENT(ContinueStatement) -CARBON_PARSE_NODE_KIND(ReturnStatementStart) -CARBON_PARSE_NODE_KIND(ReturnVarModifier) -CARBON_PARSE_NODE_KIND(ReturnStatement) +CARBON_PARSE_NODE_KIND_STATEMENT(ReturnStatementStart) +CARBON_PARSE_NODE_KIND_STATEMENT(ReturnVarModifier) +CARBON_PARSE_NODE_KIND_STATEMENT(ReturnStatement) -CARBON_PARSE_NODE_KIND(ForHeaderStart) -CARBON_PARSE_NODE_KIND(ForIn) -CARBON_PARSE_NODE_KIND(ForHeader) -CARBON_PARSE_NODE_KIND(ForStatement) +CARBON_PARSE_NODE_KIND_STATEMENT(ForHeaderStart) +CARBON_PARSE_NODE_KIND_STATEMENT(ForIn) +CARBON_PARSE_NODE_KIND_STATEMENT(ForHeader) +CARBON_PARSE_NODE_KIND_STATEMENT(ForStatement) -CARBON_PARSE_NODE_KIND(IfConditionStart) -CARBON_PARSE_NODE_KIND(IfCondition) -CARBON_PARSE_NODE_KIND(IfStatementElse) -CARBON_PARSE_NODE_KIND(IfStatement) +CARBON_PARSE_NODE_KIND_STATEMENT(IfConditionStart) +CARBON_PARSE_NODE_KIND_STATEMENT(IfCondition) +CARBON_PARSE_NODE_KIND_STATEMENT(IfStatementElse) +CARBON_PARSE_NODE_KIND_STATEMENT(IfStatement) -CARBON_PARSE_NODE_KIND(WhileConditionStart) -CARBON_PARSE_NODE_KIND(WhileCondition) -CARBON_PARSE_NODE_KIND(WhileStatement) +CARBON_PARSE_NODE_KIND_STATEMENT(WhileConditionStart) +CARBON_PARSE_NODE_KIND_STATEMENT(WhileCondition) +CARBON_PARSE_NODE_KIND_STATEMENT(WhileStatement) -CARBON_PARSE_NODE_KIND(IndexExprStart) -CARBON_PARSE_NODE_KIND(IndexExpr) +CARBON_PARSE_NODE_KIND_EXPRESSION(IndexExprStart) +CARBON_PARSE_NODE_KIND_EXPRESSION(IndexExpr) -CARBON_PARSE_NODE_KIND(RefPrimitiveForm) -CARBON_PARSE_NODE_KIND(VarPrimitiveForm) -CARBON_PARSE_NODE_KIND(ValPrimitiveForm) -CARBON_PARSE_NODE_KIND(FormLiteralKeyword) -CARBON_PARSE_NODE_KIND(FormLiteralOpenParen) -CARBON_PARSE_NODE_KIND(FormLiteral) +CARBON_PARSE_NODE_KIND_EXPRESSION(RefPrimitiveForm) +CARBON_PARSE_NODE_KIND_EXPRESSION(VarPrimitiveForm) +CARBON_PARSE_NODE_KIND_EXPRESSION(ValPrimitiveForm) +CARBON_PARSE_NODE_KIND_EXPRESSION(FormLiteralKeyword) +CARBON_PARSE_NODE_KIND_EXPRESSION(FormLiteralOpenParen) +CARBON_PARSE_NODE_KIND_EXPRESSION(FormLiteral) -CARBON_PARSE_NODE_KIND(ParenExprStart) -CARBON_PARSE_NODE_KIND(ParenExpr) +CARBON_PARSE_NODE_KIND_EXPRESSION(ParenExprStart) +CARBON_PARSE_NODE_KIND_EXPRESSION(ParenExpr) -CARBON_PARSE_NODE_KIND(TupleLiteralStart) -CARBON_PARSE_NODE_KIND(TupleLiteralComma) -CARBON_PARSE_NODE_KIND(TupleLiteral) +CARBON_PARSE_NODE_KIND_EXPRESSION(TupleLiteralStart) +CARBON_PARSE_NODE_KIND_EXPRESSION(TupleLiteralComma) +CARBON_PARSE_NODE_KIND_EXPRESSION(TupleLiteral) -CARBON_PARSE_NODE_KIND(CallExprStart) -CARBON_PARSE_NODE_KIND(CallExpr) +CARBON_PARSE_NODE_KIND_EXPRESSION(CallExprStart) +CARBON_PARSE_NODE_KIND_EXPRESSION(CallExpr) -CARBON_PARSE_NODE_KIND(MemberAccessExpr) +CARBON_PARSE_NODE_KIND_EXPRESSION(MemberAccessExpr) -CARBON_PARSE_NODE_KIND(PointerMemberAccessExpr) +CARBON_PARSE_NODE_KIND_EXPRESSION(PointerMemberAccessExpr) -CARBON_PARSE_NODE_KIND(IntLiteral) +CARBON_PARSE_NODE_KIND_EXPRESSION(IntLiteral) CARBON_PARSE_NODE_KIND_TOKEN_LITERAL(BoolLiteralFalse, False) CARBON_PARSE_NODE_KIND_TOKEN_LITERAL(BoolLiteralTrue, True) @@ -324,40 +368,40 @@ CARBON_PARSE_NODE_KIND_INFIX_OPERATOR(StarEqual) CARBON_PARSE_NODE_KIND_POSTFIX_OPERATOR(Star) -CARBON_PARSE_NODE_KIND(ShortCircuitOperandAnd) -CARBON_PARSE_NODE_KIND(ShortCircuitOperandOr) -CARBON_PARSE_NODE_KIND(ShortCircuitOperatorAnd) -CARBON_PARSE_NODE_KIND(ShortCircuitOperatorOr) +CARBON_PARSE_NODE_KIND_EXPRESSION(ShortCircuitOperandAnd) +CARBON_PARSE_NODE_KIND_EXPRESSION(ShortCircuitOperandOr) +CARBON_PARSE_NODE_KIND_EXPRESSION(ShortCircuitOperatorAnd) +CARBON_PARSE_NODE_KIND_EXPRESSION(ShortCircuitOperatorOr) -CARBON_PARSE_NODE_KIND(UnsafeModifier) +CARBON_PARSE_NODE_KIND_PATTERN(UnsafeModifier) -CARBON_PARSE_NODE_KIND(DesignatorExpr) -CARBON_PARSE_NODE_KIND(SelfTypeName) -CARBON_PARSE_NODE_KIND(RequirementAnd) -CARBON_PARSE_NODE_KIND(RequirementEqual) -CARBON_PARSE_NODE_KIND(RequirementEqualEqual) -CARBON_PARSE_NODE_KIND(RequirementImpls) -CARBON_PARSE_NODE_KIND(WhereExpr) -CARBON_PARSE_NODE_KIND(WhereOperand) +CARBON_PARSE_NODE_KIND_EXPRESSION(DesignatorExpr) +CARBON_PARSE_NODE_KIND_EXPRESSION(SelfTypeName) +CARBON_PARSE_NODE_KIND_EXPRESSION(RequirementAnd) +CARBON_PARSE_NODE_KIND_EXPRESSION(RequirementEqual) +CARBON_PARSE_NODE_KIND_EXPRESSION(RequirementEqualEqual) +CARBON_PARSE_NODE_KIND_EXPRESSION(RequirementImpls) +CARBON_PARSE_NODE_KIND_EXPRESSION(WhereExpr) +CARBON_PARSE_NODE_KIND_EXPRESSION(WhereOperand) -CARBON_PARSE_NODE_KIND(IfExprIf) -CARBON_PARSE_NODE_KIND(IfExprThen) -CARBON_PARSE_NODE_KIND(IfExprElse) +CARBON_PARSE_NODE_KIND_EXPRESSION(IfExprIf) +CARBON_PARSE_NODE_KIND_EXPRESSION(IfExprThen) +CARBON_PARSE_NODE_KIND_EXPRESSION(IfExprElse) -CARBON_PARSE_NODE_KIND(StructFieldDesignator) +CARBON_PARSE_NODE_KIND_EXPRESSION(StructFieldDesignator) -CARBON_PARSE_NODE_KIND(StructLiteralStart) -CARBON_PARSE_NODE_KIND(StructLiteralField) -CARBON_PARSE_NODE_KIND(StructLiteralComma) -CARBON_PARSE_NODE_KIND(StructLiteral) +CARBON_PARSE_NODE_KIND_EXPRESSION(StructLiteralStart) +CARBON_PARSE_NODE_KIND_EXPRESSION(StructLiteralField) +CARBON_PARSE_NODE_KIND_EXPRESSION(StructLiteralComma) +CARBON_PARSE_NODE_KIND_EXPRESSION(StructLiteral) -CARBON_PARSE_NODE_KIND(StructTypeLiteralStart) -CARBON_PARSE_NODE_KIND(StructTypeLiteralField) -CARBON_PARSE_NODE_KIND(StructTypeLiteralComma) -CARBON_PARSE_NODE_KIND(StructTypeLiteral) +CARBON_PARSE_NODE_KIND_EXPRESSION(StructTypeLiteralStart) +CARBON_PARSE_NODE_KIND_EXPRESSION(StructTypeLiteralField) +CARBON_PARSE_NODE_KIND_EXPRESSION(StructTypeLiteralComma) +CARBON_PARSE_NODE_KIND_EXPRESSION(StructTypeLiteral) -CARBON_PARSE_NODE_KIND(ExternModifierWithLibrary) -CARBON_PARSE_NODE_KIND(ExternModifier) +CARBON_PARSE_NODE_KIND_PATTERN(ExternModifierWithLibrary) +CARBON_PARSE_NODE_KIND_PATTERN(ExternModifier) CARBON_PARSE_NODE_KIND_TOKEN_MODIFIER(Abstract) CARBON_PARSE_NODE_KIND_TOKEN_MODIFIER(Base) @@ -374,67 +418,71 @@ CARBON_PARSE_NODE_KIND_TOKEN_MODIFIER(Protected) CARBON_PARSE_NODE_KIND_TOKEN_MODIFIER(Static) CARBON_PARSE_NODE_KIND_TOKEN_MODIFIER(Virtual) -CARBON_PARSE_NODE_KIND(ClassIntroducer) -CARBON_PARSE_NODE_KIND(ClassDefinitionStart) -CARBON_PARSE_NODE_KIND(ClassDefinition) -CARBON_PARSE_NODE_KIND(ClassDecl) +CARBON_PARSE_NODE_KIND_DECLARATION(ClassIntroducer) +CARBON_PARSE_NODE_KIND_DECLARATION(ClassDefinitionStart) +CARBON_PARSE_NODE_KIND_DECLARATION(ClassDefinition) +CARBON_PARSE_NODE_KIND_DECLARATION(ClassDecl) -CARBON_PARSE_NODE_KIND(AdaptIntroducer) -CARBON_PARSE_NODE_KIND(AdaptDecl) +CARBON_PARSE_NODE_KIND_DECLARATION(AdaptIntroducer) +CARBON_PARSE_NODE_KIND_DECLARATION(AdaptDecl) -CARBON_PARSE_NODE_KIND(BaseIntroducer) -CARBON_PARSE_NODE_KIND(BaseColon) -CARBON_PARSE_NODE_KIND(BaseDecl) +CARBON_PARSE_NODE_KIND_DECLARATION(BaseIntroducer) +CARBON_PARSE_NODE_KIND_DECLARATION(BaseColon) +CARBON_PARSE_NODE_KIND_DECLARATION(BaseDecl) -CARBON_PARSE_NODE_KIND(InterfaceIntroducer) -CARBON_PARSE_NODE_KIND(InterfaceDefinitionStart) -CARBON_PARSE_NODE_KIND(InterfaceDefinition) -CARBON_PARSE_NODE_KIND(InterfaceDecl) +CARBON_PARSE_NODE_KIND_DECLARATION(InterfaceIntroducer) +CARBON_PARSE_NODE_KIND_DECLARATION(InterfaceDefinitionStart) +CARBON_PARSE_NODE_KIND_DECLARATION(InterfaceDefinition) +CARBON_PARSE_NODE_KIND_DECLARATION(InterfaceDecl) -CARBON_PARSE_NODE_KIND(ImplIntroducer) -CARBON_PARSE_NODE_KIND(ImplDefinitionStart) -CARBON_PARSE_NODE_KIND(ImplDefinition) -CARBON_PARSE_NODE_KIND(ImplDecl) -CARBON_PARSE_NODE_KIND(Forall) -CARBON_PARSE_NODE_KIND(ImplTypeAs) -CARBON_PARSE_NODE_KIND(ImplDefaultSelfAs) +CARBON_PARSE_NODE_KIND_DECLARATION(ImplIntroducer) +CARBON_PARSE_NODE_KIND_DECLARATION(ImplDefinitionStart) +CARBON_PARSE_NODE_KIND_DECLARATION(ImplDefinition) +CARBON_PARSE_NODE_KIND_DECLARATION(ImplDecl) +CARBON_PARSE_NODE_KIND_DECLARATION(Forall) +CARBON_PARSE_NODE_KIND_DECLARATION(ImplTypeAs) +CARBON_PARSE_NODE_KIND_DECLARATION(ImplDefaultSelfAs) -CARBON_PARSE_NODE_KIND(RequireIntroducer) -CARBON_PARSE_NODE_KIND(RequireTypeImpls) -CARBON_PARSE_NODE_KIND(RequireDefaultSelfImpls) -CARBON_PARSE_NODE_KIND(RequireDecl) +CARBON_PARSE_NODE_KIND_DECLARATION(RequireIntroducer) +CARBON_PARSE_NODE_KIND_DECLARATION(RequireTypeImpls) +CARBON_PARSE_NODE_KIND_DECLARATION(RequireDefaultSelfImpls) +CARBON_PARSE_NODE_KIND_DECLARATION(RequireDecl) -CARBON_PARSE_NODE_KIND(ObserveIntroducer) -CARBON_PARSE_NODE_KIND(ObserveEqualEqual) -CARBON_PARSE_NODE_KIND(ObserveImpls) -CARBON_PARSE_NODE_KIND(ObserveDecl) +CARBON_PARSE_NODE_KIND_DECLARATION(ObserveIntroducer) +CARBON_PARSE_NODE_KIND_DECLARATION(ObserveEqualEqual) +CARBON_PARSE_NODE_KIND_DECLARATION(ObserveImpls) +CARBON_PARSE_NODE_KIND_DECLARATION(ObserveDecl) -CARBON_PARSE_NODE_KIND(NamedConstraintIntroducer) -CARBON_PARSE_NODE_KIND(NamedConstraintDefinitionStart) -CARBON_PARSE_NODE_KIND(NamedConstraintDefinition) -CARBON_PARSE_NODE_KIND(NamedConstraintDecl) +CARBON_PARSE_NODE_KIND_DECLARATION(NamedConstraintIntroducer) +CARBON_PARSE_NODE_KIND_DECLARATION(NamedConstraintDefinitionStart) +CARBON_PARSE_NODE_KIND_DECLARATION(NamedConstraintDefinition) +CARBON_PARSE_NODE_KIND_DECLARATION(NamedConstraintDecl) -CARBON_PARSE_NODE_KIND(ChoiceIntroducer) -CARBON_PARSE_NODE_KIND(ChoiceDefinitionStart) -CARBON_PARSE_NODE_KIND(ChoiceDefinition) -CARBON_PARSE_NODE_KIND(ChoiceAlternativeListComma) +CARBON_PARSE_NODE_KIND_DECLARATION(ChoiceIntroducer) +CARBON_PARSE_NODE_KIND_DECLARATION(ChoiceDefinitionStart) +CARBON_PARSE_NODE_KIND_DECLARATION(ChoiceDefinition) +CARBON_PARSE_NODE_KIND_DECLARATION(ChoiceAlternativeListComma) -CARBON_PARSE_NODE_KIND(MatchIntroducer) -CARBON_PARSE_NODE_KIND(MatchConditionStart) -CARBON_PARSE_NODE_KIND(MatchCondition) -CARBON_PARSE_NODE_KIND(MatchStatementStart) -CARBON_PARSE_NODE_KIND(MatchStatement) -CARBON_PARSE_NODE_KIND(MatchCaseIntroducer) -CARBON_PARSE_NODE_KIND(MatchCaseGuardIntroducer) -CARBON_PARSE_NODE_KIND(MatchCaseGuardStart) -CARBON_PARSE_NODE_KIND(MatchCaseGuard) -CARBON_PARSE_NODE_KIND(MatchCase) -CARBON_PARSE_NODE_KIND(MatchDefaultIntroducer) -CARBON_PARSE_NODE_KIND(MatchDefault) -CARBON_PARSE_NODE_KIND(MatchHandlerStart) -CARBON_PARSE_NODE_KIND(MatchHandler) +CARBON_PARSE_NODE_KIND_STATEMENT(MatchIntroducer) +CARBON_PARSE_NODE_KIND_STATEMENT(MatchConditionStart) +CARBON_PARSE_NODE_KIND_STATEMENT(MatchCondition) +CARBON_PARSE_NODE_KIND_STATEMENT(MatchStatementStart) +CARBON_PARSE_NODE_KIND_STATEMENT(MatchStatement) +CARBON_PARSE_NODE_KIND_STATEMENT(MatchCaseIntroducer) +CARBON_PARSE_NODE_KIND_STATEMENT(MatchCaseGuardIntroducer) +CARBON_PARSE_NODE_KIND_STATEMENT(MatchCaseGuardStart) +CARBON_PARSE_NODE_KIND_STATEMENT(MatchCaseGuard) +CARBON_PARSE_NODE_KIND_STATEMENT(MatchCase) +CARBON_PARSE_NODE_KIND_STATEMENT(MatchDefaultIntroducer) +CARBON_PARSE_NODE_KIND_STATEMENT(MatchDefault) +CARBON_PARSE_NODE_KIND_STATEMENT(MatchHandlerStart) +CARBON_PARSE_NODE_KIND_STATEMENT(MatchHandler) #undef CARBON_PARSE_NODE_KIND +#undef CARBON_PARSE_NODE_KIND_DECLARATION +#undef CARBON_PARSE_NODE_KIND_EXPRESSION +#undef CARBON_PARSE_NODE_KIND_PATTERN +#undef CARBON_PARSE_NODE_KIND_STATEMENT #undef CARBON_PARSE_NODE_KIND_INFIX_OPERATOR #undef CARBON_PARSE_NODE_KIND_POSTFIX_OPERATOR #undef CARBON_PARSE_NODE_KIND_PREFIX_OPERATOR diff --git a/toolchain/parse/node_kind.h b/toolchain/parse/node_kind.h index 524c1df81038..0ff02ea399fc 100644 --- a/toolchain/parse/node_kind.h +++ b/toolchain/parse/node_kind.h @@ -7,6 +7,7 @@ #include +#include "common/check.h" #include "common/enum_base.h" #include "common/ostream.h" #include "toolchain/lex/token_kind.h"