Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzBase includes
Toshihiro Shimizu 890ddd
#include "tgrammar.h"
Toshihiro Shimizu 890ddd
#include "tparser.h"
Toshihiro Shimizu 890ddd
#include "tunit.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "texpression.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using namespace TSyntax;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//**********************************************************************************
Toshihiro Shimizu 890ddd
//    TExpression::Imp  definition
Toshihiro Shimizu 890ddd
//**********************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class TExpression::Imp {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  const Grammar *m_grammar;  //!< (not owned) The expression's grammar
Shinya Kitaoka 120a6e
  TDoubleParam *m_param;     //!< (not owned) The expression's owner
Shinya Kitaoka 120a6e
  Calculator *m_calculator;  //!< (owned) Expression calculator object
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  std::string m_text;  //!< Text content
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  std::string m_error;  //!< Description of an error in the expression's text
Shinya Kitaoka 120a6e
  std::pair<int, int=""></int,>
Shinya Kitaoka 120a6e
      m_errorPos;  //!< Position of the error in the expression's text
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  bool m_isValid,       //!< Whether the expression is valid
shun-iwasawa 4a3868
      m_hasBeenParsed,  //!< Whether the expression has already been parsed
shun-iwasawa 4a3868
      m_hasReference;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  Imp()
Shinya Kitaoka 120a6e
      : m_grammar(0)
Shinya Kitaoka 120a6e
      , m_param(0)
Shinya Kitaoka 120a6e
      , m_calculator(0)
Shinya Kitaoka 120a6e
      , m_errorPos(0, -1)
Shinya Kitaoka 120a6e
      , m_isValid(false)
shun-iwasawa 4a3868
      , m_hasBeenParsed(true)
shun-iwasawa 4a3868
      , m_hasReference(false) {}
Shinya Kitaoka 120a6e
  ~Imp() { delete m_calculator; }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//**********************************************************************************
Toshihiro Shimizu 890ddd
//    TExpression  implementation
Toshihiro Shimizu 890ddd
//**********************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TExpression::TExpression() : m_imp(new Imp()) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TExpression::~TExpression() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TExpression::TExpression(const TExpression &src) : m_imp(new Imp()) {
Shinya Kitaoka 120a6e
  m_imp->m_grammar       = src.m_imp->m_grammar;
Shinya Kitaoka 120a6e
  m_imp->m_param         = src.m_imp->m_param;
Shinya Kitaoka 120a6e
  m_imp->m_text          = src.m_imp->m_text;
Shinya Kitaoka 120a6e
  m_imp->m_calculator    = 0;
Shinya Kitaoka 120a6e
  m_imp->m_isValid       = src.m_imp->m_isValid;
Shinya Kitaoka 120a6e
  m_imp->m_error         = src.m_imp->m_error;
Shinya Kitaoka 120a6e
  m_imp->m_errorPos      = src.m_imp->m_errorPos;
Shinya Kitaoka 120a6e
  m_imp->m_hasBeenParsed = false;
