diff --git a/toolchain/parse/BUILD b/toolchain/parse/BUILD index b5878eb48f3c..983528e1c91e 100644 --- a/toolchain/parse/BUILD +++ b/toolchain/parse/BUILD @@ -21,6 +21,7 @@ cc_library( deps = [ "//common:check", "//common:enum_base", + "//toolchain/lex:token_kind", ], ) diff --git a/toolchain/parse/context.cpp b/toolchain/parse/context.cpp index 751e9d2e1525..a8ef7a2879e6 100644 --- a/toolchain/parse/context.cpp +++ b/toolchain/parse/context.cpp @@ -58,6 +58,7 @@ Context::Context(Tree& tree, Lex::TokenizedBuffer& tokens, auto Context::AddLeafNode(NodeKind kind, Lex::Token token, bool has_error) -> void { + CheckNodeMatchesLexerToken(kind, tokens_->GetKind(token), has_error); tree_->node_impls_.push_back( Tree::NodeImpl(kind, has_error, token, /*subtree_size=*/1)); if (has_error) { @@ -67,6 +68,7 @@ auto Context::AddLeafNode(NodeKind kind, Lex::Token token, bool has_error) auto Context::AddNode(NodeKind kind, Lex::Token token, int subtree_start, bool has_error) -> void { + CheckNodeMatchesLexerToken(kind, tokens_->GetKind(token), has_error); int subtree_size = tree_->size() - subtree_start + 1; tree_->node_impls_.push_back( Tree::NodeImpl(kind, has_error, token, subtree_size)); diff --git a/toolchain/parse/handle_declaration_name_and_params.cpp b/toolchain/parse/handle_declaration_name_and_params.cpp index a4a9c779e196..2b220c3c7fed 100644 --- a/toolchain/parse/handle_declaration_name_and_params.cpp +++ b/toolchain/parse/handle_declaration_name_and_params.cpp @@ -33,7 +33,8 @@ static auto HandleDeclarationNameAndParams(Context& context, State after_name) context.emitter().Emit(*context.position(), ExpectedDeclarationName, context.tokens().GetKind(state.token)); context.ReturnErrorOnState(); - context.AddLeafNode(NodeKind::InvalidParse, *context.position()); + context.AddLeafNode(NodeKind::InvalidParse, *context.position(), + /*has_error=*/true); } } diff --git a/toolchain/parse/node_kind.cpp b/toolchain/parse/node_kind.cpp index d095a8c1719b..abccdee9fdd6 100644 --- a/toolchain/parse/node_kind.cpp +++ b/toolchain/parse/node_kind.cpp @@ -26,7 +26,8 @@ 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_BRACKET(Name, BracketName, ...) \ + NodeKind::BracketName, #define CARBON_PARSE_NODE_KIND_CHILD_COUNT(Name, ...) NodeKind::Name, #include "toolchain/parse/node_kind.def" }; @@ -38,7 +39,7 @@ auto NodeKind::bracket() const -> NodeKind { 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, +#define CARBON_PARSE_NODE_KIND_CHILD_COUNT(Name, Size, ...) Size, #include "toolchain/parse/node_kind.def" }; auto child_count = ChildCount[AsInt()]; @@ -46,4 +47,47 @@ auto NodeKind::child_count() const -> int32_t { return child_count; } +void CheckNodeMatchesLexerToken(NodeKind node_kind, Lex::TokenKind token_kind, + bool has_error) { + switch (node_kind) { + // Use `CARBON_LOG CARBON_ANY_TOKEN` to discover which combinations happen + // in practice. +#define CARBON_LOG \ + llvm::errs() << "ZZZ: Created parse node with NodeKind " << node_kind \ + << " and has_error " << has_error << " for lexical token " \ + << token_kind << "\n"; + +#define CARBON_ANY_TOKEN return; + +#define CARBON_TOKEN(Expected) \ + if (token_kind == Lex::TokenKind::Expected) { \ + return; \ + } + +#define CARBON_IF_ERROR(MatchActions) \ + if (has_error) { \ + MatchActions \ + } + +#define CARBON_CASE(Name, MatchActions) \ + case NodeKind::Name: \ + MatchActions; \ + break; + +#define CARBON_PARSE_NODE_KIND_BRACKET(Name, BracketName, MatchActions) \ + CARBON_CASE(Name, MatchActions) + +#define CARBON_PARSE_NODE_KIND_CHILD_COUNT(Name, Size, MatchActions) \ + CARBON_CASE(Name, MatchActions) + +#include "toolchain/parse/node_kind.def" + +#undef CARBON_LOG +#undef CARBON_CASE + } + CARBON_FATAL() << "Created parse node with NodeKind " << node_kind + << " and has_error " << has_error + << " for unexpected lexical token " << token_kind; +} + } // namespace Carbon::Parse diff --git a/toolchain/parse/node_kind.def b/toolchain/parse/node_kind.def index e1748120aed0..42872053235e 100644 --- a/toolchain/parse/node_kind.def +++ b/toolchain/parse/node_kind.def @@ -11,13 +11,20 @@ // - 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) +// - 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) +// - 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. // +// 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. // @@ -41,22 +48,27 @@ #endif // The start of the file. -CARBON_PARSE_NODE_KIND_CHILD_COUNT(FileStart, 0) +CARBON_PARSE_NODE_KIND_CHILD_COUNT(FileStart, 0, CARBON_TOKEN(StartOfFile)) // The end of the file. -CARBON_PARSE_NODE_KIND_CHILD_COUNT(FileEnd, 0) +CARBON_PARSE_NODE_KIND_CHILD_COUNT(FileEnd, 0, CARBON_TOKEN(EndOfFile)) // An invalid parse. Used to balance the parse tree. Always has an error. -CARBON_PARSE_NODE_KIND_CHILD_COUNT(InvalidParse, 0) +CARBON_PARSE_NODE_KIND_CHILD_COUNT(InvalidParse, 0, + CARBON_IF_ERROR(CARBON_ANY_TOKEN)) // An empty declaration, such as `;`. -CARBON_PARSE_NODE_KIND_CHILD_COUNT(EmptyDeclaration, 0) +CARBON_PARSE_NODE_KIND_CHILD_COUNT(EmptyDeclaration, 0, + CARBON_TOKEN(Semi) + CARBON_IF_ERROR(CARBON_ANY_TOKEN)) // A name in a non-expression context, such as a declaration. -CARBON_PARSE_NODE_KIND_CHILD_COUNT(Name, 0) +CARBON_PARSE_NODE_KIND_CHILD_COUNT(Name, 0, + CARBON_TOKEN(Identifier) + CARBON_IF_ERROR(CARBON_ANY_TOKEN)) // A name in an expression context. -CARBON_PARSE_NODE_KIND_CHILD_COUNT(NameExpression, 0) +CARBON_PARSE_NODE_KIND_CHILD_COUNT(NameExpression, 0, CARBON_TOKEN(Identifier)) // `package`: // PackageIntroducer @@ -65,25 +77,31 @@ CARBON_PARSE_NODE_KIND_CHILD_COUNT(NameExpression, 0) // PackageLibrary // PackageApi or PackageImpl // PackageDirective -CARBON_PARSE_NODE_KIND_CHILD_COUNT(PackageIntroducer, 0) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(PackageApi, 0) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(PackageImpl, 0) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(PackageLibrary, 1) -CARBON_PARSE_NODE_KIND_BRACKET(PackageDirective, PackageIntroducer) +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_CHILD_COUNT(PackageLibrary, 1, CARBON_TOKEN(Library)) +CARBON_PARSE_NODE_KIND_BRACKET(PackageDirective, PackageIntroducer, + CARBON_TOKEN(Semi) + CARBON_IF_ERROR(CARBON_TOKEN(Package))) // `namespace`: // NamespaceStart // _external_: Name or QualifiedDeclaration // Namespace -CARBON_PARSE_NODE_KIND_CHILD_COUNT(NamespaceStart, 0) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(Namespace, 2) +CARBON_PARSE_NODE_KIND_CHILD_COUNT(NamespaceStart, 0, CARBON_TOKEN(Namespace)) +CARBON_PARSE_NODE_KIND_CHILD_COUNT(Namespace, 2, CARBON_TOKEN(Semi)) // A code block: // CodeBlockStart // _external_: statements // CodeBlock -CARBON_PARSE_NODE_KIND_CHILD_COUNT(CodeBlockStart, 0) -CARBON_PARSE_NODE_KIND_BRACKET(CodeBlock, CodeBlockStart) +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 @@ -98,11 +116,15 @@ CARBON_PARSE_NODE_KIND_BRACKET(CodeBlock, CodeBlockStart) // The above is the structure for a definition; for a declaration, // FunctionDefinitionStart and later nodes are removed and replaced by // FunctionDeclaration. -CARBON_PARSE_NODE_KIND_CHILD_COUNT(FunctionIntroducer, 0) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(ReturnType, 1) -CARBON_PARSE_NODE_KIND_BRACKET(FunctionDefinitionStart, FunctionIntroducer) -CARBON_PARSE_NODE_KIND_BRACKET(FunctionDefinition, FunctionDefinitionStart) -CARBON_PARSE_NODE_KIND_BRACKET(FunctionDeclaration, FunctionIntroducer) +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(FunctionDeclaration, FunctionIntroducer, + CARBON_TOKEN(Semi) + CARBON_IF_ERROR(CARBON_TOKEN(Fn))) // A parameter list, possibly deduced: // [Deduced]ParamertListStart @@ -112,11 +134,15 @@ CARBON_PARSE_NODE_KIND_BRACKET(FunctionDeclaration, FunctionIntroducer) // // Expressions and ParameterListComma may repeat with ParameterListComma as a // separator. -CARBON_PARSE_NODE_KIND_CHILD_COUNT(ParameterListStart, 0) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(DeducedParameterListStart, 0) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(ParameterListComma, 0) -CARBON_PARSE_NODE_KIND_BRACKET(ParameterList, ParameterListStart) -CARBON_PARSE_NODE_KIND_BRACKET(DeducedParameterList, DeducedParameterListStart) +CARBON_PARSE_NODE_KIND_CHILD_COUNT(ParameterListStart, 0, + CARBON_TOKEN(OpenParen)) +CARBON_PARSE_NODE_KIND_CHILD_COUNT(DeducedParameterListStart, 0, + CARBON_TOKEN(OpenSquareBracket)) +CARBON_PARSE_NODE_KIND_CHILD_COUNT(ParameterListComma, 0, CARBON_TOKEN(Comma)) +CARBON_PARSE_NODE_KIND_BRACKET(ParameterList, ParameterListStart, + CARBON_TOKEN(CloseParen)) +CARBON_PARSE_NODE_KIND_BRACKET(DeducedParameterList, DeducedParameterListStart, + CARBON_TOKEN(CloseSquareBracket)) // An array type, such as `[i32; 3]` or `[i32;]`: // ArrayExpressionStart @@ -126,9 +152,14 @@ CARBON_PARSE_NODE_KIND_BRACKET(DeducedParameterList, DeducedParameterListStart) // ArrayExpression // // The bound expression is optional. -CARBON_PARSE_NODE_KIND_CHILD_COUNT(ArrayExpressionStart, 0) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(ArrayExpressionSemi, 2) -CARBON_PARSE_NODE_KIND_BRACKET(ArrayExpression, ArrayExpressionSemi) +CARBON_PARSE_NODE_KIND_CHILD_COUNT(ArrayExpressionStart, 0, + CARBON_TOKEN(OpenSquareBracket)) +// May be associated with a `]` token on error. +CARBON_PARSE_NODE_KIND_CHILD_COUNT( + ArrayExpressionSemi, 2, + CARBON_TOKEN(Semi) CARBON_IF_ERROR(CARBON_TOKEN(CloseSquareBracket))) +CARBON_PARSE_NODE_KIND_BRACKET(ArrayExpression, ArrayExpressionSemi, + CARBON_TOKEN(CloseSquareBracket)) // A pattern binding, such as `name: Type`: // Name @@ -137,10 +168,13 @@ CARBON_PARSE_NODE_KIND_BRACKET(ArrayExpression, ArrayExpressionSemi) // // Address and Template may be parents to [Generic]PatternBinding, in that // order. -CARBON_PARSE_NODE_KIND_CHILD_COUNT(PatternBinding, 2) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(GenericPatternBinding, 2) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(Address, 1) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(Template, 1) +CARBON_PARSE_NODE_KIND_CHILD_COUNT(PatternBinding, 2, + CARBON_TOKEN(Colon) + CARBON_IF_ERROR(CARBON_ANY_TOKEN)) +CARBON_PARSE_NODE_KIND_CHILD_COUNT(GenericPatternBinding, 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 @@ -148,9 +182,10 @@ CARBON_PARSE_NODE_KIND_CHILD_COUNT(Template, 1) // LetInitializer // _external_: expression // LetDeclaration -CARBON_PARSE_NODE_KIND_CHILD_COUNT(LetIntroducer, 0) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(LetInitializer, 0) -CARBON_PARSE_NODE_KIND_BRACKET(LetDeclaration, LetIntroducer) +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(LetDeclaration, LetIntroducer, + CARBON_TOKEN(Semi)) // `var`: // VariableIntroducer @@ -161,26 +196,33 @@ CARBON_PARSE_NODE_KIND_BRACKET(LetDeclaration, LetIntroducer) // // The VariableInitializer and following expression are paired: either both will // be present, or neither will. -CARBON_PARSE_NODE_KIND_CHILD_COUNT(VariableIntroducer, 0) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(VariableInitializer, 0) -CARBON_PARSE_NODE_KIND_BRACKET(VariableDeclaration, VariableIntroducer) +CARBON_PARSE_NODE_KIND_CHILD_COUNT(VariableIntroducer, 0, CARBON_TOKEN(Var)) +CARBON_PARSE_NODE_KIND_CHILD_COUNT(VariableInitializer, 0, CARBON_TOKEN(Equal)) +CARBON_PARSE_NODE_KIND_BRACKET(VariableDeclaration, VariableIntroducer, + CARBON_TOKEN(Semi) + CARBON_IF_ERROR(CARBON_TOKEN(Var))) // An expression statement: // _external_: expression // ExpressionStatement -CARBON_PARSE_NODE_KIND_CHILD_COUNT(ExpressionStatement, 1) +CARBON_PARSE_NODE_KIND_CHILD_COUNT(ExpressionStatement, 1, CARBON_TOKEN(Semi)) // `break`: // BreakStatementStart // BreakStatement -CARBON_PARSE_NODE_KIND_CHILD_COUNT(BreakStatementStart, 0) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(BreakStatement, 1) +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_PARSE_NODE_KIND_CHILD_COUNT(ContinueStatement, 1) +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 @@ -188,8 +230,11 @@ CARBON_PARSE_NODE_KIND_CHILD_COUNT(ContinueStatement, 1) // ReturnStatement // // The child expression is optional. -CARBON_PARSE_NODE_KIND_CHILD_COUNT(ReturnStatementStart, 0) -CARBON_PARSE_NODE_KIND_BRACKET(ReturnStatement, ReturnStatementStart) +CARBON_PARSE_NODE_KIND_CHILD_COUNT(ReturnStatementStart, 0, + CARBON_TOKEN(Return)) +CARBON_PARSE_NODE_KIND_BRACKET(ReturnStatement, ReturnStatementStart, + CARBON_TOKEN(Semi) + CARBON_IF_ERROR(CARBON_TOKEN(Return))) // `for`: // ForHeaderStart @@ -203,10 +248,16 @@ CARBON_PARSE_NODE_KIND_BRACKET(ReturnStatement, ReturnStatementStart) // ForStatement // // Versus a normal `var`, ForIn replaces VariableDeclaration. -CARBON_PARSE_NODE_KIND_CHILD_COUNT(ForHeaderStart, 0) -CARBON_PARSE_NODE_KIND_BRACKET(ForIn, VariableIntroducer) -CARBON_PARSE_NODE_KIND_BRACKET(ForHeader, ForHeaderStart) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(ForStatement, 2) +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 @@ -218,10 +269,14 @@ CARBON_PARSE_NODE_KIND_CHILD_COUNT(ForStatement, 2) // IfStatement // // IfStatementElse and the following node are optional based on `else` presence. -CARBON_PARSE_NODE_KIND_CHILD_COUNT(IfConditionStart, 0) -CARBON_PARSE_NODE_KIND_BRACKET(IfCondition, IfConditionStart) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(IfStatementElse, 0) -CARBON_PARSE_NODE_KIND_BRACKET(IfStatement, IfCondition) +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 @@ -229,17 +284,21 @@ CARBON_PARSE_NODE_KIND_BRACKET(IfStatement, IfCondition) // WhileCondition // _external_: CodeBlock // WhileStatement -CARBON_PARSE_NODE_KIND_CHILD_COUNT(WhileConditionStart, 0) -CARBON_PARSE_NODE_KIND_BRACKET(WhileCondition, WhileConditionStart) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(WhileStatement, 2) +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 // IndexExpressionStart // _external_: expression // IndexExpression -CARBON_PARSE_NODE_KIND_CHILD_COUNT(IndexExpressionStart, 1) -CARBON_PARSE_NODE_KIND_BRACKET(IndexExpression, IndexExpressionStart) +CARBON_PARSE_NODE_KIND_CHILD_COUNT(IndexExpressionStart, 1, + CARBON_TOKEN(OpenSquareBracket)) +CARBON_PARSE_NODE_KIND_BRACKET(IndexExpression, IndexExpressionStart, + CARBON_TOKEN(CloseSquareBracket)) // Parenthesized expressions, such as `(2)`: // ParenExpressionOrTupleLiteralStart @@ -254,11 +313,14 @@ CARBON_PARSE_NODE_KIND_BRACKET(IndexExpression, IndexExpressionStart) // // Expressions and TupleLiteralComma may repeat with TupleLiteralComma as a // separator. -CARBON_PARSE_NODE_KIND_CHILD_COUNT(ParenExpressionOrTupleLiteralStart, 0) +CARBON_PARSE_NODE_KIND_CHILD_COUNT(ParenExpressionOrTupleLiteralStart, 0, + CARBON_TOKEN(OpenParen)) CARBON_PARSE_NODE_KIND_BRACKET(ParenExpression, - ParenExpressionOrTupleLiteralStart) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(TupleLiteralComma, 0) -CARBON_PARSE_NODE_KIND_BRACKET(TupleLiteral, ParenExpressionOrTupleLiteralStart) + ParenExpressionOrTupleLiteralStart, + CARBON_TOKEN(CloseParen)) +CARBON_PARSE_NODE_KIND_CHILD_COUNT(TupleLiteralComma, 0, CARBON_TOKEN(Comma)) +CARBON_PARSE_NODE_KIND_BRACKET(TupleLiteral, ParenExpressionOrTupleLiteralStart, + CARBON_TOKEN(CloseParen)) // Call expressions, such as `a()`: // _external_: expression @@ -269,9 +331,11 @@ CARBON_PARSE_NODE_KIND_BRACKET(TupleLiteral, ParenExpressionOrTupleLiteralStart) // // Expressions and CallExpressionComma may repeat with CallExpressionComma as a // separator. -CARBON_PARSE_NODE_KIND_CHILD_COUNT(CallExpressionStart, 1) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(CallExpressionComma, 0) -CARBON_PARSE_NODE_KIND_BRACKET(CallExpression, CallExpressionStart) +CARBON_PARSE_NODE_KIND_CHILD_COUNT(CallExpressionStart, 1, + CARBON_TOKEN(OpenParen)) +CARBON_PARSE_NODE_KIND_CHILD_COUNT(CallExpressionComma, 0, CARBON_TOKEN(Comma)) +CARBON_PARSE_NODE_KIND_BRACKET(CallExpression, CallExpressionStart, + CARBON_TOKEN(CloseParen)) // A qualified declaration, such as `a.b`: // _external_: NameExpression or QualifiedDeclaration @@ -280,47 +344,104 @@ CARBON_PARSE_NODE_KIND_BRACKET(CallExpression, CallExpressionStart) // // TODO: This will eventually more general expressions, for example with // `GenericType(type_args).ChildType(child_type_args).Name`. -CARBON_PARSE_NODE_KIND_CHILD_COUNT(QualifiedDeclaration, 2) +CARBON_PARSE_NODE_KIND_CHILD_COUNT(QualifiedDeclaration, 2, + CARBON_TOKEN(Period)) // A member access expression, such as `a.b` or // `GetObject().(Interface.member)`: // _external_: lhs expression // _external_: rhs expression // QualifiedExpression -CARBON_PARSE_NODE_KIND_CHILD_COUNT(MemberAccessExpression, 2) +CARBON_PARSE_NODE_KIND_CHILD_COUNT(MemberAccessExpression, 2, + CARBON_TOKEN(Period)) // A pointer member access expression, such as `a->b` or // `GetObject()->(Interface.member)`: // _external_: lhs expression // _external_: rhs expression // QualifiedExpression -CARBON_PARSE_NODE_KIND_CHILD_COUNT(PointerMemberAccessExpression, 2) +CARBON_PARSE_NODE_KIND_CHILD_COUNT(PointerMemberAccessExpression, 2, + CARBON_TOKEN(MinusGreater)) + +// clang-format off // A literal. -CARBON_PARSE_NODE_KIND_CHILD_COUNT(Literal, 0) +CARBON_PARSE_NODE_KIND_CHILD_COUNT(Literal, 0, + CARBON_TOKEN(False) + CARBON_TOKEN(True) + CARBON_TOKEN(IntegerLiteral) + CARBON_TOKEN(RealLiteral) + CARBON_TOKEN(StringLiteral) + CARBON_TOKEN(Bool) + CARBON_TOKEN(IntegerTypeLiteral) + CARBON_TOKEN(UnsignedIntegerTypeLiteral) + CARBON_TOKEN(FloatingPointTypeLiteral) + CARBON_TOKEN(StringTypeLiteral) + CARBON_TOKEN(Type)) // A prefix operator: // _external_: expression // PrefixOperator -CARBON_PARSE_NODE_KIND_CHILD_COUNT(PrefixOperator, 1) +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_PARSE_NODE_KIND_CHILD_COUNT(InfixOperator, 2, + CARBON_TOKEN(Amp) + CARBON_TOKEN(AmpEqual) + CARBON_TOKEN(And) + 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(Or) + 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 // The first operand of a short-circuiting infix operator: // _external_: expression // ShortCircuitOperand // _external_: expression // _external_: InfixOperator -CARBON_PARSE_NODE_KIND_CHILD_COUNT(ShortCircuitOperand, 1) +CARBON_PARSE_NODE_KIND_CHILD_COUNT(ShortCircuitOperand, 1, + CARBON_TOKEN(And) CARBON_TOKEN(Or)) // A postfix operator: // _external_: expression // PostfixOperator -CARBON_PARSE_NODE_KIND_CHILD_COUNT(PostfixOperator, 1) +CARBON_PARSE_NODE_KIND_CHILD_COUNT(PostfixOperator, 1, CARBON_TOKEN(Star)) // `if` expression + `then` + `else`: // _external_: expression @@ -329,9 +450,11 @@ CARBON_PARSE_NODE_KIND_CHILD_COUNT(PostfixOperator, 1) // IfExpressionThen // _external_: expression // IfExpressionElse -CARBON_PARSE_NODE_KIND_CHILD_COUNT(IfExpressionIf, 1) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(IfExpressionThen, 1) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(IfExpressionElse, 3) +CARBON_PARSE_NODE_KIND_CHILD_COUNT(IfExpressionIf, 1, CARBON_TOKEN(If)) +CARBON_PARSE_NODE_KIND_CHILD_COUNT(IfExpressionThen, 1, CARBON_TOKEN(Then)) +CARBON_PARSE_NODE_KIND_CHILD_COUNT(IfExpressionElse, 3, + CARBON_TOKEN(Else) + CARBON_IF_ERROR(CARBON_TOKEN(If))) // Struct literals, such as `{.a = 0}`: // StructLiteralOrStructTypeLiteralStart @@ -356,16 +479,21 @@ CARBON_PARSE_NODE_KIND_CHILD_COUNT(IfExpressionElse, 3) // 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_PARSE_NODE_KIND_CHILD_COUNT(StructFieldDesignator, 1) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(StructFieldValue, 2) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(StructFieldType, 2) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(StructFieldUnknown, 0) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(StructComma, 0) +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) + StructLiteralOrStructTypeLiteralStart, + CARBON_TOKEN(CloseCurlyBrace)) CARBON_PARSE_NODE_KIND_BRACKET(StructTypeLiteral, - StructLiteralOrStructTypeLiteralStart) + StructLiteralOrStructTypeLiteralStart, + CARBON_TOKEN(CloseCurlyBrace)) // `class`: // ClassIntroducer @@ -377,10 +505,14 @@ CARBON_PARSE_NODE_KIND_BRACKET(StructTypeLiteral, // The above is the structure for a definition; for a declaration, // ClassDefinitionStart and later nodes are removed and replaced by // ClassDeclaration. -CARBON_PARSE_NODE_KIND_CHILD_COUNT(ClassIntroducer, 0) -CARBON_PARSE_NODE_KIND_BRACKET(ClassDefinitionStart, ClassIntroducer) -CARBON_PARSE_NODE_KIND_BRACKET(ClassDefinition, ClassDefinitionStart) -CARBON_PARSE_NODE_KIND_BRACKET(ClassDeclaration, ClassIntroducer) +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(ClassDeclaration, ClassIntroducer, + CARBON_TOKEN(Semi) + CARBON_IF_ERROR(CARBON_TOKEN(Class))) // `interface`: // InterfaceIntroducer @@ -392,10 +524,15 @@ CARBON_PARSE_NODE_KIND_BRACKET(ClassDeclaration, ClassIntroducer) // The above is the structure for a definition; for a declaration, // InterfaceDefinitionStart and later nodes are removed and replaced by // InterfaceDeclaration. -CARBON_PARSE_NODE_KIND_CHILD_COUNT(InterfaceIntroducer, 0) -CARBON_PARSE_NODE_KIND_BRACKET(InterfaceDefinitionStart, InterfaceIntroducer) -CARBON_PARSE_NODE_KIND_BRACKET(InterfaceDefinition, InterfaceDefinitionStart) -CARBON_PARSE_NODE_KIND_BRACKET(InterfaceDeclaration, InterfaceIntroducer) +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(InterfaceDeclaration, InterfaceIntroducer, + CARBON_TOKEN(Semi) + CARBON_IF_ERROR(CARBON_TOKEN(Interface))) // `constraint`: // NamedConstraintIntroducer @@ -407,22 +544,30 @@ CARBON_PARSE_NODE_KIND_BRACKET(InterfaceDeclaration, InterfaceIntroducer) // The above is the structure for a definition; for a declaration, // NamedConstraintDefinitionStart and later nodes are removed and replaced by // NamedConstraintDeclaration. -CARBON_PARSE_NODE_KIND_CHILD_COUNT(NamedConstraintIntroducer, 0) +CARBON_PARSE_NODE_KIND_CHILD_COUNT(NamedConstraintIntroducer, 0, + CARBON_TOKEN(Constraint)) CARBON_PARSE_NODE_KIND_BRACKET(NamedConstraintDefinitionStart, - NamedConstraintIntroducer) + NamedConstraintIntroducer, + CARBON_TOKEN(OpenCurlyBrace)) CARBON_PARSE_NODE_KIND_BRACKET(NamedConstraintDefinition, - NamedConstraintDefinitionStart) + NamedConstraintDefinitionStart, + CARBON_TOKEN(CloseCurlyBrace)) CARBON_PARSE_NODE_KIND_BRACKET(NamedConstraintDeclaration, - NamedConstraintIntroducer) + NamedConstraintIntroducer, CARBON_TOKEN(Semi)) // The `self` value and `Self` type identifier keywords. Typically of the form // `self: Self`: // SelfValueName // SelfTypeNameExpression // PatternBinding -CARBON_PARSE_NODE_KIND_CHILD_COUNT(SelfValueName, 0) -CARBON_PARSE_NODE_KIND_CHILD_COUNT(SelfTypeNameExpression, 0) +CARBON_PARSE_NODE_KIND_CHILD_COUNT(SelfValueName, 0, + CARBON_TOKEN(SelfValueIdentifier)) +CARBON_PARSE_NODE_KIND_CHILD_COUNT(SelfTypeNameExpression, 0, + CARBON_TOKEN(SelfTypeIdentifier)) #undef CARBON_PARSE_NODE_KIND #undef CARBON_PARSE_NODE_KIND_BRACKET #undef CARBON_PARSE_NODE_KIND_CHILD_COUNT +#undef CARBON_TOKEN +#undef CARBON_ANY_TOKEN +#undef CARBON_IF_ERROR diff --git a/toolchain/parse/node_kind.h b/toolchain/parse/node_kind.h index 3172c4d15620..8c6c5ed5625e 100644 --- a/toolchain/parse/node_kind.h +++ b/toolchain/parse/node_kind.h @@ -8,6 +8,7 @@ #include #include "common/enum_base.h" +#include "toolchain/lex/token_kind.h" namespace Carbon::Parse { @@ -44,6 +45,11 @@ class NodeKind : public CARBON_ENUM_BASE(NodeKind) { // We expect the parse node kind to fit compactly into 8 bits. static_assert(sizeof(NodeKind) == 1, "Kind objects include padding!"); +// Validates that a `parse_node_kind` parser node can be generated for a +// `lex_token_kind` lexer token. +void CheckNodeMatchesLexerToken(NodeKind parse_node_kind, + Lex::TokenKind lex_token_kind, bool has_error); + } // namespace Carbon::Parse #endif // CARBON_TOOLCHAIN_PARSE_NODE_KIND_H_ diff --git a/toolchain/parse/testdata/function/declaration/fail_missing_name.carbon b/toolchain/parse/testdata/function/declaration/fail_missing_name.carbon index c167165c60de..7fcb67d2f4df 100644 --- a/toolchain/parse/testdata/function/declaration/fail_missing_name.carbon +++ b/toolchain/parse/testdata/function/declaration/fail_missing_name.carbon @@ -13,7 +13,7 @@ fn (); // CHECK:STDOUT: parse_tree: [ // CHECK:STDOUT: {kind: 'FileStart', text: ''}, // CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'}, -// CHECK:STDOUT: {kind: 'InvalidParse', text: '('}, +// CHECK:STDOUT: {kind: 'InvalidParse', text: '(', has_error: yes}, // CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', has_error: yes, subtree_size: 3}, // CHECK:STDOUT: {kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] diff --git a/toolchain/parse/testdata/function/declaration/fail_only_fn_and_semi.carbon b/toolchain/parse/testdata/function/declaration/fail_only_fn_and_semi.carbon index f4a148ade67c..5ef4c23c46d3 100644 --- a/toolchain/parse/testdata/function/declaration/fail_only_fn_and_semi.carbon +++ b/toolchain/parse/testdata/function/declaration/fail_only_fn_and_semi.carbon @@ -13,7 +13,7 @@ fn; // CHECK:STDOUT: parse_tree: [ // CHECK:STDOUT: {kind: 'FileStart', text: ''}, // CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'}, -// CHECK:STDOUT: {kind: 'InvalidParse', text: ';'}, +// CHECK:STDOUT: {kind: 'InvalidParse', text: ';', has_error: yes}, // CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', has_error: yes, subtree_size: 3}, // CHECK:STDOUT: {kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] diff --git a/toolchain/parse/testdata/function/declaration/fail_repeated_fn_and_semi.carbon b/toolchain/parse/testdata/function/declaration/fail_repeated_fn_and_semi.carbon index be06d77bda6c..ed5125359fd7 100644 --- a/toolchain/parse/testdata/function/declaration/fail_repeated_fn_and_semi.carbon +++ b/toolchain/parse/testdata/function/declaration/fail_repeated_fn_and_semi.carbon @@ -13,7 +13,7 @@ fn fn; // CHECK:STDOUT: parse_tree: [ // CHECK:STDOUT: {kind: 'FileStart', text: ''}, // CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'}, -// CHECK:STDOUT: {kind: 'InvalidParse', text: 'fn'}, +// CHECK:STDOUT: {kind: 'InvalidParse', text: 'fn', has_error: yes}, // CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', has_error: yes, subtree_size: 3}, // CHECK:STDOUT: {kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] diff --git a/toolchain/parse/testdata/function/declaration/fail_skip_indented_newline_until_outdent.carbon b/toolchain/parse/testdata/function/declaration/fail_skip_indented_newline_until_outdent.carbon index bdbe3c8b26f4..de7f93babd36 100644 --- a/toolchain/parse/testdata/function/declaration/fail_skip_indented_newline_until_outdent.carbon +++ b/toolchain/parse/testdata/function/declaration/fail_skip_indented_newline_until_outdent.carbon @@ -16,7 +16,7 @@ fn F(); // CHECK:STDOUT: parse_tree: [ // CHECK:STDOUT: {kind: 'FileStart', text: ''}, // CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'}, -// CHECK:STDOUT: {kind: 'InvalidParse', text: '('}, +// CHECK:STDOUT: {kind: 'InvalidParse', text: '(', has_error: yes}, // CHECK:STDOUT: {kind: 'FunctionDeclaration', text: 'fn', has_error: yes, subtree_size: 3}, // CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'}, // CHECK:STDOUT: {kind: 'Name', text: 'F'}, diff --git a/toolchain/parse/testdata/function/declaration/fail_skip_indented_newline_with_semi.carbon b/toolchain/parse/testdata/function/declaration/fail_skip_indented_newline_with_semi.carbon index 48af24f52b0c..d666535d0434 100644 --- a/toolchain/parse/testdata/function/declaration/fail_skip_indented_newline_with_semi.carbon +++ b/toolchain/parse/testdata/function/declaration/fail_skip_indented_newline_with_semi.carbon @@ -16,7 +16,7 @@ fn F(); // CHECK:STDOUT: parse_tree: [ // CHECK:STDOUT: {kind: 'FileStart', text: ''}, // CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'}, -// CHECK:STDOUT: {kind: 'InvalidParse', text: '('}, +// CHECK:STDOUT: {kind: 'InvalidParse', text: '(', has_error: yes}, // CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', has_error: yes, subtree_size: 3}, // CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'}, // CHECK:STDOUT: {kind: 'Name', text: 'F'}, diff --git a/toolchain/parse/testdata/function/declaration/fail_skip_indented_newline_without_semi.carbon b/toolchain/parse/testdata/function/declaration/fail_skip_indented_newline_without_semi.carbon index a31fda0816b0..cb6b55ba6c80 100644 --- a/toolchain/parse/testdata/function/declaration/fail_skip_indented_newline_without_semi.carbon +++ b/toolchain/parse/testdata/function/declaration/fail_skip_indented_newline_without_semi.carbon @@ -16,7 +16,7 @@ fn F(); // CHECK:STDOUT: parse_tree: [ // CHECK:STDOUT: {kind: 'FileStart', text: ''}, // CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'}, -// CHECK:STDOUT: {kind: 'InvalidParse', text: '('}, +// CHECK:STDOUT: {kind: 'InvalidParse', text: '(', has_error: yes}, // CHECK:STDOUT: {kind: 'FunctionDeclaration', text: 'fn', has_error: yes, subtree_size: 3}, // CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'}, // CHECK:STDOUT: {kind: 'Name', text: 'F'}, diff --git a/toolchain/parse/testdata/function/declaration/fail_skip_to_newline_without_semi.carbon b/toolchain/parse/testdata/function/declaration/fail_skip_to_newline_without_semi.carbon index 4793e4586ba2..25606bc0f8bf 100644 --- a/toolchain/parse/testdata/function/declaration/fail_skip_to_newline_without_semi.carbon +++ b/toolchain/parse/testdata/function/declaration/fail_skip_to_newline_without_semi.carbon @@ -14,7 +14,7 @@ fn F(); // CHECK:STDOUT: parse_tree: [ // CHECK:STDOUT: {kind: 'FileStart', text: ''}, // CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'}, -// CHECK:STDOUT: {kind: 'InvalidParse', text: '('}, +// CHECK:STDOUT: {kind: 'InvalidParse', text: '(', has_error: yes}, // CHECK:STDOUT: {kind: 'FunctionDeclaration', text: 'fn', has_error: yes, subtree_size: 3}, // CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'}, // CHECK:STDOUT: {kind: 'Name', text: 'F'}, diff --git a/toolchain/parse/testdata/function/declaration/fail_without_name_and_many_tokens_in_params.carbon b/toolchain/parse/testdata/function/declaration/fail_without_name_and_many_tokens_in_params.carbon index 836b0dca6725..e1febd92c636 100644 --- a/toolchain/parse/testdata/function/declaration/fail_without_name_and_many_tokens_in_params.carbon +++ b/toolchain/parse/testdata/function/declaration/fail_without_name_and_many_tokens_in_params.carbon @@ -13,7 +13,7 @@ fn (a tokens c d e f g h i j k l m n o p q r s t u v w x y z); // CHECK:STDOUT: parse_tree: [ // CHECK:STDOUT: {kind: 'FileStart', text: ''}, // CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'}, -// CHECK:STDOUT: {kind: 'InvalidParse', text: '('}, +// CHECK:STDOUT: {kind: 'InvalidParse', text: '(', has_error: yes}, // CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', has_error: yes, subtree_size: 3}, // CHECK:STDOUT: {kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] diff --git a/toolchain/parse/testdata/generics/interface/fail_missing_name.carbon b/toolchain/parse/testdata/generics/interface/fail_missing_name.carbon index 430c527297bc..f2af4a7f3270 100644 --- a/toolchain/parse/testdata/generics/interface/fail_missing_name.carbon +++ b/toolchain/parse/testdata/generics/interface/fail_missing_name.carbon @@ -14,7 +14,7 @@ interface { // CHECK:STDOUT: parse_tree: [ // CHECK:STDOUT: {kind: 'FileStart', text: ''}, // CHECK:STDOUT: {kind: 'InterfaceIntroducer', text: 'interface'}, -// CHECK:STDOUT: {kind: 'InvalidParse', text: '{'}, +// CHECK:STDOUT: {kind: 'InvalidParse', text: '{', has_error: yes}, // CHECK:STDOUT: {kind: 'InterfaceDeclaration', text: 'interface', has_error: yes, subtree_size: 3}, // CHECK:STDOUT: {kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] diff --git a/toolchain/parse/testdata/namespace/fail_no_name.carbon b/toolchain/parse/testdata/namespace/fail_no_name.carbon index a0abef76b692..6256b1cbd65b 100644 --- a/toolchain/parse/testdata/namespace/fail_no_name.carbon +++ b/toolchain/parse/testdata/namespace/fail_no_name.carbon @@ -13,7 +13,7 @@ namespace; // CHECK:STDOUT: parse_tree: [ // CHECK:STDOUT: {kind: 'FileStart', text: ''}, // CHECK:STDOUT: {kind: 'NamespaceStart', text: 'namespace'}, -// CHECK:STDOUT: {kind: 'InvalidParse', text: ';'}, +// CHECK:STDOUT: {kind: 'InvalidParse', text: ';', has_error: yes}, // CHECK:STDOUT: {kind: 'Namespace', text: ';', has_error: yes, subtree_size: 3}, // CHECK:STDOUT: {kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ]