From: Pierre-Emmanuel Patry Date: Fri, 26 Dec 2025 03:38:52 +0000 (+0100) Subject: gccrs: Use error wrapper when required instead of nullptr X-Git-Tag: basepoints/gcc-17~1972 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=5ebb482c253ca0dd95378f5d53f20d20f4fe4ff8;p=thirdparty%2Fgcc.git gccrs: Use error wrapper when required instead of nullptr gcc/rust/ChangeLog: * ast/rust-ast-collector.cc (TokenCollector::visit): Update function name. * ast/rust-ast-pointer-visitor.cc (PointerVisitor::visit): Likewise. * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Likewise. * ast/rust-ast.cc (BreakExpr::as_string): Use getter function. (AttributeParser::parse_path_meta_item): Convert to expected type. (ReturnExpr::as_string): Change access to returned expr. * ast/rust-desugar-for-loops.cc (DesugarForLoops::DesugarCtx::make_break_arm): Likewise. * ast/rust-expr.h (class BreakExpr): Make expr in break optional. (class ReturnExpr): Make returned expr explicitely optional. Change the getters and introduce a const getter. * expand/rust-cfg-strip.cc (CfgStrip::visit): Convert to expected type. * expand/rust-macro-builtins-asm.cc (parse_reg_operand_in): Update constructor call to new expected types. (parse_reg_operand_out): Likewise. (parse_reg_operand_inout): Likewise. (parse_llvm_operands): Likewise. * expand/rust-macro-builtins-format-args.cc (format_args_parse_expr): Likewise. (format_args_parse_arguments): Likewise. * expand/rust-macro-builtins-helpers.cc (try_expand_many_expr): Update value for tl::expected. * expand/rust-macro-builtins-include.cc (MacroBuiltin::include_handler): Likewise. * expand/rust-macro-expand.cc (transcribe_expression): Update constructor call with expected value. * hir/rust-ast-lower-expr.cc (ASTLoweringExpr::visit): Likewise. * parse/rust-parse-error.h (enum class): Add new error types for Expr and StructExprField. * parse/rust-parse-impl-expr.hxx: Explicitely handle return expr parsing failure. Update to fit new expected types. * parse/rust-parse-impl.hxx: Likewise. * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Adapt to tl::expected. * ast/rust-desugar-while-let.cc (DesugarWhileLet::DesugarCtx::make_break_arm): Use optional for break expressions when missing instead of nullptr. * parse/rust-parse.h: Change function return type with expected. Remove error state from ExprOrStmt. Signed-off-by: Pierre-Emmanuel Patry --- diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc index 3da35557578..0ef5f06e529 100644 --- a/gcc/rust/ast/rust-ast-collector.cc +++ b/gcc/rust/ast/rust-ast-collector.cc @@ -1477,7 +1477,7 @@ TokenCollector::visit (BreakExpr &expr) if (expr.has_label ()) visit (expr.get_label_unchecked ()); if (expr.has_break_expr ()) - visit (expr.get_break_expr ()); + visit (expr.get_break_expr_unchecked ()); }); } diff --git a/gcc/rust/ast/rust-ast-pointer-visitor.cc b/gcc/rust/ast/rust-ast-pointer-visitor.cc index 6b5b5f2c66b..d403ef61578 100644 --- a/gcc/rust/ast/rust-ast-pointer-visitor.cc +++ b/gcc/rust/ast/rust-ast-pointer-visitor.cc @@ -490,7 +490,7 @@ PointerVisitor::visit (AST::BreakExpr &expr) visit (expr.get_label_unchecked ()); if (expr.has_break_expr ()) - reseat (expr.get_break_expr_ptr ()); + reseat (expr.get_break_expr_ptr_unchecked ()); } void diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc index 4157b75ab8a..6973d65bcff 100644 --- a/gcc/rust/ast/rust-ast-visitor.cc +++ b/gcc/rust/ast/rust-ast-visitor.cc @@ -510,7 +510,7 @@ DefaultASTVisitor::visit (AST::BreakExpr &expr) visit (expr.get_label_unchecked ()); if (expr.has_break_expr ()) - visit (expr.get_break_expr ()); + visit (expr.get_break_expr_unchecked ()); } void diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc index b9f7d280d80..f550edb088d 100644 --- a/gcc/rust/ast/rust-ast.cc +++ b/gcc/rust/ast/rust-ast.cc @@ -1649,7 +1649,7 @@ ReturnExpr::as_string () const std::string str ("return "); if (has_returned_expr ()) - str += return_expr->as_string (); + str += get_returned_expr ().as_string (); return str; } @@ -2233,7 +2233,7 @@ BreakExpr::as_string () const str += get_label_unchecked ().as_string () + " "; if (has_break_expr ()) - str += break_expr->as_string (); + str += get_break_expr_unchecked ().as_string (); return str; } @@ -3726,7 +3726,7 @@ AttributeParser::parse_path_meta_item () { lexer->skip_token (); - std::unique_ptr expr = parser->parse_expr (); + auto expr = parser->parse_expr (); // handle error // parse_expr should already emit an error and return nullptr @@ -3734,7 +3734,8 @@ AttributeParser::parse_path_meta_item () return nullptr; return std::unique_ptr ( - new MetaItemPathExpr (std::move (path.value ()), std::move (expr))); + new MetaItemPathExpr (std::move (path.value ()), + std::move (expr.value ()))); } case COMMA: // just simple path diff --git a/gcc/rust/ast/rust-desugar-for-loops.cc b/gcc/rust/ast/rust-desugar-for-loops.cc index eda844790f1..20aca533d91 100644 --- a/gcc/rust/ast/rust-desugar-for-loops.cc +++ b/gcc/rust/ast/rust-desugar-for-loops.cc @@ -37,7 +37,7 @@ DesugarForLoops::DesugarCtx::make_break_arm () builder.path_in_expression (LangItem::Kind::OPTION_NONE)))); auto break_expr - = std::unique_ptr (new BreakExpr (tl::nullopt, nullptr, {}, loc)); + = std::unique_ptr (new BreakExpr (tl::nullopt, tl::nullopt, {}, loc)); return MatchCase (std::move (arm), std::move (break_expr)); } diff --git a/gcc/rust/ast/rust-desugar-while-let.cc b/gcc/rust/ast/rust-desugar-while-let.cc index f75e39193d0..f2aec109f50 100644 --- a/gcc/rust/ast/rust-desugar-while-let.cc +++ b/gcc/rust/ast/rust-desugar-while-let.cc @@ -36,7 +36,7 @@ DesugarWhileLet::DesugarCtx::make_break_arm () auto arm = builder.match_arm (builder.wildcard ()); auto break_expr - = std::unique_ptr (new BreakExpr (tl::nullopt, nullptr, {}, loc)); + = std::unique_ptr (new BreakExpr (tl::nullopt, tl::nullopt, {}, loc)); return MatchCase (std::move (arm), std::move (break_expr)); } diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index ce3f4141f4d..2e49c50f46f 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -3192,7 +3192,7 @@ class BreakExpr : public ExprWithoutBlock { std::vector outer_attrs; tl::optional label; - std::unique_ptr break_expr; + tl::optional> break_expr; location_t locus; // TODO: find another way to store this to save memory? @@ -3206,15 +3206,18 @@ public: /* Returns whether the break expression has an expression used in the break or * not. */ - bool has_break_expr () const { return break_expr != nullptr; } + bool has_break_expr () const { return break_expr.has_value (); } // Constructor for a break expression BreakExpr (tl::optional break_label, - std::unique_ptr expr_in_break, + tl::optional> expr_in_break, std::vector outer_attribs, location_t locus) : outer_attrs (std::move (outer_attribs)), label (std::move (break_label)), break_expr (std::move (expr_in_break)), locus (locus) - {} + { + if (this->has_break_expr ()) + rust_assert (this->break_expr != nullptr); + } // Copy constructor defined to use clone for unique pointer BreakExpr (BreakExpr const &other) @@ -3222,9 +3225,8 @@ public: label (other.label), locus (other.locus), marked_for_strip (other.marked_for_strip) { - // guard to protect from null pointer dereference - if (other.break_expr != nullptr) - break_expr = other.break_expr->clone_expr (); + if (other.has_break_expr ()) + break_expr = other.get_break_expr_unchecked ().clone_expr (); } // Overload assignment operator to clone unique pointer @@ -3237,10 +3239,10 @@ public: outer_attrs = other.outer_attrs; // guard to protect from null pointer dereference - if (other.break_expr != nullptr) - break_expr = other.break_expr->clone_expr (); + if (other.has_break_expr ()) + break_expr = other.get_break_expr_unchecked ().clone_expr (); else - break_expr = nullptr; + break_expr = tl::nullopt; return *this; } @@ -3258,16 +3260,22 @@ public: bool is_marked_for_strip () const override { return marked_for_strip; } // TODO: is this better? Or is a "vis_block" better? - Expr &get_break_expr () + Expr &get_break_expr_unchecked () { rust_assert (has_break_expr ()); - return *break_expr; + return *break_expr.value (); } - std::unique_ptr &get_break_expr_ptr () + const Expr &get_break_expr_unchecked () const { rust_assert (has_break_expr ()); - return break_expr; + return *break_expr.value (); + } + + std::unique_ptr &get_break_expr_ptr_unchecked () + { + rust_assert (has_break_expr ()); + return break_expr.value (); } const std::vector &get_outer_attrs () const { return outer_attrs; } @@ -3831,7 +3839,7 @@ protected: class ReturnExpr : public ExprWithoutBlock { std::vector outer_attrs; - std::unique_ptr return_expr; + tl::optional> return_expr; location_t locus; // TODO: find another way to store this to save memory? @@ -3842,10 +3850,10 @@ public: /* Returns whether the object has an expression returned (i.e. not void return * type). */ - bool has_returned_expr () const { return return_expr != nullptr; } + bool has_returned_expr () const { return return_expr.has_value (); } // Constructor for ReturnExpr. - ReturnExpr (std::unique_ptr returned_expr, + ReturnExpr (tl::optional> returned_expr, std::vector outer_attribs, location_t locus) : outer_attrs (std::move (outer_attribs)), return_expr (std::move (returned_expr)), locus (locus) @@ -3857,8 +3865,8 @@ public: locus (other.locus), marked_for_strip (other.marked_for_strip) { // guard to protect from null pointer dereference - if (other.return_expr != nullptr) - return_expr = other.return_expr->clone_expr (); + if (other.return_expr) + return_expr = other.return_expr.value ()->clone_expr (); } // Overloaded assignment operator to clone return_expr pointer @@ -3870,10 +3878,10 @@ public: outer_attrs = other.outer_attrs; // guard to protect from null pointer dereference - if (other.return_expr != nullptr) - return_expr = other.return_expr->clone_expr (); + if (other.return_expr) + return_expr = other.return_expr.value ()->clone_expr (); else - return_expr = nullptr; + return_expr = tl::nullopt; return *this; } @@ -3893,14 +3901,20 @@ public: // TODO: is this better? Or is a "vis_block" better? Expr &get_returned_expr () { - rust_assert (return_expr != nullptr); - return *return_expr; + rust_assert (return_expr); + return *return_expr.value (); + } + + const Expr &get_returned_expr () const + { + rust_assert (return_expr); + return *return_expr.value (); } std::unique_ptr &get_returned_expr_ptr () { - rust_assert (return_expr != nullptr); - return return_expr; + rust_assert (return_expr); + return return_expr.value (); } const std::vector &get_outer_attrs () const { return outer_attrs; } diff --git a/gcc/rust/expand/rust-cfg-strip.cc b/gcc/rust/expand/rust-cfg-strip.cc index ef43ae785b0..071104036f7 100644 --- a/gcc/rust/expand/rust-cfg-strip.cc +++ b/gcc/rust/expand/rust-cfg-strip.cc @@ -1236,7 +1236,7 @@ CfgStrip::visit (AST::BreakExpr &expr) * is the only thing that can be done */ if (expr.has_break_expr ()) { - auto &break_expr = expr.get_break_expr (); + auto &break_expr = expr.get_break_expr_unchecked (); if (break_expr.is_marked_for_strip ()) rust_error_at (break_expr.get_locus (), diff --git a/gcc/rust/expand/rust-macro-builtins-asm.cc b/gcc/rust/expand/rust-macro-builtins-asm.cc index 136e6197c69..77c747bf5cd 100644 --- a/gcc/rust/expand/rust-macro-builtins-asm.cc +++ b/gcc/rust/expand/rust-macro-builtins-asm.cc @@ -326,10 +326,11 @@ parse_reg_operand_in (InlineAsmContext inline_asm_ctx) } auto expr = parser.parse_expr (); + rust_assert (expr); // TODO: When we've succesfully parse an expr, remember to clone_expr() // instead of nullptr - AST::InlineAsmOperand::In in (reg, std::move (expr)); + AST::InlineAsmOperand::In in (reg, std::move (expr.value ())); inline_asm_ctx.inline_asm.operands.emplace_back (in, locus); return inline_asm_ctx; } @@ -344,16 +345,15 @@ parse_reg_operand_out (InlineAsmContext inline_asm_ctx) if (!inline_asm_ctx.is_global_asm () && check_identifier (parser, "out")) { auto reg = parse_reg (inline_asm_ctx); - std::unique_ptr expr = parser.parse_expr (); - - rust_assert (expr != nullptr); + auto expr = parser.parse_expr (); + rust_assert (expr); /*auto expr_ptr = std::make_unique(AST::LiteralExpr(Literal))*/ // TODO: When we've succesfully parse an expr, remember to clone_expr() // instead of nullptr - AST::InlineAsmOperand::Out out (reg, false, std::move (expr)); + AST::InlineAsmOperand::Out out (reg, false, std::move (expr.value ())); inline_asm_ctx.inline_asm.operands.emplace_back (out, locus); @@ -402,10 +402,8 @@ parse_reg_operand_inout (InlineAsmContext inline_asm_ctx) // TODO: Is error propogation our top priority, the ? in rust's asm.rs is // doing a lot of work. - std::unique_ptr in_expr = parser.parse_expr (); - rust_assert (in_expr != nullptr); - - std::unique_ptr out_expr; + auto in_expr = parser.parse_expr (); + rust_assert (in_expr); if (parser.skip_token (MATCH_ARROW)) { @@ -413,10 +411,12 @@ parse_reg_operand_inout (InlineAsmContext inline_asm_ctx) { // auto result = parse_format_string (inline_asm_ctx); - out_expr = parser.parse_expr (); + auto out_expr = parser.parse_expr (); + rust_assert (out_expr); AST::InlineAsmOperand::SplitInOut splitinout ( - reg, false, std::move (in_expr), std::move (out_expr)); + reg, false, std::move (in_expr.value ()), + std::move (out_expr.value ())); inline_asm_ctx.inline_asm.operands.emplace_back (splitinout, locus); @@ -439,7 +439,8 @@ parse_reg_operand_inout (InlineAsmContext inline_asm_ctx) } else { - AST::InlineAsmOperand::InOut inout (reg, false, std::move (in_expr)); + AST::InlineAsmOperand::InOut inout (reg, false, + std::move (in_expr.value ())); inline_asm_ctx.inline_asm.operands.emplace_back (inout, locus); // https://github.com/rust-lang/rust/blob/a3167859f2fd8ff2241295469876a2b687280bdc/compiler/rustc_builtin_macros/src/asm.rs#L137 // RUST VERSION: ast::InlineAsmOperand::InOut { reg, expr, late: false @@ -1090,10 +1091,11 @@ parse_llvm_operands (LlvmAsmContext &ctx, std::vector &result) ParseRestrictions restrictions; restrictions.expr_can_be_null = true; auto expr = parser.parse_expr (); + rust_assert (expr); parser.skip_token (RIGHT_PAREN); - result.emplace_back (constraint, std::move (expr)); + result.emplace_back (constraint, std::move (expr.value ())); if (parser.peek_current_token ()->get_id () == COMMA) parser.skip_token (COMMA); diff --git a/gcc/rust/expand/rust-macro-builtins-format-args.cc b/gcc/rust/expand/rust-macro-builtins-format-args.cc index b4cbe0f8db7..d7d2aa3d447 100644 --- a/gcc/rust/expand/rust-macro-builtins-format-args.cc +++ b/gcc/rust/expand/rust-macro-builtins-format-args.cc @@ -42,8 +42,9 @@ format_args_parse_expr (location_t invoc_locus, AST::MacroInvocData &invoc, Parser &parser, BuiltinMacro macro_kind) { - std::unique_ptr format_expr = parser.parse_expr (); - rust_assert (format_expr); + auto format_expr_res = parser.parse_expr (); + rust_assert (format_expr_res); + auto format_expr = std::move (format_expr_res.value ()); if (format_expr->get_expr_kind () == AST::Expr::Kind::MacroInvocation) { @@ -114,7 +115,8 @@ format_args_parse_arguments (AST::MacroInvocData &invoc, if (!expr) rust_unreachable (); - args.push (AST::FormatArgument::named (ident, std::move (expr))); + args.push ( + AST::FormatArgument::named (ident, std::move (expr.value ()))); } else { @@ -124,7 +126,7 @@ format_args_parse_arguments (AST::MacroInvocData &invoc, if (!expr) rust_unreachable (); - args.push (AST::FormatArgument::normal (std::move (expr))); + args.push (AST::FormatArgument::normal (std::move (expr.value ()))); } // we need to skip commas, don't we? } diff --git a/gcc/rust/expand/rust-macro-builtins-helpers.cc b/gcc/rust/expand/rust-macro-builtins-helpers.cc index 2e5710c3bfa..e1b983c524f 100644 --- a/gcc/rust/expand/rust-macro-builtins-helpers.cc +++ b/gcc/rust/expand/rust-macro-builtins-helpers.cc @@ -151,7 +151,7 @@ try_expand_many_expr (Parser &parser, auto expr = parser.parse_expr (AST::AttrVec (), restrictions); // something must be so wrong that the expression could not be parsed rust_assert (expr); - result.push_back (std::move (expr)); + result.push_back (std::move (expr.value ())); auto next_token = parser.peek_current_token (); if (!parser.skip_token (COMMA) && next_token->get_id () != last_token_id) diff --git a/gcc/rust/expand/rust-macro-builtins-include.cc b/gcc/rust/expand/rust-macro-builtins-include.cc index 2f6e36d4feb..1461e523eaa 100644 --- a/gcc/rust/expand/rust-macro-builtins-include.cc +++ b/gcc/rust/expand/rust-macro-builtins-include.cc @@ -251,7 +251,7 @@ MacroBuiltin::include_handler (location_t invoc_locus, parsed_items = parser.parse_items ().value_or ( std::vector>{}); else - parsed_expr = parser.parse_expr (); + parsed_expr = parser.parse_expr ().value (); bool has_error = !parser.get_errors ().empty (); diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc index a37252644de..3848328ce72 100644 --- a/gcc/rust/expand/rust-macro-expand.cc +++ b/gcc/rust/expand/rust-macro-expand.cc @@ -987,7 +987,8 @@ transcribe_expression (Parser &parser) auto end = lexer.get_offs (); - return AST::Fragment ({std::move (expr)}, lexer.get_token_slice (start, end)); + return AST::Fragment ({std::move (expr.value ())}, + lexer.get_token_slice (start, end)); } /** diff --git a/gcc/rust/hir/rust-ast-lower-expr.cc b/gcc/rust/hir/rust-ast-lower-expr.cc index e3596bd77bb..d76811855f6 100644 --- a/gcc/rust/hir/rust-ast-lower-expr.cc +++ b/gcc/rust/hir/rust-ast-lower-expr.cc @@ -639,7 +639,7 @@ ASTLoweringExpr::visit (AST::BreakExpr &expr) HIR::Expr *break_expr = expr.has_break_expr () - ? ASTLoweringExpr::translate (expr.get_break_expr ()) + ? ASTLoweringExpr::translate (expr.get_break_expr_unchecked ()) : nullptr; auto crate_num = mappings.get_current_crate (); diff --git a/gcc/rust/parse/rust-parse-error.h b/gcc/rust/parse/rust-parse-error.h index 4d2d0e1c1a7..73d42f0c0fa 100644 --- a/gcc/rust/parse/rust-parse-error.h +++ b/gcc/rust/parse/rust-parse-error.h @@ -303,6 +303,23 @@ private: Self (Kind kind) : kind (kind) {} }; +enum class Expr +{ + MALFORMED, + CHILD_ERROR, + NULL_EXPR, + NULL_DENOTATION, + LEFT_DENOTATION, +}; + +enum class StructExprField +{ + MALFORMED, + CHILD_ERROR, + // Not a hard error + STRUCT_BASE, +}; + // Generic intermediate AST node error used when the errors need no special // handling enum class Node diff --git a/gcc/rust/parse/rust-parse-impl-expr.hxx b/gcc/rust/parse/rust-parse-impl-expr.hxx index 4eae47cfd2f..80a47803669 100644 --- a/gcc/rust/parse/rust-parse-impl-expr.hxx +++ b/gcc/rust/parse/rust-parse-impl-expr.hxx @@ -51,8 +51,8 @@ Parser::parse_block_expr ( const_TokenPtr t = lexer.peek_token (); while (t->get_id () != RIGHT_CURLY) { - ExprOrStmt expr_or_stmt = parse_stmt_or_expr (); - if (expr_or_stmt.is_error ()) + auto expr_or_stmt = parse_stmt_or_expr (); + if (!expr_or_stmt) { skip_after_end_block (); return tl::unexpected (Parse::Error::Node::CHILD_ERROR); @@ -60,15 +60,14 @@ Parser::parse_block_expr ( t = lexer.peek_token (); - if (expr_or_stmt.stmt != nullptr) + if (expr_or_stmt->stmt != nullptr) { - stmts.push_back (std::move (expr_or_stmt.stmt)); + stmts.push_back (std::move (expr_or_stmt->stmt)); } else { // assign to expression and end parsing inside - expr = std::move (expr_or_stmt.expr); - break; + expr = std::move (expr_or_stmt->expr); } } @@ -113,7 +112,7 @@ Parser::parse_anon_const () if (!expr) return tl::make_unexpected (Parse::Error::Node{}); - return AST::AnonConst (std::move (expr), locus); + return AST::AnonConst (std::move (expr.value ()), locus); } /* Parse a "const block", a block preceded by the `const` keyword whose @@ -153,7 +152,7 @@ Parser::parse_grouped_expr (AST::AttrVec outer_attrs) AST::AttrVec inner_attrs = parse_inner_attributes (); // parse required expr inside parentheses - std::unique_ptr expr_in_parens = parse_expr (); + auto expr_in_parens = parse_expr (); if (!expr_in_parens) { // skip after somewhere? @@ -168,8 +167,9 @@ Parser::parse_grouped_expr (AST::AttrVec outer_attrs) } return std::unique_ptr ( - new AST::GroupedExpr (std::move (expr_in_parens), std::move (inner_attrs), - std::move (outer_attrs), locus)); + new AST::GroupedExpr (std::move (expr_in_parens.value ()), + std::move (inner_attrs), std::move (outer_attrs), + locus)); } // Parses a closure expression (closure definition). @@ -282,8 +282,8 @@ Parser::parse_closure_expr (AST::AttrVec outer_attrs) // must be expr-only closure // parse expr, which is required - std::unique_ptr expr = parse_expr (); - if (expr == nullptr) + auto expr = parse_expr (); + if (!expr) { Error error (t->get_locus (), "failed to parse expression in closure"); @@ -294,8 +294,9 @@ Parser::parse_closure_expr (AST::AttrVec outer_attrs) } return std::unique_ptr ( - new AST::ClosureExprInner (std::move (expr), std::move (params), locus, - has_move, std::move (outer_attrs))); + new AST::ClosureExprInner (std::move (expr.value ()), + std::move (params), locus, has_move, + std::move (outer_attrs))); } } @@ -378,7 +379,7 @@ Parser::parse_literal_expr (AST::AttrVec outer_attrs) } template -std::unique_ptr +tl::expected, Parse::Error::Node> Parser::parse_box_expr (AST::AttrVec outer_attrs, location_t pratt_parsed_loc) { @@ -392,15 +393,18 @@ Parser::parse_box_expr (AST::AttrVec outer_attrs, ParseRestrictions restrictions; restrictions.expr_can_be_null = false; - std::unique_ptr expr = parse_expr (AST::AttrVec (), restrictions); + auto expr = parse_expr (AST::AttrVec (), restrictions); + if (!expr) + return tl::unexpected (Parse::Error::Node::CHILD_ERROR); return std::unique_ptr ( - new AST::BoxExpr (std::move (expr), std::move (outer_attrs), locus)); + new AST::BoxExpr (std::move (expr.value ()), std::move (outer_attrs), + locus)); } // Parses a return expression (including any expression to return). template -std::unique_ptr +tl::expected, Parse::Error::Node> Parser::parse_return_expr (AST::AttrVec outer_attrs, location_t pratt_parsed_loc) { @@ -414,17 +418,18 @@ Parser::parse_return_expr (AST::AttrVec outer_attrs, // parse expression to return, if it exists ParseRestrictions restrictions; restrictions.expr_can_be_null = true; - std::unique_ptr returned_expr - = parse_expr (AST::AttrVec (), restrictions); + auto returned_expr = parse_expr (AST::AttrVec (), restrictions); + tl::optional> expr = tl::nullopt; + if (returned_expr) + expr = std::move (returned_expr.value ()); - return std::unique_ptr ( - new AST::ReturnExpr (std::move (returned_expr), std::move (outer_attrs), - locus)); + return std::make_unique (std::move (expr), + std::move (outer_attrs), locus); } // Parses a try expression. template -std::unique_ptr +tl::expected, Parse::Error::Node> Parser::parse_try_expr (AST::AttrVec outer_attrs, location_t pratt_parsed_loc) { @@ -438,13 +443,7 @@ Parser::parse_try_expr (AST::AttrVec outer_attrs, auto 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 tl::unexpected (Parse::Error::Node::CHILD_ERROR); return std::unique_ptr ( new AST::TryExpr (std::move (block_expr.value ()), std::move (outer_attrs), @@ -454,7 +453,7 @@ Parser::parse_try_expr (AST::AttrVec outer_attrs, /* Parses a break expression (including any label to break to AND any return * expression). */ template -std::unique_ptr +tl::expected, Parse::Error::Node> Parser::parse_break_expr (AST::AttrVec outer_attrs, location_t pratt_parsed_loc) { @@ -473,12 +472,18 @@ Parser::parse_break_expr (AST::AttrVec outer_attrs, // parse break return expression if it exists ParseRestrictions restrictions; restrictions.expr_can_be_null = true; - std::unique_ptr return_expr - = parse_expr (AST::AttrVec (), restrictions); + auto return_expr = parse_expr (AST::AttrVec (), restrictions); - return std::unique_ptr ( - new AST::BreakExpr (std::move (label), std::move (return_expr), - std::move (outer_attrs), locus)); + if (return_expr) + return std::unique_ptr ( + new AST::BreakExpr (std::move (label), std::move (return_expr.value ()), + std::move (outer_attrs), locus)); + else if (return_expr.error () == Parse::Error::Expr::NULL_EXPR) + return std::unique_ptr ( + new AST::BreakExpr (std::move (label), tl::nullopt, + std::move (outer_attrs), locus)); + else + return tl::unexpected (Parse::Error::Node::CHILD_ERROR); } // Parses a continue expression (including any label to continue from). @@ -499,15 +504,15 @@ Parser::parse_continue_expr (AST::AttrVec outer_attrs, ? tl::optional (parsed_label.value ()) : tl::nullopt; - return std::unique_ptr ( - new AST::ContinueExpr (std::move (label), std::move (outer_attrs), locus)); + return std::make_unique (std::move (label), + std::move (outer_attrs), locus); } /* Parses an if expression of any kind, including with else, else if, else if * let, and neither. Note that any outer attributes will be ignored because if * expressions don't support them. */ template -std::unique_ptr +tl::expected, Parse::Error::Node> Parser::parse_if_expr (AST::AttrVec outer_attrs, location_t pratt_parsed_loc) { @@ -519,7 +524,7 @@ Parser::parse_if_expr (AST::AttrVec outer_attrs, if (!skip_token (IF)) { skip_after_end_block (); - return nullptr; + return tl::unexpected (Parse::Error::Node::MALFORMED); } } @@ -532,36 +537,37 @@ Parser::parse_if_expr (AST::AttrVec outer_attrs, add_error (std::move (error)); // skip somewhere? - return nullptr; + return tl::unexpected (Parse::Error::Node::MALFORMED); } /* parse required condition expr - HACK to prevent struct expr from being * parsed */ ParseRestrictions no_struct_expr; no_struct_expr.can_be_struct_expr = false; - std::unique_ptr condition = parse_expr ({}, no_struct_expr); - if (condition == nullptr) + auto condition = parse_expr ({}, no_struct_expr); + if (!condition) { Error error (lexer.peek_token ()->get_locus (), "failed to parse condition expression in if expression"); add_error (std::move (error)); // skip somewhere? - return nullptr; + return tl::unexpected (Parse::Error::Node::CHILD_ERROR); } // parse required block expr auto if_body = parse_block_expr (); if (!if_body) - return nullptr; + return tl::unexpected (Parse::Error::Node::CHILD_ERROR); // branch to parse end or else (and then else, else if, or else if let) if (lexer.peek_token ()->get_id () != ELSE) { // single selection - end of if expression return std::unique_ptr ( - new AST::IfExpr (std::move (condition), std::move (if_body.value ()), - std::move (outer_attrs), locus)); + new AST::IfExpr (std::move (condition.value ()), + std::move (if_body.value ()), std::move (outer_attrs), + locus)); } else { @@ -587,11 +593,11 @@ Parser::parse_if_expr (AST::AttrVec outer_attrs, add_error (std::move (error)); // skip somewhere? - return nullptr; + return tl::unexpected (Parse::Error::Node::CHILD_ERROR); } return std::unique_ptr ( - new AST::IfExprConseqElse (std::move (condition), + new AST::IfExprConseqElse (std::move (condition.value ()), std::move (if_body.value ()), std::move (else_body.value ()), std::move (outer_attrs), locus)); @@ -603,9 +609,8 @@ Parser::parse_if_expr (AST::AttrVec outer_attrs, if (lexer.peek_token (1)->get_id () == LET) { // parse if let expr (required) - std::unique_ptr if_let_expr - = parse_if_let_expr (); - if (if_let_expr == nullptr) + auto if_let_expr = parse_if_let_expr (); + if (!if_let_expr) { Error error (lexer.peek_token ()->get_locus (), "failed to parse (else) if let expression " @@ -613,20 +618,20 @@ Parser::parse_if_expr (AST::AttrVec outer_attrs, add_error (std::move (error)); // skip somewhere? - return nullptr; + return tl::unexpected (Parse::Error::Node::CHILD_ERROR); } return std::unique_ptr ( - new AST::IfExprConseqElse (std::move (condition), + new AST::IfExprConseqElse (std::move (condition.value ()), std::move (if_body.value ()), - std::move (if_let_expr), + std::move (if_let_expr.value ()), std::move (outer_attrs), locus)); } else { // parse if expr (required) - std::unique_ptr if_expr = parse_if_expr (); - if (if_expr == nullptr) + auto if_expr = parse_if_expr (); + if (!if_expr) { Error error (lexer.peek_token ()->get_locus (), "failed to parse (else) if expression after " @@ -634,13 +639,13 @@ Parser::parse_if_expr (AST::AttrVec outer_attrs, add_error (std::move (error)); // skip somewhere? - return nullptr; + return tl::unexpected (Parse::Error::Node::CHILD_ERROR); } return std::unique_ptr ( - new AST::IfExprConseqElse (std::move (condition), + new AST::IfExprConseqElse (std::move (condition.value ()), std::move (if_body.value ()), - std::move (if_expr), + std::move (if_expr.value ()), std::move (outer_attrs), locus)); } } @@ -651,7 +656,7 @@ Parser::parse_if_expr (AST::AttrVec outer_attrs, t->get_token_description ())); // skip somewhere? - return nullptr; + return tl::unexpected (Parse::Error::Node::MALFORMED); } } } @@ -660,7 +665,7 @@ Parser::parse_if_expr (AST::AttrVec outer_attrs, * if let, and none. Note that any outer attributes will be ignored as if let * expressions don't support them. */ template -std::unique_ptr +tl::expected, Parse::Error::Node> Parser::parse_if_let_expr (AST::AttrVec outer_attrs, location_t pratt_parsed_loc) { @@ -672,7 +677,7 @@ Parser::parse_if_let_expr (AST::AttrVec outer_attrs, if (!skip_token (IF)) { skip_after_end_block (); - return nullptr; + return tl::unexpected (Parse::Error::Node::MALFORMED); } } @@ -685,7 +690,7 @@ Parser::parse_if_let_expr (AST::AttrVec outer_attrs, add_error (std::move (error)); // skip somewhere? - return nullptr; + return tl::unexpected (Parse::Error::Node::MALFORMED); } lexer.skip_token (); @@ -700,27 +705,27 @@ Parser::parse_if_let_expr (AST::AttrVec outer_attrs, add_error (std::move (error)); // skip somewhere? - return nullptr; + return tl::unexpected (Parse::Error::Node::CHILD_ERROR); } if (!skip_token (EQUAL)) { // skip somewhere? - return nullptr; + return tl::unexpected (Parse::Error::Node::MALFORMED); } // parse expression (required) - HACK to prevent struct expr being parsed ParseRestrictions no_struct_expr; no_struct_expr.can_be_struct_expr = false; - std::unique_ptr scrutinee_expr = parse_expr ({}, no_struct_expr); - if (scrutinee_expr == nullptr) + auto scrutinee_expr = parse_expr ({}, no_struct_expr); + if (!scrutinee_expr) { Error error (lexer.peek_token ()->get_locus (), "failed to parse scrutinee expression in if let expression"); add_error (std::move (error)); // skip somewhere? - return nullptr; + return tl::unexpected (Parse::Error::Node::CHILD_ERROR); } /* TODO: check for expression not being a struct expression or lazy boolean * expression here? or actually probably in semantic analysis. */ @@ -735,7 +740,7 @@ Parser::parse_if_let_expr (AST::AttrVec outer_attrs, add_error (std::move (error)); // skip somewhere? - return nullptr; + return tl::unexpected (Parse::Error::Node::CHILD_ERROR); } // branch to parse end or else (and then else, else if, or else if let) @@ -743,7 +748,7 @@ Parser::parse_if_let_expr (AST::AttrVec outer_attrs, { // single selection - end of if let expression return std::unique_ptr (new AST::IfLetExpr ( - std::move (match_arm_pattern), std::move (scrutinee_expr), + std::move (match_arm_pattern), std::move (scrutinee_expr.value ()), std::move (if_let_body.value ()), std::move (outer_attrs), locus)); } else @@ -770,12 +775,12 @@ Parser::parse_if_let_expr (AST::AttrVec outer_attrs, add_error (std::move (error)); // skip somewhere? - return nullptr; + return tl::unexpected (Parse::Error::Node::CHILD_ERROR); } return std::unique_ptr ( new AST::IfLetExprConseqElse (std::move (match_arm_pattern), - std::move (scrutinee_expr), + std::move (scrutinee_expr.value ()), std::move (if_let_body.value ()), std::move (else_body.value ()), std::move (outer_attrs), locus)); @@ -787,9 +792,8 @@ Parser::parse_if_let_expr (AST::AttrVec outer_attrs, if (lexer.peek_token (1)->get_id () == LET) { // parse if let expr (required) - std::unique_ptr if_let_expr - = parse_if_let_expr (); - if (if_let_expr == nullptr) + auto if_let_expr = parse_if_let_expr (); + if (!if_let_expr) { Error error (lexer.peek_token ()->get_locus (), "failed to parse (else) if let expression " @@ -797,20 +801,22 @@ Parser::parse_if_let_expr (AST::AttrVec outer_attrs, add_error (std::move (error)); // skip somewhere? - return nullptr; + return tl::unexpected (Parse::Error::Node::CHILD_ERROR); } return std::unique_ptr ( new AST::IfLetExprConseqElse ( - std::move (match_arm_pattern), std::move (scrutinee_expr), - std::move (if_let_body.value ()), std::move (if_let_expr), - std::move (outer_attrs), locus)); + std::move (match_arm_pattern), + std::move (scrutinee_expr.value ()), + std::move (if_let_body.value ()), + std::move (if_let_expr.value ()), std::move (outer_attrs), + locus)); } else { // parse if expr (required) - std::unique_ptr if_expr = parse_if_expr (); - if (if_expr == nullptr) + auto if_expr = parse_if_expr (); + if (!if_expr) { Error error (lexer.peek_token ()->get_locus (), "failed to parse (else) if expression after " @@ -818,14 +824,16 @@ Parser::parse_if_let_expr (AST::AttrVec outer_attrs, add_error (std::move (error)); // skip somewhere? - return nullptr; + return tl::unexpected (Parse::Error::Node::CHILD_ERROR); } return std::unique_ptr ( new AST::IfLetExprConseqElse ( - std::move (match_arm_pattern), std::move (scrutinee_expr), - std::move (if_let_body.value ()), std::move (if_expr), - std::move (outer_attrs), locus)); + std::move (match_arm_pattern), + std::move (scrutinee_expr.value ()), + std::move (if_let_body.value ()), + std::move (if_expr.value ()), std::move (outer_attrs), + locus)); } } default: @@ -836,7 +844,7 @@ Parser::parse_if_let_expr (AST::AttrVec outer_attrs, t->get_token_description ())); // skip somewhere? - return nullptr; + return tl::unexpected (Parse::Error::Node::MALFORMED); } } } @@ -847,7 +855,7 @@ Parser::parse_if_let_expr (AST::AttrVec outer_attrs, /* Parses a "loop" infinite loop expression. Label is not parsed and should be * parsed via parse_labelled_loop_expr, which would call this. */ template -std::unique_ptr +tl::expected, Parse::Error::Node> Parser::parse_loop_expr (AST::AttrVec outer_attrs, tl::optional label, location_t pratt_parsed_loc) @@ -863,7 +871,7 @@ Parser::parse_loop_expr (AST::AttrVec outer_attrs, if (!skip_token (LOOP)) { skip_after_end_block (); - return nullptr; + return tl::unexpected (Parse::Error::Node::MALFORMED); } } else @@ -875,7 +883,7 @@ Parser::parse_loop_expr (AST::AttrVec outer_attrs, // parse loop body, which is required auto loop_body = parse_block_expr (); if (!loop_body) - return nullptr; + return tl::unexpected (Parse::Error::Node::CHILD_ERROR); return std::unique_ptr ( new AST::LoopExpr (std::move (loop_body.value ()), locus, std::move (label), @@ -885,7 +893,7 @@ Parser::parse_loop_expr (AST::AttrVec outer_attrs, /* Parses a "while" loop expression. Label is not parsed and should be parsed * via parse_labelled_loop_expr, which would call this. */ template -std::unique_ptr +tl::expected, Parse::Error::Node> Parser::parse_while_loop_expr ( AST::AttrVec outer_attrs, tl::optional label, location_t pratt_parsed_loc) @@ -901,7 +909,7 @@ Parser::parse_while_loop_expr ( if (!skip_token (WHILE)) { skip_after_end_block (); - return nullptr; + return tl::unexpected (Parse::Error::Node::MALFORMED); } } else @@ -919,21 +927,21 @@ Parser::parse_while_loop_expr ( add_error (std::move (error)); // skip somewhere? - return nullptr; + return tl::unexpected (Parse::Error::Node::MALFORMED); } // parse loop predicate (required) with HACK to prevent struct expr parsing ParseRestrictions no_struct_expr; no_struct_expr.can_be_struct_expr = false; - std::unique_ptr predicate = parse_expr ({}, no_struct_expr); - if (predicate == nullptr) + auto predicate = parse_expr ({}, no_struct_expr); + if (!predicate) { Error error (lexer.peek_token ()->get_locus (), "failed to parse predicate expression in while loop"); add_error (std::move (error)); // skip somewhere? - return nullptr; + return tl::unexpected (Parse::Error::Node::CHILD_ERROR); } /* TODO: check that it isn't struct expression here? actually, probably in * semantic analysis */ @@ -947,18 +955,19 @@ Parser::parse_while_loop_expr ( add_error (std::move (error)); // skip somewhere - return nullptr; + return tl::unexpected (Parse::Error::Node::CHILD_ERROR); } return std::unique_ptr ( - new AST::WhileLoopExpr (std::move (predicate), std::move (body.value ()), - locus, std::move (label), std::move (outer_attrs))); + new AST::WhileLoopExpr (std::move (predicate.value ()), + std::move (body.value ()), locus, std::move (label), + std::move (outer_attrs))); } /* Parses a "while let" loop expression. Label is not parsed and should be * parsed via parse_labelled_loop_expr, which would call this. */ template -std::unique_ptr +tl::expected, Parse::Error::Node> Parser::parse_while_let_loop_expr ( AST::AttrVec outer_attrs, tl::optional label) { @@ -979,7 +988,7 @@ Parser::parse_while_let_loop_expr ( add_error (std::move (error)); // skip somewhere - return nullptr; + return tl::unexpected (Parse::Error::Node::MALFORMED); } // as this token is definitely let now, save the computation of comparison lexer.skip_token (); @@ -993,28 +1002,28 @@ Parser::parse_while_let_loop_expr ( Error error (lexer.peek_token ()->get_locus (), "should be at least 1 pattern"); add_error (std::move (error)); - return nullptr; + return tl::unexpected (Parse::Error::Node::MALFORMED); } if (!skip_token (EQUAL)) { // skip somewhere? - return nullptr; + return tl::unexpected (Parse::Error::Node::MALFORMED); } /* parse predicate expression, which is required (and HACK to prevent struct * expr) */ ParseRestrictions no_struct_expr; no_struct_expr.can_be_struct_expr = false; - std::unique_ptr predicate_expr = parse_expr ({}, no_struct_expr); - if (predicate_expr == nullptr) + auto predicate_expr = parse_expr ({}, no_struct_expr); + if (!predicate_expr) { Error error (lexer.peek_token ()->get_locus (), "failed to parse predicate expression in while let loop"); add_error (std::move (error)); // skip somewhere? - return nullptr; + return tl::unexpected (Parse::Error::Node::CHILD_ERROR); } /* TODO: ensure that struct expression is not parsed? Actually, probably in * semantic analysis. */ @@ -1028,12 +1037,12 @@ Parser::parse_while_let_loop_expr ( add_error (std::move (error)); // skip somewhere? - return nullptr; + return tl::unexpected (Parse::Error::Node::CHILD_ERROR); } return std::unique_ptr ( new AST::WhileLetLoopExpr (std::move (predicate_pattern), - std::move (predicate_expr), + std::move (predicate_expr.value ()), std::move (body.value ()), locus, std::move (label), std::move (outer_attrs))); } @@ -1041,7 +1050,7 @@ Parser::parse_while_let_loop_expr ( /* Parses a "for" iterative loop. Label is not parsed and should be parsed via * parse_labelled_loop_expr, which would call this. */ template -std::unique_ptr +tl::expected, Parse::Error::Node> Parser::parse_for_loop_expr ( AST::AttrVec outer_attrs, tl::optional label) { @@ -1054,35 +1063,35 @@ Parser::parse_for_loop_expr ( // parse pattern, which is required std::unique_ptr pattern = parse_pattern (); - if (pattern == nullptr) + if (!pattern) { Error error (lexer.peek_token ()->get_locus (), "failed to parse iterator pattern in for loop"); add_error (std::move (error)); // skip somewhere? - return nullptr; + return tl::unexpected (Parse::Error::Node::CHILD_ERROR); } if (!skip_token (IN)) { // skip somewhere? - return nullptr; + return tl::unexpected (Parse::Error::Node::MALFORMED); } /* parse iterator expression, which is required - also HACK to prevent * struct expr */ ParseRestrictions no_struct_expr; no_struct_expr.can_be_struct_expr = false; - std::unique_ptr expr = parse_expr ({}, no_struct_expr); - if (expr == nullptr) + auto expr = parse_expr ({}, no_struct_expr); + if (!expr) { Error error (lexer.peek_token ()->get_locus (), "failed to parse iterator expression in for loop"); add_error (std::move (error)); // skip somewhere? - return nullptr; + return tl::unexpected (Parse::Error::Node::CHILD_ERROR); } // TODO: check to ensure this isn't struct expr? Or in semantic analysis. @@ -1095,17 +1104,17 @@ Parser::parse_for_loop_expr ( add_error (std::move (error)); // skip somewhere? - return nullptr; + return tl::unexpected (Parse::Error::Node::CHILD_ERROR); } return std::unique_ptr ( - new AST::ForLoopExpr (std::move (pattern), std::move (expr), + new AST::ForLoopExpr (std::move (pattern), std::move (expr.value ()), std::move (body.value ()), locus, std::move (label), std::move (outer_attrs))); } // Parses a loop expression with label (any kind of loop - disambiguates). template -std::unique_ptr +tl::expected, Parse::Error::Node> Parser::parse_labelled_loop_expr (const_TokenPtr tok, AST::AttrVec outer_attrs) { @@ -1125,7 +1134,7 @@ Parser::parse_labelled_loop_expr (const_TokenPtr tok, "label) - found %qs", tok->get_token_description ()); add_error (std::move (error)); - return nullptr; + return tl::unexpected (Parse::Error::Node::CHILD_ERROR); } else @@ -1135,7 +1144,7 @@ Parser::parse_labelled_loop_expr (const_TokenPtr tok, add_error (std::move (error)); // skip? - return nullptr; + return tl::unexpected (Parse::Error::Node::CHILD_ERROR); } } @@ -1154,24 +1163,13 @@ Parser::parse_labelled_loop_expr (const_TokenPtr tok, case WHILE: // further disambiguate into while vs while let if (lexer.peek_token (1)->get_id () == LET) - { - return parse_while_let_loop_expr (std::move (outer_attrs), - std::move (label)); - } + return parse_while_let_loop_expr (std::move (outer_attrs), + std::move (label)); else - { - return parse_while_loop_expr (std::move (outer_attrs), - std::move (label)); - } + return parse_while_loop_expr (std::move (outer_attrs), + std::move (label)); case LEFT_CURLY: - { - auto block - = parse_block_expr (std::move (outer_attrs), std::move (label)); - if (block) - return std::move (block.value ()); - else - return nullptr; - } + return parse_block_expr (std::move (outer_attrs), std::move (label)); default: // error add_error (Error (t->get_locus (), @@ -1179,13 +1177,13 @@ Parser::parse_labelled_loop_expr (const_TokenPtr tok, t->get_token_description ())); // skip? - return nullptr; + return tl::unexpected (Parse::Error::Node::CHILD_ERROR); } } // Parses a match expression. template -std::unique_ptr +tl::expected, Parse::Error::Node> Parser::parse_match_expr (AST::AttrVec outer_attrs, location_t pratt_parsed_loc) { @@ -1200,15 +1198,15 @@ Parser::parse_match_expr (AST::AttrVec outer_attrs, * expr) */ ParseRestrictions no_struct_expr; no_struct_expr.can_be_struct_expr = false; - std::unique_ptr scrutinee = parse_expr ({}, no_struct_expr); - if (scrutinee == nullptr) + auto scrutinee = parse_expr ({}, no_struct_expr); + if (!scrutinee) { Error error (lexer.peek_token ()->get_locus (), "failed to parse scrutinee expression in match expression"); add_error (std::move (error)); // skip somewhere? - return nullptr; + return tl::unexpected (Parse::Error::Node::CHILD_ERROR); } /* TODO: check for scrutinee expr not being struct expr? or do so in * semantic analysis */ @@ -1216,7 +1214,7 @@ Parser::parse_match_expr (AST::AttrVec outer_attrs, if (!skip_token (LEFT_CURLY)) { // skip somewhere? - return nullptr; + return tl::unexpected (Parse::Error::Node::MALFORMED); } // parse inner attributes (if they exist) @@ -1238,34 +1236,35 @@ Parser::parse_match_expr (AST::AttrVec outer_attrs, "failed to parse match arm in match arms"); add_error (std::move (error)); - return nullptr; + return tl::unexpected (Parse::Error::Node::CHILD_ERROR); } if (!skip_token (MATCH_ARROW)) { // skip after somewhere? // TODO is returning here a good idea? or is break better? - return nullptr; + return tl::unexpected (Parse::Error::Node::MALFORMED); } ParseRestrictions restrictions; restrictions.expr_can_be_stmt = true; - std::unique_ptr expr = parse_expr ({}, restrictions); + auto expr = parse_expr ({}, restrictions); - if (expr == nullptr) + if (!expr) { Error error (lexer.peek_token ()->get_locus (), "failed to parse expr in match arm in match expr"); add_error (std::move (error)); // skip somewhere? - return nullptr; + return tl::unexpected (Parse::Error::Node::CHILD_ERROR); } - bool is_expr_without_block = expr->is_expr_without_block (); + bool is_expr_without_block = expr.value ()->is_expr_without_block (); - match_arms.push_back (AST::MatchCase (std::move (arm), std::move (expr))); + match_arms.push_back ( + AST::MatchCase (std::move (arm), std::move (expr.value ()))); // handle comma presence if (lexer.peek_token ()->get_id () != COMMA) @@ -1284,7 +1283,7 @@ Parser::parse_match_expr (AST::AttrVec outer_attrs, "expression in match arm (if not final case)"); add_error (std::move (error)); - return nullptr; + return tl::unexpected (Parse::Error::Node::MALFORMED); } else { @@ -1298,20 +1297,20 @@ Parser::parse_match_expr (AST::AttrVec outer_attrs, if (!skip_token (RIGHT_CURLY)) { // skip somewhere? - return nullptr; + return tl::unexpected (Parse::Error::Node::MALFORMED); } match_arms.shrink_to_fit (); return std::unique_ptr ( - new AST::MatchExpr (std::move (scrutinee), std::move (match_arms), + new AST::MatchExpr (std::move (scrutinee.value ()), std::move (match_arms), std::move (inner_attrs), std::move (outer_attrs), locus)); } // Parses an async block expression. template -std::unique_ptr +tl::expected, Parse::Error::Node> Parser::parse_async_block_expr (AST::AttrVec outer_attrs) { location_t locus = lexer.peek_token ()->get_locus (); @@ -1335,7 +1334,7 @@ Parser::parse_async_block_expr (AST::AttrVec outer_attrs) add_error (std::move (error)); // skip somewhere? - return nullptr; + return tl::unexpected (Parse::Error::Node::CHILD_ERROR); } return std::unique_ptr ( @@ -1345,7 +1344,7 @@ Parser::parse_async_block_expr (AST::AttrVec outer_attrs) // Parses an unsafe block expression. template -std::unique_ptr +tl::expected, Parse::Error::Node> Parser::parse_unsafe_block_expr ( AST::AttrVec outer_attrs, location_t pratt_parsed_loc) { @@ -1366,7 +1365,7 @@ Parser::parse_unsafe_block_expr ( add_error (std::move (error)); // skip somewhere? - return nullptr; + return tl::unexpected (Parse::Error::Node::CHILD_ERROR); } return std::unique_ptr ( new AST::UnsafeBlockExpr (std::move (block_expr.value ()), @@ -1375,7 +1374,7 @@ Parser::parse_unsafe_block_expr ( // Parses an array definition expression. template -std::unique_ptr +tl::expected, Parse::Error::Node> Parser::parse_array_expr (AST::AttrVec outer_attrs, location_t pratt_parsed_loc) { @@ -1406,8 +1405,8 @@ Parser::parse_array_expr (AST::AttrVec outer_attrs, { // should have array elements // parse initial expression, which is required for either - std::unique_ptr initial_expr = parse_expr (); - if (initial_expr == nullptr) + auto initial_expr = parse_expr (); + if (!initial_expr) { Error error (lexer.peek_token ()->get_locus (), "could not parse expression in array expression " @@ -1415,7 +1414,7 @@ Parser::parse_array_expr (AST::AttrVec outer_attrs, add_error (std::move (error)); // skip somewhere? - return nullptr; + return tl::unexpected (Parse::Error::Node::CHILD_ERROR); } if (lexer.peek_token ()->get_id () == SEMICOLON) @@ -1424,8 +1423,8 @@ Parser::parse_array_expr (AST::AttrVec outer_attrs, lexer.skip_token (); // parse copy amount expression (required) - std::unique_ptr copy_amount = parse_expr (); - if (copy_amount == nullptr) + auto copy_amount = parse_expr (); + if (!copy_amount) { Error error (lexer.peek_token ()->get_locus (), "could not parse copy amount expression in array " @@ -1433,14 +1432,15 @@ Parser::parse_array_expr (AST::AttrVec outer_attrs, add_error (std::move (error)); // skip somewhere? - return nullptr; + return tl::unexpected (Parse::Error::Node::CHILD_ERROR); } skip_token (RIGHT_SQUARE); std::unique_ptr copied_array_elems ( - new AST::ArrayElemsCopied (std::move (initial_expr), - std::move (copy_amount), locus)); + new AST::ArrayElemsCopied (std::move (initial_expr.value ()), + std::move (copy_amount.value ()), + locus)); return std::unique_ptr ( new AST::ArrayExpr (std::move (copied_array_elems), std::move (inner_attrs), @@ -1451,7 +1451,7 @@ Parser::parse_array_expr (AST::AttrVec outer_attrs, // single-element array expression std::vector> exprs; exprs.reserve (1); - exprs.push_back (std::move (initial_expr)); + exprs.push_back (std::move (initial_expr.value ())); exprs.shrink_to_fit (); skip_token (RIGHT_SQUARE); @@ -1467,7 +1467,7 @@ Parser::parse_array_expr (AST::AttrVec outer_attrs, { // multi-element array expression (or trailing comma) std::vector> exprs; - exprs.push_back (std::move (initial_expr)); + exprs.push_back (std::move (initial_expr.value ())); const_TokenPtr t = lexer.peek_token (); while (t->get_id () == COMMA) @@ -1479,17 +1479,17 @@ Parser::parse_array_expr (AST::AttrVec outer_attrs, break; // parse expression (required) - std::unique_ptr expr = parse_expr (); - if (expr == nullptr) + auto expr = parse_expr (); + if (!expr) { Error error (lexer.peek_token ()->get_locus (), "failed to parse element in array expression"); add_error (std::move (error)); // skip somewhere? - return nullptr; + return tl::unexpected (Parse::Error::Node::CHILD_ERROR); } - exprs.push_back (std::move (expr)); + exprs.push_back (std::move (expr.value ())); t = lexer.peek_token (); } @@ -1514,14 +1514,14 @@ Parser::parse_array_expr (AST::AttrVec outer_attrs, add_error (std::move (error)); // skip somewhere? - return nullptr; + return tl::unexpected (Parse::Error::Node::MALFORMED); } } } // Parses a grouped or tuple expression (disambiguates). template -std::unique_ptr +tl::expected, Parse::Error::Node> Parser::parse_grouped_or_tuple_expr ( AST::AttrVec outer_attrs, location_t pratt_parsed_loc) { @@ -1549,15 +1549,15 @@ Parser::parse_grouped_or_tuple_expr ( } // parse first expression (required) - std::unique_ptr first_expr = parse_expr (); - if (first_expr == nullptr) + auto first_expr = parse_expr (); + if (!first_expr) { Error error (lexer.peek_token ()->get_locus (), "failed to parse expression in grouped or tuple expression"); add_error (std::move (error)); // skip after somewhere? - return nullptr; + return tl::unexpected (Parse::Error::Node::CHILD_ERROR); } // detect whether grouped expression with right parentheses as next token @@ -1568,14 +1568,15 @@ Parser::parse_grouped_or_tuple_expr ( // create grouped expr return std::unique_ptr ( - new AST::GroupedExpr (std::move (first_expr), std::move (inner_attrs), - std::move (outer_attrs), locus)); + new AST::GroupedExpr (std::move (first_expr.value ()), + std::move (inner_attrs), std::move (outer_attrs), + locus)); } else if (lexer.peek_token ()->get_id () == COMMA) { // tuple expr std::vector> exprs; - exprs.push_back (std::move (first_expr)); + exprs.push_back (std::move (first_expr.value ())); // parse potential other tuple exprs const_TokenPtr t = lexer.peek_token (); @@ -1588,17 +1589,17 @@ Parser::parse_grouped_or_tuple_expr ( break; // parse expr, which is now required - std::unique_ptr expr = parse_expr (); - if (expr == nullptr) + auto expr = parse_expr (); + if (!expr) { Error error (lexer.peek_token ()->get_locus (), "failed to parse expr in tuple expr"); add_error (std::move (error)); // skip somewhere? - return nullptr; + return tl::unexpected (Parse::Error::Node::CHILD_ERROR); } - exprs.push_back (std::move (expr)); + exprs.push_back (std::move (expr.value ())); t = lexer.peek_token (); } @@ -1622,13 +1623,14 @@ Parser::parse_grouped_or_tuple_expr ( add_error (std::move (error)); // skip somewhere? - return nullptr; + return tl::unexpected (Parse::Error::Node::MALFORMED); } } // Parses a struct expression field. template -std::unique_ptr +tl::expected, + Parse::Error::StructExprField> Parser::parse_struct_expr_field () { AST::AttrVec outer_attrs = parse_outer_attributes (); @@ -1643,20 +1645,21 @@ Parser::parse_struct_expr_field () lexer.skip_token (1); // parse expression (required) - std::unique_ptr expr = parse_expr (); - if (expr == nullptr) + auto expr = parse_expr (); + if (!expr) { Error error (t->get_locus (), "failed to parse struct expression field with " "identifier and expression"); add_error (std::move (error)); - return nullptr; + return tl::unexpected ( + Parse::Error::StructExprField::CHILD_ERROR); } return std::unique_ptr ( new AST::StructExprFieldIdentifierValue (std::move (ident), - std::move (expr), + std::move (expr.value ()), std::move (outer_attrs), t->get_locus ())); } @@ -1680,23 +1683,23 @@ Parser::parse_struct_expr_field () if (!skip_token (COLON)) { // skip somewhere? - return nullptr; + return tl::unexpected (Parse::Error::StructExprField::MALFORMED); } // parse field expression (required) - std::unique_ptr expr = parse_expr (); - if (expr == nullptr) + auto expr = parse_expr (); + if (!expr) { Error error (t->get_locus (), "failed to parse expr in struct (or enum) expr " "field with tuple index"); add_error (std::move (error)); - return nullptr; + return tl::unexpected (Parse::Error::StructExprField::CHILD_ERROR); } return std::unique_ptr ( - new AST::StructExprFieldIndexValue (index, std::move (expr), + new AST::StructExprFieldIndexValue (index, std::move (expr.value ()), std::move (outer_attrs), t->get_locus ())); } @@ -1704,7 +1707,7 @@ Parser::parse_struct_expr_field () /* this is a struct base and can't be parsed here, so just return * nothing without erroring */ - return nullptr; + return tl::unexpected (Parse::Error::StructExprField::STRUCT_BASE); default: add_error ( Error (t->get_locus (), @@ -1712,14 +1715,14 @@ Parser::parse_struct_expr_field () "expected identifier or integer literal", t->get_token_description ())); - return nullptr; + return tl::unexpected (Parse::Error::StructExprField::MALFORMED); } } /* Pratt parser impl of parse_expr. FIXME: this is only provisional and * probably will be changed. */ template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_expr (int right_binding_power, AST::AttrVec outer_attrs, ParseRestrictions restrictions) @@ -1735,17 +1738,17 @@ Parser::parse_expr (int right_binding_power, TokenId id = current_token->get_id (); if (id == SEMICOLON || id == RIGHT_PAREN || id == RIGHT_CURLY || id == RIGHT_SQUARE || id == COMMA || id == LEFT_CURLY) - return nullptr; + return tl::unexpected (Parse::Error::Expr::NULL_EXPR); } ParseRestrictions null_denotation_restrictions = restrictions; null_denotation_restrictions.expr_can_be_stmt = false; // parse null denotation (unary part of expression) - std::unique_ptr expr + tl::expected, Parse::Error::Expr> expr = null_denotation ({}, null_denotation_restrictions); - if (expr == nullptr) - return nullptr; + if (!expr) + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); return left_denotations (std::move (expr), right_binding_power, std::move (outer_attrs), restrictions); @@ -1753,7 +1756,7 @@ Parser::parse_expr (int right_binding_power, // Parse expression with lowest left binding power. template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_expr (AST::AttrVec outer_attrs, ParseRestrictions restrictions) { @@ -1761,27 +1764,27 @@ Parser::parse_expr (AST::AttrVec outer_attrs, } template -std::unique_ptr -Parser::left_denotations (std::unique_ptr expr, - int right_binding_power, - AST::AttrVec outer_attrs, - ParseRestrictions restrictions) +tl::expected, Parse::Error::Expr> +Parser::left_denotations ( + tl::expected, Parse::Error::Expr> expr, + int right_binding_power, AST::AttrVec outer_attrs, + ParseRestrictions restrictions) { - if (expr == nullptr) + if (!expr) { // DEBUG rust_debug ("null denotation is null; returning null for parse_expr"); - return nullptr; + return tl::unexpected (Parse::Error::Expr::NULL_DENOTATION); } const_TokenPtr current_token = lexer.peek_token (); - if (restrictions.expr_can_be_stmt && !expr->is_expr_without_block () + if (restrictions.expr_can_be_stmt && !expr.value ()->is_expr_without_block () && current_token->get_id () != DOT && current_token->get_id () != QUESTION_MARK) { rust_debug ("statement expression with block"); - expr->set_outer_attrs (std::move (outer_attrs)); + expr.value ()->set_outer_attrs (std::move (outer_attrs)); return expr; } @@ -1793,15 +1796,15 @@ Parser::left_denotations (std::unique_ptr expr, lexer.skip_token (); // FIXME attributes should generally be applied to the null denotation. - expr = left_denotation (current_token, std::move (expr), + expr = left_denotation (current_token, std::move (expr.value ()), std::move (outer_attrs), restrictions); - if (expr == nullptr) + if (!expr) { // DEBUG rust_debug ("left denotation is null; returning null for parse_expr"); - return nullptr; + return tl::unexpected (Parse::Error::Expr::LEFT_DENOTATION); } current_token = lexer.peek_token (); @@ -1812,7 +1815,7 @@ Parser::left_denotations (std::unique_ptr expr, /* Determines action to take when finding token at beginning of expression. */ template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::null_denotation (AST::AttrVec outer_attrs, ParseRestrictions restrictions) { @@ -1860,7 +1863,7 @@ Parser::null_denotation (AST::AttrVec outer_attrs, // Handling of expresions that start with a path for `null_denotation`. template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::null_denotation_path ( AST::PathInExpression path, AST::AttrVec outer_attrs, ParseRestrictions restrictions) @@ -1873,8 +1876,7 @@ Parser::null_denotation_path ( { // HACK: add outer attrs to path path.set_outer_attrs (std::move (outer_attrs)); - return std::unique_ptr ( - new AST::PathInExpression (std::move (path))); + return std::make_unique (std::move (path)); } // branch on next token @@ -1928,8 +1930,7 @@ Parser::null_denotation_path ( // assume path is returned // HACK: add outer attributes to path path.set_outer_attrs (std::move (outer_attrs)); - return std::unique_ptr ( - new AST::PathInExpression (std::move (path))); + return std::make_unique (std::move (path)); } return parse_struct_expr_tuple_partial (std::move (path), std::move (outer_attrs)); @@ -1954,7 +1955,7 @@ Parser::null_denotation_path ( // Handling of expresions that do not start with a path for `null_denotation`. template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::null_denotation_not_path ( const_TokenPtr tok, AST::AttrVec outer_attrs, ParseRestrictions restrictions) { @@ -1969,8 +1970,8 @@ Parser::null_denotation_not_path ( AST::QualifiedPathInExpression path = parse_qualified_path_in_expression (tok->get_locus ()); path.set_outer_attrs (std::move (outer_attrs)); - return std::unique_ptr ( - new AST::QualifiedPathInExpression (std::move (path))); + return std::make_unique ( + std::move (path)); } // FIXME: delegate to parse_literal_expr instead? would have to rejig // tokens and whatever. @@ -2018,8 +2019,15 @@ Parser::null_denotation_not_path ( AST::Literal::BOOL, tok->get_type_hint (), {}, tok->get_locus ())); case LEFT_PAREN: - return parse_grouped_or_tuple_expr (std::move (outer_attrs), - tok->get_locus ()); + { + auto grouped_or_tuple_expr + = parse_grouped_or_tuple_expr (std::move (outer_attrs), + tok->get_locus ()); + if (grouped_or_tuple_expr) + return std::move (grouped_or_tuple_expr.value ()); + else + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); + } /*case PLUS: { // unary plus operator // invoke parse_expr recursively with appropriate priority, etc. for @@ -2043,11 +2051,10 @@ Parser::null_denotation_not_path ( entered_from_unary.entered_from_unary = true; if (!restrictions.can_be_struct_expr) entered_from_unary.can_be_struct_expr = false; - std::unique_ptr expr - = parse_expr (LBP_UNARY_MINUS, {}, entered_from_unary); + auto expr = parse_expr (LBP_UNARY_MINUS, {}, entered_from_unary); - if (expr == nullptr) - return nullptr; + if (!expr) + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); // 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 @@ -2061,9 +2068,10 @@ Parser::null_denotation_not_path ( /* FIXME: allow outer attributes on these expressions by having an * outer attrs parameter in function*/ - return std::unique_ptr ( - new AST::NegationExpr (std::move (expr), NegationOperator::NEGATE, - std::move (outer_attrs), tok->get_locus ())); + return std::make_unique (std::move (expr.value ()), + NegationOperator::NEGATE, + std::move (outer_attrs), + tok->get_locus ()); } case EXCLAM: { // logical or bitwise not @@ -2071,11 +2079,10 @@ Parser::null_denotation_not_path ( entered_from_unary.entered_from_unary = true; if (!restrictions.can_be_struct_expr) entered_from_unary.can_be_struct_expr = false; - std::unique_ptr expr - = parse_expr (LBP_UNARY_EXCLAM, {}, entered_from_unary); + auto expr = parse_expr (LBP_UNARY_EXCLAM, {}, entered_from_unary); - if (expr == nullptr) - return nullptr; + if (!expr) + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); // can only apply to boolean expressions /*if (expr.get_type() != boolean_type_node) { rust_error_at(tok->get_locus(), @@ -2087,9 +2094,10 @@ Parser::null_denotation_not_path ( * analysis */ // FIXME: allow outer attributes on these expressions - return std::unique_ptr ( - new AST::NegationExpr (std::move (expr), NegationOperator::NOT, - std::move (outer_attrs), tok->get_locus ())); + return std::make_unique (std::move (expr.value ()), + NegationOperator::NOT, + std::move (outer_attrs), + tok->get_locus ()); } case ASTERISK: { @@ -2098,17 +2106,20 @@ Parser::null_denotation_not_path ( ParseRestrictions entered_from_unary; entered_from_unary.entered_from_unary = true; entered_from_unary.can_be_struct_expr = false; - std::unique_ptr expr - = parse_expr (LBP_UNARY_ASTERISK, {}, entered_from_unary); + auto expr = parse_expr (LBP_UNARY_ASTERISK, {}, entered_from_unary); + if (!expr) + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); // FIXME: allow outer attributes on expression - return std::unique_ptr ( - new AST::DereferenceExpr (std::move (expr), std::move (outer_attrs), - tok->get_locus ())); + return std::make_unique (std::move ( + expr.value ()), + std::move (outer_attrs), + tok->get_locus ()); } case AMP: { // (single) "borrow" expression - shared (mutable) or immutable - std::unique_ptr expr = nullptr; + tl::expected, Parse::Error::Expr> expr + = tl::unexpected (Parse::Error::Expr::MALFORMED); Mutability mutability = Mutability::Imm; bool raw_borrow = false; @@ -2142,26 +2153,42 @@ Parser::null_denotation_not_path ( "raw borrow should be either const or mut"); } lexer.skip_token (); - expr = parse_expr (LBP_UNARY_AMP_MUT, {}, entered_from_unary); + auto expr_result + = parse_expr (LBP_UNARY_AMP_MUT, {}, entered_from_unary); + if (expr_result) + expr = std::move (expr_result.value ()); + else + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); raw_borrow = true; } else if (t->get_id () == MUT) { lexer.skip_token (); - expr = parse_expr (LBP_UNARY_AMP_MUT, {}, entered_from_unary); + auto expr_result + = parse_expr (LBP_UNARY_AMP_MUT, {}, entered_from_unary); + if (expr_result) + expr = std::move (expr_result.value ()); + else + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); mutability = Mutability::Mut; raw_borrow = false; } else { - expr = parse_expr (LBP_UNARY_AMP, {}, entered_from_unary); + auto expr_result + = parse_expr (LBP_UNARY_AMP, {}, entered_from_unary); + if (expr_result) + expr = std::move (expr_result.value ()); + else + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); raw_borrow = false; } // FIXME: allow outer attributes on expression - return std::unique_ptr ( - new AST::BorrowExpr (std::move (expr), mutability, raw_borrow, false, - std::move (outer_attrs), tok->get_locus ())); + return std::make_unique (std::move (expr.value ()), + mutability, raw_borrow, false, + std::move (outer_attrs), + tok->get_locus ()); } case LOGICAL_AND: { @@ -2175,113 +2202,224 @@ Parser::null_denotation_not_path ( if (lexer.peek_token ()->get_id () == MUT) { lexer.skip_token (); - expr = parse_expr (LBP_UNARY_AMP_MUT, {}, entered_from_unary); + auto expr_res + = parse_expr (LBP_UNARY_AMP_MUT, {}, entered_from_unary); + if (!expr_res) + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); + expr = std::move (expr_res.value ()); mutability = Mutability::Mut; } else { - expr = parse_expr (LBP_UNARY_AMP, {}, entered_from_unary); + auto expr_result + = parse_expr (LBP_UNARY_AMP, {}, entered_from_unary); + if (expr_result) + expr = std::move (expr_result.value ()); + else + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); mutability = Mutability::Imm; } // FIXME: allow outer attributes on expression - return std::unique_ptr ( - new AST::BorrowExpr (std::move (expr), mutability, false, true, - std::move (outer_attrs), tok->get_locus ())); + return std::make_unique (std::move (expr), mutability, + false, true, + std::move (outer_attrs), + tok->get_locus ()); } case OR: case PIPE: case MOVE: // closure expression - return parse_closure_expr_pratt (tok, std::move (outer_attrs)); + { + auto ret = parse_closure_expr_pratt (tok, std::move (outer_attrs)); + if (ret) + return std::move (ret.value ()); + else + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); + } case DOT_DOT: // either "range to" or "range full" expressions - return parse_nud_range_exclusive_expr (tok, std::move (outer_attrs)); + { + auto ret + = parse_nud_range_exclusive_expr (tok, std::move (outer_attrs)); + if (ret) + return std::move (ret.value ()); + else + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); + } case DOT_DOT_EQ: // range to inclusive expr - return parse_range_to_inclusive_expr (tok, std::move (outer_attrs)); + { + auto ret = parse_range_to_inclusive_expr (tok, std::move (outer_attrs)); + if (ret) + return std::move (ret.value ()); + else + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); + } case RETURN_KW: // FIXME: is this really a null denotation expression? - return parse_return_expr (std::move (outer_attrs), tok->get_locus ()); + { + auto ret + = parse_return_expr (std::move (outer_attrs), tok->get_locus ()); + if (ret) + return std::move (ret.value ()); + else + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); + } case TRY: // FIXME: is this really a null denotation expression? - return parse_try_expr (std::move (outer_attrs), tok->get_locus ()); + { + auto ret = parse_try_expr (std::move (outer_attrs), tok->get_locus ()); + if (ret) + return std::move (ret.value ()); + else + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); + } case BREAK: // FIXME: is this really a null denotation expression? - return parse_break_expr (std::move (outer_attrs), tok->get_locus ()); + { + auto ret + = parse_break_expr (std::move (outer_attrs), tok->get_locus ()); + if (ret) + return std::move (ret.value ()); + else + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); + } case CONTINUE: return parse_continue_expr (std::move (outer_attrs), tok->get_locus ()); case LEFT_CURLY: // ok - this is an expression with block for once. { - auto block = parse_block_expr (std::move (outer_attrs), tl::nullopt, - tok->get_locus ()); - if (block) - return std::move (block.value ()); + auto ret = parse_block_expr (std::move (outer_attrs), tl::nullopt, + tok->get_locus ()); + if (ret) + return std::move (ret.value ()); else - return nullptr; + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); } case IF: // if or if let, so more lookahead to find out if (lexer.peek_token ()->get_id () == LET) { // if let expr - return parse_if_let_expr (std::move (outer_attrs), tok->get_locus ()); + auto ret + = parse_if_let_expr (std::move (outer_attrs), tok->get_locus ()); + if (ret) + return std::move (ret.value ()); + else + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); } else { // if expr - return parse_if_expr (std::move (outer_attrs), tok->get_locus ()); + auto ret = parse_if_expr (std::move (outer_attrs), tok->get_locus ()); + if (ret) + return std::move (ret.value ()); + else + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); } case LIFETIME: - return parse_labelled_loop_expr (tok, std::move (outer_attrs)); + { + auto ret = parse_labelled_loop_expr (tok, std::move (outer_attrs)); + if (ret) + return std::move (ret.value ()); + else + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); + } case LOOP: - return parse_loop_expr (std::move (outer_attrs), tl::nullopt, - tok->get_locus ()); + { + auto ret = parse_loop_expr (std::move (outer_attrs), tl::nullopt, + tok->get_locus ()); + if (ret) + return std::move (ret.value ()); + else + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); + } case WHILE: if (lexer.peek_token ()->get_id () == LET) { - return parse_while_let_loop_expr (std::move (outer_attrs)); + auto ret = parse_while_let_loop_expr (std::move (outer_attrs)); + if (ret) + return std::move (ret.value ()); + else + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); } else { - return parse_while_loop_expr (std::move (outer_attrs), tl::nullopt, - tok->get_locus ()); + auto ret = parse_while_loop_expr (std::move (outer_attrs), + tl::nullopt, tok->get_locus ()); + if (ret) + return std::move (ret.value ()); + else + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); } case FOR: - return parse_for_loop_expr (std::move (outer_attrs), tl::nullopt); + { + auto ret = parse_for_loop_expr (std::move (outer_attrs), tl::nullopt); + if (ret) + return std::move (ret.value ()); + else + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); + } case MATCH_KW: // also an expression with block - return parse_match_expr (std::move (outer_attrs), tok->get_locus ()); + { + auto ret + = parse_match_expr (std::move (outer_attrs), tok->get_locus ()); + if (ret) + return std::move (ret.value ()); + else + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); + } + case LEFT_SQUARE: // array definition expr (not indexing) - return parse_array_expr (std::move (outer_attrs), tok->get_locus ()); + { + auto ret + = parse_array_expr (std::move (outer_attrs), tok->get_locus ()); + if (ret) + return std::move (ret.value ()); + else + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); + } case UNSAFE: - return parse_unsafe_block_expr (std::move (outer_attrs), - tok->get_locus ()); + { + auto ret = parse_unsafe_block_expr (std::move (outer_attrs), + tok->get_locus ()); + if (ret) + return std::move (ret.value ()); + else + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); + } case BOX: - return parse_box_expr (std::move (outer_attrs), tok->get_locus ()); + { + auto ret = parse_box_expr (std::move (outer_attrs), tok->get_locus ()); + if (ret) + return std::move (ret.value ()); + else + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); + } case UNDERSCORE: add_error ( Error (tok->get_locus (), "use of %qs is not allowed on the right-side of an assignment", tok->get_token_description ())); - return nullptr; + return tl::unexpected (Parse::Error::Expr::MALFORMED); case CONST: { - auto const_block + auto ret = parse_const_block_expr (std::move (outer_attrs), tok->get_locus ()); - if (const_block) - return std::move (const_block.value ()); + if (ret) + return std::move (ret.value ()); else - return nullptr; + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); } default: if (!restrictions.expr_can_be_null) add_error (Error (tok->get_locus (), "found unexpected token %qs in null denotation", tok->get_token_description ())); - return nullptr; + return tl::unexpected (Parse::Error::Expr::MALFORMED); } } @@ -2289,7 +2427,7 @@ Parser::null_denotation_not_path ( * operators or other punctuation. Returns a function pointer to member * function that implements the left denotation for the token given. */ template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::left_denotation (const_TokenPtr tok, std::unique_ptr left, AST::AttrVec outer_attrs, @@ -2303,9 +2441,8 @@ Parser::left_denotation (const_TokenPtr tok, { location_t left_locus = left->get_locus (); // error propagation expression - unary postfix - return std::unique_ptr ( - new AST::ErrorPropagationExpr (std::move (left), - std::move (outer_attrs), left_locus)); + return std::make_unique ( + std::move (left), std::move (outer_attrs), left_locus); } case PLUS: // sum expression - binary infix @@ -2553,7 +2690,7 @@ Parser::left_denotation (const_TokenPtr tok, "found scope resolution operator in left denotation " "function - this should probably be handled elsewhere")); - return nullptr; + return tl::unexpected (Parse::Error::Expr::MALFORMED); case DOT: { /* field expression or method call - relies on parentheses after next @@ -2634,7 +2771,7 @@ Parser::left_denotation (const_TokenPtr tok, "found unexpected token %qs in left denotation", tok->get_token_description ())); - return nullptr; + return tl::unexpected (Parse::Error::Expr::MALFORMED); } } @@ -2676,247 +2813,226 @@ get_lbp_for_arithmetic_or_logical_expr ( // Parses an arithmetic or logical expression (with Pratt parsing). template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_arithmetic_or_logical_expr ( const_TokenPtr, std::unique_ptr left, AST::AttrVec, AST::ArithmeticOrLogicalExpr::ExprType expr_type, ParseRestrictions restrictions) { // parse RHS (as tok has already been consumed in parse_expression) - std::unique_ptr right - = parse_expr (get_lbp_for_arithmetic_or_logical_expr (expr_type), - AST::AttrVec (), restrictions); - if (right == nullptr) - return nullptr; + auto right = parse_expr (get_lbp_for_arithmetic_or_logical_expr (expr_type), + AST::AttrVec (), restrictions); + if (!right) + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); // TODO: check types. actually, do so during semantic analysis location_t locus = left->get_locus (); - return std::unique_ptr ( - new AST::ArithmeticOrLogicalExpr (std::move (left), std::move (right), - expr_type, locus)); + return std::make_unique ( + std::move (left), std::move (right.value ()), expr_type, locus); } // Parses a binary addition expression (with Pratt parsing). template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_binary_plus_expr ( const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr left, AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { // parse RHS (as tok has already been consumed in parse_expression) - std::unique_ptr right - = parse_expr (LBP_PLUS, AST::AttrVec (), restrictions); - if (right == nullptr) - return nullptr; + auto right = parse_expr (LBP_PLUS, AST::AttrVec (), restrictions); + if (!right) + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); // TODO: check types. actually, do so during semantic analysis location_t locus = left->get_locus (); - return std::unique_ptr ( - new AST::ArithmeticOrLogicalExpr (std::move (left), std::move (right), - ArithmeticOrLogicalOperator::ADD, locus)); + return std::make_unique ( + std::move (left), std::move (right.value ()), + ArithmeticOrLogicalOperator::ADD, locus); } // Parses a binary subtraction expression (with Pratt parsing). template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_binary_minus_expr ( const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr left, AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { // parse RHS (as tok has already been consumed in parse_expression) - std::unique_ptr right - = parse_expr (LBP_MINUS, AST::AttrVec (), restrictions); - if (right == nullptr) - return nullptr; + auto right = parse_expr (LBP_MINUS, AST::AttrVec (), restrictions); + if (!right) + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); // TODO: check types. actually, do so during semantic analysis location_t locus = left->get_locus (); - return std::unique_ptr ( - new AST::ArithmeticOrLogicalExpr (std::move (left), std::move (right), - ArithmeticOrLogicalOperator::SUBTRACT, - locus)); + return std::make_unique ( + std::move (left), std::move (right.value ()), + ArithmeticOrLogicalOperator::SUBTRACT, locus); } // Parses a binary multiplication expression (with Pratt parsing). template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_binary_mult_expr ( const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr left, AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { // parse RHS (as tok has already been consumed in parse_expression) - std::unique_ptr right - = parse_expr (LBP_MUL, AST::AttrVec (), restrictions); - if (right == nullptr) - return nullptr; + auto right = parse_expr (LBP_MUL, AST::AttrVec (), restrictions); + if (!right) + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); // TODO: check types. actually, do so during semantic analysis location_t locus = left->get_locus (); - return std::unique_ptr ( - new AST::ArithmeticOrLogicalExpr (std::move (left), std::move (right), - ArithmeticOrLogicalOperator::MULTIPLY, - locus)); + return std::make_unique ( + std::move (left), std::move (right.value ()), + ArithmeticOrLogicalOperator::MULTIPLY, locus); } // Parses a binary division expression (with Pratt parsing). template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_binary_div_expr ( const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr left, AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { // parse RHS (as tok has already been consumed in parse_expression) - std::unique_ptr right - = parse_expr (LBP_DIV, AST::AttrVec (), restrictions); - if (right == nullptr) - return nullptr; + auto right = parse_expr (LBP_DIV, AST::AttrVec (), restrictions); + if (!right) + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); // TODO: check types. actually, do so during semantic analysis location_t locus = left->get_locus (); - return std::unique_ptr ( - new AST::ArithmeticOrLogicalExpr (std::move (left), std::move (right), - ArithmeticOrLogicalOperator::DIVIDE, - locus)); + return std::make_unique ( + std::move (left), std::move (right.value ()), + ArithmeticOrLogicalOperator::DIVIDE, locus); } // Parses a binary modulo expression (with Pratt parsing). template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_binary_mod_expr ( const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr left, AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { // parse RHS (as tok has already been consumed in parse_expression) - std::unique_ptr right - = parse_expr (LBP_MOD, AST::AttrVec (), restrictions); - if (right == nullptr) - return nullptr; + auto right = parse_expr (LBP_MOD, AST::AttrVec (), restrictions); + if (!right) + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); // TODO: check types. actually, do so during semantic analysis location_t locus = left->get_locus (); - return std::unique_ptr ( - new AST::ArithmeticOrLogicalExpr (std::move (left), std::move (right), - ArithmeticOrLogicalOperator::MODULUS, - locus)); + return std::make_unique ( + std::move (left), std::move (right.value ()), + ArithmeticOrLogicalOperator::MODULUS, locus); } /* Parses a binary bitwise (or eager logical) and expression (with Pratt * parsing). */ template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_bitwise_and_expr ( const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr left, AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { // parse RHS (as tok has already been consumed in parse_expression) - std::unique_ptr right - = parse_expr (LBP_AMP, AST::AttrVec (), restrictions); - if (right == nullptr) - return nullptr; + auto right = parse_expr (LBP_AMP, AST::AttrVec (), restrictions); + if (!right) + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); // TODO: check types. actually, do so during semantic analysis location_t locus = left->get_locus (); - return std::unique_ptr ( - new AST::ArithmeticOrLogicalExpr (std::move (left), std::move (right), - ArithmeticOrLogicalOperator::BITWISE_AND, - locus)); + return std::make_unique ( + std::move (left), std::move (right.value ()), + ArithmeticOrLogicalOperator::BITWISE_AND, locus); } /* Parses a binary bitwise (or eager logical) or expression (with Pratt * parsing). */ template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_bitwise_or_expr ( const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr left, AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { // parse RHS (as tok has already been consumed in parse_expression) - std::unique_ptr right - = parse_expr (LBP_PIPE, AST::AttrVec (), restrictions); - if (right == nullptr) - return nullptr; + auto right = parse_expr (LBP_PIPE, AST::AttrVec (), restrictions); + if (!right) + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); // TODO: check types. actually, do so during semantic analysis location_t locus = left->get_locus (); - return std::unique_ptr ( - new AST::ArithmeticOrLogicalExpr (std::move (left), std::move (right), - ArithmeticOrLogicalOperator::BITWISE_OR, - locus)); + return std::make_unique ( + std::move (left), std::move (right.value ()), + ArithmeticOrLogicalOperator::BITWISE_OR, locus); } /* Parses a binary bitwise (or eager logical) xor expression (with Pratt * parsing). */ template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_bitwise_xor_expr ( const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr left, AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { // parse RHS (as tok has already been consumed in parse_expression) - std::unique_ptr right - = parse_expr (LBP_CARET, AST::AttrVec (), restrictions); - if (right == nullptr) - return nullptr; + auto right = parse_expr (LBP_CARET, AST::AttrVec (), restrictions); + if (!right) + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); // TODO: check types. actually, do so during semantic analysis location_t locus = left->get_locus (); - return std::unique_ptr ( - new AST::ArithmeticOrLogicalExpr (std::move (left), std::move (right), - ArithmeticOrLogicalOperator::BITWISE_XOR, - locus)); + return std::make_unique ( + std::move (left), std::move (right.value ()), + ArithmeticOrLogicalOperator::BITWISE_XOR, locus); } // Parses a binary left shift expression (with Pratt parsing). template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_left_shift_expr ( const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr left, AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { // parse RHS (as tok has already been consumed in parse_expression) - std::unique_ptr right - = parse_expr (LBP_L_SHIFT, AST::AttrVec (), restrictions); - if (right == nullptr) - return nullptr; + auto right = parse_expr (LBP_L_SHIFT, AST::AttrVec (), restrictions); + if (!right) + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); // TODO: check types. actually, do so during semantic analysis location_t locus = left->get_locus (); - return std::unique_ptr ( - new AST::ArithmeticOrLogicalExpr (std::move (left), std::move (right), - ArithmeticOrLogicalOperator::LEFT_SHIFT, - locus)); + return std::make_unique ( + std::move (left), std::move (right.value ()), + ArithmeticOrLogicalOperator::LEFT_SHIFT, locus); } // Parses a binary right shift expression (with Pratt parsing). template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_right_shift_expr ( const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr left, AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { // parse RHS (as tok has already been consumed in parse_expression) - std::unique_ptr right - = parse_expr (LBP_R_SHIFT, AST::AttrVec (), restrictions); - if (right == nullptr) - return nullptr; + auto right = parse_expr (LBP_R_SHIFT, AST::AttrVec (), restrictions); + if (!right) + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); // TODO: check types. actually, do so during semantic analysis location_t locus = left->get_locus (); - return std::unique_ptr ( - new AST::ArithmeticOrLogicalExpr (std::move (left), std::move (right), - ArithmeticOrLogicalOperator::RIGHT_SHIFT, - locus)); + return std::make_unique ( + std::move (left), std::move (right.value ()), + ArithmeticOrLogicalOperator::RIGHT_SHIFT, locus); } /* Returns the left binding power for the given ComparisonExpr type. @@ -2950,235 +3066,227 @@ get_lbp_for_comparison_expr (AST::ComparisonExpr::ExprType expr_type) * specify one and have the other looked up - e.g. specify ExprType and * binding power is looked up? */ template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_comparison_expr ( const_TokenPtr, std::unique_ptr left, AST::AttrVec, AST::ComparisonExpr::ExprType expr_type, ParseRestrictions restrictions) { // parse RHS (as tok has already been consumed in parse_expression) - std::unique_ptr right - = parse_expr (get_lbp_for_comparison_expr (expr_type), AST::AttrVec (), - restrictions); - if (right == nullptr) - return nullptr; + auto right = parse_expr (get_lbp_for_comparison_expr (expr_type), + AST::AttrVec (), restrictions); + if (!right) + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); // TODO: check types. actually, do so during semantic analysis location_t locus = left->get_locus (); - return std::unique_ptr ( - new AST::ComparisonExpr (std::move (left), std::move (right), expr_type, - locus)); + return std::make_unique (std::move (left), + std::move (right.value ()), + expr_type, locus); } // Parses a binary equal to expression (with Pratt parsing). template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_binary_equal_expr ( const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr left, AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { // parse RHS (as tok has already been consumed in parse_expression) - std::unique_ptr right - = parse_expr (LBP_EQUAL, AST::AttrVec (), restrictions); - if (right == nullptr) - return nullptr; + auto right = parse_expr (LBP_EQUAL, AST::AttrVec (), restrictions); + if (!right) + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); // TODO: check types. actually, do so during semantic analysis location_t locus = left->get_locus (); - return std::unique_ptr ( - new AST::ComparisonExpr (std::move (left), std::move (right), - ComparisonOperator::EQUAL, locus)); + return std::make_unique (std::move (left), + std::move (right.value ()), + ComparisonOperator::EQUAL, + locus); } // Parses a binary not equal to expression (with Pratt parsing). template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_binary_not_equal_expr ( const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr left, AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { // parse RHS (as tok has already been consumed in parse_expression) - std::unique_ptr right - = parse_expr (LBP_NOT_EQUAL, AST::AttrVec (), restrictions); - if (right == nullptr) - return nullptr; + auto right = parse_expr (LBP_NOT_EQUAL, AST::AttrVec (), restrictions); + if (!right) + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); // TODO: check types. actually, do so during semantic analysis location_t locus = left->get_locus (); - return std::unique_ptr ( - new AST::ComparisonExpr (std::move (left), std::move (right), - ComparisonOperator::NOT_EQUAL, locus)); + return std::make_unique (std::move (left), + std::move (right.value ()), + ComparisonOperator::NOT_EQUAL, + locus); } // Parses a binary greater than expression (with Pratt parsing). template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_binary_greater_than_expr ( const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr left, AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { // parse RHS (as tok has already been consumed in parse_expression) - std::unique_ptr right - = parse_expr (LBP_GREATER_THAN, AST::AttrVec (), restrictions); - if (right == nullptr) - return nullptr; + auto right = parse_expr (LBP_GREATER_THAN, AST::AttrVec (), restrictions); + if (!right) + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); // TODO: check types. actually, do so during semantic analysis location_t locus = left->get_locus (); - return std::unique_ptr ( - new AST::ComparisonExpr (std::move (left), std::move (right), - ComparisonOperator::GREATER_THAN, locus)); + return std::make_unique ( + std::move (left), std::move (right.value ()), + ComparisonOperator::GREATER_THAN, locus); } // Parses a binary less than expression (with Pratt parsing). template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_binary_less_than_expr ( const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr left, AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { // parse RHS (as tok has already been consumed in parse_expression) - std::unique_ptr right - = parse_expr (LBP_SMALLER_THAN, AST::AttrVec (), restrictions); - if (right == nullptr) - return nullptr; + auto right = parse_expr (LBP_SMALLER_THAN, AST::AttrVec (), restrictions); + if (!right) + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); // TODO: check types. actually, do so during semantic analysis location_t locus = left->get_locus (); - return std::unique_ptr ( - new AST::ComparisonExpr (std::move (left), std::move (right), - ComparisonOperator::LESS_THAN, locus)); + return std::make_unique (std::move (left), + std::move (right.value ()), + ComparisonOperator::LESS_THAN, + locus); } // Parses a binary greater than or equal to expression (with Pratt parsing). template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_binary_greater_equal_expr ( const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr left, AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { // parse RHS (as tok has already been consumed in parse_expression) - std::unique_ptr right - = parse_expr (LBP_GREATER_EQUAL, AST::AttrVec (), restrictions); - if (right == nullptr) - return nullptr; + auto right = parse_expr (LBP_GREATER_EQUAL, AST::AttrVec (), restrictions); + if (!right) + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); // TODO: check types. actually, do so during semantic analysis location_t locus = left->get_locus (); - return std::unique_ptr ( - new AST::ComparisonExpr (std::move (left), std::move (right), - ComparisonOperator::GREATER_OR_EQUAL, locus)); + return std::make_unique ( + std::move (left), std::move (right.value ()), + ComparisonOperator::GREATER_OR_EQUAL, locus); } // Parses a binary less than or equal to expression (with Pratt parsing). template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_binary_less_equal_expr ( const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr left, AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { // parse RHS (as tok has already been consumed in parse_expression) - std::unique_ptr right - = parse_expr (LBP_SMALLER_EQUAL, AST::AttrVec (), restrictions); - if (right == nullptr) - return nullptr; + auto right = parse_expr (LBP_SMALLER_EQUAL, AST::AttrVec (), restrictions); + if (!right) + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); // TODO: check types. actually, do so during semantic analysis location_t locus = left->get_locus (); - return std::unique_ptr ( - new AST::ComparisonExpr (std::move (left), std::move (right), - ComparisonOperator::LESS_OR_EQUAL, locus)); + return std::make_unique ( + std::move (left), std::move (right.value ()), + ComparisonOperator::LESS_OR_EQUAL, locus); } // Parses a binary lazy boolean or expression (with Pratt parsing). template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_lazy_or_expr ( const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr left, AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { // parse RHS (as tok has already been consumed in parse_expression) - std::unique_ptr right - = parse_expr (LBP_LOGICAL_OR, AST::AttrVec (), restrictions); - if (right == nullptr) - return nullptr; + auto right = parse_expr (LBP_LOGICAL_OR, AST::AttrVec (), restrictions); + if (!right) + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); // TODO: check types. actually, do so during semantic analysis location_t locus = left->get_locus (); - return std::unique_ptr ( - new AST::LazyBooleanExpr (std::move (left), std::move (right), - LazyBooleanOperator::LOGICAL_OR, locus)); + return std::make_unique ( + std::move (left), std::move (right.value ()), + LazyBooleanOperator::LOGICAL_OR, locus); } // Parses a binary lazy boolean and expression (with Pratt parsing). template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_lazy_and_expr ( const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr left, AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { // parse RHS (as tok has already been consumed in parse_expression) - std::unique_ptr right - = parse_expr (LBP_LOGICAL_AND, AST::AttrVec (), restrictions); - if (right == nullptr) - return nullptr; + auto right = parse_expr (LBP_LOGICAL_AND, AST::AttrVec (), restrictions); + if (!right) + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); // TODO: check types. actually, do so during semantic analysis location_t locus = left->get_locus (); - return std::unique_ptr ( - new AST::LazyBooleanExpr (std::move (left), std::move (right), - LazyBooleanOperator::LOGICAL_AND, locus)); + return std::make_unique ( + std::move (left), std::move (right.value ()), + LazyBooleanOperator::LOGICAL_AND, locus); } // Parses a pseudo-binary infix type cast expression (with Pratt parsing). template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_type_cast_expr ( const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr expr_to_cast, AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions ATTRIBUTE_UNUSED) { // parse RHS (as tok has already been consumed in parse_expression) - std::unique_ptr type = parse_type_no_bounds (); - if (type == nullptr) - return nullptr; + auto type = parse_type_no_bounds (); + if (!type) + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); // FIXME: how do I get precedence put in here? // TODO: check types. actually, do so during semantic analysis location_t locus = expr_to_cast->get_locus (); - return std::unique_ptr ( - new AST::TypeCastExpr (std::move (expr_to_cast), std::move (type), locus)); + return std::make_unique (std::move (expr_to_cast), + std::move (type), locus); } // Parses a binary assignment expression (with Pratt parsing). template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_assig_expr ( const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr left, AST::AttrVec outer_attrs, ParseRestrictions restrictions) { // parse RHS (as tok has already been consumed in parse_expression) - std::unique_ptr right - = parse_expr (LBP_ASSIG - 1, AST::AttrVec (), restrictions); - if (right == nullptr) - return nullptr; + auto right = parse_expr (LBP_ASSIG - 1, AST::AttrVec (), restrictions); + if (!right) + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); // FIXME: ensure right-associativity for this - 'LBP - 1' may do this? - // TODO: check types. actually, do so during semantic analysis location_t locus = left->get_locus (); - return std::unique_ptr ( - new AST::AssignmentExpr (std::move (left), std::move (right), - std::move (outer_attrs), locus)); + return std::make_unique (std::move (left), + std::move (right.value ()), + std::move (outer_attrs), locus); } /* Returns the left binding power for the given CompoundAssignmentExpr type. @@ -3219,260 +3327,241 @@ get_lbp_for_compound_assignment_expr ( // Parses a compound assignment expression (with Pratt parsing). template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_compound_assignment_expr ( const_TokenPtr, std::unique_ptr left, AST::AttrVec, AST::CompoundAssignmentExpr::ExprType expr_type, ParseRestrictions restrictions) { // parse RHS (as tok has already been consumed in parse_expression) - std::unique_ptr right - = parse_expr (get_lbp_for_compound_assignment_expr (expr_type) - 1, - AST::AttrVec (), restrictions); - if (right == nullptr) - return nullptr; + auto right = parse_expr (get_lbp_for_compound_assignment_expr (expr_type) - 1, + AST::AttrVec (), restrictions); + if (!right) + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); // FIXME: ensure right-associativity for this - 'LBP - 1' may do this? // TODO: check types. actually, do so during semantic analysis location_t locus = left->get_locus (); - return std::unique_ptr ( - new AST::CompoundAssignmentExpr (std::move (left), std::move (right), - expr_type, locus)); + return std::make_unique ( + std::move (left), std::move (right.value ()), expr_type, locus); } // Parses a binary add-assignment expression (with Pratt parsing). template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_plus_assig_expr ( const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr left, AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { // parse RHS (as tok has already been consumed in parse_expression) - std::unique_ptr right - = parse_expr (LBP_PLUS_ASSIG - 1, AST::AttrVec (), restrictions); - if (right == nullptr) - return nullptr; + auto right = parse_expr (LBP_PLUS_ASSIG - 1, AST::AttrVec (), restrictions); + if (!right) + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); // FIXME: ensure right-associativity for this - 'LBP - 1' may do this? // TODO: check types. actually, do so during semantic analysis location_t locus = left->get_locus (); - return std::unique_ptr ( - new AST::CompoundAssignmentExpr (std::move (left), std::move (right), - CompoundAssignmentOperator::ADD, locus)); + return std::make_unique ( + std::move (left), std::move (right.value ()), + CompoundAssignmentOperator::ADD, locus); } // Parses a binary minus-assignment expression (with Pratt parsing). template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_minus_assig_expr ( const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr left, AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { // parse RHS (as tok has already been consumed in parse_expression) - std::unique_ptr right - = parse_expr (LBP_MINUS_ASSIG - 1, AST::AttrVec (), restrictions); - if (right == nullptr) - return nullptr; + auto right = parse_expr (LBP_MINUS_ASSIG - 1, AST::AttrVec (), restrictions); + if (!right) + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); // FIXME: ensure right-associativity for this - 'LBP - 1' may do this? // TODO: check types. actually, do so during semantic analysis location_t locus = left->get_locus (); - return std::unique_ptr ( - new AST::CompoundAssignmentExpr (std::move (left), std::move (right), - CompoundAssignmentOperator::SUBTRACT, - locus)); + return std::make_unique ( + std::move (left), std::move (right.value ()), + CompoundAssignmentOperator::SUBTRACT, locus); } // Parses a binary multiplication-assignment expression (with Pratt parsing). template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_mult_assig_expr ( const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr left, AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { // parse RHS (as tok has already been consumed in parse_expression) - std::unique_ptr right - = parse_expr (LBP_MULT_ASSIG - 1, AST::AttrVec (), restrictions); - if (right == nullptr) - return nullptr; + auto right = parse_expr (LBP_MULT_ASSIG - 1, AST::AttrVec (), restrictions); + if (!right) + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); // FIXME: ensure right-associativity for this - 'LBP - 1' may do this? // TODO: check types. actually, do so during semantic analysis location_t locus = left->get_locus (); - return std::unique_ptr ( - new AST::CompoundAssignmentExpr (std::move (left), std::move (right), - CompoundAssignmentOperator::MULTIPLY, - locus)); + return std::make_unique ( + std::move (left), std::move (right.value ()), + CompoundAssignmentOperator::MULTIPLY, locus); } // Parses a binary division-assignment expression (with Pratt parsing). template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_div_assig_expr ( const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr left, AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { // parse RHS (as tok has already been consumed in parse_expression) - std::unique_ptr right - = parse_expr (LBP_DIV_ASSIG - 1, AST::AttrVec (), restrictions); - if (right == nullptr) - return nullptr; + auto right = parse_expr (LBP_DIV_ASSIG - 1, AST::AttrVec (), restrictions); + if (!right) + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); // FIXME: ensure right-associativity for this - 'LBP - 1' may do this? // TODO: check types. actually, do so during semantic analysis location_t locus = left->get_locus (); - return std::unique_ptr ( - new AST::CompoundAssignmentExpr (std::move (left), std::move (right), - CompoundAssignmentOperator::DIVIDE, - locus)); + return std::make_unique ( + std::move (left), std::move (right.value ()), + CompoundAssignmentOperator::DIVIDE, locus); } // Parses a binary modulo-assignment expression (with Pratt parsing). template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_mod_assig_expr ( const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr left, AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { // parse RHS (as tok has already been consumed in parse_expression) - std::unique_ptr right - = parse_expr (LBP_MOD_ASSIG - 1, AST::AttrVec (), restrictions); - if (right == nullptr) - return nullptr; + auto right = parse_expr (LBP_MOD_ASSIG - 1, AST::AttrVec (), restrictions); + if (!right) + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); // FIXME: ensure right-associativity for this - 'LBP - 1' may do this? // TODO: check types. actually, do so during semantic analysis location_t locus = left->get_locus (); - return std::unique_ptr ( - new AST::CompoundAssignmentExpr (std::move (left), std::move (right), - CompoundAssignmentOperator::MODULUS, - locus)); + return std::make_unique ( + std::move (left), std::move (right.value ()), + CompoundAssignmentOperator::MODULUS, locus); } // Parses a binary and-assignment expression (with Pratt parsing). template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_and_assig_expr ( const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr left, AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { // parse RHS (as tok has already been consumed in parse_expression) - std::unique_ptr right - = parse_expr (LBP_AMP_ASSIG - 1, AST::AttrVec (), restrictions); - if (right == nullptr) - return nullptr; + auto right = parse_expr (LBP_AMP_ASSIG - 1, AST::AttrVec (), restrictions); + if (!right) + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); // FIXME: ensure right-associativity for this - 'LBP - 1' may do this? // TODO: check types. actually, do so during semantic analysis location_t locus = left->get_locus (); - return std::unique_ptr ( - new AST::CompoundAssignmentExpr (std::move (left), std::move (right), - CompoundAssignmentOperator::BITWISE_AND, - locus)); + return std::make_unique ( + std::move (left), std::move (right.value ()), + CompoundAssignmentOperator::BITWISE_AND, locus); } // Parses a binary or-assignment expression (with Pratt parsing). template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_or_assig_expr ( const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr left, AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { // parse RHS (as tok has already been consumed in parse_expression) - std::unique_ptr right - = parse_expr (LBP_PIPE_ASSIG - 1, AST::AttrVec (), restrictions); - if (right == nullptr) - return nullptr; + auto right = parse_expr (LBP_PIPE_ASSIG - 1, AST::AttrVec (), restrictions); + if (!right) + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); // FIXME: ensure right-associativity for this - 'LBP - 1' may do this? // TODO: check types. actually, do so during semantic analysis location_t locus = left->get_locus (); - return std::unique_ptr ( - new AST::CompoundAssignmentExpr (std::move (left), std::move (right), - CompoundAssignmentOperator::BITWISE_OR, - locus)); + return std::make_unique ( + std::move (left), std::move (right.value ()), + CompoundAssignmentOperator::BITWISE_OR, locus); } // Parses a binary xor-assignment expression (with Pratt parsing). template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_xor_assig_expr ( const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr left, AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { // parse RHS (as tok has already been consumed in parse_expression) - std::unique_ptr right - = parse_expr (LBP_CARET_ASSIG - 1, AST::AttrVec (), restrictions); - if (right == nullptr) - return nullptr; + auto right = parse_expr (LBP_CARET_ASSIG - 1, AST::AttrVec (), restrictions); + if (!right) + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); // FIXME: ensure right-associativity for this - 'LBP - 1' may do this? // TODO: check types. actually, do so during semantic analysis location_t locus = left->get_locus (); - return std::unique_ptr ( - new AST::CompoundAssignmentExpr (std::move (left), std::move (right), - CompoundAssignmentOperator::BITWISE_XOR, - locus)); + return std::make_unique ( + std::move (left), std::move (right.value ()), + CompoundAssignmentOperator::BITWISE_XOR, locus); } // Parses a binary left shift-assignment expression (with Pratt parsing). template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_left_shift_assig_expr ( const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr left, AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { // parse RHS (as tok has already been consumed in parse_expression) - std::unique_ptr right + auto right = parse_expr (LBP_L_SHIFT_ASSIG - 1, AST::AttrVec (), restrictions); - if (right == nullptr) - return nullptr; + if (!right) + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); // FIXME: ensure right-associativity for this - 'LBP - 1' may do this? // TODO: check types. actually, do so during semantic analysis location_t locus = left->get_locus (); - return std::unique_ptr ( - new AST::CompoundAssignmentExpr (std::move (left), std::move (right), - CompoundAssignmentOperator::LEFT_SHIFT, - locus)); + return std::make_unique ( + std::move (left), std::move (right.value ()), + CompoundAssignmentOperator::LEFT_SHIFT, locus); } // Parses a binary right shift-assignment expression (with Pratt parsing). template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_right_shift_assig_expr ( const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr left, AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { // parse RHS (as tok has already been consumed in parse_expression) - std::unique_ptr right + auto right = parse_expr (LBP_R_SHIFT_ASSIG - 1, AST::AttrVec (), restrictions); - if (right == nullptr) - return nullptr; + if (!right) + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); // FIXME: ensure right-associativity for this - 'LBP - 1' may do this? // TODO: check types. actually, do so during semantic analysis location_t locus = left->get_locus (); - return std::unique_ptr ( - new AST::CompoundAssignmentExpr (std::move (left), std::move (right), - CompoundAssignmentOperator::RIGHT_SHIFT, - locus)); + return std::make_unique ( + std::move (left), std::move (right.value ()), + CompoundAssignmentOperator::RIGHT_SHIFT, locus); } // Parses a postfix unary await expression (with Pratt parsing). template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_await_expr ( const_TokenPtr tok, std::unique_ptr expr_to_await, AST::AttrVec outer_attrs) @@ -3487,7 +3576,7 @@ Parser::parse_await_expr ( add_error (std::move (error)); // skip somewhere? - return nullptr; + return tl::unexpected (Parse::Error::Expr::MALFORMED); } // TODO: check inside async block in semantic analysis @@ -3501,7 +3590,7 @@ Parser::parse_await_expr ( /* Parses an exclusive range ('..') in left denotation position (i.e. * RangeFromExpr or RangeFromToExpr). */ template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_led_range_exclusive_expr ( const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr left, AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) @@ -3511,21 +3600,20 @@ Parser::parse_led_range_exclusive_expr ( // Can be nullptr, in which case it is a RangeFromExpr, otherwise a // RangeFromToExpr. restrictions.expr_can_be_null = true; - std::unique_ptr right - = parse_expr (LBP_DOT_DOT, AST::AttrVec (), restrictions); + auto right = parse_expr (LBP_DOT_DOT, AST::AttrVec (), restrictions); location_t locus = left->get_locus (); - if (right == nullptr) + if (!right) { // range from expr - return std::unique_ptr ( - new AST::RangeFromExpr (std::move (left), locus)); + return std::make_unique (std::move (left), locus); } else { - return std::unique_ptr ( - new AST::RangeFromToExpr (std::move (left), std::move (right), locus)); + return std::make_unique (std::move (left), + std::move (right.value ()), + locus); } // FIXME: make non-associative } @@ -3533,7 +3621,7 @@ Parser::parse_led_range_exclusive_expr ( /* Parses an exclusive range ('..') in null denotation position (i.e. * RangeToExpr or RangeFullExpr). */ template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_nud_range_exclusive_expr ( const_TokenPtr tok, AST::AttrVec outer_attrs ATTRIBUTE_UNUSED) { @@ -3542,67 +3630,65 @@ Parser::parse_nud_range_exclusive_expr ( // FIXME: this probably parses expressions accidently or whatever // try parsing RHS (as tok has already been consumed in parse_expression) - std::unique_ptr right - = parse_expr (LBP_DOT_DOT, AST::AttrVec (), restrictions); + auto right = parse_expr (LBP_DOT_DOT, AST::AttrVec (), restrictions); location_t locus = tok->get_locus (); - if (right == nullptr) + if (!right) { // range from expr - return std::unique_ptr ( - new AST::RangeFullExpr (locus)); + return std::make_unique (locus); } else { - return std::unique_ptr ( - new AST::RangeToExpr (std::move (right), locus)); + return std::make_unique (std::move (right.value ()), + locus); } // FIXME: make non-associative } // Parses a full binary range inclusive expression. template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_range_inclusive_expr ( const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr left, AST::AttrVec outer_attrs ATTRIBUTE_UNUSED, ParseRestrictions restrictions) { // parse RHS (as tok has already been consumed in parse_expression) - std::unique_ptr right - = parse_expr (LBP_DOT_DOT_EQ, AST::AttrVec (), restrictions); - if (right == nullptr) - return nullptr; + auto right = parse_expr (LBP_DOT_DOT_EQ, AST::AttrVec (), restrictions); + if (!right) + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); // FIXME: make non-associative // TODO: check types. actually, do so during semantic analysis location_t locus = left->get_locus (); - return std::unique_ptr ( - new AST::RangeFromToInclExpr (std::move (left), std::move (right), locus)); + return std::make_unique (std::move (left), + std::move (right.value ()), + locus); } // Parses an inclusive range-to prefix unary expression. template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_range_to_inclusive_expr ( const_TokenPtr tok, AST::AttrVec outer_attrs ATTRIBUTE_UNUSED) { // parse RHS (as tok has already been consumed in parse_expression) - std::unique_ptr right = parse_expr (LBP_DOT_DOT_EQ); - if (right == nullptr) - return nullptr; + auto right = parse_expr (LBP_DOT_DOT_EQ); + if (!right) + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); // FIXME: make non-associative // TODO: check types. actually, do so during semantic analysis - return std::unique_ptr ( - new AST::RangeToInclExpr (std::move (right), tok->get_locus ())); + return std::make_unique (std::move (right.value ()), + tok->get_locus ()); } // Parses a pseudo-binary infix tuple index expression. template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_tuple_index_expr ( const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr tuple_expr, AST::AttrVec outer_attrs, ParseRestrictions restrictions ATTRIBUTE_UNUSED) @@ -3610,9 +3696,8 @@ Parser::parse_tuple_index_expr ( // parse int literal (as token already skipped) const_TokenPtr index_tok = expect_token (INT_LITERAL); if (index_tok == nullptr) - { - return nullptr; - } + return tl::unexpected (Parse::Error::Expr::MALFORMED); + std::string index = index_tok->get_str (); // convert to integer @@ -3626,14 +3711,14 @@ Parser::parse_tuple_index_expr ( location_t locus = tuple_expr->get_locus (); - return std::unique_ptr ( - new AST::TupleIndexExpr (std::move (tuple_expr), index_int, - std::move (outer_attrs), locus)); + return std::make_unique (std::move (tuple_expr), + index_int, + std::move (outer_attrs), locus); } // Parses a pseudo-binary infix array (or slice) index expression. template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_index_expr ( const_TokenPtr, std::unique_ptr array_expr, AST::AttrVec outer_attrs, ParseRestrictions) @@ -3643,28 +3728,28 @@ Parser::parse_index_expr ( = parse_expr (LBP_ARRAY_REF, AST::AttrVec (), restrictions);*/ // TODO: conceptually, should treat [] as brackets, so just parse all expr - std::unique_ptr index_expr = parse_expr (); - if (index_expr == nullptr) - return nullptr; + auto index_expr = parse_expr (); + if (!index_expr) + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); // skip ']' at end of array if (!skip_token (RIGHT_SQUARE)) { // skip somewhere? - return nullptr; + return tl::unexpected (Parse::Error::Expr::MALFORMED); } // TODO: check types. actually, do so during semantic analysis location_t locus = array_expr->get_locus (); - return std::unique_ptr ( - new AST::ArrayIndexExpr (std::move (array_expr), std::move (index_expr), - std::move (outer_attrs), locus)); + return std::make_unique (std::move (array_expr), + std::move (index_expr.value ()), + std::move (outer_attrs), locus); } // Parses a pseudo-binary infix struct field access expression. template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_field_access_expr ( const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr struct_expr, AST::AttrVec outer_attrs, ParseRestrictions restrictions ATTRIBUTE_UNUSED) @@ -3673,21 +3758,22 @@ Parser::parse_field_access_expr ( * not await, for instance) */ const_TokenPtr ident_tok = expect_token (IDENTIFIER); if (ident_tok == nullptr) - return nullptr; + return tl::unexpected (Parse::Error::Expr::MALFORMED); Identifier ident{ident_tok}; location_t locus = struct_expr->get_locus (); // TODO: check types. actually, do so during semantic analysis - return std::unique_ptr ( - new AST::FieldAccessExpr (std::move (struct_expr), std::move (ident), - std::move (outer_attrs), locus)); + return std::make_unique (std::move (struct_expr), + std::move (ident), + std::move (outer_attrs), + locus); } // Parses a pseudo-binary infix method call expression. template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_method_call_expr ( const_TokenPtr tok, std::unique_ptr receiver_expr, AST::AttrVec outer_attrs, ParseRestrictions) @@ -3700,13 +3786,13 @@ Parser::parse_method_call_expr ( "failed to parse path expr segment of method call expr"); add_error (std::move (error)); - return nullptr; + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); } // skip left parentheses if (!skip_token (LEFT_PAREN)) { - return nullptr; + return tl::unexpected (Parse::Error::Expr::MALFORMED); } // parse method params (if they exist) @@ -3715,16 +3801,16 @@ Parser::parse_method_call_expr ( const_TokenPtr t = lexer.peek_token (); while (t->get_id () != RIGHT_PAREN) { - std::unique_ptr param = parse_expr (); - if (param == nullptr) + auto param = parse_expr (); + if (!param) { Error error (t->get_locus (), "failed to parse method param in method call"); add_error (std::move (error)); - return nullptr; + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); } - params.push_back (std::move (param)); + params.push_back (std::move (param.value ())); if (lexer.peek_token ()->get_id () != COMMA) break; @@ -3736,21 +3822,21 @@ Parser::parse_method_call_expr ( // skip right paren if (!skip_token (RIGHT_PAREN)) { - return nullptr; + return tl::unexpected (Parse::Error::Expr::MALFORMED); } // TODO: check types. actually do so in semantic analysis pass. location_t locus = receiver_expr->get_locus (); - return std::unique_ptr ( - new AST::MethodCallExpr (std::move (receiver_expr), std::move (segment), - std::move (params), std::move (outer_attrs), - locus)); + return std::make_unique (std::move (receiver_expr), + std::move (segment), + std::move (params), + std::move (outer_attrs), locus); } // Parses a pseudo-binary infix function call expression. template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_function_call_expr ( const_TokenPtr, std::unique_ptr function_expr, AST::AttrVec outer_attrs, ParseRestrictions) @@ -3761,16 +3847,16 @@ Parser::parse_function_call_expr ( const_TokenPtr t = lexer.peek_token (); while (t->get_id () != RIGHT_PAREN) { - std::unique_ptr param = parse_expr (); - if (param == nullptr) + auto param = parse_expr (); + if (!param) { Error error (t->get_locus (), "failed to parse function param in function call"); add_error (std::move (error)); - return nullptr; + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); } - params.push_back (std::move (param)); + params.push_back (std::move (param.value ())); if (lexer.peek_token ()->get_id () != COMMA) break; @@ -3783,22 +3869,22 @@ Parser::parse_function_call_expr ( if (!skip_token (RIGHT_PAREN)) { // skip somewhere? - return nullptr; + return tl::unexpected (Parse::Error::Expr::MALFORMED); } // TODO: check types. actually, do so during semantic analysis location_t locus = function_expr->get_locus (); - return std::unique_ptr ( - new AST::CallExpr (std::move (function_expr), std::move (params), - std::move (outer_attrs), locus)); + return std::make_unique (std::move (function_expr), + std::move (params), + std::move (outer_attrs), locus); } /* Parses a struct expr struct with a path in expression already parsed (but * not * '{' token). */ template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_struct_expr_struct_partial ( AST::PathInExpression path, AST::AttrVec outer_attrs) { @@ -3806,7 +3892,7 @@ Parser::parse_struct_expr_struct_partial ( // lookup) again, make statement if final ';' if (!skip_token (LEFT_CURLY)) { - return nullptr; + return tl::unexpected (Parse::Error::Expr::MALFORMED); } // parse inner attributes @@ -3821,9 +3907,10 @@ Parser::parse_struct_expr_struct_partial ( // struct with no body lexer.skip_token (); - return std::unique_ptr ( - new AST::StructExprStruct (std::move (path), std::move (inner_attrs), - std::move (outer_attrs), path_locus)); + return std::make_unique (std::move (path), + std::move (inner_attrs), + std::move (outer_attrs), + path_locus); case DOT_DOT: /* technically this would give a struct base-only struct, but this * algorithm should work too. As such, AST type not happening. */ @@ -3838,21 +3925,21 @@ Parser::parse_struct_expr_struct_partial ( while (t->get_id () != RIGHT_CURLY && t->get_id () != DOT_DOT) { - std::unique_ptr field - = parse_struct_expr_field (); - if (field == nullptr) + auto field = parse_struct_expr_field (); + if (!field + && field.error () != Parse::Error::StructExprField::STRUCT_BASE) { Error error (t->get_locus (), "failed to parse struct (or enum) expr field"); add_error (std::move (error)); - return nullptr; + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); } // DEBUG: rust_debug ("struct/enum expr field validated to not be null"); - fields.push_back (std::move (field)); + fields.push_back (std::move (field.value ())); // DEBUG: rust_debug ("struct/enum expr field pushed back"); @@ -3883,22 +3970,22 @@ Parser::parse_struct_expr_struct_partial ( lexer.skip_token (); // parse required struct base expr - std::unique_ptr base_expr = parse_expr (); - if (base_expr == nullptr) + auto base_expr = parse_expr (); + if (!base_expr) { Error error (lexer.peek_token ()->get_locus (), "failed to parse struct base expression in struct " "expression"); add_error (std::move (error)); - return nullptr; + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); } // DEBUG: rust_debug ("struct/enum expr - parsed and validated base expr"); - struct_base - = AST::StructBase (std::move (base_expr), dot_dot_location); + struct_base = AST::StructBase (std::move (base_expr.value ()), + dot_dot_location); // DEBUG: rust_debug ("assigned struct base to new struct base "); @@ -3906,18 +3993,17 @@ Parser::parse_struct_expr_struct_partial ( if (!skip_token (RIGHT_CURLY)) { - return nullptr; + return tl::unexpected (Parse::Error::Expr::MALFORMED); } // DEBUG: rust_debug ( "struct/enum expr skipped right curly - done and ready to return"); - return std::unique_ptr ( - new AST::StructExprStructFields (std::move (path), std::move (fields), - path_locus, std::move (struct_base), - std::move (inner_attrs), - std::move (outer_attrs))); + return std::make_unique ( + std::move (path), std::move (fields), path_locus, + std::move (struct_base), std::move (inner_attrs), + std::move (outer_attrs)); } default: add_error ( @@ -3926,7 +4012,7 @@ Parser::parse_struct_expr_struct_partial ( "expected %<}%>, identifier, integer literal, or %<..%>", t->get_token_description ())); - return nullptr; + return tl::unexpected (Parse::Error::Expr::MALFORMED); } } @@ -3937,13 +4023,13 @@ Parser::parse_struct_expr_struct_partial ( * A better solution would be to just get this to call that function directly. * */ template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_struct_expr_tuple_partial ( AST::PathInExpression path, AST::AttrVec outer_attrs) { if (!skip_token (LEFT_PAREN)) { - return nullptr; + return tl::unexpected (Parse::Error::Expr::MALFORMED); } AST::AttrVec inner_attrs = parse_inner_attributes (); @@ -3954,16 +4040,16 @@ Parser::parse_struct_expr_tuple_partial ( while (t->get_id () != RIGHT_PAREN) { // parse expression (required) - std::unique_ptr expr = parse_expr (); - if (expr == nullptr) + auto expr = parse_expr (); + if (!expr) { Error error (t->get_locus (), "failed to parse expression in " "struct (or enum) expression tuple"); add_error (std::move (error)); - return nullptr; + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); } - exprs.push_back (std::move (expr)); + exprs.push_back (std::move (expr.value ())); if (lexer.peek_token ()->get_id () != COMMA) break; @@ -3975,22 +4061,21 @@ Parser::parse_struct_expr_tuple_partial ( if (!skip_token (RIGHT_PAREN)) { - return nullptr; + return tl::unexpected (Parse::Error::Expr::MALFORMED); } location_t path_locus = path.get_locus (); - auto pathExpr = std::unique_ptr ( - new AST::PathInExpression (std::move (path))); + auto pathExpr = std::make_unique (std::move (path)); - return std::unique_ptr ( - new AST::CallExpr (std::move (pathExpr), std::move (exprs), - std::move (outer_attrs), path_locus)); + return std::make_unique (std::move (pathExpr), + std::move (exprs), + std::move (outer_attrs), path_locus); } // Parses a closure expression with pratt parsing (from null denotation). template -std::unique_ptr +tl::expected, Parse::Error::Expr> Parser::parse_closure_expr_pratt (const_TokenPtr tok, AST::AttrVec outer_attrs) { @@ -4028,7 +4113,7 @@ Parser::parse_closure_expr_pratt (const_TokenPtr tok, Error error (t->get_locus (), "could not parse closure param"); add_error (std::move (error)); - return nullptr; + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); } params.push_back (std::move (param)); @@ -4050,7 +4135,7 @@ Parser::parse_closure_expr_pratt (const_TokenPtr tok, if (!skip_token (PIPE)) { - return nullptr; + return tl::unexpected (Parse::Error::Expr::MALFORMED); } break; } @@ -4061,7 +4146,7 @@ Parser::parse_closure_expr_pratt (const_TokenPtr tok, tok->get_token_description ())); // skip somewhere? - return nullptr; + return tl::unexpected (Parse::Error::Expr::MALFORMED); } // again branch based on next token @@ -4074,15 +4159,15 @@ Parser::parse_closure_expr_pratt (const_TokenPtr tok, lexer.skip_token (); // parse actual type, which is required - std::unique_ptr type = parse_type_no_bounds (); - if (type == nullptr) + auto type = parse_type_no_bounds (); + if (!type) { // error Error error (tok->get_locus (), "failed to parse type for closure"); add_error (std::move (error)); // skip somewhere? - return nullptr; + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); } // parse block expr, which is required @@ -4095,34 +4180,33 @@ Parser::parse_closure_expr_pratt (const_TokenPtr tok, add_error (std::move (error)); // skip somewhere? - return nullptr; + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); } - return std::unique_ptr ( - new AST::ClosureExprInnerTyped (std::move (type), - std::move (block.value ()), - std::move (params), locus, has_move, - std::move (outer_attrs))); + return std::make_unique ( + std::move (type), std::move (block.value ()), std::move (params), locus, + has_move, std::move (outer_attrs)); } else { // must be expr-only closure // parse expr, which is required - std::unique_ptr expr = parse_expr (); - if (expr == nullptr) + auto expr = parse_expr (); + if (!expr) { Error error (tok->get_locus (), "failed to parse expression in closure"); add_error (std::move (error)); // skip somewhere? - return nullptr; + return tl::unexpected (Parse::Error::Expr::CHILD_ERROR); } - return std::unique_ptr ( - new AST::ClosureExprInner (std::move (expr), std::move (params), locus, - has_move, std::move (outer_attrs))); + return std::make_unique (std::move (expr.value ()), + std::move (params), locus, + has_move, + std::move (outer_attrs)); } } diff --git a/gcc/rust/parse/rust-parse-impl.hxx b/gcc/rust/parse/rust-parse-impl.hxx index 1be2a5c2897..9f4440ee329 100644 --- a/gcc/rust/parse/rust-parse-impl.hxx +++ b/gcc/rust/parse/rust-parse-impl.hxx @@ -3497,11 +3497,13 @@ Parser::parse_enum_item () // discriminant enum item lexer.skip_token (); - std::unique_ptr discriminant_expr = parse_expr (); + auto discriminant_expr = parse_expr (); + if (!discriminant_expr) + return nullptr; return std::unique_ptr ( new AST::EnumItemDiscriminant (std::move (item_name), std::move (vis), - std::move (discriminant_expr), + std::move (discriminant_expr.value ()), std::move (outer_attrs), item_name_tok->get_locus ())); } @@ -3627,7 +3629,9 @@ Parser::parse_const_item (AST::Visibility vis, } // parse constant expression (required) - std::unique_ptr expr = parse_expr (); + auto expr = parse_expr (); + if (!expr) + return nullptr; if (!skip_token (SEMICOLON)) { @@ -3637,7 +3641,8 @@ Parser::parse_const_item (AST::Visibility vis, return std::unique_ptr ( new AST::ConstantItem (std::move (ident), std::move (vis), std::move (type), - std::move (expr), std::move (outer_attrs), locus)); + std::move (expr.value ()), std::move (outer_attrs), + locus)); } // Parses a "static item" (static storage item, with 'static lifetime). @@ -3679,7 +3684,9 @@ Parser::parse_static_item (AST::Visibility vis, } // parse static item expression (required) - std::unique_ptr expr = parse_expr (); + auto expr = parse_expr (); + if (!expr) + return nullptr; if (!skip_token (SEMICOLON)) { @@ -3689,7 +3696,7 @@ Parser::parse_static_item (AST::Visibility vis, return std::unique_ptr ( new AST::StaticItem (std::move (ident), is_mut, std::move (type), - std::move (expr), std::move (vis), + std::move (expr.value ()), std::move (vis), std::move (outer_attrs), locus)); } @@ -3923,7 +3930,10 @@ Parser::parse_trait_const (AST::AttrVec outer_attrs) lexer.skip_token (); // expression must exist, so parse it - const_body = parse_expr (); + auto expr = parse_expr (); + if (!expr) + return nullptr; + const_body = std::move (expr.value ()); } if (!skip_token (SEMICOLON)) @@ -4880,12 +4890,13 @@ Parser::parse_let_stmt (AST::AttrVec outer_attrs, // must have an expression lexer.skip_token (); - expr = parse_expr (); - if (expr == nullptr) + auto expr_res = parse_expr (); + if (!expr_res) { skip_after_semicolon (); return nullptr; } + expr = std::move (expr_res.value ()); } tl::optional> else_expr = tl::nullopt; @@ -5300,7 +5311,7 @@ Parser::parse_expr_stmt (AST::AttrVec outer_attrs, { location_t locus = lexer.peek_token ()->get_locus (); - std::unique_ptr expr; + tl::expected, Parse::Error::Expr> expr; switch (lexer.peek_token ()->get_id ()) { @@ -5313,7 +5324,8 @@ Parser::parse_expr_stmt (AST::AttrVec outer_attrs, case SCOPE_RESOLUTION: { AST::PathInExpression path = parse_path_in_expression (); - std::unique_ptr null_denotation; + tl::expected, Parse::Error::Expr> + null_denotation; if (lexer.peek_token ()->get_id () == EXCLAM) { @@ -5361,7 +5373,7 @@ Parser::parse_expr_stmt (AST::AttrVec outer_attrs, break; } - if (expr == nullptr) + if (!expr) { // expr is required, error Error error (lexer.peek_token ()->get_locus (), @@ -5380,7 +5392,7 @@ Parser::parse_expr_stmt (AST::AttrVec outer_attrs, { has_semi = true; } - else if (expr->is_expr_without_block ()) + else if (expr.value ()->is_expr_without_block ()) { if (restrictions.allow_close_after_expr_stmt) { @@ -5399,8 +5411,8 @@ Parser::parse_expr_stmt (AST::AttrVec outer_attrs, } } - return std::unique_ptr ( - new AST::ExprStmt (std::move (expr), locus, has_semi)); + return std::make_unique (std::move (expr.value ()), locus, + has_semi); } // Parses a loop label used in loop expressions. @@ -5468,8 +5480,8 @@ Parser::parse_match_arm () { lexer.skip_token (); - guard_expr = parse_expr (); - if (guard_expr == nullptr) + auto guard_expr_res = parse_expr (); + if (!guard_expr_res) { Error error (lexer.peek_token ()->get_locus (), "failed to parse guard expression in match arm"); @@ -5478,6 +5490,7 @@ Parser::parse_match_arm () // skip somewhere? return AST::MatchArm::create_error (); } + guard_expr = std::move (guard_expr_res.value ()); } // DEBUG @@ -6959,7 +6972,7 @@ Parser::parse_tuple_struct_items () * exists). Useful for block expressions where it cannot be determined through * lookahead whether it is a statement or expression to be parsed. */ template -ExprOrStmt +tl::expected Parser::parse_stmt_or_expr () { // quick exit for empty statement @@ -6976,7 +6989,9 @@ Parser::parse_stmt_or_expr () AST::AttrVec outer_attrs = parse_outer_attributes (); ParseRestrictions restrictions; restrictions.expr_can_be_stmt = true; - std::unique_ptr expr; + + // Defered child error checking: we need to check for a semicolon + tl::expected, Parse::Error::Expr> expr; // parsing this will be annoying because of the many different possibilities /* best may be just to copy paste in parse_item switch, and failing that try @@ -7066,7 +7081,7 @@ Parser::parse_stmt_or_expr () t->get_token_description ())); // skip somewhere? - return ExprOrStmt::create_error (); + return tl::unexpected (Parse::Error::Node::MALFORMED); } break; } @@ -7101,7 +7116,8 @@ Parser::parse_stmt_or_expr () case DOLLAR_SIGN: { AST::PathInExpression path = parse_path_in_expression (); - std::unique_ptr null_denotation; + tl::expected, Parse::Error::Expr> + null_denotation; if (lexer.peek_token ()->get_id () == EXCLAM) { @@ -7109,7 +7125,7 @@ Parser::parse_stmt_or_expr () = parse_macro_invocation_partial (std::move (path), std::move (outer_attrs)); if (invoc == nullptr) - return ExprOrStmt::create_error (); + return tl::unexpected (Parse::Error::Node::CHILD_ERROR); if (restrictions.consume_semi && maybe_skip_token (SEMICOLON)) { @@ -7160,27 +7176,31 @@ Parser::parse_stmt_or_expr () if (expr) { - std::unique_ptr stmt ( - new AST::ExprStmt (std::move (expr), t->get_locus (), true)); - return ExprOrStmt (std::move (stmt)); + return ExprOrStmt ( + std::make_unique (std::move (expr.value ()), + t->get_locus (), true)); } else { - return ExprOrStmt::create_error (); + return tl::unexpected (Parse::Error::Node::CHILD_ERROR); } } - if (expr && !expr->is_expr_without_block () - && after_expr->get_id () != RIGHT_CURLY) + if (expr) { // block expression statement. - std::unique_ptr stmt ( - new AST::ExprStmt (std::move (expr), t->get_locus (), false)); - return ExprOrStmt (std::move (stmt)); + if (!expr.value ()->is_expr_without_block () + && after_expr->get_id () != RIGHT_CURLY) + return ExprOrStmt ( + std::make_unique (std::move (expr.value ()), + t->get_locus (), false)); } // return expression - return ExprOrStmt (std::move (expr)); + if (expr) + return ExprOrStmt (std::move (expr.value ())); + else + return tl::unexpected (Parse::Error::Node::CHILD_ERROR); } } // namespace Rust diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h index cf26cc2dacb..7d632391c7a 100644 --- a/gcc/rust/parse/rust-parse.h +++ b/gcc/rust/parse/rust-parse.h @@ -152,16 +152,6 @@ struct ExprOrStmt : expr (std::move (macro)) {} - // Returns whether this object is in an error state. - bool is_error () const - { - return (expr == nullptr && stmt == nullptr) - || (expr != nullptr && stmt != nullptr); - } - - // Returns an error state object. - static ExprOrStmt create_error () { return ExprOrStmt (nullptr, nullptr); } - ~ExprOrStmt () = default; /* no copy constructors/assignment as simple object like this shouldn't @@ -237,7 +227,7 @@ public: */ bool maybe_skip_token (TokenId t); - std::unique_ptr + tl::expected, Parse::Error::Expr> parse_expr (AST::AttrVec outer_attrs = AST::AttrVec (), ParseRestrictions restrictions = ParseRestrictions ()); @@ -478,217 +468,256 @@ private: AST::AttrVec outer_attrs); // Expression-related (Pratt parsed) - std::unique_ptr + tl::expected, Parse::Error::Expr> parse_expr (int right_binding_power, AST::AttrVec outer_attrs = AST::AttrVec (), ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr + tl::expected, Parse::Error::Expr> null_denotation (AST::AttrVec outer_attrs = AST::AttrVec (), ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr + tl::expected, Parse::Error::Expr> null_denotation_path (AST::PathInExpression path, AST::AttrVec outer_attrs, ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr + tl::expected, Parse::Error::Expr> null_denotation_not_path (const_TokenPtr t, AST::AttrVec outer_attrs, ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr - left_denotations (std::unique_ptr null_denotation, + tl::expected, Parse::Error::Expr> + left_denotations (tl::expected, Parse::Error::Expr> + null_denotation, int right_binding_power, AST::AttrVec outer_attrs, ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr + tl::expected, Parse::Error::Expr> left_denotation (const_TokenPtr t, std::unique_ptr left, AST::AttrVec outer_attrs = AST::AttrVec (), ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr + tl::expected, + Parse::Error::Expr> parse_arithmetic_or_logical_expr ( const_TokenPtr tok, std::unique_ptr left, AST::AttrVec outer_attrs, AST::ArithmeticOrLogicalExpr::ExprType expr_type, ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr + tl::expected, + Parse::Error::Expr> parse_binary_plus_expr (const_TokenPtr tok, std::unique_ptr left, AST::AttrVec outer_attrs, ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr + tl::expected, + Parse::Error::Expr> parse_binary_minus_expr (const_TokenPtr tok, std::unique_ptr left, AST::AttrVec outer_attrs, ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr + tl::expected, + Parse::Error::Expr> parse_binary_mult_expr (const_TokenPtr tok, std::unique_ptr left, AST::AttrVec outer_attrs, ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr + tl::expected, + Parse::Error::Expr> parse_binary_div_expr (const_TokenPtr tok, std::unique_ptr left, AST::AttrVec outer_attrs, ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr + tl::expected, + Parse::Error::Expr> parse_binary_mod_expr (const_TokenPtr tok, std::unique_ptr left, AST::AttrVec outer_attrs, ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr + tl::expected, + Parse::Error::Expr> parse_bitwise_and_expr (const_TokenPtr tok, std::unique_ptr left, AST::AttrVec outer_attrs, ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr + tl::expected, + Parse::Error::Expr> parse_bitwise_or_expr (const_TokenPtr tok, std::unique_ptr left, AST::AttrVec outer_attrs, ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr + tl::expected, + Parse::Error::Expr> parse_bitwise_xor_expr (const_TokenPtr tok, std::unique_ptr left, AST::AttrVec outer_attrs, ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr + tl::expected, + Parse::Error::Expr> parse_left_shift_expr (const_TokenPtr tok, std::unique_ptr left, AST::AttrVec outer_attrs, ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr + tl::expected, + Parse::Error::Expr> parse_right_shift_expr (const_TokenPtr tok, std::unique_ptr left, AST::AttrVec outer_attrs, ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr + tl::expected, Parse::Error::Expr> parse_comparison_expr (const_TokenPtr tok, std::unique_ptr left, AST::AttrVec outer_attrs, AST::ComparisonExpr::ExprType expr_type, ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr + tl::expected, Parse::Error::Expr> parse_binary_equal_expr (const_TokenPtr tok, std::unique_ptr left, AST::AttrVec outer_attrs, ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr parse_binary_not_equal_expr ( - const_TokenPtr tok, std::unique_ptr left, - AST::AttrVec outer_attrs, - ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr parse_binary_greater_than_expr ( - const_TokenPtr tok, std::unique_ptr left, - AST::AttrVec outer_attrs, - ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr parse_binary_less_than_expr ( - const_TokenPtr tok, std::unique_ptr left, - AST::AttrVec outer_attrs, - ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr parse_binary_greater_equal_expr ( - const_TokenPtr tok, std::unique_ptr left, - AST::AttrVec outer_attrs, - ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr parse_binary_less_equal_expr ( - const_TokenPtr tok, std::unique_ptr left, - AST::AttrVec outer_attrs, - ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr + tl::expected, Parse::Error::Expr> + parse_binary_not_equal_expr (const_TokenPtr tok, + std::unique_ptr left, + AST::AttrVec outer_attrs, + ParseRestrictions restrictions + = ParseRestrictions ()); + tl::expected, Parse::Error::Expr> + parse_binary_greater_than_expr (const_TokenPtr tok, + std::unique_ptr left, + AST::AttrVec outer_attrs, + ParseRestrictions restrictions + = ParseRestrictions ()); + tl::expected, Parse::Error::Expr> + parse_binary_less_than_expr (const_TokenPtr tok, + std::unique_ptr left, + AST::AttrVec outer_attrs, + ParseRestrictions restrictions + = ParseRestrictions ()); + tl::expected, Parse::Error::Expr> + parse_binary_greater_equal_expr (const_TokenPtr tok, + std::unique_ptr left, + AST::AttrVec outer_attrs, + ParseRestrictions restrictions + = ParseRestrictions ()); + tl::expected, Parse::Error::Expr> + parse_binary_less_equal_expr (const_TokenPtr tok, + std::unique_ptr left, + AST::AttrVec outer_attrs, + ParseRestrictions restrictions + = ParseRestrictions ()); + tl::expected, Parse::Error::Expr> parse_lazy_or_expr (const_TokenPtr tok, std::unique_ptr left, AST::AttrVec outer_attrs, ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr + tl::expected, Parse::Error::Expr> parse_lazy_and_expr (const_TokenPtr tok, std::unique_ptr left, AST::AttrVec outer_attrs, ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr + tl::expected, Parse::Error::Expr> parse_type_cast_expr (const_TokenPtr tok, std::unique_ptr expr_to_cast, AST::AttrVec outer_attrs, ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr + tl::expected, Parse::Error::Expr> parse_assig_expr (const_TokenPtr tok, std::unique_ptr left, AST::AttrVec outer_attrs, ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr parse_compound_assignment_expr ( + tl::expected, Parse::Error::Expr> + parse_compound_assignment_expr ( const_TokenPtr tok, std::unique_ptr left, AST::AttrVec outer_attrs, AST::CompoundAssignmentExpr::ExprType expr_type, ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr + tl::expected, Parse::Error::Expr> parse_plus_assig_expr (const_TokenPtr tok, std::unique_ptr left, AST::AttrVec outer_attrs, ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr + tl::expected, Parse::Error::Expr> parse_minus_assig_expr (const_TokenPtr tok, std::unique_ptr left, AST::AttrVec outer_attrs, ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr + tl::expected, Parse::Error::Expr> parse_mult_assig_expr (const_TokenPtr tok, std::unique_ptr left, AST::AttrVec outer_attrs, ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr + tl::expected, Parse::Error::Expr> parse_div_assig_expr (const_TokenPtr tok, std::unique_ptr left, AST::AttrVec outer_attrs, ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr + tl::expected, Parse::Error::Expr> parse_mod_assig_expr (const_TokenPtr tok, std::unique_ptr left, AST::AttrVec outer_attrs, ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr + tl::expected, Parse::Error::Expr> parse_and_assig_expr (const_TokenPtr tok, std::unique_ptr left, AST::AttrVec outer_attrs, ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr + tl::expected, Parse::Error::Expr> parse_or_assig_expr (const_TokenPtr tok, std::unique_ptr left, AST::AttrVec outer_attrs, ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr + tl::expected, Parse::Error::Expr> parse_xor_assig_expr (const_TokenPtr tok, std::unique_ptr left, AST::AttrVec outer_attrs, ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr parse_left_shift_assig_expr ( - const_TokenPtr tok, std::unique_ptr left, - AST::AttrVec outer_attrs, - ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr parse_right_shift_assig_expr ( - const_TokenPtr tok, std::unique_ptr left, - AST::AttrVec outer_attrs, - ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr + tl::expected, Parse::Error::Expr> + parse_left_shift_assig_expr (const_TokenPtr tok, + std::unique_ptr left, + AST::AttrVec outer_attrs, + ParseRestrictions restrictions + = ParseRestrictions ()); + tl::expected, Parse::Error::Expr> + parse_right_shift_assig_expr (const_TokenPtr tok, + std::unique_ptr left, + AST::AttrVec outer_attrs, + ParseRestrictions restrictions + = ParseRestrictions ()); + tl::expected, Parse::Error::Expr> parse_await_expr (const_TokenPtr tok, std::unique_ptr expr_to_await, AST::AttrVec outer_attrs); - std::unique_ptr parse_method_call_expr ( - const_TokenPtr tok, std::unique_ptr receiver_expr, - AST::AttrVec outer_attrs, - ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr parse_function_call_expr ( - const_TokenPtr tok, std::unique_ptr function_expr, - AST::AttrVec outer_attrs, - ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr parse_led_range_exclusive_expr ( - const_TokenPtr tok, std::unique_ptr left, - AST::AttrVec outer_attrs, - ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr + tl::expected, Parse::Error::Expr> + parse_method_call_expr (const_TokenPtr tok, + std::unique_ptr receiver_expr, + AST::AttrVec outer_attrs, + ParseRestrictions restrictions + = ParseRestrictions ()); + tl::expected, Parse::Error::Expr> + parse_function_call_expr (const_TokenPtr tok, + std::unique_ptr function_expr, + AST::AttrVec outer_attrs, + ParseRestrictions restrictions + = ParseRestrictions ()); + tl::expected, Parse::Error::Expr> + parse_led_range_exclusive_expr (const_TokenPtr tok, + std::unique_ptr left, + AST::AttrVec outer_attrs, + ParseRestrictions restrictions + = ParseRestrictions ()); + tl::expected, Parse::Error::Expr> parse_nud_range_exclusive_expr (const_TokenPtr tok, AST::AttrVec outer_attrs); - std::unique_ptr parse_range_inclusive_expr ( - const_TokenPtr tok, std::unique_ptr left, - AST::AttrVec outer_attrs, - ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr + tl::expected, Parse::Error::Expr> + parse_range_inclusive_expr (const_TokenPtr tok, + std::unique_ptr left, + AST::AttrVec outer_attrs, + ParseRestrictions restrictions + = ParseRestrictions ()); + tl::expected, Parse::Error::Expr> parse_range_to_inclusive_expr (const_TokenPtr tok, AST::AttrVec outer_attrs); - std::unique_ptr parse_tuple_index_expr ( - const_TokenPtr tok, std::unique_ptr tuple_expr, - AST::AttrVec outer_attrs, - ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr parse_field_access_expr ( - const_TokenPtr tok, std::unique_ptr struct_expr, - AST::AttrVec outer_attrs, - ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr + tl::expected, Parse::Error::Expr> + parse_tuple_index_expr (const_TokenPtr tok, + std::unique_ptr tuple_expr, + AST::AttrVec outer_attrs, + ParseRestrictions restrictions + = ParseRestrictions ()); + tl::expected, Parse::Error::Expr> + parse_field_access_expr (const_TokenPtr tok, + std::unique_ptr struct_expr, + AST::AttrVec outer_attrs, + ParseRestrictions restrictions + = ParseRestrictions ()); + tl::expected, Parse::Error::Expr> parse_index_expr (const_TokenPtr tok, std::unique_ptr array_expr, AST::AttrVec outer_attrs, ParseRestrictions restrictions = ParseRestrictions ()); std::unique_ptr parse_macro_invocation_partial ( AST::PathInExpression path, AST::AttrVec outer_attrs, ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr + tl::expected, Parse::Error::Expr> parse_struct_expr_struct_partial (AST::PathInExpression path, AST::AttrVec outer_attrs); - std::unique_ptr + tl::expected, Parse::Error::Expr> parse_struct_expr_tuple_partial (AST::PathInExpression path, AST::AttrVec outer_attrs); - std::unique_ptr + tl::expected, Parse::Error::Expr> parse_closure_expr_pratt (const_TokenPtr tok, AST::AttrVec outer_attrs = AST::AttrVec ()); std::unique_ptr parse_tuple_index_expr_float ( @@ -699,37 +728,37 @@ private: // When given a pratt_parsed_loc, use it as the location of the // first token parsed in the expression (the parsing of that first // token should be skipped). - std::unique_ptr + tl::expected, Parse::Error::Node> parse_if_expr (AST::AttrVec outer_attrs = AST::AttrVec (), location_t pratt_parsed_loc = UNKNOWN_LOCATION); - std::unique_ptr + tl::expected, Parse::Error::Node> parse_if_let_expr (AST::AttrVec outer_attrs = AST::AttrVec (), location_t pratt_parsed_loc = UNKNOWN_LOCATION); - std::unique_ptr + tl::expected, Parse::Error::Node> parse_loop_expr (AST::AttrVec outer_attrs = AST::AttrVec (), tl::optional label = tl::nullopt, location_t pratt_parsed_loc = UNKNOWN_LOCATION); - std::unique_ptr + tl::expected, Parse::Error::Node> parse_while_loop_expr (AST::AttrVec outer_attrs = AST::AttrVec (), tl::optional label = tl::nullopt, location_t pratt_parsed_loc = UNKNOWN_LOCATION); - std::unique_ptr + tl::expected, Parse::Error::Node> parse_while_let_loop_expr (AST::AttrVec outer_attrs = AST::AttrVec (), tl::optional label = tl::nullopt); - std::unique_ptr + tl::expected, Parse::Error::Node> parse_for_loop_expr (AST::AttrVec outer_attrs = AST::AttrVec (), tl::optional label = tl::nullopt); - std::unique_ptr + tl::expected, Parse::Error::Node> parse_match_expr (AST::AttrVec outer_attrs = AST::AttrVec (), location_t pratt_parsed_loc = UNKNOWN_LOCATION); AST::MatchArm parse_match_arm (); std::unique_ptr parse_match_arm_pattern (TokenId end_token_id); - std::unique_ptr parse_labelled_loop_expr (const_TokenPtr tok, - AST::AttrVec outer_attrs - = AST::AttrVec ()); + tl::expected, Parse::Error::Node> + parse_labelled_loop_expr (const_TokenPtr tok, + AST::AttrVec outer_attrs = AST::AttrVec ()); tl::expected parse_loop_label (const_TokenPtr tok); - std::unique_ptr + tl::expected, Parse::Error::Node> parse_async_block_expr (AST::AttrVec outer_attrs = AST::AttrVec ()); tl::expected, Parse::Error::Node> parse_grouped_expr (AST::AttrVec outer_attrs = AST::AttrVec ()); @@ -737,34 +766,36 @@ private: parse_closure_expr (AST::AttrVec outer_attrs = AST::AttrVec ()); AST::ClosureParam parse_closure_param (); - std::unique_ptr parse_box_expr (AST::AttrVec outer_attrs, - location_t pratt_parsed_loc - = UNKNOWN_LOCATION); + tl::expected, Parse::Error::Node> + parse_box_expr (AST::AttrVec outer_attrs, + location_t pratt_parsed_loc = UNKNOWN_LOCATION); // When given a pratt_parsed_loc, use it as the location of the // first token parsed in the expression (the parsing of that first // token should be skipped). - std::unique_ptr + tl::expected, Parse::Error::Node> parse_return_expr (AST::AttrVec outer_attrs = AST::AttrVec (), location_t pratt_parsed_loc = UNKNOWN_LOCATION); - std::unique_ptr + tl::expected, Parse::Error::Node> parse_try_expr (AST::AttrVec outer_attrs = AST::AttrVec (), location_t pratt_parsed_loc = UNKNOWN_LOCATION); - std::unique_ptr + tl::expected, Parse::Error::Node> parse_break_expr (AST::AttrVec outer_attrs = AST::AttrVec (), location_t pratt_parsed_loc = UNKNOWN_LOCATION); std::unique_ptr parse_continue_expr (AST::AttrVec outer_attrs = AST::AttrVec (), location_t pratt_parsed_loc = UNKNOWN_LOCATION); - std::unique_ptr + tl::expected, Parse::Error::Node> parse_unsafe_block_expr (AST::AttrVec outer_attrs = AST::AttrVec (), location_t pratt_parsed_loc = UNKNOWN_LOCATION); - std::unique_ptr + tl::expected, Parse::Error::Node> parse_array_expr (AST::AttrVec outer_attrs = AST::AttrVec (), location_t pratt_parsed_loc = UNKNOWN_LOCATION); - std::unique_ptr + tl::expected, Parse::Error::Node> parse_grouped_or_tuple_expr (AST::AttrVec outer_attrs = AST::AttrVec (), location_t pratt_parsed_loc = UNKNOWN_LOCATION); - std::unique_ptr parse_struct_expr_field (); + tl::expected, + Parse::Error::StructExprField> + parse_struct_expr_field (); bool will_be_expr_with_block (); // Type-related @@ -798,7 +829,7 @@ private: std::unique_ptr parse_expr_stmt (AST::AttrVec outer_attrs, ParseRestrictions restrictions = ParseRestrictions ()); - ExprOrStmt parse_stmt_or_expr (); + tl::expected parse_stmt_or_expr (); // Pattern-related std::unique_ptr parse_literal_or_range_pattern (); diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc index 54b3be8f1ef..0da8c38b63e 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -263,7 +263,7 @@ Late::visit (AST::BreakExpr &expr) if (expr.has_break_expr ()) { - auto &break_expr = expr.get_break_expr (); + auto &break_expr = expr.get_break_expr_unchecked (); if (break_expr.get_expr_kind () == AST::Expr::Kind::Identifier) { /* This is a break with an expression, and the expression is @@ -273,9 +273,9 @@ Late::visit (AST::BreakExpr &expr) emit the error here though, because the identifier may still be in scope, and ICE'ing on valid programs would not be very funny. */ - std::string ident - = static_cast (expr.get_break_expr ()) - .as_string (); + std::string ident = static_cast ( + expr.get_break_expr_unchecked ()) + .as_string (); if (ident == "rust" || ident == "gcc") funny_error = true; }