shun-iwasawa 4a3868
  m_imp->m_hasReference  = src.m_imp->m_hasReference;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TExpression &TExpression::operator=(TExpression copy) {
Shinya Kitaoka 120a6e
  std::swap(copy.m_imp, m_imp);
Shinya Kitaoka 120a6e
  return *this;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TExpression::setGrammar(const TSyntax::Grammar *grammar) {
Shinya Kitaoka 120a6e
  m_imp->m_grammar       = grammar;
Shinya Kitaoka 120a6e
  m_imp->m_hasBeenParsed = false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
const TSyntax::Grammar *TExpression::getGrammar() const {
Shinya Kitaoka 120a6e
  return m_imp->m_grammar;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TExpression::setText(std::string text) {
shun-iwasawa 4a3868
  if (m_imp->m_text != text || m_imp->m_hasReference) {
Shinya Kitaoka 120a6e
    m_imp->m_text = text;
Shinya Kitaoka 120a6e
    delete m_imp->m_calculator;
Shinya Kitaoka 120a6e
    m_imp->m_calculator    = 0;
Shinya Kitaoka 120a6e
    m_imp->m_isValid       = false;
shun-iwasawa 4a3868
    m_imp->m_hasReference  = false;
Shinya Kitaoka 120a6e
    m_imp->m_hasBeenParsed = false;
Shinya Kitaoka 120a6e
    m_imp->m_error         = "";
Shinya Kitaoka 120a6e
    m_imp->m_errorPos      = std::make_pair(0, -1);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
std::string TExpression::getText() const { return m_imp->m_text; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// note: unit is used by the CycleNode node only
Shinya Kitaoka 120a6e
TSyntax::Calculator *TExpression::getCalculator() {
Shinya Kitaoka 120a6e
  if (!m_imp->m_hasBeenParsed) parse();
Shinya Kitaoka 120a6e
  if (m_imp->m_isValid && m_imp->m_calculator)
Shinya Kitaoka 120a6e
    return m_imp->m_calculator;
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    return 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TExpression::isValid() {
Shinya Kitaoka 120a6e
  if (!m_imp->m_hasBeenParsed) parse();
Shinya Kitaoka 120a6e
  return m_imp->m_isValid;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
std::string TExpression::getError() const { return m_imp->m_error; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
std::pair<int, int=""> TExpression::getErrorPos() const {</int,>
Shinya Kitaoka 120a6e
  return m_imp->m_errorPos;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TExpression::accept(TSyntax::CalculatorNodeVisitor &visitor) {
Shinya Kitaoka 120a6e
  if (!m_imp->m_hasBeenParsed) parse();
Shinya Kitaoka 120a6e
  if (m_imp->m_isValid && m_imp->m_calculator)
Shinya Kitaoka 120a6e
    m_imp->m_calculator->accept(visitor);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TExpression::parse() {
Shinya Kitaoka 120a6e
  delete m_imp->m_calculator;
Shinya Kitaoka 120a6e
  m_imp->m_calculator = 0;
Toshihiro Shimizu 890ddd
shun-iwasawa 4a3868
  m_imp->m_errorPos     = std::make_pair(0, -1);
shun-iwasawa 4a3868
  m_imp->m_error        = std::string();
shun-iwasawa 4a3868
  m_imp->m_hasReference = false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (!m_imp->m_grammar) {
Shinya Kitaoka 120a6e
    m_imp->m_error   = "No grammar defined";
Shinya Kitaoka 120a6e
    m_imp->m_isValid = false;
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    Parser parser(m_imp->m_grammar);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    m_imp->m_calculator = parser.parse(m_imp->m_text);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (m_imp->m_calculator)
Shinya Kitaoka 120a6e
      m_imp->m_calculator->setOwnerParameter(m_imp->m_param);
Toshihiro Shimizu 890ddd
shun-iwasawa 4a3868
    m_imp->m_isValid      = parser.isValid();
shun-iwasawa 4a3868
    m_imp->m_hasReference = parser.hasReference();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (!m_imp->m_isValid) {
Shinya Kitaoka 120a6e
      m_imp->m_error    = parser.getError();
Shinya Kitaoka 120a6e
      m_imp->m_errorPos = parser.getErrorPos();
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_imp->m_hasBeenParsed = true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TExpression::setOwnerParameter(TDoubleParam *param) {
Shinya Kitaoka 120a6e
  m_imp->m_param = param;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (m_imp->m_calculator) m_imp->m_calculator->setOwnerParameter(param);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TDoubleParam *TExpression::getOwnerParameter() const { return m_imp->m_param; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TExpression::isCycling() const {
Shinya Kitaoka 120a6e
  // TODO: this is a quick&dirty implementation to be replaced with a more
Shinya Kitaoka 120a6e
  // "semantic" one
Shinya Kitaoka 120a6e
  return getText().find("cycle") != std::string::npos;
Toshihiro Shimizu 890ddd
}