/* This file is part of GCC.
GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3.  If not see
. */
#ifndef RUST_PARSE_H
#define RUST_PARSE_H
#include "rust-lex.h"
#include "rust-ast-full.h"
#include "rust-diagnostics.h"
namespace Rust {
/* HACK: used to resolve the expression-or-statement problem at the end of a
 * block by allowing either to be returned (technically). Tagged union would
 * probably take up the same amount of space. */
struct ExprOrStmt
{
  std::unique_ptr expr;
  std::unique_ptr stmt;
  /* I was going to resist the urge to make this a real class and make it POD,
   * but construction in steps is too difficult. So it'll just also have a
   * constructor. */
  // expression constructor
  ExprOrStmt (std::unique_ptr expr) : expr (std::move (expr)) {}
  // statement constructor
  ExprOrStmt (std::unique_ptr stmt) : stmt (std::move (stmt)) {}
  // macro constructor
  ExprOrStmt (std::unique_ptr macro)
    : 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
   * require it */
  // move constructors
  ExprOrStmt (ExprOrStmt &&other) = default;
  ExprOrStmt &operator= (ExprOrStmt &&other) = default;
private:
  // private constructor only used for creating error state expr or stmt objects
  ExprOrStmt (AST::Expr *expr, AST::Stmt *stmt) : expr (expr), stmt (stmt) {}
  // make this work: have a disambiguation specifically for known statements
  // (i.e. ';' and 'let'). then, have a special "parse expr or stmt" function
  // that returns this type. inside it, it parses an expression, and then
  // determines whether to return expr or stmt via whether the next token is a
  // semicolon. should be able to disambiguate inside that function between
  // stmts with blocks and without blocks.
};
/* Restrictions on parsing used to signal that certain ambiguous grammar
 * features should be parsed in a certain way. */
struct ParseRestrictions
{
  bool can_be_struct_expr = true;
  /* Whether the expression was entered from a unary expression - prevents stuff
   * like struct exprs being parsed from a dereference. */
  bool entered_from_unary = false;
  bool expr_can_be_null = false;
  bool expr_can_be_stmt = false;
  bool consume_semi = true;
};
// Parser implementation for gccrs.
// TODO: if updated to C++20, ManagedTokenSource would be useful as a concept
template  class Parser
{
public:
  /**
   * Consume a token, reporting an error if it isn't the next token
   *
   * @param t ID of the token to consume
   *
   * @return true if the token was next, false if it wasn't found
   */
  bool skip_token (TokenId t);
  /**
   * Same as `skip_token` but allows for failure without necessarily reporting
   * an error
   *
   * @param t ID of the token to consume
   *
   * @return true if the token was next, false if it wasn't found
   */
  bool maybe_skip_token (TokenId t);
  std::unique_ptr
  parse_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
	      ParseRestrictions restrictions = ParseRestrictions ());
  std::unique_ptr parse_literal_expr (AST::AttrVec outer_attrs
							= AST::AttrVec ());
  std::unique_ptr
  parse_block_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
		    Location pratt_parsed_loc = Linemap::unknown_location ());
  std::unique_ptr parse_item (bool called_from_statement);
  std::unique_ptr parse_pattern ();
  /**
   * Parse a statement
   *
   * Statement : ';'
   *    | Item
   *    | LetStatement
   *    | ExpressionStatement
   *    | MacroInvocationSemi
   */
  std::unique_ptr parse_stmt (ParseRestrictions restrictions
					 = ParseRestrictions ());
  std::unique_ptr parse_type (bool save_errors = true);
  std::unique_ptr parse_external_item ();
  std::unique_ptr parse_trait_item ();
  std::unique_ptr parse_inherent_impl_item ();
  std::unique_ptr parse_trait_impl_item ();
  AST::PathInExpression parse_path_in_expression ();
  std::vector > parse_lifetime_params ();
  AST::Visibility parse_visibility ();
  std::unique_ptr parse_identifier_pattern ();
  std::unique_ptr parse_token_tree ();
  AST::Attribute parse_attribute_body ();
