diff options
author | SimplyTheOther <simplytheother@gmail.com> | 2020-09-27 15:11:48 +0800 |
---|---|---|
committer | Philip Herron <philip.herron@embecosm.com> | 2020-11-28 21:13:21 +0000 |
commit | 4cfd93746242dc6e73f4fa71520bb361a2d6de4a (patch) | |
tree | 3d664542f2ac5b07cd4a535b3fe3cfab93c99d59 /gcc | |
parent | 5fbc20189d0a9648c2ab6f4f9a7cf0bd82e73186 (diff) | |
download | gcc-4cfd93746242dc6e73f4fa71520bb361a2d6de4a.zip gcc-4cfd93746242dc6e73f4fa71520bb361a2d6de4a.tar.gz gcc-4cfd93746242dc6e73f4fa71520bb361a2d6de4a.tar.bz2 |
Testing some more algorithmic changes
Fixed syntax errors
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/parse/rust-parse-impl.h | 481 | ||||
-rw-r--r-- | gcc/rust/parse/rust-parse.h | 10 |
2 files changed, 389 insertions, 102 deletions
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index fadbfb4..286d7a4 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -546,19 +546,15 @@ Parser<ManagedTokenSource>::parse_simple_path () // get location if not gotten already if (locus == Linemap::unknown_location ()) - { - locus = segment.get_locus (); - } + locus = segment.get_locus (); std::vector<AST::SimplePathSegment> segments; // Return empty vector if first, actually required segment is an error if (segment.is_error ()) - { - return AST::SimplePath::create_empty (); - } + return AST::SimplePath::create_empty (); - segments.push_back (segment); + segments.push_back (std::move (segment)); // Parse all other simple path segments while (lexer.peek_token ()->get_id () == SCOPE_RESOLUTION) @@ -570,10 +566,9 @@ Parser<ManagedTokenSource>::parse_simple_path () // Return path as currently constructed if segment in error state. if (new_segment.is_error ()) - { - break; - } - segments.push_back (new_segment); + break; + + segments.push_back (std::move (new_segment)); } // DEBUG: check for any empty segments @@ -2203,9 +2198,9 @@ Parser<ManagedTokenSource>::parse_use_tree () * top two then try parse :: - if fails, one of top two. Next is deciding * character for top two. */ - // Thus, parsing smaller parts of use tree may require feeding into function - // via parameters (or could handle all in this single function because other - // use tree types aren't recognised) as separate in the spec + /* Thus, parsing smaller parts of use tree may require feeding into function + * via parameters (or could handle all in this single function because other + * use tree types aren't recognised as separate in the spec) */ // TODO: I think this function is too complex, probably should split it @@ -2546,7 +2541,7 @@ Parser<ManagedTokenSource>::parse_generic_params_in_angles () fprintf (stderr, "skipped left angle in generic param\n"); std::vector<std::unique_ptr<AST::GenericParam> > generic_params - = parse_generic_params (); + = parse_generic_params (is_right_angle_tok); // DEBUG: fprintf (stderr, @@ -2579,12 +2574,12 @@ Parser<ManagedTokenSource>::parse_generic_params () fprintf (stderr, "starting to parse generic params (inside angle brackets)\n"); - // HACK: used to retain attribute data if a lifetime param is tentatively - // parsed but it turns out to be type param + /* 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 + /* 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 ())) @@ -2618,7 +2613,8 @@ Parser<ManagedTokenSource>::parse_generic_params () { lexer.skip_token (); // parse required bounds - lifetime_bounds = parse_lifetime_bounds (); + lifetime_bounds = parse_lifetime_bounds ( + [] (TokenId id) { return is_right_angle_tok (id) || id == COMMA; }); } std::unique_ptr<AST::LifetimeParam> param ( @@ -2752,6 +2748,163 @@ Parser<ManagedTokenSource>::parse_generic_params () 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 <typename ManagedTokenSource> +template <typename EndTokenPred> +std::vector<std::unique_ptr<AST::GenericParam> > +Parser<ManagedTokenSource>::parse_generic_params (EndTokenPred is_end_token) +{ + std::vector<std::unique_ptr<AST::GenericParam> > generic_params; + + /* can't parse lifetime and type params separately due to lookahead issues + * thus, parse them all here */ + + /* 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 (); + + 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<AST::Lifetime> 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<AST::LifetimeParam> param ( + new AST::LifetimeParam (std::move (lifetime), locus, + std::move (lifetime_bounds), + std::move (outer_attr))); + 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) + { + rust_error_at ( + lexer.peek_token ()->get_locus (), + "failed to parse identifier in type param in generic params"); + return {}; + } + Identifier ident = ident_tok->get_str (); + + // parse optional bounds + std::vector<std::unique_ptr<AST::TypeParamBound> > 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<AST::Type> type = nullptr; + if (lexer.peek_token ()->get_id () == EQUAL) + { + lexer.skip_token (); + + // parse required type + type = parse_type (); + if (type == nullptr) + { + rust_error_at ( + lexer.peek_token ()->get_locus (), + "failed to parse type in type param in generic params"); + return {}; + } + } + + std::unique_ptr<AST::TypeParam> 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 ())) + { + std::unique_ptr<AST::TypeParam> type_param = parse_type_param (); + + if (type_param == nullptr) + { + rust_error_at (lexer.peek_token ()->get_locus (), + "failed to parse type param in generic params"); + return {}; + } + + 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 (); + } + + // old code + /* + // parse lifetime params (optional), allowed to end with a trailing comma + std::vector<std::unique_ptr<AST::LifetimeParam>> 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<std::unique_ptr<AST::TypeParam>> 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())); + }*/ + + return generic_params; +} + /* Parses lifetime generic parameters (pointers). Will also consume any trailing * comma. No extra checks for end token. */ template <typename ManagedTokenSource> @@ -2801,8 +2954,8 @@ Parser<ManagedTokenSource>::parse_lifetime_params (EndTokenPred is_end_token) if (lifetime_param.is_error ()) { - // TODO: is it worth throwing away all lifetime params just because - // one failed? + /* TODO: is it worth throwing away all lifetime params just because + * one failed? */ rust_error_at (lexer.peek_token ()->get_locus (), "failed to parse lifetime param in lifetime params"); return {}; @@ -2898,7 +3051,8 @@ Parser<ManagedTokenSource>::parse_lifetime_params_objs ( /* Parses a sequence of a certain grammar rule in object form (not pointer or * smart pointer), delimited by commas and ending when 'is_end_token' is * satisfied (templated). Will also consume any trailing comma. - * TODO: is this best solution? implements most of the same algorithm. */ + * FIXME: this cannot be used due to member function pointer problems (i.e. + * parsing_function cannot be specified properly) */ template <typename ManagedTokenSource> template <typename ParseFunction, typename EndTokenPred> auto @@ -2960,6 +3114,7 @@ Parser<ManagedTokenSource>::parse_lifetime_param () { // parse lifetime bounds lifetime_bounds = parse_lifetime_bounds (); + // TODO: have end token passed in? } return AST::LifetimeParam (std::move (lifetime), lifetime_tok->get_locus (), @@ -2974,8 +3129,7 @@ Parser<ManagedTokenSource>::parse_type_params () { std::vector<std::unique_ptr<AST::TypeParam> > type_params; - // TODO: think of better control structure than infinite loop with break on - // failure? + // infinite loop with break on failure as no info on ending token while (true) { std::unique_ptr<AST::TypeParam> type_param = parse_type_param (); @@ -2989,16 +3143,46 @@ Parser<ManagedTokenSource>::parse_type_params () type_params.push_back (std::move (type_param)); if (lexer.peek_token ()->get_id () != COMMA) + break; + + // skip commas, including trailing commas + lexer.skip_token (); + } + + return type_params; +} + +// Parses type generic parameters. Will also consume any trailing comma. +template <typename ManagedTokenSource> +template <typename EndTokenPred> +std::vector<std::unique_ptr<AST::TypeParam> > +Parser<ManagedTokenSource>::parse_type_params (EndTokenPred is_end_token) +{ + std::vector<std::unique_ptr<AST::TypeParam> > type_params; + + while (!is_end_token (lexer.peek_token ()->get_id ())) + { + std::unique_ptr<AST::TypeParam> type_param = parse_type_param (); + + if (type_param == nullptr) { - break; + rust_error_at (lexer.peek_token ()->get_locus (), + "failed to parse type param in type params"); + return {}; } + + type_params.push_back (std::move (type_param)); + + if (lexer.peek_token ()->get_id () != COMMA) + break; + // skip commas, including trailing commas lexer.skip_token (); } return type_params; - // TODO: this shares most code with parse_lifetime_params - good place to use - // template? + /* TODO: this shares most code with parse_lifetime_params - good place to use + * template (i.e. parse_non_ptr_sequence if doable) */ } /* Parses a single type (generic) parameter, not including commas. May change to @@ -3244,6 +3428,7 @@ Parser<ManagedTokenSource>::parse_lifetime_where_clause_item () } std::vector<AST::Lifetime> lifetime_bounds = parse_lifetime_bounds (); + // TODO: have end token passed in? return std::unique_ptr<AST::LifetimeWhereClauseItem> ( new AST::LifetimeWhereClauseItem (std::move (lifetime), @@ -3303,10 +3488,7 @@ Parser<ManagedTokenSource>::parse_for_lifetimes () /* cannot specify end token due to parsing problems with '>' tokens being * nested */ - //params = parse_lifetime_params_objs (is_right_angle_tok); - params = parse_non_ptr_sequence ( - parse_lifetime_param, is_right_angle_tok, - "failed to parse lifetime param in lifetime params"); + params = parse_lifetime_params_objs (is_right_angle_tok); if (!skip_generics_right_angle ()) { @@ -3335,34 +3517,74 @@ Parser<ManagedTokenSource>::parse_type_param_bounds () // quick exit if null if (initial_bound == nullptr) { - // error? type param bounds must have at least one term, but are bounds - // optional? + /* error? type param bounds must have at least one term, but are bounds + * optional? */ return type_param_bounds; } - type_param_bounds.push_back (std::move (initial_bound)); - // TODO think of better control structure than infinite loop - while (true) + while (lexer.peek_token ()->get_id () == PLUS) { - // Quick exit for no more bounds - if (lexer.peek_token ()->get_id () != PLUS) + lexer.skip_token (); + + std::unique_ptr<AST::TypeParamBound> bound = parse_type_param_bound (); + if (bound == nullptr) { + /* not an error: bound is allowed to be null as trailing plus is + * allowed */ return type_param_bounds; } + + type_param_bounds.push_back (std::move (bound)); + } + + type_param_bounds.shrink_to_fit (); + return type_param_bounds; +} + +// Parses type parameter bounds in where clause or generic arguments, with end +// token handling. +template <typename ManagedTokenSource> +template <typename EndTokenPred> +std::vector<std::unique_ptr<AST::TypeParamBound> > +Parser<ManagedTokenSource>::parse_type_param_bounds (EndTokenPred is_end_token) +{ + std::vector<std::unique_ptr<AST::TypeParamBound> > type_param_bounds; + + std::unique_ptr<AST::TypeParamBound> initial_bound + = parse_type_param_bound (); + + // quick exit if null + if (initial_bound == nullptr) + { + /* error? type param bounds must have at least one term, but are bounds + * optional? */ + return type_param_bounds; + } + type_param_bounds.push_back (std::move (initial_bound)); + + while (lexer.peek_token ()->get_id () == PLUS) + { lexer.skip_token (); + // break if end token character + if (is_end_token (lexer.peek_token ()->get_id ())) + break; + std::unique_ptr<AST::TypeParamBound> bound = parse_type_param_bound (); if (bound == nullptr) { - // not an error: bound is allowed to be null as trailing plus is - // allowed - return type_param_bounds; + // TODO how wise is it to ditch all bounds if only one failed? + rust_error_at ( + lexer.peek_token ()->get_locus (), + "failed to parse type param bound in type param bounds"); + return {}; } type_param_bounds.push_back (std::move (bound)); } + type_param_bounds.shrink_to_fit (); return type_param_bounds; } @@ -3451,29 +3673,60 @@ Parser<ManagedTokenSource>::parse_lifetime_bounds () { std::vector<AST::Lifetime> lifetime_bounds; - // TODO: think of better control structure while (true) { AST::Lifetime lifetime = parse_lifetime (); // quick exit for parsing failure if (lifetime.is_error ()) - { - return lifetime_bounds; - } + break; lifetime_bounds.push_back (std::move (lifetime)); - // plus is maybe required - spec defines it poorly, so assuming not - // required + /* plus is maybe not allowed at end - spec defines it weirdly, so assuming + * allowed at end */ if (lexer.peek_token ()->get_id () != PLUS) + break; + + lexer.skip_token (); + } + + lifetime_bounds.shrink_to_fit (); + return lifetime_bounds; +} + +// Parses lifetime bounds, with added check for ending token. +template <typename ManagedTokenSource> +template <typename EndTokenPred> +std::vector<AST::Lifetime> +Parser<ManagedTokenSource>::parse_lifetime_bounds (EndTokenPred is_end_token) +{ + std::vector<AST::Lifetime> lifetime_bounds; + + while (!is_end_token (lexer.peek_token ()->get_id ())) + { + AST::Lifetime lifetime = parse_lifetime (); + + if (lifetime.is_error ()) { - return lifetime_bounds; + /* TODO: is it worth throwing away all lifetime bound info just + * because one failed? */ + rust_error_at (lexer.peek_token ()->get_locus (), + "failed to parse lifetime in lifetime bounds"); + return {}; } + lifetime_bounds.push_back (std::move (lifetime)); + + /* plus is maybe not allowed at end - spec defines it weirdly, so assuming + * allowed at end */ + if (lexer.peek_token ()->get_id () != PLUS) + break; + lexer.skip_token (); } + lifetime_bounds.shrink_to_fit (); return lifetime_bounds; } @@ -3871,7 +4124,8 @@ Parser<ManagedTokenSource>::parse_enum (AST::Visibility vis, } // parse actual enum variant definitions - std::vector<std::unique_ptr<AST::EnumItem> > enum_items = parse_enum_items (); + std::vector<std::unique_ptr<AST::EnumItem> > enum_items + = parse_enum_items ([] (TokenId id) { return id == RIGHT_CURLY; }); if (!skip_token (RIGHT_CURLY)) { @@ -3896,47 +4150,72 @@ Parser<ManagedTokenSource>::parse_enum_items () // Return empty item list if no field there if (initial_item == nullptr) - { - return items; - } + return items; items.push_back (std::move (initial_item)); - // maybe think of a better control structure here - do-while with an initial - // error state? basically, loop through item list until can't find any more - // params - while (true) + while (lexer.peek_token ()->get_id () == COMMA) { - if (lexer.peek_token ()->get_id () != COMMA) + lexer.skip_token (); + + std::unique_ptr<AST::EnumItem> item = parse_enum_item (); + if (item == nullptr) { + // this would occur with a trailing comma, which is allowed break; } - // skip comma if applies + items.push_back (std::move (item)); + } + + return items; + + /* TODO: use template if doable (parse_non_ptr_sequence) */ +} + +// Parses the enum variants inside an enum definiton. +template <typename ManagedTokenSource> +template <typename EndTokenPred> +std::vector<std::unique_ptr<AST::EnumItem> > +Parser<ManagedTokenSource>::parse_enum_items (EndTokenPred is_end_tok) +{ + std::vector<std::unique_ptr<AST::EnumItem> > items; + + std::unique_ptr<AST::EnumItem> initial_item = parse_enum_item (); + + // Return empty item list if no field there + if (initial_item == nullptr) + return items; + + items.push_back (std::move (initial_item)); + + while (lexer.peek_token ()->get_id () == COMMA) + { lexer.skip_token (); - std::unique_ptr<AST::EnumItem> item = parse_enum_item (); + if (is_end_tok (lexer.peek_token ()->get_id ())) + break; - if (item != nullptr) - { - items.push_back (std::move (item)); - } - else + std::unique_ptr<AST::EnumItem> item = parse_enum_item (); + if (item == nullptr) { - // this would occur with a trailing comma, which is allowed - break; + /* TODO should this ignore all successfully parsed enum items just + * because one failed? */ + rust_error_at (lexer.peek_token ()->get_locus (), + "failed to parse enum item in enum items"); + return {}; } + + items.push_back (std::move (item)); } - // TODO: does this need move? return items; - // TODO: shares virtually all code with function params, tuple and struct - // fields - templates? + /* TODO: use template if doable (parse_non_ptr_sequence) */ } -// Parses a single enum variant item in an enum definition. Does not parse -// commas. +/* Parses a single enum variant item in an enum definition. Does not parse + * commas. */ template <typename ManagedTokenSource> std::unique_ptr<AST::EnumItem> Parser<ManagedTokenSource>::parse_enum_item () @@ -4016,11 +4295,12 @@ std::unique_ptr<AST::Union> Parser<ManagedTokenSource>::parse_union ( AST::Visibility vis, std::vector<AST::Attribute> outer_attrs) { - // hack - "weak keyword" by finding identifier called "union" (lookahead in - // item switch) - Location locus = lexer.peek_token ()->get_locus (); - // skip union "identifier" - skip_token (IDENTIFIER); + /* hack - "weak keyword" by finding identifier called "union" (lookahead in + * item switch) */ + const_TokenPtr union_keyword = expect_token (IDENTIFIER); + rust_assert (union_keyword->get_str () == "union"); + Location locus = union_keyword->get_locus (); + lexer.skip_token (); // parse actual union name const_TokenPtr union_name_tok = expect_token (IDENTIFIER); @@ -4044,8 +4324,8 @@ Parser<ManagedTokenSource>::parse_union ( return nullptr; } - // parse union inner items as "struct fields" because hey, syntax reuse. Spec - // said so. + /* parse union inner items as "struct fields" because hey, syntax reuse. Spec + * said so. */ std::vector<AST::StructField> union_fields = parse_struct_fields (); if (!skip_token (RIGHT_CURLY)) @@ -4070,8 +4350,8 @@ Parser<ManagedTokenSource>::parse_const_item ( Location locus = lexer.peek_token ()->get_locus (); skip_token (CONST); - // get constant identifier - this is either a proper identifier or the _ - // wildcard + /* get constant identifier - this is either a proper identifier or the _ + * wildcard */ const_TokenPtr ident_tok = lexer.peek_token (); // make default identifier the underscore wildcard one std::string ident ("_"); @@ -4206,8 +4486,9 @@ Parser<ManagedTokenSource>::parse_trait ( { lexer.skip_token (); - // TODO: does this need move? - type_param_bounds = parse_type_param_bounds (); + type_param_bounds = parse_type_param_bounds ( + [] (TokenId id) { return id == WHERE || id == LEFT_CURLY; }); + // type_param_bounds = parse_type_param_bounds (); } // parse where clause (if it exists) @@ -4229,11 +4510,10 @@ Parser<ManagedTokenSource>::parse_trait ( if (trait_item == nullptr) { - // TODO: this is probably an error as next character should equal - // RIGHT_CURLY - break; + rust_error_at (lexer.peek_token ()->get_locus (), + "failed to parse trait item in trait"); + return nullptr; } - trait_items.push_back (std::move (trait_item)); t = lexer.peek_token (); @@ -4435,7 +4715,9 @@ Parser<ManagedTokenSource>::parse_trait_type ( lexer.skip_token (); // parse optional type param bounds - bounds = parse_type_param_bounds (); + bounds + = parse_type_param_bounds ([] (TokenId id) { return id == SEMICOLON; }); + // bounds = parse_type_param_bounds (); } if (!skip_token (SEMICOLON)) @@ -4582,11 +4864,10 @@ Parser<ManagedTokenSource>::parse_impl (AST::Visibility vis, if (impl_item == nullptr) { - // TODO: this is probably an error as next character should equal - // RIGHT_CURLY - fprintf (stderr, "impl item is null and next char wasn't " - "RIGHT_CURLY - probably an error"); - break; + rust_error_at ( + lexer.peek_token ()->get_locus (), + "failed to parse inherent impl item in inherent impl"); + return nullptr; } impl_items.push_back (std::move (impl_item)); @@ -4652,13 +4933,9 @@ Parser<ManagedTokenSource>::parse_impl (AST::Visibility vis, if (impl_item == nullptr) { - // DEBUG - fprintf (stderr, "break out of parsing trait impl items (due to " - "parse giving null)\n"); - - // TODO: this is probably an error as next character should equal - // RIGHT_CURLY - break; + rust_error_at (lexer.peek_token ()->get_locus (), + "failed to parse trait impl item in trait impl"); + return nullptr; } impl_items.push_back (std::move (impl_item)); @@ -4765,8 +5042,8 @@ Parser<ManagedTokenSource>::parse_inherent_impl_item () return parse_inherent_impl_function_or_method ( AST::Visibility::create_error (), std::move (outer_attrs)); case CONST: - // lookahead to resolve production - could be function/method or const - // item + /* lookahead to resolve production - could be function/method or const + * item */ t = lexer.peek_token (1); switch (t->get_id ()) diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h index 928bb96..b2de05e 100644 --- a/gcc/rust/parse/rust-parse.h +++ b/gcc/rust/parse/rust-parse.h @@ -149,6 +149,8 @@ private: std::vector<std::unique_ptr<AST::GenericParam> > parse_generic_params_in_angles (); std::vector<std::unique_ptr<AST::GenericParam> > parse_generic_params (); + template <typename EndTokenPred> + std::vector<std::unique_ptr<AST::GenericParam> > parse_generic_params (EndTokenPred is_end_token); std::vector<std::unique_ptr<AST::LifetimeParam> > parse_lifetime_params (); template <typename EndTokenPred> std::vector<std::unique_ptr<AST::LifetimeParam> > parse_lifetime_params (EndTokenPred is_end_token); @@ -159,6 +161,8 @@ private: auto parse_non_ptr_sequence (ParseFunction parsing_function, EndTokenPred is_end_token, std::string error_msg = "failed to parse generic param in generic params") -> std::vector<decltype(parsing_function ())>; AST::LifetimeParam parse_lifetime_param (); std::vector<std::unique_ptr<AST::TypeParam> > parse_type_params (); + template <typename EndTokenPred> + std::vector<std::unique_ptr<AST::TypeParam> > parse_type_params (EndTokenPred is_end_token); std::unique_ptr<AST::TypeParam> parse_type_param (); std::vector<AST::FunctionParam> parse_function_params (); AST::FunctionParam parse_function_param (); @@ -170,10 +174,14 @@ private: std::unique_ptr<AST::TypeBoundWhereClauseItem> parse_type_bound_where_clause_item (); std::vector<AST::LifetimeParam> parse_for_lifetimes (); + template <typename EndTokenPred> + std::vector<std::unique_ptr<AST::TypeParamBound> > parse_type_param_bounds (EndTokenPred is_end_token); std::vector<std::unique_ptr<AST::TypeParamBound> > parse_type_param_bounds (); std::unique_ptr<AST::TypeParamBound> parse_type_param_bound (); std::unique_ptr<AST::TraitBound> parse_trait_bound (); std::vector<AST::Lifetime> parse_lifetime_bounds (); + template <typename EndTokenPred> + std::vector<AST::Lifetime> parse_lifetime_bounds (EndTokenPred is_end_token); AST::Lifetime parse_lifetime (); std::unique_ptr<AST::TypeAlias> parse_type_alias (AST::Visibility vis, @@ -187,6 +195,8 @@ private: std::unique_ptr<AST::Enum> parse_enum (AST::Visibility vis, std::vector<AST::Attribute> outer_attrs); std::vector<std::unique_ptr<AST::EnumItem> > parse_enum_items (); + template <typename EndTokenPred> + std::vector<std::unique_ptr<AST::EnumItem> > parse_enum_items (EndTokenPred is_end_token); std::unique_ptr<AST::EnumItem> parse_enum_item (); std::unique_ptr<AST::Union> parse_union (AST::Visibility vis, std::vector<AST::Attribute> outer_attrs); |