//===-- lib/Parser/basic-parsers.h ------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef FORTRAN_PARSER_BASIC_PARSERS_H_
#define FORTRAN_PARSER_BASIC_PARSERS_H_

// Let a "parser" be an instance of any class that supports this
// type definition and member (or static) function:
//
//   using resultType = ...;
//   std::optional<resultType> Parse(ParseState &) const;
//
// which either returns a value to signify a successful recognition or else
// returns {} to signify failure.  On failure, the state cannot be assumed
// to still be valid, in general -- see below for exceptions.
//
// This header defines the fundamental parser class templates and helper
// template functions.  See parser-combinators.txt for documentation.

#include "flang/Common/Fortran-features.h"
#include "flang/Common/idioms.h"
#include "flang/Common/indirection.h"
#include "flang/Parser/char-block.h"
#include "flang/Parser/message.h"
#include "flang/Parser/parse-state.h"
#include "flang/Parser/provenance.h"
#include "flang/Parser/user-state.h"
#include <cstring>
#include <functional>
#include <list>
#include <memory>
#include <optional>
#include <string>
#include <tuple>
#include <type_traits>
#include <utility>

namespace Fortran::parser {

// fail<A>("..."_err_en_US) returns a parser that never succeeds.  It reports an
// error message at the current position.  The result type is unused,
// but might have to be specified at the point of call to satisfy
// the type checker.  The state remains valid.
template <typename A> class FailParser {
public:
  using resultType = A;
  constexpr FailParser(const FailParser &) = default;
  constexpr explicit FailParser(MessageFixedText t) : text_{t} {}
  std::optional<A> Parse(ParseState &state) const {
    state.Say(text_);
    return std::nullopt;
  }

private:
  const MessageFixedText text_;
};

template <typename A = Success> inline constexpr auto fail(MessageFixedText t) {
  return FailParser<A>{t};
}

// pure(x) returns a parser that always succeeds, does not advance the
// parse, and returns a captured value x whose type must be copy-constructible.
//
// pure<A>() is essentially pure(A{}); it returns a default-constructed A{},
// and works even when A is not copy-constructible.
template <typename A> class PureParser {
public:
  using resultType = A;
  constexpr PureParser(const PureParser &) = default;
  constexpr explicit PureParser(A &&x) : value_(std::move(x)) {}
  std::optional<A> Parse(ParseState &) const { return value_; }

private:
  const A value_;
};

template <typename A> inline constexpr auto pure(A x) {
  return PureParser<A>(std::move(x));
}

template <typename A> class PureDefaultParser {
public:
  using resultType = A;
  constexpr PureDefaultParser(const PureDefaultParser &) = default;
  constexpr PureDefaultParser() {}
  std::optional<A> Parse(ParseState &) const { return std::make_optional<A>(); }
};

template <typename A> inline constexpr auto pure() {
  return PureDefaultParser<A>();
}

// If a is a parser, attempt(a) is the same parser, but on failure
// the ParseState is guaranteed to have been restored to its initial value.
template <typename A> class BacktrackingParser {
public:
  using resultType = typename A::resultType;
  constexpr BacktrackingParser(const BacktrackingParser &) = default;
  constexpr BacktrackingParser(const A &parser) : parser_{parser} {}
  std::optional<resultType> Parse(ParseState &state) const {
    Messages messages{std::move(state.messages())};
    ParseState backtrack{state};
    std::optional<resultType> result{parser_.Parse(state)};
    if (result) {
      state.messages().Restore(std::move(messages));
    } else {
      state = std::move(backtrack);
      state.messages() = std::move(messages);
    }
    return result;
  }

private:
  const A parser_;
};

template <typename A> inline constexpr auto attempt(const A &parser) {
  return BacktrackingParser<A>{parser};
}

// For any parser x, the parser returned by !x is one that succeeds when
// x fails, returning a useless (but present) result.  !x fails when x succeeds.
template <typename PA> class NegatedParser {
public:
  using resultType = Success;
  constexpr NegatedParser(const NegatedParser &) = default;
  constexpr NegatedParser(PA p) : parser_{p} {}
  std::optional<Success> Parse(ParseState &state) const {
    ParseState forked{state};
    forked.set_deferMessages(true);
    if (parser_.Parse(forked)) {
      return std::nullopt;
    }
    return Success{};
  }

private:
  const PA parser_;
};

template <typename PA, typename = typename PA::resultType>
constexpr auto operator!(PA p) {
  return NegatedParser<PA>(p);
}

// For any parser x, the parser returned by lookAhead(x) is one that succeeds
// or fails if x does, but the state is not modified.
template <typename PA> class LookAheadParser {
public:
  using resultType = Success;
  constexpr LookAheadParser(const LookAheadParser &) = default;
  constexpr LookAheadParser(PA p) : parser_{p} {}
  std::optional<Success> Parse(ParseState &state) const {
    ParseState forked{state};
    forked.set_deferMessages(true);
    if (parser_.Parse(forked)) {
      return Success{};
    }
    return std::nullopt;
  }

private:
  const PA parser_;
};

template <typename PA> inline constexpr auto lookAhead(PA p) {
  return LookAheadParser<PA>{p};
}

// If a is a parser, inContext("..."_en_US, a) runs it in a nested message
// context.
template <typename PA> class MessageContextParser {
public:
  using resultType = typename PA::resultType;
  constexpr MessageContextParser(const MessageContextParser &) = default;
  constexpr MessageContextParser(MessageFixedText t, PA p)
      : text_{t}, parser_{p} {}
  std::optional<resultType> Parse(ParseState &state) const {
    state.PushContext(text_);
    std::optional<resultType> result{parser_.Parse(state)};
    state.PopContext();
    return result;
  }

private:
  const MessageFixedText text_;
  const PA parser_;
};

template <typename PA>
inline constexpr auto inContext(MessageFixedText context, PA parser) {
  return MessageContextParser{context, parser};
}

// If a is a parser, withMessage("..."_en_US, a) runs it unchanged if it
// succeeds, and overrides its messages with a specific one if it fails and
// has matched no tokens.
template <typename PA> class WithMessageParser {
public:
  using resultType = typename PA::resultType;
  constexpr WithMessageParser(const WithMessageParser &) = default;
  constexpr WithMessageParser(MessageFixedText t, PA p)
      : text_{t}, parser_{p} {}
  std::optional<resultType> Parse(ParseState &state) const {
    Messages messages{std::move(state.messages())};
    ParseState backtrack{state};
    state.set_anyTokenMatched(false);
    std::optional<resultType> result{parser_.Parse(state)};
    bool emitMessage{false};
    if (result) {
      messages.Annex(std::move(state.messages()));
      if (backtrack.anyTokenMatched()) {
        state.set_anyTokenMatched();
      }
    } else if (state.anyTokenMatched()) {
      emitMessage = state.messages().empty();
      messages.Annex(std::move(state.messages()));
      backtrack.set_anyTokenMatched();
      if (state.anyDeferredMessages()) {
        backtrack.set_anyDeferredMessages(true);
      }
      state = std::move(backtrack);
    } else {
      emitMessage = true;
    }
    state.messages() = std::move(messages);
    if (emitMessage) {
      state.Say(text_);
    }
    return result;
  }

private:
  const MessageFixedText text_;
  const PA parser_;
};

template <typename PA>
inline constexpr auto withMessage(MessageFixedText msg, PA parser) {
  return WithMessageParser{msg, parser};
}

// If a and b are parsers, then a >> b returns a parser that succeeds when
// b succeeds after a does so, but fails when either a or b does.  The
// result is taken from b.  Similarly, a / b also succeeds if both a and b
// do so, but the result is that returned by a.
template <typename PA, typename PB> class SequenceParser {
public:
  using resultType = typename PB::resultType;
  constexpr SequenceParser(const SequenceParser &) = default;
  constexpr SequenceParser(PA pa, PB pb) : pa_{pa}, pb2_{pb} {}
  std::optional<resultType> Parse(ParseState &state) const {
    if (pa_.Parse(state)) {
      return pb2_.Parse(state);
    } else {
      return std::nullopt;
    }
  }

private:
  const PA pa_;
  const PB pb2_;
};

template <typename PA, typename PB>
inline constexpr auto operator>>(PA pa, PB pb) {
  return SequenceParser<PA, PB>{pa, pb};
}

template <typename PA, typename PB> class FollowParser {
public:
  using resultType = typename PA::resultType;
  constexpr FollowParser(const FollowParser &) = default;
  constexpr FollowParser(PA pa, PB pb) : pa_{pa}, pb_{pb} {}
  std::optional<resultType> Parse(ParseState &state) const {
    if (std::optional<resultType> ax{pa_.Parse(state)}) {
      if (pb_.Parse(state)) {
        return ax;
      }
    }
    return std::nullopt;
  }

private:
  const PA pa_;
  const PB pb_;
};

template <typename PA, typename PB>
inline constexpr auto operator/(PA pa, PB pb) {
  return FollowParser<PA, PB>{pa, pb};
}

template <typename PA, typename... Ps> class AlternativesParser {
public:
  using resultType = typename PA::resultType;
  constexpr AlternativesParser(PA pa, Ps... ps) : ps_{pa, ps...} {}
  constexpr AlternativesParser(const AlternativesParser &) = default;
  std::optional<resultType> Parse(ParseState &state) const {
    Messages messages{std::move(state.messages())};
    ParseState backtrack{state};
    std::optional<resultType> result{std::get<0>(ps_).Parse(state)};
    if constexpr (sizeof...(Ps) > 0) {
      if (!result) {
        ParseRest<1>(result, state, backtrack);
      }
    }
    state.messages().Restore(std::move(messages));
    return result;
  }

private:
  template <int J>
  void ParseRest(std::optional<resultType> &result, ParseState &state,
      ParseState &backtrack) const {
    ParseState prevState{std::move(state)};
    state = backtrack;
    result = std::get<J>(ps_).Parse(state);
    if (!result) {
      state.CombineFailedParses(std::move(prevState));
      if constexpr (J < sizeof...(Ps)) {
        ParseRest<J + 1>(result, state, backtrack);
      }
    }
  }

  const std::tuple<PA, Ps...> ps_;
};

template <typename... Ps> inline constexpr auto first(Ps... ps) {
  return AlternativesParser<Ps...>{ps...};
}

template <typename PA, typename PB>
inline constexpr auto operator||(PA pa, PB pb) {
  return AlternativesParser<PA, PB>{pa, pb};
}

// If a and b are parsers, then recovery(a,b) returns a parser that succeeds if
// a does so, or if a fails and b succeeds.  If a succeeds, b is not attempted.
// All messages from the first parse are retained.
// The two parsers must return values of the same type.
template <typename PA, typename PB> class RecoveryParser {
public:
  using resultType = typename PA::resultType;
  static_assert(std::is_same_v<resultType, typename PB::resultType>);
  constexpr RecoveryParser(const RecoveryParser &) = default;
  constexpr RecoveryParser(PA pa, PB pb) : pa_{pa}, pb3_{pb} {}
  std::optional<resultType> Parse(ParseState &state) const {
    bool originallyDeferred{state.deferMessages()};
    ParseState backtrack{state};
    if (!originallyDeferred && state.messages().empty() &&
        !state.anyErrorRecovery()) {
      // Fast path.  There are no messages or recovered errors in the incoming
      // state.  Attempt to parse with messages deferred, expecting that the
      // parse will succeed silently.
      state.set_deferMessages(true);
      if (std::optional<resultType> ax{pa_.Parse(state)}) {
        if (!state.anyDeferredMessages() && !state.anyErrorRecovery()) {
          state.set_deferMessages(false);
          return ax;
        }
      }
      state = backtrack;
    }
    Messages messages{std::move(state.messages())};
    if (std::optional<resultType> ax{pa_.Parse(state)}) {
      state.messages().Restore(std::move(messages));
      return ax;
    }
    messages.Annex(std::move(state.messages()));
    bool hadDeferredMessages{state.anyDeferredMessages()};
    bool anyTokenMatched{state.anyTokenMatched()};
    state = std::move(backtrack);
    state.set_deferMessages(true);
    std::optional<resultType> bx{pb3_.Parse(state)};
    state.messages() = std::move(messages);
    state.set_deferMessages(originallyDeferred);
    if (anyTokenMatched) {
      state.set_anyTokenMatched();
    }
    if (hadDeferredMessages) {
      state.set_anyDeferredMessages();
    }
    if (bx) {
      // Error recovery situations must also produce messages.
      CHECK(state.anyDeferredMessages() || state.messages().AnyFatalError());
      state.set_anyErrorRecovery();
    }
    return bx;
  }

private:
  const PA pa_;
  const PB pb3_;
};

template <typename PA, typename PB>
inline constexpr auto recovery(PA pa, PB pb) {
  return RecoveryParser<PA, PB>{pa, pb};
}

// If x is a parser, then many(x) returns a parser that always succeeds
// and whose value is a list, possibly empty, of the values returned from
// repeated application of x until it fails or does not advance the parse.
template <typename PA> class ManyParser {
  using paType = typename PA::resultType;

public:
  using resultType = std::list<paType>;
  constexpr ManyParser(const ManyParser &) = default;
  constexpr ManyParser(PA parser) : parser_{parser} {}
  std::optional<resultType> Parse(ParseState &state) const {
    resultType result;
    auto at{state.GetLocation()};
    while (std::optional<paType> x{parser_.Parse(state)}) {
      result.emplace_back(std::move(*x));
      if (state.GetLocation() <= at) {
        break; // no forward progress, don't loop
      }
      at = state.GetLocation();
    }
    return {std::move(result)};
  }

private:
  const BacktrackingParser<PA> parser_;
};

template <typename PA> inline constexpr auto many(PA parser) {
  return ManyParser<PA>{parser};
}

// If x is a parser, then some(x) returns a parser that succeeds if x does
// and whose value is a nonempty list of the values returned from repeated
// application of x until it fails or does not advance the parse.  In other
// words, some(x) is a variant of many(x) that has to succeed at least once.
template <typename PA> class SomeParser {
  using paType = typename PA::resultType;

public:
  using resultType = std::list<paType>;
  constexpr SomeParser(const SomeParser &) = default;
  constexpr SomeParser(PA parser) : parser_{parser} {}
  std::optional<resultType> Parse(ParseState &state) const {
    auto start{state.GetLocation()};
    if (std::optional<paType> first{parser_.Parse(state)}) {
      resultType result;
      result.emplace_back(std::move(*first));
      if (state.GetLocation() > start) {
        result.splice(result.end(), many(parser_).Parse(state).value());
      }
      return {std::move(result)};
    }
    return std::nullopt;
  }

private:
  const PA parser_;
};

template <typename PA> inline constexpr auto some(PA parser) {
  return SomeParser<PA>{parser};
}

// If x is a parser, skipMany(x) is equivalent to many(x) but with no result.
template <typename PA> class SkipManyParser {
public:
  using resultType = Success;
  constexpr SkipManyParser(const SkipManyParser &) = default;
  constexpr SkipManyParser(PA parser) : parser_{parser} {}
  std::optional<Success> Parse(ParseState &state) const {
    for (auto at{state.GetLocation()};
         parser_.Parse(state) && state.GetLocation() > at;
         at = state.GetLocation()) {
    }
    return Success{};
  }

private:
  const BacktrackingParser<PA> parser_;
};

template <typename PA> inline constexpr auto skipMany(PA parser) {
  return SkipManyParser<PA>{parser};
}

// If x is a parser, skipManyFast(x) is equivalent to skipMany(x).
// The parser x must always advance on success and never invalidate the
// state on failure.
template <typename PA> class SkipManyFastParser {
public:
  using resultType = Success;
  constexpr SkipManyFastParser(const SkipManyFastParser &) = default;
  constexpr SkipManyFastParser(PA parser) : parser_{parser} {}
  std::optional<Success> Parse(ParseState &state) const {
    while (parser_.Parse(state)) {
    }
    return Success{};
  }

private:
  const PA parser_;
};

template <typename PA> inline constexpr auto skipManyFast(PA parser) {
  return SkipManyFastParser<PA>{parser};
}

// If x is a parser returning some type A, then maybe(x) returns a
// parser that returns std::optional<A>, always succeeding.
template <typename PA> class MaybeParser {
  using paType = typename PA::resultType;

public:
  using resultType = std::optional<paType>;
  constexpr MaybeParser(const MaybeParser &) = default;
  constexpr MaybeParser(PA parser) : parser_{parser} {}
  std::optional<resultType> Parse(ParseState &state) const {
    if (resultType result{parser_.Parse(state)}) {
      // permit optional<optional<...>>
      return {std::move(result)};
    }
    return resultType{};
  }

private:
  const BacktrackingParser<PA> parser_;
};

template <typename PA> inline constexpr auto maybe(PA parser) {
  return MaybeParser<PA>{parser};
}

// If x is a parser, then defaulted(x) returns a parser that always
// succeeds.  When x succeeds, its result is that of x; otherwise, its
// result is a default-constructed value of x's result type.
template <typename PA> class DefaultedParser {
public:
  using resultType = typename PA::resultType;
  constexpr DefaultedParser(const DefaultedParser &) = default;
  constexpr DefaultedParser(PA p) : parser_{p} {}
  std::optional<resultType> Parse(ParseState &state) const {
    std::optional<std::optional<resultType>> ax{maybe(parser_).Parse(state)};
    if (ax.value()) { // maybe() always succeeds
      return std::move(*ax);
    }
    return resultType{};
  }

private:
  const BacktrackingParser<PA> parser_;
};

template <typename PA> inline constexpr auto defaulted(PA p) {
  return DefaultedParser<PA>(p);
}

// If a is a parser, and f is a function mapping an rvalue of a's result type
// to some other type T, then applyFunction(f, a) returns a parser that succeeds
// iff a does, and whose result value ax has been passed through the function;
// the final result is that returned by the call f(std::move(ax)).
//
// Function application is generalized to functions with more than one
// argument with applyFunction(f, a, b, ...) succeeding if all of the parsers
// a, b, &c. do so, and the result is the value of applying f to their
// results.
//
// applyLambda(f, ...) is the same concept extended to std::function<> functors.
// It is not constexpr.
//
// Member function application is supported by applyMem(f, a).  If the
// parser a succeeds and returns some value ax, the result is that returned
// by ax.f().  Additional parser arguments can be specified to supply their
// results to the member function call, so applyMem(f, a, b) succeeds if
// both a and b do so and returns the result of calling ax.f(std::move(bx)).

// Runs a sequence of parsers until one fails or all have succeeded.
// Collects their results in a std::tuple<std::optional<>...>.
template <typename... PARSER>
using ApplyArgs = std::tuple<std::optional<typename PARSER::resultType>...>;

template <typename... PARSER, std::size_t... J>
inline bool ApplyHelperArgs(const std::tuple<PARSER...> &parsers,
    ApplyArgs<PARSER...> &args, ParseState &state, std::index_sequence<J...>) {
  return (... &&
      (std::get<J>(args) = std::get<J>(parsers).Parse(state),
          std::get<J>(args).has_value()));
}

// Applies a function to the arguments collected by ApplyHelperArgs.
template <typename RESULT, typename... PARSER>
using ApplicableFunctionPointer = RESULT (*)(typename PARSER::resultType &&...);
template <typename RESULT, typename... PARSER>
using ApplicableFunctionObject =
    const std::function<RESULT(typename PARSER::resultType &&...)> &;

template <template <typename...> class FUNCTION, typename RESULT,
    typename... PARSER, std::size_t... J>
inline RESULT ApplyHelperFunction(FUNCTION<RESULT, PARSER...> f,
    ApplyArgs<PARSER...> &&args, std::index_sequence<J...>) {
  return f(std::move(*std::get<J>(args))...);
}

template <template <typename...> class FUNCTION, typename RESULT,
    typename... PARSER>
class ApplyFunction {
  using funcType = FUNCTION<RESULT, PARSER...>;

public:
  using resultType = RESULT;
  constexpr ApplyFunction(const ApplyFunction &) = default;
  constexpr ApplyFunction(funcType f, PARSER... p)
      : function_{f}, parsers_{p...} {}
  std::optional<resultType> Parse(ParseState &state) const {
    ApplyArgs<PARSER...> results;
    using Sequence = std::index_sequence_for<PARSER...>;
    if (ApplyHelperArgs(parsers_, results, state, Sequence{})) {
      return ApplyHelperFunction<FUNCTION, RESULT, PARSER...>(
          function_, std::move(results), Sequence{});
    } else {
      return std::nullopt;
    }
  }

private:
  const funcType function_;
  const std::tuple<PARSER...> parsers_;
};

template <typename RESULT, typename... PARSER>
inline constexpr auto applyFunction(
    ApplicableFunctionPointer<RESULT, PARSER...> f, const PARSER &... parser) {
  return ApplyFunction<ApplicableFunctionPointer, RESULT, PARSER...>{
      f, parser...};
}

template <typename RESULT, typename... PARSER>
inline /* not constexpr */ auto applyLambda(
    ApplicableFunctionObject<RESULT, PARSER...> f, const PARSER &... parser) {
  return ApplyFunction<ApplicableFunctionObject, RESULT, PARSER...>{
      f, parser...};
}

// Member function application
template <typename OBJPARSER, typename... PARSER> class AMFPHelper {
  using resultType = typename OBJPARSER::resultType;

public:
  using type = void (resultType::*)(typename PARSER::resultType &&...);
};
template <typename OBJPARSER, typename... PARSER>
using ApplicableMemberFunctionPointer =
    typename AMFPHelper<OBJPARSER, PARSER...>::type;

template <typename OBJPARSER, typename... PARSER, std::size_t... J>
inline auto ApplyHelperMember(
    ApplicableMemberFunctionPointer<OBJPARSER, PARSER...> mfp,
    ApplyArgs<OBJPARSER, PARSER...> &&args, std::index_sequence<J...>) ->
    typename OBJPARSER::resultType {
  ((*std::get<0>(args)).*mfp)(std::move(*std::get<J + 1>(args))...);
  return std::get<0>(std::move(args));
}

template <typename OBJPARSER, typename... PARSER> class ApplyMemberFunction {
  using funcType = ApplicableMemberFunctionPointer<OBJPARSER, PARSER...>;

public:
  using resultType = typename OBJPARSER::resultType;
  constexpr ApplyMemberFunction(const ApplyMemberFunction &) = default;
  constexpr ApplyMemberFunction(funcType f, OBJPARSER o, PARSER... p)
      : function_{f}, parsers_{o, p...} {}
  std::optional<resultType> Parse(ParseState &state) const {
    ApplyArgs<OBJPARSER, PARSER...> results;
    using Sequence1 = std::index_sequence_for<OBJPARSER, PARSER...>;
    using Sequence2 = std::index_sequence_for<PARSER...>;
    if (ApplyHelperArgs(parsers_, results, state, Sequence1{})) {
      return ApplyHelperMember<OBJPARSER, PARSER...>(
          function_, std::move(results), Sequence2{});
    } else {
      return std::nullopt;
    }
  }

private:
  const funcType function_;
  const std::tuple<OBJPARSER, PARSER...> parsers_;
};

template <typename OBJPARSER, typename... PARSER>
inline constexpr auto applyMem(
    ApplicableMemberFunctionPointer<OBJPARSER, PARSER...> mfp,
    const OBJPARSER &objParser, PARSER... parser) {
  return ApplyMemberFunction<OBJPARSER, PARSER...>{mfp, objParser, parser...};
}

// As is done with function application via applyFunction() above, class
// instance construction can also be based upon the results of successful
// parses.  For some type T and zero or more parsers a, b, &c., the call
// construct<T>(a, b, ...) returns a parser that succeeds if all of
// its argument parsers do so in succession, and whose result is an
// instance of T constructed upon the values they returned.
// With a single argument that is a parser with no usable value,
// construct<T>(p) invokes T's default nullary constructor (T(){}).
// (This means that "construct<T>(Foo >> Bar >> ok)" is functionally
// equivalent to "Foo >> Bar >> construct<T>()", but I'd like to hold open
// the opportunity to make construct<> capture source provenance all of the
// time, and the first form will then lead to better error positioning.)

template <typename RESULT, typename... PARSER, std::size_t... J>
inline RESULT ApplyHelperConstructor(
    ApplyArgs<PARSER...> &&args, std::index_sequence<J...>) {
  return RESULT{std::move(*std::get<J>(args))...};
}

template <typename RESULT, typename... PARSER> class ApplyConstructor {
public:
  using resultType = RESULT;
  constexpr ApplyConstructor(const ApplyConstructor &) = default;
  constexpr explicit ApplyConstructor(PARSER... p) : parsers_{p...} {}
  std::optional<resultType> Parse(ParseState &state) const {
    if constexpr (sizeof...(PARSER) == 0) {
      return RESULT{};
    } else {
      if constexpr (sizeof...(PARSER) == 1) {
        if constexpr (std::is_same_v<Success, typename PARSER::resultType...>) {
          if (std::get<0>(parsers_).Parse(state)) {
            return RESULT{};
          }
        } else if (auto arg{std::get<0>(parsers_).Parse(state)}) {
          return RESULT{std::move(*arg)};
        }
      } else {
        ApplyArgs<PARSER...> results;
        using Sequence = std::index_sequence_for<PARSER...>;
        if (ApplyHelperArgs(parsers_, results, state, Sequence{})) {
          return ApplyHelperConstructor<RESULT, PARSER...>(
              std::move(results), Sequence{});
        }
      }
      return std::nullopt;
    }
  }

private:
  const std::tuple<PARSER...> parsers_;
};

template <typename RESULT, typename... PARSER>
inline constexpr auto construct(PARSER... p) {
  return ApplyConstructor<RESULT, PARSER...>{p...};
}

// For a parser p, indirect(p) returns a parser that builds an indirect
// reference to p's return type.
template <typename PA> inline constexpr auto indirect(PA p) {
  return construct<common::Indirection<typename PA::resultType>>(p);
}

// If a and b are parsers, then nonemptySeparated(a, b) returns a parser
// that succeeds if a does.  If a succeeds, it then applies many(b >> a).
// The result is the list of the values returned from all of the applications
// of a.
template <typename T>
common::IfNoLvalue<std::list<T>, T> prepend(T &&head, std::list<T> &&rest) {
  rest.push_front(std::move(head));
  return std::move(rest);
}

template <typename PA, typename PB> class NonemptySeparated {
private:
  using paType = typename PA::resultType;

public:
  using resultType = std::list<paType>;
  constexpr NonemptySeparated(const NonemptySeparated &) = default;
  constexpr NonemptySeparated(PA p, PB sep) : parser_{p}, separator_{sep} {}
  std::optional<resultType> Parse(ParseState &state) const {
    return applyFunction(prepend<paType>, parser_, many(separator_ >> parser_))
        .Parse(state);
  }

private:
  const PA parser_;
  const PB separator_;
};

template <typename PA, typename PB>
inline constexpr auto nonemptySeparated(PA p, PB sep) {
  return NonemptySeparated<PA, PB>{p, sep};
}

// ok is a parser that always succeeds.  It is useful when a parser
// must discard its result in order to be compatible in type with other
// parsers in an alternative, e.g. "x >> ok || y >> ok" is type-safe even
// when x and y have distinct result types.
constexpr struct OkParser {
  using resultType = Success;
  constexpr OkParser() {}
  static constexpr std::optional<Success> Parse(ParseState &) {
    return Success{};
  }
} ok;

// A variant of recovery() above for convenience.
template <typename PA, typename PB>
inline constexpr auto localRecovery(MessageFixedText msg, PA pa, PB pb) {
  return recovery(withMessage(msg, pa), pb >> pure<typename PA::resultType>());
}

// nextCh is a parser that succeeds if the parsing state is not
// at the end of its input, returning the next character location and
// advancing the parse when it does so.
struct NextCh {
  using resultType = const char *;
  constexpr NextCh() {}
  std::optional<const char *> Parse(ParseState &state) const {
    if (std::optional<const char *> result{state.GetNextChar()}) {
      return result;
    }
    state.Say("end of file"_err_en_US);
    return std::nullopt;
  }
};

constexpr NextCh nextCh;

// If a is a parser for some nonstandard language feature LF, extension<LF>(a)
// is a parser that optionally enabled, sets a strict conformance violation
// flag, and may emit a warning message, if those are enabled.
template <LanguageFeature LF, typename PA> class NonstandardParser {
public:
  using resultType = typename PA::resultType;
  constexpr NonstandardParser(const NonstandardParser &) = default;
  constexpr NonstandardParser(PA parser) : parser_{parser} {}
  std::optional<resultType> Parse(ParseState &state) const {
    if (UserState * ustate{state.userState()}) {
      if (!ustate->features().IsEnabled(LF)) {
        return std::nullopt;
      }
    }
    auto at{state.GetLocation()};
    auto result{parser_.Parse(state)};
    if (result) {
      state.Nonstandard(
          CharBlock{at, state.GetLocation()}, LF, "nonstandard usage"_en_US);
    }
    return result;
  }

private:
  const PA parser_;
};

template <LanguageFeature LF, typename PA>
inline constexpr auto extension(PA parser) {
  return NonstandardParser<LF, PA>(parser);
}

// If a is a parser for some deprecated or deleted language feature LF,
// deprecated<LF>(a) is a parser that is optionally enabled, sets a strict
// conformance violation flag, and may emit a warning message, if enabled.
template <LanguageFeature LF, typename PA> class DeprecatedParser {
public:
  using resultType = typename PA::resultType;
  constexpr DeprecatedParser(const DeprecatedParser &) = default;
  constexpr DeprecatedParser(PA parser) : parser_{parser} {}
  std::optional<resultType> Parse(ParseState &state) const {
    if (UserState * ustate{state.userState()}) {
      if (!ustate->features().IsEnabled(LF)) {
        return std::nullopt;
      }
    }
    auto at{state.GetLocation()};
    auto result{parser_.Parse(state)};
    if (result) {
      state.Nonstandard(
          CharBlock{at, state.GetLocation()}, LF, "deprecated usage"_en_US);
    }
    return result;
  }

private:
  const PA parser_;
};

template <LanguageFeature LF, typename PA>
inline constexpr auto deprecated(PA parser) {
  return DeprecatedParser<LF, PA>(parser);
}

// Parsing objects with "source" members.
template <typename PA> class SourcedParser {
public:
  using resultType = typename PA::resultType;
  constexpr SourcedParser(const SourcedParser &) = default;
  constexpr SourcedParser(PA parser) : parser_{parser} {}
  std::optional<resultType> Parse(ParseState &state) const {
    const char *start{state.GetLocation()};
    auto result{parser_.Parse(state)};
    if (result) {
      const char *end{state.GetLocation()};
      for (; start < end && start[0] == ' '; ++start) {
      }
      for (; start < end && end[-1] == ' '; --end) {
      }
      result->source = CharBlock{start, end};
    }
    return result;
  }

private:
  const PA parser_;
};

template <typename PA> inline constexpr auto sourced(PA parser) {
  return SourcedParser<PA>{parser};
}
} // namespace Fortran::parser
#endif // FORTRAN_PARSER_BASIC_PARSERS_H_