private:
  void skip_after_semicolon ();
  void skip_after_end ();
  void skip_after_end_block ();
  void skip_after_next_block ();
  void skip_after_end_attribute ();
  const_TokenPtr expect_token (TokenId t);
  void unexpected_token (const_TokenPtr t);
  bool skip_generics_right_angle ();
  void parse_statement_seq (bool (Parser::*done) ());
  // AST-related stuff - maybe move or something?
  AST::AttrVec parse_inner_attributes ();
  AST::Attribute parse_inner_attribute ();
  AST::AttrVec parse_outer_attributes ();
  AST::Attribute parse_outer_attribute ();
  std::unique_ptr parse_attr_input ();
  AST::Attribute parse_doc_comment ();
  // Path-related
  AST::SimplePath parse_simple_path ();
  AST::SimplePathSegment parse_simple_path_segment ();
  AST::TypePath parse_type_path ();
  std::unique_ptr parse_type_path_segment ();
  AST::PathIdentSegment parse_path_ident_segment ();
  std::unique_ptr parse_const_generic_expression ();
  AST::GenericArgs parse_path_generic_args ();
  AST::GenericArgsBinding parse_generic_args_binding ();
  AST::TypePathFunction parse_type_path_function (Location locus);
  AST::PathExprSegment parse_path_expr_segment ();
  AST::QualifiedPathInExpression
  // 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).
  parse_qualified_path_in_expression (Location pratt_parsed_loc
				      = Linemap::unknown_location ());
  AST::QualifiedPathType
  parse_qualified_path_type (Location pratt_parsed_loc
			     = Linemap::unknown_location ());
  AST::QualifiedPathInType parse_qualified_path_in_type ();
  // Token tree or macro related
  AST::DelimTokenTree parse_delim_token_tree ();
  std::unique_ptr
  parse_macro_rules_def (AST::AttrVec outer_attrs);
  std::unique_ptr
  parse_macro_invocation_semi (AST::AttrVec outer_attrs);
  std::unique_ptr
  parse_macro_invocation (AST::AttrVec outer_attrs);
  AST::MacroRule parse_macro_rule ();
  AST::MacroMatcher parse_macro_matcher ();
  std::unique_ptr parse_macro_match ();
  std::unique_ptr parse_macro_match_fragment ();
  std::unique_ptr parse_macro_match_repetition ();
  // Top-level item-related
  std::unique_ptr parse_vis_item (AST::AttrVec outer_attrs);
  std::unique_ptr parse_macro_item (AST::AttrVec outer_attrs);
  // VisItem subclass-related
  std::unique_ptr parse_module (AST::Visibility vis,
					     AST::AttrVec outer_attrs);
  std::unique_ptr
  parse_extern_crate (AST::Visibility vis, AST::AttrVec outer_attrs);
  std::unique_ptr
  parse_use_decl (AST::Visibility vis, AST::AttrVec outer_attrs);
  std::unique_ptr parse_use_tree ();
  std::unique_ptr parse_function (AST::Visibility vis,
						 AST::AttrVec outer_attrs);
  AST::FunctionQualifiers parse_function_qualifiers ();
  std::vector >
  parse_generic_params_in_angles ();
  template 
  std::vector >
  parse_generic_params (EndTokenPred is_end_token);
  template 
  std::unique_ptr
  parse_generic_param (EndTokenPred is_end_token);
  template 
  std::vector >
  parse_lifetime_params (EndTokenPred is_end_token);
  std::vector parse_lifetime_params_objs ();
  template 
  std::vector
  parse_lifetime_params_objs (EndTokenPred is_end_token);
  template 
  auto parse_non_ptr_sequence (
    ParseFunction parsing_function, EndTokenPred is_end_token,
    std::string error_msg = "failed to parse generic param in generic params")
    -> std::vector;
  AST::LifetimeParam parse_lifetime_param ();
  std::vector > parse_type_params ();
  template 
  std::vector >
  parse_type_params (EndTokenPred is_end_token);
  std::unique_ptr parse_type_param ();
  template 
  std::vector
  parse_function_params (EndTokenPred is_end_token);
  AST::FunctionParam parse_function_param ();
  std::unique_ptr parse_function_return_type ();
  AST::WhereClause parse_where_clause ();
  std::unique_ptr parse_where_clause_item ();
  std::unique_ptr
  parse_lifetime_where_clause_item ();
  std::unique_ptr
  parse_type_bound_where_clause_item ();
  std::vector parse_for_lifetimes ();
  template 
  std::vector >
  parse_type_param_bounds (EndTokenPred is_end_token);
  std::vector > parse_type_param_bounds ();
  std::unique_ptr parse_type_param_bound ();
  std::unique_ptr parse_trait_bound ();
  std::vector parse_lifetime_bounds ();
  template 
  std::vector parse_lifetime_bounds (EndTokenPred is_end_token);
  AST::Lifetime parse_lifetime ();
  std::unique_ptr parse_type_alias (AST::Visibility vis,
						    AST::AttrVec outer_attrs);
  std::unique_ptr parse_struct (AST::Visibility vis,
					     AST::AttrVec outer_attrs);
  std::vector parse_struct_fields ();
  template 
  std::vector parse_struct_fields (EndTokenPred is_end_token);
  AST::StructField parse_struct_field ();
  std::vector parse_tuple_fields ();
  AST::TupleField parse_tuple_field ();
  std::unique_ptr parse_enum (AST::Visibility vis,
					 AST::AttrVec outer_attrs);
  std::vector > parse_enum_items ();
  template 
  std::vector >
  parse_enum_items (EndTokenPred is_end_token);
  std::unique_ptr parse_enum_item ();
  std::unique_ptr parse_union (AST::Visibility vis,
					   AST::AttrVec outer_attrs);
  std::unique_ptr
  parse_const_item (AST::Visibility vis, AST::AttrVec outer_attrs);
  std::unique_ptr parse_static_item (AST::Visibility vis,
						      AST::AttrVec outer_attrs);
  std::unique_ptr parse_trait (AST::Visibility vis,
					   AST::AttrVec outer_attrs);
  std::unique_ptr
  parse_trait_type (AST::AttrVec outer_attrs);
  std::unique_ptr
  parse_trait_const (AST::AttrVec outer_attrs);
  AST::SelfParam parse_self_param ();
  std::unique_ptr parse_impl (AST::Visibility vis,
					 AST::AttrVec outer_attrs);
  std::unique_ptr
  parse_inherent_impl_function_or_method (AST::Visibility vis,
					  AST::AttrVec outer_attrs);
  std::unique_ptr
  parse_trait_impl_function_or_method (AST::Visibility vis,
				       AST::AttrVec outer_attrs);
  std::unique_ptr
  parse_extern_block (AST::Visibility vis, AST::AttrVec outer_attrs);
  AST::NamedFunctionParam parse_named_function_param (AST::AttrVec outer_attrs
						      = AST::AttrVec ());
  AST::Method parse_method ();
  // Expression-related (Pratt parsed)
  std::unique_ptr
  parse_expr (int right_binding_power,
	      AST::AttrVec outer_attrs = AST::AttrVec (),
	      ParseRestrictions restrictions = ParseRestrictions ());
  std::unique_ptr
  null_denotation (const_TokenPtr t, AST::AttrVec outer_attrs = AST::AttrVec (),
		   ParseRestrictions restrictions = ParseRestrictions ());
  std::unique_ptr
  left_denotation (const_TokenPtr t, std::unique_ptr left,
		   AST::AttrVec outer_attrs = AST::AttrVec (),
		   ParseRestrictions restrictions = ParseRestrictions ());
  std::unique_ptr
  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
  parse_binary_plus_expr (const_TokenPtr tok, std::unique_ptr left,
			  AST::AttrVec outer_attrs,
			  ParseRestrictions restrictions
			  = ParseRestrictions ());
  std::unique_ptr
  parse_binary_minus_expr (const_TokenPtr tok, std::unique_ptr left,
			   AST::AttrVec outer_attrs,
			   ParseRestrictions restrictions
			   = ParseRestrictions ());
  std::unique_ptr
  parse_binary_mult_expr (const_TokenPtr tok, std::unique_ptr left,
			  AST::AttrVec outer_attrs,
			  ParseRestrictions restrictions
			  = ParseRestrictions ());
  std::unique_ptr
  parse_binary_div_expr (const_TokenPtr tok, std::unique_ptr left,
			 AST::AttrVec outer_attrs,
			 ParseRestrictions restrictions = ParseRestrictions ());
  std::unique_ptr
  parse_binary_mod_expr (const_TokenPtr tok, std::unique_ptr left,
			 AST::AttrVec outer_attrs,
			 ParseRestrictions restrictions = ParseRestrictions ());
  std::unique_ptr
  parse_bitwise_and_expr (const_TokenPtr tok, std::unique_ptr left,
			  AST::AttrVec outer_attrs,
			  ParseRestrictions restrictions
			  = ParseRestrictions ());
  std::unique_ptr
  parse_bitwise_or_expr (const_TokenPtr tok, std::unique_ptr left,
			 AST::AttrVec outer_attrs,
			 ParseRestrictions restrictions = ParseRestrictions ());
  std::unique_ptr
  parse_bitwise_xor_expr (const_TokenPtr tok, std::unique_ptr left,
			  AST::AttrVec outer_attrs,
			  ParseRestrictions restrictions
			  = ParseRestrictions ());
  std::unique_ptr
  parse_left_shift_expr (const_TokenPtr tok, std::unique_ptr left,
			 AST::AttrVec outer_attrs,
			 ParseRestrictions restrictions = ParseRestrictions ());
  std::unique_ptr
  parse_right_shift_expr (const_TokenPtr tok, std::unique_ptr left,
			  AST::AttrVec outer_attrs,
			  ParseRestrictions restrictions
			  = ParseRestrictions ());
  std::unique_ptr
  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
  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
  parse_lazy_or_expr (const_TokenPtr tok, std::unique_ptr left,
		      AST::AttrVec outer_attrs,
		      ParseRestrictions restrictions = ParseRestrictions ());
  std::unique_ptr
  parse_lazy_and_expr (const_TokenPtr tok, std::unique_ptr left,
		       AST::AttrVec outer_attrs,
		       ParseRestrictions restrictions = ParseRestrictions ());
  std::unique_ptr
  parse_type_cast_expr (const_TokenPtr tok,
			std::unique_ptr expr_to_cast,
			AST::AttrVec outer_attrs,
			ParseRestrictions restrictions = ParseRestrictions ());
  std::unique_ptr
  parse_assig_expr (const_TokenPtr tok, std::unique_ptr left,
		    AST::AttrVec outer_attrs,
		    ParseRestrictions restrictions = ParseRestrictions ());
  std::unique_ptr 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
  parse_plus_assig_expr (const_TokenPtr tok, std::unique_ptr left,
			 AST::AttrVec outer_attrs,
			 ParseRestrictions restrictions = ParseRestrictions ());
  std::unique_ptr
  parse_minus_assig_expr (const_TokenPtr tok, std::unique_ptr left,
			  AST::AttrVec outer_attrs,
			  ParseRestrictions restrictions
			  = ParseRestrictions ());
  std::unique_ptr
  parse_mult_assig_expr (const_TokenPtr tok, std::unique_ptr left,
			 AST::AttrVec outer_attrs,
			 ParseRestrictions restrictions = ParseRestrictions ());
  std::unique_ptr
  parse_div_assig_expr (const_TokenPtr tok, std::unique_ptr left,
			AST::AttrVec outer_attrs,
			ParseRestrictions restrictions = ParseRestrictions ());
  std::unique_ptr
  parse_mod_assig_expr (const_TokenPtr tok, std::unique_ptr left,
			AST::AttrVec outer_attrs,
			ParseRestrictions restrictions = ParseRestrictions ());
  std::unique_ptr
  parse_and_assig_expr (const_TokenPtr tok, std::unique_ptr left,
			AST::AttrVec outer_attrs,
			ParseRestrictions restrictions = ParseRestrictions ());
  std::unique_ptr
  parse_or_assig_expr (const_TokenPtr tok, std::unique_ptr left,
		       AST::AttrVec outer_attrs,
		       ParseRestrictions restrictions = ParseRestrictions ());
  std::unique_ptr
  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
  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
  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
  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
  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
  parse_struct_expr_struct_partial (AST::PathInExpression path,
				    AST::AttrVec outer_attrs);
  std::unique_ptr
  parse_struct_expr_tuple_partial (AST::PathInExpression path,
				   AST::AttrVec outer_attrs);
  AST::PathInExpression parse_path_in_expression_pratt (const_TokenPtr tok);
  std::unique_ptr
  parse_closure_expr_pratt (const_TokenPtr tok,
			    AST::AttrVec outer_attrs = AST::AttrVec ());
  std::unique_ptr parse_tuple_index_expr_float (
    const_TokenPtr tok, std::unique_ptr tuple_expr,
    AST::AttrVec outer_attrs,
    ParseRestrictions restrictions = ParseRestrictions ());
  // Expression-related (non-Pratt parsed)
  std::unique_ptr
  parse_expr_with_block (AST::AttrVec outer_attrs);
  std::unique_ptr
  parse_expr_without_block (AST::AttrVec outer_attrs = AST::AttrVec (),
			    ParseRestrictions restrictions
			    = ParseRestrictions ());
  // 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
  parse_if_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
		 Location pratt_parsed_loc = Linemap::unknown_location ());
  std::unique_ptr
  parse_if_let_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
		     Location pratt_parsed_loc = Linemap::unknown_location ());
  std::unique_ptr
  parse_loop_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
		   AST::LoopLabel label = AST::LoopLabel::error (),
		   Location pratt_parsed_loc = Linemap::unknown_location ());
  std::unique_ptr
  parse_while_loop_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
			 AST::LoopLabel label = AST::LoopLabel::error (),
			 Location pratt_parsed_loc
			 = Linemap::unknown_location ());
  std::unique_ptr
  parse_while_let_loop_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
			     AST::LoopLabel label = AST::LoopLabel::error ());
  std::unique_ptr
  parse_for_loop_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
		       AST::LoopLabel label = AST::LoopLabel::error ());
  std::unique_ptr
  parse_match_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
		    Location pratt_parsed_loc = Linemap::unknown_location ());
  AST::MatchArm parse_match_arm ();
  std::vector >
  parse_match_arm_patterns (TokenId end_token_id);
  std::unique_ptr
  parse_labelled_loop_expr (AST::AttrVec outer_attrs = AST::AttrVec ());
  AST::LoopLabel parse_loop_label ();
  std::unique_ptr
  parse_async_block_expr (AST::AttrVec outer_attrs = AST::AttrVec ());
  std::unique_ptr parse_grouped_expr (AST::AttrVec outer_attrs
							= AST::AttrVec ());
  std::unique_ptr parse_closure_expr (AST::AttrVec outer_attrs
							= AST::AttrVec ());
  AST::ClosureParam parse_closure_param ();
  // 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
  parse_return_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
		     Location pratt_parsed_loc = Linemap::unknown_location ());
  std::unique_ptr
  parse_break_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
		    Location pratt_parsed_loc = Linemap::unknown_location ());
  std::unique_ptr
  parse_continue_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
		       Location pratt_parsed_loc
		       = Linemap::unknown_location ());
  std::unique_ptr
  parse_unsafe_block_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
			   Location pratt_parsed_loc
			   = Linemap::unknown_location ());
  std::unique_ptr
  parse_array_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
		    Location pratt_parsed_loc = Linemap::unknown_location ());
  std::unique_ptr
  parse_grouped_or_tuple_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
			       Location pratt_parsed_loc
			       = Linemap::unknown_location ());
  std::unique_ptr parse_struct_expr_field ();
  bool will_be_expr_with_block ();
  // Type-related
  std::unique_ptr parse_type_no_bounds ();
  std::unique_ptr parse_slice_or_array_type ();
  std::unique_ptr parse_raw_pointer_type ();
  std::unique_ptr parse_reference_type ();
  std::unique_ptr
  parse_bare_function_type (std::vector for_lifetimes);
  std::unique_ptr parse_paren_prefixed_type ();
  std::unique_ptr parse_paren_prefixed_type_no_bounds ();
  std::unique_ptr parse_for_prefixed_type ();
  AST::MaybeNamedParam parse_maybe_named_param (AST::AttrVec outer_attrs);
  // Statement-related
  /**
   *Parse a let-statement
   * LetStatement :
   * 	OuterAttribute*
   * 		'let' PatternNoTopAlt ( ':' Type )? ('=' Expression )? ';'
   *
   * @param allow_no_semi Allow parsing a let-statement without expecting a
   * 		semicolon to follow it
   */
  std::unique_ptr parse_let_stmt (AST::AttrVec outer_attrs,
						ParseRestrictions restrictions
						= ParseRestrictions ());
  std::unique_ptr parse_expr_stmt (AST::AttrVec outer_attrs,
						  ParseRestrictions restrictions
						  = ParseRestrictions ());
  std::unique_ptr
  parse_expr_stmt_with_block (AST::AttrVec outer_attrs);
  std::unique_ptr
  parse_expr_stmt_without_block (AST::AttrVec outer_attrs,
				 ParseRestrictions restrictions
				 = ParseRestrictions ());
  ExprOrStmt parse_stmt_or_expr_without_block ();
  ExprOrStmt parse_stmt_or_expr_with_block (AST::AttrVec outer_attrs);
  ExprOrStmt parse_macro_invocation_maybe_semi (AST::AttrVec outer_attrs);
  ExprOrStmt parse_path_based_stmt_or_expr (AST::AttrVec outer_attrs);
  // Pattern-related
  std::unique_ptr parse_literal_or_range_pattern ();
  std::unique_ptr parse_range_pattern_bound ();
  std::unique_ptr parse_reference_pattern ();
  std::unique_ptr parse_grouped_or_tuple_pattern ();
  std::unique_ptr parse_slice_pattern ();
  std::unique_ptr parse_ident_leading_pattern ();
  std::unique_ptr parse_tuple_struct_items ();
  AST::StructPatternElements parse_struct_pattern_elems ();
  std::unique_ptr parse_struct_pattern_field ();
  std::unique_ptr
  parse_struct_pattern_field_partial (AST::AttrVec outer_attrs);
  int left_binding_power (const_TokenPtr token);
  bool done_end ();
  bool done_end_or_else ();
  bool done_end_of_file ();
  void add_error (Error error) { error_table.push_back (std::move (error)); }
