// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "fidl/parser.h"

#include <errno.h>
#include <lib/fit/function.h>

#include "fidl/attributes.h"
#include "fidl/diagnostics.h"
#include "fidl/experimental_flags.h"
#include "fidl/types.h"
#include "fidl/utils.h"

namespace fidl {

// The "case" keyword is not folded into CASE_TOKEN and CASE_IDENTIFIER because
// doing so confuses clang-format.
#define CASE_TOKEN(K) Token::KindAndSubkind(K, Token::Subkind::kNone).combined()

#define CASE_IDENTIFIER(K) Token::KindAndSubkind(Token::Kind::kIdentifier, K).combined()

#define TOKEN_TYPE_CASES                         \
  case CASE_IDENTIFIER(Token::Subkind::kNone):   \
  case CASE_IDENTIFIER(Token::Subkind::kArray):  \
  case CASE_IDENTIFIER(Token::Subkind::kVector): \
  case CASE_IDENTIFIER(Token::Subkind::kString): \
  case CASE_IDENTIFIER(Token::Subkind::kRequest)

#define TOKEN_ATTR_CASES         \
  case Token::Kind::kDocComment: \
  case Token::Kind::kLeftSquare

#define TOKEN_LITERAL_CASES                      \
  case CASE_IDENTIFIER(Token::Subkind::kTrue):   \
  case CASE_IDENTIFIER(Token::Subkind::kFalse):  \
  case CASE_TOKEN(Token::Kind::kNumericLiteral): \
  case CASE_TOKEN(Token::Kind::kStringLiteral)

namespace {

enum {
  More,
  Done,
};

template <typename T, typename Fn>
void add(std::vector<std::unique_ptr<T>>* elements, Fn producer_fn) {
  fit::function<std::unique_ptr<T>()> producer(producer_fn);
  auto element = producer();
  if (element)
    elements->emplace_back(std::move(element));
}

}  // namespace

Parser::Parser(Lexer* lexer, Reporter* reporter, ExperimentalFlags experimental_flags)
    : lexer_(lexer),
      reporter_(reporter),
      experimental_flags_(experimental_flags),
      state_(State::kNormal) {
  last_token_ = Lex();
}

std::nullptr_t Parser::Fail() { return Fail(ErrUnexpectedToken); }

std::nullptr_t Parser::Fail(std::unique_ptr<Diagnostic> err) {
  assert(err && "should not report nullptr error");
  if (Ok()) {
    err->span = last_token_.span();
    reporter_->Report(std::move(err));
  }
  return nullptr;
}

template <typename... Args>
std::nullptr_t Parser::Fail(const ErrorDef<Args...>& err, const Args&... args) {
  return Fail(err, last_token_, args...);
}

template <typename... Args>
std::nullptr_t Parser::Fail(const ErrorDef<Args...>& err, Token token, const Args&... args) {
  if (Ok()) {
    reporter_->Report(err, token, args...);
  }
  return nullptr;
}

template <typename... Args>
std::nullptr_t Parser::Fail(const ErrorDef<Args...>& err, const std::optional<SourceSpan>& span,
                            const Args&... args) {
  if (Ok()) {
    reporter_->Report(err, span, args...);
  }
  return nullptr;
}

Parser::Modifiers Parser::ParseModifiers() {
  Modifiers modifiers;
  Token token;

  // Consume tokens until we get one that isn't a modifier, treating duplicates
  // and conflicts as immediately recovered errors. For conflicts (e.g. "strict
  // flexible" or "flexible strict"), we use the earliest one.
  for (;;) {
    switch (Peek().combined()) {
      case CASE_IDENTIFIER(Token::Subkind::kStrict):
      case CASE_IDENTIFIER(Token::Subkind::kFlexible):
        token = ConsumeToken(OfKind(Token::Kind::kIdentifier)).value();
        if (modifiers.strictness) {
          if (token.subkind() == modifiers.strictness_token->subkind()) {
            Fail(ErrDuplicateModifier, token, token.kind_and_subkind());
            RecoverOneError();
          } else {
            Fail(ErrConflictingModifier, token, token.kind_and_subkind(),
                 modifiers.strictness_token->kind_and_subkind());
            RecoverOneError();
          }
        } else {
          const auto value = token.subkind() == Token::Subkind::kStrict
                                 ? types::Strictness::kStrict
                                 : types::Strictness::kFlexible;
          modifiers.strictness = value;
          modifiers.strictness_token = token;
        }
        break;
      case CASE_IDENTIFIER(Token::Subkind::kResource):
        token = ConsumeToken(IdentifierOfSubkind(Token::Subkind::kResource)).value();
        if (modifiers.resourceness) {
          Fail(ErrDuplicateModifier, token, token.kind_and_subkind());
          RecoverOneError();
        } else {
          modifiers.resourceness = types::Resourceness::kResource;
          modifiers.resourceness_token = token;
        }
        break;
      default:
        return modifiers;
    }
  }
}

std::unique_ptr<raw::Identifier> Parser::ParseIdentifier(bool is_discarded) {
  ASTScope scope(this, is_discarded);
  std::optional<Token> token = ConsumeToken(OfKind(Token::Kind::kIdentifier));
  if (!Ok() || !token)
    return Fail();
  std::string identifier(token->data());
  if (!utils::IsValidIdentifierComponent(identifier))
    return Fail(ErrInvalidIdentifier, identifier);

  return std::make_unique<raw::Identifier>(scope.GetSourceElement());
}

std::unique_ptr<raw::CompoundIdentifier> Parser::ParseCompoundIdentifier() {
  ASTScope scope(this);
  std::vector<std::unique_ptr<raw::Identifier>> components;

  components.emplace_back(ParseIdentifier());
  if (!Ok())
    return Fail();

  auto parse_component = [&components, this]() {
    switch (Peek().combined()) {
      default:
        return Done;

      case CASE_TOKEN(Token::Kind::kDot):
        ConsumeToken(OfKind(Token::Kind::kDot));
        if (Ok()) {
          components.emplace_back(ParseIdentifier());
        }
        return More;
    }
  };

  while (parse_component() == More) {
    if (!Ok())
      return Fail();
  }

  return std::make_unique<raw::CompoundIdentifier>(scope.GetSourceElement(), std::move(components));
}

std::unique_ptr<raw::CompoundIdentifier> Parser::ParseLibraryName() {
  auto library_name = ParseCompoundIdentifier();
  if (!Ok())
    return Fail();

  for (const auto& component : library_name->components) {
    std::string component_data(component->start_.data());
    if (!utils::IsValidLibraryComponent(component_data)) {
      return Fail(ErrInvalidLibraryNameComponent, component->start_, component_data);
    }
  }

  return library_name;
}

std::unique_ptr<raw::StringLiteral> Parser::ParseStringLiteral() {
  ASTScope scope(this);
  ConsumeToken(OfKind(Token::Kind::kStringLiteral));
  if (!Ok())
    return Fail();

  return std::make_unique<raw::StringLiteral>(scope.GetSourceElement());
}

std::unique_ptr<raw::NumericLiteral> Parser::ParseNumericLiteral() {
  ASTScope scope(this);
  ConsumeToken(OfKind(Token::Kind::kNumericLiteral));
  if (!Ok())
    return Fail();

  return std::make_unique<raw::NumericLiteral>(scope.GetSourceElement());
}

std::unique_ptr<raw::Ordinal64> Parser::ParseOrdinal64() {
  ASTScope scope(this);

  if (!MaybeConsumeToken(OfKind(Token::Kind::kNumericLiteral)))
    return Fail(ErrMissingOrdinalBeforeType);
  if (!Ok())
    return Fail();
  auto data = scope.GetSourceElement().span().data();
  std::string string_data(data.data(), data.data() + data.size());
  errno = 0;
  unsigned long long value = strtoull(string_data.data(), nullptr, 0);
  assert(errno == 0 && "unparsable number should not be lexed.");
  if (value > std::numeric_limits<uint32_t>::max())
    return Fail(ErrOrdinalOutOfBound);
  uint32_t ordinal = static_cast<uint32_t>(value);
  if (ordinal == 0u)
    return Fail(ErrOrdinalsMustStartAtOne);

  ConsumeToken(OfKind(Token::Kind::kColon));
  if (!Ok())
    return Fail();

  return std::make_unique<raw::Ordinal64>(scope.GetSourceElement(), ordinal);
}

std::unique_ptr<raw::TrueLiteral> Parser::ParseTrueLiteral() {
  ASTScope scope(this);
  ConsumeToken(IdentifierOfSubkind(Token::Subkind::kTrue));
  if (!Ok())
    return Fail();

  return std::make_unique<raw::TrueLiteral>(scope.GetSourceElement());
}

std::unique_ptr<raw::FalseLiteral> Parser::ParseFalseLiteral() {
  ASTScope scope(this);
  ConsumeToken(IdentifierOfSubkind(Token::Subkind::kFalse));
  if (!Ok())
    return Fail();

  return std::make_unique<raw::FalseLiteral>(scope.GetSourceElement());
}

std::unique_ptr<raw::Literal> Parser::ParseLiteral() {
  switch (Peek().combined()) {
    case CASE_TOKEN(Token::Kind::kStringLiteral):
      return ParseStringLiteral();

    case CASE_TOKEN(Token::Kind::kNumericLiteral):
      return ParseNumericLiteral();

    case CASE_IDENTIFIER(Token::Subkind::kTrue):
      return ParseTrueLiteral();

    case CASE_IDENTIFIER(Token::Subkind::kFalse):
      return ParseFalseLiteral();

    default:
      return Fail();
  }
}

std::unique_ptr<raw::Attribute> Parser::ParseAttribute() {
  ASTScope scope(this);
  auto name = ParseIdentifier();
  if (!Ok())
    return Fail();
  std::unique_ptr<raw::StringLiteral> value;
  if (MaybeConsumeToken(OfKind(Token::Kind::kEqual))) {
    value = ParseStringLiteral();
    if (!Ok())
      return Fail();
  }

  std::string str_name("");
  std::string str_value("");
  if (name)
    str_name = std::string(name->span().data().data(), name->span().data().size());
  if (value) {
    auto data = value->span().data();
    if (data.size() >= 2 && data[0] == '"' && data[data.size() - 1] == '"') {
      str_value = std::string(value->span().data().data() + 1, value->span().data().size() - 2);
    }
  }
  return std::make_unique<raw::Attribute>(
      scope.GetSourceElement(), raw::Attribute::Provenance::kDefault, str_name, str_value);
}

std::unique_ptr<raw::AttributeList> Parser::ParseAttributeList(
    std::unique_ptr<raw::Attribute> doc_comment, ASTScope& scope) {
  AttributesBuilder attributes_builder(reporter_);
  if (doc_comment) {
    if (!attributes_builder.Insert(std::move(*doc_comment.get())))
      return Fail();
  }
  ConsumeToken(OfKind(Token::Kind::kLeftSquare));
  if (!Ok())
    return Fail();
  for (;;) {
    auto attribute = ParseAttribute();
    if (!Ok())
      return Fail();
    if (!attributes_builder.Insert(std::move(*attribute.get())))
      return Fail();
    if (!MaybeConsumeToken(OfKind(Token::Kind::kComma)))
      break;
  }
  ConsumeToken(OfKind(Token::Kind::kRightSquare));
  if (!Ok())
    return Fail();
  auto attribute_list =
      std::make_unique<raw::AttributeList>(scope.GetSourceElement(), attributes_builder.Done());
  return attribute_list;
}

std::unique_ptr<raw::Attribute> Parser::ParseDocComment() {
  ASTScope scope(this);
  std::string str_value("");

  std::optional<Token> doc_line;
  bool is_first_doc_comment = true;
  while (Peek().kind() == Token::Kind::kDocComment) {
    if (is_first_doc_comment) {
      is_first_doc_comment = false;
    } else {
      // disallow any blank lines between this doc comment and the previous one
      std::string_view trailing_whitespace = last_token_.previous_end().data();
      if (std::count(trailing_whitespace.cbegin(), trailing_whitespace.cend(), '\n') > 1)
        reporter_->Report(WarnBlankLinesWithinDocCommentBlock, previous_token_);
    }

    doc_line = ConsumeToken(OfKind(Token::Kind::kDocComment));
    if (!Ok() || !doc_line)
      return Fail();
    // NOTE: we currently explicitly only support UNIX line endings
    str_value +=
        std::string(doc_line->span().data().data() + 3, doc_line->span().data().size() - 2);
  }

  if (Peek().kind() == Token::Kind::kEndOfFile)
    reporter_->Report(WarnDocCommentMustBeFollowedByDeclaration, previous_token_);

  return std::make_unique<raw::Attribute>(
      scope.GetSourceElement(), raw::Attribute::Provenance::kDocComment, "Doc", str_value);
}

std::unique_ptr<raw::AttributeList> Parser::MaybeParseAttributeList(bool for_parameter) {
  ASTScope scope(this);
  std::unique_ptr<raw::Attribute> doc_comment;
  // Doc comments must appear above attributes
  if (Peek().kind() == Token::Kind::kDocComment) {
    doc_comment = ParseDocComment();
  }
  if (for_parameter && doc_comment) {
    reporter_->Report(ErrDocCommentOnParameters, previous_token_);
    return Fail();
  }
  if (Peek().kind() == Token::Kind::kLeftSquare) {
    return ParseAttributeList(std::move(doc_comment), scope);
  }
  // no generic attributes, start the attribute list
  if (doc_comment) {
    AttributesBuilder attributes_builder(reporter_);
    if (!attributes_builder.Insert(std::move(*doc_comment.get())))
      return Fail();
    return std::make_unique<raw::AttributeList>(scope.GetSourceElement(),
                                                attributes_builder.Done());
  }
  return nullptr;
}

std::unique_ptr<raw::Constant> Parser::ParseConstant() {
  std::unique_ptr<raw::Constant> constant;
  switch (Peek().combined()) {
    case CASE_TOKEN(Token::Kind::kIdentifier): {
      auto identifier = ParseCompoundIdentifier();
      if (!Ok())
        return Fail();
      constant = std::make_unique<raw::IdentifierConstant>(std::move(identifier));
      break;
    }

    TOKEN_LITERAL_CASES : {
      auto literal = ParseLiteral();
      if (!Ok())
        return Fail();
      constant = std::make_unique<raw::LiteralConstant>(std::move(literal));
      break;
    }

    case CASE_TOKEN(Token::Kind::kLeftParen): {
      if (!experimental_flags_.IsFlagEnabled(ExperimentalFlags::Flag::kEnableHandleRights))
        return Fail();

      ASTScope scope(this);
      ConsumeToken(OfKind(Token::Kind::kLeftParen));
      constant = ParseConstant();
      ConsumeToken(OfKind(Token::Kind::kRightParen));
      if (!Ok())
        return Fail();
      constant->update_span(scope.GetSourceElement());
      break;
    }

    default:
      return Fail();
  }

  if (Peek().combined() == Token::Kind::kPipe) {
    ConsumeToken(OfKind(Token::Kind::kPipe));
    std::unique_ptr right_operand = ParseConstant();
    if (!Ok())
      return Fail();
    return std::make_unique<raw::BinaryOperatorConstant>(
        std::move(constant), std::move(right_operand), raw::BinaryOperatorConstant::Operator::kOr);
  }
  return constant;
}

std::unique_ptr<raw::AliasDeclaration> Parser::ParseAliasDeclaration(
    std::unique_ptr<raw::AttributeList> attributes, ASTScope& scope, const Modifiers& modifiers) {
  const auto decl_token = ConsumeToken(IdentifierOfSubkind(Token::Subkind::kAlias));
  if (!Ok())
    return Fail();

  ValidateModifiers</* none */>(modifiers, decl_token.value());

  auto alias = ParseIdentifier();
  if (!Ok())
    return Fail();

  ConsumeToken(OfKind(Token::Kind::kEqual));
  if (!Ok())
    return Fail();

  auto type_ctor = ParseTypeConstructor();
  if (!Ok())
    return Fail();

  return std::make_unique<raw::AliasDeclaration>(scope.GetSourceElement(), std::move(attributes),
                                                 std::move(alias), std::move(type_ctor));
}

std::unique_ptr<raw::Using> Parser::ParseUsing(std::unique_ptr<raw::AttributeList> attributes,
                                               ASTScope& scope, const Modifiers& modifiers) {
  const auto decl_token = ConsumeToken(IdentifierOfSubkind(Token::Subkind::kUsing));
  if (!Ok())
    return Fail();
  auto decl_start_token = decl_token.value();

  ValidateModifiers</* none */>(modifiers, decl_start_token);

  auto using_path = ParseCompoundIdentifier();
  if (!Ok())
    return Fail();

  std::unique_ptr<raw::Identifier> maybe_alias;
  std::unique_ptr<raw::TypeConstructorOld> maybe_type_ctor;

  if (MaybeConsumeToken(IdentifierOfSubkind(Token::Subkind::kAs))) {
    if (!Ok())
      return Fail();
    maybe_alias = ParseIdentifier();
    if (!Ok())
      return Fail();
  } else if (MaybeConsumeToken(OfKind(Token::Kind::kEqual))) {
    if (syntax_ == utils::Syntax::kNew ||
        experimental_flags_.IsFlagEnabled(ExperimentalFlags::Flag::kDisallowOldUsingSyntax))
      return Fail(ErrOldUsingSyntaxDeprecated, using_path->span());
    if (!Ok() || using_path->components.size() != 1u)
      return Fail(ErrCompoundAliasIdentifier, using_path->span());
    maybe_type_ctor = ParseTypeConstructorOld();
    if (!Ok())
      return Fail();
  }

  return std::make_unique<raw::Using>(
      scope.GetSourceElement(), std::make_unique<Token>(decl_start_token), std::move(attributes),
      std::move(using_path), std::move(maybe_alias), std::move(maybe_type_ctor));
}

std::unique_ptr<raw::TypeConstructorOld> Parser::ParseTypeConstructorOld() {
  ASTScope scope(this);
  auto identifier = ParseCompoundIdentifier();
  if (!Ok())
    return Fail();

  std::unique_ptr<raw::TypeConstructorOld> maybe_arg_type_ctor;
  std::unique_ptr<raw::Constant> handle_rights;
  std::unique_ptr<raw::Constant> maybe_size;
  std::unique_ptr<raw::Identifier> handle_subtype_identifier;
  auto nullability = types::Nullability::kNonnullable;

  if (MaybeConsumeToken(OfKind(Token::Kind::kLeftAngle))) {
    if (!Ok())
      return Fail();
    maybe_arg_type_ctor = ParseTypeConstructorOld();
    if (!Ok())
      return Fail();
    ConsumeToken(OfKind(Token::Kind::kRightAngle));
    if (!Ok())
      return Fail();
  }

  if (MaybeConsumeToken(OfKind(Token::Kind::kColon))) {
    if (!Ok())
      return Fail();
    // TODO(fxbug.dev/64629): To properly generalize handle, while supporting
    // all the features which currently exist, we will need to parse a much more
    // liberal grammar at this stage (a 'type constructor'), and defer the
    // interpretation of this data to the compilation step.
    if (identifier->components.back()->span().data() == "handle") {
      if (MaybeConsumeToken(OfKind(Token::Kind::kLeftAngle))) {
        handle_subtype_identifier = ParseIdentifier();
        if (experimental_flags_.IsFlagEnabled(ExperimentalFlags::Flag::kEnableHandleRights)) {
          if (MaybeConsumeToken(OfKind(Token::Kind::kComma))) {
            handle_rights = ParseConstant();
          }
        }
        ConsumeToken(OfKind(Token::Kind::kRightAngle));
        if (!Ok())
          return Fail();
      } else {
        handle_subtype_identifier = ParseIdentifier();
      }
    } else {
      maybe_size = ParseConstant();
    }
    if (!Ok())
      return Fail();
  }
  if (MaybeConsumeToken(OfKind(Token::Kind::kQuestion))) {
    if (!Ok())
      return Fail();
    nullability = types::Nullability::kNullable;
  }

  return std::make_unique<raw::TypeConstructorOld>(
      scope.GetSourceElement(), std::move(identifier), std::move(maybe_arg_type_ctor),
      std::move(handle_subtype_identifier), std::move(handle_rights), std::move(maybe_size),
      nullability);
}

std::unique_ptr<raw::BitsMember> Parser::ParseBitsMember() {
  ASTScope scope(this);
  auto attributes = MaybeParseAttributeList();
  if (!Ok())
    return Fail();
  auto identifier = ParseIdentifier();
  if (!Ok())
    return Fail();

  ConsumeToken(OfKind(Token::Kind::kEqual));
  if (!Ok())
    return Fail();

  auto member_value = ParseConstant();
  if (!Ok())
    return Fail();

  return std::make_unique<raw::BitsMember>(scope.GetSourceElement(), std::move(identifier),
                                           std::move(member_value), std::move(attributes));
}

std::unique_ptr<raw::BitsDeclaration> Parser::ParseBitsDeclaration(
    std::unique_ptr<raw::AttributeList> attributes, ASTScope& scope, const Modifiers& modifiers) {
  std::vector<std::unique_ptr<raw::BitsMember>> members;
  const auto decl_token = ConsumeToken(IdentifierOfSubkind(Token::Subkind::kBits));
  if (!Ok())
    return Fail();
  auto decl_start_token = decl_token.value();

  ValidateModifiers<types::Strictness>(modifiers, decl_start_token);

  auto identifier = ParseIdentifier();
  if (!Ok())
    return Fail();

  std::unique_ptr<raw::TypeConstructorOld> maybe_type_ctor;
  if (MaybeConsumeToken(OfKind(Token::Kind::kColon))) {
    if (!Ok())
      return Fail();
    maybe_type_ctor = ParseTypeConstructorOld();
    if (!Ok())
      return Fail();
  }

  ConsumeToken(OfKind(Token::Kind::kLeftCurly));
  if (!Ok())
    return Fail();

  auto parse_member = [&members, this]() {
    if (Peek().kind() == Token::Kind::kRightCurly) {
      ConsumeToken(OfKind(Token::Kind::kRightCurly));
      return Done;
    } else {
      add(&members, [&] { return ParseBitsMember(); });
      return More;
    }
  };

  auto checkpoint = reporter_->Checkpoint();
  while (parse_member() == More) {
    if (!Ok()) {
      const auto result = RecoverToEndOfMember();
      if (result == RecoverResult::Failure) {
        return Fail();
      } else if (result == RecoverResult::EndOfScope) {
        continue;
      }
    }
    ConsumeTokenOrRecover(OfKind(Token::Kind::kSemicolon));
  }
  if (!Ok())
    Fail();

  if (!checkpoint.NoNewErrors())
    return nullptr;

  if (members.empty())
    return Fail(ErrMustHaveOneMember);

  if (modifiers.strictness != std::nullopt) {
    decl_start_token = modifiers.strictness_token.value();
  }

  return std::make_unique<raw::BitsDeclaration>(
      scope.GetSourceElement(), std::make_unique<Token>(decl_start_token), std::move(attributes),
      std::move(identifier), std::move(maybe_type_ctor), std::move(members),
      modifiers.strictness.value_or(types::Strictness::kStrict));
}

std::unique_ptr<raw::ConstDeclaration> Parser::ParseConstDeclaration(
    std::unique_ptr<raw::AttributeList> attributes, ASTScope& scope, const Modifiers& modifiers) {
  const auto decl_token = ConsumeToken(IdentifierOfSubkind(Token::Subkind::kConst));
  if (!Ok())
    return Fail();

  ValidateModifiers</* none */>(modifiers, decl_token.value());

  // TODO(fxbug.dev/70247): remove branching
  raw::TypeConstructor type_ctor;
  std::unique_ptr<raw::Identifier> identifier;
  if (syntax_ == utils::Syntax::kNew) {
    identifier = ParseIdentifier();
    if (!Ok())
      return Fail();
    type_ctor = ParseTypeConstructor();
    if (!Ok())
      return Fail();
  } else {
    type_ctor = ParseTypeConstructor();
    if (!Ok())
      return Fail();
    identifier = ParseIdentifier();
    if (!Ok())
      return Fail();
  }

  ConsumeToken(OfKind(Token::Kind::kEqual));
  if (!Ok())
    return Fail();
  auto constant = ParseConstant();
  if (!Ok())
    return Fail();

  return std::make_unique<raw::ConstDeclaration>(scope.GetSourceElement(), std::move(attributes),
                                                 std::move(type_ctor), std::move(identifier),
                                                 std::move(constant));
}

std::unique_ptr<raw::EnumMember> Parser::ParseEnumMember() {
  ASTScope scope(this);
  auto attributes = MaybeParseAttributeList();
  if (!Ok())
    return Fail();
  auto identifier = ParseIdentifier();
  if (!Ok())
    return Fail();

  ConsumeToken(OfKind(Token::Kind::kEqual));
  if (!Ok())
    return Fail();

  auto member_value = ParseConstant();
  if (!Ok())
    return Fail();

  return std::make_unique<raw::EnumMember>(scope.GetSourceElement(), std::move(identifier),
                                           std::move(member_value), std::move(attributes));
}

std::unique_ptr<raw::EnumDeclaration> Parser::ParseEnumDeclaration(
    std::unique_ptr<raw::AttributeList> attributes, ASTScope& scope, const Modifiers& modifiers) {
  std::vector<std::unique_ptr<raw::EnumMember>> members;
  const auto decl_token = ConsumeToken(IdentifierOfSubkind(Token::Subkind::kEnum));
  if (!Ok())
    return Fail();
  auto decl_start_token = decl_token.value();

  ValidateModifiers<types::Strictness>(modifiers, decl_start_token);

  auto identifier = ParseIdentifier();
  if (!Ok())
    return Fail();

  std::unique_ptr<raw::TypeConstructorOld> maybe_type_ctor;
  if (MaybeConsumeToken(OfKind(Token::Kind::kColon))) {
    if (!Ok())
      return Fail();
    maybe_type_ctor = ParseTypeConstructorOld();
    if (!Ok())
      return Fail();
  }

  ConsumeToken(OfKind(Token::Kind::kLeftCurly));
  if (!Ok())
    return Fail();

  auto parse_member = [&members, this]() {
    if (Peek().kind() == Token::Kind::kRightCurly) {
      ConsumeToken(OfKind(Token::Kind::kRightCurly));
      return Done;
    } else {
      add(&members, [&] { return ParseEnumMember(); });
      return More;
    }
  };

  auto checkpoint = reporter_->Checkpoint();
  while (parse_member() == More) {
    if (!Ok()) {
      const auto result = RecoverToEndOfMember();
      if (result == RecoverResult::Failure) {
        return Fail();
      } else if (result == RecoverResult::EndOfScope) {
        continue;
      }
    }
    ConsumeTokenOrRecover(OfKind(Token::Kind::kSemicolon));
  }
  if (!Ok())
    Fail();

  if (!checkpoint.NoNewErrors())
    return nullptr;

  if (members.empty())
    return Fail(ErrMustHaveOneMember);

  if (modifiers.strictness != std::nullopt) {
    decl_start_token = modifiers.strictness_token.value();
  }

  return std::make_unique<raw::EnumDeclaration>(
      scope.GetSourceElement(), std::make_unique<Token>(decl_start_token), std::move(attributes),
      std::move(identifier), std::move(maybe_type_ctor), std::move(members),
      modifiers.strictness.value_or(types::Strictness::kStrict));
}

std::unique_ptr<raw::Parameter> Parser::ParseParameter() {
  ASTScope scope(this);
  auto attributes = MaybeParseAttributeList(/*for_parameter=*/true);
  if (!Ok())
    return Fail();

  // TODO(fxbug.dev/70247): remove branching
  raw::TypeConstructor type_ctor;
  std::unique_ptr<raw::Identifier> identifier;
  if (syntax_ == utils::Syntax::kNew) {
    identifier = ParseIdentifier();
    if (!Ok())
      return Fail();
    type_ctor = ParseTypeConstructor();
    if (!Ok())
      return Fail();
  } else {
    type_ctor = ParseTypeConstructor();
    if (!Ok())
      return Fail();
    identifier = ParseIdentifier();
    if (!Ok())
      return Fail();
  }

  return std::make_unique<raw::Parameter>(scope.GetSourceElement(), std::move(type_ctor),
                                          std::move(identifier), std::move(attributes));
}

std::unique_ptr<raw::ParameterList> Parser::ParseParameterList() {
  ASTScope scope(this);
  std::vector<std::unique_ptr<raw::Parameter>> parameter_list;

  ConsumeToken(OfKind(Token::Kind::kLeftParen));
  if (!Ok())
    return Fail();

  if (Peek().kind() != Token::Kind::kRightParen) {
    auto parameter = ParseParameter();
    parameter_list.emplace_back(std::move(parameter));
    if (!Ok()) {
      const auto result = RecoverToEndOfParam();
      if (result == RecoverResult::Failure) {
        return Fail();
      }
    }
    while (Peek().kind() == Token::Kind::kComma) {
      ConsumeToken(OfKind(Token::Kind::kComma));
      if (!Ok())
        return Fail();
      parameter_list.emplace_back(ParseParameter());
      if (!Ok()) {
        const auto result = RecoverToEndOfParam();
        if (result == RecoverResult::Failure) {
          return Fail();
        }
      }
    }
  }

  ConsumeToken(OfKind(Token::Kind::kRightParen));
  if (!Ok())
    return Fail();

  return std::make_unique<raw::ParameterList>(scope.GetSourceElement(), std::move(parameter_list));
}

std::unique_ptr<raw::ProtocolMethod> Parser::ParseProtocolEvent(
    std::unique_ptr<raw::AttributeList> attributes, ASTScope& scope) {
  ConsumeToken(OfKind(Token::Kind::kArrow));
  if (!Ok())
    return Fail();

  auto method_name = ParseIdentifier();
  if (!Ok())
    return Fail();

  auto parse_params = [this](std::unique_ptr<raw::ParameterList>* params_out) {
    if (!Ok())
      return false;
    *params_out = ParseParameterList();
    if (!Ok())
      return false;

    return true;
  };

  std::unique_ptr<raw::ParameterList> response;
  if (!parse_params(&response))
    return Fail();

  std::unique_ptr<raw::TypeConstructorOld> maybe_error;
  if (MaybeConsumeToken(IdentifierOfSubkind(Token::Subkind::kError))) {
    maybe_error = ParseTypeConstructorOld();
    if (!Ok())
      return Fail();
  }

  assert(method_name);
  assert(response);

  return std::make_unique<raw::ProtocolMethod>(scope.GetSourceElement(), std::move(attributes),
                                               std::move(method_name), nullptr /* maybe_request */,
                                               std::move(response), std::move(maybe_error));
}

std::unique_ptr<raw::ProtocolMethod> Parser::ParseProtocolMethod(
    std::unique_ptr<raw::AttributeList> attributes, ASTScope& scope,
    std::unique_ptr<raw::Identifier> method_name) {
  auto parse_params = [this](std::unique_ptr<raw::ParameterList>* params_out) {
    *params_out = ParseParameterList();
    if (!Ok())
      return false;
    return true;
  };

  std::unique_ptr<raw::ParameterList> request;
  if (!parse_params(&request))
    return Fail();

  std::unique_ptr<raw::ParameterList> maybe_response;
  std::unique_ptr<raw::TypeConstructorOld> maybe_error;
  if (MaybeConsumeToken(OfKind(Token::Kind::kArrow))) {
    if (!Ok())
      return Fail();
    if (!parse_params(&maybe_response))
      return Fail();
    if (MaybeConsumeToken(IdentifierOfSubkind(Token::Subkind::kError))) {
      maybe_error = ParseTypeConstructorOld();
      if (!Ok())
        return Fail();
    }
  }

  assert(method_name);
  assert(request);

  return std::make_unique<raw::ProtocolMethod>(scope.GetSourceElement(), std::move(attributes),
                                               std::move(method_name), std::move(request),
                                               std::move(maybe_response), std::move(maybe_error));
}

void Parser::ParseProtocolMember(
    std::vector<std::unique_ptr<raw::ComposeProtocol>>* composed_protocols,
    std::vector<std::unique_ptr<raw::ProtocolMethod>>* methods) {
  ASTScope scope(this);
  std::unique_ptr<raw::AttributeList> attributes = MaybeParseAttributeList();
  if (!Ok())
    Fail();

  switch (Peek().kind()) {
    case Token::Kind::kArrow: {
      add(methods, [&] { return ParseProtocolEvent(std::move(attributes), scope); });
      break;
    }
    case Token::Kind::kIdentifier: {
      auto identifier = ParseIdentifier();
      if (!Ok())
        break;
      if (Peek().kind() == Token::Kind::kLeftParen) {
        add(methods, [&] {
          return ParseProtocolMethod(std::move(attributes), scope, std::move(identifier));
        });
        break;
      } else if (identifier->span().data() == "compose") {
        if (attributes) {
          Fail(ErrCannotAttachAttributesToCompose);
          break;
        }
        auto protocol_name = ParseCompoundIdentifier();
        if (!Ok())
          break;
        composed_protocols->push_back(std::make_unique<raw::ComposeProtocol>(
            raw::SourceElement(identifier->start_, protocol_name->end_), std::move(protocol_name)));
        break;
      } else {
        Fail(ErrUnrecognizedProtocolMember);
        break;
      }
    }
    default:
      Fail(ErrExpectedProtocolMember);
      break;
  }
}

std::unique_ptr<raw::ProtocolDeclaration> Parser::ParseProtocolDeclaration(
    std::unique_ptr<raw::AttributeList> attributes, ASTScope& scope, const Modifiers& modifiers) {
  std::vector<std::unique_ptr<raw::ComposeProtocol>> composed_protocols;
  std::vector<std::unique_ptr<raw::ProtocolMethod>> methods;

  const auto decl_token = ConsumeToken(IdentifierOfSubkind(Token::Subkind::kProtocol));
  if (!Ok())
    return Fail();

  ValidateModifiers</* none */>(modifiers, decl_token.value());

  auto identifier = ParseIdentifier();
  if (!Ok())
    return Fail();

  ConsumeToken(OfKind(Token::Kind::kLeftCurly));
  if (!Ok())
    return Fail();

  auto parse_member = [&composed_protocols, &methods, this]() {
    if (Peek().kind() == Token::Kind::kRightCurly) {
      ConsumeToken(OfKind(Token::Kind::kRightCurly));
      return Done;
    } else {
      ParseProtocolMember(&composed_protocols, &methods);
      return More;
    }
  };

  while (parse_member() == More) {
    if (!Ok()) {
      const auto result = RecoverToEndOfMember();
      if (result == RecoverResult::Failure) {
        return Fail();
      } else if (result == RecoverResult::EndOfScope) {
        continue;
      }
    }
    ConsumeTokenOrRecover(OfKind(Token::Kind::kSemicolon));
  }
  if (!Ok())
    Fail();

  return std::make_unique<raw::ProtocolDeclaration>(
      scope.GetSourceElement(), std::move(attributes), std::move(identifier),
      std::move(composed_protocols), std::move(methods));
}

std::unique_ptr<raw::ResourceProperty> Parser::ParseResourcePropertyDeclaration() {
  ASTScope scope(this);
  auto attributes = MaybeParseAttributeList();
  if (!Ok())
    return Fail();

  // TODO(fxbug.dev/70247): remove branching
  raw::TypeConstructor type_ctor;
  std::unique_ptr<raw::Identifier> identifier;
  if (syntax_ == utils::Syntax::kNew) {
    identifier = ParseIdentifier();
    if (!Ok())
      return Fail();
    type_ctor = ParseTypeConstructor();
    if (!Ok())
      return Fail();
  } else {
    type_ctor = ParseTypeConstructor();
    if (!Ok())
      return Fail();
    identifier = ParseIdentifier();
    if (!Ok())
      return Fail();
  }

  return std::make_unique<raw::ResourceProperty>(scope.GetSourceElement(), std::move(type_ctor),
                                                 std::move(identifier), std::move(attributes));
}

std::unique_ptr<raw::ResourceDeclaration> Parser::ParseResourceDeclaration(
    std::unique_ptr<raw::AttributeList> attributes, ASTScope& scope, const Modifiers& modifiers) {
  std::vector<std::unique_ptr<raw::ResourceProperty>> properties;

  const auto decl_token = ConsumeToken(IdentifierOfSubkind(Token::Subkind::kResourceDefinition));
  if (!Ok())
    return Fail();

  ValidateModifiers</* none */>(modifiers, decl_token.value());

  auto identifier = ParseIdentifier();
  if (!Ok())
    return Fail();

  raw::TypeConstructor maybe_type_ctor;
  if (MaybeConsumeToken(OfKind(Token::Kind::kColon))) {
    // TODO(fxbug.dev/70247): remove branching
    if (syntax_ == utils::Syntax::kNew) {
      auto resource_type_identifier = ParseCompoundIdentifier();
      if (!Ok())
        return Fail();

      maybe_type_ctor = std::make_unique<raw::TypeConstructorNew>(
          scope.GetSourceElement(),
          std::make_unique<raw::NamedLayoutReference>(scope.GetSourceElement(),
                                                      std::move(resource_type_identifier)),
          /*parameters=*/nullptr,
          /*constraints=*/nullptr);
    } else {
      if (!Ok()) {
        return Fail();
      }
      maybe_type_ctor = ParseTypeConstructor();
    }
    if (!Ok())
      return Fail();
  }

  ConsumeToken(OfKind(Token::Kind::kLeftCurly));
  if (!Ok())
    return Fail();

  // Just the scaffolding of the resource here, only properties is currently accepted.
  ConsumeToken(IdentifierOfSubkind(Token::Subkind::kProperties));
  if (!Ok())
    return Fail();

  ConsumeToken(OfKind(Token::Kind::kLeftCurly));
  if (!Ok())
    return Fail();

  auto parse_prop = [&properties, this]() {
    if (Peek().kind() == Token::Kind::kRightCurly) {
      ConsumeToken(OfKind(Token::Kind::kRightCurly));
      return Done;
    } else {
      add(&properties, [&] { return ParseResourcePropertyDeclaration(); });
      return More;
    }
  };

  auto checkpoint = reporter_->Checkpoint();
  while (parse_prop() == More) {
    if (!Ok()) {
      const auto result = RecoverToEndOfMember();
      if (result == RecoverResult::Failure) {
        return Fail();
      } else if (result == RecoverResult::EndOfScope) {
        continue;
      }
    }
    ConsumeTokenOrRecover(OfKind(Token::Kind::kSemicolon));
  }
  if (!Ok())
    Fail();

  if (!checkpoint.NoNewErrors())
    return nullptr;

  if (properties.empty())
    return Fail(ErrMustHaveOneProperty);

  // End of properties block.
  ConsumeToken(OfKind(Token::Kind::kSemicolon));
  if (!Ok())
    return Fail();

  // End of resource.
  ConsumeToken(OfKind(Token::Kind::kRightCurly));
  if (!Ok())
    return Fail();

  return std::make_unique<raw::ResourceDeclaration>(
      scope.GetSourceElement(), std::move(attributes), std::move(identifier),
      std::move(maybe_type_ctor), std::move(properties));
}

std::unique_ptr<raw::ServiceMember> Parser::ParseServiceMember() {
  ASTScope scope(this);
  auto attributes = MaybeParseAttributeList();
  if (!Ok())
    return Fail();

  // TODO(fxbug.dev/70247): remove branching
  raw::TypeConstructor type_ctor;
  std::unique_ptr<raw::Identifier> identifier;
  if (syntax_ == utils::Syntax::kNew) {
    identifier = ParseIdentifier();
    if (!Ok())
      return Fail();
    type_ctor = ParseTypeConstructor();
    if (!Ok())
      return Fail();
  } else {
    type_ctor = ParseTypeConstructor();
    if (!Ok())
      return Fail();
    identifier = ParseIdentifier();
    if (!Ok())
      return Fail();
  }

  return std::make_unique<raw::ServiceMember>(scope.GetSourceElement(), std::move(type_ctor),
                                              std::move(identifier), std::move(attributes));
}

std::unique_ptr<raw::ServiceDeclaration> Parser::ParseServiceDeclaration(
    std::unique_ptr<raw::AttributeList> attributes, ASTScope& scope, const Modifiers& modifiers) {
  std::vector<std::unique_ptr<raw::ServiceMember>> members;

  const auto decl_token = ConsumeToken(IdentifierOfSubkind(Token::Subkind::kService));
  if (!Ok())
    return Fail();

  ValidateModifiers</* none */>(modifiers, decl_token.value());

  auto identifier = ParseIdentifier();
  if (!Ok())
    return Fail();
  ConsumeToken(OfKind(Token::Kind::kLeftCurly));
  if (!Ok())
    return Fail();

  auto parse_member = [&]() {
    if (Peek().kind() == Token::Kind::kRightCurly) {
      ConsumeToken(OfKind(Token::Kind::kRightCurly));
      return Done;
    } else {
      add(&members, [&] { return ParseServiceMember(); });
      return More;
    }
  };

  while (parse_member() == More) {
    if (!Ok()) {
      const auto result = RecoverToEndOfMember();
      if (result == RecoverResult::Failure) {
        return Fail();
      } else if (result == RecoverResult::EndOfScope) {
        continue;
      }
    }
    ConsumeTokenOrRecover(OfKind(Token::Kind::kSemicolon));
  }
  if (!Ok())
    Fail();

  return std::make_unique<raw::ServiceDeclaration>(scope.GetSourceElement(), std::move(attributes),
                                                   std::move(identifier), std::move(members));
}

std::unique_ptr<raw::StructMember> Parser::ParseStructMember() {
  ASTScope scope(this);
  auto attributes = MaybeParseAttributeList();
  if (!Ok())
    return Fail();
  auto type_ctor = ParseTypeConstructorOld();
  if (!Ok())
    return Fail();
  auto identifier = ParseIdentifier();
  if (!Ok())
    return Fail();

  std::unique_ptr<raw::Constant> maybe_default_value;
  if (MaybeConsumeToken(OfKind(Token::Kind::kEqual))) {
    if (!Ok())
      return Fail();
    maybe_default_value = ParseConstant();
    if (!Ok())
      return Fail();
  }

  return std::make_unique<raw::StructMember>(scope.GetSourceElement(), std::move(type_ctor),
                                             std::move(identifier), std::move(maybe_default_value),
                                             std::move(attributes));
}

std::unique_ptr<raw::StructDeclaration> Parser::ParseStructDeclaration(
    std::unique_ptr<raw::AttributeList> attributes, ASTScope& scope, const Modifiers& modifiers) {
  std::vector<std::unique_ptr<raw::StructMember>> members;

  const auto decl_token = ConsumeToken(IdentifierOfSubkind(Token::Subkind::kStruct));
  if (!Ok())
    return Fail();
  auto decl_start_token = decl_token.value();

  ValidateModifiers<types::Resourceness>(modifiers, decl_start_token);

  auto identifier = ParseIdentifier();
  if (!Ok())
    return Fail();
  ConsumeToken(OfKind(Token::Kind::kLeftCurly));
  if (!Ok())
    return Fail();

  auto parse_member = [&members, this]() {
    if (Peek().kind() == Token::Kind::kRightCurly) {
      ConsumeToken(OfKind(Token::Kind::kRightCurly));
      return Done;
    } else {
      add(&members, [&] { return ParseStructMember(); });
      return More;
    }
  };

  while (parse_member() == More) {
    if (!Ok()) {
      const auto result = RecoverToEndOfMember();
      if (result == RecoverResult::Failure) {
        return Fail();
      } else if (result == RecoverResult::EndOfScope) {
        continue;
      }
    }
    ConsumeTokenOrRecover(OfKind(Token::Kind::kSemicolon));
  }
  if (!Ok())
    return Fail();

  const auto resourceness = modifiers.resourceness.value_or(types::Resourceness::kValue);
  if (resourceness == types::Resourceness::kResource) {
    decl_start_token = modifiers.resourceness_token.value();
  }

  return std::make_unique<raw::StructDeclaration>(
      scope.GetSourceElement(), std::make_unique<Token>(decl_start_token), std::move(attributes),
      std::move(identifier), std::move(members), resourceness);
}

std::unique_ptr<raw::TableMember> Parser::ParseTableMember() {
  ASTScope scope(this);
  std::unique_ptr<raw::AttributeList> attributes = MaybeParseAttributeList();
  if (!Ok())
    return Fail();

  auto ordinal = ParseOrdinal64();
  if (!Ok())
    return Fail();

  if (MaybeConsumeToken(IdentifierOfSubkind(Token::Subkind::kReserved))) {
    if (!Ok())
      return Fail();
    if (attributes != nullptr)
      return Fail(ErrCannotAttachAttributesToReservedOrdinals);
    return std::make_unique<raw::TableMember>(scope.GetSourceElement(), std::move(ordinal));
  }

  auto type_ctor = ParseTypeConstructorOld();
  if (!Ok())
    return Fail();
  auto identifier = ParseIdentifier();
  if (!Ok())
    return Fail();

  std::unique_ptr<raw::Constant> maybe_default_value;
  if (MaybeConsumeToken(OfKind(Token::Kind::kEqual))) {
    if (!Ok())
      return Fail();
    maybe_default_value = ParseConstant();
    if (!Ok())
      return Fail();
  }

  return std::make_unique<raw::TableMember>(scope.GetSourceElement(), std::move(ordinal),
                                            std::move(type_ctor), std::move(identifier),
                                            std::move(maybe_default_value), std::move(attributes));
}

std::unique_ptr<raw::TableDeclaration> Parser::ParseTableDeclaration(
    std::unique_ptr<raw::AttributeList> attributes, ASTScope& scope, const Modifiers& modifiers) {
  std::vector<std::unique_ptr<raw::TableMember>> members;

  const auto decl_token = ConsumeToken(IdentifierOfSubkind(Token::Subkind::kTable));
  if (!Ok())
    return Fail();
  auto decl_start_token = decl_token.value();

  ValidateModifiers<types::Resourceness>(modifiers, decl_start_token);

  auto identifier = ParseIdentifier();
  if (!Ok())
    return Fail();
  ConsumeToken(OfKind(Token::Kind::kLeftCurly));
  if (!Ok())
    return Fail();

  auto parse_member = [&members, this]() {
    switch (Peek().combined()) {
      case CASE_TOKEN(Token::Kind::kRightCurly):
        ConsumeToken(OfKind(Token::Kind::kRightCurly));
        return Done;

      case CASE_TOKEN(Token::Kind::kNumericLiteral):
      TOKEN_ATTR_CASES : {
        add(&members, [&] { return ParseTableMember(); });
        return More;
      }

      default:
        Fail(ErrExpectedOrdinalOrCloseBrace, Peek());
        return Done;
    }
  };

  while (parse_member() == More) {
    if (!Ok()) {
      const auto result = RecoverToEndOfMember();
      if (result == RecoverResult::Failure) {
        return Fail();
      } else if (result == RecoverResult::EndOfScope) {
        continue;
      }
    }
    ConsumeTokenOrRecover(OfKind(Token::Kind::kSemicolon));
  }
  if (!Ok())
    Fail();

  const auto resourceness = modifiers.resourceness.value_or(types::Resourceness::kValue);
  if (resourceness == types::Resourceness::kResource) {
    decl_start_token = modifiers.resourceness_token.value();
  }

  return std::make_unique<raw::TableDeclaration>(
      scope.GetSourceElement(), std::make_unique<Token>(decl_start_token), std::move(attributes),
      std::move(identifier), std::move(members), types::Strictness::kFlexible, resourceness);
}

std::unique_ptr<raw::UnionMember> Parser::ParseUnionMember() {
  ASTScope scope(this);

  auto attributes = MaybeParseAttributeList();
  if (!Ok())
    return Fail();
  auto ordinal = ParseOrdinal64();
  if (!Ok())
    return Fail();

  if (MaybeConsumeToken(IdentifierOfSubkind(Token::Subkind::kReserved))) {
    if (!Ok())
      return Fail();
    if (attributes)
      return Fail(ErrCannotAttachAttributesToReservedOrdinals);
    return std::make_unique<raw::UnionMember>(scope.GetSourceElement(), std::move(ordinal));
  }

  auto type_ctor = ParseTypeConstructorOld();
  if (!Ok())
    return Fail();

  auto identifier = ParseIdentifier();
  if (!Ok())
    return Fail();

  std::unique_ptr<raw::Constant> maybe_default_value;
  if (MaybeConsumeToken(OfKind(Token::Kind::kEqual))) {
    if (!Ok())
      return Fail();
    maybe_default_value = ParseConstant();
    if (!Ok())
      return Fail();
  }

  return std::make_unique<raw::UnionMember>(scope.GetSourceElement(), std::move(ordinal),
                                            std::move(type_ctor), std::move(identifier),
                                            std::move(maybe_default_value), std::move(attributes));
}

std::unique_ptr<raw::UnionDeclaration> Parser::ParseUnionDeclaration(
    std::unique_ptr<raw::AttributeList> attributes, ASTScope& scope, const Modifiers& modifiers) {
  std::vector<std::unique_ptr<raw::UnionMember>> members;

  const auto decl_token = ConsumeToken(IdentifierOfSubkind(Token::Subkind::kUnion));
  if (!Ok())
    return Fail();
  auto decl_start_token = decl_token.value();

  ValidateModifiers<types::Strictness, types::Resourceness>(modifiers, decl_start_token);

  auto identifier = ParseIdentifier();
  if (!Ok())
    return Fail();

  ConsumeToken(OfKind(Token::Kind::kLeftCurly));
  if (!Ok())
    return Fail();

  bool contains_non_reserved_member = false;
  auto parse_member = [&]() {
    if (Peek().kind() == Token::Kind::kRightCurly) {
      ConsumeToken(OfKind(Token::Kind::kRightCurly));
      return Done;
    } else {
      auto member = ParseUnionMember();
      if (member) {
        members.emplace_back(std::move(member));
        if (members.back() && members.back()->maybe_used)
          contains_non_reserved_member = true;
      }
      return More;
    }
  };

  auto checkpoint = reporter_->Checkpoint();
  while (parse_member() == More) {
    if (!Ok()) {
      const auto result = RecoverToEndOfMember();
      if (result == RecoverResult::Failure) {
        return Fail();
      } else if (result == RecoverResult::EndOfScope) {
        continue;
      }
    }
    ConsumeTokenOrRecover(OfKind(Token::Kind::kSemicolon));
  }
  if (!Ok())
    return Fail();

  if (!checkpoint.NoNewErrors())
    return nullptr;

  if (!contains_non_reserved_member)
    return Fail(ErrMustHaveNonReservedMember);

  const auto resourceness = modifiers.resourceness.value_or(types::Resourceness::kValue);
  if (resourceness == types::Resourceness::kResource) {
    decl_start_token = modifiers.resourceness_token.value();
  } else if (modifiers.strictness != std::nullopt) {
    decl_start_token = modifiers.strictness_token.value();
  }

  return std::make_unique<raw::UnionDeclaration>(
      scope.GetSourceElement(), std::make_unique<Token>(decl_start_token), std::move(attributes),
      std::move(identifier), std::move(members),
      modifiers.strictness.value_or(types::Strictness::kStrict),
      modifiers.strictness != std::nullopt, resourceness);
}

std::unique_ptr<raw::File> Parser::ParseFile() {
  ASTScope scope(this);

  syntax_ = utils::Syntax::kOld;
  if (MaybeConsumeToken(IdentifierOfSubkind(Token::Subkind::kDeprecatedSyntax))) {
    ConsumeTokenOrRecover(OfKind(Token::Kind::kSemicolon));
    if (!experimental_flags_.IsFlagEnabled(ExperimentalFlags::Flag::kAllowNewSyntax)) {
      Fail(ErrRemoveSyntaxVersion);
    }
  } else if (experimental_flags_.IsFlagEnabled(ExperimentalFlags::Flag::kAllowNewSyntax)) {
    syntax_ = utils::Syntax::kNew;
  }

  auto attributes = MaybeParseAttributeList();
  if (!Ok())
    return Fail();
  ConsumeToken(IdentifierOfSubkind(Token::Subkind::kLibrary));
  if (!Ok())
    return Fail();
  auto library_name = ParseLibraryName();
  if (!Ok())
    return Fail();
  ConsumeToken(OfKind(Token::Kind::kSemicolon));
  if (!Ok())
    return Fail();

  if (syntax_ == utils::Syntax::kNew)
    return ParseFileNewSyntax(scope, std::move(attributes), std::move(library_name));

  bool done_with_library_imports = false;
  std::vector<std::unique_ptr<raw::AliasDeclaration>> alias_list;
  std::vector<std::unique_ptr<raw::Using>> using_list;
  std::vector<std::unique_ptr<raw::BitsDeclaration>> bits_declaration_list;
  std::vector<std::unique_ptr<raw::ConstDeclaration>> const_declaration_list;
  std::vector<std::unique_ptr<raw::EnumDeclaration>> enum_declaration_list;
  std::vector<std::unique_ptr<raw::ProtocolDeclaration>> protocol_declaration_list;
  std::vector<std::unique_ptr<raw::ResourceDeclaration>> resource_declaration_list;
  std::vector<std::unique_ptr<raw::ServiceDeclaration>> service_declaration_list;
  std::vector<std::unique_ptr<raw::StructDeclaration>> struct_declaration_list;
  std::vector<std::unique_ptr<raw::TableDeclaration>> table_declaration_list;
  std::vector<std::unique_ptr<raw::UnionDeclaration>> union_declaration_list;
  std::vector<std::unique_ptr<raw::TypeDecl>> type_decls;
  auto parse_declaration = [&alias_list, &bits_declaration_list, &const_declaration_list,
                            &enum_declaration_list, &protocol_declaration_list,
                            &resource_declaration_list, &service_declaration_list,
                            &struct_declaration_list, &done_with_library_imports, &using_list,
                            &table_declaration_list, &union_declaration_list, this]() {
    ASTScope scope(this);
    std::unique_ptr<raw::AttributeList> attributes = MaybeParseAttributeList();
    if (!Ok())
      return More;

    const auto modifiers = ParseModifiers();

    switch (Peek().combined()) {
      default:
        Fail(ErrExpectedDeclaration, last_token_.data());
        return More;

      case CASE_TOKEN(Token::Kind::kEndOfFile):
        return Done;

      case CASE_IDENTIFIER(Token::Subkind::kDeprecatedSyntax): {
        if (experimental_flags_.IsFlagEnabled(ExperimentalFlags::Flag::kAllowNewSyntax)) {
          Fail(ErrMisplacedSyntaxVersion);
        } else {
          Fail(ErrRemoveSyntaxVersion);
        }
        return More;
      }

      case CASE_IDENTIFIER(Token::Subkind::kAlias): {
        done_with_library_imports = true;
        add(&alias_list,
            [&] { return ParseAliasDeclaration(std::move(attributes), scope, modifiers); });
        return More;
      }

      case CASE_IDENTIFIER(Token::Subkind::kBits): {
        done_with_library_imports = true;
        add(&bits_declaration_list,
            [&] { return ParseBitsDeclaration(std::move(attributes), scope, modifiers); });
        return More;
      }

      case CASE_IDENTIFIER(Token::Subkind::kConst): {
        done_with_library_imports = true;
        add(&const_declaration_list,
            [&] { return ParseConstDeclaration(std::move(attributes), scope, modifiers); });
        return More;
      }

      case CASE_IDENTIFIER(Token::Subkind::kEnum): {
        done_with_library_imports = true;
        add(&enum_declaration_list,
            [&] { return ParseEnumDeclaration(std::move(attributes), scope, modifiers); });
        return More;
      }

      case CASE_IDENTIFIER(Token::Subkind::kProtocol): {
        done_with_library_imports = true;
        add(&protocol_declaration_list,
            [&] { return ParseProtocolDeclaration(std::move(attributes), scope, modifiers); });
        return More;
      }

      case CASE_IDENTIFIER(Token::Subkind::kResourceDefinition): {
        done_with_library_imports = true;
        add(&resource_declaration_list,
            [&] { return ParseResourceDeclaration(std::move(attributes), scope, modifiers); });
        return More;
      }

      case CASE_IDENTIFIER(Token::Subkind::kService): {
        done_with_library_imports = true;
        add(&service_declaration_list,
            [&] { return ParseServiceDeclaration(std::move(attributes), scope, modifiers); });
        return More;
      }

      case CASE_IDENTIFIER(Token::Subkind::kStruct): {
        done_with_library_imports = true;
        add(&struct_declaration_list,
            [&] { return ParseStructDeclaration(std::move(attributes), scope, modifiers); });
        return More;
      }

      case CASE_IDENTIFIER(Token::Subkind::kTable): {
        done_with_library_imports = true;
        add(&table_declaration_list,
            [&] { return ParseTableDeclaration(std::move(attributes), scope, modifiers); });
        return More;
      }

      case CASE_IDENTIFIER(Token::Subkind::kUsing): {
        auto using_decl = ParseUsing(std::move(attributes), scope, modifiers);
        if (using_decl == nullptr) {
          // Failed to parse using declaration.
          return Done;
        }
        if (using_decl->maybe_type_ctor) {
          done_with_library_imports = true;
        } else if (done_with_library_imports) {
          reporter_->Report(ErrLibraryImportsMustBeGroupedAtTopOfFile, using_decl->span());
        }
        using_list.emplace_back(std::move(using_decl));
        return More;
      }

      case CASE_IDENTIFIER(Token::Subkind::kUnion): {
        done_with_library_imports = true;
        add(&union_declaration_list,
            [&] { return ParseUnionDeclaration(std::move(attributes), scope, modifiers); });
        return More;
      }

      case CASE_IDENTIFIER(Token::Subkind::kXUnion):
        switch (modifiers.strictness.value_or(types::Strictness::kFlexible)) {
          case types::Strictness::kFlexible:
            Fail(ErrXunionDeprecated);
            return More;
          case types::Strictness::kStrict:
            Fail(ErrStrictXunionDeprecated);
            return More;
        }
    }
  };

  while (parse_declaration() == More) {
    if (!Ok()) {
      // If this returns RecoverResult::Continue, we have consumed up to a '}'
      // and expect a ';' to follow.
      auto result = RecoverToEndOfDecl();
      if (result == RecoverResult::Failure) {
        return Fail();
      } else if (result == RecoverResult::EndOfScope) {
        break;
      }
    }
    ConsumeTokenOrRecover(OfKind(Token::Kind::kSemicolon));
  }

  std::optional<Token> end = ConsumeToken(OfKind(Token::Kind::kEndOfFile));
  if (!Ok() || !end)
    return Fail();

  return std::make_unique<raw::File>(
      scope.GetSourceElement(), end.value(), std::move(attributes), std::move(library_name),
      std::move(alias_list), std::move(using_list), std::move(bits_declaration_list),
      std::move(const_declaration_list), std::move(enum_declaration_list),
      std::move(protocol_declaration_list), std::move(resource_declaration_list),
      std::move(service_declaration_list), std::move(struct_declaration_list),
      std::move(table_declaration_list), std::move(union_declaration_list), std::move(type_decls),
      std::move(comment_tokens_), fidl::utils::Syntax::kOld);
}

std::unique_ptr<raw::LayoutParameter> Parser::ParseLayoutParameter() {
  ASTScope scope(this);

  switch (Peek().combined()) {
  TOKEN_LITERAL_CASES : {
    auto literal = ParseLiteral();
    if (!Ok())
      return Fail();
    auto constant = std::make_unique<raw::LiteralConstant>(std::move(literal));
    return std::make_unique<raw::LiteralLayoutParameter>(scope.GetSourceElement(),
                                                         std::move(constant));
  }
  default: {
    auto type_ctor = ParseTypeConstructorNew();
    if (!Ok())
      return Fail();

    // For non-anonymous type constructors like "foo<T>" or "foo:optional," the presence of type
    // parameters and constraints, respectively, confirms that "foo" refers to a type reference.
    // In cases with no type parameters or constraints present (ie, just "foo"), it is impossible
    // to deduce whether "foo" refers to a type or a value.  In such cases, we must discard the
    // recently built type constructor, and convert it to a compound identifier instead.
    if (type_ctor->layout_ref->kind == raw::LayoutReference::Kind::kNamed &&
        type_ctor->parameters == nullptr && type_ctor->constraints == nullptr) {
      auto named_ref = static_cast<raw::NamedLayoutReference*>(type_ctor->layout_ref.get());
      return std::make_unique<raw::AmbiguousLayoutParameter>(scope.GetSourceElement(),
                                                             std::move(named_ref->identifier));
    }
    return std::make_unique<raw::TypeLayoutParameter>(scope.GetSourceElement(),
                                                      std::move(type_ctor));
  }
  }
}

std::unique_ptr<raw::LayoutParameterList> Parser::MaybeParseLayoutParameterList() {
  if (!MaybeConsumeToken(OfKind(Token::Kind::kLeftAngle))) {
    return nullptr;
  }

  ASTScope scope(this);
  std::vector<std::unique_ptr<raw::LayoutParameter>> params;
  for (;;) {
    params.emplace_back(ParseLayoutParameter());
    if (!Ok())
      return Fail();
    if (!MaybeConsumeToken(OfKind(Token::Kind::kComma)))
      break;
  }

  ConsumeTokenOrRecover(OfKind(Token::Kind::kRightAngle));
  return std::make_unique<raw::LayoutParameterList>(scope.GetSourceElement(), std::move(params));
}

std::unique_ptr<raw::TypeConstraints> Parser::ParseConstraints() {
  ASTScope scope(this);
  bool bracketed = false;
  std::vector<std::unique_ptr<raw::Constant>> constraints;
  if (MaybeConsumeToken(OfKind(Token::Kind::kLeftAngle))) {
    bracketed = true;
  }

  for (;;) {
    constraints.emplace_back(ParseConstant());
    if (!Ok())
      return Fail();
    if (!MaybeConsumeToken(OfKind(Token::Kind::kComma)))
      break;
  }

  if (bracketed) {
    ConsumeTokenOrRecover(OfKind(Token::Kind::kRightAngle));
    if (constraints.size() == 1) {
      Fail(ErrUnnecessaryConstraintBrackets);
    }
  } else if (constraints.size() > 1) {
    Fail(ErrMissingConstraintBrackets);
  }
  return std::make_unique<raw::TypeConstraints>(scope.GetSourceElement(), std::move(constraints));
}

std::unique_ptr<raw::LayoutMember> Parser::ParseLayoutMember(raw::LayoutMember::Kind kind) {
  ASTScope scope(this);

  // TODO(fxbug.dev/65978): Parse attributes.

  std::unique_ptr<raw::Ordinal64> ordinal = nullptr;
  if (kind == raw::LayoutMember::Kind::kOrdinaled) {
    ordinal = ParseOrdinal64();
    if (!Ok())
      return Fail();

    if (MaybeConsumeToken(IdentifierOfSubkind(Token::Subkind::kReserved))) {
      if (!Ok())
        return Fail();
      return std::make_unique<raw::OrdinaledLayoutMember>(scope.GetSourceElement(),
                                                          std::move(ordinal));
    }
  }

  auto identifier = ParseIdentifier();
  if (!Ok())
    return Fail();

  std::unique_ptr<raw::TypeConstructorNew> layout = nullptr;
  if (kind != raw::LayoutMember::Kind::kValue) {
    layout = ParseTypeConstructorNew();
    if (!Ok())
      return Fail();
  }

  // An equal sign followed by a constant (aka, a default value) is optional for
  // a struct member, but required for a value member.
  std::unique_ptr<raw::Constant> value = nullptr;
  if (kind == raw::LayoutMember::Kind::kStruct && MaybeConsumeToken(OfKind(Token::Kind::kEqual))) {
    if (!Ok())
      return Fail();
    value = ParseConstant();
    if (!Ok())
      return Fail();
  } else if (kind == raw::LayoutMember::Kind::kValue) {
    ConsumeToken(OfKind(Token::Kind::kEqual));
    if (!Ok())
      return Fail();

    value = ParseConstant();
    if (!Ok())
      return Fail();
  }

  switch (kind) {
    case raw::LayoutMember::kOrdinaled: {
      return std::make_unique<raw::OrdinaledLayoutMember>(
          scope.GetSourceElement(), std::move(ordinal), std::move(identifier), std::move(layout));
    }
    case raw::LayoutMember::kStruct: {
      return std::make_unique<raw::StructLayoutMember>(
          scope.GetSourceElement(), std::move(identifier), std::move(layout), std::move(value));
    }
    case raw::LayoutMember::kValue: {
      return std::make_unique<raw::ValueLayoutMember>(scope.GetSourceElement(),
                                                      std::move(identifier), std::move(value));
    }
  }
}

std::unique_ptr<raw::Layout> Parser::ParseLayout(
    ASTScope& scope, const Modifiers& modifiers,
    std::unique_ptr<raw::CompoundIdentifier> identifier,
    std::unique_ptr<raw::TypeConstructorNew> subtype_ctor) {
  raw::Layout::Kind kind;
  raw::LayoutMember::Kind member_kind;

  if (identifier->components.size() != 1) {
    return Fail(ErrInvalidLayoutClass);
  }

  // TODO(fxbug.dev/65978): Once fully transitioned, we will be able to
  // remove token subkinds for struct, union, table, bits, and enum. Or
  // maybe we want to have a 'recognize token subkind' on an identifier
  // instead of doing string comparison directly.
  if (identifier->components[0]->span().data() == "bits") {
    ValidateModifiers<types::Strictness>(modifiers, identifier->components[0]->start_);
    kind = raw::Layout::Kind::kBits;
    member_kind = raw::LayoutMember::Kind::kValue;
  } else if (identifier->components[0]->span().data() == "enum") {
    ValidateModifiers<types::Strictness>(modifiers, identifier->components[0]->start_);
    kind = raw::Layout::Kind::kEnum;
    member_kind = raw::LayoutMember::Kind::kValue;
  } else if (identifier->components[0]->span().data() == "struct") {
    ValidateModifiers<types::Resourceness>(modifiers, identifier->components[0]->start_);
    kind = raw::Layout::Kind::kStruct;
    member_kind = raw::LayoutMember::Kind::kStruct;
  } else if (identifier->components[0]->span().data() == "table") {
    ValidateModifiers<types::Resourceness>(modifiers, identifier->components[0]->start_);
    kind = raw::Layout::Kind::kTable;
    member_kind = raw::LayoutMember::Kind::kOrdinaled;
  } else if (identifier->components[0]->span().data() == "union") {
    ValidateModifiers<types::Strictness, types::Resourceness>(modifiers,
                                                              identifier->components[0]->start_);
    kind = raw::Layout::Kind::kUnion;
    member_kind = raw::LayoutMember::Kind::kOrdinaled;
  } else {
    return Fail(ErrInvalidLayoutClass);
  }

  ConsumeToken(OfKind(Token::Kind::kLeftCurly));
  if (!Ok())
    return Fail();

  std::vector<std::unique_ptr<raw::LayoutMember>> members;
  auto parse_member = [&]() {
    if (Peek().kind() == Token::Kind::kRightCurly) {
      ConsumeToken(OfKind(Token::Kind::kRightCurly));
      return Done;
    }
    add(&members, [&] { return ParseLayoutMember(member_kind); });
    return More;
  };

  auto checkpoint = reporter_->Checkpoint();
  while (parse_member() == More) {
    if (!Ok()) {
      const auto result = RecoverToEndOfMember();
      if (result == RecoverResult::Failure) {
        return Fail();
      }
      if (result == RecoverResult::EndOfScope) {
        continue;
      }
    }
    ConsumeTokenOrRecover(OfKind(Token::Kind::kSemicolon));
  }
  if (!Ok())
    return Fail();

  if (member_kind == raw::LayoutMember::Kind::kValue && members.empty())
    return Fail(ErrMustHaveOneMember);

  // avoid returning a "must have non reserved member" error if there was en
  // error while parsing the members
  if (!checkpoint.NoNewErrors())
    return nullptr;

  if (kind == raw::Layout::Kind::kUnion) {
    bool contains_non_reserved_member = false;
    for (const std::unique_ptr<raw::LayoutMember>& member : members) {
      assert(member->kind == raw::LayoutMember::Kind::kOrdinaled &&
             "unions should only have ordinaled members");
      const auto& union_member = static_cast<raw::OrdinaledLayoutMember*>(member.get());
      if (!union_member->reserved)
        contains_non_reserved_member = true;
    }
    if (!contains_non_reserved_member)
      return Fail(ErrMustHaveNonReservedMember);
  }

  return std::make_unique<raw::Layout>(
      scope.GetSourceElement(), kind, std::move(members), modifiers.strictness,
      modifiers.resourceness.value_or(types::Resourceness::kValue), std::move(subtype_ctor));
}

// [ name | { ... } ][ < ... > ][ : ... ]
std::unique_ptr<raw::TypeConstructorNew> Parser::ParseTypeConstructorNew() {
  ASTScope scope(this);
  const auto modifiers = ParseModifiers();
  auto identifier = ParseCompoundIdentifier();
  if (!Ok())
    return Fail();

  std::unique_ptr<raw::LayoutReference> layout_ref;
  switch (Peek().kind()) {
    case Token::Kind::kLeftCurly: {
      auto layout = ParseLayout(scope, modifiers, std::move(identifier), /*subtype_ctor=*/nullptr);
      layout_ref =
          std::make_unique<raw::InlineLayoutReference>(scope.GetSourceElement(), std::move(layout));
      break;
    }
    case Token::Kind::kColon: {
      // The colon case is ambiguous. Consider the following two examples:
      //
      //   type A = enum : foo { BAR = 1; };
      //   type B = enum : foo;
      //
      // When the parser encounters the colon in each case, it has no idea
      // whether the value immediately after it should be interpreted as the
      // wrapped type in an inline layout of kind enum, or otherwise as the only
      // constraint on a named layout called "enum."
      //
      // To resolve this confusion, we parse the token after the colon as a
      // constant, then check to see if the token after that is a left curly
      // brace. If it is, we assume that this is in fact the inline layout case
      // ("type A"). If it is not, we assume that it is a named layout with
      // constraints ("type B").
      ASTScope after_colon_scope(this);
      ConsumeToken(OfKind(Token::Kind::kColon));
      if (!Ok())
        return Fail();

      // If the token after the colon is the opener to a constraints list, we
      // know for sure that the identifier before the colon must be a
      // NamedLayoutReference, so none of the other checks in this case are
      // required.
      if (Peek().kind() == Token::Kind::kLeftAngle) {
        layout_ref = std::make_unique<raw::NamedLayoutReference>(scope.GetSourceElement(),
                                                                 std::move(identifier));
        break;
      }

      std::unique_ptr<raw::Constant> constraint_or_subtype = ParseConstant();
      if (!Ok())
        return Fail();

      // If the token after the constant is not an open brace, this was actually
      // a one-entry constraints block the whole time, so it should be parsed as
      // such.
      if (Peek().kind() != Token::Kind::kLeftCurly) {
        layout_ref = std::make_unique<raw::NamedLayoutReference>(scope.GetSourceElement(),
                                                                 std::move(identifier));
        std::vector<std::unique_ptr<raw::Constant>> components;
        components.emplace_back(std::move(constraint_or_subtype));
        auto constraints = std::make_unique<raw::TypeConstraints>(
            after_colon_scope.GetSourceElement(), std::move(components));
        return std::make_unique<raw::TypeConstructorNew>(
            scope.GetSourceElement(), std::move(layout_ref), nullptr, std::move(constraints));
      }

      // The token we just parsed as a constant is in fact a layout subtype.
      // Coerce it into that class, then build the layout_ref.
      if (constraint_or_subtype->kind != raw::Constant::Kind::kIdentifier) {
        return Fail(ErrInvalidWrappedType);
      }

      auto subtype_element =
          raw::SourceElement(constraint_or_subtype->start_, constraint_or_subtype->end_);
      auto subtype_constant = static_cast<raw::IdentifierConstant*>(constraint_or_subtype.get());
      auto subtype_ref = std::make_unique<raw::NamedLayoutReference>(
          subtype_element, std::move(subtype_constant->identifier));
      auto subtype_ctor = std::make_unique<raw::TypeConstructorNew>(
          subtype_element, std::move(subtype_ref), /*parameters=*/nullptr, /*constraints=*/nullptr);
      auto layout = ParseLayout(scope, modifiers, std::move(identifier), std::move(subtype_ctor));
      layout_ref =
          std::make_unique<raw::InlineLayoutReference>(scope.GetSourceElement(), std::move(layout));
      break;
    }
    default: {
      ValidateModifiers</* none */>(modifiers, identifier->start_);
      layout_ref = std::make_unique<raw::NamedLayoutReference>(scope.GetSourceElement(),
                                                               std::move(identifier));
    }
  }

  std::unique_ptr<raw::LayoutParameterList> parameters;
  if (previous_token_.kind() != Token::Kind::kColon) {
    parameters = MaybeParseLayoutParameterList();
    if (!Ok())
      return Fail();
  }

  std::unique_ptr<raw::TypeConstraints> constraints;
  MaybeConsumeToken(OfKind(Token::Kind::kColon));
  if (previous_token_.kind() == Token::Kind::kColon) {
    constraints = ParseConstraints();
    if (!Ok())
      return Fail();
  }

  return std::make_unique<raw::TypeConstructorNew>(scope.GetSourceElement(), std::move(layout_ref),
                                                   std::move(parameters), std::move(constraints));
}

raw::TypeConstructor Parser::ParseTypeConstructor() {
  if (syntax_ == fidl::utils::Syntax::kNew)
    return ParseTypeConstructorNew();
  return ParseTypeConstructorOld();
}

std::unique_ptr<raw::TypeDecl> Parser::ParseTypeDecl(ASTScope& scope) {
  ConsumeToken(IdentifierOfSubkind(Token::Subkind::kType));
  assert(Ok() && "caller should check first token");

  auto identifier = ParseIdentifier();
  if (!Ok())
    return Fail();

  ConsumeToken(OfKind(Token::Kind::kEqual));
  if (!Ok())
    return Fail();

  auto layout = ParseTypeConstructorNew();
  if (!Ok())
    return Fail();

  return std::make_unique<raw::TypeDecl>(scope.GetSourceElement(), std::move(identifier),
                                         std::move(layout));
}

std::unique_ptr<raw::File> Parser::ParseFileNewSyntax(
    ASTScope& scope, std::unique_ptr<raw::AttributeList> library_attributes,
    std::unique_ptr<raw::CompoundIdentifier> library_name) {
  std::vector<std::unique_ptr<raw::AliasDeclaration>> alias_list;
  std::vector<std::unique_ptr<raw::Using>> using_list;
  std::vector<std::unique_ptr<raw::BitsDeclaration>> bits_declaration_list;
  std::vector<std::unique_ptr<raw::ConstDeclaration>> const_declaration_list;
  std::vector<std::unique_ptr<raw::EnumDeclaration>> enum_declaration_list;
  std::vector<std::unique_ptr<raw::ProtocolDeclaration>> protocol_declaration_list;
  std::vector<std::unique_ptr<raw::ResourceDeclaration>> resource_declaration_list;
  std::vector<std::unique_ptr<raw::ServiceDeclaration>> service_declaration_list;
  std::vector<std::unique_ptr<raw::StructDeclaration>> struct_declaration_list;
  std::vector<std::unique_ptr<raw::TableDeclaration>> table_declaration_list;
  std::vector<std::unique_ptr<raw::UnionDeclaration>> union_declaration_list;
  std::vector<std::unique_ptr<raw::TypeDecl>> type_decls;

  bool done_with_library_imports = false;
  auto parse_declaration = [&]() {
    // TODO(fxbug.dev/70247): Once we're fully on the new syntax, we should refactor all of the
    //  top-level "Parse..." methods to omit their externally defined ASTScope parameter.  This was
    //  necessary when top-level definitions could begin with modifiers (ex: "strict struct S {...")
    //  which is no longer possible in the new syntax.
    ASTScope scope(this);
    std::unique_ptr<raw::AttributeList> attributes = MaybeParseAttributeList();
    if (!Ok())
      return More;

    switch (Peek().combined()) {
      default:
        Fail(ErrExpectedDeclaration, last_token_.data());
        return More;

      case CASE_TOKEN(Token::Kind::kEndOfFile):
        return Done;

      case CASE_IDENTIFIER(Token::Subkind::kDeprecatedSyntax): {
        Fail(ErrMisplacedSyntaxVersion);
        return More;
      }

      case CASE_IDENTIFIER(Token::Subkind::kAlias): {
        done_with_library_imports = true;
        add(&alias_list,
            [&] { return ParseAliasDeclaration(std::move(attributes), scope, Modifiers()); });
        return More;
      }

      case CASE_IDENTIFIER(Token::Subkind::kConst): {
        done_with_library_imports = true;
        add(&const_declaration_list,
            [&] { return ParseConstDeclaration(std::move(attributes), scope, Modifiers()); });
        return More;
      }

      case CASE_IDENTIFIER(Token::Subkind::kType): {
        done_with_library_imports = true;
        add(&type_decls, [&] { return ParseTypeDecl(scope); });
        return More;
      }

      case CASE_IDENTIFIER(Token::Subkind::kProtocol): {
        done_with_library_imports = true;
        add(&protocol_declaration_list,
            [&] { return ParseProtocolDeclaration(std::move(attributes), scope, Modifiers()); });
        return More;
      }

      case CASE_IDENTIFIER(Token::Subkind::kResourceDefinition): {
        done_with_library_imports = true;
        add(&resource_declaration_list,
            [&] { return ParseResourceDeclaration(std::move(attributes), scope, Modifiers()); });
        return More;
      }

      case CASE_IDENTIFIER(Token::Subkind::kService): {
        done_with_library_imports = true;
        add(&service_declaration_list,
            [&] { return ParseServiceDeclaration(std::move(attributes), scope, Modifiers()); });
        return More;
      }

      case CASE_IDENTIFIER(Token::Subkind::kUsing): {
        add(&using_list, [&] { return ParseUsing(std::move(attributes), scope, Modifiers()); });
        if (Ok() && done_with_library_imports) {
          reporter_->Report(diagnostics::ErrLibraryImportsMustBeGroupedAtTopOfFile,
                            using_list.back()->span());
        }
        return More;
      }
    }
  };

  while (parse_declaration() == More) {
    if (!Ok()) {
      // If this returns RecoverResult::Continue, we have consumed up to a '}'
      // and expect a ';' to follow.
      auto result = RecoverToEndOfDecl();
      if (result == RecoverResult::Failure) {
        return Fail();
      } else if (result == RecoverResult::EndOfScope) {
        break;
      }
    }
    ConsumeTokenOrRecover(OfKind(Token::Kind::kSemicolon));
  }

  std::optional<Token> end = ConsumeToken(OfKind(Token::Kind::kEndOfFile));
  if (!Ok() || !end)
    return Fail();

  return std::make_unique<raw::File>(
      scope.GetSourceElement(), end.value(), std::move(library_attributes), std::move(library_name),
      std::move(alias_list), std::move(using_list), std::move(bits_declaration_list),
      std::move(const_declaration_list), std::move(enum_declaration_list),
      std::move(protocol_declaration_list), std::move(resource_declaration_list),
      std::move(service_declaration_list), std::move(struct_declaration_list),
      std::move(table_declaration_list), std::move(union_declaration_list), std::move(type_decls),
      std::move(comment_tokens_), fidl::utils::Syntax::kNew);
}

bool Parser::ConsumeTokensUntil(std::set<Token::Kind> exit_tokens) {
  auto p = [&](Token::KindAndSubkind token) -> std::unique_ptr<Diagnostic> {
    for (const auto& exit_token : exit_tokens) {
      if (token.kind() == exit_token)
        // signal to ReadToken to stop by returning an error
        return Reporter::MakeError(ErrUnexpectedToken);
    }
    // nullptr return value indicates -> yes, consume to ReadToken
    return nullptr;
  };

  // Consume tokens until we find a synchronization point
  while (ReadToken(p, OnNoMatch::kIgnore) != std::nullopt) {
    if (!Ok())
      return false;
  }
  return true;
}

Parser::RecoverResult Parser::RecoverToEndOfDecl() {
  if (ConsumedEOF()) {
    return RecoverResult::Failure;
  }

  RecoverAllErrors();

  static const auto exit_tokens = std::set<Token::Kind>{
      Token::Kind::kRightCurly,
      Token::Kind::kEndOfFile,
  };
  if (!ConsumeTokensUntil(exit_tokens)) {
    return RecoverResult::Failure;
  }

  switch (Peek().combined()) {
    case CASE_TOKEN(Token::Kind::kRightCurly):
      ConsumeToken(OfKind(Token::Kind::kRightCurly));
      if (!Ok())
        return RecoverResult::Failure;
      return RecoverResult::Continue;
    case CASE_TOKEN(Token::Kind::kEndOfFile):
      return RecoverResult::EndOfScope;
    default:
      return RecoverResult::Failure;
  }
}

Parser::RecoverResult Parser::RecoverToEndOfMember() {
  if (ConsumedEOF()) {
    return RecoverResult::Failure;
  }

  RecoverAllErrors();

  static const auto exit_tokens = std::set<Token::Kind>{
      Token::Kind::kSemicolon,
      Token::Kind::kRightCurly,
      Token::Kind::kEndOfFile,
  };
  if (!ConsumeTokensUntil(exit_tokens)) {
    return RecoverResult::Failure;
  }

  switch (Peek().combined()) {
    case CASE_TOKEN(Token::Kind::kSemicolon):
      return RecoverResult::Continue;
    case CASE_TOKEN(Token::Kind::kRightCurly):
      return RecoverResult::EndOfScope;
    default:
      return RecoverResult::Failure;
  }
}

template <Token::Kind ClosingToken>
Parser::RecoverResult Parser::RecoverToEndOfListItem() {
  if (ConsumedEOF()) {
    return RecoverResult::Failure;
  }

  RecoverAllErrors();

  static const auto exit_tokens = std::set<Token::Kind>{
      Token::Kind::kComma,
      Token::Kind::kSemicolon,
      Token::Kind::kRightCurly,
      Token::Kind::kEndOfFile,
      ClosingToken,
  };
  if (!ConsumeTokensUntil(exit_tokens)) {
    return RecoverResult::Failure;
  }

  switch (Peek().combined()) {
    case CASE_TOKEN(Token::Kind::kComma):
      return RecoverResult::Continue;
    case CASE_TOKEN(ClosingToken):
      return RecoverResult::EndOfScope;
    default:
      return RecoverResult::Failure;
  }
}

Parser::RecoverResult Parser::RecoverToEndOfParam() {
  return RecoverToEndOfListItem<Token::Kind::kRightParen>();
}

}  // namespace fidl
