diff options
Diffstat (limited to 'gcc/rust/parse')
-rw-r--r-- | gcc/rust/parse/rust-parse-impl.h | 283 | ||||
-rw-r--r-- | gcc/rust/parse/rust-parse.h | 30 |
2 files changed, 133 insertions, 180 deletions
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 44b4d74..64807b6 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -2879,12 +2879,21 @@ Parser<ManagedTokenSource>::parse_function (AST::Visibility vis, return nullptr; } + std::unique_ptr<AST::Param> initial_param = parse_self_param (); + if (initial_param != nullptr) + skip_token (COMMA); + // parse function parameters (only if next token isn't right paren) - std::vector<AST::FunctionParam> function_params; + std::vector<std::unique_ptr<AST::Param>> function_params; + if (lexer.peek_token ()->get_id () != RIGHT_PAREN) function_params = parse_function_params ([] (TokenId id) { return id == RIGHT_PAREN; }); + if (initial_param != nullptr) + function_params.insert (function_params.begin (), + std::move (initial_param)); + if (!skip_token (RIGHT_PAREN)) { Error error (lexer.peek_token ()->get_locus (), @@ -2907,11 +2916,10 @@ Parser<ManagedTokenSource>::parse_function (AST::Visibility vis, return std::unique_ptr<AST::Function> ( new AST::Function (std::move (function_name), std::move (qualifiers), - std::move (generic_params), - tl::optional<AST::SelfParam> (), - std::move (function_params), std::move (return_type), - std::move (where_clause), std::move (block_expr), - std::move (vis), std::move (outer_attrs), locus)); + std::move (generic_params), std::move (function_params), + std::move (return_type), std::move (where_clause), + std::move (block_expr), std::move (vis), + std::move (outer_attrs), locus)); } // Parses function or method qualifiers (i.e. const, unsafe, and extern). @@ -3525,18 +3533,18 @@ Parser<ManagedTokenSource>::parse_type_param () * has end token handling. */ template <typename ManagedTokenSource> template <typename EndTokenPred> -std::vector<AST::FunctionParam> +std::vector<std::unique_ptr<AST::Param>> Parser<ManagedTokenSource>::parse_function_params (EndTokenPred is_end_token) { - std::vector<AST::FunctionParam> params; + std::vector<std::unique_ptr<AST::Param>> params; if (is_end_token (lexer.peek_token ()->get_id ())) return params; - AST::FunctionParam initial_param = parse_function_param (); + auto initial_param = parse_function_param (); // Return empty parameter list if no parameter there - if (initial_param.is_error ()) + if (initial_param == nullptr) { // TODO: is this an error? return params; @@ -3558,15 +3566,15 @@ Parser<ManagedTokenSource>::parse_function_params (EndTokenPred is_end_token) break; // now, as right paren would break, function param is required - AST::FunctionParam param = parse_function_param (); - if (param.is_error ()) + auto param = parse_function_param (); + if (param == nullptr) { Error error (lexer.peek_token ()->get_locus (), "failed to parse function param (in function params)"); add_error (std::move (error)); // skip somewhere? - return std::vector<AST::FunctionParam> (); + return std::vector<std::unique_ptr<AST::Param>> (); } params.push_back (std::move (param)); @@ -3581,7 +3589,7 @@ Parser<ManagedTokenSource>::parse_function_params (EndTokenPred is_end_token) /* Parses a single regular (i.e. non-generic) parameter in a function or * method, i.e. the "name: type" bit. Also handles it not existing. */ template <typename ManagedTokenSource> -AST::FunctionParam +std::unique_ptr<AST::Param> Parser<ManagedTokenSource>::parse_function_param () { // parse outer attributes if they exist @@ -3593,7 +3601,8 @@ Parser<ManagedTokenSource>::parse_function_param () if (lexer.peek_token ()->get_id () == ELLIPSIS) // Unnamed variadic { lexer.skip_token (); // Skip ellipsis - return AST::FunctionParam (std::move (outer_attrs), locus); + return Rust::make_unique<AST::VariadicParam> ( + AST::VariadicParam (std::move (outer_attrs), locus)); } std::unique_ptr<AST::Pattern> param_pattern = parse_pattern (); @@ -3602,32 +3611,32 @@ Parser<ManagedTokenSource>::parse_function_param () if (param_pattern == nullptr) { // skip after something - return AST::FunctionParam::create_error (); + return nullptr; } if (!skip_token (COLON)) { // skip after something - return AST::FunctionParam::create_error (); + return nullptr; } if (lexer.peek_token ()->get_id () == ELLIPSIS) // Named variadic { lexer.skip_token (); // Skip ellipsis - return AST::FunctionParam (std::move (param_pattern), - std::move (outer_attrs), locus); + return Rust::make_unique<AST::VariadicParam> ( + AST::VariadicParam (std::move (param_pattern), std::move (outer_attrs), + locus)); } else { std::unique_ptr<AST::Type> param_type = parse_type (); if (param_type == nullptr) { - // skip? - return AST::FunctionParam::create_error (); + return nullptr; } - return AST::FunctionParam (std::move (param_pattern), - std::move (param_type), - std::move (outer_attrs), locus); + return Rust::make_unique<AST::FunctionParam> ( + AST::FunctionParam (std::move (param_pattern), std::move (param_type), + std::move (outer_attrs), locus)); } } @@ -5051,13 +5060,14 @@ Parser<ManagedTokenSource>::parse_trait_item () /* now for function vs method disambiguation - method has opening * "self" param */ - AST::SelfParam self_param = parse_self_param (); + std::unique_ptr<AST::Param> initial_param = parse_self_param (); /* FIXME: ensure that self param doesn't accidently consume tokens for * a function */ bool is_method = false; - if (!self_param.is_error ()) + if (initial_param != nullptr) { - is_method = true; + if (initial_param->is_self ()) + is_method = true; /* skip comma so function and method regular params can be parsed * in same way */ @@ -5066,7 +5076,7 @@ Parser<ManagedTokenSource>::parse_trait_item () } // parse trait function params - std::vector<AST::FunctionParam> function_params + std::vector<std::unique_ptr<AST::Param>> function_params = parse_function_params ( [] (TokenId id) { return id == RIGHT_PAREN; }); @@ -5076,6 +5086,10 @@ Parser<ManagedTokenSource>::parse_trait_item () return nullptr; } + if (initial_param != nullptr) + function_params.insert (function_params.begin (), + std::move (initial_param)); + // parse return type (optional) std::unique_ptr<AST::Type> return_type = parse_function_return_type (); @@ -5114,7 +5128,6 @@ Parser<ManagedTokenSource>::parse_trait_item () AST::TraitMethodDecl method_decl (std::move (ident), std::move (qualifiers), std::move (generic_params), - std::move (self_param), std::move (function_params), std::move (return_type), std::move (where_clause)); @@ -5592,14 +5605,15 @@ Parser<ManagedTokenSource>::parse_inherent_impl_function_or_method ( // now for function vs method disambiguation - method has opening "self" // param - AST::SelfParam self_param = parse_self_param (); + std::unique_ptr<AST::Param> initial_param = parse_self_param (); /* FIXME: ensure that self param doesn't accidently consume tokens for a * function one idea is to lookahead up to 4 tokens to see whether self is * one of them */ bool is_method = false; - if (!self_param.is_error ()) + if (initial_param != nullptr) { - is_method = true; + if (initial_param->is_self ()) + is_method = true; /* skip comma so function and method regular params can be parsed in * same way */ @@ -5608,9 +5622,13 @@ Parser<ManagedTokenSource>::parse_inherent_impl_function_or_method ( } // parse trait function params - std::vector<AST::FunctionParam> function_params + std::vector<std::unique_ptr<AST::Param>> function_params = parse_function_params ([] (TokenId id) { return id == RIGHT_PAREN; }); + if (initial_param != nullptr) + function_params.insert (function_params.begin (), + std::move (initial_param)); + if (!skip_token (RIGHT_PAREN)) { skip_after_end_block (); @@ -5650,18 +5668,18 @@ Parser<ManagedTokenSource>::parse_inherent_impl_function_or_method ( // do actual if instead of ternary for return value optimisation if (is_method) { - return std::unique_ptr<AST::Function> (new AST::Function ( - std::move (ident), std::move (qualifiers), std::move (generic_params), - tl::optional<AST::SelfParam> (tl::in_place, std::move (self_param)), - std::move (function_params), std::move (return_type), - std::move (where_clause), std::move (body), std::move (vis), - std::move (outer_attrs), locus)); + return std::unique_ptr<AST::Function> ( + new AST::Function (std::move (ident), std::move (qualifiers), + std::move (generic_params), + std::move (function_params), std::move (return_type), + std::move (where_clause), std::move (body), + std::move (vis), std::move (outer_attrs), locus)); } else { return std::unique_ptr<AST::Function> ( new AST::Function (std::move (ident), std::move (qualifiers), - std::move (generic_params), tl::nullopt, + std::move (generic_params), std::move (function_params), std::move (return_type), std::move (where_clause), std::move (body), std::move (vis), std::move (outer_attrs), locus)); @@ -5795,13 +5813,14 @@ Parser<ManagedTokenSource>::parse_trait_impl_function_or_method ( // now for function vs method disambiguation - method has opening "self" // param - AST::SelfParam self_param = parse_self_param (); + std::unique_ptr<AST::Param> initial_param = parse_self_param (); // FIXME: ensure that self param doesn't accidently consume tokens for a // function bool is_method = false; - if (!self_param.is_error ()) + if (initial_param != nullptr) { - is_method = true; + if (initial_param->is_self ()) + is_method = true; // skip comma so function and method regular params can be parsed in // same way @@ -5819,7 +5838,7 @@ Parser<ManagedTokenSource>::parse_trait_impl_function_or_method ( "started to parse function params in function or method trait impl item"); // parse trait function params (only if next token isn't right paren) - std::vector<AST::FunctionParam> function_params; + std::vector<std::unique_ptr<AST::Param>> function_params; if (lexer.peek_token ()->get_id () != RIGHT_PAREN) { function_params @@ -5838,6 +5857,10 @@ Parser<ManagedTokenSource>::parse_trait_impl_function_or_method ( } } + if (initial_param != nullptr) + function_params.insert (function_params.begin (), + std::move (initial_param)); + // DEBUG rust_debug ("successfully parsed function params in function or method " "trait impl item"); @@ -5886,24 +5909,12 @@ Parser<ManagedTokenSource>::parse_trait_impl_function_or_method ( return nullptr; } - // do actual if instead of ternary for return value optimisation - if (is_method) - { - return std::unique_ptr<AST::Function> (new AST::Function ( - std::move (ident), std::move (qualifiers), std::move (generic_params), - tl::optional<AST::SelfParam> (tl::in_place, std::move (self_param)), - std::move (function_params), std::move (return_type), - std::move (where_clause), std::move (body), std::move (vis), - std::move (outer_attrs), locus, is_default)); - } - else - { - return std::unique_ptr<AST::Function> (new AST::Function ( - std::move (ident), std::move (qualifiers), std::move (generic_params), - tl::nullopt, std::move (function_params), std::move (return_type), - std::move (where_clause), std::move (body), std::move (vis), - std::move (outer_attrs), locus, is_default)); - } + return std::unique_ptr<AST::Function> ( + new AST::Function (std::move (ident), std::move (qualifiers), + std::move (generic_params), std::move (function_params), + std::move (return_type), std::move (where_clause), + std::move (body), std::move (vis), + std::move (outer_attrs), locus, is_default)); } // Parses an extern block of declarations. @@ -7097,7 +7108,7 @@ Parser<ManagedTokenSource>::parse_qualified_path_in_type () // Parses a self param. Also handles self param not existing. template <typename ManagedTokenSource> -AST::SelfParam +std::unique_ptr<AST::Param> Parser<ManagedTokenSource>::parse_self_param () { bool has_reference = false; @@ -7105,6 +7116,42 @@ Parser<ManagedTokenSource>::parse_self_param () location_t locus = lexer.peek_token ()->get_locus (); + // TODO: Feels off, find a better way to clearly express this + std::vector<std::vector<TokenId>> ptrs + = {{ASTERISK, SELF} /* *self */, + {ASTERISK, CONST, SELF} /* *const self */, + {ASTERISK, MUT, SELF} /* *mut self */}; + + for (auto &s : ptrs) + { + size_t i = 0; + for (i = 0; i > s.size (); i++) + if (lexer.peek_token (i)->get_id () != s[i]) + break; + if (i == s.size ()) + rust_error_at (lexer.peek_token ()->get_locus (), + "cannot pass %<self%> by raw pointer"); + } + + // Trying to find those patterns: + // + // &'lifetime mut self + // &'lifetime self + // & mut self + // & self + // mut self + // self + // + // If not found, it is probably a function, exit and let function parsing + // handle it. + bool is_self = false; + for (size_t i = 0; i < 5; i++) + if (lexer.peek_token (i)->get_id () == SELF) + is_self = true; + + if (!is_self) + return nullptr; + // test if self is a reference parameter if (lexer.peek_token ()->get_id () == AMP) { @@ -7124,7 +7171,7 @@ Parser<ManagedTokenSource>::parse_self_param () add_error (std::move (error)); // skip after somewhere? - return AST::SelfParam::create_error (); + return nullptr; } } } @@ -7142,7 +7189,7 @@ Parser<ManagedTokenSource>::parse_self_param () if (self_tok->get_id () != SELF) { // skip after somewhere? - return AST::SelfParam::create_error (); + return nullptr; } lexer.skip_token (); @@ -7161,7 +7208,7 @@ Parser<ManagedTokenSource>::parse_self_param () add_error (std::move (error)); // skip after somewhere? - return AST::SelfParam::create_error (); + return nullptr; } } @@ -7174,114 +7221,20 @@ Parser<ManagedTokenSource>::parse_self_param () add_error (std::move (error)); // skip after somewhere? - return AST::SelfParam::create_error (); + return nullptr; } if (has_reference) { - return AST::SelfParam (std::move (lifetime), has_mut, locus); + return Rust::make_unique<AST::SelfParam> (std::move (lifetime), has_mut, + locus); } else { // note that type may be nullptr here and that's fine - return AST::SelfParam (std::move (type), has_mut, locus); - } -} - -/* Parses a method. Note that this function is probably useless because using - * lookahead to determine whether a function is a method is a PITA (maybe not - * even doable), so most places probably parse a "function or method" and then - * resolve it into whatever it is afterward. As such, this is only here for - * algorithmically defining the grammar rule. */ -template <typename ManagedTokenSource> -std::unique_ptr<AST::Function> -Parser<ManagedTokenSource>::parse_method () -{ - location_t locus = lexer.peek_token ()->get_locus (); - /* Note: as a result of the above, this will not attempt to disambiguate a - * function parse qualifiers */ - AST::FunctionQualifiers qualifiers = parse_function_qualifiers (); - - skip_token (FN_TOK); - - const_TokenPtr ident_tok = expect_token (IDENTIFIER); - if (ident_tok == nullptr) - { - skip_after_next_block (); - return nullptr; + return Rust::make_unique<AST::SelfParam> (std::move (type), has_mut, + locus); } - Identifier method_name{ident_tok}; - - // parse generic params - if exist - std::vector<std::unique_ptr<AST::GenericParam>> generic_params - = parse_generic_params_in_angles (); - - if (!skip_token (LEFT_PAREN)) - { - Error error (lexer.peek_token ()->get_locus (), - "method missing opening parentheses before parameter list"); - add_error (std::move (error)); - - skip_after_next_block (); - return nullptr; - } - - // parse self param - AST::SelfParam self_param = parse_self_param (); - if (self_param.is_error ()) - { - Error error (lexer.peek_token ()->get_locus (), - "could not parse self param in method"); - add_error (std::move (error)); - - skip_after_next_block (); - return nullptr; - } - - // skip comma if it exists - if (lexer.peek_token ()->get_id () == COMMA) - lexer.skip_token (); - - // parse function parameters - std::vector<AST::FunctionParam> function_params - = parse_function_params ([] (TokenId id) { return id == RIGHT_PAREN; }); - - if (!skip_token (RIGHT_PAREN)) - { - Error error (lexer.peek_token ()->get_locus (), - "method declaration missing closing parentheses after " - "parameter list"); - add_error (std::move (error)); - - skip_after_next_block (); - return nullptr; - } - - // parse function return type - if exists - std::unique_ptr<AST::Type> return_type = parse_function_return_type (); - - // parse where clause - if exists - AST::WhereClause where_clause = parse_where_clause (); - - // parse block expression - std::unique_ptr<AST::BlockExpr> block_expr = parse_block_expr (); - if (block_expr == nullptr) - { - Error error (lexer.peek_token ()->get_locus (), - "method declaration missing block expression"); - add_error (std::move (error)); - - skip_after_end_block (); - return nullptr; - } - - // does not parse visibility, but this method isn't used, so doesn't matter - return std::unique_ptr<AST::Function> (new AST::Function ( - std::move (method_name), std::move (qualifiers), std::move (generic_params), - tl::optional<AST::SelfParam> (tl::in_place, std::move (self_param)), - std::move (function_params), std::move (return_type), - std::move (where_clause), std::move (block_expr), - AST::Visibility::create_error (), AST::AttrVec (), locus)); } /* Parses an expression or macro statement. */ diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h index 3ff9b99..9e924e0 100644 --- a/gcc/rust/parse/rust-parse.h +++ b/gcc/rust/parse/rust-parse.h @@ -164,7 +164,7 @@ public: std::unique_ptr<AST::InherentImplItem> parse_inherent_impl_item (); std::unique_ptr<AST::TraitImplItem> parse_trait_impl_item (); AST::PathInExpression parse_path_in_expression (); - std::vector<std::unique_ptr<AST::LifetimeParam> > parse_lifetime_params (); + std::vector<std::unique_ptr<AST::LifetimeParam>> parse_lifetime_params (); AST::Visibility parse_visibility (); std::unique_ptr<AST::IdentifierPattern> parse_identifier_pattern (); std::unique_ptr<AST::Token> parse_identifier_or_keyword_token (); @@ -246,17 +246,17 @@ private: std::unique_ptr<AST::Function> parse_function (AST::Visibility vis, AST::AttrVec outer_attrs); AST::FunctionQualifiers parse_function_qualifiers (); - std::vector<std::unique_ptr<AST::GenericParam> > + std::vector<std::unique_ptr<AST::GenericParam>> parse_generic_params_in_angles (); template <typename EndTokenPred> - std::vector<std::unique_ptr<AST::GenericParam> > + std::vector<std::unique_ptr<AST::GenericParam>> parse_generic_params (EndTokenPred is_end_token); template <typename EndTokenPred> std::unique_ptr<AST::GenericParam> parse_generic_param (EndTokenPred is_end_token); template <typename EndTokenPred> - std::vector<std::unique_ptr<AST::LifetimeParam> > + std::vector<std::unique_ptr<AST::LifetimeParam>> parse_lifetime_params (EndTokenPred is_end_token); std::vector<AST::LifetimeParam> parse_lifetime_params_objs (); template <typename EndTokenPred> @@ -268,15 +268,15 @@ private: 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 (); + std::vector<std::unique_ptr<AST::TypeParam>> parse_type_params (); template <typename EndTokenPred> - std::vector<std::unique_ptr<AST::TypeParam> > + std::vector<std::unique_ptr<AST::TypeParam>> parse_type_params (EndTokenPred is_end_token); std::unique_ptr<AST::TypeParam> parse_type_param (); template <typename EndTokenPred> - std::vector<AST::FunctionParam> + std::vector<std::unique_ptr<AST::Param>> parse_function_params (EndTokenPred is_end_token); - AST::FunctionParam parse_function_param (); + std::unique_ptr<AST::Param> parse_function_param (); std::unique_ptr<AST::Type> parse_function_return_type (); AST::WhereClause parse_where_clause (); std::unique_ptr<AST::WhereClauseItem> parse_where_clause_item (); @@ -286,9 +286,9 @@ private: parse_type_bound_where_clause_item (); std::vector<AST::LifetimeParam> parse_for_lifetimes (); template <typename EndTokenPred> - std::vector<std::unique_ptr<AST::TypeParamBound> > + 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::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 (); @@ -317,9 +317,9 @@ private: AST::TupleField parse_tuple_field (); std::unique_ptr<AST::Enum> parse_enum (AST::Visibility vis, AST::AttrVec outer_attrs); - std::vector<std::unique_ptr<AST::EnumItem> > parse_enum_items (); + std::vector<std::unique_ptr<AST::EnumItem>> parse_enum_items (); template <typename EndTokenPred> - std::vector<std::unique_ptr<AST::EnumItem> > + 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, @@ -334,7 +334,7 @@ private: parse_trait_type (AST::AttrVec outer_attrs); std::unique_ptr<AST::TraitItemConst> parse_trait_const (AST::AttrVec outer_attrs); - AST::SelfParam parse_self_param (); + std::unique_ptr<AST::Param> parse_self_param (); std::unique_ptr<AST::Impl> parse_impl (AST::Visibility vis, AST::AttrVec outer_attrs); std::unique_ptr<AST::InherentImplItem> @@ -594,7 +594,7 @@ private: parse_match_expr (AST::AttrVec outer_attrs = AST::AttrVec (), location_t pratt_parsed_loc = UNKNOWN_LOCATION); AST::MatchArm parse_match_arm (); - std::vector<std::unique_ptr<AST::Pattern> > + std::vector<std::unique_ptr<AST::Pattern>> parse_match_arm_patterns (TokenId end_token_id); std::unique_ptr<AST::Expr> parse_labelled_loop_expr (const_TokenPtr tok, AST::AttrVec outer_attrs @@ -692,7 +692,7 @@ public: // Parse items without parsing an entire crate. This function is the main // parsing loop of AST::Crate::parse_crate(). - std::vector<std::unique_ptr<AST::Item> > parse_items (); + std::vector<std::unique_ptr<AST::Item>> parse_items (); // Main entry point for parser. std::unique_ptr<AST::Crate> parse_crate (); |