mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 22:02:55 +01:00
[parser] Start re-implementing interfaces using the stack parser. (#2412)
First change towards re-implementing interfaces using the new parser. I kept it small to make sure we are on the same page regarding stack states and how the parse tree should look like. Co-authored-by: ergawy <kareem.ergawy@guardsquare.com>
This commit is contained in:
@@ -78,6 +78,10 @@ CARBON_DIAGNOSTIC_KIND(ExpectedSemiToEndPackageDirective)
|
||||
// For-specific diagnostics
|
||||
CARBON_DIAGNOSTIC_KIND(ExpectedIn)
|
||||
|
||||
// Interface-specific diagnostics
|
||||
CARBON_DIAGNOSTIC_KIND(ExpectedInterfaceName)
|
||||
CARBON_DIAGNOSTIC_KIND(ExpectedInterfaceOpenCurlyBrace)
|
||||
|
||||
// ============================================================================
|
||||
// Semantics diagnostics
|
||||
// ============================================================================
|
||||
|
||||
@@ -113,6 +113,11 @@ CARBON_PARSE_NODE_KIND_CHILD_COUNT(StructFieldValue, TodoFixParseNode)
|
||||
CARBON_PARSE_NODE_KIND_CHILD_COUNT(StructFieldType, TodoFixParseNode)
|
||||
CARBON_PARSE_NODE_KIND_CHILD_COUNT(StructComma, 0)
|
||||
|
||||
// Interfaces
|
||||
CARBON_PARSE_NODE_KIND_CHILD_COUNT(InterfaceDefinition, TodoFixParseNode)
|
||||
CARBON_PARSE_NODE_KIND_CHILD_COUNT(InterfaceBodyStart, 0)
|
||||
CARBON_PARSE_NODE_KIND_BRACKET(InterfaceBody, InterfaceBodyStart)
|
||||
|
||||
#undef CARBON_PARSE_NODE_KIND
|
||||
#undef CARBON_PARSE_NODE_KIND_BRACKET
|
||||
#undef CARBON_PARSE_NODE_KIND_CHILD_COUNT
|
||||
|
||||
@@ -701,6 +701,11 @@ auto Parser::HandleDeclarationLoopState() -> void {
|
||||
PushState(ParserState::VarAsRequireSemicolon());
|
||||
break;
|
||||
}
|
||||
case TokenKind::Interface(): {
|
||||
PushState(ParserState::InterfaceIntroducer());
|
||||
++position_;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
CARBON_DIAGNOSTIC(UnrecognizedDeclaration, Error,
|
||||
"Unrecognized declaration introducer.");
|
||||
@@ -1658,4 +1663,71 @@ auto Parser::HandleVarFinishAsNoSemicolonState() -> void {
|
||||
HandleVarFinish(/*require_semicolon=*/false);
|
||||
}
|
||||
|
||||
auto Parser::HandleInterfaceIntroducerState() -> void {
|
||||
auto state = PopState();
|
||||
|
||||
if (!ConsumeAndAddLeafNodeIf(TokenKind::Identifier(),
|
||||
ParseNodeKind::DeclaredName())) {
|
||||
CARBON_DIAGNOSTIC(ExpectedInterfaceName, Error,
|
||||
"Expected interface name after `interface` keyword.");
|
||||
emitter_->Emit(*position_, ExpectedInterfaceName);
|
||||
state.has_error = true;
|
||||
}
|
||||
|
||||
bool parse_body = true;
|
||||
|
||||
if (!PositionIs(TokenKind::OpenCurlyBrace())) {
|
||||
CARBON_DIAGNOSTIC(ExpectedInterfaceOpenCurlyBrace, Error,
|
||||
"Expected `{{` to start interface definition.");
|
||||
emitter_->Emit(*position_, ExpectedInterfaceOpenCurlyBrace);
|
||||
state.has_error = true;
|
||||
|
||||
SkipPastLikelyEnd(state.token);
|
||||
parse_body = false;
|
||||
}
|
||||
|
||||
state.state = ParserState::InterfaceDefinitionFinish();
|
||||
PushState(state);
|
||||
|
||||
if (parse_body) {
|
||||
PushState(ParserState::InterfaceDefinitionLoop());
|
||||
AddLeafNode(ParseNodeKind::InterfaceBodyStart(), Consume());
|
||||
}
|
||||
}
|
||||
|
||||
auto Parser::HandleInterfaceDefinitionLoopState() -> void {
|
||||
// This maintains the current state unless we're at the end of the interface
|
||||
// definition.
|
||||
|
||||
switch (PositionKind()) {
|
||||
case TokenKind::CloseCurlyBrace(): {
|
||||
auto state = PopState();
|
||||
|
||||
AddNode(ParseNodeKind::InterfaceBody(), Consume(), state.subtree_start,
|
||||
state.has_error);
|
||||
|
||||
break;
|
||||
}
|
||||
// TODO: Handle possible declarations inside interface body.
|
||||
default: {
|
||||
CARBON_DIAGNOSTIC(UnrecognizedDeclaration, Error,
|
||||
"Unrecognized declaration introducer.");
|
||||
emitter_->Emit(*position_, UnrecognizedDeclaration);
|
||||
if (auto semi = SkipPastLikelyEnd(*position_)) {
|
||||
AddLeafNode(ParseNodeKind::EmptyDeclaration(), *semi,
|
||||
/*has_error=*/true);
|
||||
} else {
|
||||
ReturnErrorOnState();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto Parser::HandleInterfaceDefinitionFinishState() -> void {
|
||||
auto state = PopState();
|
||||
AddNode(ParseNodeKind::InterfaceDefinition(), state.token,
|
||||
state.subtree_start, state.has_error);
|
||||
}
|
||||
|
||||
} // namespace Carbon
|
||||
|
||||
@@ -123,6 +123,9 @@ CARBON_PARSER_STATE(CodeBlockFinish)
|
||||
// If `Var`:
|
||||
// 1. Var
|
||||
// 2. DeclarationLoop
|
||||
// If `interface`:
|
||||
// 1. InterfaceIntroducer
|
||||
// 2. DeclarationLoop
|
||||
// Else:
|
||||
// 1. DeclarationLoop
|
||||
CARBON_PARSER_STATE(DeclarationLoop)
|
||||
@@ -276,6 +279,31 @@ CARBON_PARSER_STATE(FunctionSignatureFinish)
|
||||
// (state done)
|
||||
CARBON_PARSER_STATE(FunctionDefinitionFinish)
|
||||
|
||||
// Finishes an interface definition.
|
||||
//
|
||||
// Always:
|
||||
// (state done)
|
||||
CARBON_PARSER_STATE(InterfaceDefinitionFinish)
|
||||
|
||||
// Handles parsing the body of an interface.
|
||||
//
|
||||
// If `}`:
|
||||
// (state done)
|
||||
// Else:
|
||||
// 1. InterfaceDefinitionLoop
|
||||
CARBON_PARSER_STATE(InterfaceDefinitionLoop)
|
||||
|
||||
// Handles processing of a intefaces's `interface <name> {`.
|
||||
//
|
||||
// If invalid:
|
||||
// 1. InterfaceDefinitionFinish
|
||||
// If `{` is missing:
|
||||
// 1. InterfaceDefinitionFinish
|
||||
// Else:
|
||||
// 1. InterfaceDefinitionLoop
|
||||
// 2. InterfaceDefinitionFinish
|
||||
CARBON_PARSER_STATE(InterfaceIntroducer)
|
||||
|
||||
// Handles `package`.
|
||||
//
|
||||
// Always:
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
// 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
|
||||
// RUN: %{carbon-run-parser}
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'foo'},
|
||||
// CHECK:STDOUT: {kind: 'InterfaceBodyStart', text: '{'},
|
||||
// CHECK:STDOUT: {kind: 'InterfaceBody', text: '}', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'InterfaceDefinition', text: 'interface', subtree_size: 4},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
// CHECK:STDOUT: ]
|
||||
interface foo {
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
// 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
|
||||
// RUN: %{not} %{carbon-run-parser}
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: {kind: 'InterfaceBodyStart', text: '{'},
|
||||
// CHECK:STDOUT: {kind: 'InterfaceBody', text: '}', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'InterfaceDefinition', text: 'interface', has_error: yes, subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
// CHECK:STDOUT: ]
|
||||
|
||||
// CHECK:STDERR: {{.*}}/toolchain/parser/testdata/generics/interface/fail_missing_name.carbon:[[@LINE+1]]:11: Expected interface name after `interface` keyword.
|
||||
interface {
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// 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
|
||||
// RUN: %{not} %{carbon-run-parser}
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'bar'},
|
||||
// CHECK:STDOUT: {kind: 'InterfaceDefinition', text: 'interface', has_error: yes, subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'foo'},
|
||||
// CHECK:STDOUT: {kind: 'InterfaceDefinition', text: 'interface', has_error: yes, subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
// CHECK:STDOUT: ]
|
||||
|
||||
// CHECK:STDERR: {{.*}}/toolchain/parser/testdata/generics/interface/fail_missing_open_curly.carbon:[[@LINE+1]]:15: Expected `{` to start interface definition.
|
||||
interface bar baz {}
|
||||
|
||||
// CHECK:STDERR: {{.*}}/toolchain/parser/testdata/generics/interface/fail_missing_open_curly.carbon:[[@LINE+1]]:14: Expected `{` to start interface definition.
|
||||
interface foo
|
||||
Reference in New Issue
Block a user