// 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.

#ifndef SRC_DEVELOPER_SHELL_PARSER_AST_H_
#define SRC_DEVELOPER_SHELL_PARSER_AST_H_

#include <lib/syslog/cpp/macros.h>

#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <variant>
#include <vector>

namespace shell::parser::ast {

class Node;
class Terminal;
class Nonterminal;
class Error;
class Program;
class VariableDecl;
class Identifier;
class Integer;
class Expression;
class DecimalGroup;
class HexGroup;
class UnescapedIdentifier;
class StringEntity;
class EscapeSequence;
class PathElement;
class PathEscape;
class PathSeparator;
class Operator;
class String;
class Object;
class Field;
class Path;
class AddSub;

template <typename T = void>
class NodeVisitor;

template <typename T>
class WrappingVisitor;

// A node in our AST.
class Node {
 public:
  explicit Node(size_t start) : start_(start) {}
  virtual ~Node() = default;

  size_t start() const { return start_; }

  // Child nodes of this node. Always empty for terminals, may be empty for non-terminals.
  virtual const std::vector<std::shared_ptr<Node>>& Children() const = 0;

  // Create an s-expression-like string representation of this node. We don't store the parsed text
  // in the node itself so we must be passed the original parsed string.
  virtual std::string ToString(std::string_view unit) const = 0;

  // Number of characters this node corresponds to in the original text.
  virtual size_t Size() const = 0;

  // Whether this node marks a parse error.
  virtual bool IsError() const { return false; }

  // Whether this node is a whitespace node.
  virtual bool IsWhitespace() const { return false; }

  // Whether this node or any of its children contains parse errors.
  virtual bool HasErrors() const { return IsError(); }

  // Visit this node with a visitor.
  template <typename T>
  T Visit(NodeVisitor<T>* visitor) const {
    WrappingVisitor wrapped(visitor);
    Visit(&wrapped);
    return std::move(wrapped.result);
  }
  template <>
  void Visit<void>(NodeVisitor<void>* visitor) const {
    VisitVoid(visitor);
  }

  // Downcasting methods
  virtual Error* AsError() { return nullptr; }
  const Error* AsError() const { return const_cast<Node*>(this)->AsError(); }
  virtual Program* AsProgram() { return nullptr; }
  const Program* AsProgram() const { return const_cast<Node*>(this)->AsProgram(); }
  virtual VariableDecl* AsVariableDecl() { return nullptr; }
  const VariableDecl* AsVariableDecl() const { return const_cast<Node*>(this)->AsVariableDecl(); }
  virtual Identifier* AsIdentifier() { return nullptr; }
  const Identifier* AsIdentifier() const { return const_cast<Node*>(this)->AsIdentifier(); }
  virtual Integer* AsInteger() { return nullptr; }
  const Integer* AsInteger() const { return const_cast<Node*>(this)->AsInteger(); }
  virtual Expression* AsExpression() { return nullptr; }
  const Expression* AsExpression() const { return const_cast<Node*>(this)->AsExpression(); }
  virtual DecimalGroup* AsDecimalGroup() { return nullptr; }
  const DecimalGroup* AsDecimalGroup() const { return const_cast<Node*>(this)->AsDecimalGroup(); }
  virtual HexGroup* AsHexGroup() { return nullptr; }
  const HexGroup* AsHexGroup() const { return const_cast<Node*>(this)->AsHexGroup(); }
  virtual UnescapedIdentifier* AsUnescapedIdentifier() { return nullptr; }
  const UnescapedIdentifier* AsUnescapedIdentifier() const {
    return const_cast<Node*>(this)->AsUnescapedIdentifier();
  }
  virtual StringEntity* AsStringEntity() { return nullptr; }
  const StringEntity* AsStringEntity() const { return const_cast<Node*>(this)->AsStringEntity(); }
  virtual EscapeSequence* AsEscapeSequence() { return nullptr; }
  const EscapeSequence* AsEscapeSequence() const {
    return const_cast<Node*>(this)->AsEscapeSequence();
  }
  virtual PathElement* AsPathElement() { return nullptr; }
  const PathElement* AsPathElement() const { return const_cast<Node*>(this)->AsPathElement(); }
  virtual PathEscape* AsPathEscape() { return nullptr; }
  const PathEscape* AsPathEscape() const { return const_cast<Node*>(this)->AsPathEscape(); }
  virtual Operator* AsOperator() { return nullptr; }
  const Operator* AsOperator() const { return const_cast<Node*>(this)->AsOperator(); }
  virtual String* AsString() { return nullptr; }
  const String* AsString() const { return const_cast<Node*>(this)->AsString(); }
  virtual Object* AsObject() { return nullptr; }
  const Object* AsObject() const { return const_cast<Node*>(this)->AsObject(); }
  virtual Field* AsField() { return nullptr; }
  const Field* AsField() const { return const_cast<Node*>(this)->AsField(); }
  virtual Path* AsPath() { return nullptr; }
  const Path* AsPath() const { return const_cast<Node*>(this)->AsPath(); }
  virtual AddSub* AsAddSub() { return nullptr; }
  const AddSub* AsAddSub() const { return const_cast<Node*>(this)->AsAddSub(); }

