// 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/parse/context.h" #include "toolchain/parse/handle.h" namespace Carbon::Parse { auto HandleLambdaIntroducer(Context& context) -> void { auto state = context.PopState(); context.AddLeafNode(NodeKind::LambdaIntroducer, context.Consume()); context.PushState(state, StateKind::LambdaAfterIntroducer); } auto HandleLambdaAfterIntroducer(Context& context) -> void { auto state = context.PopState(); if (context.PositionIs(Lex::TokenKind::OpenSquareBracket)) { context.PushState(state, StateKind::LambdaAfterImplicitParams); context.PushState(StateKind::PatternListAsImplicit); } else if (context.PositionIs(Lex::TokenKind::OpenParen)) { context.PushState(state, StateKind::LambdaAfterParams); context.PushState(StateKind::PatternListAsExplicit); } else { // No implicit or explicit params. context.PushState(state, StateKind::LambdaAfterParams); } } auto HandleLambdaAfterImplicitParams(Context& context) -> void { auto state = context.PopState(); if (context.PositionIs(Lex::TokenKind::OpenParen)) { context.PushState(state, StateKind::LambdaAfterParams); context.PushState(StateKind::PatternListAsExplicit); } else { // No explicit params after implicit params. context.PushState(state, StateKind::LambdaAfterParams); } } auto HandleLambdaAfterParams(Context& context) -> void { auto state = context.PopState(); if (context.PositionIs(Lex::TokenKind::MinusGreater)) { // Has return type. context.PushState(state, StateKind::LambdaBody); context.PushState(StateKind::FunctionReturnTypeFinish); context.ConsumeAndDiscard(); context.PushStateForExpr(PrecedenceGroup::ForType()); } else if (context.PositionIs(Lex::TokenKind::EqualGreater)) { // Terse body `=> expr` context.AddLeafNode(NodeKind::TerseBodyArrow, context.Consume()); context.PushState(state, StateKind::LambdaBodyFinish); context.PushStateForExpr(PrecedenceGroup::ForTopLevelExpr()); } else if (context.PositionIs(Lex::TokenKind::OpenCurlyBrace)) { // Block body `{ ... }` context.PushState(state, StateKind::LambdaBodyFinish); context.PushState(StateKind::CodeBlock); } else { CARBON_DIAGNOSTIC(ExpectedLambdaBody, Error, "expected `->`, `=>`, or `{{`"); context.emitter().Emit(*context.position(), ExpectedLambdaBody); state.has_error = true; context.ReturnErrorOnState(); } } auto HandleLambdaBody(Context& context) -> void { auto state = context.PopState(); // We arrive here after parsing return type. // So we look for `=>` or `{`. if (context.PositionIs(Lex::TokenKind::EqualGreater)) { // Terse body `=> expr` context.AddLeafNode(NodeKind::TerseBodyArrow, context.Consume()); context.PushState(state, StateKind::LambdaBodyFinish); context.PushStateForExpr(PrecedenceGroup::ForTopLevelExpr()); } else if (context.PositionIs(Lex::TokenKind::OpenCurlyBrace)) { // Block body `{ ... }` context.PushState(state, StateKind::LambdaBodyFinish); context.PushState(StateKind::CodeBlock); } else { CARBON_DIAGNOSTIC(ExpectedLambdaBodyAfterReturnType, Error, "expected `=>` or `{{` after return type"); context.emitter().Emit(*context.position(), ExpectedLambdaBodyAfterReturnType); state.has_error = true; context.ReturnErrorOnState(); } } auto HandleLambdaBodyFinish(Context& context) -> void { auto state = context.PopState(); context.AddNode(NodeKind::Lambda, state.token, state.has_error); } } // namespace Carbon::Parse