| // Copyright (C) 2025-2026 Free Software Foundation, Inc. | |
| // This file is part of GCC. | |
| // GCC is free software; you can redistribute it and/or modify it under | |
| // the terms of the GNU General Public License as published by the Free | |
| // Software Foundation; either version 3, or (at your option) any later | |
| // version. | |
| // GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
| // WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| // for more details. | |
| // You should have received a copy of the GNU General Public License | |
| // along with GCC; see the file COPYING3. If not see | |
| // <http://www.gnu.org/licenses/>. | |
| #ifndef RUST_PARSE_ERROR_H | |
| #define RUST_PARSE_ERROR_H | |
| #include "expected.h" | |
| #include "rust-ast.h" | |
| #include "rust-parse-utils.h" | |
| namespace Rust { | |
| 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 () | |
| { | |
| return tl::unexpected<Attribute> (Attribute (Kind::MALFORMED)); | |
| } | |
| static tl::expected<AST::Attribute, Attribute> make_malformed_body () | |
| { | |
| return tl::unexpected<Attribute> (Attribute (Kind::MALFORMED_BODY)); | |
| } | |
| static tl::expected<AST::Attribute, Attribute> make_unexpected_inner () | |
| { | |
| return tl::unexpected<Attribute> (Attribute (Kind::UNEXPECTED_INNER)); | |
| } | |
| enum class Kind | |
| { | |
| MALFORMED, | |
| MALFORMED_BODY, | |
| UNEXPECTED_INNER, | |
| } kind; | |
| private: | |
| Attribute (Kind kind) : kind (kind) {} | |
| }; | |
| struct AttributeBody | |
| { | |
| static tl::expected<Parse::AttributeBody, AttributeBody> make_invalid_path () | |
| { | |
| return tl::unexpected<AttributeBody> (AttributeBody (Kind::INVALID_PATH)); | |
| } | |
| static tl::expected<Parse::AttributeBody, AttributeBody> | |
| make_invalid_attrinput () | |
| { | |
| return tl::unexpected<AttributeBody> ( | |
| AttributeBody (Kind::INVALID_ATTRINPUT)); | |
| } | |
| enum class Kind | |
| { | |
| INVALID_PATH, | |
| INVALID_ATTRINPUT, | |
| } kind; | |
| private: | |
| AttributeBody (Kind kind) : kind (kind) {} | |
| }; | |
| struct SimplePathSegment | |
| { | |
| static tl::expected<AST::SimplePathSegment, SimplePathSegment> | |
| make_invalid_token_or_path_end () | |
| { | |
| return tl::unexpected<SimplePathSegment> ( | |
| SimplePathSegment (Kind::INVALID_SIMPLE_PATH_TOKEN)); | |
| } | |
| enum class Kind | |
| { | |
| /* Invalid token found whilst parsing a simple path segment, could be an | |
| error or the end of the path */ | |
| INVALID_SIMPLE_PATH_TOKEN, | |
| } kind; | |
| private: | |
| SimplePathSegment (Kind kind) : kind (kind) {} | |
| }; | |
| struct PathIdentSegment | |
| { | |
| static tl::expected<AST::PathIdentSegment, PathIdentSegment> | |
| make_invalid_token () | |
| { | |
| return tl::unexpected<PathIdentSegment> ( | |
| PathIdentSegment (Kind::INVALID_PATH_IDENT_TOKEN)); | |
| } | |
| enum class Kind | |
| { | |
| INVALID_PATH_IDENT_TOKEN, | |
| } kind; | |
| private: | |
| PathIdentSegment (Kind kind) : kind (kind) {} | |
| }; | |
| struct AttrInput | |
| { | |
| static tl::expected<std::unique_ptr<AST::AttrInput>, AttrInput> | |
| make_malformed () | |
| { | |
| return tl::unexpected<AttrInput> (AttrInput (Kind::MALFORMED)); | |
| } | |
| static tl::expected<std::unique_ptr<AST::AttrInput>, AttrInput> | |
| make_bad_macro_invocation () | |
| { | |
| return tl::unexpected<AttrInput> (AttrInput (Kind::BAD_MACRO_INVOCATION)); | |
| } | |
| static tl::expected<std::unique_ptr<AST::AttrInput>, AttrInput> | |
| make_missing_attrinput () | |
| { | |
| return tl::unexpected<AttrInput> (AttrInput (Kind::MISSING)); | |
| } | |
| static tl::expected<std::unique_ptr<AST::AttrInput>, AttrInput> | |
| make_bad_token_tree () | |
| { | |
| return tl::unexpected<AttrInput> (AttrInput (Kind::BAD_TOKEN_TREE)); | |
| } | |
| enum class Kind | |
| { | |
| MALFORMED, | |
| BAD_MACRO_INVOCATION, | |
| BAD_TOKEN_TREE, | |
| // Not an hard error in some context | |
| MISSING, | |
| } kind; | |
| private: | |
| AttrInput (Kind kind) : kind (kind) {} | |
| }; | |
| struct Item | |
| { | |
| static tl::expected<std::unique_ptr<AST::Item>, Item> make_end_of_file () | |
| { | |
| return tl::unexpected<Item> (Item (Kind::END_OF_FILE)); | |
| } | |
| static tl::expected<std::unique_ptr<AST::Item>, Item> make_malformed () | |
| { | |
| return tl::unexpected<Item> (Item (Kind::MALFORMED)); | |
| } | |
| enum class Kind | |
| { | |
| END_OF_FILE, | |
| MALFORMED, | |
| } kind; | |
| private: | |
| Item (Kind kind) : kind (kind) {} | |
| }; | |
| struct Items | |
| { | |
| static tl::expected<std::vector<std::unique_ptr<AST::Item>>, Items> | |
| make_malformed (std::vector<std::unique_ptr<AST::Item>> items) | |
| { | |
| return tl::unexpected<Items> (Items (Kind::MALFORMED, std::move (items))); | |
| } | |
| enum class Kind | |
| { | |
| MALFORMED, | |
| } kind; | |
| Items (Items const &) = delete; | |
| Items &operator= (Items const &) = delete; | |
| Items (Items &&items) = default; | |
| Items &operator= (Items &&) = default; | |
| // Should we do anything with valid items ? | |
| std::vector<std::unique_ptr<AST::Item>> items; | |
| private: | |
| Items (Kind kind, std::vector<std::unique_ptr<AST::Item>> items) | |
| : kind (kind), items (std::move (items)) | |
| {} | |
| }; | |
| struct Visibility | |
| { | |
| static tl::expected<AST::Visibility, Visibility> make_malformed () | |
| { | |
| return tl::unexpected<Visibility> (Visibility (Kind::MALFORMED)); | |
| } | |
| static tl::expected<AST::Visibility, Visibility> make_missing_path () | |
| { | |
| return tl::unexpected<Visibility> (Visibility (Kind::MISSING_PATH)); | |
| } | |
| enum class Kind | |
| { | |
| MISSING_PATH, | |
| MALFORMED, | |
| } kind; | |
| private: | |
| Visibility (Kind kind) : kind (kind) {} | |
| }; | |
| struct LifetimeParam | |
| { | |
| static tl::expected<AST::LifetimeParam, LifetimeParam> | |
| make_not_a_lifetime_param () | |
| { | |
| return tl::unexpected<LifetimeParam> ( | |
| LifetimeParam (Kind::NOT_A_LIFETIME_PARAM)); | |
| } | |
| enum class Kind | |
| { | |
| NOT_A_LIFETIME_PARAM, | |
| } kind; | |
| private: | |
| LifetimeParam (Kind kind) : kind (kind) {} | |
| }; | |
| class Lifetime | |
| { | |
| }; | |
| struct LoopLabel | |
| { | |
| static tl::expected<AST::LoopLabel, LoopLabel> make_not_loop_label () | |
| { | |
| return tl::unexpected<LoopLabel> (LoopLabel (Kind::NOT_LOOP_LABEL)); | |
| } | |
| static tl::expected<AST::LoopLabel, LoopLabel> make_missing_colon () | |
| { | |
| return tl::unexpected<LoopLabel> (LoopLabel (Kind::MISSING_COLON)); | |
| } | |
| enum class Kind | |
| { | |
| // Not an hard error | |
| NOT_LOOP_LABEL, | |
| // Hard error | |
| MISSING_COLON, | |
| } kind; | |
| private: | |
| LoopLabel (Kind kind) : kind (kind) {} | |
| }; | |
| struct Self | |
| { | |
| static tl::expected<std::unique_ptr<AST::Param>, Self> | |
| make_self_raw_pointer () | |
| { | |
| return tl::unexpected<Self> (Self (Kind::SELF_RAW_PTR)); | |
| } | |
| static tl::expected<std::unique_ptr<AST::Param>, Self> make_not_self () | |
| { | |
| return tl::unexpected<Self> (Self (Kind::NOT_SELF)); | |
| } | |
| static tl::expected<std::unique_ptr<AST::Param>, Self> make_parsing_error () | |
| { | |
| return tl::unexpected<Self> (Self (Kind::PARSING)); | |
| } | |
| enum class Kind | |
| { | |
| SELF_RAW_PTR, | |
| PARSING, | |
| NOT_SELF, | |
| } kind; | |
| private: | |
| Self (Kind kind) : kind (kind) {} | |
| }; | |
| enum class Expr | |
| { | |
| MALFORMED, | |
| CHILD_ERROR, | |
| NULL_EXPR, | |
| NULL_DENOTATION, | |
| LEFT_DENOTATION, | |
| }; | |
| enum class StructExprField | |
| { | |
| MALFORMED, | |
| CHILD_ERROR, | |
| STRUCT_BASE_ATTRIBUTES, | |
| // Not a hard error | |
| STRUCT_BASE, | |
| }; | |
| // Generic intermediate AST node error used when the errors need no special | |
| // handling | |
| enum class Node | |
| { | |
| // Unexpected or missing token whilst parsing the node | |
| MALFORMED, | |
| // Error whilst parsing a child construct for the current node | |
| CHILD_ERROR, | |
| }; | |
| } // namespace Error | |
| } // namespace Parse | |
| } // namespace Rust | |
| #endif /* !RUST_PARSE_ERROR_H */ |