[parser] More support for interfaces: methods and self deduced param. (#2427)

Summary:

Extends the current support for parsing `interface`s. In particular, adds support for parsing functions and `me` params.
This commit is contained in:
Kareem Ergawy
2022-12-16 11:23:02 -08:00
committed by GitHub
parent 63487da665
commit c74e39dbb3
12 changed files with 494 additions and 59 deletions
+140 -3
View File
@@ -88,7 +88,8 @@ Parser::Parser(ParseTree& tree, TokenizedBuffer& tokens,
emitter_(&emitter),
vlog_stream_(vlog_stream),
position_(tokens_->tokens().begin()),
end_(tokens_->tokens().end()) {
end_(tokens_->tokens().end()),
stack_context_(ParseContext::File) {
CARBON_CHECK(position_ != end_) << "Empty TokenizedBuffer";
--end_;
CARBON_CHECK(tokens_->GetKind(*end_) == TokenKind::EndOfFile())
@@ -852,6 +853,11 @@ auto Parser::HandleExpressionInPostfixState() -> void {
PushState(ParserState::ParenExpression());
break;
}
case TokenKind::SelfType(): {
AddLeafNode(ParseNodeKind::SelfType(), Consume());
PushState(state);
break;
}
default: {
CARBON_DIAGNOSTIC(ExpectedExpression, Error, "Expected expression.");
emitter_->Emit(*position_, ExpectedExpression);
@@ -1015,6 +1021,41 @@ auto Parser::HandleFunctionIntroducerState() -> void {
return;
}
state.state = ParserState::FunctionAfterDeducedParameterList();
PushState(state);
// If there are deduced params handle them next.
if (PositionIs(TokenKind::OpenSquareBracket())) {
PushState(ParserState::DeducedParameterListFinish());
// This is for sure a `[`, we can safely create the corresponding node.
AddLeafNode(ParseNodeKind::DeducedParameterListStart(), Consume());
if (PositionIs(TokenKind::CloseSquareBracket())) {
return;
}
// TODO: For now only `self` is supported. When other types of deduced
// parameters need to be added, we will probably need to push a more
// general state.
// Push state to handle `self`'s pattern binding.
PushState(ParserState::SelfPattern());
return;
}
}
auto Parser::HandleDeducedParameterListFinishState() -> void {
auto state = PopState();
CARBON_CHECK(tokens_->GetKind(*position_) == TokenKind::CloseSquareBracket())
<< "Expected current token to be: `]`, found: "
<< tokens_->GetKind(state.token);
AddNode(ParseNodeKind::DeducedParameterList(), Consume(), state.subtree_start,
state.has_error);
}
auto Parser::HandleFunctionAfterDeducedParameterListState() -> void {
auto state = PopState();
if (!PositionIs(TokenKind::OpenParen())) {
CARBON_DIAGNOSTIC(ExpectedFunctionParams, Error,
"Expected `(` after function name.");
@@ -1029,6 +1070,7 @@ auto Parser::HandleFunctionIntroducerState() -> void {
PushState(state);
PushState(ParserState::FunctionParameterListFinish());
AddLeafNode(ParseNodeKind::ParameterListStart(), Consume());
if (!PositionIs(TokenKind::CloseParen())) {
PushState(ParserState::FunctionParameter());
}
@@ -1096,6 +1138,15 @@ auto Parser::HandleFunctionSignatureFinishState() -> void {
break;
}
case TokenKind::OpenCurlyBrace(): {
if (stack_context_ == ParseContext::Interface) {
CARBON_DIAGNOSTIC(
MethodImplNotAllowed, Error,
"Method implementations are not allowed in interfaces.");
emitter_->Emit(*position_, MethodImplNotAllowed);
HandleFunctionError(state, /*skip_past_likely_end=*/true);
break;
}
AddNode(ParseNodeKind::FunctionDefinitionStart(), Consume(),
state.subtree_start, state.has_error);
// Any error is recorded on the FunctionDefinitionStart.
@@ -1307,13 +1358,78 @@ auto Parser::HandleParenExpressionFinishAsTupleState() -> void {
state.has_error);
}
// TODO: This can possibly be merged with `HandlePattern`. Regular function
// parameters support `addr` as well but it is not implemented yet.
auto Parser::HandleSelfPatternState() -> void {
auto state = PopState();
// self `:` type
auto possible_self_param =
(PositionIs(TokenKind::SelfParameter()) &&
tokens_->GetKind(*(position_ + 1)) == TokenKind::Colon());
if (possible_self_param) {
// Ensure the finish state always follows.
state.state = ParserState::PatternFinish();
// Switch the context token to the colon, so that it'll be used for the root
// node.
state.token = *(position_ + 1);
PushState(state);
PushStateForExpression(PrecedenceGroup::ForType());
AddLeafNode(ParseNodeKind::SelfDeducedParameter(), *position_);
position_ += 2;
return;
}
// addr self `:` type
auto possible_addr_self_param =
(PositionIs(TokenKind::Addr()) &&
tokens_->GetKind(*(position_ + 1)) == TokenKind::SelfParameter() &&
tokens_->GetKind(*(position_ + 2)) == TokenKind::Colon());
if (possible_addr_self_param) {
// Ensure the finish state always follows.
state.state = ParserState::PatternAddress();
state.token = Consume();
PushState(state);
PushState(ParserState::PatternFinish());
PushStateForExpression(PrecedenceGroup::ForType());
// auto size = tree_->size();
// AddLeafNode(ParseNodeKind::Address(), *position_);
AddLeafNode(ParseNodeKind::SelfDeducedParameter(), *(position_ + 1));
// AddNode(ParseNodeKind::SelfDeducedParameterAddress(), *(position_ + 1),
// size, false);
position_ += 2;
return;
}
CARBON_DIAGNOSTIC(ExpectedDeducedParam, Error,
"Deduced parameters must be of the form: `<name>: <Type>` "
"or `addr <name>: <Type>`.");
emitter_->Emit(*position_, ExpectedDeducedParam);
state.state = ParserState::PatternFinish();
state.has_error = true;
// Try to recover by skipping to the next `]`.
if (auto next_close_square_bracket =
FindNextOf({TokenKind::CloseSquareBracket()});
next_close_square_bracket) {
SkipTo(*next_close_square_bracket);
}
PushState(state);
}
auto Parser::HandlePattern(PatternKind pattern_kind) -> void {
auto state = PopState();
// Ensure the finish state always follows.
state.state = ParserState::PatternFinish();
// Handle an invalid pattern introducer.
// Handle an invalid pattern introducer for parameters and variables.
if (!PositionIs(TokenKind::Identifier()) ||
tokens_->GetKind(*(position_ + 1)) != TokenKind::Colon()) {
switch (pattern_kind) {
@@ -1366,6 +1482,19 @@ auto Parser::HandlePatternFinishState() -> void {
/*has_error=*/false);
}
auto Parser::HandlePatternAddressState() -> void {
auto state = PopState();
// If an error was encountered, propagate it without adding a node.
if (state.has_error) {
ReturnErrorOnState();
return;
}
AddNode(ParseNodeKind::Address(), state.token, state.subtree_start,
/*has_error=*/false);
}
auto Parser::HandleStatementState() -> void {
PopAndDiscardState();
@@ -1662,6 +1791,9 @@ auto Parser::HandleVarFinishAsForState() -> 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())) {
@@ -1711,7 +1843,11 @@ auto Parser::HandleInterfaceDefinitionLoopState() -> void {
break;
}
// TODO: Handle possible declarations inside interface body.
case TokenKind::Fn(): {
PushState(ParserState::FunctionIntroducer());
AddLeafNode(ParseNodeKind::FunctionIntroducer(), Consume());
break;
}
default: {
CARBON_DIAGNOSTIC(UnrecognizedDeclaration, Error,
"Unrecognized declaration introducer.");
@@ -1731,6 +1867,7 @@ auto Parser::HandleInterfaceDefinitionFinishState() -> void {
auto state = PopState();
AddNode(ParseNodeKind::InterfaceDefinition(), state.token,
state.subtree_start, state.has_error);
stack_context_ = ParseContext::File;
}
} // namespace Carbon