  // ID methods for keywords
  virtual bool IsConst() const { return false; }
  virtual bool IsVar() const { return false; }
  virtual bool IsFieldSeparator() const { return false; }
  virtual bool IsPathSeparator() const { return false; }

 private:
  virtual void VisitVoid(NodeVisitor<void>* visitor) const = 0;

  // Offset into the original text where the text this node corresponds to starts.
  const size_t start_;
};

// Superclass of all terminal nodes in our AST.
class Terminal : public Node {
 public:
  Terminal(size_t start, size_t size, std::string_view /*content*/) : Node(start), size_(size) {}

  const std::vector<std::shared_ptr<Node>>& Children() const override { return kEmptyChildren; }
  size_t Size() const override { return size_; }

  std::string ToString(std::string_view unit) const override;

 private:
  void VisitVoid(NodeVisitor<void>* visitor) const override;

  static const std::vector<std::shared_ptr<Node>> kEmptyChildren;

  const size_t size_;
};

class Error : public Terminal {
 public:
  Error(size_t start, size_t size, std::string_view message)
      : Terminal(start, size, ""), message_(message) {}

  const std::string& message() const { return message_; }

  bool IsError() const override { return true; }

  std::string ToString(std::string_view unit) const override;
  Error* AsError() override { return this; }

 private:
  void VisitVoid(NodeVisitor<void>* visitor) const override;

  const std::string message_;
};

// Terminal representing a ":".
class FieldSeparator : public Terminal {
 public:
  FieldSeparator(size_t start, size_t size, std::string_view content)
      : Terminal(start, size, content) {}

  bool IsFieldSeparator() const override { return true; }

 private:
  void VisitVoid(NodeVisitor<void>* visitor) const override;
};

// Terminal representing the "const" keyword.
class Const : public Terminal {
 public:
  Const(size_t start, size_t size, std::string_view content) : Terminal(start, size, content) {}

  bool IsConst() const override { return true; }

 private:
  void VisitVoid(NodeVisitor<void>* visitor) const override;
};

// Terminal representing the "var" keyword.
class Var : public Terminal {
 public:
  Var(size_t start, size_t size, std::string_view content) : Terminal(start, size, content) {}

  bool IsVar() const override { return true; }

 private:
  void VisitVoid(NodeVisitor<void>* visitor) const override;
};

// Terminal representing a sequence of decimal digits.
class DecimalGroup : public Terminal {
 public:
  DecimalGroup(size_t start, size_t size, std::string_view content);

  size_t digits() const { return digits_; }
  uint64_t value() const { return value_; }

  DecimalGroup* AsDecimalGroup() override { return this; }

 private:
  void VisitVoid(NodeVisitor<void>* visitor) const override;

