From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1643) id E069A3858C27; Wed, 15 Jun 2022 07:00:42 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org E069A3858C27 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Thomas Schwinge To: gcc-cvs@gcc.gnu.org Subject: [gcc/devel/rust/master] parser: Refactor generic parameter parsing X-Act-Checkin: gcc X-Git-Author: Arthur Cohen X-Git-Refname: refs/heads/devel/rust/master X-Git-Oldrev: 1c679d7f42834a72956d6fb39c8d298dd6dc4b4e X-Git-Newrev: 2fe0a4da436b928900220c84c24fd5955df58dae Message-Id: <20220615070042.E069A3858C27@sourceware.org> Date: Wed, 15 Jun 2022 07:00:42 +0000 (GMT) X-BeenThere: gcc-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 15 Jun 2022 07:00:43 -0000 https://gcc.gnu.org/g:2fe0a4da436b928900220c84c24fd5955df58dae commit 2fe0a4da436b928900220c84c24fd5955df58dae Author: Arthur Cohen Date: Tue Jun 14 11:38:08 2022 +0200 parser: Refactor generic parameter parsing This allows us to parse lifetimes and types (and later const generics) in any order without necessarily erroring out. It also simplifies the code greatly and makes it easier to modify. Finally, this commit removes an unused duplicate parse_generic_params function Diff: --- gcc/rust/parse/rust-parse-impl.h | 389 ++++++++------------------------------- gcc/rust/parse/rust-parse.h | 4 +- 2 files changed, 77 insertions(+), 316 deletions(-) diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 0fc1c1fe3ac..0fd381c7b72 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -2793,197 +2793,87 @@ Parser::parse_generic_params_in_angles () return generic_params; } -/* Parse generic (lifetime or type) params NOT INSIDE ANGLE BRACKETS!!! Almost - * always parse_generic_params_in_angles is what is wanted. */ template -std::vector> -Parser::parse_generic_params () +template +std::unique_ptr +Parser::parse_generic_param (EndTokenPred is_end_token) { - std::vector> generic_params; - - // can't parse lifetime and type params separately due to lookahead issues - // thus, parse them all here + auto token = lexer.peek_token (); + auto outer_attrs = parse_outer_attribute (); + std::unique_ptr param; - // DEBUG - rust_debug ("starting to parse generic params (inside angle brackets)"); - - /* HACK: used to retain attribute data if a lifetime param is tentatively - * parsed but it turns out to be type param */ - AST::Attribute parsed_outer_attr = AST::Attribute::create_empty (); - - /* HACK: generic params always in angle brackets with current syntax, so have - * that as end char */ - const_TokenPtr t = lexer.peek_token (); - // parse lifetime params - while (!is_right_angle_tok (t->get_id ())) - { - // HACK: reimpl of lifetime param parsing - AST::Attribute outer_attr = parse_outer_attribute (); - - // move attribute outward if type param - if (lexer.peek_token ()->get_id () != LIFETIME) - { - parsed_outer_attr = std::move (outer_attr); - - // DEBUG - rust_debug ( - "broke from parsing lifetime params as next token isn't lifetime - " - "saved attribute"); - - break; - } - - Location locus = lexer.peek_token ()->get_locus (); - AST::Lifetime lifetime = parse_lifetime (); - - // DEBUG - rust_debug ("parsed lifetime in lifetime params"); - - // parse optional bounds - std::vector lifetime_bounds; - if (lexer.peek_token ()->get_id () == COLON) - { - lexer.skip_token (); - // parse required bounds - lifetime_bounds = parse_lifetime_bounds ( - [] (TokenId id) { return is_right_angle_tok (id) || id == COMMA; }); - } - - std::unique_ptr param ( - new AST::LifetimeParam (std::move (lifetime), - std::move (lifetime_bounds), - std::move (outer_attr), locus)); - generic_params.push_back (std::move (param)); - - if (lexer.peek_token ()->get_id () != COMMA) - { - break; - } - lexer.skip_token (); - - t = lexer.peek_token (); - } - - // parse type params (reimpl required for first one but not others) - if (!is_right_angle_tok (lexer.peek_token ()->get_id ()) - && !parsed_outer_attr.is_empty ()) + switch (token->get_id ()) { - // DEBUG - rust_debug ("as parsed outer attr isn't empty, started parsing type " - "param reimpl"); - - // reimpl as type param definitely exists - const_TokenPtr ident_tok = expect_token (IDENTIFIER); - if (ident_tok == nullptr) - { - Error error ( - lexer.peek_token ()->get_locus (), - "failed to parse identifier in type param in generic params"); - add_error (std::move (error)); - - return std::vector> (); - } - Identifier ident = ident_tok->get_str (); - - // parse optional bounds - std::vector> type_param_bounds; - if (lexer.peek_token ()->get_id () == COLON) - { - lexer.skip_token (); - - // parse optional type param bounds - type_param_bounds = parse_type_param_bounds (); - } - - // parse optional type - std::unique_ptr type = nullptr; - if (lexer.peek_token ()->get_id () == EQUAL) - { - lexer.skip_token (); - - // parse required type - type = parse_type (); - if (type == nullptr) - { - Error error ( - lexer.peek_token ()->get_locus (), - "failed to parse type in type param in generic params"); - add_error (std::move (error)); - - return std::vector> (); - } - } - - std::unique_ptr param ( - new AST::TypeParam (std::move (ident), ident_tok->get_locus (), - std::move (type_param_bounds), std::move (type), - std::move (parsed_outer_attr))); - generic_params.push_back (std::move (param)); - - // handle comma - if (lexer.peek_token ()->get_id () == COMMA) - { - lexer.skip_token (); - } - } - - // DEBUG - rust_debug ( - "about to start parsing normally-parsed type params in generic params"); + case LIFETIME: { + auto lifetime = parse_lifetime (); + if (lifetime.is_error ()) + { + rust_error_at ( + token->get_locus (), + "failed to parse lifetime in generic parameter list"); + return nullptr; + } - // parse rest of type params - reimpl due to right angle tokens - t = lexer.peek_token (); - while (!is_right_angle_tok (t->get_id ())) - { - std::unique_ptr type_param = parse_type_param (); + std::vector lifetime_bounds; + if (lexer.peek_token ()->get_id () == COLON) + { + lexer.skip_token (); + // parse required bounds + lifetime_bounds + = parse_lifetime_bounds ([is_end_token] (TokenId id) { + return is_end_token (id) || id == COMMA; + }); + } - if (type_param == nullptr) - { - Error error (lexer.peek_token ()->get_locus (), - "failed to parse type param in generic params"); - add_error (std::move (error)); + param = std::unique_ptr (new AST::LifetimeParam ( + std::move (lifetime), std::move (lifetime_bounds), + std::move (outer_attrs), token->get_locus ())); + break; + } + case IDENTIFIER: { + auto type_ident = token->get_str (); + lexer.skip_token (); - return std::vector> (); - } + std::vector> type_param_bounds; + if (lexer.peek_token ()->get_id () == COLON) + { + lexer.skip_token (); - // DEBUG - rust_debug ("successfully parsed type param"); + // parse optional type param bounds + type_param_bounds = parse_type_param_bounds (); + } - generic_params.push_back (std::move (type_param)); + std::unique_ptr type = nullptr; + if (lexer.peek_token ()->get_id () == EQUAL) + { + lexer.skip_token (); - if (lexer.peek_token ()->get_id () != COMMA) - { - break; - } - // skip commas, including trailing commas - lexer.skip_token (); + // parse required type + type = parse_type (); + if (!type) + { + rust_error_at ( + lexer.peek_token ()->get_locus (), + "failed to parse type in type param in generic params"); + return nullptr; + } + } - t = lexer.peek_token (); + param = std::unique_ptr ( + new AST::TypeParam (std::move (type_ident), token->get_locus (), + std::move (type_param_bounds), std::move (type), + std::move (outer_attrs))); + break; + } + default: + // FIXME: Can we clean this last call with a method call? + rust_error_at (token->get_locus (), + "unexpected token when parsing generic parameters: %qs", + token->get_str ().c_str ()); + return nullptr; } - // old code - /* - // parse lifetime params (optional), allowed to end with a trailing comma - std::vector> lifetime_params - = parse_lifetime_params(); - if (!lifetime_params.empty()) { - // C++11 code: - generic_params.insert(generic_params.end(), - std::make_move_iterator(lifetime_params.begin()), - std::make_move_iterator(lifetime_params.end())); - } - - // parse type params (optional) - std::vector> type_params = - parse_type_params(); if (!type_params.empty()) { - // C++11 code: - generic_params.insert(generic_params.end(), - std::make_move_iterator(type_params.begin()), - std::make_move_iterator(type_params.end())); - }*/ - - generic_params.shrink_to_fit (); - return generic_params; + return param; } /* Parse generic (lifetime or type) params NOT INSIDE ANGLE BRACKETS!!! Almost @@ -3002,150 +2892,19 @@ Parser::parse_generic_params (EndTokenPred is_end_token) * parsed but it turns out to be type param */ AST::Attribute parsed_outer_attr = AST::Attribute::create_empty (); - const_TokenPtr t = lexer.peek_token (); // parse lifetime params - while (!is_end_token (t->get_id ())) - { - // HACK: reimpl of lifetime param parsing - AST::Attribute outer_attr = parse_outer_attribute (); - - // move attribute outward if type param - if (lexer.peek_token ()->get_id () != LIFETIME) - { - parsed_outer_attr = std::move (outer_attr); - break; - } - - Location locus = lexer.peek_token ()->get_locus (); - AST::Lifetime lifetime = parse_lifetime (); - - // parse optional bounds - std::vector lifetime_bounds; - if (lexer.peek_token ()->get_id () == COLON) - { - lexer.skip_token (); - // parse required bounds - lifetime_bounds = parse_lifetime_bounds ([is_end_token] (TokenId id) { - return is_end_token (id) || id == COMMA; - }); - } - - std::unique_ptr param ( - new AST::LifetimeParam (std::move (lifetime), - std::move (lifetime_bounds), - std::move (outer_attr), locus)); - generic_params.push_back (std::move (param)); - - if (lexer.peek_token ()->get_id () != COMMA) - break; - - lexer.skip_token (); - t = lexer.peek_token (); - } - - // parse type params (reimpl required for first one but not others) - if (!is_end_token (lexer.peek_token ()->get_id ()) - && !parsed_outer_attr.is_empty ()) - { - // reimpl as type param definitely exists - const_TokenPtr ident_tok = expect_token (IDENTIFIER); - if (ident_tok == nullptr) - { - Error error ( - lexer.peek_token ()->get_locus (), - "failed to parse identifier in type param in generic params"); - add_error (std::move (error)); - - return {}; - } - Identifier ident = ident_tok->get_str (); - - // parse optional bounds - std::vector> type_param_bounds; - if (lexer.peek_token ()->get_id () == COLON) - { - lexer.skip_token (); - - // parse optional type param bounds - type_param_bounds = parse_type_param_bounds (); - } - - // parse optional type - std::unique_ptr type = nullptr; - if (lexer.peek_token ()->get_id () == EQUAL) - { - lexer.skip_token (); - - // parse required type - type = parse_type (); - if (type == nullptr) - { - Error error ( - lexer.peek_token ()->get_locus (), - "failed to parse type in type param in generic params"); - add_error (std::move (error)); - - return {}; - } - } - - std::unique_ptr param ( - new AST::TypeParam (std::move (ident), ident_tok->get_locus (), - std::move (type_param_bounds), std::move (type), - std::move (parsed_outer_attr))); - generic_params.push_back (std::move (param)); - - // handle comma - if (lexer.peek_token ()->get_id () == COMMA) - lexer.skip_token (); - } - - // parse rest of type params - reimpl due to right angle tokens - t = lexer.peek_token (); - while (!is_end_token (t->get_id ())) + while (!is_end_token (lexer.peek_token ()->get_id ())) { - std::unique_ptr type_param = parse_type_param (); - - if (type_param == nullptr) + auto param = parse_generic_param (is_end_token); + if (param) { - Error error (lexer.peek_token ()->get_locus (), - "failed to parse type param in generic params"); - add_error (std::move (error)); - - return {}; + generic_params.emplace_back (std::move (param)); + maybe_skip_token (COMMA); } - generic_params.push_back (std::move (type_param)); - - if (lexer.peek_token ()->get_id () != COMMA) - break; - - // skip commas, including trailing commas - lexer.skip_token (); - t = lexer.peek_token (); + // error out if lifetime after type } - // old code - /* - // parse lifetime params (optional), allowed to end with a trailing comma - std::vector> lifetime_params - = parse_lifetime_params(); - if (!lifetime_params.empty()) { - // C++11 code: - generic_params.insert(generic_params.end(), - std::make_move_iterator(lifetime_params.begin()), - std::make_move_iterator(lifetime_params.end())); - } - - // parse type params (optional) - std::vector> type_params = - parse_type_params(); if (!type_params.empty()) { - // C++11 code: - generic_params.insert(generic_params.end(), - std::make_move_iterator(type_params.begin()), - std::make_move_iterator(type_params.end())); - }*/ - generic_params.shrink_to_fit (); return generic_params; } diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h index fcfcf18ff5b..d19bc71d310 100644 --- a/gcc/rust/parse/rust-parse.h +++ b/gcc/rust/parse/rust-parse.h @@ -223,10 +223,12 @@ private: AST::FunctionQualifiers parse_function_qualifiers (); std::vector > parse_generic_params_in_angles (); - std::vector > parse_generic_params (); template std::vector > parse_generic_params (EndTokenPred is_end_token); + template + std::unique_ptr + parse_generic_param (EndTokenPred is_end_token); template std::vector >