Skip to content
Snippets Groups Projects
Action.cpp 10.1 KiB
Newer Older
  • Learn to ignore specific revisions
  • #include "Action.hpp"
    
    
    Action::Action(Action::Type type, std::function<void(Config & config, Action & action)> apply, std::function<void(Config & config, Action & action)> undo, std::function<bool(const Config & config, const Action & action)> appliable)
    
    {
      this->type = type;
      this->apply = apply;
      this->undo = undo;
      this->appliable = appliable;
    }
    
    Action Action::addLinesIfNeeded(int nbLines)
    {
      auto apply = [nbLines](Config & config, Action &)
      {
        config.addLines(1);
      };
    
      auto undo = [](Config &, Action &)
      {
      };
    
    
      auto appliable = [](const Config &, const Action &)
    
      {
        return true;
      };
    
      return {Type::AddLines, apply, undo, appliable};
    }
    
    Action Action::moveWordIndex(int movement)
    {
      auto apply = [movement](Config & config, Action &)
      {
        config.moveWordIndex(movement);
      };
    
      auto undo = [movement](Config & config, Action &)
      {
    
        config.moveWordIndex(-movement);
    
      auto appliable = [movement](const Config & config, const Action &)
    
        return config.canMoveWordIndex(movement);
    
      };
    
      return {Type::MoveWord, apply, undo, appliable};
    }
    
    Action Action::moveCharacterIndex(int movement)
    {
      auto apply = [movement](Config & config, Action &)
      {
        config.moveCharacterIndex(movement);
      };
    
      auto undo = [movement](Config & config, Action &)
      {
    
        config.moveCharacterIndex(-movement);
    
      auto appliable = [movement](const Config & config, const Action &)
    
        return config.canMoveCharacterIndex(movement);
    
      };
    
      return {Type::MoveChar, apply, undo, appliable};
    }
    
    
    Action Action::addHypothesis(const std::string & colName, std::size_t lineIndex, const std::string & hypothesis)
    {
      auto apply = [colName, lineIndex, hypothesis](Config & config, Action &)
      {
        config.getFirstEmpty(colName, lineIndex) = hypothesis;
      };
    
      auto undo = [colName, lineIndex](Config & config, Action &)
      {
        config.getLastNotEmpty(colName, lineIndex) = "";
      };
    
    
      auto appliable = [colName, lineIndex](const Config & config, const Action &)
    
      {
        return config.has(colName, lineIndex, 0);
      };
    
      return {Type::Write, apply, undo, appliable}; 
    }
    
    Action Action::addHypothesisRelative(const std::string & colName, Object object, int relativeIndex, const std::string & hypothesis)
    {
      auto apply = [colName, object, relativeIndex, hypothesis](Config & config, Action & a)
      {
        int lineIndex = 0;
        if (object == Object::Buffer)
          lineIndex = config.getWordIndex() + relativeIndex;
        else
          lineIndex = config.getStack(relativeIndex);
    
    
    Franck Dary's avatar
    Franck Dary committed
        return addHypothesis(colName, lineIndex, hypothesis).apply(config, a);
    
      };
    
      auto undo = [colName, object, relativeIndex](Config & config, Action & a)
      {
        int lineIndex = 0;
        if (object == Object::Buffer)
          lineIndex = config.getWordIndex() + relativeIndex;
        else
          lineIndex = config.getStack(relativeIndex);
    
        return addHypothesis(colName, lineIndex, "").undo(config, a);
      };
    
    
      auto appliable = [colName, object, relativeIndex](const Config & config, const Action & a)
    
      {
        int lineIndex = 0;
        if (object == Object::Buffer)
          lineIndex = config.getWordIndex() + relativeIndex;
        else if (config.hasStack(relativeIndex))
          lineIndex = config.getStack(relativeIndex);
        else
          return false;
    
        return addHypothesis(colName, lineIndex, "").appliable(config, a);
      };
    
      return {Type::Write, apply, undo, appliable}; 
    }
    
    
    Action Action::pushWordIndexOnStack()
    {
      auto apply = [](Config & config, Action &)
      {
        config.addToStack(config.getWordIndex());
      };
    
      auto undo = [](Config & config, Action &)
      {
        config.popStack();
      };
    
    
      auto appliable = [](const Config & config, const Action &)
    
        if (config.hasStack(0) and config.getStack(0) == config.getWordIndex())
          return false;
    
        return (int)config.getWordIndex() != config.getLastPoppedStack();
    
      };
    
      return {Type::Push, apply, undo, appliable}; 
    }
    
    Action Action::popStack()
    {
      auto apply = [](Config & config, Action & a)
      {
        auto toSave = config.getStack(0);
        a.data.push_back(std::to_string(toSave));
        config.popStack();
      };
    
      auto undo = [](Config & config, Action & a)
      {
        config.addToStack(std::stoi(a.data.back()));
      };
    
      auto appliable = [](const Config & config, const Action &)
      {
        return config.hasStack(0);
      };
    
      return {Type::Pop, apply, undo, appliable}; 
    }
    
    
    Franck Dary's avatar
    Franck Dary committed
    Action Action::emptyStack()
    {
      auto apply = [](Config & config, Action & a)
      {
        while (config.hasStack(0))
        {
          a.data.push_back(std::to_string(config.getStack(0)));
          config.popStack();
        }
      };
    
      auto undo = [](Config & config, Action & a)
      {
        while (a.data.size())
        {
          config.addToStack(std::stoi(a.data.back()));
          a.data.pop_back();
        }
      };
    
      auto appliable = [](const Config & config, const Action &)
      {
        return true;
      };
    
      return {Type::Pop, apply, undo, appliable}; 
    }
    
    Action Action::setRoot()
    {
      auto apply = [](Config & config, Action & a)
      {
        int rootIndex = -1;
    
    
        for (int i = config.getStack(0); true; --i)
    
    Franck Dary's avatar
    Franck Dary committed
        {
          if (!config.has(0, i, 0))
          {
            if (i < 0)
              break;
            util::myThrow("The current sentence is too long to be completly held by the data strucure. Consider increasing SubConfig::SpanSize");
          }
          if (!config.isToken(i))
            continue;
    
          if (config.getLastNotEmptyHypConst(Config::EOSColName, i) == Config::EOSSymbol1)
            break;
    
          if (util::isEmpty(config.getLastNotEmptyHypConst(Config::headColName, i)))
          {
            rootIndex = i;
            a.data.push_back(std::to_string(i));
          }
        }
    
    
        for (int i = config.getStack(0); true; --i)
    
    Franck Dary's avatar
    Franck Dary committed
        {
          if (!config.has(0, i, 0))
          {
            if (i < 0)
              break;
            util::myThrow("The current sentence is too long to be completly held by the data strucure. Consider increasing SubConfig::SpanSize");
          }
          if (!config.isToken(i))
            continue;
    
          if (config.getLastNotEmptyHypConst(Config::EOSColName, i) == Config::EOSSymbol1)
            break;
    
    
          if (util::isEmpty(config.getLastNotEmptyHypConst(Config::headColName, i)))
    
    Franck Dary's avatar
    Franck Dary committed
          {
            if (i == rootIndex)
            {
              config.getFirstEmpty(Config::headColName, i) = "0";
              config.getFirstEmpty(Config::deprelColName, i) = "root";
            }
            else
            {
    
              config.getFirstEmpty(Config::headColName, i) = std::to_string(rootIndex);
    
    Franck Dary's avatar
    Franck Dary committed
            }
          }
        }
    
      };
    
      auto undo = [](Config & config, Action & a)
      {
        while (a.data.size())
        {
          config.getLastNotEmptyHyp(Config::headColName, std::stoi(a.data.back())) = "";
          a.data.pop_back();
        }
      };
    
      auto appliable = [](const Config & config, const Action &)
      {
        return config.hasStack(0);
      };
    
      return {Type::Write, apply, undo, appliable}; 
    }
    
    
    Action Action::updateIds()
    {
      auto apply = [](Config & config, Action & a)
      {
        int firstIndexOfSentence = -1;
    
        for (int i = config.getStack(0); true; --i)
    
        {
          if (!config.has(0, i, 0))
          {
            if (i < 0)
              break;
            util::myThrow("The current sentence is too long to be completly held by the data strucure. Consider increasing SubConfig::SpanSize");
          }
    
          if (config.isComment(i) || config.isEmptyNode(i))
    
            continue;
    
          if (config.getLastNotEmptyHypConst(Config::EOSColName, i) == Config::EOSSymbol1)
            break;
    
          firstIndexOfSentence = i;
        }
    
        if (firstIndexOfSentence < 0)
          util::myThrow("could not find any token in current sentence");
    
    
        for (unsigned int i = firstIndexOfSentence, currentId = 1; i <= config.getStack(0); ++i)
    
          if (config.isComment(i) || config.isEmptyNode(i))
    
            continue;
    
          if (config.getLastNotEmptyHypConst(Config::EOSColName, i) == Config::EOSSymbol1)
            break;
    
    
          if (config.isMultiword(i))
            config.getFirstEmpty(Config::idColName, i) = fmt::format("{}-{}", currentId, currentId+config.getMultiwordSize(i));
          else
            config.getFirstEmpty(Config::idColName, i) = fmt::format("{}", currentId++);
    
        }
      };
    
      auto undo = [](Config & config, Action & a)
      {
        // TODO : undo this
      };
    
      auto appliable = [](const Config &, const Action &)
      {
        return true;
      };
    
      return {Type::Write, apply, undo, appliable}; 
    }
    
    
    Action Action::attach(Object governorObject, int governorIndex, Object dependentObject, int dependentIndex)
    {
      auto apply = [governorObject, governorIndex, dependentObject, dependentIndex](Config & config, Action & a)
      {
        int lineIndex = 0;
        if (governorObject == Object::Buffer)
          lineIndex = config.getWordIndex() + governorIndex;
        else
          lineIndex = config.getStack(governorIndex);
    
        addHypothesisRelative(Config::headColName, dependentObject, dependentIndex, std::to_string(lineIndex)).apply(config, a);
    
      };
    
      auto undo = [governorObject, governorIndex, dependentObject, dependentIndex](Config & config, Action & a)
      {
        addHypothesisRelative(Config::headColName, dependentObject, dependentIndex, "").undo(config, a);
      };
    
      auto appliable = [governorObject, governorIndex, dependentObject, dependentIndex](const Config & config, const Action & action)
      {
        int govLineIndex = 0;
        if (governorObject == Object::Buffer)
        {
          govLineIndex = config.getWordIndex() + governorIndex;
          if (!config.has(0, govLineIndex, 0))
            return false;
        }
        else
        {
          if (!config.hasStack(governorIndex))
            return false;
          govLineIndex = config.getStack(governorIndex);
        }
    
    
        int depLineIndex = 0;
        if (dependentObject == Object::Buffer)
        {
          depLineIndex = config.getWordIndex() + dependentIndex;
          if (!config.has(0, depLineIndex, 0))
            return false;
        }
        else
        {
          if (!config.hasStack(dependentIndex))
            return false;
          depLineIndex = config.getStack(dependentIndex);
        }
    
        // Check for cycles
        while (govLineIndex != depLineIndex)
        {
          try
          {
            govLineIndex = std::stoi(config.getLastNotEmptyHypConst(Config::headColName, govLineIndex));
          } catch(std::exception &) {return true;}
        }
    
        return false;
    
      };
    
      return {Type::Write, apply, undo, appliable}; 
    }
    
    
    Action::Object Action::str2object(const std::string & s)
    {
      if (s == "b")
        return Object::Buffer;
      if (s == "s")
        return Object::Stack;
    
      util::myThrow(fmt::format("Invalid object '{}'", s));
      return Object::Buffer;
    }