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
This commit is contained in:
Chandler Carruth
2026-08-17 17:39:42 +00:00
committed by GitHub
parent b2900105d7
commit f58de06c0d
14 changed files with 698 additions and 553 deletions
+1 -2
View File
@@ -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.
+1
View File
@@ -9,6 +9,7 @@
#include <string>
#include "common/raw_string_ostream.h"
#include "toolchain/lex/tokenized_buffer.h"
namespace Carbon::Lex {
+5 -1
View File
@@ -19,10 +19,14 @@
#ifndef NDEBUG
#include "toolchain/lex/tokenized_buffer.h"
#include <string>
#include "toolchain/lex/token_index.h"
namespace Carbon::Lex {
class TokenizedBuffer;
auto Dump(const TokenizedBuffer& tokens, TokenIndex token) -> std::string;
} // namespace Carbon::Lex
+9 -1
View File
@@ -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",
],
+1
View File
@@ -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 {
+6 -1
View File
@@ -19,10 +19,15 @@
#ifndef NDEBUG
#include "toolchain/parse/tree.h"
#include <string>
#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;
+9 -325
View File
@@ -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 <initializer_list>
#include <optional>
#include <tuple>
#include <utility>
#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<T>`, 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<TreeAndSubtrees::SiblingIterator> 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<NodeKind> 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 <typename T, typename... U, size_t... Index>
auto ExtractTupleLikeType(std::index_sequence<Index...> /*indices*/,
std::tuple<U...>* /*type*/) -> std::optional<T>;
// 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 <typename... ArgT>
[[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<T> {
// // 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<T>;
// };
// ```
//
// Note that `TreeAndSubtrees::SiblingIterator`s iterate in reverse order
// through the children of a node.
//
// This class is only in this file.
template <typename T>
struct Extractable;
} // namespace
// Extract a `NodeId` as a single child.
template <>
struct Extractable<NodeId> {
static auto Extract(NodeExtractor& extractor) -> std::optional<NodeId> {
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<NodeKind::Foo>`,
// as a single required child.
template <const NodeKind& Kind>
struct Extractable<NodeIdForKind<Kind>> {
static auto Extract(NodeExtractor& extractor)
-> std::optional<NodeIdForKind<Kind>> {
if (extractor.MatchesNodeIdForKind(Kind)) {
return extractor.tree().As<NodeIdForKind<Kind>>(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<Category>` as a single child.
template <NodeCategory::RawEnumType Category>
struct Extractable<NodeIdInCategory<Category>> {
static auto Extract(NodeExtractor& extractor)
-> std::optional<NodeIdInCategory<Category>> {
if (extractor.MatchesNodeIdInCategory(Category)) {
return extractor.tree().As<NodeIdInCategory<Category>>(
extractor.ExtractNode());
} else {
return std::nullopt;
}
}
};
auto NodeExtractor::MatchesNodeIdOneOf(
std::initializer_list<NodeKind> kinds) const -> bool {
auto trace_kinds = [&] {
@@ -227,80 +75,6 @@ auto NodeExtractor::MatchesNodeIdOneOf(
return true;
}
// Extract a `NodeIdOneOf<T...>` as a single required child.
template <typename... T>
struct Extractable<NodeIdOneOf<T...>> {
static auto Extract(NodeExtractor& extractor)
-> std::optional<NodeIdOneOf<T...>> {
if (extractor.MatchesNodeIdOneOf({T::Kind...})) {
return extractor.tree().As<NodeIdOneOf<T...>>(extractor.ExtractNode());
} else {
return std::nullopt;
}
}
};
// Extract a `NodeIdNot<T>` as a single required child.
// Note: this is only instantiated once, so no need to create a helper function.
template <typename T>
struct Extractable<NodeIdNot<T>> {
static auto Extract(NodeExtractor& extractor) -> std::optional<NodeIdNot<T>> {
// 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<T>(extractor.ExtractNode());
}
};
// Extract an `llvm::SmallVector<T>` by extracting `T`s until we can't.
template <typename T>
struct Extractable<llvm::SmallVector<T>> {
static auto Extract(NodeExtractor& extractor)
-> std::optional<llvm::SmallVector<T>> {
extractor.MaybeTrace("Vector: begin\n");
llvm::SmallVector<T> result;
while (!extractor.at_end()) {
auto checkpoint = extractor.Checkpoint();
auto item = Extractable<T>::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<T>` from a list of child nodes by attempting to extract
// a `T`, and extracting nothing if that fails.
template <typename T>
struct Extractable<std::optional<T>> {
static auto Extract(NodeExtractor& extractor)
-> std::optional<std::optional<T>> {
extractor.MaybeTrace("Optional {0}: begin\n", llvm::getTypeName<T>());
auto checkpoint = extractor.Checkpoint();
std::optional<T> value = Extractable<T>::Extract(extractor);
if (value) {
extractor.MaybeTrace("Optional {0}: found\n", llvm::getTypeName<T>());
} else {
extractor.MaybeTrace("Optional {0}: missing\n", llvm::getTypeName<T>());
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 <const Lex::TokenKind& Kind>
struct Extractable<Lex::TokenIndexForKind<Kind>> {
static auto Extract(NodeExtractor& extractor)
-> std::optional<Lex::TokenIndexForKind<Kind>> {
if (extractor.MatchesTokenKind(Kind)) {
return static_cast<Lex::TokenIndexForKind<Kind>>(extractor.token());
} else {
return std::nullopt;
}
}
};
// Extract the token corresponding to a node.
template <>
struct Extractable<Lex::TokenIndex> {
static auto Extract(NodeExtractor& extractor)
-> std::optional<Lex::TokenIndex> {
if (!extractor.has_token()) {
extractor.MaybeTrace("Token expected but processing root node\n");
return std::nullopt;
}
return extractor.token();
}
};
template <typename T, typename... U, size_t... Index>
auto NodeExtractor::ExtractTupleLikeType(
std::index_sequence<Index...> /*indices*/, std::tuple<U...>* /*type*/)
-> std::optional<T> {
std::tuple<std::optional<U>...> fields;
MaybeTrace("Aggregate {0}: begin\n", llvm::getTypeName<T>());
// Use a fold over the `=` operator to parse fields from right to left.
[[maybe_unused]] int unused;
bool ok = true;
static_cast<void>(
((ok && (ok = (std::get<Index>(fields) = Extractable<U>::Extract(*this))
.has_value()),
unused) = ... = 0));
if (!ok) {
MaybeTrace("Aggregate {0}: error\n", llvm::getTypeName<T>());
return std::nullopt;
}
MaybeTrace("Aggregate {0}: success\n", llvm::getTypeName<T>());
return T{std::move(std::get<Index>(fields).value())...};
}
namespace {
// Extract the fields of a simple aggregate type.
template <typename T>
struct Extractable {
static_assert(std::is_aggregate_v<T>, "Unsupported child type");
static auto ExtractImpl(NodeExtractor& extractor) -> std::optional<T> {
// Compute the corresponding tuple type.
using TupleType = decltype(StructReflection::AsTuple(std::declval<T>()));
return extractor.ExtractTupleLikeType<T>(
std::make_index_sequence<std::tuple_size_v<TupleType>>(),
static_cast<TupleType*>(nullptr));
}
static auto Extract(NodeExtractor& extractor) -> std::optional<T> {
static_assert(!HasKindMember<T>, "Missing Id suffix");
return ExtractImpl(extractor);
}
};
} // namespace
template <typename T>
auto TreeAndSubtrees::TryExtractNodeFromChildren(
// Instantiate for `File`, which is the root container type.
template auto TreeAndSubtrees::TryExtractNodeFromChildren<File>(
NodeId node_id,
llvm::iterator_range<TreeAndSubtrees::SiblingIterator> children,
ErrorBuilder* trace) const -> std::optional<T> {
NodeExtractor extractor(this, tokens_, trace, node_id, children);
auto result = Extractable<T>::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<KindName>( \
NodeId node_id, \
llvm::iterator_range<TreeAndSubtrees::SiblingIterator> children, \
ErrorBuilder * trace) const -> std::optional<KindName>;
// 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<File>;
auto TreeAndSubtrees::ExtractFile() const -> File {
return ExtractNodeFromChildren<File>(NodeId::None, roots());
+326
View File
@@ -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 <initializer_list>
#include <optional>
#include <tuple>
#include <utility>
#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<T>`, 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<TreeAndSubtrees::SiblingIterator> 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<NodeKind> 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 <typename T, typename... U, size_t... Index>
auto ExtractTupleLikeType(std::index_sequence<Index...> /*indices*/,
std::tuple<U...>* /*type*/) -> std::optional<T>;
// 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 <typename... ArgT>
[[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<T> {
// // 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<T>;
// };
// ```
//
// Note that `TreeAndSubtrees::SiblingIterator`s iterate in reverse order
// through the children of a node.
template <typename T>
struct Extractable;
// Extract a `NodeId` as a single child.
template <>
struct Extractable<NodeId> {
static auto Extract(NodeExtractor& extractor) -> std::optional<NodeId> {
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<NodeKind::Foo>`,
// as a single required child.
template <const NodeKind& Kind>
struct Extractable<NodeIdForKind<Kind>> {
static auto Extract(NodeExtractor& extractor)
-> std::optional<NodeIdForKind<Kind>> {
if (extractor.MatchesNodeIdForKind(Kind)) {
return extractor.tree().As<NodeIdForKind<Kind>>(extractor.ExtractNode());
} else {
return std::nullopt;
}
}
};
// Extract a `NodeIdInCategory<Category>` as a single child.
template <NodeCategory::RawEnumType Category>
struct Extractable<NodeIdInCategory<Category>> {
static auto Extract(NodeExtractor& extractor)
-> std::optional<NodeIdInCategory<Category>> {
if (extractor.MatchesNodeIdInCategory(Category)) {
return extractor.tree().As<NodeIdInCategory<Category>>(
extractor.ExtractNode());
} else {
return std::nullopt;
}
}
};
// Extract a `NodeIdOneOf<T...>` as a single required child.
template <typename... T>
struct Extractable<NodeIdOneOf<T...>> {
static auto Extract(NodeExtractor& extractor)
-> std::optional<NodeIdOneOf<T...>> {
if (extractor.MatchesNodeIdOneOf({T::Kind...})) {
return extractor.tree().As<NodeIdOneOf<T...>>(extractor.ExtractNode());
} else {
return std::nullopt;
}
}
};
// Extract a `NodeIdNot<T>` as a single required child.
// Note: this is only instantiated once, so no need to create a helper function.
template <typename T>
struct Extractable<NodeIdNot<T>> {
static auto Extract(NodeExtractor& extractor) -> std::optional<NodeIdNot<T>> {
// 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<T>(extractor.ExtractNode());
}
};
// Extract an `llvm::SmallVector<T>` by extracting `T`s until we can't.
template <typename T>
struct Extractable<llvm::SmallVector<T>> {
static auto Extract(NodeExtractor& extractor)
-> std::optional<llvm::SmallVector<T>> {
extractor.MaybeTrace("Vector: begin\n");
llvm::SmallVector<T> result;
while (!extractor.at_end()) {
auto checkpoint = extractor.Checkpoint();
auto item = Extractable<T>::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<T>` from a list of child nodes by attempting to extract
// a `T`, and extracting nothing if that fails.
template <typename T>
struct Extractable<std::optional<T>> {
static auto Extract(NodeExtractor& extractor)
-> std::optional<std::optional<T>> {
extractor.MaybeTrace("Optional {0}: begin\n", llvm::getTypeName<T>());
auto checkpoint = extractor.Checkpoint();
std::optional<T> value = Extractable<T>::Extract(extractor);
if (value) {
extractor.MaybeTrace("Optional {0}: found\n", llvm::getTypeName<T>());
} else {
extractor.MaybeTrace("Optional {0}: missing\n", llvm::getTypeName<T>());
extractor.RestoreCheckpoint(checkpoint);
}
return value;
}
};
// Extract the token corresponding to a node.
template <const Lex::TokenKind& Kind>
struct Extractable<Lex::TokenIndexForKind<Kind>> {
static auto Extract(NodeExtractor& extractor)
-> std::optional<Lex::TokenIndexForKind<Kind>> {
if (extractor.MatchesTokenKind(Kind)) {
return static_cast<Lex::TokenIndexForKind<Kind>>(extractor.token());
} else {
return std::nullopt;
}
}
};
// Extract the token corresponding to a node.
template <>
struct Extractable<Lex::TokenIndex> {
static auto Extract(NodeExtractor& extractor)
-> std::optional<Lex::TokenIndex> {
if (!extractor.has_token()) {
extractor.MaybeTrace("Token expected but processing root node\n");
return std::nullopt;
}
return extractor.token();
}
};
template <typename T, typename... U, size_t... Index>
auto NodeExtractor::ExtractTupleLikeType(
std::index_sequence<Index...> /*indices*/, std::tuple<U...>* /*type*/)
-> std::optional<T> {
std::tuple<std::optional<U>...> fields;
MaybeTrace("Aggregate {0}: begin\n", llvm::getTypeName<T>());
// Use a fold over the `=` operator to parse fields from right to left.
[[maybe_unused]] int unused;
bool ok = true;
static_cast<void>(
((ok && (ok = (std::get<Index>(fields) = Extractable<U>::Extract(*this))
.has_value()),
unused) = ... = 0));
if (!ok) {
MaybeTrace("Aggregate {0}: error\n", llvm::getTypeName<T>());
return std::nullopt;
}
MaybeTrace("Aggregate {0}: success\n", llvm::getTypeName<T>());
return T{std::move(std::get<Index>(fields).value())...};
}
// Extract the fields of a simple aggregate type.
template <typename T>
struct Extractable {
static_assert(std::is_aggregate_v<T>, "Unsupported child type");
static auto ExtractImpl(NodeExtractor& extractor) -> std::optional<T> {
// Compute the corresponding tuple type.
using TupleType = decltype(StructReflection::AsTuple(std::declval<T>()));
return extractor.ExtractTupleLikeType<T>(
std::make_index_sequence<std::tuple_size_v<TupleType>>(),
static_cast<TupleType*>(nullptr));
}
static auto Extract(NodeExtractor& extractor) -> std::optional<T> {
static_assert(!HasKindMember<T>, "Missing Id suffix");
return ExtractImpl(extractor);
}
};
template <typename T>
auto TreeAndSubtrees::TryExtractNodeFromChildren(
NodeId node_id,
llvm::iterator_range<TreeAndSubtrees::SiblingIterator> children,
ErrorBuilder* trace) const -> std::optional<T> {
NodeExtractor extractor(this, tokens_, trace, node_id, children);
auto result = Extractable<T>::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_
+17
View File
@@ -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<KindName>( \
NodeId node_id, \
llvm::iterator_range<TreeAndSubtrees::SiblingIterator> children, \
ErrorBuilder * trace) const -> std::optional<KindName>;
#include "toolchain/parse/node_kind.def"
} // namespace Carbon::Parse
+17
View File
@@ -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<KindName>( \
NodeId node_id, \
llvm::iterator_range<TreeAndSubtrees::SiblingIterator> children, \
ErrorBuilder * trace) const -> std::optional<KindName>;
#include "toolchain/parse/node_kind.def"
} // namespace Carbon::Parse
+17
View File
@@ -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<KindName>( \
NodeId node_id, \
llvm::iterator_range<TreeAndSubtrees::SiblingIterator> children, \
ErrorBuilder * trace) const -> std::optional<KindName>;
#include "toolchain/parse/node_kind.def"
} // namespace Carbon::Parse
+17
View File
@@ -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<KindName>( \
NodeId node_id, \
llvm::iterator_range<TreeAndSubtrees::SiblingIterator> children, \
ErrorBuilder * trace) const -> std::optional<KindName>;
#include "toolchain/parse/node_kind.def"
} // namespace Carbon::Parse
+271 -223
View File
@@ -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) <code>
#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) <code>
#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) <code>
#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) <code>
#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) <code>
#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) <code>
#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) <code>
#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) <code>
#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) <code>
#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
+1
View File
@@ -7,6 +7,7 @@
#include <cstdint>
#include "common/check.h"
#include "common/enum_base.h"
#include "common/ostream.h"
#include "toolchain/lex/token_kind.h"