diff options
Diffstat (limited to 'gcc/rust/parse/rust-parse-impl.h')
-rw-r--r-- | gcc/rust/parse/rust-parse-impl.h | 555 |
1 files changed, 288 insertions, 267 deletions
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 263ca63..35f6c89 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -29,11 +29,10 @@ #include "rust-token.h" #define INCLUDE_ALGORITHM #include "rust-diagnostics.h" -#include "rust-make-unique.h" #include "rust-dir-owner.h" #include "rust-attribute-values.h" #include "rust-keyword-values.h" -#include "rust-session-manager.h" +#include "rust-edition.h" #include "optional.h" @@ -854,6 +853,9 @@ Parser<ManagedTokenSource>::parse_attr_input () case BYTE_STRING_LITERAL: lit_type = AST::Literal::BYTE_STRING; break; + case RAW_STRING_LITERAL: + lit_type = AST::Literal::RAW_STRING; + break; case STRING_LITERAL: default: lit_type = AST::Literal::STRING; @@ -875,7 +877,10 @@ Parser<ManagedTokenSource>::parse_attr_input () return attr_input_lit; } break; + case RIGHT_PAREN: case RIGHT_SQUARE: + case RIGHT_CURLY: + case END_OF_FILE: // means AttrInput is missing, which is allowed return nullptr; default: @@ -1451,8 +1456,7 @@ Parser<ManagedTokenSource>::parse_async_item (AST::Visibility vis, auto offset = (lexer.peek_token ()->get_id () == CONST) ? 1 : 0; const_TokenPtr t = lexer.peek_token (offset); - if (Session::get_instance ().options.get_edition () - == CompileOptions::Edition::E2015) + if (get_rust_edition () == Edition::E2015) { add_error (Error (t->get_locus (), ErrorCode::E0670, "%<async fn%> is not permitted in Rust 2015")); @@ -3093,15 +3097,15 @@ template <typename EndTokenPred> std::unique_ptr<AST::GenericParam> Parser<ManagedTokenSource>::parse_generic_param (EndTokenPred is_end_token) { - auto token = lexer.peek_token (); - auto outer_attrs = parse_outer_attribute (); + auto outer_attrs = parse_outer_attributes (); std::unique_ptr<AST::GenericParam> param; + auto token = lexer.peek_token (); switch (token->get_id ()) { case LIFETIME: { auto lifetime = parse_lifetime (false); - if (lifetime.is_error ()) + if (!lifetime) { rust_error_at ( token->get_locus (), @@ -3121,7 +3125,7 @@ Parser<ManagedTokenSource>::parse_generic_param (EndTokenPred is_end_token) } param = std::unique_ptr<AST::LifetimeParam> (new AST::LifetimeParam ( - std::move (lifetime), std::move (lifetime_bounds), + std::move (lifetime.value ()), std::move (lifetime_bounds), std::move (outer_attrs), token->get_locus ())); break; } @@ -3173,24 +3177,28 @@ Parser<ManagedTokenSource>::parse_generic_param (EndTokenPred is_end_token) return nullptr; // optional default value - auto default_expr = AST::GenericArg::create_error (); + tl::optional<AST::GenericArg> default_expr = tl::nullopt; if (lexer.peek_token ()->get_id () == EQUAL) { lexer.skip_token (); auto tok = lexer.peek_token (); default_expr = parse_generic_arg (); - if (default_expr.is_error ()) - rust_error_at (tok->get_locus (), - "invalid token for start of default value for " - "const generic parameter: expected %<block%>, " - "%<identifier%> or %<literal%>, got %qs", - token_id_to_str (tok->get_id ())); + if (!default_expr) + { + rust_error_at (tok->get_locus (), + "invalid token for start of default value for " + "const generic parameter: expected %<block%>, " + "%<identifier%> or %<literal%>, got %qs", + token_id_to_str (tok->get_id ())); + return nullptr; + } // At this point, we *know* that we are parsing a const // expression - if (default_expr.get_kind () == AST::GenericArg::Kind::Either) - default_expr = default_expr.disambiguate_to_const (); + if (default_expr.value ().get_kind () + == AST::GenericArg::Kind::Either) + default_expr = default_expr.value ().disambiguate_to_const (); } param = std::unique_ptr<AST::ConstGenericParam> ( @@ -3275,16 +3283,16 @@ Parser<ManagedTokenSource>::parse_lifetime_params () while (lexer.peek_token ()->get_id () != END_OF_FILE) { - AST::LifetimeParam lifetime_param = parse_lifetime_param (); + auto lifetime_param = parse_lifetime_param (); - if (lifetime_param.is_error ()) + if (!lifetime_param) { // can't treat as error as only way to get out with trailing comma break; } lifetime_params.push_back (std::unique_ptr<AST::LifetimeParam> ( - new AST::LifetimeParam (std::move (lifetime_param)))); + new AST::LifetimeParam (std::move (lifetime_param.value ())))); if (lexer.peek_token ()->get_id () != COMMA) break; @@ -3310,9 +3318,9 @@ Parser<ManagedTokenSource>::parse_lifetime_params (EndTokenPred is_end_token) // if end_token is not specified, it defaults to EOF, so should work fine while (!is_end_token (lexer.peek_token ()->get_id ())) { - AST::LifetimeParam lifetime_param = parse_lifetime_param (); + auto lifetime_param = parse_lifetime_param (); - if (lifetime_param.is_error ()) + if (!lifetime_param) { /* TODO: is it worth throwing away all lifetime params just because * one failed? */ @@ -3350,9 +3358,9 @@ Parser<ManagedTokenSource>::parse_lifetime_params_objs () // bad control structure as end token cannot be guaranteed while (true) { - AST::LifetimeParam lifetime_param = parse_lifetime_param (); + auto lifetime_param = parse_lifetime_param (); - if (lifetime_param.is_error ()) + if (!lifetime_param) { // not an error as only way to exit if trailing comma break; @@ -3385,9 +3393,9 @@ Parser<ManagedTokenSource>::parse_lifetime_params_objs ( while (!is_end_token (lexer.peek_token ()->get_id ())) { - AST::LifetimeParam lifetime_param = parse_lifetime_param (); + auto lifetime_param = parse_lifetime_param (); - if (lifetime_param.is_error ()) + if (!lifetime_param) { /* TODO: is it worth throwing away all lifetime params just because * one failed? */ @@ -3398,7 +3406,7 @@ Parser<ManagedTokenSource>::parse_lifetime_params_objs ( return {}; } - lifetime_params.push_back (std::move (lifetime_param)); + lifetime_params.push_back (std::move (lifetime_param.value ())); if (lexer.peek_token ()->get_id () != COMMA) break; @@ -3457,18 +3465,18 @@ Parser<ManagedTokenSource>::parse_non_ptr_sequence ( /* Parses a single lifetime generic parameter (not including comma). */ template <typename ManagedTokenSource> -AST::LifetimeParam +tl::expected<AST::LifetimeParam, ParseLifetimeParamError> Parser<ManagedTokenSource>::parse_lifetime_param () { - // parse outer attribute, which is optional and may not exist - AST::Attribute outer_attr = parse_outer_attribute (); + // parse outer attributes, which are optional and may not exist + auto outer_attrs = parse_outer_attributes (); // save lifetime token - required const_TokenPtr lifetime_tok = lexer.peek_token (); if (lifetime_tok->get_id () != LIFETIME) { - // if lifetime is missing, must not be a lifetime param, so return null - return AST::LifetimeParam::create_error (); + // if lifetime is missing, must not be a lifetime param, so return error + return tl::make_unexpected<ParseLifetimeParamError> ({}); } lexer.skip_token (); AST::Lifetime lifetime (AST::Lifetime::NAMED, lifetime_tok->get_str (), @@ -3484,7 +3492,7 @@ Parser<ManagedTokenSource>::parse_lifetime_param () } return AST::LifetimeParam (std::move (lifetime), std::move (lifetime_bounds), - std::move (outer_attr), + std::move (outer_attrs), lifetime_tok->get_locus ()); } @@ -3561,8 +3569,8 @@ template <typename ManagedTokenSource> std::unique_ptr<AST::TypeParam> Parser<ManagedTokenSource>::parse_type_param () { - // parse outer attribute, which is optional and may not exist - AST::Attribute outer_attr = parse_outer_attribute (); + // parse outer attributes, which are optional and may not exist + auto outer_attrs = parse_outer_attributes (); const_TokenPtr identifier_tok = lexer.peek_token (); if (identifier_tok->get_id () != IDENTIFIER) @@ -3605,7 +3613,7 @@ Parser<ManagedTokenSource>::parse_type_param () return std::unique_ptr<AST::TypeParam> ( new AST::TypeParam (std::move (ident), identifier_tok->get_locus (), std::move (type_param_bounds), std::move (type), - std::move (outer_attr))); + std::move (outer_attrs))); } /* Parses regular (i.e. non-generic) parameters in functions or methods. Also @@ -3680,7 +3688,7 @@ Parser<ManagedTokenSource>::parse_function_param () if (lexer.peek_token ()->get_id () == ELLIPSIS) // Unnamed variadic { lexer.skip_token (); // Skip ellipsis - return Rust::make_unique<AST::VariadicParam> ( + return std::make_unique<AST::VariadicParam> ( AST::VariadicParam (std::move (outer_attrs), locus)); } @@ -3702,7 +3710,7 @@ Parser<ManagedTokenSource>::parse_function_param () if (lexer.peek_token ()->get_id () == ELLIPSIS) // Named variadic { lexer.skip_token (); // Skip ellipsis - return Rust::make_unique<AST::VariadicParam> ( + return std::make_unique<AST::VariadicParam> ( AST::VariadicParam (std::move (param_pattern), std::move (outer_attrs), locus)); } @@ -3713,7 +3721,7 @@ Parser<ManagedTokenSource>::parse_function_param () { return nullptr; } - return Rust::make_unique<AST::FunctionParam> ( + return std::make_unique<AST::FunctionParam> ( AST::FunctionParam (std::move (param_pattern), std::move (param_type), std::move (outer_attrs), locus)); } @@ -3814,12 +3822,13 @@ template <typename ManagedTokenSource> std::unique_ptr<AST::LifetimeWhereClauseItem> Parser<ManagedTokenSource>::parse_lifetime_where_clause_item () { - AST::Lifetime lifetime = parse_lifetime (false); - if (lifetime.is_error ()) + auto parsed_lifetime = parse_lifetime (false); + if (!parsed_lifetime) { // TODO: error here? return nullptr; } + auto lifetime = parsed_lifetime.value (); if (!skip_token (COLON)) { @@ -4012,7 +4021,7 @@ Parser<ManagedTokenSource>::parse_type_param_bound () { case LIFETIME: return std::unique_ptr<AST::Lifetime> ( - new AST::Lifetime (parse_lifetime (false))); + new AST::Lifetime (parse_lifetime (false).value ())); case LEFT_PAREN: case QUESTION_MARK: case FOR: @@ -4085,13 +4094,13 @@ Parser<ManagedTokenSource>::parse_lifetime_bounds () while (true) { - AST::Lifetime lifetime = parse_lifetime (false); + auto lifetime = parse_lifetime (false); // quick exit for parsing failure - if (lifetime.is_error ()) + if (!lifetime) break; - lifetime_bounds.push_back (std::move (lifetime)); + lifetime_bounds.push_back (std::move (lifetime.value ())); /* plus is maybe not allowed at end - spec defines it weirdly, so * assuming allowed at end */ @@ -4115,9 +4124,9 @@ Parser<ManagedTokenSource>::parse_lifetime_bounds (EndTokenPred is_end_token) while (!is_end_token (lexer.peek_token ()->get_id ())) { - AST::Lifetime lifetime = parse_lifetime (false); + auto lifetime = parse_lifetime (false); - if (lifetime.is_error ()) + if (!lifetime) { /* TODO: is it worth throwing away all lifetime bound info just * because one failed? */ @@ -4128,7 +4137,7 @@ Parser<ManagedTokenSource>::parse_lifetime_bounds (EndTokenPred is_end_token) return {}; } - lifetime_bounds.push_back (std::move (lifetime)); + lifetime_bounds.push_back (std::move (lifetime.value ())); /* plus is maybe not allowed at end - spec defines it weirdly, so * assuming allowed at end */ @@ -4145,14 +4154,20 @@ Parser<ManagedTokenSource>::parse_lifetime_bounds (EndTokenPred is_end_token) /* Parses a lifetime token (named, 'static, or '_). Also handles lifetime not * existing. */ template <typename ManagedTokenSource> -AST::Lifetime +tl::expected<AST::Lifetime, ParseLifetimeError> Parser<ManagedTokenSource>::parse_lifetime (bool allow_elided) { const_TokenPtr lifetime_tok = lexer.peek_token (); if (lifetime_tok->get_id () != LIFETIME) { - return (allow_elided) ? AST::Lifetime::elided () - : AST::Lifetime::error (); + if (allow_elided) + { + return AST::Lifetime::elided (); + } + else + { + return tl::make_unexpected<ParseLifetimeError> ({}); + } } lexer.skip_token (); @@ -5934,106 +5949,6 @@ Parser<ManagedTokenSource>::parse_extern_block (AST::Visibility vis, std::move (outer_attrs), locus)); } -template <typename ManagedTokenSource> -AST::NamedFunctionParam -Parser<ManagedTokenSource>::parse_named_function_param () -{ - AST::AttrVec outer_attrs = parse_outer_attributes (); - location_t locus = lexer.peek_token ()->get_locus (); - - if (lexer.peek_token ()->get_id () == ELLIPSIS) // Unnamed variadic - { - lexer.skip_token (); // Skip ellipsis - return AST::NamedFunctionParam (std::move (outer_attrs), locus); - } - - // parse identifier/_ - std::string name; - - const_TokenPtr t = lexer.peek_token (); - location_t name_location = t->get_locus (); - switch (t->get_id ()) - { - case IDENTIFIER: - name = t->get_str (); - lexer.skip_token (); - break; - case UNDERSCORE: - name = "_"; - lexer.skip_token (); - break; - default: - // this is not a function param, but not necessarily an error - return AST::NamedFunctionParam::create_error (); - } - - if (!skip_token (COLON)) - { - // skip after somewhere? - return AST::NamedFunctionParam::create_error (); - } - - if (lexer.peek_token ()->get_id () == ELLIPSIS) // Named variadic - { - lexer.skip_token (); // Skip ellipsis - return AST::NamedFunctionParam (std::move (name), std::move (outer_attrs), - locus); - } - - // parse (required) type - std::unique_ptr<AST::Type> param_type = parse_type (); - if (param_type == nullptr) - { - Error error ( - lexer.peek_token ()->get_locus (), - "could not parse param type in extern block function declaration"); - add_error (std::move (error)); - - skip_after_semicolon (); - return AST::NamedFunctionParam::create_error (); - } - - return AST::NamedFunctionParam (std::move (name), std::move (param_type), - std::move (outer_attrs), name_location); -} - -template <typename ManagedTokenSource> -template <typename EndTokenPred> -std::vector<AST::NamedFunctionParam> -Parser<ManagedTokenSource>::parse_named_function_params ( - EndTokenPred is_end_token) -{ - std::vector<AST::NamedFunctionParam> params; - if (is_end_token (lexer.peek_token ()->get_id ())) - return params; - - auto initial_param = parse_named_function_param (); - if (initial_param.is_error ()) - return params; - - params.push_back (std::move (initial_param)); - auto t = lexer.peek_token (); - while (t->get_id () == COMMA) - { - lexer.skip_token (); - if (is_end_token (lexer.peek_token ()->get_id ())) - break; - - auto param = parse_named_function_param (); - if (param.is_error ()) - { - Error error (lexer.peek_token ()->get_locus (), - "failed to parse param in c function params"); - add_error (error); - return std::vector<AST::NamedFunctionParam> (); - } - params.push_back (std::move (param)); - t = lexer.peek_token (); - } - params.shrink_to_fit (); - return params; -} - // Parses a single extern block item (static or function declaration). template <typename ManagedTokenSource> std::unique_ptr<AST::ExternalItem> @@ -6262,6 +6177,10 @@ Parser<ManagedTokenSource>::parse_let_stmt (AST::AttrVec outer_attrs, } } + tl::optional<std::unique_ptr<AST::Expr>> else_expr = tl::nullopt; + if (maybe_skip_token (ELSE)) + else_expr = parse_block_expr (); + if (restrictions.consume_semi) { // `stmt` macro variables are parsed without a semicolon, but should be @@ -6276,7 +6195,7 @@ Parser<ManagedTokenSource>::parse_let_stmt (AST::AttrVec outer_attrs, return std::unique_ptr<AST::LetStmt> ( new AST::LetStmt (std::move (pattern), std::move (expr), std::move (type), - std::move (outer_attrs), locus)); + std::move (else_expr), std::move (outer_attrs), locus)); } // Parses a type path. @@ -6337,7 +6256,7 @@ Parser<ManagedTokenSource>::parse_type_path () } template <typename ManagedTokenSource> -AST::GenericArg +tl::optional<AST::GenericArg> Parser<ManagedTokenSource>::parse_generic_arg () { auto tok = lexer.peek_token (); @@ -6358,7 +6277,7 @@ Parser<ManagedTokenSource>::parse_generic_arg () if (type) return AST::GenericArg::create_type (std::move (type)); else - return AST::GenericArg::create_error (); + return tl::nullopt; } else if (next_tok->get_id () == COLON) { @@ -6375,7 +6294,7 @@ Parser<ManagedTokenSource>::parse_generic_arg () if (type) return AST::GenericArg::create_type (std::move (type)); else - return AST::GenericArg::create_error (); + return tl::nullopt; } lexer.skip_token (); return AST::GenericArg::create_ambiguous (tok->get_str (), @@ -6401,12 +6320,12 @@ Parser<ManagedTokenSource>::parse_generic_arg () if (type) return AST::GenericArg::create_type (std::move (type)); else - return AST::GenericArg::create_error (); + return tl::nullopt; } } if (!expr) - return AST::GenericArg::create_error (); + return tl::nullopt; return AST::GenericArg::create_const (std::move (expr)); } @@ -6435,14 +6354,14 @@ Parser<ManagedTokenSource>::parse_path_generic_args () location_t locus = t->get_locus (); while (!is_right_angle_tok (t->get_id ())) { - AST::Lifetime lifetime = parse_lifetime (false); - if (lifetime.is_error ()) + auto lifetime = parse_lifetime (false); + if (!lifetime) { // not necessarily an error break; } - lifetime_args.push_back (std::move (lifetime)); + lifetime_args.push_back (std::move (lifetime.value ())); // if next token isn't comma, then it must be end of list if (lexer.peek_token ()->get_id () != COMMA) @@ -6471,9 +6390,9 @@ Parser<ManagedTokenSource>::parse_path_generic_args () break; auto arg = parse_generic_arg (); - if (!arg.is_error ()) + if (arg) { - generic_args.emplace_back (std::move (arg)); + generic_args.emplace_back (std::move (arg.value ())); } // FIXME: Do we need to break if we encounter an error? @@ -7056,10 +6975,12 @@ Parser<ManagedTokenSource>::parse_self_param () // now test whether it has a lifetime if (lexer.peek_token ()->get_id () == LIFETIME) { - lifetime = parse_lifetime (true); - // something went wrong somehow - if (lifetime.is_error ()) + if (auto parsed_lifetime = parse_lifetime (true)) + { + lifetime = parsed_lifetime.value (); + } + else { Error error (lexer.peek_token ()->get_locus (), "failed to parse lifetime in self param"); @@ -7121,14 +7042,14 @@ Parser<ManagedTokenSource>::parse_self_param () if (has_reference) { - return Rust::make_unique<AST::SelfParam> (std::move (lifetime), has_mut, - locus); + return std::make_unique<AST::SelfParam> (std::move (lifetime), has_mut, + locus); } else { // note that type may be nullptr here and that's fine - return Rust::make_unique<AST::SelfParam> (std::move (type), has_mut, - locus); + return std::make_unique<AST::SelfParam> (std::move (type), has_mut, + locus); } } @@ -7156,10 +7077,7 @@ Parser<ManagedTokenSource>::parse_expr_stmt (AST::AttrVec outer_attrs, if (lexer.peek_token ()->get_id () == EXCLAM) { - // Bind a reference to avoid -Wredundant-move on post-P1825R0 - // compilers. Change to non-reference type and remove the moves - // below once C++20 is required to build gcc. - std::unique_ptr<AST::MacroInvocation> &&invoc + std::unique_ptr<AST::MacroInvocation> invoc = parse_macro_invocation_partial (std::move (path), std::move (outer_attrs)); @@ -7167,7 +7085,7 @@ Parser<ManagedTokenSource>::parse_expr_stmt (AST::AttrVec outer_attrs, { invoc->add_semicolon (); // Macro invocation with semicolon. - return std::move (invoc); + return invoc; } TokenId after_macro = lexer.peek_token ()->get_id (); @@ -7175,14 +7093,14 @@ Parser<ManagedTokenSource>::parse_expr_stmt (AST::AttrVec outer_attrs, if (restrictions.allow_close_after_expr_stmt && (after_macro == RIGHT_PAREN || after_macro == RIGHT_CURLY || after_macro == RIGHT_SQUARE)) - return std::move (invoc); + return invoc; if (invoc->get_invoc_data ().get_delim_tok_tree ().get_delim_type () == AST::CURLY && after_macro != DOT && after_macro != QUESTION_MARK) { rust_debug ("braced macro statement"); - return std::move (invoc); + return invoc; } null_denotation = std::move (invoc); @@ -7248,9 +7166,9 @@ Parser<ManagedTokenSource>::parse_expr_stmt (AST::AttrVec outer_attrs, // Parses a block expression, including the curly braces at start and end. template <typename ManagedTokenSource> std::unique_ptr<AST::BlockExpr> -Parser<ManagedTokenSource>::parse_block_expr (AST::AttrVec outer_attrs, - AST::LoopLabel label, - location_t pratt_parsed_loc) +Parser<ManagedTokenSource>::parse_block_expr ( + AST::AttrVec outer_attrs, tl::optional<AST::LoopLabel> label, + location_t pratt_parsed_loc) { location_t locus = pratt_parsed_loc; if (locus == UNKNOWN_LOCATION) @@ -7320,6 +7238,30 @@ Parser<ManagedTokenSource>::parse_block_expr (AST::AttrVec outer_attrs, std::move (label), locus, end_locus)); } +/* Parse a "const block", a block preceded by the `const` keyword whose + * statements can be const evaluated and used in constant contexts */ +template <typename ManagedTokenSource> +std::unique_ptr<AST::ConstBlock> +Parser<ManagedTokenSource>::parse_const_block_expr (AST::AttrVec outer_attrs, + location_t locus) +{ + auto block = parse_block_expr (); + + if (!block) + { + add_error (Error (locus, "failed to parse inner block in const block")); + skip_after_end_block (); + + return nullptr; + } + + auto block_locus = block->get_locus (); + + return std::make_unique<AST::ConstBlock> (AST::AnonConst (std::move (block), + block_locus), + locus, std::move (outer_attrs)); +} + /* Parses a "grouped" expression (expression in parentheses), used to control * precedence. */ template <typename ManagedTokenSource> @@ -7511,6 +7453,11 @@ Parser<ManagedTokenSource>::parse_literal_expr (AST::AttrVec outer_attrs) literal_value = t->get_str (); lexer.skip_token (); break; + case RAW_STRING_LITERAL: + type = AST::Literal::RAW_STRING; + literal_value = t->get_str (); + lexer.skip_token (); + break; case INT_LITERAL: type = AST::Literal::INT; literal_value = t->get_str (); @@ -7550,6 +7497,27 @@ Parser<ManagedTokenSource>::parse_literal_expr (AST::AttrVec outer_attrs) t->get_locus ())); } +template <typename ManagedTokenSource> +std::unique_ptr<AST::BoxExpr> +Parser<ManagedTokenSource>::parse_box_expr (AST::AttrVec outer_attrs, + location_t pratt_parsed_loc) +{ + location_t locus = pratt_parsed_loc; + if (locus == UNKNOWN_LOCATION) + { + locus = lexer.peek_token ()->get_locus (); + skip_token (BOX); + } + + ParseRestrictions restrictions; + restrictions.expr_can_be_null = false; + + std::unique_ptr<AST::Expr> expr = parse_expr (AST::AttrVec (), restrictions); + + return std::unique_ptr<AST::BoxExpr> ( + new AST::BoxExpr (std::move (expr), std::move (outer_attrs), locus)); +} + // Parses a return expression (including any expression to return). template <typename ManagedTokenSource> std::unique_ptr<AST::ReturnExpr> @@ -7588,12 +7556,10 @@ Parser<ManagedTokenSource>::parse_break_expr (AST::AttrVec outer_attrs, skip_token (BREAK); } - // parse label (lifetime) if it exists - create dummy first - AST::Lifetime label = AST::Lifetime::error (); - if (lexer.peek_token ()->get_id () == LIFETIME) - { - label = parse_lifetime (false); - } + auto parsed_label = parse_lifetime (false); + auto label = (parsed_label) + ? tl::optional<AST::Lifetime> (parsed_label.value ()) + : tl::nullopt; // parse break return expression if it exists ParseRestrictions restrictions; @@ -7619,12 +7585,10 @@ Parser<ManagedTokenSource>::parse_continue_expr (AST::AttrVec outer_attrs, skip_token (CONTINUE); } - // parse label (lifetime) if it exists - create dummy first - AST::Lifetime label = AST::Lifetime::error (); - if (lexer.peek_token ()->get_id () == LIFETIME) - { - label = parse_lifetime (false); - } + auto parsed_label = parse_lifetime (false); + auto label = (parsed_label) + ? tl::optional<AST::Lifetime> (parsed_label.value ()) + : tl::nullopt; return std::unique_ptr<AST::ContinueExpr> ( new AST::ContinueExpr (std::move (label), std::move (outer_attrs), locus)); @@ -7632,14 +7596,15 @@ Parser<ManagedTokenSource>::parse_continue_expr (AST::AttrVec outer_attrs, // Parses a loop label used in loop expressions. template <typename ManagedTokenSource> -AST::LoopLabel +tl::expected<AST::LoopLabel, ParseLoopLabelError> Parser<ManagedTokenSource>::parse_loop_label (const_TokenPtr tok) { // parse lifetime - if doesn't exist, assume no label if (tok->get_id () != LIFETIME) { // not necessarily an error - return AST::LoopLabel::error (); + return tl::unexpected<ParseLoopLabelError> ( + ParseLoopLabelError::NOT_LOOP_LABEL); } /* FIXME: check for named lifetime requirement here? or check in semantic * analysis phase? */ @@ -7648,10 +7613,12 @@ Parser<ManagedTokenSource>::parse_loop_label (const_TokenPtr tok) if (!skip_token (COLON)) { // skip somewhere? - return AST::LoopLabel::error (); + return tl::unexpected<ParseLoopLabelError> ( + ParseLoopLabelError::MISSING_COLON); } - return AST::LoopLabel (std::move (label), tok->get_locus ()); + return tl::expected<AST::LoopLabel, ParseLoopLabelError> ( + AST::LoopLabel (std::move (label), tok->get_locus ())); } /* Parses an if expression of any kind, including with else, else if, else if @@ -8004,16 +7971,16 @@ Parser<ManagedTokenSource>::parse_if_let_expr (AST::AttrVec outer_attrs, template <typename ManagedTokenSource> std::unique_ptr<AST::LoopExpr> Parser<ManagedTokenSource>::parse_loop_expr (AST::AttrVec outer_attrs, - AST::LoopLabel label, + tl::optional<AST::LoopLabel> label, location_t pratt_parsed_loc) { location_t locus = pratt_parsed_loc; if (locus == UNKNOWN_LOCATION) { - if (label.is_error ()) - locus = lexer.peek_token ()->get_locus (); + if (label) + locus = label->get_locus (); else - locus = label.get_locus (); + locus = lexer.peek_token ()->get_locus (); if (!skip_token (LOOP)) { @@ -8023,8 +7990,8 @@ Parser<ManagedTokenSource>::parse_loop_expr (AST::AttrVec outer_attrs, } else { - if (!label.is_error ()) - locus = label.get_locus (); + if (label) + locus = label->get_locus (); } // parse loop body, which is required @@ -8047,17 +8014,17 @@ Parser<ManagedTokenSource>::parse_loop_expr (AST::AttrVec outer_attrs, * via parse_labelled_loop_expr, which would call this. */ template <typename ManagedTokenSource> std::unique_ptr<AST::WhileLoopExpr> -Parser<ManagedTokenSource>::parse_while_loop_expr (AST::AttrVec outer_attrs, - AST::LoopLabel label, - location_t pratt_parsed_loc) +Parser<ManagedTokenSource>::parse_while_loop_expr ( + AST::AttrVec outer_attrs, tl::optional<AST::LoopLabel> label, + location_t pratt_parsed_loc) { location_t locus = pratt_parsed_loc; if (locus == UNKNOWN_LOCATION) { - if (label.is_error ()) - locus = lexer.peek_token ()->get_locus (); + if (label) + locus = label->get_locus (); else - locus = label.get_locus (); + locus = lexer.peek_token ()->get_locus (); if (!skip_token (WHILE)) { @@ -8067,8 +8034,8 @@ Parser<ManagedTokenSource>::parse_while_loop_expr (AST::AttrVec outer_attrs, } else { - if (!label.is_error ()) - locus = label.get_locus (); + if (label) + locus = label->get_locus (); } // ensure it isn't a while let loop @@ -8120,14 +8087,14 @@ Parser<ManagedTokenSource>::parse_while_loop_expr (AST::AttrVec outer_attrs, * parsed via parse_labelled_loop_expr, which would call this. */ template <typename ManagedTokenSource> std::unique_ptr<AST::WhileLetLoopExpr> -Parser<ManagedTokenSource>::parse_while_let_loop_expr (AST::AttrVec outer_attrs, - AST::LoopLabel label) +Parser<ManagedTokenSource>::parse_while_let_loop_expr ( + AST::AttrVec outer_attrs, tl::optional<AST::LoopLabel> label) { location_t locus = UNKNOWN_LOCATION; - if (label.is_error ()) - locus = lexer.peek_token ()->get_locus (); + if (label) + locus = label->get_locus (); else - locus = label.get_locus (); + locus = lexer.peek_token ()->get_locus (); maybe_skip_token (WHILE); /* check for possible accidental recognition of a while loop as a while let @@ -8194,14 +8161,14 @@ Parser<ManagedTokenSource>::parse_while_let_loop_expr (AST::AttrVec outer_attrs, * parse_labelled_loop_expr, which would call this. */ template <typename ManagedTokenSource> std::unique_ptr<AST::ForLoopExpr> -Parser<ManagedTokenSource>::parse_for_loop_expr (AST::AttrVec outer_attrs, - AST::LoopLabel label) +Parser<ManagedTokenSource>::parse_for_loop_expr ( + AST::AttrVec outer_attrs, tl::optional<AST::LoopLabel> label) { location_t locus = UNKNOWN_LOCATION; - if (label.is_error ()) - locus = lexer.peek_token ()->get_locus (); + if (label) + locus = label->get_locus (); else - locus = label.get_locus (); + locus = lexer.peek_token ()->get_locus (); maybe_skip_token (FOR); // parse pattern, which is required @@ -8279,8 +8246,9 @@ Parser<ManagedTokenSource>::parse_labelled_loop_expr (const_TokenPtr tok, } // parse loop label (required) - AST::LoopLabel label = parse_loop_label (tok); - if (label.is_error ()) + // TODO: Convert this return type to tl::expected instead of tl::optional + auto parsed_label = parse_loop_label (tok); + if (!parsed_label) { Error error (lexer.peek_token ()->get_locus (), "failed to parse loop label in labelled loop expr"); @@ -8290,6 +8258,10 @@ Parser<ManagedTokenSource>::parse_labelled_loop_expr (const_TokenPtr tok, return nullptr; } + auto label = parsed_label + ? tl::optional<AST::LoopLabel> (parsed_label.value ()) + : tl::nullopt; + // branch on next token const_TokenPtr t = lexer.peek_token (); switch (t->get_id ()) @@ -8664,10 +8636,10 @@ Parser<ManagedTokenSource>::parse_array_expr (AST::AttrVec outer_attrs, std::vector<std::unique_ptr<AST::Expr>> exprs; auto array_elems - = Rust::make_unique<AST::ArrayElemsValues> (std::move (exprs), locus); - return Rust::make_unique<AST::ArrayExpr> (std::move (array_elems), - std::move (inner_attrs), - std::move (outer_attrs), locus); + = std::make_unique<AST::ArrayElemsValues> (std::move (exprs), locus); + return std::make_unique<AST::ArrayExpr> (std::move (array_elems), + std::move (inner_attrs), + std::move (outer_attrs), locus); } else { @@ -9169,14 +9141,8 @@ Parser<ManagedTokenSource>::parse_type (bool save_errors) t = lexer.peek_token (); if (t->get_id () != PLUS) { - // convert trait bound to value object - AST::TraitBound value_bound (*initial_bound); - - // DEBUG: removed as unique ptr, so should auto-delete - // delete initial_bound; - return std::unique_ptr<AST::ImplTraitTypeOneBound> ( - new AST::ImplTraitTypeOneBound (std::move (value_bound), + new AST::ImplTraitTypeOneBound (std::move (initial_bound), locus)); } @@ -9667,8 +9633,12 @@ Parser<ManagedTokenSource>::parse_reference_type_inner (location_t locus) AST::Lifetime lifetime = AST::Lifetime::elided (); if (lexer.peek_token ()->get_id () == LIFETIME) { - lifetime = parse_lifetime (true); - if (lifetime.is_error ()) + auto parsed_lifetime = parse_lifetime (true); + if (parsed_lifetime) + { + lifetime = parsed_lifetime.value (); + } + else { Error error (lexer.peek_token ()->get_locus (), "failed to parse lifetime in reference type"); @@ -10003,11 +9973,8 @@ Parser<ManagedTokenSource>::parse_type_no_bounds () return nullptr; } - // convert trait bound to value object - AST::TraitBound value_bound (*initial_bound); - return std::unique_ptr<AST::ImplTraitTypeOneBound> ( - new AST::ImplTraitTypeOneBound (std::move (value_bound), locus)); + new AST::ImplTraitTypeOneBound (std::move (initial_bound), locus)); } case DYN: case QUESTION_MARK: { @@ -10240,8 +10207,10 @@ Parser<ManagedTokenSource>::parse_literal_or_range_pattern () } const_TokenPtr next = lexer.peek_token (); - if (next->get_id () == DOT_DOT_EQ || next->get_id () == ELLIPSIS) + if (next->get_id () == DOT_DOT_EQ || next->get_id () == ELLIPSIS + || next->get_id () == DOT_DOT) { + AST::RangeKind kind = AST::tokenid_to_rangekind (next->get_id ()); // range pattern lexer.skip_token (); std::unique_ptr<AST::RangePatternBound> lower ( @@ -10262,7 +10231,7 @@ Parser<ManagedTokenSource>::parse_literal_or_range_pattern () } return std::unique_ptr<AST::RangePattern> ( - new AST::RangePattern (std::move (lower), std::move (upper), + new AST::RangePattern (std::move (lower), std::move (upper), kind, range_lower->get_locus ())); } else @@ -10458,6 +10427,11 @@ Parser<ManagedTokenSource>::parse_pattern_no_alt () return std::unique_ptr<AST::LiteralPattern> ( new AST::LiteralPattern (t->get_str (), AST::Literal::BYTE_STRING, t->get_locus (), t->get_type_hint ())); + case RAW_STRING_LITERAL: + lexer.skip_token (); + return std::unique_ptr<AST::LiteralPattern> ( + new AST::LiteralPattern (t->get_str (), AST::Literal::RAW_STRING, + t->get_locus (), t->get_type_hint ())); // raw string and raw byte string literals too if they are readded to // lexer case MINUS: @@ -10511,11 +10485,12 @@ Parser<ManagedTokenSource>::parse_pattern_no_alt () = parse_qualified_path_in_expression (); if (lexer.peek_token ()->get_id () == DOT_DOT_EQ - || lexer.peek_token ()->get_id () == ELLIPSIS) + || lexer.peek_token ()->get_id () == ELLIPSIS + || lexer.peek_token ()->get_id () == DOT_DOT) { // qualified range pattern bound, so parse rest of range pattern - bool has_ellipsis_syntax - = lexer.peek_token ()->get_id () == ELLIPSIS; + AST::RangeKind kind + = AST::tokenid_to_rangekind (lexer.peek_token ()->get_id ()); lexer.skip_token (); std::unique_ptr<AST::RangePatternBoundQualPath> lower_bound ( @@ -10525,8 +10500,8 @@ Parser<ManagedTokenSource>::parse_pattern_no_alt () return std::unique_ptr<AST::RangePattern> ( new AST::RangePattern (std::move (lower_bound), - std::move (upper_bound), t->get_locus (), - has_ellipsis_syntax)); + std::move (upper_bound), kind, + t->get_locus ())); } else { @@ -10548,10 +10523,10 @@ Parser<ManagedTokenSource>::parse_pattern_no_alt () switch (next->get_id ()) { case DOT_DOT_EQ: + case DOT_DOT: case ELLIPSIS: { // qualified range pattern bound, so parse rest of range pattern - bool has_ellipsis_syntax - = lexer.peek_token ()->get_id () == ELLIPSIS; + AST::RangeKind kind = AST::tokenid_to_rangekind (next->get_id ()); lexer.skip_token (); std::unique_ptr<AST::RangePatternBoundPath> lower_bound ( @@ -10561,8 +10536,8 @@ Parser<ManagedTokenSource>::parse_pattern_no_alt () return std::unique_ptr<AST::RangePattern> ( new AST::RangePattern (std::move (lower_bound), - std::move (upper_bound), - UNKNOWN_LOCATION, has_ellipsis_syntax)); + std::move (upper_bound), kind, + next->get_locus ())); } case EXCLAM: return parse_macro_invocation_partial (std::move (path), @@ -11072,9 +11047,11 @@ Parser<ManagedTokenSource>::parse_ident_leading_pattern () std::move (elems))); } case DOT_DOT_EQ: + case DOT_DOT: case ELLIPSIS: { // range - bool has_ellipsis_syntax = lexer.peek_token ()->get_id () == ELLIPSIS; + AST::RangeKind kind + = AST::tokenid_to_rangekind (lexer.peek_token ()->get_id ()); lexer.skip_token (); @@ -11085,8 +11062,8 @@ Parser<ManagedTokenSource>::parse_ident_leading_pattern () return std::unique_ptr<AST::RangePattern> ( new AST::RangePattern (std::move (lower_bound), - std::move (upper_bound), UNKNOWN_LOCATION, - has_ellipsis_syntax)); + std::move (upper_bound), kind, + t->get_locus ())); } case PATTERN_BIND: { // only allow on single-segment paths @@ -11678,6 +11655,7 @@ template <typename ManagedTokenSource> std::unique_ptr<AST::StructExprField> Parser<ManagedTokenSource>::parse_struct_expr_field () { + AST::AttrVec outer_attrs = parse_outer_attributes (); const_TokenPtr t = lexer.peek_token (); switch (t->get_id ()) { @@ -11703,6 +11681,7 @@ Parser<ManagedTokenSource>::parse_struct_expr_field () return std::unique_ptr<AST::StructExprFieldIdentifierValue> ( new AST::StructExprFieldIdentifierValue (std::move (ident), std::move (expr), + std::move (outer_attrs), t->get_locus ())); } else @@ -11713,6 +11692,7 @@ Parser<ManagedTokenSource>::parse_struct_expr_field () return std::unique_ptr<AST::StructExprFieldIdentifier> ( new AST::StructExprFieldIdentifier (std::move (ident), + std::move (outer_attrs), t->get_locus ())); } case INT_LITERAL: { @@ -11740,6 +11720,7 @@ Parser<ManagedTokenSource>::parse_struct_expr_field () return std::unique_ptr<AST::StructExprFieldIndexValue> ( new AST::StructExprFieldIndexValue (index, std::move (expr), + std::move (outer_attrs), t->get_locus ())); } case DOT_DOT: @@ -11954,7 +11935,7 @@ Parser<ManagedTokenSource>::skip_after_end_attribute () { const_TokenPtr t = lexer.peek_token (); - while (t->get_id () != RIGHT_SQUARE) + while (t->get_id () != RIGHT_SQUARE && t->get_id () != END_OF_FILE) { lexer.skip_token (); t = lexer.peek_token (); @@ -12245,6 +12226,10 @@ Parser<ManagedTokenSource>::null_denotation_not_path ( return std::unique_ptr<AST::LiteralExpr> ( new AST::LiteralExpr (tok->get_str (), AST::Literal::BYTE_STRING, tok->get_type_hint (), {}, tok->get_locus ())); + case RAW_STRING_LITERAL: + return std::unique_ptr<AST::LiteralExpr> ( + new AST::LiteralExpr (tok->get_str (), AST::Literal::RAW_STRING, + tok->get_type_hint (), {}, tok->get_locus ())); case CHAR_LITERAL: return std::unique_ptr<AST::LiteralExpr> ( new AST::LiteralExpr (tok->get_str (), AST::Literal::CHAR, @@ -12351,33 +12336,64 @@ Parser<ManagedTokenSource>::null_denotation_not_path ( case AMP: { // (single) "borrow" expression - shared (mutable) or immutable std::unique_ptr<AST::Expr> expr = nullptr; - bool is_mut_borrow = false; + Mutability mutability = Mutability::Imm; + bool raw_borrow = false; ParseRestrictions entered_from_unary; entered_from_unary.entered_from_unary = true; if (!restrictions.can_be_struct_expr) entered_from_unary.can_be_struct_expr = false; - if (lexer.peek_token ()->get_id () == MUT) + auto is_mutability = [] (const_TokenPtr token) { + return token->get_id () == CONST || token->get_id () == MUT; + }; + + auto t = lexer.peek_token (); + // Weak raw keyword, we look (1) ahead and treat it as an identifier if + // there is no mut nor const. + if (t->get_id () == IDENTIFIER + && t->get_str () == Values::WeakKeywords::RAW + && is_mutability (lexer.peek_token (1))) + { + lexer.skip_token (); + switch (lexer.peek_token ()->get_id ()) + { + case MUT: + mutability = Mutability::Mut; + break; + case CONST: + mutability = Mutability::Imm; + break; + default: + rust_error_at (lexer.peek_token ()->get_locus (), + "raw borrow should be either const or mut"); + } + lexer.skip_token (); + expr = parse_expr (LBP_UNARY_AMP_MUT, {}, entered_from_unary); + raw_borrow = true; + } + else if (t->get_id () == MUT) { lexer.skip_token (); expr = parse_expr (LBP_UNARY_AMP_MUT, {}, entered_from_unary); - is_mut_borrow = true; + mutability = Mutability::Mut; + raw_borrow = false; } else { expr = parse_expr (LBP_UNARY_AMP, {}, entered_from_unary); + raw_borrow = false; } // FIXME: allow outer attributes on expression return std::unique_ptr<AST::BorrowExpr> ( - new AST::BorrowExpr (std::move (expr), is_mut_borrow, false, + new AST::BorrowExpr (std::move (expr), mutability, raw_borrow, false, std::move (outer_attrs), tok->get_locus ())); } case LOGICAL_AND: { // (double) "borrow" expression - shared (mutable) or immutable std::unique_ptr<AST::Expr> expr = nullptr; - bool is_mut_borrow = false; + Mutability mutability = Mutability::Imm; ParseRestrictions entered_from_unary; entered_from_unary.entered_from_unary = true; @@ -12386,16 +12402,17 @@ Parser<ManagedTokenSource>::null_denotation_not_path ( { lexer.skip_token (); expr = parse_expr (LBP_UNARY_AMP_MUT, {}, entered_from_unary); - is_mut_borrow = true; + mutability = Mutability::Mut; } else { expr = parse_expr (LBP_UNARY_AMP, {}, entered_from_unary); + mutability = Mutability::Imm; } // FIXME: allow outer attributes on expression return std::unique_ptr<AST::BorrowExpr> ( - new AST::BorrowExpr (std::move (expr), is_mut_borrow, true, + new AST::BorrowExpr (std::move (expr), mutability, false, true, std::move (outer_attrs), tok->get_locus ())); } case OR: @@ -12419,8 +12436,8 @@ Parser<ManagedTokenSource>::null_denotation_not_path ( return parse_continue_expr (std::move (outer_attrs), tok->get_locus ()); case LEFT_CURLY: // ok - this is an expression with block for once. - return parse_block_expr (std::move (outer_attrs), - AST::LoopLabel::error (), tok->get_locus ()); + return parse_block_expr (std::move (outer_attrs), tl::nullopt, + tok->get_locus ()); case IF: // if or if let, so more lookahead to find out if (lexer.peek_token ()->get_id () == LET) @@ -12436,7 +12453,7 @@ Parser<ManagedTokenSource>::null_denotation_not_path ( case LIFETIME: return parse_labelled_loop_expr (tok, std::move (outer_attrs)); case LOOP: - return parse_loop_expr (std::move (outer_attrs), AST::LoopLabel::error (), + return parse_loop_expr (std::move (outer_attrs), tl::nullopt, tok->get_locus ()); case WHILE: if (lexer.peek_token ()->get_id () == LET) @@ -12445,13 +12462,11 @@ Parser<ManagedTokenSource>::null_denotation_not_path ( } else { - return parse_while_loop_expr (std::move (outer_attrs), - AST::LoopLabel::error (), + return parse_while_loop_expr (std::move (outer_attrs), tl::nullopt, tok->get_locus ()); } case FOR: - return parse_for_loop_expr (std::move (outer_attrs), - AST::LoopLabel::error ()); + return parse_for_loop_expr (std::move (outer_attrs), tl::nullopt); case MATCH_KW: // also an expression with block return parse_match_expr (std::move (outer_attrs), tok->get_locus ()); @@ -12461,12 +12476,17 @@ Parser<ManagedTokenSource>::null_denotation_not_path ( case UNSAFE: return parse_unsafe_block_expr (std::move (outer_attrs), tok->get_locus ()); + case BOX: + return parse_box_expr (std::move (outer_attrs), tok->get_locus ()); case UNDERSCORE: add_error ( Error (tok->get_locus (), "use of %qs is not allowed on the right-side of an assignment", tok->get_token_description ())); return nullptr; + case CONST: + return parse_const_block_expr (std::move (outer_attrs), + tok->get_locus ()); default: if (!restrictions.expr_can_be_null) add_error (Error (tok->get_locus (), @@ -14059,6 +14079,7 @@ Parser<ManagedTokenSource>::parse_struct_expr_struct_partial ( /* technically this would give a struct base-only struct, but this * algorithm should work too. As such, AST type not happening. */ case IDENTIFIER: + case HASH: case INT_LITERAL: { // struct with struct expr fields |