Replace ParseContext with an examination of state_stack_. (#2645)

Per [discussion](https://discord.com/channels/655572317891461132/655578254970716160/1078427629427904563), there's a preference for having the support this enables in the parser. For example, that the parser should detect and error on a non-default interface function's definition.

However, we do need to handle nesting of declarations. We could do that by making this a stack. I think though that it'll be more efficient to keep using state_stack_, since it'll be called in places which are a limited number of steps from the actual state. That may already be in cache since we frequently look at state_stack_, so I'm uncertain that maintaining an additional stack would be a net benefit.
This commit is contained in:
Jon Ross-Perkins
2023-03-06 15:09:48 -08:00
committed by GitHub
parent 4e9e43a109
commit 28327a00a9
2 changed files with 25 additions and 13 deletions
+17 -7
View File
@@ -91,8 +91,7 @@ Parser::Parser(ParseTree& tree, TokenizedBuffer& tokens,
emitter_(&emitter),
vlog_stream_(vlog_stream),
position_(tokens_->tokens().begin()),
end_(tokens_->tokens().end()),
stack_context_(ParseContext::File) {
end_(tokens_->tokens().end()) {
CARBON_CHECK(position_ != end_) << "Empty TokenizedBuffer";
--end_;
CARBON_CHECK(tokens_->GetKind(*end_) == TokenKind::EndOfFile)
@@ -451,6 +450,21 @@ auto Parser::Parse() -> void {
AddLeafNode(ParseNodeKind::FileEnd, *position_);
}
auto Parser::GetDeclarationContext() -> DeclarationContext {
for (auto entry : llvm::reverse(state_stack_)) {
switch (entry.state) {
case ParserState::InterfaceDefinitionLoop:
return DeclarationContext::Interface;
case ParserState::DeclarationLoop:
return DeclarationContext::File;
default:
// Continue checking.
break;
}
}
llvm_unreachable("Should always be able to find DeclarationLoop");
}
auto Parser::HandleBraceExpressionState() -> void {
auto state = PopState();
@@ -1135,7 +1149,7 @@ auto Parser::HandleFunctionSignatureFinishState() -> void {
break;
}
case TokenKind::OpenCurlyBrace: {
if (stack_context_ == ParseContext::Interface) {
if (GetDeclarationContext() == DeclarationContext::Interface) {
CARBON_DIAGNOSTIC(
MethodImplNotAllowed, Error,
"Method implementations are not allowed in interfaces.");
@@ -1175,9 +1189,6 @@ auto Parser::HandleFunctionDefinitionFinishState() -> void {
auto Parser::HandleInterfaceIntroducerState() -> void {
auto state = PopState();
CARBON_CHECK(stack_context_ == ParseContext::File)
<< "TODO: Support nesting.";
stack_context_ = ParseContext::Interface;
if (!ConsumeAndAddLeafNodeIf(TokenKind::Identifier,
ParseNodeKind::DeclaredName)) {
@@ -1249,7 +1260,6 @@ auto Parser::HandleInterfaceDefinitionFinishState() -> void {
auto state = PopState();
AddNode(ParseNodeKind::InterfaceDefinition, state.token, state.subtree_start,
state.has_error);
stack_context_ = ParseContext::File;
}
auto Parser::HandlePackageState() -> void {