diff --git a/toolchain/parse/node_kind.cpp b/toolchain/parse/node_kind.cpp index b5fe9c803555..68798d1637a5 100644 --- a/toolchain/parse/node_kind.cpp +++ b/toolchain/parse/node_kind.cpp @@ -39,55 +39,17 @@ CARBON_DEFINE_ENUM_CLASS_NAMES(NodeKind) = { #include "toolchain/parse/node_kind.def" }; -auto NodeKind::has_bracket() const -> bool { - static constexpr bool HasBracket[] = { -#define CARBON_PARSE_NODE_KIND_BRACKET(...) true, -#define CARBON_PARSE_NODE_KIND_CHILD_COUNT(...) false, -#include "toolchain/parse/node_kind.def" - }; - return HasBracket[AsInt()]; -} - -auto NodeKind::bracket() const -> NodeKind { - // Nodes are never self-bracketed, so we use that for nodes that instead set - // child_count. - static constexpr NodeKind Bracket[] = { -#define CARBON_PARSE_NODE_KIND_BRACKET(Name, BracketName, ...) \ - NodeKind::BracketName, -#define CARBON_PARSE_NODE_KIND_CHILD_COUNT(Name, ...) NodeKind::Name, -#include "toolchain/parse/node_kind.def" - }; - auto bracket = Bracket[AsInt()]; - CARBON_CHECK(bracket != *this) << *this; - return bracket; -} - -auto NodeKind::child_count() const -> int32_t { - static constexpr int32_t ChildCount[] = { -#define CARBON_PARSE_NODE_KIND_BRACKET(...) -1, -#define CARBON_PARSE_NODE_KIND_CHILD_COUNT(Name, Size, ...) Size, -#include "toolchain/parse/node_kind.def" - }; - auto child_count = ChildCount[AsInt()]; - CARBON_CHECK(child_count >= 0) << *this; - return child_count; -} - auto NodeKind::CheckMatchesTokenKind(Lex::TokenKind token_kind, bool has_error) -> void { static constexpr Lex::TokenKind TokenIfValid[] = { #define CARBON_IF_VALID(LexTokenKind) LexTokenKind -#define CARBON_PARSE_NODE_KIND_BRACKET(Name, BracketName, LexTokenKind) \ - Lex::TokenKind::LexTokenKind, -#define CARBON_PARSE_NODE_KIND_CHILD_COUNT(Name, Size, LexTokenKind) \ +#define CARBON_PARSE_NODE_KIND_WITH_TOKEN(Name, LexTokenKind) \ Lex::TokenKind::LexTokenKind, #include "toolchain/parse/node_kind.def" }; static constexpr Lex::TokenKind TokenIfError[] = { #define CARBON_IF_VALID(LexTokenKind) Error -#define CARBON_PARSE_NODE_KIND_BRACKET(Name, BracketName, LexTokenKind) \ - Lex::TokenKind::LexTokenKind, -#define CARBON_PARSE_NODE_KIND_CHILD_COUNT(Name, Size, LexTokenKind) \ +#define CARBON_PARSE_NODE_KIND_WITH_TOKEN(Name, LexTokenKind) \ Lex::TokenKind::LexTokenKind, #include "toolchain/parse/node_kind.def" }; @@ -102,6 +64,20 @@ auto NodeKind::CheckMatchesTokenKind(Lex::TokenKind token_kind, bool has_error) << ", but expected token kind " << expected_token_kind; } +auto NodeKind::has_bracket() const -> bool { + return definition().has_bracket(); +} + +auto NodeKind::bracket() const -> NodeKind { return definition().bracket(); } + +auto NodeKind::has_child_count() const -> bool { + return definition().has_child_count(); +} + +auto NodeKind::child_count() const -> int32_t { + return definition().child_count(); +} + auto NodeKind::category() const -> NodeCategory { return definition().category(); } diff --git a/toolchain/parse/node_kind.def b/toolchain/parse/node_kind.def index ca7e72245784..aaa8752ac040 100644 --- a/toolchain/parse/node_kind.def +++ b/toolchain/parse/node_kind.def @@ -10,12 +10,8 @@ // Supported x-macros are: // - CARBON_PARSE_NODE_KIND(Name) // Used as a fallback if other macros are missing. -// - CARBON_PARSE_NODE_KIND_BRACKET(Name, BracketName, LexTokenKind) -// Defines a bracketed node kind. BracketName should refer to the node -// kind that is the _start_ of the bracketed range. -// - CARBON_PARSE_NODE_KIND_CHILD_COUNT(Name, ChildCount, LexTokenKind) -// Defines a parse node with a set number of children, often 0. This count -// must be correct even when the node contains errors. +// - CARBON_PARSE_NODE_KIND_WITH_TOKEN(Name, LexTokenKind) +// Defines a parse node kind and specifies its corresponding token kind. // - 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) @@ -39,22 +35,18 @@ // This tree represents the subset relationship between these macros, where if a // specific x-macro isn't defined, it'll fall back to the parent macro. // -// Parse nodes are clustered based on language feature. Comments will show their -// relationship in postorder, using indentation for child node relationships. +// Parse nodes are clustered based on language feature. See typed_nodes.h for +// the expected tree structure under each node kind. -#if !(defined(CARBON_PARSE_NODE_KIND) || \ - (defined(CARBON_PARSE_NODE_KIND_BRACKET) && \ - defined(CARBON_PARSE_NODE_KIND_CHILD_COUNT))) +#if !(defined(CARBON_PARSE_NODE_KIND) || \ + defined(CARBON_PARSE_NODE_KIND_WITH_TOKEN)) #error "Must define CARBON_PARSE_NODE_KIND family x-macros to use this file." #endif -// The BRACKET and CHILD_COUNT macros will use CARBON_PARSE_NODE_KIND by default -// when undefined. -#ifndef CARBON_PARSE_NODE_KIND_BRACKET -#define CARBON_PARSE_NODE_KIND_BRACKET(Name, ...) CARBON_PARSE_NODE_KIND(Name) -#endif -#ifndef CARBON_PARSE_NODE_KIND_CHILD_COUNT -#define CARBON_PARSE_NODE_KIND_CHILD_COUNT(Name, ...) \ +// The WITH_TOKEN macro will use CARBON_PARSE_NODE_KIND by default when +// undefined. +#ifndef CARBON_PARSE_NODE_KIND_WITH_TOKEN +#define CARBON_PARSE_NODE_KIND_WITH_TOKEN(Name, LexTokenKind) \ CARBON_PARSE_NODE_KIND(Name) #endif @@ -65,7 +57,7 @@ // #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_CHILD_COUNT(PrefixOperator##Name, 1, Name) + CARBON_PARSE_NODE_KIND_WITH_TOKEN(PrefixOperator##Name, Name) #endif // This is expected to be used with something like: @@ -75,7 +67,7 @@ // #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_CHILD_COUNT(InfixOperator##Name, 2, Name) + CARBON_PARSE_NODE_KIND_WITH_TOKEN(InfixOperator##Name, Name) #endif // This is expected to be used with something like: @@ -85,7 +77,7 @@ // #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_CHILD_COUNT(PostfixOperator##Name, 1, Name) + CARBON_PARSE_NODE_KIND_WITH_TOKEN(PostfixOperator##Name, Name) #endif // This is expected to be used with something like: @@ -95,7 +87,7 @@ // #define CARBON_PARSE_NODE_KIND_TOKEN_LITERAL(Name, ...) #ifndef CARBON_PARSE_NODE_KIND_TOKEN_LITERAL #define CARBON_PARSE_NODE_KIND_TOKEN_LITERAL(Name, LexTokenKinds) \ - CARBON_PARSE_NODE_KIND_CHILD_COUNT(Name, 0, LexTokenKinds) + CARBON_PARSE_NODE_KIND_WITH_TOKEN(Name, LexTokenKinds) #endif // This is expected to be used with something like: @@ -105,49 +97,48 @@ // #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_CHILD_COUNT(Name##Modifier, 0, Name) + CARBON_PARSE_NODE_KIND_WITH_TOKEN(Name##Modifier, Name) #endif // The start of the file. -CARBON_PARSE_NODE_KIND_CHILD_COUNT(FileStart, 0, FileStart) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(FileStart, FileStart) // The end of the file. -CARBON_PARSE_NODE_KIND_CHILD_COUNT(FileEnd, 0, FileEnd) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(FileEnd, FileEnd) // An invalid parse. Used to balance the parse tree. Always has an error. -CARBON_PARSE_NODE_KIND_CHILD_COUNT(InvalidParse, 0, Error) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(InvalidParse, Error) // An invalid subtree. Always has an error. -CARBON_PARSE_NODE_KIND_CHILD_COUNT(InvalidParseStart, 0, Error) -CARBON_PARSE_NODE_KIND_BRACKET(InvalidParseSubtree, InvalidParseStart, Error) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(InvalidParseStart, Error) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(InvalidParseSubtree, Error) // A placeholder node to be replaced; it will never exist in a valid parse tree. // Its token kind is not enforced even when valid. -CARBON_PARSE_NODE_KIND_CHILD_COUNT(Placeholder, 0, Error) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(Placeholder, Error) // An empty declaration, such as `;`. -CARBON_PARSE_NODE_KIND_CHILD_COUNT(EmptyDecl, 0, CARBON_IF_VALID(Semi)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(EmptyDecl, CARBON_IF_VALID(Semi)) // An identifier name in a non-expression context, such as a declaration. -CARBON_PARSE_NODE_KIND_CHILD_COUNT(IdentifierName, 0, - CARBON_IF_VALID(Identifier)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(IdentifierName, CARBON_IF_VALID(Identifier)) // An identifier name in an expression context. -CARBON_PARSE_NODE_KIND_CHILD_COUNT(IdentifierNameExpr, 0, Identifier) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(IdentifierNameExpr, Identifier) // The `self` value and `Self` type identifier keywords. Typically of the form // `self: Self`. -CARBON_PARSE_NODE_KIND_CHILD_COUNT(SelfValueName, 0, SelfValueIdentifier) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(SelfValueNameExpr, 0, SelfValueIdentifier) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(SelfTypeNameExpr, 0, SelfTypeIdentifier) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(SelfValueName, SelfValueIdentifier) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(SelfValueNameExpr, SelfValueIdentifier) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(SelfTypeNameExpr, SelfTypeIdentifier) // The `base` value keyword, introduced by `base: B`. Typically referenced in // an expression, as in `x.base` or `{.base = ...}`, but can also be used as a // declared name, as in `{.base: partial B}`. -CARBON_PARSE_NODE_KIND_CHILD_COUNT(BaseName, 0, Base) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(BaseName, Base) // The `package` keyword in an expression. -CARBON_PARSE_NODE_KIND_CHILD_COUNT(PackageExpr, 0, Package) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(PackageExpr, Package) // ---------------------------------------------------------------------------- @@ -177,8 +168,8 @@ CARBON_PARSE_NODE_KIND_CHILD_COUNT(PackageExpr, 0, Package) // ---------------------------------------------------------------------------- // The name of a package or library for `package`, `import`, and `library`. -CARBON_PARSE_NODE_KIND_CHILD_COUNT(PackageName, 0, Identifier) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(LibraryName, 0, StringLiteral) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(PackageName, Identifier) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(LibraryName, StringLiteral) // `package`: // PackageIntroducer @@ -186,9 +177,8 @@ CARBON_PARSE_NODE_KIND_CHILD_COUNT(LibraryName, 0, StringLiteral) // _optional_ _external_: PackageName // _optional_ _external_: LibrarySpecifier // PackageDecl -CARBON_PARSE_NODE_KIND_CHILD_COUNT(PackageIntroducer, 0, Package) -CARBON_PARSE_NODE_KIND_BRACKET(PackageDecl, PackageIntroducer, - CARBON_IF_VALID(Semi)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(PackageIntroducer, Package) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(PackageDecl, CARBON_IF_VALID(Semi)) // `import`: // ImportIntroducer @@ -196,24 +186,22 @@ CARBON_PARSE_NODE_KIND_BRACKET(PackageDecl, PackageIntroducer, // _optional_ _external_: PackageName // _optional_ _external_: LibrarySpecifier // ImportDecl -CARBON_PARSE_NODE_KIND_CHILD_COUNT(ImportIntroducer, 0, Import) -CARBON_PARSE_NODE_KIND_BRACKET(ImportDecl, ImportIntroducer, - CARBON_IF_VALID(Semi)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(ImportIntroducer, Import) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(ImportDecl, CARBON_IF_VALID(Semi)) // `library` as declaration: // LibraryIntroducer // _repeated_ _external_: modifier // DefaultLibrary or _external_: LibraryName // LibraryDecl -CARBON_PARSE_NODE_KIND_CHILD_COUNT(DefaultLibrary, 0, Default) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(LibraryIntroducer, 0, Library) -CARBON_PARSE_NODE_KIND_BRACKET(LibraryDecl, LibraryIntroducer, - CARBON_IF_VALID(Semi)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(DefaultLibrary, Default) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(LibraryIntroducer, Library) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(LibraryDecl, CARBON_IF_VALID(Semi)) // `library` in `package` or `import`: // _external_: LibraryName or DefaultLibrary // LibrarySpecifier -CARBON_PARSE_NODE_KIND_CHILD_COUNT(LibrarySpecifier, 1, Library) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(LibrarySpecifier, Library) // Declaration names. // @@ -227,33 +215,30 @@ CARBON_PARSE_NODE_KIND_CHILD_COUNT(LibrarySpecifier, 1, Library) // _optional_ _external_: ImplicitParamList // _optional_ _external_: TuplePattern // NameQualifier -CARBON_PARSE_NODE_KIND_BRACKET(NameQualifier, IdentifierName, - CARBON_IF_VALID(Period)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(NameQualifier, CARBON_IF_VALID(Period)) // `export`: // ExportIntroducer // _external_: _declaration name_ // ExportDecl -CARBON_PARSE_NODE_KIND_CHILD_COUNT(ExportIntroducer, 0, Export) -CARBON_PARSE_NODE_KIND_BRACKET(ExportDecl, ExportIntroducer, - CARBON_IF_VALID(Semi)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(ExportIntroducer, Export) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(ExportDecl, CARBON_IF_VALID(Semi)) // `namespace`: // NamespaceStart // _repeated_ _external_: modifier // _external_: _declaration name_ // Namespace -CARBON_PARSE_NODE_KIND_CHILD_COUNT(NamespaceStart, 0, Namespace) -CARBON_PARSE_NODE_KIND_BRACKET(Namespace, NamespaceStart, CARBON_IF_VALID(Semi)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(NamespaceStart, Namespace) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(Namespace, CARBON_IF_VALID(Semi)) // A code block: // CodeBlockStart // _repeated_ _external_: statement // CodeBlock -CARBON_PARSE_NODE_KIND_CHILD_COUNT(CodeBlockStart, 0, - CARBON_IF_VALID(OpenCurlyBrace)) -CARBON_PARSE_NODE_KIND_BRACKET(CodeBlock, CodeBlockStart, - CARBON_IF_VALID(CloseCurlyBrace)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(CodeBlockStart, + CARBON_IF_VALID(OpenCurlyBrace)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(CodeBlock, CARBON_IF_VALID(CloseCurlyBrace)) // `fn` declarations start with a function signature: // @@ -277,20 +262,15 @@ CARBON_PARSE_NODE_KIND_BRACKET(CodeBlock, CodeBlockStart, // BuiltinFunctionDefinitionStart // BuiltinName // BuiltinFunctionDefinition -CARBON_PARSE_NODE_KIND_CHILD_COUNT(FunctionIntroducer, 0, Fn) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(ReturnType, 1, MinusGreater) -CARBON_PARSE_NODE_KIND_BRACKET(FunctionDefinitionStart, FunctionIntroducer, - OpenCurlyBrace) -CARBON_PARSE_NODE_KIND_BRACKET(FunctionDefinition, FunctionDefinitionStart, - CloseCurlyBrace) -CARBON_PARSE_NODE_KIND_BRACKET(FunctionDecl, FunctionIntroducer, - CARBON_IF_VALID(Semi)) -CARBON_PARSE_NODE_KIND_BRACKET(BuiltinFunctionDefinitionStart, - FunctionIntroducer, Equal) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(BuiltinName, 0, StringLiteral) -CARBON_PARSE_NODE_KIND_BRACKET(BuiltinFunctionDefinition, - BuiltinFunctionDefinitionStart, - CARBON_IF_VALID(Semi)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(FunctionIntroducer, Fn) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(ReturnType, MinusGreater) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(FunctionDefinitionStart, OpenCurlyBrace) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(FunctionDefinition, CloseCurlyBrace) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(FunctionDecl, CARBON_IF_VALID(Semi)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(BuiltinFunctionDefinitionStart, Equal) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(BuiltinName, StringLiteral) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(BuiltinFunctionDefinition, + CARBON_IF_VALID(Semi)) // `alias`: // AliasIntroducer @@ -299,9 +279,9 @@ CARBON_PARSE_NODE_KIND_BRACKET(BuiltinFunctionDefinition, // AliasInitializer // _external_: expression // Alias -CARBON_PARSE_NODE_KIND_CHILD_COUNT(AliasIntroducer, 0, Alias) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(AliasInitializer, 0, Equal) -CARBON_PARSE_NODE_KIND_BRACKET(Alias, AliasIntroducer, CARBON_IF_VALID(Semi)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(AliasIntroducer, Alias) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(AliasInitializer, Equal) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(Alias, CARBON_IF_VALID(Semi)) // A tuple pattern: // TuplePatternStart @@ -312,9 +292,9 @@ CARBON_PARSE_NODE_KIND_BRACKET(Alias, AliasIntroducer, CARBON_IF_VALID(Semi)) // // Patterns and PatternListComma may repeat with PatternListComma as a // separator. -CARBON_PARSE_NODE_KIND_CHILD_COUNT(TuplePatternStart, 0, OpenParen) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(PatternListComma, 0, Comma) -CARBON_PARSE_NODE_KIND_BRACKET(TuplePattern, TuplePatternStart, CloseParen) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(TuplePatternStart, OpenParen) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(PatternListComma, Comma) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(TuplePattern, CloseParen) // An implicit parameter list: // ImplicitParamListStart @@ -325,9 +305,8 @@ CARBON_PARSE_NODE_KIND_BRACKET(TuplePattern, TuplePatternStart, CloseParen) // // Patterns and PatternListComma may repeat with PatternListComma as a // separator. -CARBON_PARSE_NODE_KIND_CHILD_COUNT(ImplicitParamListStart, 0, OpenSquareBracket) -CARBON_PARSE_NODE_KIND_BRACKET(ImplicitParamList, ImplicitParamListStart, - CloseSquareBracket) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(ImplicitParamListStart, OpenSquareBracket) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(ImplicitParamList, CloseSquareBracket) // An array type, such as `[i32; 3]` or `[i32;]`: // ArrayExprStart @@ -335,9 +314,9 @@ CARBON_PARSE_NODE_KIND_BRACKET(ImplicitParamList, ImplicitParamListStart, // ArrayExprSemi // _optional_ _external_: expression // ArrayExpr -CARBON_PARSE_NODE_KIND_CHILD_COUNT(ArrayExprStart, 0, OpenSquareBracket) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(ArrayExprSemi, 2, CARBON_IF_VALID(Semi)) -CARBON_PARSE_NODE_KIND_BRACKET(ArrayExpr, ArrayExprSemi, CloseSquareBracket) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(ArrayExprStart, OpenSquareBracket) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(ArrayExprSemi, CARBON_IF_VALID(Semi)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(ArrayExpr, CloseSquareBracket) // A binding pattern, such as `name: Type`: // IdentifierName or SelfValueName @@ -345,10 +324,10 @@ CARBON_PARSE_NODE_KIND_BRACKET(ArrayExpr, ArrayExprSemi, CloseSquareBracket) // [Generic]BindingPattern // _optional_ Addr // _optional_ Template -CARBON_PARSE_NODE_KIND_CHILD_COUNT(BindingPattern, 2, CARBON_IF_VALID(Colon)) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(CompileTimeBindingPattern, 2, ColonExclaim) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(Addr, 1, Addr) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(Template, 1, Template) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(BindingPattern, CARBON_IF_VALID(Colon)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(CompileTimeBindingPattern, ColonExclaim) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(Addr, Addr) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(Template, Template) // `let` declarations, including associated constant declarations: // LetIntroducer @@ -363,9 +342,9 @@ CARBON_PARSE_NODE_KIND_CHILD_COUNT(Template, 1, Template) // // The LetInitializer and following expression are paired: either both will be // present, or neither will. -CARBON_PARSE_NODE_KIND_CHILD_COUNT(LetIntroducer, 0, Let) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(LetInitializer, 0, Equal) -CARBON_PARSE_NODE_KIND_BRACKET(LetDecl, LetIntroducer, CARBON_IF_VALID(Semi)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(LetIntroducer, Let) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(LetInitializer, Equal) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(LetDecl, CARBON_IF_VALID(Semi)) // `var` and `returned var`: // VariableIntroducer @@ -382,37 +361,35 @@ CARBON_PARSE_NODE_KIND_BRACKET(LetDecl, LetIntroducer, CARBON_IF_VALID(Semi)) // // The VariableInitializer and following expression are paired: either both will // be present, or neither will. -CARBON_PARSE_NODE_KIND_CHILD_COUNT(VariableIntroducer, 0, CARBON_IF_VALID(Var)) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(ReturnedModifier, 0, Returned) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(VariableInitializer, 0, Equal) -CARBON_PARSE_NODE_KIND_BRACKET(VariableDecl, VariableIntroducer, - CARBON_IF_VALID(Semi)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(VariableIntroducer, CARBON_IF_VALID(Var)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(ReturnedModifier, Returned) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(VariableInitializer, Equal) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(VariableDecl, CARBON_IF_VALID(Semi)) // An expression statement: // _external_: expression // ExprStatement -CARBON_PARSE_NODE_KIND_CHILD_COUNT(ExprStatement, 1, CARBON_IF_VALID(Semi)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(ExprStatement, CARBON_IF_VALID(Semi)) // `break`: // BreakStatementStart // BreakStatement -CARBON_PARSE_NODE_KIND_CHILD_COUNT(BreakStatementStart, 0, Break) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(BreakStatement, 1, CARBON_IF_VALID(Semi)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(BreakStatementStart, Break) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(BreakStatement, CARBON_IF_VALID(Semi)) // `continue`: // ContinueStatementStart // ContinueStatement -CARBON_PARSE_NODE_KIND_CHILD_COUNT(ContinueStatementStart, 0, Continue) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(ContinueStatement, 1, CARBON_IF_VALID(Semi)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(ContinueStatementStart, Continue) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(ContinueStatement, CARBON_IF_VALID(Semi)) // `return`: // ReturnStatementStart // _optional_ ReturnVarModifier or _external_: expression // ReturnStatement -CARBON_PARSE_NODE_KIND_CHILD_COUNT(ReturnStatementStart, 0, Return) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(ReturnVarModifier, 0, Var) -CARBON_PARSE_NODE_KIND_BRACKET(ReturnStatement, ReturnStatementStart, - CARBON_IF_VALID(Semi)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(ReturnStatementStart, Return) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(ReturnVarModifier, Var) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(ReturnStatement, CARBON_IF_VALID(Semi)) // `for`: // ForHeaderStart @@ -425,12 +402,10 @@ CARBON_PARSE_NODE_KIND_BRACKET(ReturnStatement, ReturnStatementStart, // ForStatement // // Versus a normal `var`, ForIn replaces VariableDecl. -CARBON_PARSE_NODE_KIND_CHILD_COUNT(ForHeaderStart, 0, - CARBON_IF_VALID(OpenParen)) -CARBON_PARSE_NODE_KIND_BRACKET(ForIn, VariableIntroducer, CARBON_IF_VALID(In)) -CARBON_PARSE_NODE_KIND_BRACKET(ForHeader, ForHeaderStart, - CARBON_IF_VALID(CloseParen)) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(ForStatement, 2, For) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(ForHeaderStart, CARBON_IF_VALID(OpenParen)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(ForIn, CARBON_IF_VALID(In)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(ForHeader, CARBON_IF_VALID(CloseParen)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(ForStatement, For) // `if` statement + `else`: // IfConditionStart @@ -442,12 +417,10 @@ CARBON_PARSE_NODE_KIND_CHILD_COUNT(ForStatement, 2, For) // IfStatement // // IfStatementElse and the following node are optional based on `else` presence. -CARBON_PARSE_NODE_KIND_CHILD_COUNT(IfConditionStart, 0, - CARBON_IF_VALID(OpenParen)) -CARBON_PARSE_NODE_KIND_BRACKET(IfCondition, IfConditionStart, - CARBON_IF_VALID(CloseParen)) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(IfStatementElse, 0, Else) -CARBON_PARSE_NODE_KIND_BRACKET(IfStatement, IfCondition, If) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(IfConditionStart, CARBON_IF_VALID(OpenParen)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(IfCondition, CARBON_IF_VALID(CloseParen)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(IfStatementElse, Else) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(IfStatement, If) // `while`: // WhileConditionStart @@ -455,26 +428,25 @@ CARBON_PARSE_NODE_KIND_BRACKET(IfStatement, IfCondition, If) // WhileCondition // _external_: CodeBlock // WhileStatement -CARBON_PARSE_NODE_KIND_CHILD_COUNT(WhileConditionStart, 0, - CARBON_IF_VALID(OpenParen)) -CARBON_PARSE_NODE_KIND_BRACKET(WhileCondition, WhileConditionStart, - CARBON_IF_VALID(CloseParen)) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(WhileStatement, 2, While) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(WhileConditionStart, + CARBON_IF_VALID(OpenParen)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(WhileCondition, CARBON_IF_VALID(CloseParen)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(WhileStatement, While) // Index expressions, such as `a[1]`: // _external_: expression // IndexExprStart // _external_: expression // IndexExpr -CARBON_PARSE_NODE_KIND_CHILD_COUNT(IndexExprStart, 1, OpenSquareBracket) -CARBON_PARSE_NODE_KIND_BRACKET(IndexExpr, IndexExprStart, CloseSquareBracket) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(IndexExprStart, OpenSquareBracket) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(IndexExpr, CloseSquareBracket) // Parenthesized single expressions, such as `(2)`: // ParenExprStart // _external_: expression // ParenExpr -CARBON_PARSE_NODE_KIND_CHILD_COUNT(ParenExprStart, 0, OpenParen) -CARBON_PARSE_NODE_KIND_BRACKET(ParenExpr, ParenExprStart, CloseParen) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(ParenExprStart, OpenParen) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(ParenExpr, CloseParen) // Tuples, such as `(1, 2)`: // TupleLiteralStart @@ -485,9 +457,9 @@ CARBON_PARSE_NODE_KIND_BRACKET(ParenExpr, ParenExprStart, CloseParen) // // Expressions and TupleLiteralComma may repeat with TupleLiteralComma as a // separator. -CARBON_PARSE_NODE_KIND_CHILD_COUNT(TupleLiteralStart, 0, OpenParen) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(TupleLiteralComma, 0, Comma) -CARBON_PARSE_NODE_KIND_BRACKET(TupleLiteral, TupleLiteralStart, CloseParen) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(TupleLiteralStart, OpenParen) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(TupleLiteralComma, Comma) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(TupleLiteral, CloseParen) // Call expressions, such as `a()`: // _external_: expression @@ -498,23 +470,23 @@ CARBON_PARSE_NODE_KIND_BRACKET(TupleLiteral, TupleLiteralStart, CloseParen) // CallExpr // // Exprs and CallExprComma may repeat with CallExprComma as a separator. -CARBON_PARSE_NODE_KIND_CHILD_COUNT(CallExprStart, 1, OpenParen) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(CallExprComma, 0, Comma) -CARBON_PARSE_NODE_KIND_BRACKET(CallExpr, CallExprStart, CloseParen) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(CallExprStart, OpenParen) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(CallExprComma, Comma) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(CallExpr, CloseParen) // A member access expression, such as `a.b` or // `GetObject().(Interface.member)`: // _external_: lhs expression // _external_: rhs expression // MemberAccessExpr -CARBON_PARSE_NODE_KIND_CHILD_COUNT(MemberAccessExpr, 2, Period) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(MemberAccessExpr, Period) // A pointer member access expression, such as `a->b` or // `GetObject()->(Interface.member)`: // _external_: lhs expression // _external_: rhs expression // PointerMemberAccessExpr -CARBON_PARSE_NODE_KIND_CHILD_COUNT(PointerMemberAccessExpr, 2, MinusGreater) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(PointerMemberAccessExpr, MinusGreater) // A value literal. CARBON_PARSE_NODE_KIND_TOKEN_LITERAL(BoolLiteralFalse, False) @@ -589,10 +561,10 @@ CARBON_PARSE_NODE_KIND_POSTFIX_OPERATOR(Star) // ShortCircuitOperand(And|Or) // _external_: expression // ShortCircuitOperand(And|Or) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(ShortCircuitOperandAnd, 1, And) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(ShortCircuitOperandOr, 1, Or) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(ShortCircuitOperatorAnd, 2, And) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(ShortCircuitOperatorOr, 2, Or) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(ShortCircuitOperandAnd, And) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(ShortCircuitOperandOr, Or) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(ShortCircuitOperatorAnd, And) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(ShortCircuitOperatorOr, Or) // `if` expression + `then` + `else`: // _external_: expression @@ -601,9 +573,9 @@ CARBON_PARSE_NODE_KIND_CHILD_COUNT(ShortCircuitOperatorOr, 2, Or) // IfExprThen // _external_: expression // IfExprElse -CARBON_PARSE_NODE_KIND_CHILD_COUNT(IfExprIf, 1, If) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(IfExprThen, 1, Then) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(IfExprElse, 3, CARBON_IF_VALID(Else)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(IfExprIf, If) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(IfExprThen, Then) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(IfExprElse, CARBON_IF_VALID(Else)) // Struct literals, such as `{.a = 0}`: // StructLiteralStart @@ -631,16 +603,14 @@ CARBON_PARSE_NODE_KIND_CHILD_COUNT(IfExprElse, 3, CARBON_IF_VALID(Else)) // When a valid StructTypeField or StructField cannot be formed, elements // may be replaced by InvalidParse, which may have a preceding sibling // StructFieldDesignator if one was successfully parsed. -CARBON_PARSE_NODE_KIND_CHILD_COUNT(StructLiteralStart, 0, OpenCurlyBrace) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(StructTypeLiteralStart, 0, OpenCurlyBrace) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(StructFieldDesignator, 1, Period) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(StructField, 2, Equal) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(StructTypeField, 2, Colon) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(StructComma, 0, Comma) -CARBON_PARSE_NODE_KIND_BRACKET(StructLiteral, StructLiteralStart, - CloseCurlyBrace) -CARBON_PARSE_NODE_KIND_BRACKET(StructTypeLiteral, StructTypeLiteralStart, - CloseCurlyBrace) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(StructLiteralStart, OpenCurlyBrace) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(StructTypeLiteralStart, OpenCurlyBrace) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(StructFieldDesignator, Period) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(StructField, Equal) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(StructTypeField, Colon) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(StructComma, Comma) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(StructLiteral, CloseCurlyBrace) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(StructTypeLiteral, CloseCurlyBrace) // Various modifiers. These are all a single token. CARBON_PARSE_NODE_KIND_TOKEN_MODIFIER(Abstract) @@ -668,22 +638,18 @@ CARBON_PARSE_NODE_KIND_TOKEN_MODIFIER(Virtual) // The above is the structure for a definition; for a declaration, // ClassDefinitionStart and later nodes are removed and replaced by // ClassDecl. -CARBON_PARSE_NODE_KIND_CHILD_COUNT(ClassIntroducer, 0, Class) -CARBON_PARSE_NODE_KIND_BRACKET(ClassDefinitionStart, ClassIntroducer, - OpenCurlyBrace) -CARBON_PARSE_NODE_KIND_BRACKET(ClassDefinition, ClassDefinitionStart, - CloseCurlyBrace) -CARBON_PARSE_NODE_KIND_BRACKET(ClassDecl, ClassIntroducer, - CARBON_IF_VALID(Semi)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(ClassIntroducer, Class) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(ClassDefinitionStart, OpenCurlyBrace) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(ClassDefinition, CloseCurlyBrace) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(ClassDecl, CARBON_IF_VALID(Semi)) // `adapt`: // AdaptIntroducer // _repeated_ _external_: modifier // _external_: expression // AdaptDecl -CARBON_PARSE_NODE_KIND_CHILD_COUNT(AdaptIntroducer, 0, Adapt) -CARBON_PARSE_NODE_KIND_BRACKET(AdaptDecl, AdaptIntroducer, - CARBON_IF_VALID(Semi)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(AdaptIntroducer, Adapt) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(AdaptDecl, CARBON_IF_VALID(Semi)) // `base`: // BaseIntroducer @@ -691,9 +657,9 @@ CARBON_PARSE_NODE_KIND_BRACKET(AdaptDecl, AdaptIntroducer, // BaseColon // _external_: expression // BaseDecl -CARBON_PARSE_NODE_KIND_CHILD_COUNT(BaseIntroducer, 0, Base) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(BaseColon, 0, Colon) -CARBON_PARSE_NODE_KIND_BRACKET(BaseDecl, BaseIntroducer, CARBON_IF_VALID(Semi)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(BaseIntroducer, Base) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(BaseColon, Colon) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(BaseDecl, CARBON_IF_VALID(Semi)) // `interface`: // InterfaceIntroducer @@ -708,13 +674,10 @@ CARBON_PARSE_NODE_KIND_BRACKET(BaseDecl, BaseIntroducer, CARBON_IF_VALID(Semi)) // The above is the structure for a definition; for a declaration, // InterfaceDefinitionStart and later nodes are removed and replaced by // InterfaceDecl. -CARBON_PARSE_NODE_KIND_CHILD_COUNT(InterfaceIntroducer, 0, Interface) -CARBON_PARSE_NODE_KIND_BRACKET(InterfaceDefinitionStart, InterfaceIntroducer, - OpenCurlyBrace) -CARBON_PARSE_NODE_KIND_BRACKET(InterfaceDefinition, InterfaceDefinitionStart, - CloseCurlyBrace) -CARBON_PARSE_NODE_KIND_BRACKET(InterfaceDecl, InterfaceIntroducer, - CARBON_IF_VALID(Semi)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(InterfaceIntroducer, Interface) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(InterfaceDefinitionStart, OpenCurlyBrace) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(InterfaceDefinition, CloseCurlyBrace) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(InterfaceDecl, CARBON_IF_VALID(Semi)) // `impl ... as`: // ImplIntroducer @@ -730,24 +693,22 @@ CARBON_PARSE_NODE_KIND_BRACKET(InterfaceDecl, InterfaceIntroducer, // The above is the structure for a definition; for a declaration, // ImplDefinitionStart and later nodes are removed and replaced by // ImplDecl. -CARBON_PARSE_NODE_KIND_CHILD_COUNT(ImplIntroducer, 0, Impl) -CARBON_PARSE_NODE_KIND_BRACKET(ImplDefinitionStart, ImplIntroducer, - OpenCurlyBrace) -CARBON_PARSE_NODE_KIND_BRACKET(ImplDefinition, ImplDefinitionStart, - CloseCurlyBrace) -CARBON_PARSE_NODE_KIND_BRACKET(ImplDecl, ImplIntroducer, CARBON_IF_VALID(Semi)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(ImplIntroducer, Impl) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(ImplDefinitionStart, OpenCurlyBrace) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(ImplDefinition, CloseCurlyBrace) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(ImplDecl, CARBON_IF_VALID(Semi)) // `forall ...`: // _external_: ImplicitParamList // ImplForall -CARBON_PARSE_NODE_KIND_CHILD_COUNT(ImplForall, 1, Forall) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(ImplForall, Forall) // `... as`: // _external_: expression // TypeImplAs -CARBON_PARSE_NODE_KIND_CHILD_COUNT(TypeImplAs, 1, As) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(TypeImplAs, As) // `as` without a type before it -CARBON_PARSE_NODE_KIND_CHILD_COUNT(DefaultSelfImplAs, 0, As) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(DefaultSelfImplAs, As) // `constraint`: // NamedConstraintIntroducer @@ -762,13 +723,11 @@ CARBON_PARSE_NODE_KIND_CHILD_COUNT(DefaultSelfImplAs, 0, As) // The above is the structure for a definition; for a declaration, // NamedConstraintDefinitionStart and later nodes are removed and replaced by // NamedConstraintDecl. -CARBON_PARSE_NODE_KIND_CHILD_COUNT(NamedConstraintIntroducer, 0, Constraint) -CARBON_PARSE_NODE_KIND_BRACKET(NamedConstraintDefinitionStart, - NamedConstraintIntroducer, OpenCurlyBrace) -CARBON_PARSE_NODE_KIND_BRACKET(NamedConstraintDefinition, - NamedConstraintDefinitionStart, CloseCurlyBrace) -CARBON_PARSE_NODE_KIND_BRACKET(NamedConstraintDecl, NamedConstraintIntroducer, - CARBON_IF_VALID(Semi)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(NamedConstraintIntroducer, Constraint) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(NamedConstraintDefinitionStart, + OpenCurlyBrace) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(NamedConstraintDefinition, CloseCurlyBrace) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(NamedConstraintDecl, CARBON_IF_VALID(Semi)) // `choice`: // ChoiceIntroducer @@ -776,11 +735,11 @@ CARBON_PARSE_NODE_KIND_BRACKET(NamedConstraintDecl, NamedConstraintIntroducer, // ChoiceDefinitionStart // _optional_ _external_: ChoiceAlternativeList // ChoiceDefinition -CARBON_PARSE_NODE_KIND_CHILD_COUNT(ChoiceIntroducer, 0, Choice) -CARBON_PARSE_NODE_KIND_BRACKET(ChoiceDefinitionStart, ChoiceIntroducer, - CARBON_IF_VALID(OpenCurlyBrace)) -CARBON_PARSE_NODE_KIND_BRACKET(ChoiceDefinition, ChoiceDefinitionStart, - CARBON_IF_VALID(CloseCurlyBrace)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(ChoiceIntroducer, Choice) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(ChoiceDefinitionStart, + CARBON_IF_VALID(OpenCurlyBrace)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(ChoiceDefinition, + CARBON_IF_VALID(CloseCurlyBrace)) // Choice alternative list: // _external_: IdentifierName @@ -788,7 +747,7 @@ CARBON_PARSE_NODE_KIND_BRACKET(ChoiceDefinition, ChoiceDefinitionStart, // _optional_: ChoiceAlternativeListComma // _repeated_ // ChoiceAlternativeList -CARBON_PARSE_NODE_KIND_CHILD_COUNT(ChoiceAlternativeListComma, 0, Comma) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(ChoiceAlternativeListComma, Comma) // `match`: // MatchIntroducer @@ -799,15 +758,14 @@ CARBON_PARSE_NODE_KIND_CHILD_COUNT(ChoiceAlternativeListComma, 0, Comma) // _repeated_ _external_: MatchCase // _optional_ _external_: MatchStatementDefault // MatchStatement -CARBON_PARSE_NODE_KIND_CHILD_COUNT(MatchIntroducer, 0, Match) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(MatchConditionStart, 0, - CARBON_IF_VALID(OpenParen)) -CARBON_PARSE_NODE_KIND_BRACKET(MatchCondition, MatchConditionStart, - CARBON_IF_VALID(CloseParen)) -CARBON_PARSE_NODE_KIND_BRACKET(MatchStatementStart, MatchIntroducer, - CARBON_IF_VALID(OpenCurlyBrace)) -CARBON_PARSE_NODE_KIND_BRACKET(MatchStatement, MatchStatementStart, - CARBON_IF_VALID(CloseCurlyBrace)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(MatchIntroducer, Match) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(MatchConditionStart, + CARBON_IF_VALID(OpenParen)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(MatchCondition, CARBON_IF_VALID(CloseParen)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(MatchStatementStart, + CARBON_IF_VALID(OpenCurlyBrace)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(MatchStatement, + CARBON_IF_VALID(CloseCurlyBrace)) // `case`: // MatchCaseIntroducer @@ -820,18 +778,16 @@ CARBON_PARSE_NODE_KIND_BRACKET(MatchStatement, MatchStatementStart, // MatchCaseStart // _repeated_ _external_: statement // MatchCase -CARBON_PARSE_NODE_KIND_CHILD_COUNT(MatchCaseIntroducer, 0, Case) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(MatchCaseGuardIntroducer, 0, If) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(MatchCaseGuardStart, 0, - CARBON_IF_VALID(OpenParen)) -CARBON_PARSE_NODE_KIND_BRACKET(MatchCaseGuard, MatchCaseGuardIntroducer, - CARBON_IF_VALID(CloseParen)) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(MatchCaseEqualGreater, 0, - CARBON_IF_VALID(EqualGreater)) -CARBON_PARSE_NODE_KIND_BRACKET(MatchCaseStart, MatchCaseIntroducer, - CARBON_IF_VALID(OpenCurlyBrace)) -CARBON_PARSE_NODE_KIND_BRACKET(MatchCase, MatchCaseStart, - CARBON_IF_VALID(CloseCurlyBrace)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(MatchCaseIntroducer, Case) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(MatchCaseGuardIntroducer, If) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(MatchCaseGuardStart, + CARBON_IF_VALID(OpenParen)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(MatchCaseGuard, CARBON_IF_VALID(CloseParen)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(MatchCaseEqualGreater, + CARBON_IF_VALID(EqualGreater)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(MatchCaseStart, + CARBON_IF_VALID(OpenCurlyBrace)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(MatchCase, CARBON_IF_VALID(CloseCurlyBrace)) // `default`: // MatchDefaultIntroducer @@ -839,17 +795,16 @@ CARBON_PARSE_NODE_KIND_BRACKET(MatchCase, MatchCaseStart, // MatchDefaultStart // _repeated_ _external_: statement // MatchDefault -CARBON_PARSE_NODE_KIND_CHILD_COUNT(MatchDefaultIntroducer, 0, Default) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(MatchDefaultEqualGreater, 0, - CARBON_IF_VALID(EqualGreater)) -CARBON_PARSE_NODE_KIND_BRACKET(MatchDefaultStart, MatchDefaultIntroducer, - CARBON_IF_VALID(OpenCurlyBrace)) -CARBON_PARSE_NODE_KIND_BRACKET(MatchDefault, MatchDefaultStart, - CARBON_IF_VALID(CloseCurlyBrace)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(MatchDefaultIntroducer, Default) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(MatchDefaultEqualGreater, + CARBON_IF_VALID(EqualGreater)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(MatchDefaultStart, + CARBON_IF_VALID(OpenCurlyBrace)) +CARBON_PARSE_NODE_KIND_WITH_TOKEN(MatchDefault, + CARBON_IF_VALID(CloseCurlyBrace)) #undef CARBON_PARSE_NODE_KIND -#undef CARBON_PARSE_NODE_KIND_BRACKET -#undef CARBON_PARSE_NODE_KIND_CHILD_COUNT +#undef CARBON_PARSE_NODE_KIND_WITH_TOKEN #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 555e8c67441f..a80ed85ef27d 100644 --- a/toolchain/parse/node_kind.h +++ b/toolchain/parse/node_kind.h @@ -33,7 +33,7 @@ enum class NodeCategory : uint32_t { LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/Statement) }; -inline constexpr auto operator!(NodeCategory k) -> bool { +constexpr auto operator!(NodeCategory k) -> bool { return !static_cast(k); } @@ -47,6 +47,16 @@ CARBON_DEFINE_RAW_ENUM_CLASS(NodeKind, uint8_t) { // A class wrapping an enumeration of the different kinds of nodes in the parse // tree. +// +// In order to allow the children of a node to be determined without relying on +// the subtree size field in the parse node, each node kind must have one of: +// +// - a bracketing node kind, which is always the kind for the first child, and +// is never the kind of any other child, or +// - a fixed child count, +// +// or both. This is required even for nodes for which `Tree::node_has_errors` +// returns `true`. class NodeKind : public CARBON_ENUM_BASE(NodeKind) { public: #define CARBON_PARSE_NODE_KIND(Name) CARBON_ENUM_CONSTANT_DECL(Name) @@ -57,15 +67,18 @@ class NodeKind : public CARBON_ENUM_BASE(NodeKind) { auto CheckMatchesTokenKind(Lex::TokenKind lex_token_kind, bool has_error) -> void; - // Returns true if the node is bracketed; otherwise, child_count is used. + // Returns true if the node is bracketed. auto has_bracket() const -> bool; // Returns the bracketing node kind for the current node kind. Requires that // has_bracket is true. auto bracket() const -> NodeKind; + // Returns true if the node is has a fixed child count. + auto has_child_count() const -> bool; + // Returns the number of children that the node must have, often 0. Requires - // that has_bracket is false. + // that has_child_count is true. auto child_count() const -> int32_t; // Returns which categories this node kind is in. @@ -78,11 +91,11 @@ class NodeKind : public CARBON_ENUM_BASE(NodeKind) { using EnumBase::Make; class Definition; + struct DefinitionArgs; // Provides a definition for this parse node kind. Should only be called // once, to construct the kind as part of defining it in `typed_nodes.h`. - constexpr auto Define(NodeCategory category = NodeCategory::None) const - -> Definition; + constexpr auto Define(DefinitionArgs args) const -> Definition; private: // Looks up the definition for this instruction kind. @@ -107,6 +120,17 @@ static_assert( // We expect the parse node kind to fit compactly into 8 bits. static_assert(sizeof(NodeKind) == 1, "Kind objects include padding!"); +// Optional arguments that can be supplied when defining a node kind. At least +// one of `bracketed_by` and `child_count` is required. +struct NodeKind::DefinitionArgs { + // The category for the node. + NodeCategory category = NodeCategory::None; + // The kind of the bracketing node, which is the first child. + std::optional bracketed_by = std::nullopt; + // The fixed child count. + int32_t child_count = -1; +}; + // A definition of a parse node kind. This is a NodeKind value, plus // ancillary data such as the name to use for the node kind in LLVM IR. These // are not copyable, and only one instance of this type is expected to exist per @@ -118,20 +142,58 @@ class NodeKind::Definition : public NodeKind { Definition(const Definition&) = delete; auto operator=(const Definition&) -> Definition& = delete; + // Returns true if the node is bracketed. + constexpr auto has_bracket() const -> bool { return bracket_ != *this; } + + // Returns the bracketing node kind for the current node kind. Requires that + // has_bracket is true. + constexpr auto bracket() const -> NodeKind { + CARBON_CHECK(has_bracket()) << *this; + return bracket_; + } + + // Returns true if the node is has a fixed child count. + constexpr auto has_child_count() const -> bool { return child_count_ >= 0; } + + // Returns the number of children that the node must have, often 0. Requires + // that has_child_count is true. + constexpr auto child_count() const -> int32_t { + CARBON_CHECK(has_child_count()) << *this; + return child_count_; + } + // Returns which categories this node kind is in. constexpr auto category() const -> NodeCategory { return category_; } private: friend class NodeKind; - constexpr Definition(NodeKind kind, NodeCategory category) - : NodeKind(kind), category_(category) {} + // This is factored out and non-constexpr to improve the compile-time error + // message if the check below fails. + auto MustSpecifyEitherBracketingNodeOrChildCount() { + CARBON_FATAL() + << "Must specify either bracketing node or fixed child count."; + } - NodeCategory category_; + constexpr explicit Definition(NodeKind kind, DefinitionArgs args) + : NodeKind(kind), + category_(args.category), + bracket_(args.bracketed_by.value_or(kind)), + child_count_(args.child_count) { + if (!has_bracket() && !has_child_count()) { + MustSpecifyEitherBracketingNodeOrChildCount(); + } + } + + NodeCategory category_ = NodeCategory::None; + // Nodes are never self-bracketed, so we use *this to indicate that the node + // is not bracketed. + NodeKind bracket_ = *this; + int32_t child_count_ = -1; }; -constexpr auto NodeKind::Define(NodeCategory category) const -> Definition { - return Definition(*this, category); +constexpr auto NodeKind::Define(DefinitionArgs args) const -> Definition { + return Definition(*this, args); } // HasKindMember is true if T has a `static const NodeKind::Definition Kind` diff --git a/toolchain/parse/tree.cpp b/toolchain/parse/tree.cpp index 92adb7a36823..2d15f9bc0613 100644 --- a/toolchain/parse/tree.cpp +++ b/toolchain/parse/tree.cpp @@ -211,6 +211,7 @@ auto Tree::Verify() const -> ErrorOr { int subtree_size = 1; if (n_impl.kind.has_bracket()) { + int child_count = 0; while (true) { if (nodes.empty()) { return Error( @@ -220,7 +221,17 @@ auto Tree::Verify() const -> ErrorOr { } auto child_impl = node_impls_[nodes.pop_back_val().index]; subtree_size += child_impl.subtree_size; + ++child_count; if (n_impl.kind.bracket() == child_impl.kind) { + // If there's a bracketing node and a child count, verify the child + // count too. + if (n_impl.kind.has_child_count() && + child_count != n_impl.kind.child_count()) { + return Error(llvm::formatv( + "NodeId #{0} is a {1} with child_count {2}, but encountered " + "{3} nodes before we reached the bracketing node.", + n, n_impl.kind, n_impl.kind.child_count(), child_count)); + } break; } } diff --git a/toolchain/parse/typed_nodes.h b/toolchain/parse/typed_nodes.h index af89d7935745..98ddc3972dac 100644 --- a/toolchain/parse/typed_nodes.h +++ b/toolchain/parse/typed_nodes.h @@ -29,7 +29,8 @@ using CommaSeparatedList = llvm::SmallVector>; // This class provides a shorthand for defining parse node kinds for leaf nodes. template struct LeafNode { - static constexpr auto Kind = KindT.Define(Category); + static constexpr auto Kind = + KindT.Define({.category = Category, .child_count = 0}); }; // ---------------------------------------------------------------------------- @@ -81,8 +82,9 @@ using InvalidParse = // An invalid subtree. Always has an error so can never be extracted. using InvalidParseStart = LeafNode; struct InvalidParseSubtree { - static constexpr auto Kind = - NodeKind::InvalidParseSubtree.Define(NodeCategory::Decl); + static constexpr auto Kind = NodeKind::InvalidParseSubtree.Define( + {.category = NodeCategory::Decl, + .bracketed_by = InvalidParseStart::Kind}); InvalidParseStartId start; llvm::SmallVector> extra; @@ -139,7 +141,8 @@ struct NameAndParams { // A name qualifier: `A.`, `A(T:! type).`, or `A[T:! type](N:! T).`. struct NameQualifier { - static constexpr auto Kind = NodeKind::NameQualifier.Define(); + static constexpr auto Kind = + NodeKind::NameQualifier.Define({.bracketed_by = IdentifierName::Kind}); NameAndParams name_and_params; }; @@ -166,7 +169,8 @@ using PackageIntroducer = LeafNode; // `library` in `package` or `import`. struct LibrarySpecifier { - static constexpr auto Kind = NodeKind::LibrarySpecifier.Define(); + static constexpr auto Kind = + NodeKind::LibrarySpecifier.Define({.child_count = 1}); NodeIdOneOf name; }; @@ -174,7 +178,9 @@ struct LibrarySpecifier { // First line of the file, such as: // `impl package MyPackage library "MyLibrary";` struct PackageDecl { - static constexpr auto Kind = NodeKind::PackageDecl.Define(NodeCategory::Decl); + static constexpr auto Kind = + NodeKind::PackageDecl.Define({.category = NodeCategory::Decl, + .bracketed_by = PackageIntroducer::Kind}); PackageIntroducerId introducer; llvm::SmallVector modifiers; @@ -185,7 +191,8 @@ struct PackageDecl { // `import TheirPackage library "TheirLibrary";` using ImportIntroducer = LeafNode; struct ImportDecl { - static constexpr auto Kind = NodeKind::ImportDecl.Define(NodeCategory::Decl); + static constexpr auto Kind = NodeKind::ImportDecl.Define( + {.category = NodeCategory::Decl, .bracketed_by = ImportIntroducer::Kind}); ImportIntroducerId introducer; llvm::SmallVector modifiers; @@ -196,7 +203,9 @@ struct ImportDecl { // `library` as declaration. using LibraryIntroducer = LeafNode; struct LibraryDecl { - static constexpr auto Kind = NodeKind::LibraryDecl.Define(NodeCategory::Decl); + static constexpr auto Kind = + NodeKind::LibraryDecl.Define({.category = NodeCategory::Decl, + .bracketed_by = LibraryIntroducer::Kind}); LibraryIntroducerId introducer; llvm::SmallVector modifiers; @@ -206,7 +215,8 @@ struct LibraryDecl { // `export` as a declaration. using ExportIntroducer = LeafNode; struct ExportDecl { - static constexpr auto Kind = NodeKind::ExportDecl.Define(NodeCategory::Decl); + static constexpr auto Kind = NodeKind::ExportDecl.Define( + {.category = NodeCategory::Decl, .bracketed_by = ExportIntroducer::Kind}); ExportIntroducerId introducer; llvm::SmallVector modifiers; @@ -220,7 +230,8 @@ using NamespaceStart = LeafNode; // A namespace: `namespace N;`. struct Namespace { - static constexpr auto Kind = NodeKind::Namespace.Define(NodeCategory::Decl); + static constexpr auto Kind = NodeKind::Namespace.Define( + {.category = NodeCategory::Decl, .bracketed_by = NamespaceStart::Kind}); NamespaceStartId introducer; llvm::SmallVector modifiers; @@ -232,8 +243,8 @@ struct Namespace { // A pattern binding, such as `name: Type`. struct BindingPattern { - static constexpr auto Kind = - NodeKind::BindingPattern.Define(NodeCategory::Pattern); + static constexpr auto Kind = NodeKind::BindingPattern.Define( + {.category = NodeCategory::Pattern, .child_count = 2}); NodeIdOneOf name; AnyExprId type; @@ -241,8 +252,8 @@ struct BindingPattern { // `name:! Type` struct CompileTimeBindingPattern { - static constexpr auto Kind = - NodeKind::CompileTimeBindingPattern.Define(NodeCategory::Pattern); + static constexpr auto Kind = NodeKind::CompileTimeBindingPattern.Define( + {.category = NodeCategory::Pattern, .child_count = 2}); NodeIdOneOf name; AnyExprId type; @@ -250,14 +261,16 @@ struct CompileTimeBindingPattern { // An address-of binding: `addr self: Self*`. struct Addr { - static constexpr auto Kind = NodeKind::Addr.Define(NodeCategory::Pattern); + static constexpr auto Kind = NodeKind::Addr.Define( + {.category = NodeCategory::Pattern, .child_count = 1}); AnyPatternId inner; }; // A template binding: `template T:! type`. struct Template { - static constexpr auto Kind = NodeKind::Template.Define(NodeCategory::Pattern); + static constexpr auto Kind = NodeKind::Template.Define( + {.category = NodeCategory::Pattern, .child_count = 1}); // This is a CompileTimeBindingPatternId in any valid program. // TODO: Should the parser enforce that? @@ -270,7 +283,8 @@ using PatternListComma = LeafNode; // A parameter list or tuple pattern: `(a: i32, b: i32)`. struct TuplePattern { static constexpr auto Kind = - NodeKind::TuplePattern.Define(NodeCategory::Pattern); + NodeKind::TuplePattern.Define({.category = NodeCategory::Pattern, + .bracketed_by = TuplePatternStart::Kind}); TuplePatternStartId left_paren; CommaSeparatedList params; @@ -280,7 +294,8 @@ using ImplicitParamListStart = LeafNode; // An implicit parameter list: `[T:! type, self: Self]`. struct ImplicitParamList { - static constexpr auto Kind = NodeKind::ImplicitParamList.Define(); + static constexpr auto Kind = NodeKind::ImplicitParamList.Define( + {.bracketed_by = ImplicitParamListStart::Kind}); ImplicitParamListStartId left_square; CommaSeparatedList params; @@ -293,7 +308,7 @@ using FunctionIntroducer = LeafNode; // A return type: `-> i32`. struct ReturnType { - static constexpr auto Kind = NodeKind::ReturnType.Define(); + static constexpr auto Kind = NodeKind::ReturnType.Define({.child_count = 1}); AnyExprId type; }; @@ -301,7 +316,8 @@ struct ReturnType { // A function signature: `fn F() -> i32`. template struct FunctionSignature { - static constexpr auto Kind = KindT.Define(Category); + static constexpr auto Kind = KindT.Define( + {.category = Category, .bracketed_by = FunctionIntroducer::Kind}); FunctionIntroducerId introducer; llvm::SmallVector modifiers; @@ -316,8 +332,9 @@ using FunctionDefinitionStart = // A function definition: `fn F() -> i32 { ... }`. struct FunctionDefinition { - static constexpr auto Kind = - NodeKind::FunctionDefinition.Define(NodeCategory::Decl); + static constexpr auto Kind = NodeKind::FunctionDefinition.Define( + {.category = NodeCategory::Decl, + .bracketed_by = FunctionDefinitionStart::Kind}); FunctionDefinitionStartId signature; llvm::SmallVector body; @@ -330,8 +347,9 @@ using BuiltinName = LeafNode; // A builtin function definition: `fn F() -> i32 = "builtin name";` struct BuiltinFunctionDefinition { - static constexpr auto Kind = - NodeKind::BuiltinFunctionDefinition.Define(NodeCategory::Decl); + static constexpr auto Kind = NodeKind::BuiltinFunctionDefinition.Define( + {.category = NodeCategory::Decl, + .bracketed_by = BuiltinFunctionDefinitionStart::Kind}); BuiltinFunctionDefinitionStartId signature; BuiltinNameId builtin_name; @@ -345,8 +363,9 @@ using AliasInitializer = LeafNode; // An `alias` declaration: `alias a = b;`. struct Alias { - static constexpr auto Kind = - NodeKind::Alias.Define(NodeCategory::Decl | NodeCategory::Statement); + static constexpr auto Kind = NodeKind::Alias.Define( + {.category = NodeCategory::Decl | NodeCategory::Statement, + .bracketed_by = AliasIntroducer::Kind}); AliasIntroducerId introducer; llvm::SmallVector modifiers; @@ -363,8 +382,9 @@ using LetInitializer = LeafNode; // A `let` declaration: `let a: i32 = 5;`. struct LetDecl { - static constexpr auto Kind = - NodeKind::LetDecl.Define(NodeCategory::Decl | NodeCategory::Statement); + static constexpr auto Kind = NodeKind::LetDecl.Define( + {.category = NodeCategory::Decl | NodeCategory::Statement, + .bracketed_by = LetIntroducer::Kind}); LetIntroducerId introducer; llvm::SmallVector modifiers; @@ -387,7 +407,8 @@ using VariableInitializer = LeafNode; // A `var` declaration: `var a: i32;` or `var a: i32 = 5;`. struct VariableDecl { static constexpr auto Kind = NodeKind::VariableDecl.Define( - NodeCategory::Decl | NodeCategory::Statement); + {.category = NodeCategory::Decl | NodeCategory::Statement, + .bracketed_by = VariableIntroducer::Kind}); VariableIntroducerId introducer; llvm::SmallVector modifiers; @@ -408,7 +429,8 @@ using CodeBlockStart = LeafNode; // A code block: `{ statement; statement; ... }`. struct CodeBlock { - static constexpr auto Kind = NodeKind::CodeBlock.Define(); + static constexpr auto Kind = + NodeKind::CodeBlock.Define({.bracketed_by = CodeBlockStart::Kind}); CodeBlockStartId left_brace; llvm::SmallVector statements; @@ -416,8 +438,8 @@ struct CodeBlock { // An expression statement: `F(x);`. struct ExprStatement { - static constexpr auto Kind = - NodeKind::ExprStatement.Define(NodeCategory::Statement); + static constexpr auto Kind = NodeKind::ExprStatement.Define( + {.category = NodeCategory::Statement, .child_count = 1}); AnyExprId expr; }; @@ -426,8 +448,10 @@ using BreakStatementStart = LeafNode; // A break statement: `break;`. struct BreakStatement { - static constexpr auto Kind = - NodeKind::BreakStatement.Define(NodeCategory::Statement); + static constexpr auto Kind = NodeKind::BreakStatement.Define( + {.category = NodeCategory::Statement, + .bracketed_by = BreakStatementStart::Kind, + .child_count = 1}); BreakStatementStartId introducer; }; @@ -436,8 +460,10 @@ using ContinueStatementStart = LeafNode; // A continue statement: `continue;`. struct ContinueStatement { - static constexpr auto Kind = - NodeKind::ContinueStatement.Define(NodeCategory::Statement); + static constexpr auto Kind = NodeKind::ContinueStatement.Define( + {.category = NodeCategory::Statement, + .bracketed_by = ContinueStatementStart::Kind, + .child_count = 1}); ContinueStatementStartId introducer; }; @@ -447,8 +473,9 @@ using ReturnVarModifier = LeafNode; // A return statement: `return;` or `return expr;` or `return var;`. struct ReturnStatement { - static constexpr auto Kind = - NodeKind::ReturnStatement.Define(NodeCategory::Statement); + static constexpr auto Kind = NodeKind::ReturnStatement.Define( + {.category = NodeCategory::Statement, + .bracketed_by = ReturnStatementStart::Kind}); ReturnStatementStartId introducer; std::optional expr; @@ -459,7 +486,8 @@ using ForHeaderStart = LeafNode; // The `var ... in` portion of a `for` statement. struct ForIn { - static constexpr auto Kind = NodeKind::ForIn.Define(); + static constexpr auto Kind = NodeKind::ForIn.Define( + {.bracketed_by = VariableIntroducer::Kind, .child_count = 2}); VariableIntroducerId introducer; AnyPatternId pattern; @@ -467,7 +495,8 @@ struct ForIn { // The `for (var ... in ...)` portion of a `for` statement. struct ForHeader { - static constexpr auto Kind = NodeKind::ForHeader.Define(); + static constexpr auto Kind = + NodeKind::ForHeader.Define({.bracketed_by = ForHeaderStart::Kind}); ForHeaderStartId introducer; ForInId var; @@ -477,7 +506,9 @@ struct ForHeader { // A complete `for (...) { ... }` statement. struct ForStatement { static constexpr auto Kind = - NodeKind::ForStatement.Define(NodeCategory::Statement); + NodeKind::ForStatement.Define({.category = NodeCategory::Statement, + .bracketed_by = ForHeader::Kind, + .child_count = 2}); ForHeaderId header; CodeBlockId body; @@ -487,7 +518,8 @@ using IfConditionStart = LeafNode; // The condition portion of an `if` statement: `(expr)`. struct IfCondition { - static constexpr auto Kind = NodeKind::IfCondition.Define(); + static constexpr auto Kind = NodeKind::IfCondition.Define( + {.bracketed_by = IfConditionStart::Kind, .child_count = 2}); IfConditionStartId left_paren; AnyExprId condition; @@ -497,8 +529,8 @@ using IfStatementElse = LeafNode; // An `if` statement: `if (expr) { ... } else { ... }`. struct IfStatement { - static constexpr auto Kind = - NodeKind::IfStatement.Define(NodeCategory::Statement); + static constexpr auto Kind = NodeKind::IfStatement.Define( + {.category = NodeCategory::Statement, .bracketed_by = IfCondition::Kind}); IfConditionId head; CodeBlockId then; @@ -514,7 +546,8 @@ using WhileConditionStart = LeafNode; // The condition portion of a `while` statement: `(expr)`. struct WhileCondition { - static constexpr auto Kind = NodeKind::WhileCondition.Define(); + static constexpr auto Kind = NodeKind::WhileCondition.Define( + {.bracketed_by = WhileConditionStart::Kind, .child_count = 2}); WhileConditionStartId left_paren; AnyExprId condition; @@ -523,7 +556,9 @@ struct WhileCondition { // A `while` statement: `while (expr) { ... }`. struct WhileStatement { static constexpr auto Kind = - NodeKind::WhileStatement.Define(NodeCategory::Statement); + NodeKind::WhileStatement.Define({.category = NodeCategory::Statement, + .bracketed_by = WhileCondition::Kind, + .child_count = 2}); WhileConditionId head; CodeBlockId body; @@ -532,7 +567,8 @@ struct WhileStatement { using MatchConditionStart = LeafNode; struct MatchCondition { - static constexpr auto Kind = NodeKind::MatchCondition.Define(); + static constexpr auto Kind = NodeKind::MatchCondition.Define( + {.bracketed_by = MatchConditionStart::Kind, .child_count = 2}); MatchConditionStartId left_paren; AnyExprId condition; @@ -540,7 +576,8 @@ struct MatchCondition { using MatchIntroducer = LeafNode; struct MatchStatementStart { - static constexpr auto Kind = NodeKind::MatchStatementStart.Define(); + static constexpr auto Kind = NodeKind::MatchStatementStart.Define( + {.bracketed_by = MatchIntroducer::Kind, .child_count = 2}); MatchIntroducerId introducer; MatchConditionId left_brace; @@ -551,7 +588,9 @@ using MatchCaseGuardIntroducer = LeafNode; using MatchCaseGuardStart = LeafNode; struct MatchCaseGuard { - static constexpr auto Kind = NodeKind::MatchCaseGuard.Define(); + static constexpr auto Kind = NodeKind::MatchCaseGuard.Define( + {.bracketed_by = MatchCaseGuardIntroducer::Kind, .child_count = 3}); + MatchCaseGuardIntroducerId introducer; MatchCaseGuardStartId left_paren; AnyExprId condition; @@ -560,7 +599,9 @@ struct MatchCaseGuard { using MatchCaseEqualGreater = LeafNode; struct MatchCaseStart { - static constexpr auto Kind = NodeKind::MatchCaseStart.Define(); + static constexpr auto Kind = NodeKind::MatchCaseStart.Define( + {.bracketed_by = MatchCaseIntroducer::Kind}); + MatchCaseIntroducerId introducer; AnyPatternId pattern; std::optional guard; @@ -568,7 +609,9 @@ struct MatchCaseStart { }; struct MatchCase { - static constexpr auto Kind = NodeKind::MatchCase.Define(); + static constexpr auto Kind = + NodeKind::MatchCase.Define({.bracketed_by = MatchCaseStart::Kind}); + MatchCaseStartId head; llvm::SmallVector statements; }; @@ -577,13 +620,16 @@ using MatchDefaultIntroducer = LeafNode; using MatchDefaultEqualGreater = LeafNode; struct MatchDefaultStart { - static constexpr auto Kind = NodeKind::MatchDefaultStart.Define(); + static constexpr auto Kind = NodeKind::MatchDefaultStart.Define( + {.bracketed_by = MatchDefaultIntroducer::Kind, .child_count = 2}); + MatchDefaultIntroducerId introducer; MatchDefaultEqualGreaterId equal_greater_token; }; struct MatchDefault { - static constexpr auto Kind = NodeKind::MatchDefault.Define(); + static constexpr auto Kind = + NodeKind::MatchDefault.Define({.bracketed_by = MatchDefaultStart::Kind}); MatchDefaultStartId introducer; llvm::SmallVector statements; @@ -591,8 +637,9 @@ struct MatchDefault { // A `match` statement: `match (expr) { case (...) => {...} default => {...}}`. struct MatchStatement { - static constexpr auto Kind = - NodeKind::MatchStatement.Define(NodeCategory::Statement); + static constexpr auto Kind = NodeKind::MatchStatement.Define( + {.category = NodeCategory::Statement, + .bracketed_by = MatchStatementStart::Kind}); MatchStatementStartId head; @@ -609,7 +656,8 @@ using ArrayExprStart = LeafNode; // // TODO: Consider flattening this into `ArrayExpr`. struct ArrayExprSemi { - static constexpr auto Kind = NodeKind::ArrayExprSemi.Define(); + static constexpr auto Kind = NodeKind::ArrayExprSemi.Define( + {.bracketed_by = ArrayExprStart::Kind, .child_count = 2}); ArrayExprStartId left_square; AnyExprId type; @@ -617,7 +665,8 @@ struct ArrayExprSemi { // An array type, such as `[i32; 3]` or `[i32;]`. struct ArrayExpr { - static constexpr auto Kind = NodeKind::ArrayExpr.Define(NodeCategory::Expr); + static constexpr auto Kind = NodeKind::ArrayExpr.Define( + {.category = NodeCategory::Expr, .bracketed_by = ArrayExprSemi::Kind}); ArrayExprSemiId start; std::optional bound; @@ -627,14 +676,18 @@ struct ArrayExpr { // // TODO: Consider flattening this into `IndexExpr`. struct IndexExprStart { - static constexpr auto Kind = NodeKind::IndexExprStart.Define(); + static constexpr auto Kind = + NodeKind::IndexExprStart.Define({.child_count = 1}); AnyExprId sequence; }; // An indexing expression, such as `a[1]`. struct IndexExpr { - static constexpr auto Kind = NodeKind::IndexExpr.Define(NodeCategory::Expr); + static constexpr auto Kind = + NodeKind::IndexExpr.Define({.category = NodeCategory::Expr, + .bracketed_by = IndexExprStart::Kind, + .child_count = 2}); IndexExprStartId start; AnyExprId index; @@ -644,8 +697,10 @@ using ParenExprStart = LeafNode; // A parenthesized expression: `(a)`. struct ParenExpr { - static constexpr auto Kind = - NodeKind::ParenExpr.Define(NodeCategory::Expr | NodeCategory::MemberExpr); + static constexpr auto Kind = NodeKind::ParenExpr.Define( + {.category = NodeCategory::Expr | NodeCategory::MemberExpr, + .bracketed_by = ParenExprStart::Kind, + .child_count = 2}); ParenExprStartId start; AnyExprId expr; @@ -657,7 +712,8 @@ using TupleLiteralComma = LeafNode; // A tuple literal: `()`, `(a, b, c)`, or `(a,)`. struct TupleLiteral { static constexpr auto Kind = - NodeKind::TupleLiteral.Define(NodeCategory::Expr); + NodeKind::TupleLiteral.Define({.category = NodeCategory::Expr, + .bracketed_by = TupleLiteralStart::Kind}); TupleLiteralStartId start; CommaSeparatedList elements; @@ -667,7 +723,8 @@ struct TupleLiteral { // // TODO: Consider flattening this into `CallExpr`. struct CallExprStart { - static constexpr auto Kind = NodeKind::CallExprStart.Define(); + static constexpr auto Kind = + NodeKind::CallExprStart.Define({.child_count = 1}); AnyExprId callee; }; @@ -676,7 +733,8 @@ using CallExprComma = LeafNode; // A call expression: `F(a, b, c)`. struct CallExpr { - static constexpr auto Kind = NodeKind::CallExpr.Define(NodeCategory::Expr); + static constexpr auto Kind = NodeKind::CallExpr.Define( + {.category = NodeCategory::Expr, .bracketed_by = CallExprStart::Kind}); CallExprStartId start; CommaSeparatedList arguments; @@ -684,8 +742,8 @@ struct CallExpr { // A member access expression: `a.b` or `a.(b)`. struct MemberAccessExpr { - static constexpr auto Kind = - NodeKind::MemberAccessExpr.Define(NodeCategory::Expr); + static constexpr auto Kind = NodeKind::MemberAccessExpr.Define( + {.category = NodeCategory::Expr, .child_count = 2}); AnyExprId lhs; AnyMemberNameOrMemberExprId rhs; @@ -693,8 +751,8 @@ struct MemberAccessExpr { // An indirect member access expression: `a->b` or `a->(b)`. struct PointerMemberAccessExpr { - static constexpr auto Kind = - NodeKind::PointerMemberAccessExpr.Define(NodeCategory::Expr); + static constexpr auto Kind = NodeKind::PointerMemberAccessExpr.Define( + {.category = NodeCategory::Expr, .child_count = 2}); AnyExprId lhs; AnyMemberNameOrMemberExprId rhs; @@ -703,7 +761,8 @@ struct PointerMemberAccessExpr { // A prefix operator expression. template struct PrefixOperator { - static constexpr auto Kind = KindT.Define(NodeCategory::Expr); + static constexpr auto Kind = + KindT.Define({.category = NodeCategory::Expr, .child_count = 1}); AnyExprId operand; }; @@ -711,7 +770,8 @@ struct PrefixOperator { // An infix operator expression. template struct InfixOperator { - static constexpr auto Kind = KindT.Define(NodeCategory::Expr); + static constexpr auto Kind = + KindT.Define({.category = NodeCategory::Expr, .child_count = 2}); AnyExprId lhs; AnyExprId rhs; @@ -720,7 +780,8 @@ struct InfixOperator { // A postfix operator expression. template struct PostfixOperator { - static constexpr auto Kind = KindT.Define(NodeCategory::Expr); + static constexpr auto Kind = + KindT.Define({.category = NodeCategory::Expr, .child_count = 1}); AnyExprId operand; }; @@ -748,28 +809,34 @@ struct PostfixOperator { // TODO: Make this be a template if we ever need to write generic code to cover // both cases at once, say in check. struct ShortCircuitOperandAnd { - static constexpr auto Kind = NodeKind::ShortCircuitOperandAnd.Define(); + static constexpr auto Kind = + NodeKind::ShortCircuitOperandAnd.Define({.child_count = 1}); AnyExprId operand; }; struct ShortCircuitOperandOr { - static constexpr auto Kind = NodeKind::ShortCircuitOperandOr.Define(); + static constexpr auto Kind = + NodeKind::ShortCircuitOperandOr.Define({.child_count = 1}); AnyExprId operand; }; struct ShortCircuitOperatorAnd { - static constexpr auto Kind = - NodeKind::ShortCircuitOperatorAnd.Define(NodeCategory::Expr); + static constexpr auto Kind = NodeKind::ShortCircuitOperatorAnd.Define( + {.category = NodeCategory::Expr, + .bracketed_by = ShortCircuitOperandAnd::Kind, + .child_count = 2}); ShortCircuitOperandAndId lhs; AnyExprId rhs; }; struct ShortCircuitOperatorOr { - static constexpr auto Kind = - NodeKind::ShortCircuitOperatorOr.Define(NodeCategory::Expr); + static constexpr auto Kind = NodeKind::ShortCircuitOperatorOr.Define( + {.category = NodeCategory::Expr, + .bracketed_by = ShortCircuitOperandOr::Kind, + .child_count = 2}); ShortCircuitOperandOrId lhs; AnyExprId rhs; @@ -777,21 +844,24 @@ struct ShortCircuitOperatorOr { // The `if` portion of an `if` expression: `if expr`. struct IfExprIf { - static constexpr auto Kind = NodeKind::IfExprIf.Define(); + static constexpr auto Kind = NodeKind::IfExprIf.Define({.child_count = 1}); AnyExprId condition; }; // The `then` portion of an `if` expression: `then expr`. struct IfExprThen { - static constexpr auto Kind = NodeKind::IfExprThen.Define(); + static constexpr auto Kind = NodeKind::IfExprThen.Define({.child_count = 1}); AnyExprId result; }; // A full `if` expression: `if expr then expr else expr`. struct IfExprElse { - static constexpr auto Kind = NodeKind::IfExprElse.Define(NodeCategory::Expr); + static constexpr auto Kind = + NodeKind::IfExprElse.Define({.category = NodeCategory::Expr, + .bracketed_by = IfExprIf::Kind, + .child_count = 3}); IfExprIfId start; IfExprThenId then; @@ -804,8 +874,8 @@ struct IfExprElse { using ChoiceIntroducer = LeafNode; struct ChoiceSignature { - static constexpr auto Kind = - NodeKind::ChoiceDefinitionStart.Define(NodeCategory::None); + static constexpr auto Kind = NodeKind::ChoiceDefinitionStart.Define( + {.category = NodeCategory::None, .bracketed_by = ChoiceIntroducer::Kind}); ChoiceIntroducerId introducer; llvm::SmallVector modifiers; @@ -818,8 +888,9 @@ using ChoiceAlternativeListComma = LeafNode; struct ChoiceDefinition { - static constexpr auto Kind = - NodeKind::ChoiceDefinition.Define(NodeCategory::Decl); + static constexpr auto Kind = NodeKind::ChoiceDefinition.Define( + {.category = NodeCategory::Decl, + .bracketed_by = ChoiceDefinitionStart::Kind}); ChoiceDefinitionStartId signature; struct Alternative { @@ -840,14 +911,16 @@ using StructComma = LeafNode; // `.a` struct StructFieldDesignator { - static constexpr auto Kind = NodeKind::StructFieldDesignator.Define(); + static constexpr auto Kind = + NodeKind::StructFieldDesignator.Define({.child_count = 1}); NodeIdOneOf name; }; // `.a = 0` struct StructField { - static constexpr auto Kind = NodeKind::StructField.Define(); + static constexpr auto Kind = NodeKind::StructField.Define( + {.bracketed_by = StructFieldDesignator::Kind, .child_count = 2}); StructFieldDesignatorId designator; AnyExprId expr; @@ -855,7 +928,8 @@ struct StructField { // `.a: i32` struct StructTypeField { - static constexpr auto Kind = NodeKind::StructTypeField.Define(); + static constexpr auto Kind = NodeKind::StructTypeField.Define( + {.bracketed_by = StructFieldDesignator::Kind, .child_count = 2}); StructFieldDesignatorId designator; AnyExprId type_expr; @@ -863,8 +937,9 @@ struct StructTypeField { // Struct literals, such as `{.a = 0}`. struct StructLiteral { - static constexpr auto Kind = - NodeKind::StructLiteral.Define(NodeCategory::Expr); + static constexpr auto Kind = NodeKind::StructLiteral.Define( + {.category = NodeCategory::Expr, + .bracketed_by = StructLiteralStart::Kind}); StructLiteralStartId start; CommaSeparatedList fields; @@ -872,8 +947,9 @@ struct StructLiteral { // Struct type literals, such as `{.a: i32}`. struct StructTypeLiteral { - static constexpr auto Kind = - NodeKind::StructTypeLiteral.Define(NodeCategory::Expr); + static constexpr auto Kind = NodeKind::StructTypeLiteral.Define( + {.category = NodeCategory::Expr, + .bracketed_by = StructTypeLiteralStart::Kind}); StructTypeLiteralStartId start; CommaSeparatedList fields; @@ -888,7 +964,8 @@ using ClassIntroducer = LeafNode; // A class signature `class C` template struct ClassSignature { - static constexpr auto Kind = KindT.Define(Category); + static constexpr auto Kind = KindT.Define( + {.category = Category, .bracketed_by = ClassIntroducer::Kind}); ClassIntroducerId introducer; llvm::SmallVector modifiers; @@ -903,8 +980,9 @@ using ClassDefinitionStart = // `class C { ... }` struct ClassDefinition { - static constexpr auto Kind = - NodeKind::ClassDefinition.Define(NodeCategory::Decl); + static constexpr auto Kind = NodeKind::ClassDefinition.Define( + {.category = NodeCategory::Decl, + .bracketed_by = ClassDefinitionStart::Kind}); ClassDefinitionStartId signature; llvm::SmallVector members; @@ -917,7 +995,8 @@ struct ClassDefinition { using AdaptIntroducer = LeafNode; // `adapt SomeType;` struct AdaptDecl { - static constexpr auto Kind = NodeKind::AdaptDecl.Define(NodeCategory::Decl); + static constexpr auto Kind = NodeKind::AdaptDecl.Define( + {.category = NodeCategory::Decl, .bracketed_by = AdaptIntroducer::Kind}); AdaptIntroducerId introducer; llvm::SmallVector modifiers; @@ -932,7 +1011,8 @@ using BaseIntroducer = LeafNode; using BaseColon = LeafNode; // `extend base: BaseClass;` struct BaseDecl { - static constexpr auto Kind = NodeKind::BaseDecl.Define(NodeCategory::Decl); + static constexpr auto Kind = NodeKind::BaseDecl.Define( + {.category = NodeCategory::Decl, .bracketed_by = BaseIntroducer::Kind}); BaseIntroducerId introducer; llvm::SmallVector modifiers; @@ -949,7 +1029,8 @@ using InterfaceIntroducer = LeafNode; // `interface I` template struct InterfaceSignature { - static constexpr auto Kind = KindT.Define(Category); + static constexpr auto Kind = KindT.Define( + {.category = Category, .bracketed_by = InterfaceIntroducer::Kind}); InterfaceIntroducerId introducer; llvm::SmallVector modifiers; @@ -965,8 +1046,9 @@ using InterfaceDefinitionStart = // `interface I { ... }` struct InterfaceDefinition { - static constexpr auto Kind = - NodeKind::InterfaceDefinition.Define(NodeCategory::Decl); + static constexpr auto Kind = NodeKind::InterfaceDefinition.Define( + {.category = NodeCategory::Decl, + .bracketed_by = InterfaceDefinitionStart::Kind}); InterfaceDefinitionStartId signature; llvm::SmallVector members; @@ -980,7 +1062,7 @@ using ImplIntroducer = LeafNode; // `forall [...]` struct ImplForall { - static constexpr auto Kind = NodeKind::ImplForall.Define(); + static constexpr auto Kind = NodeKind::ImplForall.Define({.child_count = 1}); ImplicitParamListId params; }; @@ -991,8 +1073,8 @@ using DefaultSelfImplAs = // ` as` struct TypeImplAs { - static constexpr auto Kind = - NodeKind::TypeImplAs.Define(NodeCategory::ImplAs); + static constexpr auto Kind = NodeKind::TypeImplAs.Define( + {.category = NodeCategory::ImplAs, .child_count = 1}); AnyExprId type_expr; }; @@ -1000,7 +1082,8 @@ struct TypeImplAs { // `impl T as I` template struct ImplSignature { - static constexpr auto Kind = KindT.Define(Category); + static constexpr auto Kind = KindT.Define( + {.category = Category, .bracketed_by = ImplIntroducer::Kind}); ImplIntroducerId introducer; llvm::SmallVector modifiers; @@ -1017,8 +1100,9 @@ using ImplDefinitionStart = // `impl T as I { ... }` struct ImplDefinition { - static constexpr auto Kind = - NodeKind::ImplDefinition.Define(NodeCategory::Decl); + static constexpr auto Kind = NodeKind::ImplDefinition.Define( + {.category = NodeCategory::Decl, + .bracketed_by = ImplDefinitionStart::Kind}); ImplDefinitionStartId signature; llvm::SmallVector members; @@ -1033,7 +1117,8 @@ using NamedConstraintIntroducer = LeafNode; // `constraint NC` template struct NamedConstraintSignature { - static constexpr auto Kind = KindT.Define(Category); + static constexpr auto Kind = KindT.Define( + {.category = Category, .bracketed_by = NamedConstraintIntroducer::Kind}); NamedConstraintIntroducerId introducer; llvm::SmallVector modifiers; @@ -1050,8 +1135,9 @@ using NamedConstraintDefinitionStart = // `constraint NC { ... }` struct NamedConstraintDefinition { - static constexpr auto Kind = - NodeKind::NamedConstraintDefinition.Define(NodeCategory::Decl); + static constexpr auto Kind = NodeKind::NamedConstraintDefinition.Define( + {.category = NodeCategory::Decl, + .bracketed_by = NamedConstraintDefinitionStart::Kind}); NamedConstraintDefinitionStartId signature; llvm::SmallVector members;