#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); 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 &, const Action &) { return true; }; 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}; } 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) { 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) { 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))) { 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); } } } }; 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.isToken(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.isToken(i)) continue; if (config.getLastNotEmptyHypConst(Config::EOSColName, i) == Config::EOSSymbol1) break; config.getFirstEmpty(Config::idColName, i) = fmt::format("{}", currentId); ++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); } return addHypothesisRelative(Config::headColName, dependentObject, dependentIndex, std::to_string(govLineIndex)).appliable(config, action); }; 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; }