diff --git a/toolchain/parse/context.h b/toolchain/parse/context.h index 454ce5389dfd..3806cac94af6 100644 --- a/toolchain/parse/context.h +++ b/toolchain/parse/context.h @@ -273,6 +273,12 @@ class Context { << "Excessive stack size: likely infinite loop"; } + // Pushes a constructed state onto the stack, with a different parse state. + auto PushState(StateStackEntry state_entry, State parse_state) -> void { + state_entry.state = parse_state; + PushState(state_entry); + } + // Propagates an error up the state stack, to the parent state. auto ReturnErrorOnState() -> void { state_stack_.back().has_error = true; } diff --git a/toolchain/parse/handle_array_expr.cpp b/toolchain/parse/handle_array_expr.cpp index e5a79606b691..50fc4ebee261 100644 --- a/toolchain/parse/handle_array_expr.cpp +++ b/toolchain/parse/handle_array_expr.cpp @@ -12,11 +12,10 @@ namespace Carbon::Parse { auto HandleArrayExpr(Context& context) -> void { auto state = context.PopState(); - state.state = State::ArrayExprSemi; context.AddLeafNode(NodeKind::ArrayExprStart, context.ConsumeChecked(Lex::TokenKind::OpenSquareBracket), state.has_error); - context.PushState(state); + context.PushState(state, State::ArrayExprSemi); context.PushState(State::Expr); } @@ -33,8 +32,7 @@ auto HandleArrayExprSemi(Context& context) -> void { context.AddNode(NodeKind::ArrayExprSemi, *semi, state.subtree_start, state.has_error); } - state.state = State::ArrayExprFinish; - context.PushState(state); + context.PushState(state, State::ArrayExprFinish); if (!context.PositionIs(Lex::TokenKind::CloseSquareBracket)) { context.PushState(State::Expr); } diff --git a/toolchain/parse/handle_binding_pattern.cpp b/toolchain/parse/handle_binding_pattern.cpp index 7a51b0f734e1..c6860919fc22 100644 --- a/toolchain/parse/handle_binding_pattern.cpp +++ b/toolchain/parse/handle_binding_pattern.cpp @@ -31,9 +31,8 @@ auto HandleBindingPattern(Context& context) -> void { // Add a placeholder for the type. context.AddLeafNode(NodeKind::InvalidParse, *context.position(), /*has_error=*/true); - state.state = State::BindingPatternFinishAsRegular; state.has_error = true; - context.PushState(state); + context.PushState(state, State::BindingPatternFinishAsRegular); }; // The first item should be an identifier or `self`. diff --git a/toolchain/parse/handle_brace_expr.cpp b/toolchain/parse/handle_brace_expr.cpp index 94016063b6e3..d41e329163b6 100644 --- a/toolchain/parse/handle_brace_expr.cpp +++ b/toolchain/parse/handle_brace_expr.cpp @@ -8,9 +8,7 @@ namespace Carbon::Parse { auto HandleBraceExpr(Context& context) -> void { auto state = context.PopState(); - - state.state = State::BraceExprFinishAsUnknown; - context.PushState(state); + context.PushState(state, State::BraceExprFinishAsUnknown); CARBON_CHECK(context.ConsumeAndAddLeafNodeIf( Lex::TokenKind::OpenCurlyBrace, @@ -39,9 +37,8 @@ static auto HandleBraceExprParamError(Context& context, (is_value || is_unknown) ? llvm::StringLiteral("`.field = value`") : llvm::StringLiteral("")); - state.state = param_finish_state; state.has_error = true; - context.PushState(state); + context.PushState(state, param_finish_state); } // Handles BraceExprParamAs(Type|Value|Unknown). @@ -54,8 +51,7 @@ static auto HandleBraceExprParam(Context& context, State after_designator_state, return; } - state.state = after_designator_state; - context.PushState(state); + context.PushState(state, after_designator_state); context.PushState(State::PeriodAsStruct); } @@ -85,8 +81,7 @@ static auto HandleBraceExprParamAfterDesignator(Context& context, {Lex::TokenKind::Equal, Lex::TokenKind::Colon, Lex::TokenKind::Comma}); if (!recovery_pos || context.tokens().GetKind(*recovery_pos) == Lex::TokenKind::Comma) { - state.state = param_finish_state; - context.PushState(state); + context.PushState(state, param_finish_state); return; } context.SkipTo(*recovery_pos); @@ -126,9 +121,8 @@ static auto HandleBraceExprParamAfterDesignator(Context& context, // Struct type fields and value fields use the same grammar except // that one has a `:` separator and the other has an `=` separator. - state.state = param_finish_state; state.token = context.Consume(); - context.PushState(state); + context.PushState(state, param_finish_state); context.PushState(State::Expr); } diff --git a/toolchain/parse/handle_call_expr.cpp b/toolchain/parse/handle_call_expr.cpp index 3d7b7aec01a2..62bae20a0977 100644 --- a/toolchain/parse/handle_call_expr.cpp +++ b/toolchain/parse/handle_call_expr.cpp @@ -8,9 +8,7 @@ namespace Carbon::Parse { auto HandleCallExpr(Context& context) -> void { auto state = context.PopState(); - - state.state = State::CallExprFinish; - context.PushState(state); + context.PushState(state, State::CallExprFinish); context.AddNode(NodeKind::CallExprStart, context.Consume(), state.subtree_start, state.has_error); diff --git a/toolchain/parse/handle_decl_name_and_params.cpp b/toolchain/parse/handle_decl_name_and_params.cpp index b0c2f3b08787..5259c5c8edcc 100644 --- a/toolchain/parse/handle_decl_name_and_params.cpp +++ b/toolchain/parse/handle_decl_name_and_params.cpp @@ -13,13 +13,11 @@ static auto HandleDeclNameAndParams(Context& context, State after_name) // TODO: Should handle designated names. if (auto identifier = context.ConsumeIf(Lex::TokenKind::Identifier)) { - state.state = after_name; - context.PushState(state); + context.PushState(state, after_name); if (context.PositionIs(Lex::TokenKind::Period)) { context.AddLeafNode(NodeKind::IdentifierName, *identifier); - state.state = State::PeriodAsDecl; - context.PushState(state); + context.PushState(state, State::PeriodAsDecl); } else { context.AddLeafNode(NodeKind::IdentifierName, *identifier); } @@ -66,8 +64,7 @@ static auto HandleDeclNameAndParamsAfterName(Context& context, Params params) if (context.PositionIs(Lex::TokenKind::Period)) { // Continue designator processing. context.PushState(state); - state.state = State::PeriodAsDecl; - context.PushState(state); + context.PushState(state, State::PeriodAsDecl); return; } diff --git a/toolchain/parse/handle_decl_scope_loop.cpp b/toolchain/parse/handle_decl_scope_loop.cpp index 71b792584ad8..15053d6dfa2a 100644 --- a/toolchain/parse/handle_decl_scope_loop.cpp +++ b/toolchain/parse/handle_decl_scope_loop.cpp @@ -85,8 +85,7 @@ static auto ApplyIntroducer(Context& context, Context::StateStackEntry state, context.ReplacePlaceholderNode(state.subtree_start, introducer_kind, context.Consume()); // Reuse state here to retain its `subtree_start`. - state.state = next_state; - context.PushState(state); + context.PushState(state, next_state); } // Handles `base` as a declaration. diff --git a/toolchain/parse/handle_expr.cpp b/toolchain/parse/handle_expr.cpp index 21006a15ca39..4c99b4b09469 100644 --- a/toolchain/parse/handle_expr.cpp +++ b/toolchain/parse/handle_expr.cpp @@ -182,26 +182,22 @@ auto HandleExprInPostfixLoop(Context& context) -> void { switch (context.PositionKind()) { case Lex::TokenKind::Period: { context.PushState(state); - state.state = State::PeriodAsExpr; - context.PushState(state); + context.PushState(state, State::PeriodAsExpr); break; } case Lex::TokenKind::MinusGreater: { context.PushState(state); - state.state = State::ArrowExpr; - context.PushState(state); + context.PushState(state, State::ArrowExpr); break; } case Lex::TokenKind::OpenParen: { context.PushState(state); - state.state = State::CallExpr; - context.PushState(state); + context.PushState(state, State::CallExpr); break; } case Lex::TokenKind::OpenSquareBracket: { context.PushState(state); - state.state = State::IndexExpr; - context.PushState(state); + context.PushState(state, State::IndexExpr); break; } default: { @@ -276,8 +272,7 @@ auto HandleExprLoop(Context& context) -> void { state.subtree_start, state.has_error); } - state.state = State::ExprLoopForBinary; - context.PushState(state); + context.PushState(state, State::ExprLoopForBinary); context.PushStateForExpr(operator_precedence); } else { context.AddNode(NodeKind::PostfixOperator, state.token, state.subtree_start, @@ -292,9 +287,8 @@ auto HandleExprLoopForBinary(Context& context) -> void { context.AddNode(NodeKind::InfixOperator, state.token, state.subtree_start, state.has_error); - state.state = State::ExprLoop; state.has_error = false; - context.PushState(state); + context.PushState(state, State::ExprLoop); } auto HandleExprLoopForPrefix(Context& context) -> void { @@ -302,9 +296,8 @@ auto HandleExprLoopForPrefix(Context& context) -> void { context.AddNode(NodeKind::PrefixOperator, state.token, state.subtree_start, state.has_error); - state.state = State::ExprLoop; state.has_error = false; - context.PushState(state); + context.PushState(state, State::ExprLoop); } auto HandleIfExprFinishCondition(Context& context) -> void { diff --git a/toolchain/parse/handle_function.cpp b/toolchain/parse/handle_function.cpp index 9e3738b0a263..d1d3dd607d63 100644 --- a/toolchain/parse/handle_function.cpp +++ b/toolchain/parse/handle_function.cpp @@ -8,8 +8,7 @@ namespace Carbon::Parse { auto HandleFunctionIntroducer(Context& context) -> void { auto state = context.PopState(); - state.state = State::FunctionAfterParams; - context.PushState(state); + context.PushState(state, State::FunctionAfterParams); context.PushState(State::DeclNameAndParamsAsRequired, state.token); } @@ -17,8 +16,7 @@ auto HandleFunctionAfterParams(Context& context) -> void { auto state = context.PopState(); // Regardless of whether there's a return type, we'll finish the signature. - state.state = State::FunctionSignatureFinish; - context.PushState(state); + context.PushState(state, State::FunctionSignatureFinish); // If there is a return type, parse the expression before adding the return // type node. @@ -50,8 +48,7 @@ auto HandleFunctionSignatureFinish(Context& context) -> void { state.subtree_start, state.has_error); // Any error is recorded on the FunctionDefinitionStart. state.has_error = false; - state.state = State::FunctionDefinitionFinish; - context.PushState(state); + context.PushState(state, State::FunctionDefinitionFinish); context.PushState(State::StatementScopeLoop); break; } diff --git a/toolchain/parse/handle_index_expr.cpp b/toolchain/parse/handle_index_expr.cpp index 783e3196e31b..c6ca25a7c633 100644 --- a/toolchain/parse/handle_index_expr.cpp +++ b/toolchain/parse/handle_index_expr.cpp @@ -9,8 +9,7 @@ namespace Carbon::Parse { auto HandleIndexExpr(Context& context) -> void { auto state = context.PopState(); - state.state = State::IndexExprFinish; - context.PushState(state); + context.PushState(state, State::IndexExprFinish); context.AddNode(NodeKind::IndexExprStart, context.ConsumeChecked(Lex::TokenKind::OpenSquareBracket), state.subtree_start, state.has_error); diff --git a/toolchain/parse/handle_let.cpp b/toolchain/parse/handle_let.cpp index 73db9a8408ec..7c74678911c6 100644 --- a/toolchain/parse/handle_let.cpp +++ b/toolchain/parse/handle_let.cpp @@ -10,10 +10,8 @@ auto HandleLet(Context& context) -> void { auto state = context.PopState(); // These will start at the `let`. - state.state = State::LetFinish; - context.PushState(state); - state.state = State::LetAfterPattern; - context.PushState(state); + context.PushState(state, State::LetFinish); + context.PushState(state, State::LetAfterPattern); // This will start at the pattern. context.PushState(State::Pattern); diff --git a/toolchain/parse/handle_namespace.cpp b/toolchain/parse/handle_namespace.cpp index ed016951ad3a..3f0fe31468eb 100644 --- a/toolchain/parse/handle_namespace.cpp +++ b/toolchain/parse/handle_namespace.cpp @@ -8,9 +8,7 @@ namespace Carbon::Parse { auto HandleNamespace(Context& context) -> void { auto state = context.PopState(); - state.state = State::NamespaceFinish; - context.PushState(state); - + context.PushState(state, State::NamespaceFinish); context.PushState(State::DeclNameAndParamsAsNone, state.token); } diff --git a/toolchain/parse/handle_paren_condition.cpp b/toolchain/parse/handle_paren_condition.cpp index de94cbf9cc37..e4a587f4af37 100644 --- a/toolchain/parse/handle_paren_condition.cpp +++ b/toolchain/parse/handle_paren_condition.cpp @@ -16,8 +16,7 @@ static auto HandleParenCondition(Context& context, NodeKind start_kind, if (open_paren) { state.token = *open_paren; } - state.state = finish_state; - context.PushState(state); + context.PushState(state, finish_state); if (!open_paren && context.PositionIs(Lex::TokenKind::OpenCurlyBrace)) { // For an open curly, assume the condition was completely omitted. diff --git a/toolchain/parse/handle_paren_expr.cpp b/toolchain/parse/handle_paren_expr.cpp index 9b445380de38..35f673db588b 100644 --- a/toolchain/parse/handle_paren_expr.cpp +++ b/toolchain/parse/handle_paren_expr.cpp @@ -14,11 +14,9 @@ auto HandleParenExpr(Context& context) -> void { context.ConsumeChecked(Lex::TokenKind::OpenParen)); if (context.PositionIs(Lex::TokenKind::CloseParen)) { - state.state = State::TupleLiteralFinish; - context.PushState(state); + context.PushState(state, State::TupleLiteralFinish); } else { - state.state = State::ParenExprFinish; - context.PushState(state); + context.PushState(state, State::ParenExprFinish); context.PushState(State::ExprAfterOpenParenFinish); context.PushState(State::Expr); } @@ -37,14 +35,12 @@ auto HandleExprAfterOpenParenFinish(Context& context) -> void { auto finish_state = context.PopState(); CARBON_CHECK(finish_state.state == State::ParenExprFinish) << "Unexpected parent state, found: " << finish_state.state; - finish_state.state = State::TupleLiteralFinish; - context.PushState(finish_state); + context.PushState(finish_state, State::TupleLiteralFinish); // If the comma is not immediately followed by a close paren, push handlers // for the next tuple element. if (list_token_kind != Context::ListTokenKind::CommaClose) { - state.state = State::TupleLiteralElementFinish; - context.PushState(state); + context.PushState(state, State::TupleLiteralElementFinish); context.PushState(State::Expr); } } diff --git a/toolchain/parse/handle_statement.cpp b/toolchain/parse/handle_statement.cpp index 0791dedbbe5d..4399cbc34f17 100644 --- a/toolchain/parse/handle_statement.cpp +++ b/toolchain/parse/handle_statement.cpp @@ -120,9 +120,7 @@ auto HandleStatementForHeader(Context& context) -> void { auto HandleStatementForHeaderIn(Context& context) -> void { auto state = context.PopState(); - - state.state = State::StatementForHeaderFinish; - context.PushState(state); + context.PushState(state, State::StatementForHeaderFinish); context.PushState(State::Expr); } @@ -151,9 +149,7 @@ auto HandleStatementIf(Context& context) -> void { auto HandleStatementIfConditionFinish(Context& context) -> void { auto state = context.PopState(); - - state.state = State::StatementIfThenBlockFinish; - context.PushState(state); + context.PushState(state, State::StatementIfThenBlockFinish); context.PushState(State::CodeBlock); } @@ -162,8 +158,7 @@ auto HandleStatementIfThenBlockFinish(Context& context) -> void { if (context.ConsumeAndAddLeafNodeIf(Lex::TokenKind::Else, NodeKind::IfStatementElse)) { - state.state = State::StatementIfElseBlockFinish; - context.PushState(state); + context.PushState(state, State::StatementIfElseBlockFinish); // `else if` is permitted as a special case. context.PushState(context.PositionIs(Lex::TokenKind::If) ? State::StatementIf @@ -182,8 +177,7 @@ auto HandleStatementIfElseBlockFinish(Context& context) -> void { auto HandleStatementReturn(Context& context) -> void { auto state = context.PopState(); - state.state = State::StatementReturnFinish; - context.PushState(state); + context.PushState(state, State::StatementReturnFinish); context.AddLeafNode(NodeKind::ReturnStatementStart, context.Consume()); @@ -227,8 +221,7 @@ auto HandleStatementWhile(Context& context) -> void { auto HandleStatementWhileConditionFinish(Context& context) -> void { auto state = context.PopState(); - state.state = State::StatementWhileBlockFinish; - context.PushState(state); + context.PushState(state, State::StatementWhileBlockFinish); context.PushState(State::CodeBlock); } diff --git a/toolchain/parse/handle_type.cpp b/toolchain/parse/handle_type.cpp index 754a738a2541..964118ad8ee2 100644 --- a/toolchain/parse/handle_type.cpp +++ b/toolchain/parse/handle_type.cpp @@ -10,8 +10,7 @@ namespace Carbon::Parse { static auto HandleTypeAfterIntroducer(Context& context, State after_params_state) -> void { auto state = context.PopState(); - state.state = after_params_state; - context.PushState(state); + context.PushState(state, after_params_state); context.PushState(State::DeclNameAndParamsAsOptional, state.token); } @@ -53,8 +52,7 @@ static auto HandleTypeAfterParams(Context& context, NodeKind decl_kind, return; } - state.state = definition_finish_state; - context.PushState(state); + context.PushState(state, definition_finish_state); context.PushState(State::DeclScopeLoop); context.AddNode(definition_start_kind, context.Consume(), state.subtree_start, state.has_error); diff --git a/toolchain/parse/handle_var.cpp b/toolchain/parse/handle_var.cpp index e3de77dd8503..a8e9ba0a2090 100644 --- a/toolchain/parse/handle_var.cpp +++ b/toolchain/parse/handle_var.cpp @@ -13,11 +13,9 @@ static auto HandleVar(Context& context, State finish_state, auto state = context.PopState(); // The finished variable declaration will start at the `var` or `returned`. - state.state = finish_state; - context.PushState(state); + context.PushState(state, finish_state); - state.state = State::VarAfterPattern; - context.PushState(state); + context.PushState(state, State::VarAfterPattern); if (returned_token.is_valid()) { context.AddLeafNode(NodeKind::ReturnedModifier, returned_token);