// Part of the Carbon Language project, under the Apache License v2.0 with LLVM // Exceptions. See /LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // // This is an X-macro header. It does not use `#include` guards, and instead is // designed to be `#include`ed after the x-macro is defined in order for its // inclusion to expand to the desired output. Macro definitions are cleaned up // at the end of this file. // // Supported x-macros are: // - CARBON_PARSE_NODE_KIND(Name) // Used as a fallback if other macros are missing. No kinds should use this // directly. // - CARBON_PARSE_NODE_KIND_BRACKET(Name, BracketName, LexTokenKinds) // 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, LexTokenKinds) // 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_TOKEN_LITERAL(Name, LexTokenKinds) // Defines a parse node that corresponds to a token that is a single-token // literal. The token is wrapped for LexTokenKinds. // - CARBON_PARSE_NODE_KIND_TOKEN_MODIFIER(Name) // A token-based modifier. The Name is the TokenKind, and will be appended // with "Modifier" for the parse kind. // // In both cases, LexTokenKinds says which Lex::TokenKind values that this // parse node can correspond to, and is a sequence of: // - CARBON_TOKEN(kind): This node can correspond to this kind of token. // - CARBON_ANY_TOKEN: This node can correspond to any token. // - CARBON_IF_ERROR(LexTokenKinds): This node can additionally correspond // to the given kinds of tokens if its `has_error` flag is set. // // 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. #if !(defined(CARBON_PARSE_NODE_KIND) || \ (defined(CARBON_PARSE_NODE_KIND_BRACKET) && \ defined(CARBON_PARSE_NODE_KIND_CHILD_COUNT))) #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, ...) \ CARBON_PARSE_NODE_KIND(Name) #endif // This is expected to be used with something like: // // // Use x-macros to handle literal cases. // #define CARBON_PARSE_NODE_KIND(...) // #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) #endif // This is expected to be used with something like: // // // Use x-macros to handle modifier cases. // #define CARBON_PARSE_NODE_KIND(...) // #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, CARBON_TOKEN(Name)) #endif // The start of the file. CARBON_PARSE_NODE_KIND_CHILD_COUNT(FileStart, 0, CARBON_TOKEN(FileStart)) // The end of the file. CARBON_PARSE_NODE_KIND_CHILD_COUNT(FileEnd, 0, CARBON_TOKEN(FileEnd)) // An invalid parse. Used to balance the parse tree. Always has an error. CARBON_PARSE_NODE_KIND_CHILD_COUNT(InvalidParse, 0, CARBON_IF_ERROR(CARBON_ANY_TOKEN)) // An invalid subtree. Always has an error. CARBON_PARSE_NODE_KIND_CHILD_COUNT(InvalidParseStart, 0, CARBON_IF_ERROR(CARBON_ANY_TOKEN)) CARBON_PARSE_NODE_KIND_BRACKET(InvalidParseSubtree, InvalidParseStart, CARBON_IF_ERROR(CARBON_ANY_TOKEN)) // A placeholder node to be replaced. CARBON_PARSE_NODE_KIND_CHILD_COUNT(Placeholder, 0, CARBON_ANY_TOKEN) // An empty declaration, such as `;`. CARBON_PARSE_NODE_KIND_CHILD_COUNT(EmptyDecl, 0, CARBON_TOKEN(Semi) CARBON_IF_ERROR(CARBON_ANY_TOKEN)) // An identifier name in a non-expression context, such as a declaration. CARBON_PARSE_NODE_KIND_CHILD_COUNT(IdentifierName, 0, CARBON_TOKEN(Identifier) CARBON_IF_ERROR(CARBON_ANY_TOKEN)) // An identifier name in an expression context. CARBON_PARSE_NODE_KIND_CHILD_COUNT(IdentifierNameExpr, 0, CARBON_TOKEN(Identifier)) // The `self` value and `Self` type identifier keywords. Typically of the form // `self: Self`. CARBON_PARSE_NODE_KIND_CHILD_COUNT(SelfValueName, 0, CARBON_TOKEN(SelfValueIdentifier)) CARBON_PARSE_NODE_KIND_CHILD_COUNT(SelfValueNameExpr, 0, CARBON_TOKEN(SelfValueIdentifier)) CARBON_PARSE_NODE_KIND_CHILD_COUNT(SelfTypeNameExpr, 0, CARBON_TOKEN(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, CARBON_TOKEN(Base)) // The `package` keyword in an expression. CARBON_PARSE_NODE_KIND_CHILD_COUNT(PackageExpr, 0, CARBON_TOKEN(Package)) // ---------------------------------------------------------------------------- // The comments below follow this pattern: // // // Descriptive heading: // // Child1 // // Child2 // // Parent // // In this, `Child1`, `Child2`, and `Parent` are all kinds of parse nodes, which // are then defined using the `CARBON_PARSE_NODE_KIND_*` macros. They are // written in postorder, with the indentation showing the tree structure. See // tree.h for more information. // // A parse node kind may be preceded by: // - `_optional_` if this node (or nodes) may be present or omitted in valid // parses, depending on which tokens are in the source code. // - `_repeated_` if this node (or nodes) may be repeated or omitted in valid // parses, depending on which tokens are in the source code. // - `_external_:` if this node is the child of multiple kinds of nodes and // is documented separately. // // There is generally a close correspondence between handling of tokens and the // creation of non-external nodes in a given block. // ---------------------------------------------------------------------------- // The name of a package or library for `package`, `import`, and `library`. CARBON_PARSE_NODE_KIND_CHILD_COUNT(PackageName, 0, CARBON_TOKEN(Identifier)) CARBON_PARSE_NODE_KIND_CHILD_COUNT(LibraryName, 0, CARBON_TOKEN(StringLiteral)) // `package`: // PackageIntroducer // _optional_ _external_: PackageName // _optional_ _external_: LibrarySpecifier // PackageApi or PackageImpl // PackageDirective CARBON_PARSE_NODE_KIND_CHILD_COUNT(PackageIntroducer, 0, CARBON_TOKEN(Package)) CARBON_PARSE_NODE_KIND_CHILD_COUNT(PackageApi, 0, CARBON_TOKEN(Api)) CARBON_PARSE_NODE_KIND_CHILD_COUNT(PackageImpl, 0, CARBON_TOKEN(Impl)) CARBON_PARSE_NODE_KIND_BRACKET(PackageDirective, PackageIntroducer, CARBON_TOKEN(Semi) CARBON_IF_ERROR(CARBON_TOKEN(Package))) // `import`: // ImportIntroducer // _optional_ _external_: PackageName // _optional_ _external_: LibrarySpecifier // ImportDirective CARBON_PARSE_NODE_KIND_CHILD_COUNT(ImportIntroducer, 0, CARBON_TOKEN(Import)) CARBON_PARSE_NODE_KIND_BRACKET(ImportDirective, ImportIntroducer, CARBON_TOKEN(Semi) CARBON_IF_ERROR(CARBON_TOKEN(Import))) // `library` as directive: // LibraryIntroducer // DefaultLibrary or _external_: LibraryName // LibraryDirective CARBON_PARSE_NODE_KIND_CHILD_COUNT(DefaultLibrary, 0, CARBON_TOKEN(Default)) CARBON_PARSE_NODE_KIND_CHILD_COUNT(LibraryIntroducer, 0, CARBON_TOKEN(Library)) CARBON_PARSE_NODE_KIND_BRACKET(LibraryDirective, LibraryIntroducer, CARBON_TOKEN(Semi) CARBON_IF_ERROR(CARBON_TOKEN(Library))) // `library` in `package` or `import`: // _external_: LibraryName // LibrarySpecifier CARBON_PARSE_NODE_KIND_CHILD_COUNT(LibrarySpecifier, 1, CARBON_TOKEN(Library)) // `namespace`: // NamespaceStart // _repeated_ _external_: modifier // _external_: Name or QualifiedDecl // Namespace CARBON_PARSE_NODE_KIND_CHILD_COUNT(NamespaceStart, 0, CARBON_TOKEN(Namespace)) CARBON_PARSE_NODE_KIND_BRACKET(Namespace, NamespaceStart, CARBON_TOKEN(Semi) CARBON_IF_ERROR(CARBON_TOKEN(Namespace))) // A code block: // CodeBlockStart // _repeated_ _external_: statement // CodeBlock CARBON_PARSE_NODE_KIND_CHILD_COUNT(CodeBlockStart, 0, CARBON_TOKEN(OpenCurlyBrace) CARBON_IF_ERROR(CARBON_ANY_TOKEN)) CARBON_PARSE_NODE_KIND_BRACKET(CodeBlock, CodeBlockStart, CARBON_TOKEN(CloseCurlyBrace) CARBON_IF_ERROR(CARBON_ANY_TOKEN)) // `fn`: // FunctionIntroducer // _repeated_ _external_: modifier // _external_: Name or QualifiedDecl // _external_: TuplePattern // _external_: type expression // ReturnType // FunctionDefinitionStart // _repeated_ _external_: statement // FunctionDefinition // // The above is the structure for a definition; for a declaration, // FunctionDefinitionStart and later nodes are removed and replaced by // FunctionDecl. CARBON_PARSE_NODE_KIND_CHILD_COUNT(FunctionIntroducer, 0, CARBON_TOKEN(Fn)) CARBON_PARSE_NODE_KIND_CHILD_COUNT(ReturnType, 1, CARBON_TOKEN(MinusGreater)) CARBON_PARSE_NODE_KIND_BRACKET(FunctionDefinitionStart, FunctionIntroducer, CARBON_TOKEN(OpenCurlyBrace)) CARBON_PARSE_NODE_KIND_BRACKET(FunctionDefinition, FunctionDefinitionStart, CARBON_TOKEN(CloseCurlyBrace)) CARBON_PARSE_NODE_KIND_BRACKET(FunctionDecl, FunctionIntroducer, CARBON_TOKEN(Semi) CARBON_IF_ERROR(CARBON_TOKEN(Fn))) // A tuple pattern: // TuplePatternStart // _external_: [Generic]BindingPattern // PatternListComma // _repeated_ // TuplePattern // // Patterns and PatternListComma may repeat with PatternListComma as a // separator. CARBON_PARSE_NODE_KIND_CHILD_COUNT(TuplePatternStart, 0, CARBON_TOKEN(OpenParen)) CARBON_PARSE_NODE_KIND_CHILD_COUNT(PatternListComma, 0, CARBON_TOKEN(Comma)) CARBON_PARSE_NODE_KIND_BRACKET(TuplePattern, TuplePatternStart, CARBON_TOKEN(CloseParen)) // An implicit parameter list: // ImplicitParamListStart // _external_: [Generic]BindingPattern // PatternListComma // _repeated_ // ImplicitParamList // // Patterns and PatternListComma may repeat with PatternListComma as a // separator. CARBON_PARSE_NODE_KIND_CHILD_COUNT(ImplicitParamListStart, 0, CARBON_TOKEN(OpenSquareBracket)) CARBON_PARSE_NODE_KIND_BRACKET(ImplicitParamList, ImplicitParamListStart, CARBON_TOKEN(CloseSquareBracket)) // An array type, such as `[i32; 3]` or `[i32;]`: // ArrayExprStart // _external_: type expression // ArrayExprSemi // _optional_ _external_: expression // ArrayExpr CARBON_PARSE_NODE_KIND_CHILD_COUNT(ArrayExprStart, 0, CARBON_TOKEN(OpenSquareBracket)) CARBON_PARSE_NODE_KIND_CHILD_COUNT(ArrayExprSemi, 2, CARBON_TOKEN(Semi) CARBON_IF_ERROR(CARBON_ANY_TOKEN)) CARBON_PARSE_NODE_KIND_BRACKET(ArrayExpr, ArrayExprSemi, CARBON_TOKEN(CloseSquareBracket)) // A binding pattern, such as `name: Type`: // Name or SelfValueName // _external_: type expression // [Generic]BindingPattern // _optional_ Address // _optional_ Template CARBON_PARSE_NODE_KIND_CHILD_COUNT(BindingPattern, 2, CARBON_TOKEN(Colon) CARBON_IF_ERROR(CARBON_ANY_TOKEN)) CARBON_PARSE_NODE_KIND_CHILD_COUNT(GenericBindingPattern, 2, CARBON_TOKEN(ColonExclaim)) CARBON_PARSE_NODE_KIND_CHILD_COUNT(Address, 1, CARBON_TOKEN(Addr)) CARBON_PARSE_NODE_KIND_CHILD_COUNT(Template, 1, CARBON_TOKEN(Template)) // `let`: // LetIntroducer // _repeated_ _external_: modifier // _external_: BindingPattern or TuplePattern // LetInitializer // _external_: expression // LetDecl // // Modifier keywords only appear for `let` declarations, not `let` statements. CARBON_PARSE_NODE_KIND_CHILD_COUNT(LetIntroducer, 0, CARBON_TOKEN(Let)) CARBON_PARSE_NODE_KIND_CHILD_COUNT(LetInitializer, 0, CARBON_TOKEN(Equal)) CARBON_PARSE_NODE_KIND_BRACKET(LetDecl, LetIntroducer, CARBON_TOKEN(Semi) CARBON_IF_ERROR(CARBON_TOKEN(Let))) // `var` and `returned var`: // VariableIntroducer // _repeated_ _external_: modifier // _optional_ ReturnedModifier // _external_: BindingPattern or TuplePattern // VariableInitializer // _external_: expression // _optional_ // VariableDecl // // Access and declaration modifier keywords only appear for `var` declarations, // whereas the returned modifier only appears on `var` statements. // The VariableInitializer and following expression are paired: either both will // be present, or neither will. CARBON_PARSE_NODE_KIND_CHILD_COUNT(VariableIntroducer, 0, CARBON_TOKEN(Var) CARBON_IF_ERROR(CARBON_TOKEN(Returned))) CARBON_PARSE_NODE_KIND_CHILD_COUNT(ReturnedModifier, 0, CARBON_TOKEN(Returned)) CARBON_PARSE_NODE_KIND_CHILD_COUNT(VariableInitializer, 0, CARBON_TOKEN(Equal)) CARBON_PARSE_NODE_KIND_BRACKET(VariableDecl, VariableIntroducer, CARBON_TOKEN(Semi) CARBON_IF_ERROR(CARBON_TOKEN(Var) CARBON_TOKEN(Returned))) // An expression statement: // _external_: expression // ExprStatement CARBON_PARSE_NODE_KIND_CHILD_COUNT(ExprStatement, 1, CARBON_TOKEN(Semi)) // `break`: // BreakStatementStart // BreakStatement CARBON_PARSE_NODE_KIND_CHILD_COUNT(BreakStatementStart, 0, CARBON_TOKEN(Break)) CARBON_PARSE_NODE_KIND_CHILD_COUNT(BreakStatement, 1, CARBON_TOKEN(Semi) CARBON_IF_ERROR(CARBON_TOKEN(Break))) // `continue`: // ContinueStatementStart // ContinueStatement CARBON_PARSE_NODE_KIND_CHILD_COUNT(ContinueStatementStart, 0, CARBON_TOKEN(Continue)) CARBON_PARSE_NODE_KIND_CHILD_COUNT(ContinueStatement, 1, CARBON_TOKEN(Semi) CARBON_IF_ERROR(CARBON_TOKEN(Continue))) // `return`: // ReturnStatementStart // _optional_ ReturnVarModifier or _external_: expression // ReturnStatement CARBON_PARSE_NODE_KIND_CHILD_COUNT(ReturnStatementStart, 0, CARBON_TOKEN(Return)) CARBON_PARSE_NODE_KIND_CHILD_COUNT(ReturnVarModifier, 0, CARBON_TOKEN(Var)) CARBON_PARSE_NODE_KIND_BRACKET(ReturnStatement, ReturnStatementStart, CARBON_TOKEN(Semi) CARBON_IF_ERROR(CARBON_TOKEN(Return))) // `for`: // ForHeaderStart // VariableIntroducer // _external_: BindingPattern // ForIn // _external_: expression // ForHeader // _external_: CodeBlock // ForStatement // // Versus a normal `var`, ForIn replaces VariableDecl. CARBON_PARSE_NODE_KIND_CHILD_COUNT(ForHeaderStart, 0, CARBON_TOKEN(OpenParen) CARBON_IF_ERROR(CARBON_TOKEN(For))) CARBON_PARSE_NODE_KIND_BRACKET(ForIn, VariableIntroducer, CARBON_TOKEN(In) CARBON_IF_ERROR(CARBON_ANY_TOKEN)) CARBON_PARSE_NODE_KIND_BRACKET(ForHeader, ForHeaderStart, CARBON_TOKEN(CloseParen) CARBON_IF_ERROR(CARBON_TOKEN(For))) CARBON_PARSE_NODE_KIND_CHILD_COUNT(ForStatement, 2, CARBON_TOKEN(For)) // `if` statement + `else`: // IfConditionStart // _external_: expression // IfCondition // _external_: CodeBlock // IfStatementElse // _external_: CodeBlock or IfStatement // IfStatement // // IfStatementElse and the following node are optional based on `else` presence. CARBON_PARSE_NODE_KIND_CHILD_COUNT(IfConditionStart, 0, CARBON_TOKEN(OpenParen) CARBON_IF_ERROR(CARBON_TOKEN(If))) CARBON_PARSE_NODE_KIND_BRACKET(IfCondition, IfConditionStart, CARBON_TOKEN(CloseParen) CARBON_IF_ERROR(CARBON_TOKEN(If))) CARBON_PARSE_NODE_KIND_CHILD_COUNT(IfStatementElse, 0, CARBON_TOKEN(Else)) CARBON_PARSE_NODE_KIND_BRACKET(IfStatement, IfCondition, CARBON_TOKEN(If)) // `while`: // WhileConditionStart // _external_: expression // WhileCondition // _external_: CodeBlock // WhileStatement CARBON_PARSE_NODE_KIND_CHILD_COUNT(WhileConditionStart, 0, CARBON_TOKEN(OpenParen)) CARBON_PARSE_NODE_KIND_BRACKET(WhileCondition, WhileConditionStart, CARBON_TOKEN(CloseParen)) CARBON_PARSE_NODE_KIND_CHILD_COUNT(WhileStatement, 2, CARBON_TOKEN(While)) // Index expressions, such as `a[1]`: // _external_: expression // IndexExprStart // _external_: expression // IndexExpr CARBON_PARSE_NODE_KIND_CHILD_COUNT(IndexExprStart, 1, CARBON_TOKEN(OpenSquareBracket)) CARBON_PARSE_NODE_KIND_BRACKET(IndexExpr, IndexExprStart, CARBON_TOKEN(CloseSquareBracket)) // Parenthesized single expressions, such as `(2)`: // ExprOpenParen // _external_: expression // ParenExpr // // Tuples, such as `(1, 2)`: // ExprOpenParen // _external_: expression // TupleLiteralComma // _repeated_ // TupleLiteral // // Expressions and TupleLiteralComma may repeat with TupleLiteralComma as a // separator. CARBON_PARSE_NODE_KIND_CHILD_COUNT(ExprOpenParen, 0, CARBON_TOKEN(OpenParen)) CARBON_PARSE_NODE_KIND_BRACKET(ParenExpr, ExprOpenParen, CARBON_TOKEN(CloseParen)) CARBON_PARSE_NODE_KIND_CHILD_COUNT(TupleLiteralComma, 0, CARBON_TOKEN(Comma)) CARBON_PARSE_NODE_KIND_BRACKET(TupleLiteral, ExprOpenParen, CARBON_TOKEN(CloseParen)) // Call expressions, such as `a()`: // _external_: expression // CallExprStart // _external_: expression // CallExprComma // _repeated_ // CallExpr // // Exprs and CallExprComma may repeat with CallExprComma as a separator. CARBON_PARSE_NODE_KIND_CHILD_COUNT(CallExprStart, 1, CARBON_TOKEN(OpenParen)) CARBON_PARSE_NODE_KIND_CHILD_COUNT(CallExprComma, 0, CARBON_TOKEN(Comma)) CARBON_PARSE_NODE_KIND_BRACKET(CallExpr, CallExprStart, CARBON_TOKEN(CloseParen)) // A qualified declaration, such as `a.b`: // _external_: Name or QualifiedDecl // _external_: Name // QualifiedDecl // // TODO: This will eventually more general expressions, for example with // `GenericType(type_args).ChildType(child_type_args).Name`. CARBON_PARSE_NODE_KIND_CHILD_COUNT(QualifiedDecl, 2, CARBON_TOKEN(Period)) // A member access expression, such as `a.b` or // `GetObject().(Interface.member)`: // _external_: lhs expression // _external_: rhs expression // QualifiedExpr CARBON_PARSE_NODE_KIND_CHILD_COUNT(MemberAccessExpr, 2, CARBON_TOKEN(Period)) // A pointer member access expression, such as `a->b` or // `GetObject()->(Interface.member)`: // _external_: lhs expression // _external_: rhs expression // QualifiedExpr CARBON_PARSE_NODE_KIND_CHILD_COUNT(PointerMemberAccessExpr, 2, CARBON_TOKEN(MinusGreater)) // A value literal. CARBON_PARSE_NODE_KIND_TOKEN_LITERAL(BoolLiteralFalse, CARBON_TOKEN(False)) CARBON_PARSE_NODE_KIND_TOKEN_LITERAL(BoolLiteralTrue, CARBON_TOKEN(True)) CARBON_PARSE_NODE_KIND_TOKEN_LITERAL(IntLiteral, CARBON_TOKEN(IntLiteral)) CARBON_PARSE_NODE_KIND_TOKEN_LITERAL(RealLiteral, CARBON_TOKEN(RealLiteral)) CARBON_PARSE_NODE_KIND_TOKEN_LITERAL(StringLiteral, CARBON_TOKEN(StringLiteral)) // A type literal. CARBON_PARSE_NODE_KIND_TOKEN_LITERAL(BoolTypeLiteral, CARBON_TOKEN(Bool)) CARBON_PARSE_NODE_KIND_TOKEN_LITERAL(IntTypeLiteral, CARBON_TOKEN(IntTypeLiteral)) CARBON_PARSE_NODE_KIND_TOKEN_LITERAL(UnsignedIntTypeLiteral, CARBON_TOKEN(UnsignedIntTypeLiteral)) CARBON_PARSE_NODE_KIND_TOKEN_LITERAL(FloatTypeLiteral, CARBON_TOKEN(FloatTypeLiteral)) CARBON_PARSE_NODE_KIND_TOKEN_LITERAL(StringTypeLiteral, CARBON_TOKEN(StringTypeLiteral)) CARBON_PARSE_NODE_KIND_TOKEN_LITERAL(TypeTypeLiteral, CARBON_TOKEN(Type)) // clang-format off // A prefix operator: // _external_: expression // PrefixOperator CARBON_PARSE_NODE_KIND_CHILD_COUNT(PrefixOperator, 1, CARBON_TOKEN(Star) CARBON_TOKEN(Amp) CARBON_TOKEN(Not) CARBON_TOKEN(Minus) CARBON_TOKEN(MinusMinus) CARBON_TOKEN(PlusPlus) CARBON_TOKEN(Caret) CARBON_TOKEN(Const)) // An infix operator: // _external_: lhs expression // _external_: rhs expression // InfixOperator CARBON_PARSE_NODE_KIND_CHILD_COUNT(InfixOperator, 2, CARBON_TOKEN(Amp) CARBON_TOKEN(AmpEqual) CARBON_TOKEN(As) CARBON_TOKEN(Caret) CARBON_TOKEN(CaretEqual) CARBON_TOKEN(Equal) CARBON_TOKEN(EqualEqual) CARBON_TOKEN(ExclaimEqual) CARBON_TOKEN(Greater) CARBON_TOKEN(GreaterEqual) CARBON_TOKEN(GreaterGreater) CARBON_TOKEN(GreaterGreaterEqual) CARBON_TOKEN(Less) CARBON_TOKEN(LessEqual) CARBON_TOKEN(LessLess) CARBON_TOKEN(LessLessEqual) CARBON_TOKEN(Minus) CARBON_TOKEN(MinusEqual) CARBON_TOKEN(Percent) CARBON_TOKEN(PercentEqual) CARBON_TOKEN(Pipe) CARBON_TOKEN(PipeEqual) CARBON_TOKEN(Plus) CARBON_TOKEN(PlusEqual) CARBON_TOKEN(Slash) CARBON_TOKEN(SlashEqual) CARBON_TOKEN(Star) CARBON_TOKEN(StarEqual)) // clang-format on // A short-circuiting infix operator: // _external_: expression // ShortCircuitOperand(And|Or) // _external_: expression // ShortCircuitOperand(And|Or) CARBON_PARSE_NODE_KIND_CHILD_COUNT(ShortCircuitOperandAnd, 1, CARBON_TOKEN(And)) CARBON_PARSE_NODE_KIND_CHILD_COUNT(ShortCircuitOperandOr, 1, CARBON_TOKEN(Or)) CARBON_PARSE_NODE_KIND_CHILD_COUNT(ShortCircuitOperatorAnd, 2, CARBON_TOKEN(And)) CARBON_PARSE_NODE_KIND_CHILD_COUNT(ShortCircuitOperatorOr, 2, CARBON_TOKEN(Or)) // A postfix operator: // _external_: expression // PostfixOperator CARBON_PARSE_NODE_KIND_CHILD_COUNT(PostfixOperator, 1, CARBON_TOKEN(Star)) // `if` expression + `then` + `else`: // _external_: expression // IfExprIf // _external_: expression // IfExprThen // _external_: expression // IfExprElse CARBON_PARSE_NODE_KIND_CHILD_COUNT(IfExprIf, 1, CARBON_TOKEN(If)) CARBON_PARSE_NODE_KIND_CHILD_COUNT(IfExprThen, 1, CARBON_TOKEN(Then)) CARBON_PARSE_NODE_KIND_CHILD_COUNT(IfExprElse, 3, CARBON_TOKEN(Else) CARBON_IF_ERROR(CARBON_TOKEN(If))) // Struct literals, such as `{.a = 0}`: // StructLiteralOrStructTypeLiteralStart // _external_: Name // StructFieldDesignator // _external_: expression // StructFieldValue // StructComma // _repeated_ // StructLiteral // // Struct type literals, such as `{.a: i32}`: // StructLiteralOrStructTypeLiteralStart // _external_: Name // StructFieldDesignator // _external_: type expression // StructFieldType // StructComma // _repeated_ // StructTypeLiteral // // Elements (StructFieldValue and StructFieldType, respectively) and StructComma // may repeat with StructComma as a separator. // // When a valid StructFieldType or StructFieldValue cannot be formed, elements // may be replaced by StructFieldUnknown, which may have a preceding sibling // StructFieldDesignator if one was successfully parsed. CARBON_PARSE_NODE_KIND_CHILD_COUNT(StructLiteralOrStructTypeLiteralStart, 0, CARBON_TOKEN(OpenCurlyBrace)) CARBON_PARSE_NODE_KIND_CHILD_COUNT(StructFieldDesignator, 1, CARBON_TOKEN(Period)) CARBON_PARSE_NODE_KIND_CHILD_COUNT(StructFieldValue, 2, CARBON_TOKEN(Equal)) CARBON_PARSE_NODE_KIND_CHILD_COUNT(StructFieldType, 2, CARBON_TOKEN(Colon)) CARBON_PARSE_NODE_KIND_CHILD_COUNT(StructFieldUnknown, 0, CARBON_IF_ERROR(CARBON_ANY_TOKEN)) CARBON_PARSE_NODE_KIND_CHILD_COUNT(StructComma, 0, CARBON_TOKEN(Comma)) CARBON_PARSE_NODE_KIND_BRACKET(StructLiteral, StructLiteralOrStructTypeLiteralStart, CARBON_TOKEN(CloseCurlyBrace)) CARBON_PARSE_NODE_KIND_BRACKET(StructTypeLiteral, StructLiteralOrStructTypeLiteralStart, CARBON_TOKEN(CloseCurlyBrace)) // Various modifiers. These are all a single token. CARBON_PARSE_NODE_KIND_TOKEN_MODIFIER(Abstract) CARBON_PARSE_NODE_KIND_TOKEN_MODIFIER(Base) CARBON_PARSE_NODE_KIND_TOKEN_MODIFIER(Default) CARBON_PARSE_NODE_KIND_TOKEN_MODIFIER(Extend) CARBON_PARSE_NODE_KIND_TOKEN_MODIFIER(Final) CARBON_PARSE_NODE_KIND_TOKEN_MODIFIER(Impl) CARBON_PARSE_NODE_KIND_TOKEN_MODIFIER(Private) CARBON_PARSE_NODE_KIND_TOKEN_MODIFIER(Protected) CARBON_PARSE_NODE_KIND_TOKEN_MODIFIER(Virtual) // `class`: // ClassIntroducer // _repeated_ _external_: modifier // _external_: Name or QualifiedDecl // ClassDefinitionStart // _external_: declarations // ClassDefinition // // 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, CARBON_TOKEN(Class)) CARBON_PARSE_NODE_KIND_BRACKET(ClassDefinitionStart, ClassIntroducer, CARBON_TOKEN(OpenCurlyBrace)) CARBON_PARSE_NODE_KIND_BRACKET(ClassDefinition, ClassDefinitionStart, CARBON_TOKEN(CloseCurlyBrace)) CARBON_PARSE_NODE_KIND_BRACKET(ClassDecl, ClassIntroducer, CARBON_TOKEN(Semi) CARBON_IF_ERROR(CARBON_TOKEN(Class))) // `base`: // BaseIntroducer // _repeated_ _external_: modifier // BaseColon // _external_: expression // BaseDecl CARBON_PARSE_NODE_KIND_CHILD_COUNT(BaseIntroducer, 0, CARBON_TOKEN(Base)) CARBON_PARSE_NODE_KIND_CHILD_COUNT(BaseColon, 0, CARBON_TOKEN(Colon)) CARBON_PARSE_NODE_KIND_BRACKET(BaseDecl, BaseIntroducer, CARBON_TOKEN(Semi) CARBON_IF_ERROR(CARBON_TOKEN(Base))) // `interface`: // InterfaceIntroducer // _repeated_ _external_: modifier // _external_: Name or QualifiedDecl // InterfaceDefinitionStart // _external_: declarations // InterfaceDefinition // // 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, CARBON_TOKEN(Interface)) CARBON_PARSE_NODE_KIND_BRACKET(InterfaceDefinitionStart, InterfaceIntroducer, CARBON_TOKEN(OpenCurlyBrace)) CARBON_PARSE_NODE_KIND_BRACKET(InterfaceDefinition, InterfaceDefinitionStart, CARBON_TOKEN(CloseCurlyBrace)) CARBON_PARSE_NODE_KIND_BRACKET(InterfaceDecl, InterfaceIntroducer, CARBON_TOKEN(Semi) CARBON_IF_ERROR(CARBON_TOKEN(Interface))) // `constraint`: // NamedConstraintIntroducer // _repeated_ _external_: modifier // _external_: Name or QualifiedDecl // NamedConstraintDefinitionStart // _external_: declarations // NamedConstraintDefinition // // 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, CARBON_TOKEN(Constraint)) CARBON_PARSE_NODE_KIND_BRACKET(NamedConstraintDefinitionStart, NamedConstraintIntroducer, CARBON_TOKEN(OpenCurlyBrace)) CARBON_PARSE_NODE_KIND_BRACKET(NamedConstraintDefinition, NamedConstraintDefinitionStart, CARBON_TOKEN(CloseCurlyBrace)) CARBON_PARSE_NODE_KIND_BRACKET(NamedConstraintDecl, NamedConstraintIntroducer, CARBON_TOKEN(Semi)) #undef CARBON_PARSE_NODE_KIND #undef CARBON_PARSE_NODE_KIND_BRACKET #undef CARBON_PARSE_NODE_KIND_CHILD_COUNT #undef CARBON_PARSE_NODE_KIND_TOKEN_LITERAL #undef CARBON_PARSE_NODE_KIND_TOKEN_MODIFIER #undef CARBON_TOKEN #undef CARBON_ANY_TOKEN #undef CARBON_IF_ERROR