diff --git a/parser/parse_node_kind.def b/parser/parse_node_kind.def index f25da9ec1311..030de307b902 100644 --- a/parser/parse_node_kind.def +++ b/parser/parse_node_kind.def @@ -22,6 +22,7 @@ CARBON_PARSE_NODE_KIND(ParameterList) CARBON_PARSE_NODE_KIND(ParameterListComma) CARBON_PARSE_NODE_KIND(ParameterListEnd) CARBON_PARSE_NODE_KIND(ParameterDeclaration) +CARBON_PARSE_NODE_KIND(ReturnType) CARBON_PARSE_NODE_KIND(VariableDeclaration) CARBON_PARSE_NODE_KIND(VariableInitializer) CARBON_PARSE_NODE_KIND(FileEnd) diff --git a/parser/parse_tree_test.cpp b/parser/parse_tree_test.cpp index 1437d1aba716..580131f1e6d6 100644 --- a/parser/parse_tree_test.cpp +++ b/parser/parse_tree_test.cpp @@ -196,6 +196,37 @@ TEST_F(ParseTreeTest, FunctionDefinitionWithParameterList) { MatchFileEnd()})); } +TEST_F(ParseTreeTest, FunctionDeclarationWithReturnType) { + TokenizedBuffer tokens = GetTokenizedBuffer("fn foo() -> Int;"); + ParseTree tree = ParseTree::Parse(tokens, consumer); + EXPECT_FALSE(tree.HasErrors()); + EXPECT_THAT( + tree, + MatchParseTreeNodes( + {MatchFunctionDeclaration(MatchDeclaredName("foo"), MatchParameters(), + MatchReturnType(MatchNameReference("Int")), + MatchDeclarationEnd()), + MatchFileEnd()})); +} + +TEST_F(ParseTreeTest, FunctionDefinitionWithReturnType) { + TokenizedBuffer tokens = GetTokenizedBuffer( + "fn foo() -> Int {\n" + " // return 42;\n" + "}"); + ParseTree tree = ParseTree::Parse(tokens, consumer); + EXPECT_FALSE(tree.HasErrors()); + EXPECT_THAT( + tree, + MatchParseTreeNodes( + {MatchFunctionDeclaration(MatchDeclaredName("foo"), MatchParameters(), + MatchReturnType(MatchNameReference("Int")), + MatchCodeBlock( + // TODO: Match a return statement. + MatchCodeBlockEnd())), + MatchFileEnd()})); +} + TEST_F(ParseTreeTest, FunctionDeclarationWithSingleIdentifierParameterList) { TokenizedBuffer tokens = GetTokenizedBuffer("fn foo(bar);"); ParseTree tree = ParseTree::Parse(tokens, consumer); diff --git a/parser/parser_impl.cpp b/parser/parser_impl.cpp index 73033b600794..a6e78cfae9f3 100644 --- a/parser/parser_impl.cpp +++ b/parser/parser_impl.cpp @@ -413,7 +413,15 @@ auto ParseTree::Parser::ParseFunctionSignature() -> bool { has_errors); }); - // FIXME: Implement parsing of a return type. + auto start_return_type = StartSubtree(); + if (auto arrow = ConsumeIf(TokenKind::MinusGreater())) { + auto return_type = ParseType(); + AddNode(ParseNodeKind::ReturnType(), *arrow, start_return_type, + /*has_error=*/!return_type); + if (!return_type) { + return false; + } + } return params.hasValue(); } @@ -478,11 +486,7 @@ auto ParseTree::Parser::ParseFunctionDeclaration() -> Node { TokenizedBuffer::Token close_paren = tokens.GetMatchedClosingToken(open_paren); - bool signature_ok = ParseFunctionSignature(); - assert(*std::prev(position) == close_paren && - "Should have parsed through the close paren, whether successfully " - "or with errors."); - if (!signature_ok) { + if (!ParseFunctionSignature()) { // Don't try to parse more of the function declaration, but consume a // declaration ending semicolon if found (without going to a new line). SkipPastLikelyEnd(function_intro_token, handle_semi_in_error_recovery);