aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/parse/rust-parse-impl.h
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/rust/parse/rust-parse-impl.h')
-rw-r--r--gcc/rust/parse/rust-parse-impl.h986
1 files changed, 562 insertions, 424 deletions
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index d5383ad..14bccbd 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -19,21 +19,24 @@
/* 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"
-#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"
@@ -228,19 +231,22 @@ Parser<ManagedTokenSource>::skip_generics_right_angle ()
// this is good - skip token
lexer.skip_token ();
return true;
- case RIGHT_SHIFT: {
+ case RIGHT_SHIFT:
+ {
// new implementation that should be better
lexer.split_current_token (RIGHT_ANGLE, RIGHT_ANGLE);
lexer.skip_token ();
return true;
}
- case GREATER_OR_EQUAL: {
+ case GREATER_OR_EQUAL:
+ {
// new implementation that should be better
lexer.split_current_token (RIGHT_ANGLE, EQUAL);
lexer.skip_token ();
return true;
}
- case RIGHT_SHIFT_EQ: {
+ case RIGHT_SHIFT_EQ:
+ {
// new implementation that should be better
lexer.split_current_token (RIGHT_ANGLE, GREATER_OR_EQUAL);
lexer.skip_token ();
@@ -652,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 ())
@@ -683,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 ());
}
@@ -791,7 +795,8 @@ Parser<ManagedTokenSource>::parse_attr_input ()
{
case LEFT_PAREN:
case LEFT_SQUARE:
- case LEFT_CURLY: {
+ case LEFT_CURLY:
+ {
// must be a delimited token tree, so parse that
std::unique_ptr<AST::AttrInput> input_tree (
new AST::DelimTokenTree (parse_delim_token_tree ()));
@@ -800,7 +805,8 @@ Parser<ManagedTokenSource>::parse_attr_input ()
return input_tree;
}
- case EQUAL: {
+ case EQUAL:
+ {
// = LiteralExpr
lexer.skip_token ();
@@ -878,7 +884,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:
@@ -1454,8 +1463,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"));
@@ -2119,7 +2127,8 @@ Parser<ManagedTokenSource>::parse_macro_match ()
{
case LEFT_PAREN:
case LEFT_SQUARE:
- case LEFT_CURLY: {
+ case LEFT_CURLY:
+ {
// must be macro matcher as delimited
AST::MacroMatcher matcher = parse_macro_matcher ();
if (matcher.is_error ())
@@ -2133,7 +2142,8 @@ Parser<ManagedTokenSource>::parse_macro_match ()
return std::unique_ptr<AST::MacroMatcher> (
new AST::MacroMatcher (std::move (matcher)));
}
- case DOLLAR_SIGN: {
+ case DOLLAR_SIGN:
+ {
// have to do more lookahead to determine if fragment or repetition
const_TokenPtr t2 = lexer.peek_token (1);
switch (t2->get_id ())
@@ -2404,7 +2414,8 @@ Parser<ManagedTokenSource>::parse_visibility ()
skip_token (RIGHT_PAREN);
return AST::Visibility::create_super (path_loc, vis_loc);
- case IN: {
+ case IN:
+ {
lexer.skip_token ();
// parse the "in" path as well
@@ -2468,7 +2479,8 @@ Parser<ManagedTokenSource>::parse_module (AST::Visibility vis,
new AST::Module (std::move (name), std::move (vis),
std::move (outer_attrs), locus, safety,
lexer.get_filename (), inline_module_stack));
- case LEFT_CURLY: {
+ case LEFT_CURLY:
+ {
lexer.skip_token ();
// parse inner attributes
@@ -2732,7 +2744,8 @@ Parser<ManagedTokenSource>::parse_use_tree ()
return std::unique_ptr<AST::UseTreeGlob> (
new AST::UseTreeGlob (AST::UseTreeGlob::NO_PATH,
AST::SimplePath::create_empty (), locus));
- case LEFT_CURLY: {
+ case LEFT_CURLY:
+ {
// nested tree UseTree type
lexer.skip_token ();
@@ -2796,58 +2809,12 @@ 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: {
+ case AS:
+ {
// rebind UseTree type
lexer.skip_token ();
@@ -2886,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",
@@ -3102,9 +3125,10 @@ Parser<ManagedTokenSource>::parse_generic_param (EndTokenPred is_end_token)
switch (token->get_id ())
{
- case LIFETIME: {
+ case LIFETIME:
+ {
auto lifetime = parse_lifetime (false);
- if (lifetime.is_error ())
+ if (!lifetime)
{
rust_error_at (
token->get_locus (),
@@ -3124,11 +3148,12 @@ 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;
}
- case IDENTIFIER: {
+ case IDENTIFIER:
+ {
auto type_ident = token->get_str ();
lexer.skip_token ();
@@ -3163,7 +3188,8 @@ Parser<ManagedTokenSource>::parse_generic_param (EndTokenPred is_end_token)
std::move (outer_attrs)));
break;
}
- case CONST: {
+ case CONST:
+ {
lexer.skip_token ();
auto name_token = expect_token (IDENTIFIER);
@@ -3176,24 +3202,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> (
@@ -3278,16 +3308,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;
@@ -3313,9 +3343,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? */
@@ -3343,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 ()
@@ -3353,15 +3384,15 @@ 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;
}
- 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;
@@ -3388,9 +3419,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? */
@@ -3401,7 +3432,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;
@@ -3460,7 +3491,7 @@ 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 attributes, which are optional and may not exist
@@ -3470,8 +3501,8 @@ Parser<ManagedTokenSource>::parse_lifetime_param ()
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 (),
@@ -3683,7 +3714,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));
}
@@ -3705,7 +3736,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));
}
@@ -3716,7 +3747,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));
}
@@ -3817,12 +3848,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))
{
@@ -4015,7 +4047,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:
@@ -4088,13 +4120,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 */
@@ -4118,9 +4150,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? */
@@ -4131,7 +4163,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 */
@@ -4148,14 +4180,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 ();
@@ -4347,7 +4385,8 @@ Parser<ManagedTokenSource>::parse_struct (AST::Visibility vis,
const_TokenPtr t = lexer.peek_token ();
switch (t->get_id ())
{
- case LEFT_CURLY: {
+ case LEFT_CURLY:
+ {
// struct with body
// skip curly bracket
@@ -4750,7 +4789,8 @@ Parser<ManagedTokenSource>::parse_enum_item ()
const_TokenPtr t = lexer.peek_token ();
switch (t->get_id ())
{
- case LEFT_PAREN: {
+ case LEFT_PAREN:
+ {
// tuple enum item
lexer.skip_token ();
@@ -4771,7 +4811,8 @@ Parser<ManagedTokenSource>::parse_enum_item ()
std::move (item_name), std::move (vis), std::move (tuple_fields),
std::move (outer_attrs), item_name_tok->get_locus ()));
}
- case LEFT_CURLY: {
+ case LEFT_CURLY:
+ {
// struct enum item
lexer.skip_token ();
@@ -4788,7 +4829,8 @@ Parser<ManagedTokenSource>::parse_enum_item ()
std::move (item_name), std::move (vis), std::move (struct_fields),
std::move (outer_attrs), item_name_tok->get_locus ()));
}
- case EQUAL: {
+ case EQUAL:
+ {
// discriminant enum item
lexer.skip_token ();
@@ -5441,7 +5483,8 @@ Parser<ManagedTokenSource>::parse_inherent_impl_item ()
case SUPER:
case SELF:
case CRATE:
- case PUB: {
+ case PUB:
+ {
// visibility, so not a macro invocation semi - must be constant,
// function, or method
AST::Visibility vis = parse_visibility ();
@@ -5572,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
@@ -5771,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
@@ -5937,106 +5982,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>
@@ -6055,7 +6000,8 @@ Parser<ManagedTokenSource>::parse_external_item ()
{
case IDENTIFIER:
return parse_macro_invocation_semi (outer_attrs);
- case STATIC_KW: {
+ case STATIC_KW:
+ {
// parse extern static item
lexer.skip_token ();
@@ -6265,6 +6211,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
@@ -6279,7 +6229,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.
@@ -6340,7 +6290,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 ();
@@ -6348,7 +6298,8 @@ Parser<ManagedTokenSource>::parse_generic_arg ()
switch (tok->get_id ())
{
- case IDENTIFIER: {
+ case IDENTIFIER:
+ {
// This is a bit of a weird situation: With an identifier token, we
// could either have a valid type or a macro (FIXME: anything else?). So
// we need one bit of lookahead to differentiate if this is really
@@ -6361,7 +6312,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)
{
@@ -6378,7 +6329,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 (),
@@ -6396,20 +6347,21 @@ Parser<ManagedTokenSource>::parse_generic_arg ()
case FALSE_LITERAL:
expr = parse_literal_expr ();
break;
- // FIXME: Because of this, error reporting is garbage for const generic
- // parameter's default values
- default: {
+ // FIXME: Because of this, error reporting is garbage for const generic
+ // parameter's default values
+ default:
+ {
auto type = parse_type ();
// FIXME: Find a better way to do this?
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));
}
@@ -6438,14 +6390,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)
@@ -6474,9 +6426,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?
@@ -6597,7 +6549,8 @@ Parser<ManagedTokenSource>::parse_type_path_segment ()
switch (t->get_id ())
{
case LEFT_SHIFT:
- case LEFT_ANGLE: {
+ case LEFT_ANGLE:
+ {
// parse generic args
AST::GenericArgs generic_args = parse_path_generic_args ();
@@ -6606,7 +6559,8 @@ Parser<ManagedTokenSource>::parse_type_path_segment ()
has_separating_scope_resolution,
std::move (generic_args), locus));
}
- case LEFT_PAREN: {
+ case LEFT_PAREN:
+ {
// parse type path function
AST::TypePathFunction type_path_function
= parse_type_path_function (locus);
@@ -7059,10 +7013,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");
@@ -7124,14 +7080,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);
}
}
@@ -7153,16 +7109,14 @@ Parser<ManagedTokenSource>::parse_expr_stmt (AST::AttrVec outer_attrs,
case SELF:
case SELF_ALIAS:
case DOLLAR_SIGN:
- case SCOPE_RESOLUTION: {
+ case SCOPE_RESOLUTION:
+ {
AST::PathInExpression path = parse_path_in_expression ();
std::unique_ptr<AST::Expr> null_denotation;
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));
@@ -7170,7 +7124,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 ();
@@ -7178,14 +7132,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);
@@ -7251,9 +7205,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)
@@ -7323,6 +7277,51 @@ Parser<ManagedTokenSource>::parse_block_expr (AST::AttrVec outer_attrs,
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>
+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>
@@ -7603,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>
@@ -7617,12 +7644,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;
@@ -7648,12 +7673,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));
@@ -7661,14 +7684,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? */
@@ -7677,10 +7701,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
@@ -7761,7 +7787,8 @@ Parser<ManagedTokenSource>::parse_if_expr (AST::AttrVec outer_attrs,
const_TokenPtr t = lexer.peek_token ();
switch (t->get_id ())
{
- case LEFT_CURLY: {
+ case LEFT_CURLY:
+ {
// double selection - else
// parse else block expr (required)
std::unique_ptr<AST::BlockExpr> else_body = parse_block_expr ();
@@ -7782,7 +7809,8 @@ Parser<ManagedTokenSource>::parse_if_expr (AST::AttrVec outer_attrs,
std::move (else_body),
std::move (outer_attrs), locus));
}
- case IF: {
+ case IF:
+ {
// multiple selection - else if or else if let
// branch on whether next token is 'let' or not
if (lexer.peek_token (1)->get_id () == LET)
@@ -7943,7 +7971,8 @@ Parser<ManagedTokenSource>::parse_if_let_expr (AST::AttrVec outer_attrs,
const_TokenPtr t = lexer.peek_token ();
switch (t->get_id ())
{
- case LEFT_CURLY: {
+ case LEFT_CURLY:
+ {
// double selection - else
// parse else block expr (required)
std::unique_ptr<AST::BlockExpr> else_body = parse_block_expr ();
@@ -7965,7 +7994,8 @@ Parser<ManagedTokenSource>::parse_if_let_expr (AST::AttrVec outer_attrs,
std::move (else_body),
std::move (outer_attrs), locus));
}
- case IF: {
+ case IF:
+ {
// multiple selection - else if or else if let
// branch on whether next token is 'let' or not
if (lexer.peek_token (1)->get_id () == LET)
@@ -8033,16 +8063,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))
{
@@ -8052,8 +8082,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
@@ -8076,17 +8106,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))
{
@@ -8096,8 +8126,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
@@ -8149,14 +8179,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
@@ -8223,14 +8253,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
@@ -8308,8 +8338,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");
@@ -8319,6 +8350,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 ())
@@ -8693,10 +8728,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
{
@@ -9012,7 +9047,8 @@ Parser<ManagedTokenSource>::parse_type (bool save_errors)
// slice type or array type - requires further disambiguation
return parse_slice_or_array_type ();
case LEFT_SHIFT:
- case LEFT_ANGLE: {
+ case LEFT_ANGLE:
+ {
// qualified path in type
AST::QualifiedPathInType path = parse_qualified_path_in_type ();
if (path.is_error ())
@@ -9041,7 +9077,8 @@ Parser<ManagedTokenSource>::parse_type (bool save_errors)
case LOGICAL_AND:
// reference type
return parse_reference_type ();
- case LIFETIME: {
+ case LIFETIME:
+ {
/* probably a lifetime bound, so probably type param bounds in
* TraitObjectType */
std::vector<std::unique_ptr<AST::TypeParamBound>> bounds
@@ -9057,7 +9094,8 @@ Parser<ManagedTokenSource>::parse_type (bool save_errors)
case SELF_ALIAS:
case CRATE:
case DOLLAR_SIGN:
- case SCOPE_RESOLUTION: {
+ case SCOPE_RESOLUTION:
+ {
// macro invocation or type path - requires further disambiguation.
/* for parsing path component of each rule, perhaps parse it as a
* typepath and attempt conversion to simplepath if a trailing '!' is
@@ -9087,7 +9125,8 @@ Parser<ManagedTokenSource>::parse_type (bool save_errors)
t = lexer.peek_token ();
switch (t->get_id ())
{
- case EXCLAM: {
+ case EXCLAM:
+ {
// macro invocation
// convert to simple path
AST::SimplePath macro_path = path.as_simple_path ();
@@ -9113,7 +9152,8 @@ Parser<ManagedTokenSource>::parse_type (bool save_errors)
std::move (tok_tree)),
{}, locus);
}
- case PLUS: {
+ case PLUS:
+ {
// type param bounds
std::vector<std::unique_ptr<AST::TypeParamBound>> bounds;
@@ -9198,14 +9238,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));
}
@@ -9233,7 +9267,8 @@ Parser<ManagedTokenSource>::parse_type (bool save_errors)
new AST::ImplTraitType (std::move (bounds), locus));
}
case DYN:
- case QUESTION_MARK: {
+ case QUESTION_MARK:
+ {
// either TraitObjectType or TraitObjectTypeOneBound
bool has_dyn = false;
if (t->get_id () == DYN)
@@ -9486,7 +9521,8 @@ Parser<ManagedTokenSource>::parse_for_prefixed_type ()
case SELF:
case SELF_ALIAS:
case CRATE:
- case DOLLAR_SIGN: {
+ case DOLLAR_SIGN:
+ {
// path, so trait type
// parse type path to finish parsing trait bound
@@ -9696,8 +9732,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");
@@ -9828,13 +9868,15 @@ Parser<ManagedTokenSource>::parse_slice_or_array_type ()
return std::unique_ptr<AST::SliceType> (
new AST::SliceType (std::move (inner_type), locus));
- case SEMICOLON: {
+ case SEMICOLON:
+ {
// 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");
@@ -9849,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
@@ -9879,7 +9922,8 @@ Parser<ManagedTokenSource>::parse_type_no_bounds ()
// slice type or array type - requires further disambiguation
return parse_slice_or_array_type ();
case LEFT_SHIFT:
- case LEFT_ANGLE: {
+ case LEFT_ANGLE:
+ {
// qualified path in type
AST::QualifiedPathInType path = parse_qualified_path_in_type ();
if (path.is_error ())
@@ -9920,7 +9964,8 @@ Parser<ManagedTokenSource>::parse_type_no_bounds ()
case SELF_ALIAS:
case CRATE:
case DOLLAR_SIGN:
- case SCOPE_RESOLUTION: {
+ case SCOPE_RESOLUTION:
+ {
// macro invocation or type path - requires further disambiguation.
/* for parsing path component of each rule, perhaps parse it as a
* typepath and attempt conversion to simplepath if a trailing '!' is
@@ -9948,7 +9993,8 @@ Parser<ManagedTokenSource>::parse_type_no_bounds ()
t = lexer.peek_token ();
switch (t->get_id ())
{
- case EXCLAM: {
+ case EXCLAM:
+ {
// macro invocation
// convert to simple path
AST::SimplePath macro_path = path.as_simple_path ();
@@ -10032,14 +10078,12 @@ 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: {
+ case QUESTION_MARK:
+ {
// either TraitObjectTypeOneBound
bool has_dyn = false;
if (t->get_id () == DYN)
@@ -10380,7 +10424,8 @@ Parser<ManagedTokenSource>::parse_range_pattern_bound ()
case SELF_ALIAS:
case CRATE:
case SCOPE_RESOLUTION:
- case DOLLAR_SIGN: {
+ case DOLLAR_SIGN:
+ {
// path in expression
AST::PathInExpression path = parse_path_in_expression ();
if (path.is_error ())
@@ -10396,7 +10441,8 @@ Parser<ManagedTokenSource>::parse_range_pattern_bound ()
new AST::RangePatternBoundPath (std::move (path)));
}
case LEFT_SHIFT:
- case LEFT_ANGLE: {
+ case LEFT_ANGLE:
+ {
// qualified path in expression
AST::QualifiedPathInExpression path
= parse_qualified_path_in_expression ();
@@ -10541,7 +10587,8 @@ Parser<ManagedTokenSource>::parse_pattern_no_alt ()
// slice pattern
return parse_slice_pattern ();
case LEFT_SHIFT:
- case LEFT_ANGLE: {
+ case LEFT_ANGLE:
+ {
// qualified path in expression or qualified range pattern bound
AST::QualifiedPathInExpression path
= parse_qualified_path_in_expression ();
@@ -10577,7 +10624,8 @@ Parser<ManagedTokenSource>::parse_pattern_no_alt ()
case SELF_ALIAS:
case CRATE:
case SCOPE_RESOLUTION:
- case DOLLAR_SIGN: {
+ case DOLLAR_SIGN:
+ {
// path in expression or range pattern bound
AST::PathInExpression path = parse_path_in_expression ();
@@ -10586,7 +10634,8 @@ Parser<ManagedTokenSource>::parse_pattern_no_alt ()
{
case DOT_DOT_EQ:
case DOT_DOT:
- case ELLIPSIS: {
+ case ELLIPSIS:
+ {
// qualified range pattern bound, so parse rest of range pattern
AST::RangeKind kind = AST::tokenid_to_rangekind (next->get_id ());
lexer.skip_token ();
@@ -10604,7 +10653,8 @@ Parser<ManagedTokenSource>::parse_pattern_no_alt ()
case EXCLAM:
return parse_macro_invocation_partial (std::move (path),
AST::AttrVec ());
- case LEFT_PAREN: {
+ case LEFT_PAREN:
+ {
// tuple struct
lexer.skip_token ();
@@ -10629,7 +10679,8 @@ Parser<ManagedTokenSource>::parse_pattern_no_alt ()
new AST::TupleStructPattern (std::move (path),
std::move (items)));
}
- case LEFT_CURLY: {
+ case LEFT_CURLY:
+ {
// struct
lexer.skip_token ();
@@ -10799,7 +10850,8 @@ Parser<ManagedTokenSource>::parse_grouped_or_tuple_pattern ()
return std::unique_ptr<AST::GroupedPattern> (
new AST::GroupedPattern (std::move (initial_pattern), paren_locus));
- case COMMA: {
+ case COMMA:
+ {
// tuple pattern
lexer.skip_token ();
@@ -10912,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)
@@ -10943,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)
@@ -10953,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 ();
}
@@ -10963,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
@@ -11056,7 +11158,8 @@ Parser<ManagedTokenSource>::parse_ident_leading_pattern ()
{
case EXCLAM:
return parse_macro_invocation_partial (std::move (path), AST::AttrVec ());
- case LEFT_PAREN: {
+ case LEFT_PAREN:
+ {
// tuple struct
lexer.skip_token ();
@@ -11089,7 +11192,8 @@ Parser<ManagedTokenSource>::parse_ident_leading_pattern ()
return std::unique_ptr<AST::TupleStructPattern> (
new AST::TupleStructPattern (std::move (path), std::move (items)));
}
- case LEFT_CURLY: {
+ case LEFT_CURLY:
+ {
// struct
lexer.skip_token ();
@@ -11110,7 +11214,8 @@ Parser<ManagedTokenSource>::parse_ident_leading_pattern ()
}
case DOT_DOT_EQ:
case DOT_DOT:
- case ELLIPSIS: {
+ case ELLIPSIS:
+ {
// range
AST::RangeKind kind
= AST::tokenid_to_rangekind (lexer.peek_token ()->get_id ());
@@ -11127,7 +11232,8 @@ Parser<ManagedTokenSource>::parse_ident_leading_pattern ()
std::move (upper_bound), kind,
t->get_locus ()));
}
- case PATTERN_BIND: {
+ case PATTERN_BIND:
+ {
// only allow on single-segment paths
if (path.is_single_segment ())
{
@@ -11265,7 +11371,8 @@ Parser<ManagedTokenSource>::parse_tuple_struct_items ()
case RIGHT_PAREN:
return std::unique_ptr<AST::TupleStructItemsNoRange> (
new AST::TupleStructItemsNoRange (std::move (lower_patterns)));
- case DOT_DOT: {
+ case DOT_DOT:
+ {
// has an upper range that must be parsed separately
lexer.skip_token ();
@@ -11385,7 +11492,8 @@ Parser<ManagedTokenSource>::parse_struct_pattern_field_partial (
const_TokenPtr t = lexer.peek_token ();
switch (t->get_id ())
{
- case INT_LITERAL: {
+ case INT_LITERAL:
+ {
// tuple index
std::string index_str = t->get_str ();
int index = atoi (index_str.c_str ());
@@ -11419,7 +11527,8 @@ Parser<ManagedTokenSource>::parse_struct_pattern_field_partial (
// branch on next token
switch (lexer.peek_token (1)->get_id ())
{
- case COLON: {
+ case COLON:
+ {
// identifier-pattern
Identifier ident{t};
lexer.skip_token ();
@@ -11444,7 +11553,8 @@ Parser<ManagedTokenSource>::parse_struct_pattern_field_partial (
t->get_locus ()));
}
case COMMA:
- case RIGHT_CURLY: {
+ case RIGHT_CURLY:
+ {
// identifier only
Identifier ident = {t};
lexer.skip_token ();
@@ -11463,7 +11573,8 @@ Parser<ManagedTokenSource>::parse_struct_pattern_field_partial (
return nullptr;
}
case REF:
- case MUT: {
+ case MUT:
+ {
// only identifier
bool has_ref = false;
if (t->get_id () == REF)
@@ -11535,7 +11646,8 @@ Parser<ManagedTokenSource>::parse_stmt_or_expr ()
t = lexer.peek_token ();
switch (t->get_id ())
{
- case LET: {
+ case LET:
+ {
// let statement
std::unique_ptr<AST::LetStmt> stmt (
parse_let_stmt (std::move (outer_attrs)));
@@ -11553,42 +11665,48 @@ Parser<ManagedTokenSource>::parse_stmt_or_expr ()
case STATIC_KW:
case AUTO:
case TRAIT:
- case IMPL: {
+ case IMPL:
+ {
std::unique_ptr<AST::VisItem> item (
parse_vis_item (std::move (outer_attrs)));
return ExprOrStmt (std::move (item));
}
- /* TODO: implement union keyword but not really because of
- * context-dependence crappy hack way to parse a union written below to
- * separate it from the good code. */
- // case UNION:
- case UNSAFE: { // maybe - unsafe traits are a thing
+ /* TODO: implement union keyword but not really because of
+ * context-dependence crappy hack way to parse a union written below to
+ * separate it from the good code. */
+ // case UNION:
+ case UNSAFE:
+ { // maybe - unsafe traits are a thing
/* if any of these (should be all possible VisItem prefixes), parse a
* VisItem - can't parse item because would require reparsing outer
* attributes */
const_TokenPtr t2 = lexer.peek_token (1);
switch (t2->get_id ())
{
- case LEFT_CURLY: {
+ case LEFT_CURLY:
+ {
// unsafe block: parse as expression
expr = parse_expr (std::move (outer_attrs), restrictions);
break;
}
case AUTO:
- case TRAIT: {
+ case TRAIT:
+ {
// unsafe trait
std::unique_ptr<AST::VisItem> item (
parse_vis_item (std::move (outer_attrs)));
return ExprOrStmt (std::move (item));
}
case EXTERN_KW:
- case FN_KW: {
+ case FN_KW:
+ {
// unsafe function
std::unique_ptr<AST::VisItem> item (
parse_vis_item (std::move (outer_attrs)));
return ExprOrStmt (std::move (item));
}
- case IMPL: {
+ case IMPL:
+ {
// unsafe trait impl
std::unique_ptr<AST::VisItem> item (
parse_vis_item (std::move (outer_attrs)));
@@ -11633,7 +11751,8 @@ Parser<ManagedTokenSource>::parse_stmt_or_expr ()
case SELF_ALIAS:
case CRATE:
case SCOPE_RESOLUTION:
- case DOLLAR_SIGN: {
+ case DOLLAR_SIGN:
+ {
AST::PathInExpression path = parse_path_in_expression ();
std::unique_ptr<AST::Expr> null_denotation;
@@ -11757,7 +11876,8 @@ Parser<ManagedTokenSource>::parse_struct_expr_field ()
std::move (outer_attrs),
t->get_locus ()));
}
- case INT_LITERAL: {
+ case INT_LITERAL:
+ {
// parse tuple index field
int index = atoi (t->get_str ().c_str ());
lexer.skip_token ();
@@ -11802,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));
}
@@ -11997,7 +12118,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 ();
@@ -12127,7 +12248,8 @@ Parser<ManagedTokenSource>::null_denotation (const_TokenPtr tok,
case SELF_ALIAS:
case DOLLAR_SIGN:
case CRATE:
- case SUPER: {
+ case SUPER:
+ {
// DEBUG
rust_debug ("beginning null denotation identifier handling");
@@ -12138,7 +12260,8 @@ Parser<ManagedTokenSource>::null_denotation (const_TokenPtr tok,
return null_denotation_path (std::move (path), std::move (outer_attrs),
restrictions);
}
- case SCOPE_RESOLUTION: {
+ case SCOPE_RESOLUTION:
+ {
// TODO: fix: this is for global paths, i.e. std::string::whatever
Error error (tok->get_locus (),
"found null denotation scope resolution operator, and "
@@ -12180,7 +12303,8 @@ Parser<ManagedTokenSource>::null_denotation_path (
// macro
return parse_macro_invocation_partial (std::move (path),
std::move (outer_attrs));
- case LEFT_CURLY: {
+ case LEFT_CURLY:
+ {
bool not_a_block = lexer.peek_token (1)->get_id () == IDENTIFIER
&& (lexer.peek_token (2)->get_id () == COMMA
|| (lexer.peek_token (2)->get_id () == COLON
@@ -12256,7 +12380,8 @@ Parser<ManagedTokenSource>::null_denotation_not_path (
{
// FIXME: Handle in null_denotation_path?
case LEFT_SHIFT:
- case LEFT_ANGLE: {
+ case LEFT_ANGLE:
+ {
// qualified path
// HACK: add outer attrs to path
AST::QualifiedPathInExpression path
@@ -12314,23 +12439,24 @@ Parser<ManagedTokenSource>::null_denotation_not_path (
return parse_grouped_or_tuple_expr (std::move (outer_attrs),
tok->get_locus ());
- /*case PLUS: { // unary plus operator
- // invoke parse_expr recursively with appropriate priority, etc. for
- below AST::Expr* expr = parse_expr(LBP_UNARY_PLUS);
+ /*case PLUS: { // unary plus operator
+ // invoke parse_expr recursively with appropriate priority, etc. for
+ below AST::Expr* expr = parse_expr(LBP_UNARY_PLUS);
- if (expr == nullptr)
- return nullptr;
- // can only apply to integer and float expressions
- if (expr->get_type() != integer_type_node || expr->get_type() !=
- float_type_node) { rust_error_at(tok->get_locus(), "operand of unary
- plus must be int or float but it is %s", print_type(expr->get_type()));
- return nullptr;
- }
+ if (expr == nullptr)
+ return nullptr;
+ // can only apply to integer and float expressions
+ if (expr->get_type() != integer_type_node || expr->get_type() !=
+ float_type_node) { rust_error_at(tok->get_locus(), "operand of unary
+ plus must be int or float but it is %s", print_type(expr->get_type()));
+ return nullptr;
+ }
- return Tree(expr, tok->get_locus());
- }*/
- // Rust has no unary plus operator
- case MINUS: { // unary minus
+ return Tree(expr, tok->get_locus());
+ }*/
+ // Rust has no unary plus operator
+ case MINUS:
+ { // unary minus
ParseRestrictions entered_from_unary;
entered_from_unary.entered_from_unary = true;
if (!restrictions.can_be_struct_expr)
@@ -12357,7 +12483,8 @@ Parser<ManagedTokenSource>::null_denotation_not_path (
new AST::NegationExpr (std::move (expr), NegationOperator::NEGATE,
std::move (outer_attrs), tok->get_locus ()));
}
- case EXCLAM: { // logical or bitwise not
+ case EXCLAM:
+ { // logical or bitwise not
ParseRestrictions entered_from_unary;
entered_from_unary.entered_from_unary = true;
if (!restrictions.can_be_struct_expr)
@@ -12382,7 +12509,8 @@ Parser<ManagedTokenSource>::null_denotation_not_path (
new AST::NegationExpr (std::move (expr), NegationOperator::NOT,
std::move (outer_attrs), tok->get_locus ()));
}
- case ASTERISK: {
+ case ASTERISK:
+ {
/* pointer dereference only - HACK: as struct expressions should
* always be value expressions, cannot be dereferenced */
ParseRestrictions entered_from_unary;
@@ -12395,7 +12523,8 @@ Parser<ManagedTokenSource>::null_denotation_not_path (
new AST::DereferenceExpr (std::move (expr), std::move (outer_attrs),
tok->get_locus ()));
}
- case AMP: {
+ case AMP:
+ {
// (single) "borrow" expression - shared (mutable) or immutable
std::unique_ptr<AST::Expr> expr = nullptr;
Mutability mutability = Mutability::Imm;
@@ -12452,7 +12581,8 @@ Parser<ManagedTokenSource>::null_denotation_not_path (
new AST::BorrowExpr (std::move (expr), mutability, raw_borrow, false,
std::move (outer_attrs), tok->get_locus ()));
}
- case LOGICAL_AND: {
+ case LOGICAL_AND:
+ {
// (double) "borrow" expression - shared (mutable) or immutable
std::unique_ptr<AST::Expr> expr = nullptr;
Mutability mutability = Mutability::Imm;
@@ -12491,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 ());
@@ -12498,8 +12631,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)
@@ -12515,7 +12648,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)
@@ -12524,13 +12657,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 ());
@@ -12548,6 +12679,9 @@ Parser<ManagedTokenSource>::null_denotation_not_path (
"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 (),
@@ -12570,8 +12704,9 @@ Parser<ManagedTokenSource>::left_denotation (const_TokenPtr tok,
// Token passed in has already been skipped, so peek gives "next" token
switch (tok->get_id ())
{
- // FIXME: allow for outer attributes to be applied
- case QUESTION_MARK: {
+ // FIXME: allow for outer attributes to be applied
+ case QUESTION_MARK:
+ {
location_t left_locus = left->get_locus ();
// error propagation expression - unary postfix
return std::unique_ptr<AST::ErrorPropagationExpr> (
@@ -12825,7 +12960,8 @@ Parser<ManagedTokenSource>::left_denotation (const_TokenPtr tok,
"function - this should probably be handled elsewhere"));
return nullptr;
- case DOT: {
+ case DOT:
+ {
/* field expression or method call - relies on parentheses after next
* identifier or await if token after is "await" (unary postfix) or
* tuple index if token after is a decimal int literal */
@@ -14141,7 +14277,8 @@ Parser<ManagedTokenSource>::parse_struct_expr_struct_partial (
* algorithm should work too. As such, AST type not happening. */
case IDENTIFIER:
case HASH:
- case INT_LITERAL: {
+ case INT_LITERAL:
+ {
// struct with struct expr fields
// parse struct expr fields
@@ -14438,7 +14575,8 @@ Parser<ManagedTokenSource>::parse_closure_expr_pratt (const_TokenPtr tok,
case OR:
// no parameters, don't skip token
break;
- case PIPE: {
+ case PIPE:
+ {
// actually may have parameters
// don't skip token
const_TokenPtr t = lexer.peek_token ();