public:
  // Construct parser with specified "managed" token source.
  Parser (ManagedTokenSource tokenSource) : lexer (std::move (tokenSource)) {}
  // Parse items without parsing an entire crate. This function is the main
  // parsing loop of AST::Crate::parse_crate().
  std::vector > parse_items ();
  // Main entry point for parser.
  AST::Crate parse_crate ();
  // Dumps all lexer output.
  void debug_dump_lex_output (std::ostream &out);
  void debug_dump_ast_output (AST::Crate &crate, std::ostream &out);
  // Returns whether any parsing errors have occurred.
  bool has_errors () const { return !error_table.empty (); }
  // Remove all parsing errors from the table
  void clear_errors () { error_table.clear (); }
  // Get a reference to the list of errors encountered
  std::vector &get_errors () { return error_table; }
  const ManagedTokenSource &get_token_source () const { return lexer; }
  const_TokenPtr peek_current_token () { return lexer.peek_token (0); }
private:
  // The token source (usually lexer) associated with the parser.
  ManagedTokenSource lexer;
  // The error list.
  std::vector error_table;
  // The names of inline modules while parsing.
  std::vector inline_module_stack;
  class InlineModuleStackScope
  {
  private:
    Parser &parser;
  public:
    InlineModuleStackScope (Parser &parser, std::string name) : parser (parser)
    {
      parser.inline_module_stack.emplace_back (std::move (name));
    }
    ~InlineModuleStackScope () { parser.inline_module_stack.pop_back (); }
  };
};
std::string
extract_module_path (const AST::AttrVec &inner_attrs,
		     const AST::AttrVec &outer_attrs, const std::string &name);
/**
 * Check if a MacroMatch is allowed to follow the last parsed MacroMatch.
 *
 * @param last_match Last matcher parsed before the current match
 * @param match Current matcher to check
 *
 * @return true if the follow-up is valid, false otherwise
 */
bool
is_match_compatible (const AST::MacroMatch &last_match,
		     const AST::MacroMatch ¤t_match);
} // namespace Rust
// as now template, include implementations of all methods
#include "rust-parse-impl.h"
#endif // RUST_PARSE_H