  size_t digits_;
  uint64_t value_ = 0;
};

// Terminal representing a sequence of hex digits.
class HexGroup : public Terminal {
 public:
  HexGroup(size_t start, size_t size, std::string_view content);

  size_t digits() const { return digits_; }
  uint64_t value() const { return value_; }

  HexGroup* AsHexGroup() override { return this; }

 private:
  void VisitVoid(NodeVisitor<void>* visitor) const override;

  size_t digits_;
  uint64_t value_ = 0;
};

// Terminal representing an unescaped identifier
class UnescapedIdentifier : public Terminal {
 public:
  UnescapedIdentifier(size_t start, size_t size, std::string_view content)
      : Terminal(start, size, content), identifier_(content) {}

  const std::string& identifier() const { return identifier_; }

  UnescapedIdentifier* AsUnescapedIdentifier() override { return this; }

 private:
  void VisitVoid(NodeVisitor<void>* visitor) const override;

  std::string identifier_ = "";
};

// Terminal representing a piece of a string literal.
class StringEntity : public Terminal {
 public:
  StringEntity(size_t start, size_t size, std::string_view content)
      : Terminal(start, size, content), content_(content) {}

  const std::string& content() const { return content_; }

  StringEntity* AsStringEntity() override { return this; }

 private:
  void VisitVoid(NodeVisitor<void>* visitor) const override;

  std::string content_ = "";
};

// Terminal representing a piece of an escape sequence in a string literal.
class EscapeSequence : public StringEntity {
 public:
  EscapeSequence(size_t start, size_t size, std::string_view content)
      : StringEntity(start, size, Decode(content)) {}

  EscapeSequence* AsEscapeSequence() override { return this; }

 private:
  void VisitVoid(NodeVisitor<void>* visitor) const override;

  static std::string Decode(std::string_view sequence);
};

// Terminal representing a continuous piece of a path.
class PathElement : public Terminal {
 public:
  PathElement(size_t start, size_t size, std::string_view content)
      : Terminal(start, size, content), content_(content) {}

  const std::string& content() const { return content_; }

  PathElement* AsPathElement() override { return this; }

 private:
  void VisitVoid(NodeVisitor<void>* visitor) const override;

  std::string content_ = "";
};

// Terminal representing a piece of an escape sequence in a path.
class PathEscape : public PathElement {
 public:
  PathEscape(size_t start, size_t size, std::string_view content)
      : PathElement(start, size, content.substr(1)) {}

  PathEscape* AsPathEscape() override { return this; }

 private:
  void VisitVoid(NodeVisitor<void>* visitor) const override;
};

// Terminal representing a path separator.
class PathSeparator : public Terminal {
 public:
  PathSeparator(size_t start, size_t size, std::string_view content)
      : Terminal(start, size, content) {}

  bool IsPathSeparator() const override { return true; }

 private:
  void VisitVoid(NodeVisitor<void>* visitor) const override;
};

// Terminal representing an operator.
class Operator : public Terminal {
 public:
  Operator(size_t start, size_t size, std::string_view content)
      : Terminal(start, size, content), operator_(content) {}

  const std::string& op() const { return operator_; }

  Operator* AsOperator() override { return this; }

 private:
  void VisitVoid(NodeVisitor<void>* visitor) const override;

  std::string operator_ = "";
};

// Superclass of all non-terminal nodes in our AST.
class Nonterminal : public Node {
 public:
  Nonterminal(size_t start, std::vector<std::shared_ptr<Node>> children)
      : Node(start), children_(std::move(children)) {
    for (const auto& child : children_) {
      if (child->HasErrors()) {
        has_errors_ = true;
        break;
      }
    }
  }

  // Name of this node as a string.
  virtual std::string_view Name() const = 0;

  const std::vector<std::shared_ptr<Node>>& Children() const override { return children_; }
  size_t Size() const override {
    if (children_.empty()) {
      return 0;
    } else {
      return children_.back()->start() - start() + children_.back()->Size();
    }
  }

