Files
carbon-lang/toolchain/parser/parser_handle_function.cpp
T
Jon Ross-Perkins 8ad08e34e2 Refactor diagnostics out of parser_context.h (#2834)
This is addressing an issue left behind by the context switch, removing a few diagnostics that had been in the header rather than figuring out proper homes. I'm splitting one for semis a little further, sharing one, and then the other two are actually able to be moved into more specific homes as-is (one is only used in one place, clearly an oversight that it wasn't there already).
2023-05-18 12:45:08 -07:00

97 lines
3.5 KiB
C++

// 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
#include "toolchain/parser/parser_context.h"
namespace Carbon {
auto ParserHandleFunctionIntroducer(ParserContext& context) -> void {
auto state = context.PopState();
context.AddLeafNode(ParseNodeKind::FunctionIntroducer, context.Consume());
state.state = ParserState::FunctionAfterParameters;
context.PushState(state);
state.state = ParserState::DeclarationNameAndParamsAsRequired;
context.PushState(state);
}
auto ParserHandleFunctionAfterParameters(ParserContext& context) -> void {
auto state = context.PopState();
// Regardless of whether there's a return type, we'll finish the signature.
state.state = ParserState::FunctionSignatureFinish;
context.PushState(state);
// If there is a return type, parse the expression before adding the return
// type nod.e
if (context.PositionIs(TokenKind::MinusGreater)) {
context.PushState(ParserState::FunctionReturnTypeFinish);
++context.position();
context.PushStateForExpression(PrecedenceGroup::ForType());
}
}
auto ParserHandleFunctionReturnTypeFinish(ParserContext& context) -> void {
auto state = context.PopState();
context.AddNode(ParseNodeKind::ReturnType, state.token, state.subtree_start,
state.has_error);
}
auto ParserHandleFunctionSignatureFinish(ParserContext& context) -> void {
auto state = context.PopState();
switch (context.PositionKind()) {
case TokenKind::Semi: {
context.AddNode(ParseNodeKind::FunctionDeclaration, context.Consume(),
state.subtree_start, state.has_error);
break;
}
case TokenKind::OpenCurlyBrace: {
if (auto decl_context = context.GetDeclarationContext();
decl_context == ParserContext::DeclarationContext::Interface ||
decl_context == ParserContext::DeclarationContext::NamedConstraint) {
CARBON_DIAGNOSTIC(
MethodImplNotAllowed, Error,
"Method implementations are not allowed in interfaces.");
context.emitter().Emit(*context.position(), MethodImplNotAllowed);
context.RecoverFromDeclarationError(state,
ParseNodeKind::FunctionDeclaration,
/*skip_past_likely_end=*/true);
break;
}
context.AddNode(ParseNodeKind::FunctionDefinitionStart, context.Consume(),
state.subtree_start, state.has_error);
// Any error is recorded on the FunctionDefinitionStart.
state.has_error = false;
state.state = ParserState::FunctionDefinitionFinish;
context.PushState(state);
context.PushState(ParserState::StatementScopeLoop);
break;
}
default: {
if (!state.has_error) {
context.EmitExpectedDeclarationSemiOrDefinition(TokenKind::Fn);
}
// Only need to skip if we've not already found a new line.
bool skip_past_likely_end =
context.tokens().GetLine(*context.position()) ==
context.tokens().GetLine(state.token);
context.RecoverFromDeclarationError(
state, ParseNodeKind::FunctionDeclaration, skip_past_likely_end);
break;
}
}
}
auto ParserHandleFunctionDefinitionFinish(ParserContext& context) -> void {
auto state = context.PopState();
context.AddNode(ParseNodeKind::FunctionDefinition, context.Consume(),
state.subtree_start, state.has_error);
}
} // namespace Carbon