mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-25 16:50:16 +01:00
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).
97 lines
3.5 KiB
C++
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
|