/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file LICENSE.rst or https://cmake.org/licensing for details.  */
#include "cmExprParserHelper.h"

#include <iostream>
#include <sstream>
#include <stdexcept>
#include <utility>

#include "cmExprLexer.h"
#include "cmStringAlgorithms.h"

int cmExpr_yyparse(yyscan_t yyscanner);
//
cmExprParserHelper::cmExprParserHelper()
{
  this->FileLine = -1;
  this->FileName = nullptr;
  this->Result = 0;
}

cmExprParserHelper::~cmExprParserHelper() = default;

int cmExprParserHelper::ParseString(char const* str, int verb)
{
  if (!str) {
    return 0;
  }
  // printf("Do some parsing: %s\n", str);

  this->Verbose = verb;
  this->InputBuffer = str;
  this->InputBufferPos = 0;
  this->CurrentLine = 0;

  this->Result = 0;

  yyscan_t yyscanner;
  cmExpr_yylex_init(&yyscanner);
  cmExpr_yyset_extra(this, yyscanner);

  try {
    int res = cmExpr_yyparse(yyscanner);
    if (res != 0) {
      std::string e =
        cmStrCat("cannot parse the expression: \"", this->InputBuffer,
                 "\": ", this->ErrorString, '.');
      this->SetError(std::move(e));
    }
  } catch (std::runtime_error const& fail) {
    std::string e = cmStrCat("cannot evaluate the expression: \"",
                             this->InputBuffer, "\": ", fail.what(), '.');
    this->SetError(std::move(e));
  } catch (std::out_of_range const&) {
    std::string e =
      cmStrCat("cannot evaluate the expression: \"", this->InputBuffer,
               "\": a numeric value is out of range.");
    this->SetError(std::move(e));
  } catch (...) {
    std::string e =
      cmStrCat("cannot parse the expression: \"", this->InputBuffer, "\".");
    this->SetError(std::move(e));
  }
  cmExpr_yylex_destroy(yyscanner);
  if (!this->ErrorString.empty()) {
    return 0;
  }

  if (this->Verbose) {
    std::cerr << "Expanding [" << str << "] produced: [" << this->Result << "]"
              << std::endl;
  }
  return 1;
}

int cmExprParserHelper::LexInput(char* buf, int maxlen)
{
  // std::cout << "JPLexInput ";
  // std::cout.write(buf, maxlen);
  // std::cout << std::endl;
  if (maxlen < 1) {
    return 0;
  }
  if (this->InputBufferPos < this->InputBuffer.size()) {
    buf[0] = this->InputBuffer[this->InputBufferPos++];
    if (buf[0] == '\n') {
      this->CurrentLine++;
    }
    return (1);
  }
  buf[0] = '\n';
  return (0);
}

void cmExprParserHelper::Error(char const* str)
{
  unsigned long pos = static_cast<unsigned long>(this->InputBufferPos);
  std::ostringstream ostr;
  ostr << str << " (" << pos << ")";
  this->ErrorString = ostr.str();
}

void cmExprParserHelper::UnexpectedChar(char c)
{
  unsigned long pos = static_cast<unsigned long>(this->InputBufferPos);
  std::ostringstream ostr;
  ostr << "Unexpected character in expression at position " << pos << ": " << c
       << "\n";
  this->WarningString += ostr.str();
}

void cmExprParserHelper::SetResult(KWIML_INT_int64_t value)
{
  this->Result = value;
}

void cmExprParserHelper::SetError(std::string errorString)
{
  this->ErrorString = std::move(errorString);
}
