//===---- QueryParser.cpp - clang-query command parser --------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "QueryParser.h"
#include "Query.h"
#include "QuerySession.h"
#include "clang/ASTMatchers/Dynamic/Parser.h"
#include "clang/Basic/CharInfo.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include <set>

using namespace llvm;
using namespace clang::ast_matchers::dynamic;

namespace clang {
namespace query {

// Lex any amount of whitespace followed by a "word" (any sequence of
// non-whitespace characters) from the start of region [Begin,End).  If no word
// is found before End, return StringRef().  Begin is adjusted to exclude the
// lexed region.
StringRef QueryParser::lexWord() {
  while (true) {
    if (Begin == End)
      return StringRef(Begin, 0);

    if (!isWhitespace(*Begin))
      break;

    ++Begin;
  }

  const char *WordBegin = Begin;

  while (true) {
    ++Begin;

    if (Begin == End || isWhitespace(*Begin))
      return StringRef(WordBegin, Begin - WordBegin);
  }
}

// This is the StringSwitch-alike used by lexOrCompleteWord below. See that
// function for details.
template <typename T> struct QueryParser::LexOrCompleteWord {
  StringSwitch<T> Switch;

  QueryParser *P;
  StringRef Word;
  // Set to the completion point offset in Word, or StringRef::npos if
  // completion point not in Word.
  size_t WordCompletionPos;

  LexOrCompleteWord(QueryParser *P, StringRef Word, size_t WCP)
      : Switch(Word), P(P), Word(Word), WordCompletionPos(WCP) {}

  template <unsigned N>
  LexOrCompleteWord &Case(const char (&S)[N], const T &Value,
                          bool IsCompletion = true) {
    StringRef CaseStr(S, N - 1);

    if (WordCompletionPos == StringRef::npos)
      Switch.Case(S, Value);
    else if (N != 1 && IsCompletion && WordCompletionPos <= CaseStr.size() &&
             CaseStr.substr(0, WordCompletionPos) ==
                 Word.substr(0, WordCompletionPos))
      P->Completions.push_back(LineEditor::Completion(
          (CaseStr.substr(WordCompletionPos) + " ").str(), CaseStr));
    return *this;
  }

  T Default(const T& Value) const {
    return Switch.Default(Value);
  }
};

// Lexes a word and stores it in Word. Returns a LexOrCompleteWord<T> object
// that can be used like a llvm::StringSwitch<T>, but adds cases as possible
// completions if the lexed word contains the completion point.
template <typename T>
QueryParser::LexOrCompleteWord<T>
QueryParser::lexOrCompleteWord(StringRef &Word) {
  Word = lexWord();
  size_t WordCompletionPos = StringRef::npos;
  if (CompletionPos && CompletionPos <= Word.data() + Word.size()) {
    if (CompletionPos < Word.data())
      WordCompletionPos = 0;
    else
      WordCompletionPos = CompletionPos - Word.data();
  }
  return LexOrCompleteWord<T>(this, Word, WordCompletionPos);
}

QueryRef QueryParser::parseSetBool(bool QuerySession::*Var) {
  StringRef ValStr;
  unsigned Value = lexOrCompleteWord<unsigned>(ValStr)
                      .Case("false", 0)
                      .Case("true", 1)
                      .Default(~0u);
  if (Value == ~0u) {
    return new InvalidQuery("expected 'true' or 'false', got '" + ValStr + "'");
  }
  return new SetQuery<bool>(Var, Value);
}

QueryRef QueryParser::parseSetOutputKind() {
  StringRef ValStr;
  unsigned OutKind = lexOrCompleteWord<unsigned>(ValStr)
                         .Case("diag", OK_Diag)
                         .Case("print", OK_Print)
                         .Case("dump", OK_Dump)
                         .Default(~0u);
  if (OutKind == ~0u) {
    return new InvalidQuery("expected 'diag', 'print' or 'dump', got '" +
                            ValStr + "'");
  }
  return new SetQuery<OutputKind>(&QuerySession::OutKind, OutputKind(OutKind));
}

QueryRef QueryParser::endQuery(QueryRef Q) {
  const char *Extra = Begin;
  if (!lexWord().empty())
    return new InvalidQuery("unexpected extra input: '" +
                            StringRef(Extra, End - Extra) + "'");
  return Q;
}

namespace {

enum ParsedQueryKind {
  PQK_Invalid,
  PQK_NoOp,
  PQK_Help,
  PQK_Let,
  PQK_Match,
  PQK_Set,
  PQK_Unlet,
};

enum ParsedQueryVariable {
  PQV_Invalid,
  PQV_Output,
  PQV_BindRoot
};

QueryRef makeInvalidQueryFromDiagnostics(const Diagnostics &Diag) {
  std::string ErrStr;
  llvm::raw_string_ostream OS(ErrStr);
  Diag.printToStreamFull(OS);
  return new InvalidQuery(OS.str());
}

}  // namespace

QueryRef QueryParser::completeMatcherExpression() {
  std::vector<MatcherCompletion> Comps = Parser::completeExpression(
      StringRef(Begin, End - Begin), CompletionPos - Begin, nullptr,
      &QS.NamedValues);
  for (std::vector<MatcherCompletion>::iterator I = Comps.begin(),
                                                E = Comps.end();
       I != E; ++I) {
    Completions.push_back(LineEditor::Completion(I->TypedText, I->MatcherDecl));
  }
  return QueryRef();
}

QueryRef QueryParser::doParse() {
  StringRef CommandStr;
  ParsedQueryKind QKind = lexOrCompleteWord<ParsedQueryKind>(CommandStr)
                              .Case("", PQK_NoOp)
                              .Case("help", PQK_Help)
                              .Case("m", PQK_Match, /*IsCompletion=*/false)
                              .Case("let", PQK_Let)
                              .Case("match", PQK_Match)
                              .Case("set", PQK_Set)
                              .Case("unlet", PQK_Unlet)
                              .Default(PQK_Invalid);

  switch (QKind) {
  case PQK_NoOp:
    return new NoOpQuery;

  case PQK_Help:
    return endQuery(new HelpQuery);

  case PQK_Let: {
    StringRef Name = lexWord();

    if (Name.empty())
      return new InvalidQuery("expected variable name");

    if (CompletionPos)
      return completeMatcherExpression();

    Diagnostics Diag;
    ast_matchers::dynamic::VariantValue Value;
    if (!Parser::parseExpression(StringRef(Begin, End - Begin), nullptr,
                                 &QS.NamedValues, &Value, &Diag)) {
      return makeInvalidQueryFromDiagnostics(Diag);
    }

    return new LetQuery(Name, Value);
  }

  case PQK_Match: {
    if (CompletionPos)
      return completeMatcherExpression();

    Diagnostics Diag;
    Optional<DynTypedMatcher> Matcher = Parser::parseMatcherExpression(
        StringRef(Begin, End - Begin), nullptr, &QS.NamedValues, &Diag);
    if (!Matcher) {
      return makeInvalidQueryFromDiagnostics(Diag);
    }
    return new MatchQuery(*Matcher);
  }

  case PQK_Set: {
    StringRef VarStr;
    ParsedQueryVariable Var = lexOrCompleteWord<ParsedQueryVariable>(VarStr)
                                  .Case("output", PQV_Output)
                                  .Case("bind-root", PQV_BindRoot)
                                  .Default(PQV_Invalid);
    if (VarStr.empty())
      return new InvalidQuery("expected variable name");
    if (Var == PQV_Invalid)
      return new InvalidQuery("unknown variable: '" + VarStr + "'");

    QueryRef Q;
    switch (Var) {
    case PQV_Output:
      Q = parseSetOutputKind();
      break;
    case PQV_BindRoot:
      Q = parseSetBool(&QuerySession::BindRoot);
      break;
    case PQV_Invalid:
      llvm_unreachable("Invalid query kind");
    }

    return endQuery(Q);
  }

  case PQK_Unlet: {
    StringRef Name = lexWord();

    if (Name.empty())
      return new InvalidQuery("expected variable name");

    return endQuery(new LetQuery(Name, VariantValue()));
  }

  case PQK_Invalid:
    return new InvalidQuery("unknown command: " + CommandStr);
  }

  llvm_unreachable("Invalid query kind");
}

QueryRef QueryParser::parse(StringRef Line, const QuerySession &QS) {
  return QueryParser(Line, QS).doParse();
}

std::vector<LineEditor::Completion>
QueryParser::complete(StringRef Line, size_t Pos, const QuerySession &QS) {
  QueryParser P(Line, QS);
  P.CompletionPos = Line.data() + Pos;

  P.doParse();
  return P.Completions;
}

} // namespace query
} // namespace clang
