// 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/parser.h"

#include "src/developer/shell/parser/ast.h"
#include "src/developer/shell/parser/combinators.h"
#include "src/developer/shell/parser/text_match.h"

namespace shell::parser {
namespace {

ParseResultStream Whitespace(ParseResultStream prefixes);

// Create a parser that runs a sequence of parsers consecutively, with optional whitespace parsed
// between each parser.
fit::function<ParseResultStream(ParseResultStream)> WSSeq(
    fit::function<ParseResultStream(ParseResultStream)> first) {
  return Seq(Maybe(Whitespace), std::move(first), Maybe(Whitespace));
}

template <typename... Args>
fit::function<ParseResultStream(ParseResultStream)> WSSeq(
    fit::function<ParseResultStream(ParseResultStream)> first, Args... args) {
  return Seq(Maybe(Whitespace), std::move(first), WSSeq(std::move(args)...));
}

ParseResultStream IdentifierCharacter(ParseResultStream prefixes);

// Parse a keyword.
fit::function<ParseResultStream(ParseResultStream)> KW(const std::string& keyword) {
  return Seq(Token(keyword), Not(IdentifierCharacter));
}

// Token Rules -------------------------------------------------------------------------------------

ParseResultStream IdentifierCharacter(ParseResultStream prefixes) {
  return CharGroup("identifier character", "a-zA-Z0-9_")(std::move(prefixes));
}

ParseResultStream Whitespace(ParseResultStream prefixes) {
  return NT<ast::Whitespace>(OnePlus(
      Alt(AnyChar("space", " \n\r\t"), Seq(Token("#"), ZeroPlus(AnyCharBut("non-newline", "\n")),
                                           Token("\n")))))(std::move(prefixes));
}

ParseResultStream Digit(ParseResultStream prefixes) {
  return CharGroup("digit", "0-9")(std::move(prefixes));
}

ParseResultStream HexDigit(ParseResultStream prefixes) {
  return CharGroup("hex digit", "a-fA-F0-9")(std::move(prefixes));
}

ParseResultStream UnescapedIdentifier(ParseResultStream prefixes);
fit::function<ParseResultStream(ParseResultStream)> Thingy(int min) {
  if (min > 0) {
    return Seq(IdentifierCharacter, Thingy(min - 1));
  } else {
    return [](ParseResultStream prefixes) { return Maybe(Thingy(1))(std::move(prefixes)); };
  }
}

ParseResultStream UnescapedIdentifier(ParseResultStream prefixes) {
  return Token(OnePlus(IdentifierCharacter))(std::move(prefixes));
}

// Grammar Rules -----------------------------------------------------------------------------------

// Parses an identifier
//     myVariable
ParseResultStream Identifier(ParseResultStream prefixes) {
  return NT<ast::Identifier>(Seq(Not(Digit), UnescapedIdentifier))(std::move(prefixes));
}

// Parses an unadorned decimal Integer
//     0
//     12345
//     12_345
ParseResultStream DecimalInteger(ParseResultStream prefixes) {
  return Alt(Seq(Token("0"), Not(Digit)),
             Seq(Not(Token("0")), Token(OnePlus(Digit)),
                 ZeroPlus(Seq(Token("_"), Token(OnePlus(Digit))))))(std::move(prefixes));
}

// Parses a hexadecimal integer marked by '0x'
//     0x1234abcd
//     0x12_abcd
ParseResultStream HexInteger(ParseResultStream prefixes) {
  return Seq(Token("0x"),
             Seq(Token(OnePlus(HexDigit)), ZeroPlus(Seq(Token("_"), Token(OnePlus(HexDigit))))))(
      std::move(prefixes));
}

// Parses an integer.
//     0
//     12345
//     12_345
//     0x1234abcd
//     0x12_abcd
ParseResultStream Integer(ParseResultStream prefixes) {
  // TODO: Binary integers, once we ask the FIDL team about them.
  return NT<ast::Integer>(Alt(HexInteger, DecimalInteger))(std::move(prefixes));
}

// Parses an expression. This is effectively unimplemented right now.
ParseResultStream Expression(ParseResultStream prefixes) {
  // Unimplemented
  return NT<ast::Expression>(Integer)(std::move(prefixes));
}

// Parses a variable declaration:
//     var foo = 4.5
ParseResultStream VariableDecl(ParseResultStream prefixes) {
  return NT<ast::VariableDecl>(
      WSSeq(Alt(KW("var"), KW("const")), Identifier, Token("="), Expression))(std::move(prefixes));
}

// Parses the body of a program, but doesn't create an AST node. This is useful for parsing blocks
// where we might want to include the braces in the node's children.
ParseResultStream ProgramContent(ParseResultStream prefixes) {
  /* Eventual full version of this rule is:
  return Alt(WSSeq(VariableDecl, Maybe(WSSeq(AnyChar(";&", "; or &"), ProgramMeta))),
             WSSeq(FunctionDecl, Program),
             WSSeq(Expression, Maybe(WSSeq(AnyChar(";&", "; or &"), ProgramMeta))),
  Empty)(prefixes);
  */
  return Alt(WSSeq(VariableDecl, Maybe(WSSeq(AnyChar("; or &", ";&"), ProgramContent))),
             Empty)(std::move(prefixes));
}

}  // namespace

std::shared_ptr<ast::Node> Parse(std::string_view text) {
  return NT<ast::Program>(Seq(ProgramContent, EOS))(text).Next().node();
}

}  // namespace shell::parser
