diff --git a/toolchain/parser/parse_node_kind.def b/toolchain/parser/parse_node_kind.def index 15c0127b67fd..561c78272c5c 100644 --- a/toolchain/parser/parse_node_kind.def +++ b/toolchain/parser/parse_node_kind.def @@ -79,8 +79,9 @@ CARBON_PARSE_NODE_KIND_BRACKET(CodeBlock, CodeBlockStart) // _external_: statements // FunctionDefinition // -// The above is a definition; for a declaration, FunctionDeclaration will end it -// where FunctionDefinitionStart is for a definition. +// 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) @@ -282,14 +283,19 @@ CARBON_PARSE_NODE_KIND_BRACKET(StructTypeLiteral, StructLiteralOrStructTypeLiteralStart) // `interface`: -// _external_: DeclaredName -// InterfaceBodyStart -// _external_: statements -// InterfaceBodyEnd +// InterfaceIntroducer +// DeclaredName +// InterfaceDefinitionStart +// _external_: declarations // InterfaceDefinition -CARBON_PARSE_NODE_KIND_CHILD_COUNT(InterfaceBodyStart, 0) -CARBON_PARSE_NODE_KIND_BRACKET(InterfaceBody, InterfaceBodyStart) -CARBON_PARSE_NODE_KIND_BRACKET(InterfaceDefinition, DeclaredName) +// +// 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) // A pattern binding for `self` deduced parameter: // `self` diff --git a/toolchain/parser/parser.cpp b/toolchain/parser/parser.cpp index 6287e8b54883..4ca8687b2470 100644 --- a/toolchain/parser/parser.cpp +++ b/toolchain/parser/parser.cpp @@ -28,9 +28,6 @@ CARBON_DIAGNOSTIC(ExpectedParenAfter, Error, "Expected `(` after `{0}`.", CARBON_DIAGNOSTIC(ExpectedSemiAfterExpression, Error, "Expected `;` after expression."); -CARBON_DIAGNOSTIC(UnrecognizedDeclaration, Error, - "Unrecognized declaration introducer."); - // A relative location for characters in errors. enum class RelativeLocation : int8_t { Around, @@ -465,6 +462,31 @@ auto Parser::GetDeclarationContext() -> DeclarationContext { llvm_unreachable("Should always be able to find DeclarationLoop"); } +auto Parser::HandleDeclarationError(StateStackEntry state, + ParseNodeKind parse_node_kind, + bool skip_past_likely_end) -> void { + auto token = state.token; + if (skip_past_likely_end) { + if (auto semi = SkipPastLikelyEnd(token)) { + token = *semi; + } + } + AddNode(parse_node_kind, token, state.subtree_start, + /*has_error=*/true); +} + +auto Parser::HandleUnrecognizedDeclaration() -> void { + CARBON_DIAGNOSTIC(UnrecognizedDeclaration, Error, + "Unrecognized declaration introducer."); + emitter_->Emit(*position_, UnrecognizedDeclaration); + auto cursor = *position_; + auto semi = SkipPastLikelyEnd(cursor); + // Locate the EmptyDeclaration at the semi when found, but use the + // original cursor location for an error when not. + AddLeafNode(ParseNodeKind::EmptyDeclaration, semi ? *semi : cursor, + /*has_error=*/true); +} + auto Parser::HandleBraceExpressionState() -> void { auto state = PopState(); @@ -731,7 +753,6 @@ auto Parser::HandleDeclarationLoopState() -> void { } case TokenKind::Fn: { PushState(ParserState::FunctionIntroducer); - AddLeafNode(ParseNodeKind::FunctionIntroducer, Consume()); break; } case TokenKind::Package: { @@ -748,17 +769,10 @@ auto Parser::HandleDeclarationLoopState() -> void { } case TokenKind::Interface: { PushState(ParserState::InterfaceIntroducer); - ++position_; break; } default: { - emitter_->Emit(*position_, UnrecognizedDeclaration); - auto cursor = *position_; - auto semi = SkipPastLikelyEnd(cursor); - // Locate the EmptyDeclaration at the semi when found, but use the - // original cursor location for an error when not. - AddLeafNode(ParseNodeKind::EmptyDeclaration, semi ? *semi : cursor, - /*has_error=*/true); + HandleUnrecognizedDeclaration(); break; } } @@ -1017,21 +1031,11 @@ auto Parser::HandleExpressionStatementFinishState() -> void { ReturnErrorOnState(); } -auto Parser::HandleFunctionError(StateStackEntry state, - bool skip_past_likely_end) -> void { - auto token = state.token; - if (skip_past_likely_end) { - if (auto semi = SkipPastLikelyEnd(token)) { - token = *semi; - } - } - AddNode(ParseNodeKind::FunctionDeclaration, token, state.subtree_start, - /*has_error=*/true); -} - auto Parser::HandleFunctionIntroducerState() -> void { auto state = PopState(); + AddLeafNode(ParseNodeKind::FunctionIntroducer, Consume()); + if (!ConsumeAndAddLeafNodeIf(TokenKind::Identifier, ParseNodeKind::DeclaredName)) { CARBON_DIAGNOSTIC(ExpectedFunctionName, Error, @@ -1040,7 +1044,8 @@ auto Parser::HandleFunctionIntroducerState() -> void { // TODO: We could change the lexer to allow us to synthesize certain // kinds of tokens and try to "recover" here, but unclear that this is // really useful. - HandleFunctionError(state, true); + HandleDeclarationError(state, ParseNodeKind::FunctionDeclaration, + /*skip_past_likely_end=*/true); return; } @@ -1073,7 +1078,8 @@ auto Parser::HandleFunctionAfterDeducedParameterListState() -> void { CARBON_DIAGNOSTIC(ExpectedFunctionParams, Error, "Expected `(` after function name."); emitter_->Emit(*position_, ExpectedFunctionParams); - HandleFunctionError(state, true); + HandleDeclarationError(state, ParseNodeKind::FunctionDeclaration, + /*skip_past_likely_end=*/true); return; } @@ -1154,7 +1160,8 @@ auto Parser::HandleFunctionSignatureFinishState() -> void { MethodImplNotAllowed, Error, "Method implementations are not allowed in interfaces."); emitter_->Emit(*position_, MethodImplNotAllowed); - HandleFunctionError(state, /*skip_past_likely_end=*/true); + HandleDeclarationError(state, ParseNodeKind::FunctionDeclaration, + /*skip_past_likely_end=*/true); break; } @@ -1175,7 +1182,8 @@ auto Parser::HandleFunctionSignatureFinishState() -> void { // Only need to skip if we've not already found a new line. bool skip_past_likely_end = tokens_->GetLine(*position_) == tokens_->GetLine(state.token); - HandleFunctionError(state, skip_past_likely_end); + HandleDeclarationError(state, ParseNodeKind::FunctionDeclaration, + skip_past_likely_end); break; } } @@ -1190,39 +1198,37 @@ auto Parser::HandleFunctionDefinitionFinishState() -> void { auto Parser::HandleInterfaceIntroducerState() -> void { auto state = PopState(); + AddLeafNode(ParseNodeKind::InterfaceIntroducer, Consume()); + if (!ConsumeAndAddLeafNodeIf(TokenKind::Identifier, ParseNodeKind::DeclaredName)) { CARBON_DIAGNOSTIC(ExpectedInterfaceName, Error, "Expected interface name after `interface` keyword."); emitter_->Emit(*position_, ExpectedInterfaceName); - state.has_error = true; - - // Add a name node even when it's not present because it's used for subtree - // bracketing on interfaces. - // TODO: Either fix this or normalize it, still deciding on the right - // approach. - AddLeafNode(ParseNodeKind::DeclaredName, state.token, /*has_error=*/true); + HandleDeclarationError(state, ParseNodeKind::InterfaceDeclaration, + /*skip_past_likely_end=*/true); + return; } - bool parse_body = true; + if (auto semi = ConsumeIf(TokenKind::Semi)) { + AddNode(ParseNodeKind::InterfaceDeclaration, *semi, state.subtree_start, + state.has_error); + return; + } if (!PositionIs(TokenKind::OpenCurlyBrace)) { CARBON_DIAGNOSTIC(ExpectedInterfaceOpenCurlyBrace, Error, "Expected `{{` to start interface definition."); emitter_->Emit(*position_, ExpectedInterfaceOpenCurlyBrace); - state.has_error = true; - - SkipPastLikelyEnd(state.token); - parse_body = false; + HandleDeclarationError(state, ParseNodeKind::InterfaceDeclaration, + /*skip_past_likely_end=*/true); + return; } - state.state = ParserState::InterfaceDefinitionFinish; + state.state = ParserState::InterfaceDefinitionLoop; PushState(state); - - if (parse_body) { - PushState(ParserState::InterfaceDefinitionLoop); - AddLeafNode(ParseNodeKind::InterfaceBodyStart, Consume()); - } + AddNode(ParseNodeKind::InterfaceDefinitionStart, Consume(), + state.subtree_start, state.has_error); } auto Parser::HandleInterfaceDefinitionLoopState() -> void { @@ -1232,36 +1238,21 @@ auto Parser::HandleInterfaceDefinitionLoopState() -> void { switch (PositionKind()) { case TokenKind::CloseCurlyBrace: { auto state = PopState(); - - AddNode(ParseNodeKind::InterfaceBody, Consume(), state.subtree_start, - state.has_error); - + AddNode(ParseNodeKind::InterfaceDefinition, Consume(), + state.subtree_start, state.has_error); break; } case TokenKind::Fn: { PushState(ParserState::FunctionIntroducer); - AddLeafNode(ParseNodeKind::FunctionIntroducer, Consume()); break; } default: { - emitter_->Emit(*position_, UnrecognizedDeclaration); - if (auto semi = SkipPastLikelyEnd(*position_)) { - AddLeafNode(ParseNodeKind::EmptyDeclaration, *semi, - /*has_error=*/true); - } else { - ReturnErrorOnState(); - } + HandleUnrecognizedDeclaration(); break; } } } -auto Parser::HandleInterfaceDefinitionFinishState() -> void { - auto state = PopState(); - AddNode(ParseNodeKind::InterfaceDefinition, state.token, state.subtree_start, - state.has_error); -} - auto Parser::HandlePackageState() -> void { auto state = PopState(); diff --git a/toolchain/parser/parser.h b/toolchain/parser/parser.h index 6bbfe3486b11..a3a8f90e2511 100644 --- a/toolchain/parser/parser.h +++ b/toolchain/parser/parser.h @@ -262,6 +262,17 @@ class Parser { // parses should only need to look down a couple steps. auto GetDeclarationContext() -> DeclarationContext; + // Handles error recovery in a declaration, particularly before any possible + // definition has started (although one could be present). Recover to a + // semicolon when it makes sense as a possible end, otherwise use the + // introducer token for the error. + auto HandleDeclarationError(StateStackEntry state, + ParseNodeKind parse_node_kind, + bool skip_past_likely_end) -> void; + + // Handles an unrecognized declaration, adding an error node. + auto HandleUnrecognizedDeclaration() -> void; + // Propagates an error up the state stack, to the parent state. auto ReturnErrorOnState() -> void { state_stack_.back().has_error = true; } @@ -292,12 +303,6 @@ class Parser { // Handles DesignatorAs. auto HandleDesignator(bool as_struct) -> void; - // When handling errors before the start of the definition, treat it as a - // declaration. Recover to a semicolon when it makes sense as a possible - // function end, otherwise use the fn token for the error. - auto HandleFunctionError(StateStackEntry state, bool skip_past_likely_end) - -> void; - // Handles ParenConditionAs(If|While) auto HandleParenCondition(ParseNodeKind start_kind, ParserState finish_state) -> void; diff --git a/toolchain/parser/parser_state.def b/toolchain/parser/parser_state.def index fd692d901dbf..bf83e378b22f 100644 --- a/toolchain/parser/parser_state.def +++ b/toolchain/parser/parser_state.def @@ -300,15 +300,9 @@ CARBON_PARSER_STATE(FunctionSignatureFinish) // (state done) CARBON_PARSER_STATE(FunctionDefinitionFinish) -// Finishes an interface definition. -// -// Always: -// (state done) -CARBON_PARSER_STATE(InterfaceDefinitionFinish) - // Handles parsing the body of an interface. // -// If `}`: +// If `CloseCurlyBrace`: // (state done) // Else: // 1. InterfaceDefinitionLoop @@ -316,13 +310,12 @@ CARBON_PARSER_STATE(InterfaceDefinitionLoop) // Handles processing of a intefaces's `interface {`. // -// If invalid: -// 1. InterfaceDefinitionFinish -// If `{` is missing: -// 1. InterfaceDefinitionFinish -// Else: +// If `Semi`: +// (state done) +// If `OpenCurlyBrace`: // 1. InterfaceDefinitionLoop -// 2. InterfaceDefinitionFinish +// Else: +// (state done) CARBON_PARSER_STATE(InterfaceIntroducer) // Handles `package`. diff --git a/toolchain/parser/testdata/generics/interface/basic.carbon b/toolchain/parser/testdata/generics/interface/basic.carbon index cc8e9ad285f0..6ebf323e705a 100644 --- a/toolchain/parser/testdata/generics/interface/basic.carbon +++ b/toolchain/parser/testdata/generics/interface/basic.carbon @@ -5,84 +5,84 @@ // AUTOUPDATE // RUN: %{carbon-run-parser} // CHECK:STDOUT: [ -// CHECK:STDOUT: {kind: 'DeclaredName', text: 'foo'}, -// CHECK:STDOUT: {kind: 'InterfaceBodyStart', text: '{'}, -// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'}, -// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Add'}, -// CHECK:STDOUT: {kind: 'DeducedParameterListStart', text: '['}, -// CHECK:STDOUT: {kind: 'SelfDeducedParameter', text: 'self'}, -// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'}, -// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3}, -// CHECK:STDOUT: {kind: 'DeducedParameterList', text: ']', subtree_size: 5}, -// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('}, -// CHECK:STDOUT: {kind: 'DeclaredName', text: 'b'}, -// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'}, -// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3}, -// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 5}, +// CHECK:STDOUT: {kind: 'InterfaceIntroducer', text: 'interface'}, +// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Foo'}, +// CHECK:STDOUT: {kind: 'InterfaceDefinitionStart', text: '{', subtree_size: 3}, +// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Add'}, +// CHECK:STDOUT: {kind: 'DeducedParameterListStart', text: '['}, +// CHECK:STDOUT: {kind: 'SelfDeducedParameter', text: 'self'}, // CHECK:STDOUT: {kind: 'SelfType', text: 'Self'}, -// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2}, -// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', subtree_size: 15}, -// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'}, -// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Add'}, -// CHECK:STDOUT: {kind: 'DeducedParameterListStart', text: '['}, -// CHECK:STDOUT: {kind: 'SelfDeducedParameter', text: 'self'}, -// CHECK:STDOUT: {kind: 'NameReference', text: 'foo'}, -// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3}, -// CHECK:STDOUT: {kind: 'DeducedParameterList', text: ']', subtree_size: 5}, -// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('}, -// CHECK:STDOUT: {kind: 'DeclaredName', text: 'b'}, -// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'}, -// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3}, -// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 5}, +// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3}, +// CHECK:STDOUT: {kind: 'DeducedParameterList', text: ']', subtree_size: 5}, +// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('}, +// CHECK:STDOUT: {kind: 'DeclaredName', text: 'b'}, // CHECK:STDOUT: {kind: 'SelfType', text: 'Self'}, -// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2}, -// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', subtree_size: 15}, -// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'}, -// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Sub'}, -// CHECK:STDOUT: {kind: 'DeducedParameterListStart', text: '['}, -// CHECK:STDOUT: {kind: 'SelfDeducedParameter', text: ':'}, -// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'}, -// CHECK:STDOUT: {kind: 'PostfixOperator', text: '*', subtree_size: 2}, -// CHECK:STDOUT: {kind: 'PatternBinding', text: 'self', subtree_size: 4}, -// CHECK:STDOUT: {kind: 'Address', text: 'addr', subtree_size: 5}, -// CHECK:STDOUT: {kind: 'DeducedParameterList', text: ']', subtree_size: 7}, -// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('}, -// CHECK:STDOUT: {kind: 'DeclaredName', text: 'b'}, -// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'}, -// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3}, -// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 5}, +// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3}, +// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 5}, +// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'}, +// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2}, +// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', subtree_size: 15}, +// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Add'}, +// CHECK:STDOUT: {kind: 'DeducedParameterListStart', text: '['}, +// CHECK:STDOUT: {kind: 'SelfDeducedParameter', text: 'self'}, +// CHECK:STDOUT: {kind: 'NameReference', text: 'foo'}, +// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3}, +// CHECK:STDOUT: {kind: 'DeducedParameterList', text: ']', subtree_size: 5}, +// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('}, +// CHECK:STDOUT: {kind: 'DeclaredName', text: 'b'}, // CHECK:STDOUT: {kind: 'SelfType', text: 'Self'}, -// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2}, -// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', subtree_size: 17}, -// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'}, -// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Sub'}, -// CHECK:STDOUT: {kind: 'DeducedParameterListStart', text: '['}, -// CHECK:STDOUT: {kind: 'SelfDeducedParameter', text: ':'}, -// CHECK:STDOUT: {kind: 'NameReference', text: 'foo'}, -// CHECK:STDOUT: {kind: 'PostfixOperator', text: '*', subtree_size: 2}, -// CHECK:STDOUT: {kind: 'PatternBinding', text: 'self', subtree_size: 4}, -// CHECK:STDOUT: {kind: 'Address', text: 'addr', subtree_size: 5}, -// CHECK:STDOUT: {kind: 'DeducedParameterList', text: ']', subtree_size: 7}, -// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('}, -// CHECK:STDOUT: {kind: 'DeclaredName', text: 'b'}, -// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'}, -// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3}, -// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 5}, +// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3}, +// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 5}, +// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'}, +// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2}, +// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', subtree_size: 15}, +// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Sub'}, +// CHECK:STDOUT: {kind: 'DeducedParameterListStart', text: '['}, +// CHECK:STDOUT: {kind: 'SelfDeducedParameter', text: ':'}, +// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'}, +// CHECK:STDOUT: {kind: 'PostfixOperator', text: '*', subtree_size: 2}, +// CHECK:STDOUT: {kind: 'PatternBinding', text: 'self', subtree_size: 4}, +// CHECK:STDOUT: {kind: 'Address', text: 'addr', subtree_size: 5}, +// CHECK:STDOUT: {kind: 'DeducedParameterList', text: ']', subtree_size: 7}, +// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('}, +// CHECK:STDOUT: {kind: 'DeclaredName', text: 'b'}, // CHECK:STDOUT: {kind: 'SelfType', text: 'Self'}, -// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2}, -// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', subtree_size: 17}, -// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'}, -// CHECK:STDOUT: {kind: 'DeclaredName', text: 'FooFactory'}, -// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('}, -// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 2}, +// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3}, +// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 5}, +// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'}, +// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2}, +// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', subtree_size: 17}, +// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Sub'}, +// CHECK:STDOUT: {kind: 'DeducedParameterListStart', text: '['}, +// CHECK:STDOUT: {kind: 'SelfDeducedParameter', text: ':'}, +// CHECK:STDOUT: {kind: 'NameReference', text: 'foo'}, +// CHECK:STDOUT: {kind: 'PostfixOperator', text: '*', subtree_size: 2}, +// CHECK:STDOUT: {kind: 'PatternBinding', text: 'self', subtree_size: 4}, +// CHECK:STDOUT: {kind: 'Address', text: 'addr', subtree_size: 5}, +// CHECK:STDOUT: {kind: 'DeducedParameterList', text: ']', subtree_size: 7}, +// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('}, +// CHECK:STDOUT: {kind: 'DeclaredName', text: 'b'}, // CHECK:STDOUT: {kind: 'SelfType', text: 'Self'}, -// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2}, -// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', subtree_size: 7}, -// CHECK:STDOUT: {kind: 'InterfaceBody', text: '}', subtree_size: 73}, -// CHECK:STDOUT: {kind: 'InterfaceDefinition', text: 'interface', subtree_size: 75}, +// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3}, +// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 5}, +// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'}, +// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2}, +// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', subtree_size: 17}, +// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {kind: 'DeclaredName', text: 'FooFactory'}, +// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('}, +// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 2}, +// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'}, +// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2}, +// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', subtree_size: 7}, +// CHECK:STDOUT: {kind: 'InterfaceDefinition', text: '}', subtree_size: 75}, // CHECK:STDOUT: {kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] -interface foo { +interface Foo { fn Add[self: Self](b: Self) -> Self; fn Add[self: foo](b: Self) -> Self; diff --git a/toolchain/parser/testdata/generics/interface/declaration.carbon b/toolchain/parser/testdata/generics/interface/declaration.carbon new file mode 100644 index 000000000000..5e7ba8165d34 --- /dev/null +++ b/toolchain/parser/testdata/generics/interface/declaration.carbon @@ -0,0 +1,13 @@ +// 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 +// +// AUTOUPDATE +// RUN: %{carbon-run-parser} +// CHECK:STDOUT: [ +// CHECK:STDOUT: {kind: 'InterfaceIntroducer', text: 'interface'}, +// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Foo'}, +// CHECK:STDOUT: {kind: 'InterfaceDeclaration', text: ';', subtree_size: 3}, +// CHECK:STDOUT: {kind: 'FileEnd', text: ''}, +// CHECK:STDOUT: ] +interface Foo; diff --git a/toolchain/parser/testdata/generics/interface/empty.carbon b/toolchain/parser/testdata/generics/interface/empty.carbon index 27beb7ca0d17..4a5871af403e 100644 --- a/toolchain/parser/testdata/generics/interface/empty.carbon +++ b/toolchain/parser/testdata/generics/interface/empty.carbon @@ -5,11 +5,11 @@ // AUTOUPDATE // RUN: %{carbon-run-parser} // CHECK:STDOUT: [ -// CHECK:STDOUT: {kind: 'DeclaredName', text: 'foo'}, -// CHECK:STDOUT: {kind: 'InterfaceBodyStart', text: '{'}, -// CHECK:STDOUT: {kind: 'InterfaceBody', text: '}', subtree_size: 2}, -// CHECK:STDOUT: {kind: 'InterfaceDefinition', text: 'interface', subtree_size: 4}, +// CHECK:STDOUT: {kind: 'InterfaceIntroducer', text: 'interface'}, +// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Foo'}, +// CHECK:STDOUT: {kind: 'InterfaceDefinitionStart', text: '{', subtree_size: 3}, +// CHECK:STDOUT: {kind: 'InterfaceDefinition', text: '}', subtree_size: 4}, // CHECK:STDOUT: {kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] -interface foo { +interface Foo { } diff --git a/toolchain/parser/testdata/generics/interface/fail_missing_name.carbon b/toolchain/parser/testdata/generics/interface/fail_missing_name.carbon index 47bbd050086f..70f181872064 100644 --- a/toolchain/parser/testdata/generics/interface/fail_missing_name.carbon +++ b/toolchain/parser/testdata/generics/interface/fail_missing_name.carbon @@ -5,10 +5,8 @@ // AUTOUPDATE // RUN: %{not} %{carbon-run-parser} // CHECK:STDOUT: [ -// CHECK:STDOUT: {kind: 'DeclaredName', text: 'interface', has_error: yes}, -// CHECK:STDOUT: {kind: 'InterfaceBodyStart', text: '{'}, -// CHECK:STDOUT: {kind: 'InterfaceBody', text: '}', subtree_size: 2}, -// CHECK:STDOUT: {kind: 'InterfaceDefinition', text: 'interface', has_error: yes, subtree_size: 4}, +// CHECK:STDOUT: {kind: 'InterfaceIntroducer', text: 'interface'}, +// CHECK:STDOUT: {kind: 'InterfaceDeclaration', text: 'interface', has_error: yes, subtree_size: 2}, // CHECK:STDOUT: {kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] diff --git a/toolchain/parser/testdata/generics/interface/fail_missing_open_curly.carbon b/toolchain/parser/testdata/generics/interface/fail_missing_open_curly.carbon index 0b807500e518..90e287659cda 100644 --- a/toolchain/parser/testdata/generics/interface/fail_missing_open_curly.carbon +++ b/toolchain/parser/testdata/generics/interface/fail_missing_open_curly.carbon @@ -5,15 +5,17 @@ // AUTOUPDATE // RUN: %{not} %{carbon-run-parser} // CHECK:STDOUT: [ -// CHECK:STDOUT: {kind: 'DeclaredName', text: 'bar'}, -// CHECK:STDOUT: {kind: 'InterfaceDefinition', text: 'interface', has_error: yes, subtree_size: 2}, -// CHECK:STDOUT: {kind: 'DeclaredName', text: 'foo'}, -// CHECK:STDOUT: {kind: 'InterfaceDefinition', text: 'interface', has_error: yes, subtree_size: 2}, +// CHECK:STDOUT: {kind: 'InterfaceIntroducer', text: 'interface'}, +// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Bar'}, +// CHECK:STDOUT: {kind: 'InterfaceDeclaration', text: 'interface', has_error: yes, subtree_size: 3}, +// CHECK:STDOUT: {kind: 'InterfaceIntroducer', text: 'interface'}, +// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Foo'}, +// CHECK:STDOUT: {kind: 'InterfaceDeclaration', text: 'interface', has_error: yes, subtree_size: 3}, // CHECK:STDOUT: {kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] // CHECK:STDERR: {{.*}}/toolchain/parser/testdata/generics/interface/fail_missing_open_curly.carbon:[[@LINE+1]]:15: Expected `{` to start interface definition. -interface bar baz {} +interface Bar Baz {} // CHECK:STDERR: {{.*}}/toolchain/parser/testdata/generics/interface/fail_missing_open_curly.carbon:[[@LINE+1]]:14: Expected `{` to start interface definition. -interface foo +interface Foo diff --git a/toolchain/parser/testdata/generics/interface/fail_no_impl_allowed.carbon b/toolchain/parser/testdata/generics/interface/fail_no_impl_allowed.carbon index 858c9066e363..5ead4add9238 100644 --- a/toolchain/parser/testdata/generics/interface/fail_no_impl_allowed.carbon +++ b/toolchain/parser/testdata/generics/interface/fail_no_impl_allowed.carbon @@ -5,28 +5,28 @@ // AUTOUPDATE // RUN: %{not} %{carbon-run-parser} // CHECK:STDOUT: [ -// CHECK:STDOUT: {kind: 'DeclaredName', text: 'foo'}, -// CHECK:STDOUT: {kind: 'InterfaceBodyStart', text: '{'}, -// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'}, -// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Add'}, -// CHECK:STDOUT: {kind: 'DeducedParameterListStart', text: '['}, -// CHECK:STDOUT: {kind: 'SelfDeducedParameter', text: 'self'}, -// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'}, -// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3}, -// CHECK:STDOUT: {kind: 'DeducedParameterList', text: ']', subtree_size: 5}, -// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('}, -// CHECK:STDOUT: {kind: 'DeclaredName', text: 'b'}, -// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'}, -// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3}, -// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 5}, +// CHECK:STDOUT: {kind: 'InterfaceIntroducer', text: 'interface'}, +// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Foo'}, +// CHECK:STDOUT: {kind: 'InterfaceDefinitionStart', text: '{', subtree_size: 3}, +// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Add'}, +// CHECK:STDOUT: {kind: 'DeducedParameterListStart', text: '['}, +// CHECK:STDOUT: {kind: 'SelfDeducedParameter', text: 'self'}, // CHECK:STDOUT: {kind: 'SelfType', text: 'Self'}, -// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2}, -// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: 'fn', has_error: yes, subtree_size: 15}, -// CHECK:STDOUT: {kind: 'InterfaceBody', text: '}', subtree_size: 17}, -// CHECK:STDOUT: {kind: 'InterfaceDefinition', text: 'interface', subtree_size: 19}, +// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3}, +// CHECK:STDOUT: {kind: 'DeducedParameterList', text: ']', subtree_size: 5}, +// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('}, +// CHECK:STDOUT: {kind: 'DeclaredName', text: 'b'}, +// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'}, +// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3}, +// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 5}, +// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'}, +// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2}, +// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: 'fn', has_error: yes, subtree_size: 15}, +// CHECK:STDOUT: {kind: 'InterfaceDefinition', text: '}', subtree_size: 19}, // CHECK:STDOUT: {kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] -interface foo { +interface Foo { // CHECK:STDERR: {{.*}}/toolchain/parser/testdata/generics/interface/fail_no_impl_allowed.carbon:[[@LINE+1]]:39: Method implementations are not allowed in interfaces. fn Add[self: Self](b: Self) -> Self { print("You can't do that."); diff --git a/toolchain/parser/testdata/generics/interface/fail_self_param_syntax.carbon b/toolchain/parser/testdata/generics/interface/fail_self_param_syntax.carbon index c202d3057ed2..c18cd69948b8 100644 --- a/toolchain/parser/testdata/generics/interface/fail_self_param_syntax.carbon +++ b/toolchain/parser/testdata/generics/interface/fail_self_param_syntax.carbon @@ -5,59 +5,59 @@ // AUTOUPDATE // RUN: %{not} %{carbon-run-parser} // CHECK:STDOUT: [ -// CHECK:STDOUT: {kind: 'DeclaredName', text: 'foo'}, -// CHECK:STDOUT: {kind: 'InterfaceBodyStart', text: '{'}, -// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'}, -// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Add'}, -// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('}, -// CHECK:STDOUT: {kind: 'DeclaredName', text: 'b'}, -// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'}, -// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3}, -// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 5}, +// CHECK:STDOUT: {kind: 'InterfaceIntroducer', text: 'interface'}, +// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Foo'}, +// CHECK:STDOUT: {kind: 'InterfaceDefinitionStart', text: '{', subtree_size: 3}, +// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Add'}, +// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('}, +// CHECK:STDOUT: {kind: 'DeclaredName', text: 'b'}, // CHECK:STDOUT: {kind: 'SelfType', text: 'Self'}, -// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2}, -// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', subtree_size: 10}, -// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'}, -// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Sub'}, -// CHECK:STDOUT: {kind: 'DeducedParameterListStart', text: '['}, -// CHECK:STDOUT: {kind: 'DeducedParameterList', text: ']', has_error: yes, subtree_size: 2}, -// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('}, -// CHECK:STDOUT: {kind: 'DeclaredName', text: 'b'}, -// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'}, -// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3}, -// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 5}, +// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3}, +// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 5}, +// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'}, +// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2}, +// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', subtree_size: 10}, +// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Sub'}, +// CHECK:STDOUT: {kind: 'DeducedParameterListStart', text: '['}, +// CHECK:STDOUT: {kind: 'DeducedParameterList', text: ']', has_error: yes, subtree_size: 2}, +// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('}, +// CHECK:STDOUT: {kind: 'DeclaredName', text: 'b'}, // CHECK:STDOUT: {kind: 'SelfType', text: 'Self'}, -// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2}, -// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', subtree_size: 12}, -// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'}, -// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Mul'}, -// CHECK:STDOUT: {kind: 'DeducedParameterListStart', text: '['}, -// CHECK:STDOUT: {kind: 'DeducedParameterList', text: ']', has_error: yes, subtree_size: 2}, -// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('}, -// CHECK:STDOUT: {kind: 'DeclaredName', text: 'b'}, -// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'}, -// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3}, -// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 5}, +// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3}, +// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 5}, +// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'}, +// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2}, +// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', subtree_size: 12}, +// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Mul'}, +// CHECK:STDOUT: {kind: 'DeducedParameterListStart', text: '['}, +// CHECK:STDOUT: {kind: 'DeducedParameterList', text: ']', has_error: yes, subtree_size: 2}, +// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('}, +// CHECK:STDOUT: {kind: 'DeclaredName', text: 'b'}, // CHECK:STDOUT: {kind: 'SelfType', text: 'Self'}, -// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2}, -// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', subtree_size: 12}, -// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'}, -// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Rem'}, -// CHECK:STDOUT: {kind: 'DeducedParameterListStart', text: '['}, -// CHECK:STDOUT: {kind: 'DeducedParameterList', text: ']', subtree_size: 2}, -// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('}, -// CHECK:STDOUT: {kind: 'DeclaredName', text: 'b'}, -// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'}, -// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3}, -// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 5}, +// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3}, +// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 5}, +// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'}, +// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2}, +// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', subtree_size: 12}, +// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Rem'}, +// CHECK:STDOUT: {kind: 'DeducedParameterListStart', text: '['}, +// CHECK:STDOUT: {kind: 'DeducedParameterList', text: ']', subtree_size: 2}, +// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('}, +// CHECK:STDOUT: {kind: 'DeclaredName', text: 'b'}, // CHECK:STDOUT: {kind: 'SelfType', text: 'Self'}, -// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2}, -// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', subtree_size: 12}, -// CHECK:STDOUT: {kind: 'InterfaceBody', text: '}', subtree_size: 48}, -// CHECK:STDOUT: {kind: 'InterfaceDefinition', text: 'interface', subtree_size: 50}, +// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3}, +// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 5}, +// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'}, +// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2}, +// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', subtree_size: 12}, +// CHECK:STDOUT: {kind: 'InterfaceDefinition', text: '}', subtree_size: 50}, // CHECK:STDOUT: {kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] -interface foo { +interface Foo { fn Add(b: Self) -> Self; // CHECK:STDERR: {{.*}}/toolchain/parser/testdata/generics/interface/fail_self_param_syntax.carbon:[[@LINE+1]]:10: Deduced parameters must be of the form: `: ` or `addr : `. diff --git a/toolchain/semantics/semantics_parse_tree_handler.cpp b/toolchain/semantics/semantics_parse_tree_handler.cpp index 53b958a5aba4..96ef44e91f45 100644 --- a/toolchain/semantics/semantics_parse_tree_handler.cpp +++ b/toolchain/semantics/semantics_parse_tree_handler.cpp @@ -576,15 +576,9 @@ auto SemanticsParseTreeHandler::HandleInfixOperator(ParseTree::Node parse_node) return true; } -auto SemanticsParseTreeHandler::HandleInterfaceBody(ParseTree::Node parse_node) - -> bool { - emitter_->Emit(parse_node, SemanticsTodo, "HandleInterfaceBody"); - return false; -} - -auto SemanticsParseTreeHandler::HandleInterfaceBodyStart( +auto SemanticsParseTreeHandler::HandleInterfaceDeclaration( ParseTree::Node parse_node) -> bool { - emitter_->Emit(parse_node, SemanticsTodo, "HandleInterfaceBodyStart"); + emitter_->Emit(parse_node, SemanticsTodo, "HandleInterfaceDeclaration"); return false; } @@ -594,6 +588,18 @@ auto SemanticsParseTreeHandler::HandleInterfaceDefinition( return false; } +auto SemanticsParseTreeHandler::HandleInterfaceDefinitionStart( + ParseTree::Node parse_node) -> bool { + emitter_->Emit(parse_node, SemanticsTodo, "HandleInterfaceDefinitionStart"); + return false; +} + +auto SemanticsParseTreeHandler::HandleInterfaceIntroducer( + ParseTree::Node parse_node) -> bool { + emitter_->Emit(parse_node, SemanticsTodo, "HandleInterfaceIntroducer"); + return false; +} + auto SemanticsParseTreeHandler::HandleLiteral(ParseTree::Node parse_node) -> bool { auto token = parse_tree_->node_token(parse_node);