  std::string ToString(std::string_view unit) const override;

  bool HasErrors() const override { return has_errors_; }

 private:
  void VisitVoid(NodeVisitor<void>* visitor) const override;

  bool has_errors_ = false;
  std::vector<std::shared_ptr<Node>> children_;
};

// Result of an attempt to parse a single token. Usually that will result in a terminal, but if
// there are errors, we may get one of these instead. Its children will be error nodes and the
// fragments of the token that parsed correctly.
class TokenResult : public Nonterminal {
 public:
  TokenResult(size_t start, std::vector<std::shared_ptr<Node>> children)
      : Nonterminal(start, std::move(children)) {}

  std::string_view Name() const override { return ""; }

  // If one of these ends up in output outside of the Token() combinator, then it's definitely an
  // error.
  bool IsError() const override { return true; }
};

class Whitespace : public Nonterminal {
 public:
  Whitespace(size_t start, std::vector<std::shared_ptr<Node>> children)
      : Nonterminal(start, std::move(children)) {}

  std::string_view Name() const override { return "Whitespace"; }
  bool IsWhitespace() const override { return true; }
};

class Program : public Nonterminal {
 public:
  Program(size_t start, std::vector<std::shared_ptr<Node>> children)
      : Nonterminal(start, std::move(children)) {}

  std::string_view Name() const override { return "Program"; }
  Program* AsProgram() override { return this; }

 private:
  void VisitVoid(NodeVisitor<void>* visitor) const override;
};

class VariableDecl : public Nonterminal {
 public:
  VariableDecl(size_t start, std::vector<std::shared_ptr<Node>> children);

  const std::string& identifier() const { return identifier_; }
  Expression* expression() const { return expression_; }
  bool is_const() const { return is_const_; }

  std::string_view Name() const override { return "VariableDecl"; }
  VariableDecl* AsVariableDecl() override { return this; }

 private:
  void VisitVoid(NodeVisitor<void>* visitor) const override;

  Expression* expression_ = nullptr;
  bool is_const_ = false;
  std::string identifier_ = "";
};

class Integer : public Nonterminal {
 public:
  Integer(size_t start, std::vector<std::shared_ptr<Node>> children);

  uint64_t value() const { return value_; }

  std::string_view Name() const override { return "Integer"; }

  Integer* AsInteger() override { return this; }

 private:
  void VisitVoid(NodeVisitor<void>* visitor) const override;

  uint64_t value_ = 0;
};

class String : public Nonterminal {
 public:
  String(size_t start, std::vector<std::shared_ptr<Node>> children);

  const std::string& value() const { return value_; }

  std::string_view Name() const override { return "String"; }

  String* AsString() override { return this; }

 private:
  void VisitVoid(NodeVisitor<void>* visitor) const override;

  std::string value_;
};

class Identifier : public Nonterminal {
 public:
  Identifier(size_t start, std::vector<std::shared_ptr<Node>> children);

  const std::string& identifier() const { return identifier_; }

  std::string_view Name() const override { return "Identifier"; }

  Identifier* AsIdentifier() override { return this; }

 private:
  void VisitVoid(NodeVisitor<void>* visitor) const override;

  std::string identifier_;
};

class Object : public Nonterminal {
 public:
  Object(size_t start, std::vector<std::shared_ptr<Node>> children);

  const std::vector<Field*> fields() const { return fields_; }

  std::string_view Name() const override { return "Object"; }

  Object* AsObject() override { return this; }

 private:
  void VisitVoid(NodeVisitor<void>* visitor) const override;

  std::vector<Field*> fields_;
};

class Field : public Nonterminal {
 public:
  Field(size_t start, std::vector<std::shared_ptr<Node>> children);

  const std::string& name() const { return name_; }
  Node* value() const { return value_; }

  std::string_view Name() const override { return "Field"; }

  Field* AsField() override { return this; }

