// Copyright (C) 2025-2026 Free Software Foundation, Inc.

// This file is part of GCC.

// GCC is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 3, or (at your option) any later
// version.

// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// for more details.

// You should have received a copy of the GNU General Public License
// along with GCC; see the file COPYING3.  If not see
// <http://www.gnu.org/licenses/>.

/* DO NOT INCLUDE ANYWHERE - this is automatically included
 *   by rust-parse-impl*.h
 * This is also the reason why there are no include guards. */

#include "rust-parse.h"
#include "rust-parse-error.h"
#include "rust-attribute-values.h"
#include "expected.h"

namespace Rust {

// Parse a inner or outer doc comment into an doc attribute
template <typename ManagedTokenSource>
Parse::AttributeBody
Parser<ManagedTokenSource>::parse_doc_comment ()
{
  const_TokenPtr token = lexer.peek_token ();
  location_t locus = token->get_locus ();
  AST::SimplePathSegment segment (Values::Attributes::DOC, locus);
  std::vector<AST::SimplePathSegment> segments;
  segments.push_back (std::move (segment));
  AST::SimplePath attr_path (std::move (segments), false, locus);
  AST::LiteralExpr lit_expr (token->get_str (), AST::Literal::STRING,
			     PrimitiveCoreType::CORETYPE_STR, {}, locus);
  std::unique_ptr<AST::AttrInput> attr_input (
    new AST::AttrInputLiteral (std::move (lit_expr)));
  lexer.skip_token ();

  return Parse::AttributeBody{std::move (attr_path), std::move (attr_input),
			      locus};
}

// Parse a single inner attribute.
template <typename ManagedTokenSource>
tl::expected<AST::Attribute, Parse::Error::Attribute>
Parser<ManagedTokenSource>::parse_inner_attribute ()
{
  if (lexer.peek_token ()->get_id () == INNER_DOC_COMMENT)
    {
      auto body = parse_doc_comment ();
      return AST::Attribute (std::move (body.path), std::move (body.input),
			     body.locus, true);
    }

  rust_assert (lexer.peek_token ()->get_id () == HASH);

  lexer.skip_token ();

  if (lexer.peek_token ()->get_id () != EXCLAM)
    {
      Error error (lexer.peek_token ()->get_locus (),
		   "expected %<!%> or %<[%> for inner attribute");
      add_error (std::move (error));

      return Parse::Error::Attribute::make_malformed ();
    }
  lexer.skip_token ();

  if (!skip_token (LEFT_SQUARE))
    return Parse::Error::Attribute::make_malformed ();

  auto body_res = parse_attribute_body ();
  if (!body_res)
    return Parse::Error::Attribute::make_malformed ();
  auto body = std::move (body_res.value ());

  auto actual_attribute
    = AST::Attribute (std::move (body.path), std::move (body.input), body.locus,
		      true);

  if (!skip_token (RIGHT_SQUARE))
    return Parse::Error::Attribute::make_malformed ();

  return actual_attribute;
}

// Parse a single outer attribute.
template <typename ManagedTokenSource>
tl::expected<AST::Attribute, Parse::Error::Attribute>
Parser<ManagedTokenSource>::parse_outer_attribute ()
{
  if (lexer.peek_token ()->get_id () == OUTER_DOC_COMMENT)
    {
      auto body = parse_doc_comment ();
      return AST::Attribute (std::move (body.path), std::move (body.input),
			     body.locus, false);
    }

  if (lexer.peek_token ()->get_id () == INNER_DOC_COMMENT)
    {
      Error error (
	lexer.peek_token ()->get_locus (), ErrorCode::E0753,
	"expected outer doc comment, inner doc (%<//!%> or %</*!%>) only "
	"allowed at start of item "
	"and before any outer attribute or doc (%<#[%>, %<///%> or %</**%>)");
      add_error (std::move (error));
      lexer.skip_token ();
      return Parse::Error::Attribute::make_unexpected_inner ();
    }

  /* OuterAttribute -> '#' '[' Attr ']' */

  if (lexer.peek_token ()->get_id () != HASH)
    return Parse::Error::Attribute::make_malformed ();

  lexer.skip_token ();

  TokenId id = lexer.peek_token ()->get_id ();
  if (id != LEFT_SQUARE)
    {
      if (id == EXCLAM)
	{
	  // this is inner attribute syntax, so throw error
	  // inner attributes were either already parsed or not allowed here.
	  Error error (
	    lexer.peek_token ()->get_locus (),
	    "token %<!%> found, indicating inner attribute definition. Inner "
	    "attributes are not possible at this location");
	  add_error (std::move (error));
	}
      return Parse::Error::Attribute::make_unexpected_inner ();
    }

  lexer.skip_token ();

  auto body_res = parse_attribute_body ();
  if (!body_res)
    return Parse::Error::Attribute::make_malformed_body ();
  auto body = std::move (body_res.value ());

  auto actual_attribute
    = AST::Attribute (std::move (body.path), std::move (body.input), body.locus,
		      false);

  if (lexer.peek_token ()->get_id () != RIGHT_SQUARE)
    return Parse::Error::Attribute::make_malformed ();

  lexer.skip_token ();

  return actual_attribute;
}

// Parses the body of an attribute (inner or outer).
template <typename ManagedTokenSource>
tl::expected<Parse::AttributeBody, Parse::Error::AttributeBody>
Parser<ManagedTokenSource>::parse_attribute_body ()
{
  location_t locus = lexer.peek_token ()->get_locus ();

  auto attr_path = parse_simple_path ();
  // ensure path is valid to parse attribute input
  if (!attr_path)
    {
      Error error (lexer.peek_token ()->get_locus (),
		   "empty simple path in attribute");
      add_error (std::move (error));

      // Skip past potential further info in attribute (i.e. attr_input)
      skip_after_end_attribute ();
      return Parse::Error::AttributeBody::make_invalid_path ();
    }

  auto attr_input = parse_attr_input ();
  // AttrInput is allowed to be null, so no checks here
  if (attr_input)
    return Parse::AttributeBody{std::move (attr_path.value ()),
				std::move (attr_input.value ()), locus};
  else if (attr_input.error ().kind == Parse::Error::AttrInput::Kind::MISSING)
    return Parse::AttributeBody{std::move (attr_path.value ()), nullptr, locus};
  else
    return Parse::Error::AttributeBody::make_invalid_attrinput ();
}

// Parse a contiguous block of inner attributes.
template <typename ManagedTokenSource>
AST::AttrVec
Parser<ManagedTokenSource>::parse_inner_attributes ()
{
  AST::AttrVec inner_attributes;

  auto has_valid_inner_attribute_prefix = [&] () {
    auto id = lexer.peek_token ()->get_id ();
    /* Outer attribute `#[` is not allowed, only accepts `#!` */
    return (id == HASH && lexer.peek_token (1)->get_id () == EXCLAM)
	   || id == INNER_DOC_COMMENT;
  };

  while (has_valid_inner_attribute_prefix ())
    {
      auto inner_attr = parse_inner_attribute ();

      /* Ensure only valid inner attributes are added to the inner_attributes
       * list */
      if (inner_attr)
	{
	  inner_attributes.push_back (std::move (inner_attr.value ()));
	}
      else
	{
	  /* If no more valid inner attributes, break out of loop (only
	   * contiguous inner attributes parsed). */
	  break;
	}
    }

  inner_attributes.shrink_to_fit ();
  return inner_attributes;
}

// Parses a contiguous block of outer attributes.
template <typename ManagedTokenSource>
AST::AttrVec
Parser<ManagedTokenSource>::parse_outer_attributes ()
{
  AST::AttrVec outer_attributes;

  auto has_valid_attribute_prefix = [&] () {
    auto id = lexer.peek_token ()->get_id ();
    /* We allow inner attributes `#!` and catch the error later  */
    return id == HASH || id == OUTER_DOC_COMMENT || id == INNER_DOC_COMMENT;
  };

  while (has_valid_attribute_prefix ()) /* For error handling.  */
    {
      auto outer_attr = parse_outer_attribute ();

      /* Ensure only valid outer attributes are added to the outer_attributes
       * list */
      if (outer_attr)
	{
	  outer_attributes.push_back (std::move (outer_attr.value ()));
	}
      else
	{
	  /* If no more valid outer attributes, break out of loop (only
	   * contiguous outer attributes parsed). */
	  break;
	}
    }

  outer_attributes.shrink_to_fit ();
  return outer_attributes;

  /* TODO: this shares basically all code with parse_inner_attributes except
   * function call - find way of making it more modular? function pointer? */
}

// Parses an AttrInput AST node (polymorphic, as AttrInput is abstract)
template <typename ManagedTokenSource>
tl::expected<std::unique_ptr<AST::AttrInput>, Parse::Error::AttrInput>
Parser<ManagedTokenSource>::parse_attr_input ()
{
  const_TokenPtr t = lexer.peek_token ();
  switch (t->get_id ())
    {
    case LEFT_PAREN:
    case LEFT_SQUARE:
    case LEFT_CURLY:
      {
	auto dtoken_tree = parse_delim_token_tree ();
	if (!dtoken_tree)
	  return Parse::Error::AttrInput::make_bad_token_tree ();

	// must be a delimited token tree, so parse that
	std::unique_ptr<AST::AttrInput> input_tree (
	  new AST::DelimTokenTree (dtoken_tree.value ()));

	return tl::expected<std::unique_ptr<AST::AttrInput>,
			    Parse::Error::AttrInput>{std::move (input_tree)};
      }
    case EQUAL:
      {
	// = LiteralExpr
	lexer.skip_token ();

	t = lexer.peek_token ();

	// attempt to parse macro
	// TODO: macros may/may not be allowed in attributes
	// this is needed for "#[doc = include_str!(...)]"
	if (Parse::Utils::is_simple_path_segment (t->get_id ()))
	  {
	    std::unique_ptr<AST::MacroInvocation> invoke
	      = parse_macro_invocation ({});

	    if (!invoke)
	      return Parse::Error::AttrInput::make_bad_macro_invocation ();

	    return std::unique_ptr<AST::AttrInput> (
	      new AST::AttrInputMacro (std::move (invoke)));
	  }

	/* Ensure token is a "literal expression" (literally only a literal
	 * token of any type) */
	if (!t->is_literal ())
	  {
	    Error error (
	      t->get_locus (),
	      "unknown token %qs in attribute body - literal expected",
	      t->get_token_description ());
	    add_error (std::move (error));

	    skip_after_end_attribute ();
	    return Parse::Error::AttrInput::make_malformed ();
	  }

	AST::Literal::LitType lit_type = AST::Literal::STRING;
	// Crappy mapping of token type to literal type
	switch (t->get_id ())
	  {
	  case INT_LITERAL:
	    lit_type = AST::Literal::INT;
	    break;
	  case FLOAT_LITERAL:
	    lit_type = AST::Literal::FLOAT;
	    break;
	  case CHAR_LITERAL:
	    lit_type = AST::Literal::CHAR;
	    break;
	  case BYTE_CHAR_LITERAL:
	    lit_type = AST::Literal::BYTE;
	    break;
	  case BYTE_STRING_LITERAL:
	    lit_type = AST::Literal::BYTE_STRING;
	    break;
	  case RAW_STRING_LITERAL:
	    lit_type = AST::Literal::RAW_STRING;
	    break;
	  case STRING_LITERAL:
	  default:
	    lit_type = AST::Literal::STRING;
	    break; // TODO: raw string? don't eliminate it from lexer?
	  }

	// create actual LiteralExpr
	AST::LiteralExpr lit_expr (t->get_str (), lit_type, t->get_type_hint (),
				   {}, t->get_locus ());
	lexer.skip_token ();

	std::unique_ptr<AST::AttrInput> attr_input_lit (
	  new AST::AttrInputLiteral (std::move (lit_expr)));

	// do checks or whatever? none required, really

	// FIXME: shouldn't a skip token be required here?

	return tl::expected<std::unique_ptr<AST::AttrInput>,
			    Parse::Error::AttrInput>{
	  std::move (attr_input_lit)};
      }
      break;
    case RIGHT_PAREN:
    case RIGHT_SQUARE:
    case RIGHT_CURLY:
    case END_OF_FILE:
      // means AttrInput is missing, which is allowed
      return Parse::Error::AttrInput::make_missing_attrinput ();
    default:
      add_error (
	Error (t->get_locus (),
	       "unknown token %qs in attribute body - attribute input or "
	       "none expected",
	       t->get_token_description ()));

      skip_after_end_attribute ();
      return Parse::Error::AttrInput::make_malformed ();
    }
  rust_unreachable ();
  // TODO: find out how to stop gcc error on "no return value"
}

} // namespace Rust
