diff options
Diffstat (limited to 'gcc/rust/parse/rust-parse-impl.h')
-rw-r--r-- | gcc/rust/parse/rust-parse-impl.h | 290 |
1 files changed, 204 insertions, 86 deletions
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 9c9208f..14bccbd 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -19,13 +19,17 @@ /* Template implementation for Rust::Parser. Previously in rust-parse.cc (before * Parser was template). Separated from rust-parse.h for readability. */ -/* DO NOT INCLUDE ANYWHERE - this is automatically included with rust-parse.h +/* DO NOT INCLUDE ANYWHERE - this is automatically included + * by rust-parse-impl-*.cc * This is also the reason why there are no include guards. */ +#include "expected.h" +#include "rust-ast.h" #include "rust-common.h" #include "rust-expr.h" #include "rust-item.h" #include "rust-common.h" +#include "rust-parse.h" #include "rust-token.h" #define INCLUDE_ALGORITHM #include "rust-diagnostics.h" @@ -654,10 +658,7 @@ Parser<ManagedTokenSource>::parse_simple_path () // Parse all other simple path segments while (lexer.peek_token ()->get_id () == SCOPE_RESOLUTION) { - // Skip scope resolution operator - lexer.skip_token (); - - AST::SimplePathSegment new_segment = parse_simple_path_segment (); + AST::SimplePathSegment new_segment = parse_simple_path_segment (1); // Return path as currently constructed if segment in error state. if (new_segment.is_error ()) @@ -685,35 +686,36 @@ Parser<ManagedTokenSource>::parse_simple_path () } /* Parses a single SimplePathSegment (does not handle the scope resolution - * operators) */ + * operators) + * Starts parsing at an offset of base_peek */ template <typename ManagedTokenSource> AST::SimplePathSegment -Parser<ManagedTokenSource>::parse_simple_path_segment () +Parser<ManagedTokenSource>::parse_simple_path_segment (int base_peek) { using namespace Values; - const_TokenPtr t = lexer.peek_token (); + const_TokenPtr t = lexer.peek_token (base_peek); switch (t->get_id ()) { case IDENTIFIER: - lexer.skip_token (); + lexer.skip_token (base_peek); return AST::SimplePathSegment (t->get_str (), t->get_locus ()); case SUPER: - lexer.skip_token (); + lexer.skip_token (base_peek); return AST::SimplePathSegment (Keywords::SUPER, t->get_locus ()); case SELF: - lexer.skip_token (); + lexer.skip_token (base_peek); return AST::SimplePathSegment (Keywords::SELF, t->get_locus ()); case CRATE: - lexer.skip_token (); + lexer.skip_token (base_peek); return AST::SimplePathSegment (Keywords::CRATE, t->get_locus ()); case DOLLAR_SIGN: - if (lexer.peek_token (1)->get_id () == CRATE) + if (lexer.peek_token (base_peek + 1)->get_id () == CRATE) { - lexer.skip_token (1); + lexer.skip_token (base_peek + 1); return AST::SimplePathSegment ("$crate", t->get_locus ()); } @@ -2807,58 +2809,10 @@ Parser<ManagedTokenSource>::parse_use_tree () } else { - /* Due to aforementioned implementation issues, the trailing :: token is - * consumed by the path, so it can not be used as a disambiguator. - * NOPE, not true anymore - TODO what are the consequences of this? */ - const_TokenPtr t = lexer.peek_token (); + switch (t->get_id ()) { - case ASTERISK: - // glob UseTree type - lexer.skip_token (); - - return std::unique_ptr<AST::UseTreeGlob> ( - new AST::UseTreeGlob (AST::UseTreeGlob::PATH_PREFIXED, - std::move (path), locus)); - case LEFT_CURLY: - { - // nested tree UseTree type - lexer.skip_token (); - - std::vector<std::unique_ptr<AST::UseTree>> use_trees; - - // TODO: think of better control structure - const_TokenPtr t = lexer.peek_token (); - while (t->get_id () != RIGHT_CURLY) - { - std::unique_ptr<AST::UseTree> use_tree = parse_use_tree (); - if (use_tree == nullptr) - { - break; - } - - use_trees.push_back (std::move (use_tree)); - - if (lexer.peek_token ()->get_id () != COMMA) - break; - - lexer.skip_token (); - t = lexer.peek_token (); - } - - // skip end curly delimiter - if (!skip_token (RIGHT_CURLY)) - { - // skip after somewhere? - return nullptr; - } - - return std::unique_ptr<AST::UseTreeList> ( - new AST::UseTreeList (AST::UseTreeList::PATH_PREFIXED, - std::move (path), std::move (use_trees), - locus)); - } case AS: { // rebind UseTree type @@ -2899,16 +2853,72 @@ Parser<ManagedTokenSource>::parse_use_tree () // don't skip semicolon - handled in parse_use_tree // lexer.skip_token(); - - return std::unique_ptr<AST::UseTreeRebind> ( - new AST::UseTreeRebind (AST::UseTreeRebind::NONE, std::move (path), - locus)); case COMMA: case RIGHT_CURLY: // this may occur in recursive calls - assume it is ok and ignore it return std::unique_ptr<AST::UseTreeRebind> ( new AST::UseTreeRebind (AST::UseTreeRebind::NONE, std::move (path), locus)); + case SCOPE_RESOLUTION: + // keep going + break; + default: + add_error (Error (t->get_locus (), + "unexpected token %qs in use tree with valid path", + t->get_token_description ())); + return nullptr; + } + + skip_token (); + t = lexer.peek_token (); + + switch (t->get_id ()) + { + case ASTERISK: + // glob UseTree type + lexer.skip_token (); + + return std::unique_ptr<AST::UseTreeGlob> ( + new AST::UseTreeGlob (AST::UseTreeGlob::PATH_PREFIXED, + std::move (path), locus)); + case LEFT_CURLY: + { + // nested tree UseTree type + lexer.skip_token (); + + std::vector<std::unique_ptr<AST::UseTree>> use_trees; + + // TODO: think of better control structure + const_TokenPtr t = lexer.peek_token (); + while (t->get_id () != RIGHT_CURLY) + { + std::unique_ptr<AST::UseTree> use_tree = parse_use_tree (); + if (use_tree == nullptr) + { + break; + } + + use_trees.push_back (std::move (use_tree)); + + if (lexer.peek_token ()->get_id () != COMMA) + break; + + lexer.skip_token (); + t = lexer.peek_token (); + } + + // skip end curly delimiter + if (!skip_token (RIGHT_CURLY)) + { + // skip after somewhere? + return nullptr; + } + + return std::unique_ptr<AST::UseTreeList> ( + new AST::UseTreeList (AST::UseTreeList::PATH_PREFIXED, + std::move (path), std::move (use_trees), + locus)); + } default: add_error (Error (t->get_locus (), "unexpected token %qs in use tree with valid path", @@ -3363,7 +3373,8 @@ Parser<ManagedTokenSource>::parse_lifetime_params (EndTokenPred is_end_token) /* Parses lifetime generic parameters (objects). Will also consume any * trailing comma. No extra checks for end token. - * TODO: is this best solution? implements most of the same algorithm. */ + * TODO: is this best solution? implements most of the same algorithm. + * TODO: seems to be unused, remove? */ template <typename ManagedTokenSource> std::vector<AST::LifetimeParam> Parser<ManagedTokenSource>::parse_lifetime_params_objs () @@ -3381,7 +3392,7 @@ Parser<ManagedTokenSource>::parse_lifetime_params_objs () break; } - 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; @@ -5604,7 +5615,8 @@ Parser<ManagedTokenSource>::parse_inherent_impl_function_or_method ( // param auto initial_param = parse_self_param (); - if (!initial_param.has_value () && initial_param.error () != NOT_SELF) + if (!initial_param.has_value () + && initial_param.error () != ParseSelfError::NOT_SELF) return nullptr; /* FIXME: ensure that self param doesn't accidently consume tokens for a @@ -5803,7 +5815,8 @@ Parser<ManagedTokenSource>::parse_trait_impl_function_or_method ( // param auto initial_param = parse_self_param (); - if (!initial_param.has_value () && initial_param.error () != NOT_SELF) + if (!initial_param.has_value () + && initial_param.error () != ParseSelfError::NOT_SELF) return nullptr; // FIXME: ensure that self param doesn't accidently consume tokens for a @@ -7264,6 +7277,27 @@ Parser<ManagedTokenSource>::parse_block_expr ( std::move (label), locus, end_locus)); } +/* Parse an anonymous const expression. This can be a regular const expression + * or an underscore for deferred const inference */ +template <typename ManagedTokenSource> +tl::expected<AST::AnonConst, AnonConstError> +Parser<ManagedTokenSource>::parse_anon_const () +{ + auto current = lexer.peek_token (); + auto locus = current->get_locus (); + + // Special case deferred inference constants + if (maybe_skip_token (UNDERSCORE)) + return AST::AnonConst (locus); + + auto expr = parse_expr (); + + if (!expr) + return tl::make_unexpected (AnonConstError::InvalidSizeExpr); + + return AST::AnonConst (std::move (expr), 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> @@ -7568,6 +7602,34 @@ Parser<ManagedTokenSource>::parse_return_expr (AST::AttrVec outer_attrs, locus)); } +// Parses a try expression. +template <typename ManagedTokenSource> +std::unique_ptr<AST::TryExpr> +Parser<ManagedTokenSource>::parse_try_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 (TRY); + } + + std::unique_ptr<AST::BlockExpr> block_expr = parse_block_expr (); + + if (!block_expr) + { + Error error (lexer.peek_token ()->get_locus (), + "failed to parse try block expression"); + add_error (std::move (error)); + + return nullptr; + } + + return std::unique_ptr<AST::TryExpr> ( + new AST::TryExpr (std::move (block_expr), std::move (outer_attrs), locus)); +} + /* Parses a break expression (including any label to break to AND any return * expression). */ template <typename ManagedTokenSource> @@ -9812,8 +9874,9 @@ Parser<ManagedTokenSource>::parse_slice_or_array_type () lexer.skip_token (); // parse required array size expression - std::unique_ptr<AST::Expr> size = parse_expr (); - if (size == nullptr) + auto size = parse_anon_const (); + + if (!size) { Error error (lexer.peek_token ()->get_locus (), "failed to parse size expression in array type"); @@ -9828,7 +9891,8 @@ Parser<ManagedTokenSource>::parse_slice_or_array_type () } return std::unique_ptr<AST::ArrayType> ( - new AST::ArrayType (std::move (inner_type), std::move (size), locus)); + new AST::ArrayType (std::move (inner_type), std::move (*size), + locus)); } default: // error @@ -10900,27 +10964,47 @@ Parser<ManagedTokenSource>::parse_slice_pattern () { location_t square_locus = lexer.peek_token ()->get_locus (); std::vector<std::unique_ptr<AST::Pattern>> patterns; + tl::optional<std::vector<std::unique_ptr<AST::Pattern>>> upper_patterns + = tl::nullopt; + + // lambda function to determine which vector to push new patterns into + auto get_pattern_ref + = [&] () -> std::vector<std::unique_ptr<AST::Pattern>> & { + return upper_patterns.has_value () ? upper_patterns.value () : patterns; + }; + skip_token (LEFT_SQUARE); if (lexer.peek_token ()->get_id () == RIGHT_SQUARE) { skip_token (RIGHT_SQUARE); + std::unique_ptr<AST::SlicePatternItemsNoRest> items ( + new AST::SlicePatternItemsNoRest (std::move (patterns))); return std::unique_ptr<AST::SlicePattern> ( - new AST::SlicePattern (std::move (patterns), square_locus)); + new AST::SlicePattern (std::move (items), square_locus)); } // parse initial pattern (required) - std::unique_ptr<AST::Pattern> initial_pattern = parse_pattern (); - if (initial_pattern == nullptr) + if (lexer.peek_token ()->get_id () == DOT_DOT) { - Error error (lexer.peek_token ()->get_locus (), - "failed to parse initial pattern in slice pattern"); - add_error (std::move (error)); - - return nullptr; + lexer.skip_token (); + upper_patterns = std::vector<std::unique_ptr<AST::Pattern>> (); } + else + { + // Not a rest pattern `..`, parse normally + std::unique_ptr<AST::Pattern> initial_pattern = parse_pattern (); + if (initial_pattern == nullptr) + { + Error error (lexer.peek_token ()->get_locus (), + "failed to parse initial pattern in slice pattern"); + add_error (std::move (error)); - patterns.push_back (std::move (initial_pattern)); + return nullptr; + } + + patterns.push_back (std::move (initial_pattern)); + } const_TokenPtr t = lexer.peek_token (); while (t->get_id () == COMMA) @@ -10931,6 +11015,23 @@ Parser<ManagedTokenSource>::parse_slice_pattern () if (lexer.peek_token ()->get_id () == RIGHT_SQUARE) break; + if (lexer.peek_token ()->get_id () == DOT_DOT) + { + if (upper_patterns.has_value ()) + { + // DOT_DOT has been parsed before + Error error (lexer.peek_token ()->get_locus (), "%s", + "`..` can only be used once per slice pattern"); + add_error (std::move (error)); + + return nullptr; + } + upper_patterns = std::vector<std::unique_ptr<AST::Pattern>> (); + lexer.skip_token (); + t = lexer.peek_token (); + continue; + } + // parse pattern (required) std::unique_ptr<AST::Pattern> pattern = parse_pattern (); if (pattern == nullptr) @@ -10941,7 +11042,7 @@ Parser<ManagedTokenSource>::parse_slice_pattern () return nullptr; } - patterns.push_back (std::move (pattern)); + get_pattern_ref ().push_back (std::move (pattern)); t = lexer.peek_token (); } @@ -10951,8 +11052,21 @@ Parser<ManagedTokenSource>::parse_slice_pattern () return nullptr; } + if (upper_patterns.has_value ()) + { + // Slice pattern with rest + std::unique_ptr<AST::SlicePatternItemsHasRest> items ( + new AST::SlicePatternItemsHasRest ( + std::move (patterns), std::move (upper_patterns.value ()))); + return std::unique_ptr<AST::SlicePattern> ( + new AST::SlicePattern (std::move (items), square_locus)); + } + + // Rest-less slice pattern + std::unique_ptr<AST::SlicePatternItemsNoRest> items ( + new AST::SlicePatternItemsNoRest (std::move (patterns))); return std::unique_ptr<AST::SlicePattern> ( - new AST::SlicePattern (std::move (patterns), square_locus)); + new AST::SlicePattern (std::move (items), square_locus)); } /* Parses an identifier pattern (pattern that binds a value matched to a @@ -11808,11 +11922,12 @@ Parser<ManagedTokenSource>::parse_struct_expr_field () } // "Unexpected token" panic mode - flags gcc error at unexpected token +// TODO: seems to be unused, remove? template <typename ManagedTokenSource> void Parser<ManagedTokenSource>::unexpected_token (const_TokenPtr t) { - Error error (t->get_locus (), "unexpected token %qs\n", + Error error (t->get_locus (), "unexpected token %qs", t->get_token_description ()); add_error (std::move (error)); } @@ -12506,6 +12621,9 @@ Parser<ManagedTokenSource>::null_denotation_not_path ( case RETURN_KW: // FIXME: is this really a null denotation expression? return parse_return_expr (std::move (outer_attrs), tok->get_locus ()); + case TRY: + // FIXME: is this really a null denotation expression? + return parse_try_expr (std::move (outer_attrs), tok->get_locus ()); case BREAK: // FIXME: is this really a null denotation expression? return parse_break_expr (std::move (outer_attrs), tok->get_locus ()); |