Refactor state construction and change how the decl loop makes state. (#3467)

Building on #3463. The PushState+PopState to construct a state feels
worth cleanup. The rest is just kind of making it easier to do without
adding another PushState overload.
This commit is contained in:
Jon Ross-Perkins
2023-12-08 17:29:23 +00:00
committed by GitHub
parent 3b0923c81d
commit 50071532fe
5 changed files with 62 additions and 58 deletions
+31 -26
View File
@@ -77,6 +77,18 @@ static auto HandleUnrecognizedDecl(Context& context, int32_t subtree_start)
FinishAndSkipInvalidDecl(context, subtree_start);
}
// Replaces the introducer placeholder node, and pushes the introducer state for
// processing.
static auto ApplyIntroducer(Context& context, Context::StateStackEntry state,
NodeKind introducer_kind, State next_state)
-> void {
context.ReplacePlaceholderNode(state.subtree_start, introducer_kind,
context.Consume());
// Reuse state here to retain its `subtree_start`.
state.state = next_state;
context.PushState(state);
}
// Handles `base` as a declaration.
static auto HandleBaseAsDecl(Context& context, Context::StateStackEntry state)
-> void {
@@ -84,11 +96,7 @@ static auto HandleBaseAsDecl(Context& context, Context::StateStackEntry state)
// it's followed by a colon, it's an introducer (`extend base: BaseType;`).
// Otherwise it's an error.
if (context.PositionIs(Lex::TokenKind::Colon, Lookahead::NextToken)) {
context.ReplacePlaceholderNode(state.subtree_start,
NodeKind::BaseIntroducer, context.Consume());
// Reuse state here to retain its `subtree_start`
state.state = State::BaseDecl;
context.PushState(state);
ApplyIntroducer(context, state, NodeKind::BaseIntroducer, State::BaseDecl);
context.PushState(State::Expr);
context.AddLeafNode(NodeKind::BaseColon, context.Consume());
} else {
@@ -109,26 +117,19 @@ static auto HandleBaseAsDecl(Context& context, Context::StateStackEntry state)
// to a state to parse the rest of the declaration.
static auto TryHandleAsDecl(Context& context, Context::StateStackEntry state,
bool saw_modifier) -> bool {
auto introducer = [&](NodeKind node_kind, State next_state) {
context.ReplacePlaceholderNode(state.subtree_start, node_kind,
context.Consume());
// Reuse state here to retain its `subtree_start`.
state.state = next_state;
context.PushState(state);
};
switch (context.PositionKind()) {
case Lex::TokenKind::Base: {
HandleBaseAsDecl(context, state);
return true;
}
case Lex::TokenKind::Class: {
introducer(NodeKind::ClassIntroducer, State::TypeAfterIntroducerAsClass);
ApplyIntroducer(context, state, NodeKind::ClassIntroducer,
State::TypeAfterIntroducerAsClass);
return true;
}
case Lex::TokenKind::Constraint: {
introducer(NodeKind::NamedConstraintIntroducer,
State::TypeAfterIntroducerAsNamedConstraint);
ApplyIntroducer(context, state, NodeKind::NamedConstraintIntroducer,
State::TypeAfterIntroducerAsNamedConstraint);
return true;
}
case Lex::TokenKind::Extend: {
@@ -137,7 +138,8 @@ static auto TryHandleAsDecl(Context& context, Context::StateStackEntry state,
return true;
}
case Lex::TokenKind::Fn: {
introducer(NodeKind::FunctionIntroducer, State::FunctionIntroducer);
ApplyIntroducer(context, state, NodeKind::FunctionIntroducer,
State::FunctionIntroducer);
return true;
}
case Lex::TokenKind::Impl: {
@@ -146,20 +148,22 @@ static auto TryHandleAsDecl(Context& context, Context::StateStackEntry state,
return true;
}
case Lex::TokenKind::Interface: {
introducer(NodeKind::InterfaceIntroducer,
State::TypeAfterIntroducerAsInterface);
ApplyIntroducer(context, state, NodeKind::InterfaceIntroducer,
State::TypeAfterIntroducerAsInterface);
return true;
}
case Lex::TokenKind::Namespace: {
introducer(NodeKind::NamespaceStart, State::Namespace);
ApplyIntroducer(context, state, NodeKind::NamespaceStart,
State::Namespace);
return true;
}
case Lex::TokenKind::Let: {
introducer(NodeKind::LetIntroducer, State::Let);
ApplyIntroducer(context, state, NodeKind::LetIntroducer, State::Let);
return true;
}
case Lex::TokenKind::Var: {
introducer(NodeKind::VariableIntroducer, State::VarAsDecl);
ApplyIntroducer(context, state, NodeKind::VariableIntroducer,
State::VarAsDecl);
return true;
}
@@ -243,10 +247,11 @@ auto HandleDeclScopeLoop(Context& context) -> void {
return;
}
// Create a state with the correct starting position, with a dummy kind until
// we see the declaration's introducer.
context.PushState(State::DeclScopeLoop);
auto state = context.PopState();
// Create a state with the correct starting position, with a dummy kind
// until we see the declaration's introducer.
Context::StateStackEntry state{.state = State::Invalid,
.token = *context.position(),
.subtree_start = context.tree().size()};
// Add a placeholder node, to be replaced by the declaration introducer once
// it is found.