// Copyright 2020 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 "src/developer/shell/parser/text_match.h"

namespace shell::parser {
namespace {

// Produces a parse result for a fixed token or character. This is NOT a parser or combinator; it
// must be told via its arguments whether the initial parse succeeds. The ident argument should
// provide a rendering of what is being matched suitable for error messages. The token matched must
// always be of the given size. The find callback will be used to look ahead for error correction.
// Given a starting offset into the prefix tail, it should return the next location at which a match
// is possible.
ParseResultStream FixedTextResult(ParseResult prefix, const std::string& ident, bool success,
                                  size_t size, fit::function<size_t()> find) {
  if (success) {
    return ParseResultStream(prefix.Advance(size));
  }

  return ParseResultStream(false, [prefix, size, ident, find = std::move(find), done = false,
                                   next = std::optional<ParseResult>()]() mutable {
    if (done) {
      return prefix.End();
    }

    if (next) {
      done = true;
      return std::move(*next);
    }

    size_t pos = find();

    ParseResult skip = pos == std::string::npos
                           ? prefix.Skip(prefix.tail().size()).Expected(size, ident)
                           : prefix.Skip(pos).Advance(size);
    ParseResult inject = prefix.Expected(size, ident);

    if (skip.error_score() < inject.error_score()) {
      next = std::move(inject);
      return skip;
    }

    next = std::move(skip);
    return inject;
  });
}

// Produce a parser which parses any single character from the given list. If invert is true,
// character must NOT be in the list instead.
fit::function<ParseResultStream(ParseResultStream)> AnyCharMayInvert(std::string_view chars,
                                                                     bool invert,
                                                                     const std::string& name) {
  return [chars, invert, name](ParseResultStream prefixes) {
    return std::move(prefixes).Follow([chars, invert, name](ParseResult prefix) {
      auto tail = prefix.tail();
      return FixedTextResult(
          std::move(prefix), name,
          tail.size() > 0 && (chars.find(tail[0]) == std::string::npos) == invert, 1,
          [chars, invert, tail]() {
            if (invert) {
              return tail.find_first_not_of(chars);
            } else {
              return tail.find_first_of(chars);
            }
          });
    });
  };
}

// Return whether a given character would match a regex-style char group.
bool MatchCharGroup(std::string_view chars, char c) {
  size_t pos = 0;

  while (pos < chars.size()) {
    if (c == chars[pos]) {
      return true;
    } else if (pos + 2 < chars.size() && chars[pos + 1] == '-') {
      if (c > chars[pos] && c <= chars[pos + 2]) {
        return true;
      }

      pos += 3;
    } else {
      pos += 1;
    }
  }

  return false;
}

}  // namespace

fit::function<ParseResultStream(ParseResultStream)> AnyChar(const std::string& name,
                                                            std::string_view chars) {
  return AnyCharMayInvert(chars, false, name);
}

ParseResultStream AnyChar(ParseResultStream prefixes) {
  return AnyCharBut("a character", "")(std::move(prefixes));
}

fit::function<ParseResultStream(ParseResultStream)> AnyCharBut(const std::string& name,
                                                               std::string_view chars) {
  return AnyCharMayInvert(chars, true, name);
}

fit::function<ParseResultStream(ParseResultStream)> CharGroup(const std::string& name,
                                                              std::string_view chars) {
  return [chars, name](ParseResultStream prefixes) {
    return std::move(prefixes).Follow([chars, name](ParseResult prefix) {
      auto tail = prefix.tail();
      bool matched = tail.size() > 0 && MatchCharGroup(chars, tail[0]);
      return FixedTextResult(std::move(prefix), name, matched, 1, [chars, tail]() {
        size_t i = 0;

        while (i < tail.size() && !MatchCharGroup(chars, tail[i])) {
          i++;
        }

        return i;
      });
    });
  };
}

// Produce a parser to parse a fixed text string.
fit::function<ParseResultStream(ParseResultStream)> Token(const std::string& token) {
  return [token](ParseResultStream prefixes) {
    return std::move(prefixes).Follow([token](ParseResult prefix) {
      return FixedTextResult(std::move(prefix), "'" + token + "'",
                             prefix.tail().substr(0, token.size()) == token, token.size(),
                             [tail = prefix.tail(), token]() { return tail.find(token); });
    });
  };
}

fit::function<ParseResultStream(ParseResultStream)> Token(
    fit::function<ParseResultStream(ParseResultStream)> parser) {
  return [parser = std::move(parser)](ParseResultStream prefix) {
    return parser(std::move(prefix).Mark()).Reduce<ast::TokenResult>().Map([](ParseResult result) {
      // The goal here is to return a single terminal representing the parsed region of the result,
      // but terminals don't have children, and thus can't have errors. As such, if we have error
      // children, we return an unnamed non-terminal, where we combine all the regular parse results
      // into single tokens, but leave the error tokens in place. So if we parsed ('foo' 'bar'
      // 'baz'), we'd finish with just 'foobarbaz' on the stack, but if we parsed ('foo' 'bar'
      // E[Expected 'baz']) we'd end with ('foobar' E[Expected 'baz']).
      std::optional<size_t> start = std::nullopt;
      size_t end;
      std::vector<std::shared_ptr<ast::Node>> children;
      for (const auto& child : result.node()->Children()) {
        if (child->IsError()) {
          if (start) {
            children.push_back(std::make_shared<ast::Terminal>(*start, child->start()));
          }
          children.push_back(child);
          start = std::nullopt;
        } else {
          if (!start) {
            start = child->start();
          }

          end = child->start() + child->Size();
        }
      }

      if (start) {
        children.push_back(std::make_shared<ast::Terminal>(*start, end - *start));
      }

      std::shared_ptr<ast::Node> new_child;
      if (children.size() == 1) {
        new_child = children.front();
      } else {
        new_child = std::make_shared<ast::TokenResult>(result.node()->start(), std::move(children));
      }

      return result.SetNode(new_child);
    });
  };
}

}  // namespace shell::parser