 private:
  void VisitVoid(NodeVisitor<void>* visitor) const override;

  std::string name_;
  Node* value_ = nullptr;
};

class Path : public Nonterminal {
 public:
  Path(size_t start, std::vector<std::shared_ptr<Node>> children);

  bool is_local() const { return is_local_; }
  const std::vector<std::string>& elements() const { return elements_; }

  std::string_view Name() const override { return "Path"; }

  Path* AsPath() override { return this; }

 private:
  void VisitVoid(NodeVisitor<void>* visitor) const override;

  bool is_local_;
  std::vector<std::string> elements_;
};

class AddSub : public Nonterminal {
 public:
  enum Type {
    kAdd,
    kSubtract,
  };

  AddSub(size_t start, std::vector<std::shared_ptr<Node>> children);

  Type type() const { return type_; }
  Node* a() const { return a_; }
  Node* b() const { return b_; }

  std::string_view Name() const override { return "AddSub"; }

  AddSub* AsAddSub() override { return this; }

 private:
  void VisitVoid(NodeVisitor<void>* visitor) const override;

  Type type_ = kAdd;
  Node* a_ = nullptr;
  Node* b_ = nullptr;
};

class Expression : public Nonterminal {
 public:
  Expression(size_t start, std::vector<std::shared_ptr<Node>> children)
      : Nonterminal(start, std::move(children)) {}

  std::string_view Name() const override { return "Expression"; }
  Expression* AsExpression() override { return this; }

 private:
  void VisitVoid(NodeVisitor<void>* visitor) const override;
};

// Visitor for AST nodes.
template <typename T>
class NodeVisitor {
  friend class Node;
  friend class Terminal;
  friend class Nonterminal;
  friend class Error;
  friend class Var;
  friend class Const;
  friend class FieldSeparator;
  friend class Program;
  friend class VariableDecl;
  friend class Identifier;
  friend class Integer;
  friend class Expression;
  friend class DecimalGroup;
  friend class HexGroup;
  friend class UnescapedIdentifier;
  friend class StringEntity;
  friend class EscapeSequence;
  friend class PathElement;
  friend class PathEscape;
  friend class PathSeparator;
  friend class Operator;
  friend class String;
  friend class Object;
  friend class Field;
  friend class Path;
  friend class AddSub;

  friend class WrappingVisitor<T>;

 protected:
  virtual T VisitNode(const Node& node) {
    if constexpr (!std::is_void<T>::value) {
      FX_NOTREACHED();
      std::terminate();
    }
  }

  virtual T VisitTerminal(const Terminal& node) { return VisitNode(node); }
  virtual T VisitNonterminal(const Nonterminal& node) { return VisitNode(node); }
  virtual T VisitError(const Error& node) { return VisitTerminal(node); }
  virtual T VisitConst(const Const& node) { return VisitTerminal(node); }
  virtual T VisitVar(const Var& node) { return VisitTerminal(node); }
  virtual T VisitFieldSeparator(const FieldSeparator& node) { return VisitTerminal(node); }
  virtual T VisitProgram(const Program& node) { return VisitNonterminal(node); }
  virtual T VisitVariableDecl(const VariableDecl& node) { return VisitNonterminal(node); }
  virtual T VisitIdentifier(const Identifier& node) { return VisitNonterminal(node); }
  virtual T VisitInteger(const Integer& node) { return VisitNonterminal(node); }
  virtual T VisitExpression(const Expression& node) { return VisitNonterminal(node); }
  virtual T VisitDecimalGroup(const DecimalGroup& node) { return VisitTerminal(node); }
  virtual T VisitHexGroup(const HexGroup& node) { return VisitTerminal(node); }
  virtual T VisitUnescapedIdentifier(const UnescapedIdentifier& node) {
    return VisitTerminal(node);
  }
  virtual T VisitStringEntity(const StringEntity& node) { return VisitTerminal(node); }
  virtual T VisitEscapeSequence(const EscapeSequence& node) { return VisitStringEntity(node); }
  virtual T VisitString(const String& node) { return VisitNonterminal(node); }
  virtual T VisitObject(const Object& node) { return VisitNonterminal(node); }
  virtual T VisitField(const Field& node) { return VisitNonterminal(node); }
  virtual T VisitPathElement(const PathElement& node) { return VisitTerminal(node); }
  virtual T VisitPathEscape(const PathEscape& node) { return VisitTerminal(node); }
  virtual T VisitPathSeparator(const PathSeparator& node) { return VisitTerminal(node); }
  virtual T VisitOperator(const Operator& node) { return VisitTerminal(node); }
  virtual T VisitPath(const Path& node) { return VisitNonterminal(node); }
  virtual T VisitAddSub(const AddSub& node) { return VisitNonterminal(node); }
};

template <typename T>
class WrappingVisitor : public NodeVisitor<void> {
 public:
  WrappingVisitor(NodeVisitor<T>* wrapped) : wrapped_(wrapped) {}

