Add a macro for introducer tokens. (#4031)

Playing with the macro suggestion on #4028, replace DeclKind with some
templating that asserts the in-use token is an introducer token. This
allows type-safe usage of Lex::TokenKind, reducing the benefit of a
separate enum while improving stdout (since now this will ostream as the
keyword name).
This commit is contained in:
Jon Ross-Perkins
2024-06-05 21:04:53 +00:00
committed by GitHub
parent 7792e5fce3
commit d1862e829b
16 changed files with 92 additions and 113 deletions
+1
View File
@@ -90,6 +90,7 @@ cc_library(
"//toolchain/base:kind_switch",
"//toolchain/check:scope_stack",
"//toolchain/diagnostics:diagnostic_emitter",
"//toolchain/lex:token_kind",
"//toolchain/lex:tokenized_buffer",
"//toolchain/parse:node_kind",
"//toolchain/parse:tree",
+31 -30
View File
@@ -6,6 +6,7 @@
#define CARBON_TOOLCHAIN_CHECK_DECL_INTRODUCER_STATE_H_
#include "toolchain/check/keyword_modifier_set.h"
#include "toolchain/lex/token_kind.h"
#include "toolchain/parse/node_ids.h"
namespace Carbon::Check {
@@ -14,27 +15,6 @@ namespace Carbon::Check {
// declaration and the keyword modifiers that apply to that declaration
// introducer.
struct DeclIntroducerState {
// The kind of declaration.
enum DeclKind : int8_t {
Adapt,
Alias,
Base,
Class,
Constraint,
Export,
Fn,
Impl,
Import,
Interface,
Let,
Library,
Namespace,
Package,
Var
};
explicit DeclIntroducerState(DeclKind decl_kind) : kind(decl_kind) {}
auto modifier_node_id(ModifierOrder order) -> Parse::NodeId {
return ordered_modifier_node_ids[static_cast<int8_t>(order)];
}
@@ -43,7 +23,8 @@ struct DeclIntroducerState {
ordered_modifier_node_ids[static_cast<int8_t>(order)] = node_id;
}
DeclKind kind;
// The token kind of the introducer.
Lex::TokenKind kind;
// Nodes of modifiers on this declaration, in expected order. `Invalid` if no
// modifier of that kind is present.
@@ -53,26 +34,46 @@ struct DeclIntroducerState {
Parse::NodeId::Invalid};
// Invariant: contains just the modifiers represented by `saw_*_modifier`.
KeywordModifierSet modifier_set;
KeywordModifierSet modifier_set = KeywordModifierSet();
};
// Stack of `DeclIntroducerState` values, representing all the declaration
// introducers we are currently nested within. Commonly size 0 or 1, as nested
// introducers are rare.
class DeclIntroducerStateStack {
private:
// Returns true for introducer tokens. Supports Push/Pop `requires`.
template <Lex::TokenKind::RawEnumType Kind>
static constexpr auto IsDeclIntroducer() -> bool {
switch (Kind) {
#define CARBON_TOKEN(...)
#define CARBON_DECL_INTRODUCER_TOKEN(Name, ...) case Lex::TokenKind::Name:
#include "toolchain/lex/token_kind.def"
return true;
default:
return false;
}
}
public:
// Begins introducing a declaration of kind `k`.
auto Push(DeclIntroducerState::DeclKind k) -> void { stack_.emplace_back(k); }
// Begins a declaration introducer `Kind`.
template <Lex::TokenKind::RawEnumType Kind>
requires(IsDeclIntroducer<Kind>())
auto Push() -> void {
stack_.push_back({.kind = Lex::TokenKind::Make(Kind)});
}
// Gets the state of declaration at the top of the stack -- the innermost
// declaration currently being processed.
auto innermost() -> DeclIntroducerState& { return stack_.back(); }
// Finishes introducing a declaration of kind `k` and returns the
// produced state.
auto Pop(DeclIntroducerState::DeclKind k) -> DeclIntroducerState {
CARBON_CHECK(stack_.back().kind == k)
<< "Found: " << stack_.back().kind << " expected: " << k;
// Finishes a declaration introducer `Kind` and returns the produced state.
template <Lex::TokenKind::RawEnumType Kind>
requires(IsDeclIntroducer<Kind>())
auto Pop() -> DeclIntroducerState {
CARBON_CHECK(stack_.back().kind == Kind)
<< "Found: " << stack_.back().kind
<< " expected: " << Lex::TokenKind::Make(Kind);
return stack_.pop_back_val();
}
+2 -2
View File
@@ -14,7 +14,7 @@ namespace Carbon::Check {
auto HandleAliasIntroducer(Context& context,
Parse::AliasIntroducerId /*node_id*/) -> bool {
context.decl_introducer_state_stack().Push(DeclIntroducerState::Alias);
context.decl_introducer_state_stack().Push<Lex::TokenKind::Alias>();
context.decl_name_stack().PushScopeAndStartName();
return true;
}
@@ -31,7 +31,7 @@ auto HandleAlias(Context& context, Parse::AliasId /*node_id*/) -> bool {
PopNameComponentWithoutParams(context, Lex::TokenKind::Alias));
auto introducer =
context.decl_introducer_state_stack().Pop(DeclIntroducerState::Alias);
context.decl_introducer_state_stack().Pop<Lex::TokenKind::Alias>();
LimitModifiersOnDecl(context, introducer, KeywordModifierSet::Access);
if (introducer.modifier_set.HasAnyOf(KeywordModifierSet::Access)) {
context.TODO(introducer.modifier_node_id(ModifierOrder::Access),
+6 -6
View File
@@ -36,7 +36,7 @@ auto HandleClassIntroducer(Context& context, Parse::ClassIntroducerId node_id)
// Push the bracketing node.
context.node_stack().Push(node_id);
// Optional modifiers and the name follow.
context.decl_introducer_state_stack().Push(DeclIntroducerState::Class);
context.decl_introducer_state_stack().Push<Lex::TokenKind::Class>();
context.decl_name_stack().PushScopeAndStartName();
return true;
}
@@ -188,7 +188,7 @@ static auto BuildClassDecl(Context& context, Parse::AnyClassDeclId node_id,
auto [_, parent_scope_inst] =
context.name_scopes().GetInstIfValid(name_context.parent_scope_id);
auto introducer =
context.decl_introducer_state_stack().Pop(DeclIntroducerState::Class);
context.decl_introducer_state_stack().Pop<Lex::TokenKind::Class>();
CheckAccessModifiersOnDecl(context, introducer, parent_scope_inst);
LimitModifiersOnDecl(context, introducer,
KeywordModifierSet::Class | KeywordModifierSet::Access |
@@ -355,7 +355,7 @@ static auto DiagnoseClassSpecificDeclRepeated(Context& context,
auto HandleAdaptIntroducer(Context& context,
Parse::AdaptIntroducerId /*node_id*/) -> bool {
context.decl_introducer_state_stack().Push(DeclIntroducerState::Adapt);
context.decl_introducer_state_stack().Push<Lex::TokenKind::Adapt>();
return true;
}
@@ -365,7 +365,7 @@ auto HandleAdaptDecl(Context& context, Parse::AdaptDeclId node_id) -> bool {
// Process modifiers. `extend` is permitted, no others are allowed.
auto introducer =
context.decl_introducer_state_stack().Pop(DeclIntroducerState::Adapt);
context.decl_introducer_state_stack().Pop<Lex::TokenKind::Adapt>();
LimitModifiersOnDecl(context, introducer, KeywordModifierSet::Extend);
auto parent_class_decl =
@@ -422,7 +422,7 @@ auto HandleAdaptDecl(Context& context, Parse::AdaptDeclId node_id) -> bool {
auto HandleBaseIntroducer(Context& context, Parse::BaseIntroducerId /*node_id*/)
-> bool {
context.decl_introducer_state_stack().Push(DeclIntroducerState::Base);
context.decl_introducer_state_stack().Push<Lex::TokenKind::Base>();
return true;
}
@@ -495,7 +495,7 @@ auto HandleBaseDecl(Context& context, Parse::BaseDeclId node_id) -> bool {
// Process modifiers. `extend` is required, no others are allowed.
auto introducer =
context.decl_introducer_state_stack().Pop(DeclIntroducerState::Base);
context.decl_introducer_state_stack().Pop<Lex::TokenKind::Base>();
LimitModifiersOnDecl(context, introducer, KeywordModifierSet::Extend);
if (!introducer.modifier_set.HasAnyOf(KeywordModifierSet::Extend)) {
CARBON_DIAGNOSTIC(BaseMissingExtend, Error,
+2 -2
View File
@@ -15,7 +15,7 @@ namespace Carbon::Check {
auto HandleExportIntroducer(Context& context,
Parse::ExportIntroducerId /*node_id*/) -> bool {
context.decl_introducer_state_stack().Push(DeclIntroducerState::Export);
context.decl_introducer_state_stack().Push<Lex::TokenKind::Export>();
// TODO: Probably need to update DeclNameStack to restrict to only namespaces.
context.decl_name_stack().PushScopeAndStartName();
return true;
@@ -27,7 +27,7 @@ auto HandleExportDecl(Context& context, Parse::ExportDeclId node_id) -> bool {
context.decl_name_stack().PopScope();
auto introducer =
context.decl_introducer_state_stack().Pop(DeclIntroducerState::Export);
context.decl_introducer_state_stack().Pop<Lex::TokenKind::Export>();
LimitModifiersOnDecl(context, introducer, KeywordModifierSet::None);
if (name_context.state == DeclNameStack::NameContext::State::Error) {
+2 -2
View File
@@ -30,7 +30,7 @@ auto HandleFunctionIntroducer(Context& context,
// Push the bracketing node.
context.node_stack().Push(node_id);
// Optional modifiers and the name follow.
context.decl_introducer_state_stack().Push(DeclIntroducerState::Fn);
context.decl_introducer_state_stack().Push<Lex::TokenKind::Fn>();
context.decl_name_stack().PushScopeAndStartName();
return true;
}
@@ -225,7 +225,7 @@ static auto BuildFunctionDecl(Context& context,
auto [parent_scope_inst_id, parent_scope_inst] =
context.name_scopes().GetInstIfValid(name_context.parent_scope_id);
auto introducer =
context.decl_introducer_state_stack().Pop(DeclIntroducerState::Fn);
context.decl_introducer_state_stack().Pop<Lex::TokenKind::Fn>();
DiagnoseModifiers(context, introducer, is_definition, parent_scope_inst_id,
parent_scope_inst);
if (introducer.modifier_set.HasAnyOf(KeywordModifierSet::Access)) {
+2 -2
View File
@@ -24,7 +24,7 @@ auto HandleImplIntroducer(Context& context, Parse::ImplIntroducerId node_id)
context.node_stack().Push(node_id);
// Optional modifiers follow.
context.decl_introducer_state_stack().Push(DeclIntroducerState::Impl);
context.decl_introducer_state_stack().Push<Lex::TokenKind::Impl>();
// An impl doesn't have a name per se, but it makes the processing more
// consistent to imagine that it does. This also gives us a scope for implicit
@@ -193,7 +193,7 @@ static auto BuildImplDecl(Context& context, Parse::AnyImplDeclId node_id)
// TODO: Should we somehow permit access specifiers on `impl`s?
// TODO: Handle `final` modifier.
auto introducer =
context.decl_introducer_state_stack().Pop(DeclIntroducerState::Impl);
context.decl_introducer_state_stack().Pop<Lex::TokenKind::Impl>();
LimitModifiersOnDecl(context, introducer, KeywordModifierSet::ImplDecl);
// Finish processing the name, which should be empty, but might have
@@ -14,42 +14,42 @@ namespace Carbon::Check {
auto HandleImportIntroducer(Context& context,
Parse::ImportIntroducerId /*node_id*/) -> bool {
context.decl_introducer_state_stack().Push(DeclIntroducerState::Import);
context.decl_introducer_state_stack().Push<Lex::TokenKind::Import>();
return true;
}
auto HandleImportDecl(Context& context, Parse::ImportDeclId /*node_id*/)
-> bool {
auto introducer =
context.decl_introducer_state_stack().Pop(DeclIntroducerState::Import);
context.decl_introducer_state_stack().Pop<Lex::TokenKind::Import>();
LimitModifiersOnDecl(context, introducer, KeywordModifierSet::Export);
return true;
}
auto HandleLibraryIntroducer(Context& context,
Parse::LibraryIntroducerId /*node_id*/) -> bool {
context.decl_introducer_state_stack().Push(DeclIntroducerState::Library);
context.decl_introducer_state_stack().Push<Lex::TokenKind::Library>();
return true;
}
auto HandleLibraryDecl(Context& context, Parse::LibraryDeclId /*node_id*/)
-> bool {
auto introducer =
context.decl_introducer_state_stack().Pop(DeclIntroducerState::Library);
context.decl_introducer_state_stack().Pop<Lex::TokenKind::Library>();
LimitModifiersOnDecl(context, introducer, KeywordModifierSet::Impl);
return true;
}
auto HandlePackageIntroducer(Context& context,
Parse::PackageIntroducerId /*node_id*/) -> bool {
context.decl_introducer_state_stack().Push(DeclIntroducerState::Package);
context.decl_introducer_state_stack().Push<Lex::TokenKind::Package>();
return true;
}
auto HandlePackageDecl(Context& context, Parse::PackageDeclId /*node_id*/)
-> bool {
auto introducer =
context.decl_introducer_state_stack().Pop(DeclIntroducerState::Package);
context.decl_introducer_state_stack().Pop<Lex::TokenKind::Package>();
LimitModifiersOnDecl(context, introducer, KeywordModifierSet::Impl);
return true;
}
+2 -2
View File
@@ -20,7 +20,7 @@ auto HandleInterfaceIntroducer(Context& context,
// Push the bracketing node.
context.node_stack().Push(node_id);
// Optional modifiers and the name follow.
context.decl_introducer_state_stack().Push(DeclIntroducerState::Interface);
context.decl_introducer_state_stack().Push<Lex::TokenKind::Interface>();
context.decl_name_stack().PushScopeAndStartName();
return true;
}
@@ -37,7 +37,7 @@ static auto BuildInterfaceDecl(Context& context,
auto [_, parent_scope_inst] =
context.name_scopes().GetInstIfValid(name_context.parent_scope_id);
auto introducer =
context.decl_introducer_state_stack().Pop(DeclIntroducerState::Interface);
context.decl_introducer_state_stack().Pop<Lex::TokenKind::Interface>();
CheckAccessModifiersOnDecl(context, introducer, parent_scope_inst);
LimitModifiersOnDecl(context, introducer, KeywordModifierSet::Access);
+2 -2
View File
@@ -15,7 +15,7 @@ namespace Carbon::Check {
auto HandleLetIntroducer(Context& context, Parse::LetIntroducerId node_id)
-> bool {
context.decl_introducer_state_stack().Push(DeclIntroducerState::Let);
context.decl_introducer_state_stack().Push<Lex::TokenKind::Let>();
// Push a bracketing node to establish the pattern context.
context.node_stack().Push(node_id);
return true;
@@ -83,7 +83,7 @@ auto HandleLetDecl(Context& context, Parse::LetDeclId node_id) -> bool {
context.name_scopes().GetInstIfValid(
context.scope_stack().PeekNameScopeId());
auto introducer =
context.decl_introducer_state_stack().Pop(DeclIntroducerState::Let);
context.decl_introducer_state_stack().Pop<Lex::TokenKind::Let>();
CheckAccessModifiersOnDecl(context, introducer, parent_scope_inst);
RequireDefaultFinalOnlyInInterfaces(context, introducer, parent_scope_inst);
LimitModifiersOnDecl(
+1 -1
View File
@@ -77,7 +77,7 @@ auto HandleForHeaderStart(Context& context, Parse::ForHeaderStartId node_id)
}
auto HandleForIn(Context& context, Parse::ForInId node_id) -> bool {
context.decl_introducer_state_stack().Pop(DeclIntroducerState::Var);
context.decl_introducer_state_stack().Pop<Lex::TokenKind::Var>();
return context.TODO(node_id, "HandleForIn");
}
+2 -2
View File
@@ -15,7 +15,7 @@ namespace Carbon::Check {
auto HandleNamespaceStart(Context& context, Parse::NamespaceStartId /*node_id*/)
-> bool {
// Optional modifiers and the name follow.
context.decl_introducer_state_stack().Push(DeclIntroducerState::Namespace);
context.decl_introducer_state_stack().Push<Lex::TokenKind::Namespace>();
context.decl_name_stack().PushScopeAndStartName();
return true;
}
@@ -25,7 +25,7 @@ auto HandleNamespace(Context& context, Parse::NamespaceId node_id) -> bool {
PopNameComponentWithoutParams(context, Lex::TokenKind::Namespace));
auto introducer =
context.decl_introducer_state_stack().Pop(DeclIntroducerState::Namespace);
context.decl_introducer_state_stack().Pop<Lex::TokenKind::Namespace>();
LimitModifiersOnDecl(context, introducer, KeywordModifierSet::None);
auto namespace_inst = SemIR::Namespace{
+2 -2
View File
@@ -13,7 +13,7 @@ auto HandleVariableIntroducer(Context& context,
Parse::VariableIntroducerId node_id) -> bool {
// No action, just a bracketing node.
context.node_stack().Push(node_id);
context.decl_introducer_state_stack().Push(DeclIntroducerState::Var);
context.decl_introducer_state_stack().Push<Lex::TokenKind::Var>();
return true;
}
@@ -102,7 +102,7 @@ auto HandleVariableDecl(Context& context, Parse::VariableDeclId node_id)
auto [_, parent_scope_inst] = context.name_scopes().GetInstIfValid(
context.scope_stack().PeekNameScopeId());
auto introducer =
context.decl_introducer_state_stack().Pop(DeclIntroducerState::Var);
context.decl_introducer_state_stack().Pop<Lex::TokenKind::Var>();
CheckAccessModifiersOnDecl(context, introducer, parent_scope_inst);
LimitModifiersOnDecl(context, introducer, KeywordModifierSet::Access);
if (introducer.modifier_set.HasAnyOf(KeywordModifierSet::Access)) {
+1 -39
View File
@@ -8,43 +8,6 @@
namespace Carbon::Check {
// Returns the TokenKind for a DeclKind.
static auto DeclKindToken(DeclIntroducerState::DeclKind decl_kind)
-> Lex::TokenKind {
switch (decl_kind) {
case DeclIntroducerState::Adapt:
return Lex::TokenKind::Adapt;
case DeclIntroducerState::Alias:
return Lex::TokenKind::Alias;
case DeclIntroducerState::Base:
return Lex::TokenKind::Base;
case DeclIntroducerState::Class:
return Lex::TokenKind::Class;
case DeclIntroducerState::Constraint:
return Lex::TokenKind::Constraint;
case DeclIntroducerState::Export:
return Lex::TokenKind::Export;
case DeclIntroducerState::Fn:
return Lex::TokenKind::Fn;
case DeclIntroducerState::Import:
return Lex::TokenKind::Import;
case DeclIntroducerState::Impl:
return Lex::TokenKind::Impl;
case DeclIntroducerState::Interface:
return Lex::TokenKind::Interface;
case DeclIntroducerState::Let:
return Lex::TokenKind::Let;
case DeclIntroducerState::Library:
return Lex::TokenKind::Library;
case DeclIntroducerState::Namespace:
return Lex::TokenKind::Namespace;
case DeclIntroducerState::Package:
return Lex::TokenKind::Package;
case DeclIntroducerState::Var:
return Lex::TokenKind::Var;
}
}
static auto DiagnoseNotAllowed(Context& context, Parse::NodeId modifier_node,
Lex::TokenKind decl_kind,
llvm::StringRef context_string,
@@ -89,8 +52,7 @@ auto ForbidModifiersOnDecl(Context& context, DeclIntroducerState& introducer,
auto order = static_cast<ModifierOrder>(order_index);
if (not_allowed.HasAnyOf(ModifierOrderAsSet(order))) {
DiagnoseNotAllowed(context, introducer.modifier_node_id(order),
DeclKindToken(introducer.kind), context_string,
context_loc_id);
introducer.kind, context_string, context_loc_id);
introducer.set_modifier_node_id(order, Parse::NodeId::Invalid);
}
}
+27 -15
View File
@@ -21,6 +21,8 @@
// - CARBON_KEYWORD_TOKEN(Name, Spelling)
// Defines a keyword which has the provided spelling, such as `if`.
// Spellings must be unique.
// - CARBON_DECL_INTRODUCER_TOKEN(Name, Spelling)
// A declaration introducer keyword, such as `fn`.
// - CARBON_TOKEN_WITH_VIRTUAL_NODE(TokenIndex)
// Wrapped around one of the above _TOKEN macros, indicates that this
// token has one additional virtual node in the parse tree.
@@ -137,53 +139,62 @@ CARBON_CLOSING_GROUP_SYMBOL_TOKEN(CloseSquareBracket, "]", OpenSquareBracket)
#ifndef CARBON_KEYWORD_TOKEN
#define CARBON_KEYWORD_TOKEN(Name, Spelling) CARBON_TOKEN(Name)
#endif
#ifndef CARBON_DECL_INTRODUCER_TOKEN
#define CARBON_DECL_INTRODUCER_TOKEN(Name, Spelling) \
CARBON_KEYWORD_TOKEN(Name, Spelling)
#endif
// clang-format off
CARBON_DECL_INTRODUCER_TOKEN(Adapt, "adapt")
CARBON_DECL_INTRODUCER_TOKEN(Alias, "alias")
CARBON_DECL_INTRODUCER_TOKEN(Base, "base")
CARBON_DECL_INTRODUCER_TOKEN(Class, "class")
CARBON_DECL_INTRODUCER_TOKEN(Constraint, "constraint")
CARBON_DECL_INTRODUCER_TOKEN(Export, "export")
CARBON_DECL_INTRODUCER_TOKEN(Fn, "fn")
CARBON_DECL_INTRODUCER_TOKEN(Impl, "impl")
CARBON_DECL_INTRODUCER_TOKEN(Import, "import")
CARBON_DECL_INTRODUCER_TOKEN(Interface, "interface")
CARBON_DECL_INTRODUCER_TOKEN(Let, "let")
CARBON_DECL_INTRODUCER_TOKEN(Library, "library")
CARBON_DECL_INTRODUCER_TOKEN(Namespace, "namespace")
CARBON_DECL_INTRODUCER_TOKEN(Package, "package")
CARBON_DECL_INTRODUCER_TOKEN(Var, "var")
CARBON_KEYWORD_TOKEN(Abstract, "abstract")
CARBON_KEYWORD_TOKEN(Adapt, "adapt")
CARBON_KEYWORD_TOKEN(Addr, "addr")
CARBON_KEYWORD_TOKEN(Alias, "alias")
CARBON_TOKEN_WITH_VIRTUAL_NODE(
CARBON_KEYWORD_TOKEN(And, "and"))
CARBON_KEYWORD_TOKEN(Api, "api")
CARBON_KEYWORD_TOKEN(As, "as")
CARBON_KEYWORD_TOKEN(Auto, "auto")
CARBON_KEYWORD_TOKEN(Base, "base")
CARBON_KEYWORD_TOKEN(Bool, "bool")
CARBON_KEYWORD_TOKEN(Break, "break")
CARBON_KEYWORD_TOKEN(Case, "case")
CARBON_KEYWORD_TOKEN(Choice, "choice")
CARBON_KEYWORD_TOKEN(Class, "class")
CARBON_KEYWORD_TOKEN(Const, "const")
CARBON_KEYWORD_TOKEN(Constraint, "constraint")
CARBON_KEYWORD_TOKEN(Continue, "continue")
CARBON_KEYWORD_TOKEN(Default, "default")
CARBON_KEYWORD_TOKEN(Destructor, "destructor")
CARBON_KEYWORD_TOKEN(Else, "else")
CARBON_KEYWORD_TOKEN(Export, "export")
CARBON_KEYWORD_TOKEN(Extend, "extend")
CARBON_KEYWORD_TOKEN(Extern, "extern")
CARBON_KEYWORD_TOKEN(False, "false")
CARBON_KEYWORD_TOKEN(Final, "final")
CARBON_KEYWORD_TOKEN(Fn, "fn")
CARBON_KEYWORD_TOKEN(For, "for")
CARBON_KEYWORD_TOKEN(Forall, "forall")
CARBON_KEYWORD_TOKEN(Friend, "friend")
CARBON_KEYWORD_TOKEN(If, "if")
CARBON_KEYWORD_TOKEN(Impl, "impl")
CARBON_KEYWORD_TOKEN(Impls, "impls")
CARBON_KEYWORD_TOKEN(Import, "import")
CARBON_KEYWORD_TOKEN(In, "in")
CARBON_KEYWORD_TOKEN(Interface, "interface")
CARBON_KEYWORD_TOKEN(Let, "let")
CARBON_KEYWORD_TOKEN(Library, "library")
CARBON_KEYWORD_TOKEN(Like, "like")
CARBON_KEYWORD_TOKEN(Match, "match")
CARBON_KEYWORD_TOKEN(Namespace, "namespace")
CARBON_KEYWORD_TOKEN(Not, "not")
CARBON_KEYWORD_TOKEN(Observe, "observe")
CARBON_TOKEN_WITH_VIRTUAL_NODE(
CARBON_KEYWORD_TOKEN(Or, "or"))
CARBON_KEYWORD_TOKEN(Package, "package")
CARBON_KEYWORD_TOKEN(Partial, "partial")
CARBON_KEYWORD_TOKEN(Private, "private")
CARBON_KEYWORD_TOKEN(Protected, "protected")
@@ -200,11 +211,12 @@ CARBON_KEYWORD_TOKEN(True, "true")
CARBON_KEYWORD_TOKEN(Type, "type")
// Underscore is tokenized as a keyword because it's part of identifiers.
CARBON_KEYWORD_TOKEN(Underscore, "_")
CARBON_KEYWORD_TOKEN(Var, "var")
CARBON_KEYWORD_TOKEN(Virtual, "virtual")
CARBON_KEYWORD_TOKEN(Where, "where")
CARBON_KEYWORD_TOKEN(While, "while")
// clang-format on
#undef CARBON_DECL_INTRODUCER_TOKEN
#undef CARBON_KEYWORD_TOKEN
CARBON_TOKEN(Identifier)
+3
View File
@@ -30,6 +30,9 @@ class TokenKind : public CARBON_ENUM_BASE(TokenKind) {
using EnumBase::EnumBase;
// Permit creation from RawEnumType for templates.
using EnumBase::Make;
// Permit conversion to integer for use as an array index.
using EnumBase::AsInt;