namespace Parse {
namespace Error {
+struct EnumVariant
+{
+ enum class Kind
+ {
+ CHILD_ERROR,
+ NO_IDENTIFIER,
+ UNFINISHED_TUPLE_VARIANT,
+ } kind;
+
+ static tl::expected<std::unique_ptr<AST::EnumItem>, EnumVariant>
+ make_not_identifier (const_TokenPtr unexpected_token)
+ {
+ return tl::unexpected<EnumVariant> (EnumVariant (unexpected_token));
+ }
+
+ static tl::expected<std::unique_ptr<AST::EnumItem>, EnumVariant>
+ make_child_error ()
+ {
+ return tl::unexpected<EnumVariant> (EnumVariant (Kind::CHILD_ERROR));
+ }
+
+ static tl::expected<std::unique_ptr<AST::EnumItem>, EnumVariant>
+ make_unfinished_tuple_variant ()
+ {
+ return tl::unexpected<EnumVariant> (
+ EnumVariant (Kind::UNFINISHED_TUPLE_VARIANT));
+ }
+
+private:
+ EnumVariant (const_TokenPtr unexpected_token)
+ : kind (Kind::NO_IDENTIFIER), unexpected_token (unexpected_token)
+ {}
+
+ EnumVariant (Kind kind) : kind (kind), unexpected_token (nullptr)
+ {
+ rust_assert (kind != Kind::NO_IDENTIFIER);
+ }
+
+ // Only valid for missing identifier
+ const_TokenPtr unexpected_token;
+};
+
struct Attribute
{
static tl::expected<AST::Attribute, Attribute> make_malformed ()
// handle TypePath
AST::TypePath type_path = parse_type_path ();
- if (type_path.is_error())
+ if (type_path.is_error ())
return nullptr;
// handle closing parentheses
{
std::vector<std::unique_ptr<AST::EnumItem>> items;
- std::unique_ptr<AST::EnumItem> initial_item = parse_enum_item ();
+ auto initial_item = parse_enum_item ();
// Return empty item list if no field there
- if (initial_item == nullptr)
+ if (!initial_item)
return items;
- items.push_back (std::move (initial_item));
+ items.push_back (std::move (initial_item.value ()));
while (lexer.peek_token ()->get_id () == COMMA)
{
lexer.skip_token ();
- std::unique_ptr<AST::EnumItem> item = parse_enum_item ();
- if (item == nullptr)
+ auto item = parse_enum_item ();
+ if (!item)
{
// this would occur with a trailing comma, which is allowed
break;
}
- items.push_back (std::move (item));
+ items.push_back (std::move (item.value ()));
}
items.shrink_to_fit ();
{
std::vector<std::unique_ptr<AST::EnumItem>> items;
- std::unique_ptr<AST::EnumItem> initial_item = parse_enum_item ();
+ auto initial_item = parse_enum_item ();
// Return empty item list if no field there
- if (initial_item == nullptr)
+ if (!initial_item)
return items;
- items.push_back (std::move (initial_item));
+ items.push_back (std::move (initial_item.value ()));
while (lexer.peek_token ()->get_id () == COMMA)
{
if (is_end_tok (lexer.peek_token ()->get_id ()))
break;
- std::unique_ptr<AST::EnumItem> item = parse_enum_item ();
- if (item == nullptr)
+ auto item = parse_enum_item ();
+ if (!item)
{
/* TODO should this ignore all successfully parsed enum items just
* because one failed? */
return {};
}
- items.push_back (std::move (item));
+ items.push_back (std::move (item.value ()));
}
items.shrink_to_fit ();
/* Parses a single enum variant item in an enum definition. Does not parse
* commas. */
template <typename ManagedTokenSource>
-std::unique_ptr<AST::EnumItem>
+tl::expected<std::unique_ptr<AST::EnumItem>, Parse::Error::EnumVariant>
Parser<ManagedTokenSource>::parse_enum_item ()
{
// parse outer attributes if they exist
// parse visibility, which may or may not exist
auto vis_res = parse_visibility ();
if (!vis_res)
- return nullptr;
+ return Parse::Error::EnumVariant::make_child_error ();
auto vis = vis_res.value ();
// parse name for enum item, which is required
if (item_name_tok->get_id () != IDENTIFIER)
{
// this may not be an error but it means there is no enum item here
- return nullptr;
+ return Parse::Error::EnumVariant::make_not_identifier (item_name_tok);
}
lexer.skip_token ();
Identifier item_name{item_name_tok};
if (!skip_token (RIGHT_PAREN))
{
// skip after somewhere
- return nullptr;
+ return Parse::Error::EnumVariant::make_unfinished_tuple_variant ();
}
return std::unique_ptr<AST::EnumItemTuple> (new AST::EnumItemTuple (
if (!skip_token (RIGHT_CURLY))
{
// skip after somewhere
- return nullptr;
+ return Parse::Error::EnumVariant::make_unfinished_tuple_variant ();
}
return std::unique_ptr<AST::EnumItemStruct> (new AST::EnumItemStruct (
auto discriminant_expr = parse_expr ();
if (!discriminant_expr)
- return nullptr;
+ return Parse::Error::EnumVariant::make_child_error ();
- return std::unique_ptr<AST::EnumItemDiscriminant> (
- new AST::EnumItemDiscriminant (std::move (item_name), std::move (vis),
- std::move (discriminant_expr.value ()),
- std::move (outer_attrs),
- item_name_tok->get_locus ()));
+ return std::make_unique<AST::EnumItemDiscriminant> (
+ std::move (item_name), std::move (vis),
+ std::move (discriminant_expr.value ()), std::move (outer_attrs),
+ item_name_tok->get_locus ());
}
default:
// regular enum with just an identifier
- return std::unique_ptr<AST::EnumItem> (
- new AST::EnumItem (std::move (item_name), std::move (vis),
- std::move (outer_attrs),
- item_name_tok->get_locus ()));
+ return std::make_unique<AST::EnumItem> (std::move (item_name),
+ std::move (vis),
+ std::move (outer_attrs),
+ item_name_tok->get_locus ());
}
}