  T result;

 private:
  void VisitNode(const Node& node) override { result = wrapped_->VisitNode(node); }
  void VisitTerminal(const Terminal& node) override { result = wrapped_->VisitTerminal(node); }
  void VisitNonterminal(const Nonterminal& node) override {
    result = wrapped_->VisitNonterminal(node);
  }
  void VisitError(const Error& node) override { result = wrapped_->VisitError(node); }
  void VisitConst(const Const& node) override { result = wrapped_->VisitConst(node); }
  void VisitVar(const Var& node) override { result = wrapped_->VisitVar(node); }
  void VisitFieldSeparator(const FieldSeparator& node) override {
    result = wrapped_->VisitFieldSeparator(node);
  }
  void VisitProgram(const Program& node) override { result = wrapped_->VisitProgram(node); }
  void VisitVariableDecl(const VariableDecl& node) override {
    result = wrapped_->VisitVariableDecl(node);
  }
  void VisitIdentifier(const Identifier& node) override {
    result = wrapped_->VisitIdentifier(node);
  }
  void VisitInteger(const Integer& node) override { result = wrapped_->VisitInteger(node); }
  void VisitExpression(const Expression& node) override {
    result = wrapped_->VisitExpression(node);
  }
  void VisitDecimalGroup(const DecimalGroup& node) override {
    result = wrapped_->VisitDecimalGroup(node);
  }
  void VisitHexGroup(const HexGroup& node) override { result = wrapped_->VisitHexGroup(node); }
  void VisitUnescapedIdentifier(const UnescapedIdentifier& node) override {
    result = wrapped_->VisitUnescapedIdentifier(node);
  }
  void VisitStringEntity(const StringEntity& node) override {
    result = wrapped_->VisitStringEntity(node);
  }
  void VisitEscapeSequence(const EscapeSequence& node) override {
    result = wrapped_->VisitEscapeSequence(node);
  }
  void VisitString(const String& node) override { result = wrapped_->VisitString(node); }
  void VisitObject(const Object& node) override { result = wrapped_->VisitObject(node); }
  void VisitField(const Field& node) override { result = wrapped_->VisitField(node); }
  void VisitPathElement(const PathElement& node) override {
    result = wrapped_->VisitPathElement(node);
  }
  void VisitPathEscape(const PathEscape& node) override {
    result = wrapped_->VisitPathEscape(node);
  }
  void VisitPathSeparator(const PathSeparator& node) override {
    result = wrapped_->VisitPathSeparator(node);
  }
  void VisitOperator(const Operator& node) override { result = wrapped_->VisitOperator(node); }
  void VisitPath(const Path& node) override { result = wrapped_->VisitPath(node); }
  void VisitAddSub(const AddSub& node) override { result = wrapped_->VisitAddSub(node); }

  NodeVisitor<T>* wrapped_;
};

}  // namespace shell::parser::ast

#endif  // SRC_DEVELOPER_SHELL_PARSER_AST_H_
