mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 22:02:55 +01:00
@@ -0,0 +1,95 @@
|
||||
// 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/check/context.h"
|
||||
#include "toolchain/check/convert.h"
|
||||
|
||||
namespace Carbon::Check {
|
||||
|
||||
auto HandleMatchConditionStart(Context& context,
|
||||
Parse::MatchConditionStartId parse_node)
|
||||
-> bool {
|
||||
return context.TODO(parse_node, "HandleMatchConditionStart");
|
||||
}
|
||||
|
||||
auto HandleMatchCondition(Context& context, Parse::MatchConditionId parse_node)
|
||||
-> bool {
|
||||
return context.TODO(parse_node, "HandleMatchCondition");
|
||||
}
|
||||
|
||||
auto HandleMatchIntroducer(Context& context,
|
||||
Parse::MatchIntroducerId parse_node) -> bool {
|
||||
return context.TODO(parse_node, "HandleMatchIntroducer");
|
||||
}
|
||||
|
||||
auto HandleMatchStatementStart(Context& context,
|
||||
Parse::MatchStatementStartId parse_node)
|
||||
-> bool {
|
||||
return context.TODO(parse_node, "HandleMatchStatementStart");
|
||||
}
|
||||
|
||||
auto HandleMatchCaseIntroducer(Context& context,
|
||||
Parse::MatchCaseIntroducerId parse_node)
|
||||
-> bool {
|
||||
return context.TODO(parse_node, "HandleMatchCaseIntroducer");
|
||||
}
|
||||
|
||||
auto HandleMatchCaseGuardIntroducer(
|
||||
Context& context, Parse::MatchCaseGuardIntroducerId parse_node) -> bool {
|
||||
return context.TODO(parse_node, "HandleMatchCaseGuardIntroducer");
|
||||
}
|
||||
|
||||
auto HandleMatchCaseGuardStart(Context& context,
|
||||
Parse::MatchCaseGuardStartId parse_node)
|
||||
-> bool {
|
||||
return context.TODO(parse_node, "HandleMatchCaseGuardStart");
|
||||
}
|
||||
|
||||
auto HandleMatchCaseGuard(Context& context, Parse::MatchCaseGuardId parse_node)
|
||||
-> bool {
|
||||
return context.TODO(parse_node, "HandleMatchCaseGuard");
|
||||
}
|
||||
|
||||
auto HandleMatchCaseEqualGreater(Context& context,
|
||||
Parse::MatchCaseEqualGreaterId parse_node)
|
||||
-> bool {
|
||||
return context.TODO(parse_node, "HandleMatchCaseEqualGreater");
|
||||
}
|
||||
|
||||
auto HandleMatchCaseStart(Context& context, Parse::MatchCaseStartId parse_node)
|
||||
-> bool {
|
||||
return context.TODO(parse_node, "HandleMatchCaseStart");
|
||||
}
|
||||
|
||||
auto HandleMatchCase(Context& context, Parse::MatchCaseId parse_node) -> bool {
|
||||
return context.TODO(parse_node, "HandleMatchCase");
|
||||
}
|
||||
|
||||
auto HandleMatchDefaultIntroducer(Context& context,
|
||||
Parse::MatchDefaultIntroducerId parse_node)
|
||||
-> bool {
|
||||
return context.TODO(parse_node, "MatchDefaultIntroducer");
|
||||
}
|
||||
|
||||
auto HandleMatchDefaultEqualGreater(
|
||||
Context& context, Parse::MatchDefaultEqualGreaterId parse_node) -> bool {
|
||||
return context.TODO(parse_node, "MatchDefaultEqualGreater");
|
||||
}
|
||||
|
||||
auto HandleMatchDefaultStart(Context& context,
|
||||
Parse::MatchDefaultStartId parse_node) -> bool {
|
||||
return context.TODO(parse_node, "HandleMatchDefaultStart");
|
||||
}
|
||||
|
||||
auto HandleMatchDefault(Context& context, Parse::MatchDefaultId parse_node)
|
||||
-> bool {
|
||||
return context.TODO(parse_node, "HandleMatchDefault");
|
||||
}
|
||||
|
||||
auto HandleMatchStatement(Context& context, Parse::MatchStatementId parse_node)
|
||||
-> bool {
|
||||
return context.TODO(parse_node, "HandleMatchStatement");
|
||||
}
|
||||
|
||||
} // namespace Carbon::Check
|
||||
@@ -73,6 +73,12 @@ CARBON_DIAGNOSTIC_KIND(ExpectedVarAfterReturned)
|
||||
CARBON_DIAGNOSTIC_KIND(ExpectedVariableDecl)
|
||||
CARBON_DIAGNOSTIC_KIND(ExpectedChoiceDefinition)
|
||||
CARBON_DIAGNOSTIC_KIND(ExpectedChoiceAlternativeName)
|
||||
CARBON_DIAGNOSTIC_KIND(ExpectedMatchCases)
|
||||
CARBON_DIAGNOSTIC_KIND(ExpectedMatchCasesBlock)
|
||||
CARBON_DIAGNOSTIC_KIND(ExpectedMatchCaseArrow)
|
||||
CARBON_DIAGNOSTIC_KIND(ExpectedMatchCaseBlock)
|
||||
CARBON_DIAGNOSTIC_KIND(UnexpectedTokenInMatchCasesBlock)
|
||||
CARBON_DIAGNOSTIC_KIND(UnreachableMatchCase)
|
||||
CARBON_DIAGNOSTIC_KIND(OperatorRequiresParentheses)
|
||||
CARBON_DIAGNOSTIC_KIND(StatementOperatorAsSubExpr)
|
||||
CARBON_DIAGNOSTIC_KIND(UnaryOperatorRequiresParentheses)
|
||||
|
||||
@@ -0,0 +1,232 @@
|
||||
// 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"
|
||||
|
||||
namespace Carbon::Parse {
|
||||
|
||||
static auto HandleStatementsBlockStart(Context& context, State finish,
|
||||
NodeKind equal_greater, NodeKind starter,
|
||||
NodeKind complete) -> void {
|
||||
auto state = context.PopState();
|
||||
|
||||
if (!context.PositionIs(Lex::TokenKind::EqualGreater)) {
|
||||
if (!state.has_error) {
|
||||
CARBON_DIAGNOSTIC(ExpectedMatchCaseArrow, Error,
|
||||
"Expected `=>` introducing statement block.");
|
||||
context.emitter().Emit(*context.position(), ExpectedMatchCaseArrow);
|
||||
}
|
||||
|
||||
context.AddLeafNode(equal_greater, *context.position(), true);
|
||||
context.AddNode(starter, *context.position(), state.subtree_start, true);
|
||||
context.AddNode(complete, *context.position(), state.subtree_start, true);
|
||||
context.SkipPastLikelyEnd(*context.position());
|
||||
return;
|
||||
}
|
||||
|
||||
context.AddLeafNode(equal_greater, context.Consume());
|
||||
|
||||
if (!context.PositionIs(Lex::TokenKind::OpenCurlyBrace)) {
|
||||
if (!state.has_error) {
|
||||
CARBON_DIAGNOSTIC(ExpectedMatchCaseBlock, Error,
|
||||
"Expected `{{` after `=>`.");
|
||||
context.emitter().Emit(*context.position(), ExpectedMatchCaseBlock);
|
||||
}
|
||||
|
||||
context.AddNode(starter, *context.position(), state.subtree_start, true);
|
||||
context.AddNode(complete, *context.position(), state.subtree_start, true);
|
||||
context.SkipPastLikelyEnd(*context.position());
|
||||
return;
|
||||
}
|
||||
|
||||
context.AddNode(starter, context.Consume(), state.subtree_start,
|
||||
state.has_error);
|
||||
context.PushState(state, finish);
|
||||
context.PushState(State::StatementScopeLoop);
|
||||
}
|
||||
|
||||
static auto EmitUnexpectedTokenAndRecover(Context& context) -> void {
|
||||
CARBON_DIAGNOSTIC(UnexpectedTokenInMatchCasesBlock, Error,
|
||||
"Unexpected `{0}`; expected `case`, `default` or `}`.",
|
||||
Lex::TokenKind);
|
||||
context.emitter().Emit(*context.position(), UnexpectedTokenInMatchCasesBlock,
|
||||
context.PositionKind());
|
||||
context.ReturnErrorOnState();
|
||||
context.SkipPastLikelyEnd(*context.position());
|
||||
}
|
||||
|
||||
auto HandleMatchIntroducer(Context& context) -> void {
|
||||
auto state = context.PopState();
|
||||
context.AddLeafNode(NodeKind::Placeholder, *context.position());
|
||||
context.PushState(state, State::MatchConditionFinish);
|
||||
context.PushState(State::ParenConditionAsMatch);
|
||||
context.ConsumeAndDiscard();
|
||||
}
|
||||
|
||||
auto HandleMatchConditionFinish(Context& context) -> void {
|
||||
auto state = context.PopState();
|
||||
context.ReplacePlaceholderNode(state.subtree_start, NodeKind::MatchIntroducer,
|
||||
state.token);
|
||||
|
||||
if (!context.PositionIs(Lex::TokenKind::OpenCurlyBrace)) {
|
||||
if (!state.has_error) {
|
||||
CARBON_DIAGNOSTIC(ExpectedMatchCasesBlock, Error,
|
||||
"Expected `{{` starting block with cases.");
|
||||
context.emitter().Emit(*context.position(), ExpectedMatchCasesBlock);
|
||||
}
|
||||
|
||||
context.AddNode(NodeKind::MatchStatementStart, *context.position(),
|
||||
state.subtree_start, true);
|
||||
context.AddNode(NodeKind::MatchStatement, *context.position(),
|
||||
state.subtree_start, true);
|
||||
context.SkipPastLikelyEnd(*context.position());
|
||||
return;
|
||||
}
|
||||
|
||||
context.AddNode(NodeKind::MatchStatementStart, context.Consume(),
|
||||
state.subtree_start, state.has_error);
|
||||
|
||||
state.has_error = false;
|
||||
if (context.PositionIs(Lex::TokenKind::CloseCurlyBrace)) {
|
||||
CARBON_DIAGNOSTIC(ExpectedMatchCases, Error, "Expected cases.");
|
||||
context.emitter().Emit(*context.position(), ExpectedMatchCases);
|
||||
state.has_error = true;
|
||||
}
|
||||
|
||||
context.PushState(state, State::MatchStatementFinish);
|
||||
context.PushState(State::MatchCaseLoop);
|
||||
}
|
||||
|
||||
auto HandleMatchCaseLoop(Context& context) -> void {
|
||||
context.PopAndDiscardState();
|
||||
|
||||
if (context.PositionIs(Lex::TokenKind::Case)) {
|
||||
context.PushState(State::MatchCaseLoop);
|
||||
context.PushState(State::MatchCaseIntroducer);
|
||||
} else if (context.PositionIs(Lex::TokenKind::Default)) {
|
||||
context.PushState(State::MatchCaseLoopAfterDefault);
|
||||
context.PushState(State::MatchDefaultIntroducer);
|
||||
} else if (!context.PositionIs(Lex::TokenKind::CloseCurlyBrace)) {
|
||||
EmitUnexpectedTokenAndRecover(context);
|
||||
context.PushState(State::MatchCaseLoop);
|
||||
}
|
||||
}
|
||||
|
||||
auto HandleMatchCaseLoopAfterDefault(Context& context) -> void {
|
||||
context.PopAndDiscardState();
|
||||
|
||||
Lex::TokenKind kind = context.PositionKind();
|
||||
if (kind == Lex::TokenKind::Case or kind == Lex::TokenKind::Default) {
|
||||
CARBON_DIAGNOSTIC(UnreachableMatchCase, Error, "Unreachable case; `{0}{1}",
|
||||
Lex::TokenKind, std::string);
|
||||
context.emitter().Emit(*context.position(), UnreachableMatchCase, kind,
|
||||
"` occurs after the `default`");
|
||||
|
||||
context.ReturnErrorOnState();
|
||||
context.PushState(State::MatchCaseLoopAfterDefault);
|
||||
context.SkipPastLikelyEnd(*context.position());
|
||||
return;
|
||||
} else if (kind != Lex::TokenKind::CloseCurlyBrace) {
|
||||
EmitUnexpectedTokenAndRecover(context);
|
||||
context.PushState(State::MatchCaseLoopAfterDefault);
|
||||
}
|
||||
}
|
||||
|
||||
auto HandleMatchCaseIntroducer(Context& context) -> void {
|
||||
auto state = context.PopState();
|
||||
|
||||
context.AddLeafNode(NodeKind::MatchCaseIntroducer, context.Consume());
|
||||
context.PushState(state, State::MatchCaseAfterPattern);
|
||||
context.PushState(State::Pattern);
|
||||
}
|
||||
|
||||
auto HandleMatchCaseAfterPattern(Context& context) -> void {
|
||||
auto state = context.PopState();
|
||||
if (state.has_error) {
|
||||
context.AddNode(NodeKind::MatchCaseStart, *context.position(),
|
||||
state.subtree_start, true);
|
||||
context.AddNode(NodeKind::MatchCase, *context.position(),
|
||||
state.subtree_start, true);
|
||||
context.SkipPastLikelyEnd(*context.position());
|
||||
return;
|
||||
}
|
||||
|
||||
context.PushState(state, State::MatchCaseStart);
|
||||
if (context.PositionIs(Lex::TokenKind::If)) {
|
||||
context.PushState(State::MatchCaseGuardFinish);
|
||||
context.AddLeafNode(NodeKind::MatchCaseGuardIntroducer, context.Consume());
|
||||
auto open_paren = context.ConsumeIf(Lex::TokenKind::OpenParen);
|
||||
if (open_paren) {
|
||||
context.AddLeafNode(NodeKind::MatchCaseGuardStart, *open_paren);
|
||||
context.PushState(State::Expr);
|
||||
} else {
|
||||
context.AddLeafNode(NodeKind::MatchCaseGuardStart, *context.position(),
|
||||
true);
|
||||
context.AddLeafNode(NodeKind::InvalidParse, *context.position(), true);
|
||||
state = context.PopState();
|
||||
context.AddNode(NodeKind::MatchCaseGuard, *context.position(),
|
||||
state.subtree_start, true);
|
||||
state = context.PopState();
|
||||
context.AddNode(NodeKind::MatchCaseStart, *context.position(),
|
||||
state.subtree_start, true);
|
||||
context.AddNode(NodeKind::MatchCase, *context.position(),
|
||||
state.subtree_start, true);
|
||||
context.SkipPastLikelyEnd(*context.position());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto HandleMatchCaseGuardFinish(Context& context) -> void {
|
||||
auto state = context.PopState();
|
||||
|
||||
auto close_paren = context.ConsumeIf(Lex::TokenKind::CloseParen);
|
||||
if (close_paren) {
|
||||
context.AddNode(NodeKind::MatchCaseGuard, *close_paren, state.subtree_start,
|
||||
state.has_error);
|
||||
} else {
|
||||
context.AddNode(NodeKind::MatchCaseGuard, *context.position(),
|
||||
state.subtree_start, true);
|
||||
context.ReturnErrorOnState();
|
||||
context.SkipPastLikelyEnd(*context.position());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
auto HandleMatchCaseStart(Context& context) -> void {
|
||||
HandleStatementsBlockStart(context, State::MatchCaseFinish,
|
||||
NodeKind::MatchCaseEqualGreater,
|
||||
NodeKind::MatchCaseStart, NodeKind::MatchCase);
|
||||
}
|
||||
|
||||
auto HandleMatchCaseFinish(Context& context) -> void {
|
||||
auto state = context.PopState();
|
||||
context.AddNode(NodeKind::MatchCase,
|
||||
context.ConsumeChecked(Lex::TokenKind::CloseCurlyBrace),
|
||||
state.subtree_start, state.has_error);
|
||||
}
|
||||
|
||||
auto HandleMatchDefaultIntroducer(Context& context) -> void {
|
||||
context.AddLeafNode(NodeKind::MatchDefaultIntroducer, context.Consume());
|
||||
|
||||
HandleStatementsBlockStart(
|
||||
context, State::MatchDefaultFinish, NodeKind::MatchDefaultEqualGreater,
|
||||
NodeKind::MatchDefaultStart, NodeKind::MatchDefault);
|
||||
}
|
||||
|
||||
auto HandleMatchDefaultFinish(Context& context) -> void {
|
||||
auto state = context.PopState();
|
||||
context.AddNode(NodeKind::MatchDefault,
|
||||
context.ConsumeChecked(Lex::TokenKind::CloseCurlyBrace),
|
||||
state.subtree_start, state.has_error);
|
||||
}
|
||||
|
||||
auto HandleMatchStatementFinish(Context& context) -> void {
|
||||
auto state = context.PopState();
|
||||
context.AddNode(NodeKind::MatchStatement,
|
||||
context.ConsumeChecked(Lex::TokenKind::CloseCurlyBrace),
|
||||
state.subtree_start, state.has_error);
|
||||
}
|
||||
|
||||
} // namespace Carbon::Parse
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
namespace Carbon::Parse {
|
||||
|
||||
// Handles ParenConditionAs(If|While).
|
||||
// Handles ParenConditionAs(If|While|Match).
|
||||
static auto HandleParenCondition(Context& context, NodeKind start_kind,
|
||||
State finish_state) -> void {
|
||||
auto state = context.PopState();
|
||||
@@ -39,6 +39,11 @@ auto HandleParenConditionAsWhile(Context& context) -> void {
|
||||
State::ParenConditionFinishAsWhile);
|
||||
}
|
||||
|
||||
auto HandleParenConditionAsMatch(Context& context) -> void {
|
||||
HandleParenCondition(context, NodeKind::MatchConditionStart,
|
||||
State::ParenConditionFinishAsMatch);
|
||||
}
|
||||
|
||||
auto HandleParenConditionFinishAsIf(Context& context) -> void {
|
||||
auto state = context.PopState();
|
||||
|
||||
@@ -52,4 +57,11 @@ auto HandleParenConditionFinishAsWhile(Context& context) -> void {
|
||||
NodeKind::WhileCondition);
|
||||
}
|
||||
|
||||
auto HandleParenConditionFinishAsMatch(Context& context) -> void {
|
||||
auto state = context.PopState();
|
||||
|
||||
context.ConsumeAndAddCloseSymbol(state.token, state,
|
||||
NodeKind::MatchCondition);
|
||||
}
|
||||
|
||||
} // namespace Carbon::Parse
|
||||
|
||||
@@ -52,6 +52,10 @@ auto HandleStatement(Context& context) -> void {
|
||||
context.PushState(State::StatementWhile);
|
||||
break;
|
||||
}
|
||||
case Lex::TokenKind::Match: {
|
||||
context.PushState(State::MatchIntroducer);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
context.PushState(State::ExprStatementFinish);
|
||||
context.PushStateForExpr(PrecedenceGroup::ForExprStatement());
|
||||
|
||||
@@ -737,6 +737,64 @@ CARBON_PARSE_NODE_KIND_BRACKET(ChoiceDefinition, ChoiceDefinitionStart,
|
||||
// ChoiceAlternativeList
|
||||
CARBON_PARSE_NODE_KIND_CHILD_COUNT(ChoiceAlternativeListComma, 0, Comma)
|
||||
|
||||
// `match`:
|
||||
// MatchIntroducer
|
||||
// MatchConditionStart
|
||||
// _external_: expression
|
||||
// MatchCondition
|
||||
// MatchStatementStart
|
||||
// _repeated_ _external_: MatchCase
|
||||
// _optional_ _external_: MatchStatementDefault
|
||||
// MatchStatement
|
||||
CARBON_PARSE_NODE_KIND_CHILD_COUNT(MatchIntroducer, 0, Match)
|
||||
CARBON_PARSE_NODE_KIND_CHILD_COUNT(MatchConditionStart, 0,
|
||||
CARBON_IF_VALID(OpenParen))
|
||||
CARBON_PARSE_NODE_KIND_BRACKET(MatchCondition, MatchConditionStart,
|
||||
CARBON_IF_VALID(CloseParen))
|
||||
CARBON_PARSE_NODE_KIND_BRACKET(MatchStatementStart, MatchIntroducer,
|
||||
CARBON_IF_VALID(OpenCurlyBrace))
|
||||
CARBON_PARSE_NODE_KIND_BRACKET(MatchStatement, MatchStatementStart,
|
||||
CARBON_IF_VALID(CloseCurlyBrace))
|
||||
|
||||
// `case`:
|
||||
// MatchCaseIntroducer
|
||||
// _external_: Pattern
|
||||
// MatchCaseGuardIntroducer
|
||||
// MatchCaseGuardStart
|
||||
// _external_: expression
|
||||
// MatchCaseGuard
|
||||
// MatchCaseEqualGreater
|
||||
// MatchCaseStart
|
||||
// _repeated_ _external_: statement
|
||||
// MatchCase
|
||||
CARBON_PARSE_NODE_KIND_CHILD_COUNT(MatchCaseIntroducer, 0, Case)
|
||||
CARBON_PARSE_NODE_KIND_CHILD_COUNT(MatchCaseGuardIntroducer, 0, If)
|
||||
CARBON_PARSE_NODE_KIND_CHILD_COUNT(MatchCaseGuardStart, 0,
|
||||
CARBON_IF_VALID(OpenParen))
|
||||
CARBON_PARSE_NODE_KIND_BRACKET(MatchCaseGuard,
|
||||
MatchCaseGuardIntroducer,
|
||||
CARBON_IF_VALID(CloseParen))
|
||||
CARBON_PARSE_NODE_KIND_CHILD_COUNT(MatchCaseEqualGreater, 0,
|
||||
CARBON_IF_VALID(EqualGreater))
|
||||
CARBON_PARSE_NODE_KIND_BRACKET(MatchCaseStart, MatchCaseIntroducer,
|
||||
CARBON_IF_VALID(OpenCurlyBrace))
|
||||
CARBON_PARSE_NODE_KIND_BRACKET(MatchCase, MatchCaseStart,
|
||||
CARBON_IF_VALID(CloseCurlyBrace))
|
||||
|
||||
// `default`:
|
||||
// MatchDefaultIntroducer
|
||||
// MatchDefaultEqualGreater
|
||||
// MatchDefaultStart
|
||||
// _repeated_ _external_: statement
|
||||
// MatchDefault
|
||||
CARBON_PARSE_NODE_KIND_CHILD_COUNT(MatchDefaultIntroducer, 0, Default)
|
||||
CARBON_PARSE_NODE_KIND_CHILD_COUNT(MatchDefaultEqualGreater, 0,
|
||||
CARBON_IF_VALID(EqualGreater))
|
||||
CARBON_PARSE_NODE_KIND_BRACKET(MatchDefaultStart, MatchDefaultIntroducer,
|
||||
CARBON_IF_VALID(OpenCurlyBrace))
|
||||
CARBON_PARSE_NODE_KIND_BRACKET(MatchDefault, MatchDefaultStart,
|
||||
CARBON_IF_VALID(CloseCurlyBrace))
|
||||
|
||||
#undef CARBON_PARSE_NODE_KIND
|
||||
#undef CARBON_PARSE_NODE_KIND_BRACKET
|
||||
#undef CARBON_PARSE_NODE_KIND_CHILD_COUNT
|
||||
|
||||
+147
-16
@@ -730,28 +730,28 @@ CARBON_PARSE_STATE_VARIANTS2(PatternListFinish, Implicit, Tuple)
|
||||
|
||||
// Handles the processing of a `(condition)` up through the expression.
|
||||
//
|
||||
// if/while { (invalid)
|
||||
// ^
|
||||
// 1. ParenConditionAs(If|While)Finish
|
||||
// if/while/match { (invalid)
|
||||
// ^
|
||||
// 1. ParenConditionAs(If|While|Match)Finish
|
||||
//
|
||||
// if/while ( ... )
|
||||
// ^
|
||||
// if/while ???
|
||||
// ^
|
||||
// if/while/match ( ... )
|
||||
// ^
|
||||
// if/while/match ???
|
||||
// ^
|
||||
// 1. Expr
|
||||
// 2. ParenConditionAs(If|While)Finish
|
||||
CARBON_PARSE_STATE_VARIANTS2(ParenCondition, If, While)
|
||||
// 2. ParenConditionAs(If|While|Match)Finish
|
||||
CARBON_PARSE_STATE_VARIANTS3(ParenCondition, If, While, Match)
|
||||
|
||||
// Finishes the processing of a `(condition)` after the expression.
|
||||
//
|
||||
// if/while ( expr )
|
||||
// ^
|
||||
// if/while {
|
||||
// ^
|
||||
// if/while ??? {
|
||||
// ^
|
||||
// if/while/match ( expr )
|
||||
// ^
|
||||
// if/while/match {
|
||||
// ^
|
||||
// if/while/match ??? {
|
||||
// ^
|
||||
// (state done)
|
||||
CARBON_PARSE_STATE_VARIANTS2(ParenConditionFinish, If, While)
|
||||
CARBON_PARSE_STATE_VARIANTS3(ParenConditionFinish, If, While, Match)
|
||||
|
||||
// Handles the `(` of a parenthesized single expression
|
||||
//
|
||||
@@ -922,6 +922,10 @@ CARBON_PARSE_STATE_VARIANTS2(BindingPatternFinish, Generic, Regular)
|
||||
// ^
|
||||
// 1. Expr
|
||||
// 2. ExprStatementFinish
|
||||
//
|
||||
// match ...
|
||||
// ^
|
||||
// 1. MatchIntroducer
|
||||
CARBON_PARSE_STATE(Statement)
|
||||
|
||||
// Handles `break` processing at the `;`.
|
||||
@@ -1304,4 +1308,131 @@ CARBON_PARSE_STATE(ChoiceAlternativeFinish)
|
||||
// (state done)
|
||||
CARBON_PARSE_STATE(ChoiceDefinitionFinish)
|
||||
|
||||
// Handles `match` introducer.
|
||||
//
|
||||
// match ...
|
||||
// ^~~~~
|
||||
// 1. ParenConditionAsMatch
|
||||
// 2. MatchConditionFinish
|
||||
CARBON_PARSE_STATE(MatchIntroducer)
|
||||
|
||||
// Handles `match` cases block start after the condition.
|
||||
//
|
||||
// match (...) { ... }
|
||||
// ^
|
||||
// 1. MatchCaseLoop
|
||||
// 2. MatchStatementFinish
|
||||
//
|
||||
// match (...) ???
|
||||
// ^
|
||||
// (state done)
|
||||
CARBON_PARSE_STATE(MatchConditionFinish)
|
||||
|
||||
// Handles `match` cases.
|
||||
//
|
||||
// match (...) { case ...}
|
||||
// ^
|
||||
// 1. MatchCaseIntroducer
|
||||
// 2. MatchCaseLoop
|
||||
// match (...) { default ...}
|
||||
// ^
|
||||
// 1. MatchDefaultIntroducer
|
||||
// 2. MatchCaseLoopAfterDefault
|
||||
CARBON_PARSE_STATE(MatchCaseLoop)
|
||||
|
||||
// Handles `match` `case` introducer.
|
||||
//
|
||||
// match (...) { case ...}
|
||||
// ^~~~
|
||||
// 1. Pattern
|
||||
// 2. MatchCaseAfterPattern
|
||||
CARBON_PARSE_STATE(MatchCaseIntroducer)
|
||||
|
||||
// Handles `match` case after pattern.
|
||||
//
|
||||
// match (...) { case ... => ... }
|
||||
// ^
|
||||
// 1. MatchCaseStart
|
||||
// match (...) { case ... if (...) }
|
||||
// ^~~~
|
||||
// 1. Expr
|
||||
// 2. MatchCaseGuardFinish
|
||||
// 3. MatchCaseStart
|
||||
CARBON_PARSE_STATE(MatchCaseAfterPattern)
|
||||
|
||||
// Handles `match` case guard closing parenthesis.
|
||||
//
|
||||
// match (...) { case ... if (...) => ... }
|
||||
// ^
|
||||
// (state done)
|
||||
CARBON_PARSE_STATE(MatchCaseGuardFinish)
|
||||
|
||||
// Handles `match` case `=>` and `{` opening statements block.
|
||||
//
|
||||
// match (...) { case ... => {...} }
|
||||
// ^~~~
|
||||
// 1. StatementScopeLoop
|
||||
// 2. MatchCaseFinish
|
||||
//
|
||||
// match (...) { case ... ??? }
|
||||
// ^
|
||||
// (state done)
|
||||
//
|
||||
// match (...) { case ... => ??? }
|
||||
// ^
|
||||
// (state done)
|
||||
CARBON_PARSE_STATE(MatchCaseStart)
|
||||
|
||||
// Handles `match` case statements block closing `}`.
|
||||
//
|
||||
// match (...) { case ... => {...} }
|
||||
// ^
|
||||
// (state done)
|
||||
CARBON_PARSE_STATE(MatchCaseFinish)
|
||||
|
||||
// Handles `match` default introducer, `=>` and `{` opening statements block.
|
||||
//
|
||||
// match (...) { default => {...} }
|
||||
// ^~~~~~~~~~~~
|
||||
// 1. StatementScopeLoop
|
||||
// 2. MatchDefaultFinish
|
||||
//
|
||||
// match (...) { default ??? }
|
||||
// ^
|
||||
// (state done)
|
||||
//
|
||||
// match (...) { default => ??? }
|
||||
// ^
|
||||
// (state done)
|
||||
CARBON_PARSE_STATE(MatchDefaultIntroducer)
|
||||
|
||||
// Handles `match` default case statements block closing `}`.
|
||||
//
|
||||
// match (...) { default => {...} }
|
||||
// ^
|
||||
// (state done)
|
||||
CARBON_PARSE_STATE(MatchDefaultFinish)
|
||||
|
||||
// Handles `match` cases after the `default` case.
|
||||
//
|
||||
// match (...) { default => {...} case ... }
|
||||
// ^~~~
|
||||
// 1. MatchCaseLoopAfterDefault
|
||||
//
|
||||
// match (...) { default => {...} default ... }
|
||||
// ^~~~~~~
|
||||
// 1. MatchCaseLoopAfterDefault
|
||||
//
|
||||
// match (...) { default => {...} }
|
||||
// ^
|
||||
// (state done)
|
||||
CARBON_PARSE_STATE(MatchCaseLoopAfterDefault)
|
||||
|
||||
// Finishes `match` statement.
|
||||
//
|
||||
// match (...) {...}
|
||||
// ^
|
||||
// (state done)
|
||||
CARBON_PARSE_STATE(MatchStatementFinish)
|
||||
|
||||
#undef CARBON_PARSE_STATE
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
// 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
|
||||
|
||||
fn f() -> i32 {
|
||||
var x: i32 = 3;
|
||||
match (x) {
|
||||
default => { return 1; }
|
||||
// CHECK:STDERR: fail_cases_after_default.carbon:[[@LINE+3]]:5: ERROR: Unreachable case; `case` occurs after the `default`
|
||||
// CHECK:STDERR: case a: i32 => { return 2; }
|
||||
// CHECK:STDERR: ^~~~
|
||||
case a: i32 => { return 2; }
|
||||
// CHECK:STDERR: fail_cases_after_default.carbon:[[@LINE+3]]:5: ERROR: Unreachable case; `default` occurs after the `default`
|
||||
// CHECK:STDERR: default => { return 3; }
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
default => { return 3; }
|
||||
// CHECK:STDERR: fail_cases_after_default.carbon:[[@LINE+3]]:5: ERROR: Unreachable case; `case` occurs after the `default`
|
||||
// CHECK:STDERR: case (a: i32) if (a == 4) => { return 4; }
|
||||
// CHECK:STDERR: ^~~~
|
||||
case (a: i32) if (a == 4) => { return 4; }
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// CHECK:STDOUT: - filename: fail_cases_after_default.carbon
|
||||
// CHECK:STDOUT: parse_tree: [
|
||||
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
|
||||
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierName', text: 'f'},
|
||||
// CHECK:STDOUT: {kind: 'TuplePatternStart', text: '('},
|
||||
// CHECK:STDOUT: {kind: 'TuplePattern', text: ')', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'},
|
||||
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 7},
|
||||
// CHECK:STDOUT: {kind: 'VariableIntroducer', text: 'var'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierName', text: 'x'},
|
||||
// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'},
|
||||
// CHECK:STDOUT: {kind: 'BindingPattern', text: ':', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'IntLiteral', text: '3'},
|
||||
// CHECK:STDOUT: {kind: 'VariableInitializer', text: '=', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'VariableDecl', text: ';', subtree_size: 7},
|
||||
// CHECK:STDOUT: {kind: 'MatchIntroducer', text: 'match'},
|
||||
// CHECK:STDOUT: {kind: 'MatchConditionStart', text: '('},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'x'},
|
||||
// CHECK:STDOUT: {kind: 'MatchCondition', text: ')', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'MatchStatementStart', text: '{', subtree_size: 5},
|
||||
// CHECK:STDOUT: {kind: 'MatchDefaultIntroducer', text: 'default'},
|
||||
// CHECK:STDOUT: {kind: 'MatchDefaultEqualGreater', text: '=>'},
|
||||
// CHECK:STDOUT: {kind: 'MatchDefaultStart', text: '{', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'ReturnStatementStart', text: 'return'},
|
||||
// CHECK:STDOUT: {kind: 'IntLiteral', text: '1'},
|
||||
// CHECK:STDOUT: {kind: 'ReturnStatement', text: ';', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'MatchDefault', text: '}', subtree_size: 7},
|
||||
// CHECK:STDOUT: {kind: 'MatchStatement', text: '}', has_error: yes, subtree_size: 13},
|
||||
// CHECK:STDOUT: {kind: 'ReturnStatementStart', text: 'return'},
|
||||
// CHECK:STDOUT: {kind: 'IntLiteral', text: '0'},
|
||||
// CHECK:STDOUT: {kind: 'ReturnStatement', text: ';', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 31},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
// CHECK:STDOUT: ]
|
||||
@@ -0,0 +1,62 @@
|
||||
// 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
|
||||
|
||||
fn f() -> i32 {
|
||||
match (3) {
|
||||
// CHECK:STDERR: fail_missing_case_arrow.carbon:[[@LINE+3]]:17: ERROR: Expected `=>` introducing statement block.
|
||||
// CHECK:STDERR: case x: i32 { return 2; }
|
||||
// CHECK:STDERR: ^
|
||||
case x: i32 { return 2; }
|
||||
// CHECK:STDERR: fail_missing_case_arrow.carbon:[[@LINE+3]]:29: ERROR: Expected `=>` introducing statement block.
|
||||
// CHECK:STDERR: case x: i32 if (x == 3) { return 3; }
|
||||
// CHECK:STDERR: ^
|
||||
case x: i32 if (x == 3) { return 3; }
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// CHECK:STDOUT: - filename: fail_missing_case_arrow.carbon
|
||||
// CHECK:STDOUT: parse_tree: [
|
||||
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
|
||||
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierName', text: 'f'},
|
||||
// CHECK:STDOUT: {kind: 'TuplePatternStart', text: '('},
|
||||
// CHECK:STDOUT: {kind: 'TuplePattern', text: ')', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'},
|
||||
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 7},
|
||||
// CHECK:STDOUT: {kind: 'MatchIntroducer', text: 'match'},
|
||||
// CHECK:STDOUT: {kind: 'MatchConditionStart', text: '('},
|
||||
// CHECK:STDOUT: {kind: 'IntLiteral', text: '3'},
|
||||
// CHECK:STDOUT: {kind: 'MatchCondition', text: ')', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'MatchStatementStart', text: '{', subtree_size: 5},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseIntroducer', text: 'case'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierName', text: 'x'},
|
||||
// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'},
|
||||
// CHECK:STDOUT: {kind: 'BindingPattern', text: ':', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseEqualGreater', text: '{', has_error: yes},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseStart', text: '{', has_error: yes, subtree_size: 6},
|
||||
// CHECK:STDOUT: {kind: 'MatchCase', text: '{', has_error: yes, subtree_size: 7},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseIntroducer', text: 'case'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierName', text: 'x'},
|
||||
// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'},
|
||||
// CHECK:STDOUT: {kind: 'BindingPattern', text: ':', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseGuardIntroducer', text: 'if'},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseGuardStart', text: '('},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'x'},
|
||||
// CHECK:STDOUT: {kind: 'IntLiteral', text: '3'},
|
||||
// CHECK:STDOUT: {kind: 'InfixOperatorEqualEqual', text: '==', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseGuard', text: ')', subtree_size: 6},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseEqualGreater', text: '{', has_error: yes},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseStart', text: '{', has_error: yes, subtree_size: 12},
|
||||
// CHECK:STDOUT: {kind: 'MatchCase', text: '{', has_error: yes, subtree_size: 13},
|
||||
// CHECK:STDOUT: {kind: 'MatchStatement', text: '}', subtree_size: 26},
|
||||
// CHECK:STDOUT: {kind: 'ReturnStatementStart', text: 'return'},
|
||||
// CHECK:STDOUT: {kind: 'IntLiteral', text: '0'},
|
||||
// CHECK:STDOUT: {kind: 'ReturnStatement', text: ';', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 37},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
// CHECK:STDOUT: ]
|
||||
@@ -0,0 +1,44 @@
|
||||
// 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
|
||||
|
||||
fn f() -> i32 {
|
||||
match (3) {
|
||||
// CHECK:STDERR: fail_missing_case_pattern.carbon:[[@LINE+3]]:10: ERROR: Expected binding pattern.
|
||||
// CHECK:STDERR: case => { return 2; }
|
||||
// CHECK:STDERR: ^~
|
||||
case => { return 2; }
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// CHECK:STDOUT: - filename: fail_missing_case_pattern.carbon
|
||||
// CHECK:STDOUT: parse_tree: [
|
||||
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
|
||||
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierName', text: 'f'},
|
||||
// CHECK:STDOUT: {kind: 'TuplePatternStart', text: '('},
|
||||
// CHECK:STDOUT: {kind: 'TuplePattern', text: ')', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'},
|
||||
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 7},
|
||||
// CHECK:STDOUT: {kind: 'MatchIntroducer', text: 'match'},
|
||||
// CHECK:STDOUT: {kind: 'MatchConditionStart', text: '('},
|
||||
// CHECK:STDOUT: {kind: 'IntLiteral', text: '3'},
|
||||
// CHECK:STDOUT: {kind: 'MatchCondition', text: ')', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'MatchStatementStart', text: '{', subtree_size: 5},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseIntroducer', text: 'case'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierName', text: '=>', has_error: yes},
|
||||
// CHECK:STDOUT: {kind: 'InvalidParse', text: '=>', has_error: yes},
|
||||
// CHECK:STDOUT: {kind: 'BindingPattern', text: '=>', has_error: yes, subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseStart', text: '=>', has_error: yes, subtree_size: 5},
|
||||
// CHECK:STDOUT: {kind: 'MatchCase', text: '=>', has_error: yes, subtree_size: 6},
|
||||
// CHECK:STDOUT: {kind: 'MatchStatement', text: '}', subtree_size: 12},
|
||||
// CHECK:STDOUT: {kind: 'ReturnStatementStart', text: 'return'},
|
||||
// CHECK:STDOUT: {kind: 'IntLiteral', text: '0'},
|
||||
// CHECK:STDOUT: {kind: 'ReturnStatement', text: ';', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 23},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
// CHECK:STDOUT: ]
|
||||
@@ -0,0 +1,46 @@
|
||||
// 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
|
||||
|
||||
fn f() -> i32 {
|
||||
match (3) {
|
||||
case x: i32 =>
|
||||
// CHECK:STDERR: fail_missing_case_statements_block.carbon:[[@LINE+3]]:5: ERROR: Expected `{` after `=>`.
|
||||
// CHECK:STDERR: default => { return 3; }
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
default => { return 3; }
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// CHECK:STDOUT: - filename: fail_missing_case_statements_block.carbon
|
||||
// CHECK:STDOUT: parse_tree: [
|
||||
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
|
||||
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierName', text: 'f'},
|
||||
// CHECK:STDOUT: {kind: 'TuplePatternStart', text: '('},
|
||||
// CHECK:STDOUT: {kind: 'TuplePattern', text: ')', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'},
|
||||
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 7},
|
||||
// CHECK:STDOUT: {kind: 'MatchIntroducer', text: 'match'},
|
||||
// CHECK:STDOUT: {kind: 'MatchConditionStart', text: '('},
|
||||
// CHECK:STDOUT: {kind: 'IntLiteral', text: '3'},
|
||||
// CHECK:STDOUT: {kind: 'MatchCondition', text: ')', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'MatchStatementStart', text: '{', subtree_size: 5},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseIntroducer', text: 'case'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierName', text: 'x'},
|
||||
// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'},
|
||||
// CHECK:STDOUT: {kind: 'BindingPattern', text: ':', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseEqualGreater', text: '=>'},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseStart', text: 'default', has_error: yes, subtree_size: 6},
|
||||
// CHECK:STDOUT: {kind: 'MatchCase', text: 'default', has_error: yes, subtree_size: 7},
|
||||
// CHECK:STDOUT: {kind: 'MatchStatement', text: '}', subtree_size: 13},
|
||||
// CHECK:STDOUT: {kind: 'ReturnStatementStart', text: 'return'},
|
||||
// CHECK:STDOUT: {kind: 'IntLiteral', text: '0'},
|
||||
// CHECK:STDOUT: {kind: 'ReturnStatement', text: ';', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 24},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
// CHECK:STDOUT: ]
|
||||
@@ -0,0 +1,37 @@
|
||||
// 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
|
||||
|
||||
|
||||
fn f() -> i32 {
|
||||
// CHECK:STDERR: fail_missing_cases.carbon:[[@LINE+3]]:14: ERROR: Expected cases.
|
||||
// CHECK:STDERR: match (3) {}
|
||||
// CHECK:STDERR: ^
|
||||
match (3) {}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// CHECK:STDOUT: - filename: fail_missing_cases.carbon
|
||||
// CHECK:STDOUT: parse_tree: [
|
||||
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
|
||||
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierName', text: 'f'},
|
||||
// CHECK:STDOUT: {kind: 'TuplePatternStart', text: '('},
|
||||
// CHECK:STDOUT: {kind: 'TuplePattern', text: ')', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'},
|
||||
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 7},
|
||||
// CHECK:STDOUT: {kind: 'MatchIntroducer', text: 'match'},
|
||||
// CHECK:STDOUT: {kind: 'MatchConditionStart', text: '('},
|
||||
// CHECK:STDOUT: {kind: 'IntLiteral', text: '3'},
|
||||
// CHECK:STDOUT: {kind: 'MatchCondition', text: ')', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'MatchStatementStart', text: '{', subtree_size: 5},
|
||||
// CHECK:STDOUT: {kind: 'MatchStatement', text: '}', has_error: yes, subtree_size: 6},
|
||||
// CHECK:STDOUT: {kind: 'ReturnStatementStart', text: 'return'},
|
||||
// CHECK:STDOUT: {kind: 'IntLiteral', text: '0'},
|
||||
// CHECK:STDOUT: {kind: 'ReturnStatement', text: ';', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 17},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
// CHECK:STDOUT: ]
|
||||
@@ -0,0 +1,33 @@
|
||||
// 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
|
||||
|
||||
fn f() -> i32 {
|
||||
match (1)
|
||||
// CHECK:STDERR: fail_missing_cases_block.carbon:[[@LINE+3]]:3: ERROR: Expected `{` starting block with cases.
|
||||
// CHECK:STDERR: return 0;
|
||||
// CHECK:STDERR: ^~~~~~
|
||||
return 0;
|
||||
}
|
||||
|
||||
// CHECK:STDOUT: - filename: fail_missing_cases_block.carbon
|
||||
// CHECK:STDOUT: parse_tree: [
|
||||
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
|
||||
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierName', text: 'f'},
|
||||
// CHECK:STDOUT: {kind: 'TuplePatternStart', text: '('},
|
||||
// CHECK:STDOUT: {kind: 'TuplePattern', text: ')', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'},
|
||||
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 7},
|
||||
// CHECK:STDOUT: {kind: 'MatchIntroducer', text: 'match'},
|
||||
// CHECK:STDOUT: {kind: 'MatchConditionStart', text: '('},
|
||||
// CHECK:STDOUT: {kind: 'IntLiteral', text: '1'},
|
||||
// CHECK:STDOUT: {kind: 'MatchCondition', text: ')', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'MatchStatementStart', text: 'return', has_error: yes, subtree_size: 5},
|
||||
// CHECK:STDOUT: {kind: 'MatchStatement', text: 'return', has_error: yes, subtree_size: 6},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 14},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
// CHECK:STDOUT: ]
|
||||
@@ -0,0 +1,42 @@
|
||||
// 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
|
||||
|
||||
fn f() -> i32 {
|
||||
match (3) {
|
||||
// CHECK:STDERR: fail_missing_default_arrow.carbon:[[@LINE+3]]:13: ERROR: Expected `=>` introducing statement block.
|
||||
// CHECK:STDERR: default { return 1; }
|
||||
// CHECK:STDERR: ^
|
||||
default { return 1; }
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// CHECK:STDOUT: - filename: fail_missing_default_arrow.carbon
|
||||
// CHECK:STDOUT: parse_tree: [
|
||||
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
|
||||
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierName', text: 'f'},
|
||||
// CHECK:STDOUT: {kind: 'TuplePatternStart', text: '('},
|
||||
// CHECK:STDOUT: {kind: 'TuplePattern', text: ')', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'},
|
||||
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 7},
|
||||
// CHECK:STDOUT: {kind: 'MatchIntroducer', text: 'match'},
|
||||
// CHECK:STDOUT: {kind: 'MatchConditionStart', text: '('},
|
||||
// CHECK:STDOUT: {kind: 'IntLiteral', text: '3'},
|
||||
// CHECK:STDOUT: {kind: 'MatchCondition', text: ')', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'MatchStatementStart', text: '{', subtree_size: 5},
|
||||
// CHECK:STDOUT: {kind: 'MatchDefaultIntroducer', text: 'default'},
|
||||
// CHECK:STDOUT: {kind: 'MatchDefaultEqualGreater', text: '{', has_error: yes},
|
||||
// CHECK:STDOUT: {kind: 'MatchDefaultStart', text: '{', has_error: yes, subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'MatchDefault', text: '{', has_error: yes, subtree_size: 4},
|
||||
// CHECK:STDOUT: {kind: 'MatchStatement', text: '}', subtree_size: 10},
|
||||
// CHECK:STDOUT: {kind: 'ReturnStatementStart', text: 'return'},
|
||||
// CHECK:STDOUT: {kind: 'IntLiteral', text: '0'},
|
||||
// CHECK:STDOUT: {kind: 'ReturnStatement', text: ';', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 21},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
// CHECK:STDOUT: ]
|
||||
@@ -0,0 +1,42 @@
|
||||
// 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
|
||||
|
||||
fn f() -> i32 {
|
||||
match (3) {
|
||||
default =>
|
||||
// CHECK:STDERR: fail_missing_default_statements_block.carbon:[[@LINE+3]]:3: ERROR: Expected `{` after `=>`.
|
||||
// CHECK:STDERR: }
|
||||
// CHECK:STDERR: ^
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// CHECK:STDOUT: - filename: fail_missing_default_statements_block.carbon
|
||||
// CHECK:STDOUT: parse_tree: [
|
||||
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
|
||||
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierName', text: 'f'},
|
||||
// CHECK:STDOUT: {kind: 'TuplePatternStart', text: '('},
|
||||
// CHECK:STDOUT: {kind: 'TuplePattern', text: ')', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'},
|
||||
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 7},
|
||||
// CHECK:STDOUT: {kind: 'MatchIntroducer', text: 'match'},
|
||||
// CHECK:STDOUT: {kind: 'MatchConditionStart', text: '('},
|
||||
// CHECK:STDOUT: {kind: 'IntLiteral', text: '3'},
|
||||
// CHECK:STDOUT: {kind: 'MatchCondition', text: ')', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'MatchStatementStart', text: '{', subtree_size: 5},
|
||||
// CHECK:STDOUT: {kind: 'MatchDefaultIntroducer', text: 'default'},
|
||||
// CHECK:STDOUT: {kind: 'MatchDefaultEqualGreater', text: '=>'},
|
||||
// CHECK:STDOUT: {kind: 'MatchDefaultStart', text: '}', has_error: yes, subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'MatchDefault', text: '}', has_error: yes, subtree_size: 4},
|
||||
// CHECK:STDOUT: {kind: 'MatchStatement', text: '}', subtree_size: 10},
|
||||
// CHECK:STDOUT: {kind: 'ReturnStatementStart', text: 'return'},
|
||||
// CHECK:STDOUT: {kind: 'IntLiteral', text: '0'},
|
||||
// CHECK:STDOUT: {kind: 'ReturnStatement', text: ';', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 21},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
// CHECK:STDOUT: ]
|
||||
@@ -0,0 +1,49 @@
|
||||
// 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
|
||||
|
||||
fn f() -> i32 {
|
||||
match (true) {
|
||||
// CHECK:STDERR: fail_missing_guard_close_paren.carbon:[[@LINE+3]]:21: ERROR: Opening symbol without a corresponding closing symbol.
|
||||
// CHECK:STDERR: case x: bool if (false => { return 1; }
|
||||
// CHECK:STDERR: ^
|
||||
case x: bool if (false => { return 1; }
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// CHECK:STDOUT: - filename: fail_missing_guard_close_paren.carbon
|
||||
// CHECK:STDOUT: parse_tree: [
|
||||
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
|
||||
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierName', text: 'f'},
|
||||
// CHECK:STDOUT: {kind: 'TuplePatternStart', text: '('},
|
||||
// CHECK:STDOUT: {kind: 'TuplePattern', text: ')', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'},
|
||||
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 7},
|
||||
// CHECK:STDOUT: {kind: 'MatchIntroducer', text: 'match'},
|
||||
// CHECK:STDOUT: {kind: 'MatchConditionStart', text: '('},
|
||||
// CHECK:STDOUT: {kind: 'BoolLiteralTrue', text: 'true'},
|
||||
// CHECK:STDOUT: {kind: 'MatchCondition', text: ')', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'MatchStatementStart', text: '{', subtree_size: 5},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseIntroducer', text: 'case'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierName', text: 'x'},
|
||||
// CHECK:STDOUT: {kind: 'BoolTypeLiteral', text: 'bool'},
|
||||
// CHECK:STDOUT: {kind: 'BindingPattern', text: ':', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseGuardIntroducer', text: 'if'},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseGuardStart', text: '('},
|
||||
// CHECK:STDOUT: {kind: 'BoolLiteralFalse', text: 'false'},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseGuard', text: '=>', has_error: yes, subtree_size: 4},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseEqualGreater', text: '}', has_error: yes},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseStart', text: '}', has_error: yes, subtree_size: 10},
|
||||
// CHECK:STDOUT: {kind: 'MatchCase', text: '}', has_error: yes, subtree_size: 11},
|
||||
// CHECK:STDOUT: {kind: 'MatchStatement', text: '}', subtree_size: 17},
|
||||
// CHECK:STDOUT: {kind: 'ReturnStatementStart', text: 'return'},
|
||||
// CHECK:STDOUT: {kind: 'IntLiteral', text: '0'},
|
||||
// CHECK:STDOUT: {kind: 'ReturnStatement', text: ';', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 28},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
// CHECK:STDOUT: ]
|
||||
@@ -0,0 +1,48 @@
|
||||
// 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
|
||||
|
||||
fn f() -> i32 {
|
||||
match (true) {
|
||||
// CHECK:STDERR: fail_missing_guard_open_paren.carbon:[[@LINE+3]]:26: ERROR: Closing symbol without a corresponding opening symbol.
|
||||
// CHECK:STDERR: case x: bool if false) => { return 1; }
|
||||
// CHECK:STDERR: ^
|
||||
case x: bool if false) => { return 1; }
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// CHECK:STDOUT: - filename: fail_missing_guard_open_paren.carbon
|
||||
// CHECK:STDOUT: parse_tree: [
|
||||
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
|
||||
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierName', text: 'f'},
|
||||
// CHECK:STDOUT: {kind: 'TuplePatternStart', text: '('},
|
||||
// CHECK:STDOUT: {kind: 'TuplePattern', text: ')', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'},
|
||||
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 7},
|
||||
// CHECK:STDOUT: {kind: 'MatchIntroducer', text: 'match'},
|
||||
// CHECK:STDOUT: {kind: 'MatchConditionStart', text: '('},
|
||||
// CHECK:STDOUT: {kind: 'BoolLiteralTrue', text: 'true'},
|
||||
// CHECK:STDOUT: {kind: 'MatchCondition', text: ')', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'MatchStatementStart', text: '{', subtree_size: 5},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseIntroducer', text: 'case'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierName', text: 'x'},
|
||||
// CHECK:STDOUT: {kind: 'BoolTypeLiteral', text: 'bool'},
|
||||
// CHECK:STDOUT: {kind: 'BindingPattern', text: ':', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseGuardIntroducer', text: 'if'},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseGuardStart', text: 'false', has_error: yes},
|
||||
// CHECK:STDOUT: {kind: 'InvalidParse', text: 'false', has_error: yes},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseGuard', text: 'false', has_error: yes, subtree_size: 4},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseStart', text: 'false', has_error: yes, subtree_size: 9},
|
||||
// CHECK:STDOUT: {kind: 'MatchCase', text: 'false', has_error: yes, subtree_size: 10},
|
||||
// CHECK:STDOUT: {kind: 'MatchStatement', text: '}', subtree_size: 16},
|
||||
// CHECK:STDOUT: {kind: 'ReturnStatementStart', text: 'return'},
|
||||
// CHECK:STDOUT: {kind: 'IntLiteral', text: '0'},
|
||||
// CHECK:STDOUT: {kind: 'ReturnStatement', text: ';', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 27},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
// CHECK:STDOUT: ]
|
||||
@@ -0,0 +1,45 @@
|
||||
// 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
|
||||
|
||||
fn f() -> i32 {
|
||||
// CHECK:STDERR: fail_missing_matched_expr.carbon:[[@LINE+3]]:9: ERROR: Expected `(` after `match`.
|
||||
// CHECK:STDERR: match {
|
||||
// CHECK:STDERR: ^
|
||||
match {
|
||||
default => { return 1; }
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// CHECK:STDOUT: - filename: fail_missing_matched_expr.carbon
|
||||
// CHECK:STDOUT: parse_tree: [
|
||||
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
|
||||
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierName', text: 'f'},
|
||||
// CHECK:STDOUT: {kind: 'TuplePatternStart', text: '('},
|
||||
// CHECK:STDOUT: {kind: 'TuplePattern', text: ')', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'},
|
||||
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 7},
|
||||
// CHECK:STDOUT: {kind: 'MatchIntroducer', text: 'match'},
|
||||
// CHECK:STDOUT: {kind: 'MatchConditionStart', text: 'match', has_error: yes},
|
||||
// CHECK:STDOUT: {kind: 'InvalidParse', text: '{', has_error: yes},
|
||||
// CHECK:STDOUT: {kind: 'MatchCondition', text: 'match', has_error: yes, subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'MatchStatementStart', text: '{', subtree_size: 5},
|
||||
// CHECK:STDOUT: {kind: 'MatchDefaultIntroducer', text: 'default'},
|
||||
// CHECK:STDOUT: {kind: 'MatchDefaultEqualGreater', text: '=>'},
|
||||
// CHECK:STDOUT: {kind: 'MatchDefaultStart', text: '{', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'ReturnStatementStart', text: 'return'},
|
||||
// CHECK:STDOUT: {kind: 'IntLiteral', text: '1'},
|
||||
// CHECK:STDOUT: {kind: 'ReturnStatement', text: ';', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'MatchDefault', text: '}', subtree_size: 7},
|
||||
// CHECK:STDOUT: {kind: 'MatchStatement', text: '}', subtree_size: 13},
|
||||
// CHECK:STDOUT: {kind: 'ReturnStatementStart', text: 'return'},
|
||||
// CHECK:STDOUT: {kind: 'IntLiteral', text: '0'},
|
||||
// CHECK:STDOUT: {kind: 'ReturnStatement', text: ';', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 24},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
// CHECK:STDOUT: ]
|
||||
@@ -0,0 +1,112 @@
|
||||
// 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
|
||||
|
||||
fn f() -> i32 {
|
||||
var x: i32 = 3;
|
||||
match (x) {
|
||||
// CHECK:STDERR: fail_unexpected_tokens_in_cases_block.carbon:[[@LINE+3]]:5: ERROR: Unexpected `let`; expected `case`, `default` or `}`.
|
||||
// CHECK:STDERR: let u: i32 =
|
||||
// CHECK:STDERR: ^~~
|
||||
let u: i32 =
|
||||
case y: i32 if (y > 2) => { return 1; }
|
||||
// CHECK:STDERR: fail_unexpected_tokens_in_cases_block.carbon:[[@LINE+3]]:5: ERROR: Unexpected `if`; expected `case`, `default` or `}`.
|
||||
// CHECK:STDERR: if (true) {
|
||||
// CHECK:STDERR: ^~
|
||||
if (true) {
|
||||
return 2;
|
||||
}
|
||||
// CHECK:STDERR: fail_unexpected_tokens_in_cases_block.carbon:[[@LINE+3]]:5: ERROR: Unexpected `var`; expected `case`, `default` or `}`.
|
||||
// CHECK:STDERR: var w
|
||||
// CHECK:STDERR: ^~~
|
||||
var w
|
||||
case z: i32 if (z == 3) => { return 3; }
|
||||
// CHECK:STDERR: fail_unexpected_tokens_in_cases_block.carbon:[[@LINE+3]]:5: ERROR: Unexpected `{`; expected `case`, `default` or `}`.
|
||||
// CHECK:STDERR: {
|
||||
// CHECK:STDERR: ^
|
||||
{
|
||||
break;
|
||||
}
|
||||
default => { return 3; }
|
||||
// CHECK:STDERR: fail_unexpected_tokens_in_cases_block.carbon:[[@LINE+3]]:5: ERROR: Unexpected `return`; expected `case`, `default` or `}`.
|
||||
// CHECK:STDERR: return 1;
|
||||
// CHECK:STDERR: ^~~~~~
|
||||
return 1;
|
||||
// CHECK:STDERR: fail_unexpected_tokens_in_cases_block.carbon:[[@LINE+3]]:5: ERROR: Unexpected `(`; expected `case`, `default` or `}`.
|
||||
// CHECK:STDERR: ((), (), ())
|
||||
// CHECK:STDERR: ^
|
||||
((), (), ())
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// CHECK:STDOUT: - filename: fail_unexpected_tokens_in_cases_block.carbon
|
||||
// CHECK:STDOUT: parse_tree: [
|
||||
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
|
||||
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierName', text: 'f'},
|
||||
// CHECK:STDOUT: {kind: 'TuplePatternStart', text: '('},
|
||||
// CHECK:STDOUT: {kind: 'TuplePattern', text: ')', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'},
|
||||
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 7},
|
||||
// CHECK:STDOUT: {kind: 'VariableIntroducer', text: 'var'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierName', text: 'x'},
|
||||
// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'},
|
||||
// CHECK:STDOUT: {kind: 'BindingPattern', text: ':', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'IntLiteral', text: '3'},
|
||||
// CHECK:STDOUT: {kind: 'VariableInitializer', text: '=', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'VariableDecl', text: ';', subtree_size: 7},
|
||||
// CHECK:STDOUT: {kind: 'MatchIntroducer', text: 'match'},
|
||||
// CHECK:STDOUT: {kind: 'MatchConditionStart', text: '('},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'x'},
|
||||
// CHECK:STDOUT: {kind: 'MatchCondition', text: ')', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'MatchStatementStart', text: '{', subtree_size: 5},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseIntroducer', text: 'case'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierName', text: 'y'},
|
||||
// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'},
|
||||
// CHECK:STDOUT: {kind: 'BindingPattern', text: ':', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseGuardIntroducer', text: 'if'},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseGuardStart', text: '('},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'y'},
|
||||
// CHECK:STDOUT: {kind: 'IntLiteral', text: '2'},
|
||||
// CHECK:STDOUT: {kind: 'InfixOperatorGreater', text: '>', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseGuard', text: ')', subtree_size: 6},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseEqualGreater', text: '=>'},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseStart', text: '{', subtree_size: 12},
|
||||
// CHECK:STDOUT: {kind: 'ReturnStatementStart', text: 'return'},
|
||||
// CHECK:STDOUT: {kind: 'IntLiteral', text: '1'},
|
||||
// CHECK:STDOUT: {kind: 'ReturnStatement', text: ';', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'MatchCase', text: '}', subtree_size: 16},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseIntroducer', text: 'case'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierName', text: 'z'},
|
||||
// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'},
|
||||
// CHECK:STDOUT: {kind: 'BindingPattern', text: ':', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseGuardIntroducer', text: 'if'},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseGuardStart', text: '('},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'z'},
|
||||
// CHECK:STDOUT: {kind: 'IntLiteral', text: '3'},
|
||||
// CHECK:STDOUT: {kind: 'InfixOperatorEqualEqual', text: '==', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseGuard', text: ')', subtree_size: 6},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseEqualGreater', text: '=>'},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseStart', text: '{', subtree_size: 12},
|
||||
// CHECK:STDOUT: {kind: 'ReturnStatementStart', text: 'return'},
|
||||
// CHECK:STDOUT: {kind: 'IntLiteral', text: '3'},
|
||||
// CHECK:STDOUT: {kind: 'ReturnStatement', text: ';', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'MatchCase', text: '}', subtree_size: 16},
|
||||
// CHECK:STDOUT: {kind: 'MatchDefaultIntroducer', text: 'default'},
|
||||
// CHECK:STDOUT: {kind: 'MatchDefaultEqualGreater', text: '=>'},
|
||||
// CHECK:STDOUT: {kind: 'MatchDefaultStart', text: '{', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'ReturnStatementStart', text: 'return'},
|
||||
// CHECK:STDOUT: {kind: 'IntLiteral', text: '3'},
|
||||
// CHECK:STDOUT: {kind: 'ReturnStatement', text: ';', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'MatchDefault', text: '}', subtree_size: 7},
|
||||
// CHECK:STDOUT: {kind: 'MatchStatement', text: '}', has_error: yes, subtree_size: 45},
|
||||
// CHECK:STDOUT: {kind: 'ReturnStatementStart', text: 'return'},
|
||||
// CHECK:STDOUT: {kind: 'IntLiteral', text: '0'},
|
||||
// CHECK:STDOUT: {kind: 'ReturnStatement', text: ';', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 63},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
// CHECK:STDOUT: ]
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
// 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
|
||||
|
||||
fn f() -> i32 {
|
||||
var x: i32 = 3;
|
||||
match (f(x)) {
|
||||
case (a: i32, b: i32) => { return 0; }
|
||||
case (a: i32) if (a < 0) => { return 2; }
|
||||
case a: i32 if (a != x) => { return 3; }
|
||||
default => { return 4; }
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// CHECK:STDOUT: - filename: match.carbon
|
||||
// CHECK:STDOUT: parse_tree: [
|
||||
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
|
||||
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierName', text: 'f'},
|
||||
// CHECK:STDOUT: {kind: 'TuplePatternStart', text: '('},
|
||||
// CHECK:STDOUT: {kind: 'TuplePattern', text: ')', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'},
|
||||
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 7},
|
||||
// CHECK:STDOUT: {kind: 'VariableIntroducer', text: 'var'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierName', text: 'x'},
|
||||
// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'},
|
||||
// CHECK:STDOUT: {kind: 'BindingPattern', text: ':', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'IntLiteral', text: '3'},
|
||||
// CHECK:STDOUT: {kind: 'VariableInitializer', text: '=', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'VariableDecl', text: ';', subtree_size: 7},
|
||||
// CHECK:STDOUT: {kind: 'MatchIntroducer', text: 'match'},
|
||||
// CHECK:STDOUT: {kind: 'MatchConditionStart', text: '('},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'f'},
|
||||
// CHECK:STDOUT: {kind: 'CallExprStart', text: '(', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'x'},
|
||||
// CHECK:STDOUT: {kind: 'CallExpr', text: ')', subtree_size: 4},
|
||||
// CHECK:STDOUT: {kind: 'MatchCondition', text: ')', subtree_size: 6},
|
||||
// CHECK:STDOUT: {kind: 'MatchStatementStart', text: '{', subtree_size: 8},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseIntroducer', text: 'case'},
|
||||
// CHECK:STDOUT: {kind: 'TuplePatternStart', text: '('},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierName', text: 'a'},
|
||||
// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'},
|
||||
// CHECK:STDOUT: {kind: 'BindingPattern', text: ':', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'PatternListComma', text: ','},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierName', text: 'b'},
|
||||
// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'},
|
||||
// CHECK:STDOUT: {kind: 'BindingPattern', text: ':', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'TuplePattern', text: ')', subtree_size: 9},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseEqualGreater', text: '=>'},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseStart', text: '{', subtree_size: 12},
|
||||
// CHECK:STDOUT: {kind: 'ReturnStatementStart', text: 'return'},
|
||||
// CHECK:STDOUT: {kind: 'IntLiteral', text: '0'},
|
||||
// CHECK:STDOUT: {kind: 'ReturnStatement', text: ';', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'MatchCase', text: '}', subtree_size: 16},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseIntroducer', text: 'case'},
|
||||
// CHECK:STDOUT: {kind: 'TuplePatternStart', text: '('},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierName', text: 'a'},
|
||||
// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'},
|
||||
// CHECK:STDOUT: {kind: 'BindingPattern', text: ':', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'TuplePattern', text: ')', subtree_size: 5},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseGuardIntroducer', text: 'if'},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseGuardStart', text: '('},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'a'},
|
||||
// CHECK:STDOUT: {kind: 'IntLiteral', text: '0'},
|
||||
// CHECK:STDOUT: {kind: 'InfixOperatorLess', text: '<', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseGuard', text: ')', subtree_size: 6},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseEqualGreater', text: '=>'},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseStart', text: '{', subtree_size: 14},
|
||||
// CHECK:STDOUT: {kind: 'ReturnStatementStart', text: 'return'},
|
||||
// CHECK:STDOUT: {kind: 'IntLiteral', text: '2'},
|
||||
// CHECK:STDOUT: {kind: 'ReturnStatement', text: ';', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'MatchCase', text: '}', subtree_size: 18},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseIntroducer', text: 'case'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierName', text: 'a'},
|
||||
// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'},
|
||||
// CHECK:STDOUT: {kind: 'BindingPattern', text: ':', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseGuardIntroducer', text: 'if'},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseGuardStart', text: '('},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'a'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'x'},
|
||||
// CHECK:STDOUT: {kind: 'InfixOperatorExclaimEqual', text: '!=', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseGuard', text: ')', subtree_size: 6},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseEqualGreater', text: '=>'},
|
||||
// CHECK:STDOUT: {kind: 'MatchCaseStart', text: '{', subtree_size: 12},
|
||||
// CHECK:STDOUT: {kind: 'ReturnStatementStart', text: 'return'},
|
||||
// CHECK:STDOUT: {kind: 'IntLiteral', text: '3'},
|
||||
// CHECK:STDOUT: {kind: 'ReturnStatement', text: ';', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'MatchCase', text: '}', subtree_size: 16},
|
||||
// CHECK:STDOUT: {kind: 'MatchDefaultIntroducer', text: 'default'},
|
||||
// CHECK:STDOUT: {kind: 'MatchDefaultEqualGreater', text: '=>'},
|
||||
// CHECK:STDOUT: {kind: 'MatchDefaultStart', text: '{', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'ReturnStatementStart', text: 'return'},
|
||||
// CHECK:STDOUT: {kind: 'IntLiteral', text: '4'},
|
||||
// CHECK:STDOUT: {kind: 'ReturnStatement', text: ';', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'MatchDefault', text: '}', subtree_size: 7},
|
||||
// CHECK:STDOUT: {kind: 'MatchStatement', text: '}', subtree_size: 66},
|
||||
// CHECK:STDOUT: {kind: 'ReturnStatementStart', text: 'return'},
|
||||
// CHECK:STDOUT: {kind: 'IntLiteral', text: '0'},
|
||||
// CHECK:STDOUT: {kind: 'ReturnStatement', text: ';', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 84},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
// CHECK:STDOUT: ]
|
||||
@@ -5,6 +5,8 @@
|
||||
#ifndef CARBON_TOOLCHAIN_PARSE_TYPED_NODES_H_
|
||||
#define CARBON_TOOLCHAIN_PARSE_TYPED_NODES_H_
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include "toolchain/parse/node_ids.h"
|
||||
#include "toolchain/parse/node_kind.h"
|
||||
|
||||
@@ -482,6 +484,77 @@ struct WhileStatement {
|
||||
CodeBlockId body;
|
||||
};
|
||||
|
||||
using MatchConditionStart = LeafNode<NodeKind::MatchConditionStart>;
|
||||
|
||||
struct MatchCondition {
|
||||
static constexpr auto Kind = NodeKind::MatchCondition.Define();
|
||||
|
||||
MatchConditionStartId left_paren;
|
||||
AnyExprId condition;
|
||||
};
|
||||
|
||||
using MatchIntroducer = LeafNode<NodeKind::MatchIntroducer>;
|
||||
struct MatchStatementStart {
|
||||
static constexpr auto Kind = NodeKind::MatchStatementStart.Define();
|
||||
|
||||
MatchIntroducerId introducer;
|
||||
MatchConditionId left_brace;
|
||||
};
|
||||
|
||||
using MatchCaseIntroducer = LeafNode<NodeKind::MatchCaseIntroducer>;
|
||||
using MatchCaseGuardIntroducer = LeafNode<NodeKind::MatchCaseGuardIntroducer>;
|
||||
using MatchCaseGuardStart = LeafNode<NodeKind::MatchCaseGuardStart>;
|
||||
|
||||
struct MatchCaseGuard {
|
||||
static constexpr auto Kind = NodeKind::MatchCaseGuard.Define();
|
||||
MatchCaseGuardIntroducerId introducer;
|
||||
MatchCaseGuardStartId left_paren;
|
||||
AnyExprId condition;
|
||||
};
|
||||
|
||||
using MatchCaseEqualGreater = LeafNode<NodeKind::MatchCaseEqualGreater>;
|
||||
|
||||
struct MatchCaseStart {
|
||||
static constexpr auto Kind = NodeKind::MatchCaseStart.Define();
|
||||
MatchCaseIntroducerId introducer;
|
||||
AnyPatternId pattern;
|
||||
std::optional<MatchCaseGuardId> guard;
|
||||
MatchCaseEqualGreaterId equal_greater_token;
|
||||
};
|
||||
|
||||
struct MatchCase {
|
||||
static constexpr auto Kind = NodeKind::MatchCase.Define();
|
||||
MatchCaseStartId head;
|
||||
llvm::SmallVector<AnyStatementId> statements;
|
||||
};
|
||||
|
||||
using MatchDefaultIntroducer = LeafNode<NodeKind::MatchDefaultIntroducer>;
|
||||
using MatchDefaultEqualGreater = LeafNode<NodeKind::MatchDefaultEqualGreater>;
|
||||
|
||||
struct MatchDefaultStart {
|
||||
static constexpr auto Kind = NodeKind::MatchDefaultStart.Define();
|
||||
MatchDefaultIntroducerId introducer;
|
||||
MatchDefaultEqualGreaterId equal_greater_token;
|
||||
};
|
||||
|
||||
struct MatchDefault {
|
||||
static constexpr auto Kind = NodeKind::MatchDefault.Define();
|
||||
|
||||
MatchDefaultStartId introducer;
|
||||
llvm::SmallVector<AnyStatementId> statements;
|
||||
};
|
||||
|
||||
// A `match` statement: `match (expr) { case (...) => {...} default => {...}}`.
|
||||
struct MatchStatement {
|
||||
static constexpr auto Kind =
|
||||
NodeKind::MatchStatement.Define(NodeCategory::Statement);
|
||||
|
||||
MatchStatementStartId head;
|
||||
|
||||
llvm::SmallVector<MatchCaseId> cases;
|
||||
std::optional<MatchDefaultId> default_case;
|
||||
};
|
||||
|
||||
// Expression nodes
|
||||
// ----------------
|
||||
|
||||
|
||||
Reference in New Issue
Block a user