Skip to content
Snippets Groups Projects
Select Git revision
  • 57db2a2e15f62c7e0e7b627313ce99fa0dcab4df
  • master default protected
  • loss
  • producer
4 results

upper2lower

Blame
  • ActionBank.cpp 18.10 KiB
    #include "ActionBank.hpp"
    #include "util.hpp"
    #include "ProgramParameters.hpp"
    
    std::vector<Action::BasicAction> ActionBank::str2sequence(const std::string & name)
    {
      auto invalidNameAndAbort = [&](const char * errInfo)
      {
        fprintf(stderr, "ERROR (%s) : unknown action name \'%s\' Aborting.\n", errInfo, name.c_str());
    
        exit(1);
      };
    
      std::vector<Action::BasicAction> sequence;
    
      char b1[1024];
      char b2[1024];
      char b3[1024];
      char b4[1024];
    
      if (sscanf(name.c_str(), "%s", b1) != 1)
        invalidNameAndAbort(ERRINFO);
    
      if(std::string(b1) == "WRITE")
      {
        if (sscanf(name.c_str(), "%s %s %s %s", b1, b4, b2, b3) != 4)
          invalidNameAndAbort(ERRINFO);
    
        std::string tapeName(b2);
        std::string value(b3);
        auto object = split(b4, '.');
    
        if (object.size() != 2)
          invalidNameAndAbort(ERRINFO);
    
        if (object[0] == "b")
        {
          int relativeIndex = std::stoi(object[1]);
    
          auto apply = [tapeName, value, relativeIndex](Config & c, Action::BasicAction &)
            {
              simpleBufferWrite(c, tapeName, value, relativeIndex);
            };
          auto undo = [tapeName, relativeIndex](Config & c, Action::BasicAction &)
            {
              simpleBufferWrite(c, tapeName, "", relativeIndex);
            };
          auto appliable = [tapeName, relativeIndex](Config & c, Action::BasicAction &)
            {
              return simpleBufferWriteAppliable(c, tapeName, relativeIndex);
            };
          Action::BasicAction basicAction =
            {Action::BasicAction::Type::Write, value, apply, undo, appliable};
    
          sequence.emplace_back(basicAction);
        }
        else if (object[0] == "s")
        {
           auto apply = [tapeName, value, object](Config & c, Action::BasicAction &)
            {
              int stackIndex = std::stoi(object[1]);
              int bufferIndex = c.stackGetElem(stackIndex);
              int relativeIndex = bufferIndex - c.head;
              simpleBufferWrite(c, tapeName, value, relativeIndex);
            };
          auto undo = [tapeName, object](Config & c, Action::BasicAction &)
            {
              int stackIndex = std::stoi(object[1]);
              int bufferIndex = c.stackGetElem(stackIndex);
              int relativeIndex = bufferIndex - c.head;
              simpleBufferWrite(c, tapeName, "", relativeIndex);
            };
          auto appliable = [tapeName, object](Config & c, Action::BasicAction &)
            {
              int stackIndex = std::stoi(object[1]);
              if (!c.stackHasIndex(stackIndex))
                return false;
              int bufferIndex = c.stackGetElem(stackIndex);
              int relativeIndex = bufferIndex - c.head;
              return simpleBufferWriteAppliable(c, tapeName, relativeIndex);
            };
          Action::BasicAction basicAction =
            {Action::BasicAction::Type::Write, value, apply, undo, appliable};
    
          sequence.emplace_back(basicAction);     
        }
      }
      else if(std::string(b1) == "MULTIWRITE")
      {
        int startRelIndex;
        int endRelIndex;
        
        if (sscanf(name.c_str(), "%s %d %d %s", b1, &startRelIndex, &endRelIndex, b2) != 4)
          invalidNameAndAbort(ERRINFO);
    
        std::string tapeName(b2);
    
        auto splits = split(name);
    
        for(int i = startRelIndex; i <= endRelIndex; i++)
        {
          std::string & value = splits[4+i-startRelIndex];
    
          auto apply = [tapeName, value, i](Config & c, Action::BasicAction &)
            {simpleBufferWrite(c, tapeName, value, i);};
          auto undo = [tapeName, i](Config & c, Action::BasicAction &)
            {simpleBufferWrite(c, tapeName, "", i);};
          auto appliable = [tapeName, i](Config & c, Action::BasicAction &)
            {return simpleBufferWriteAppliable(c, tapeName, i);};
    
          Action::BasicAction basicAction =
            {Action::BasicAction::Type::Write, value, apply, undo, appliable};
    
          sequence.emplace_back(basicAction);
        }
      }
      else if(std::string(b1) == "RULE")
      {
        if (sscanf(name.c_str(), "%s %s ON %s %s", b1, b2, b3, b4) != 4)
          invalidNameAndAbort(ERRINFO);
    
        std::string targetTapeName(b2);
        std::string fromTapeName(b3);
        std::string rule(b4);
    
        auto apply = [fromTapeName, targetTapeName, rule](Config & c, Action::BasicAction &)
          {writeRuleResult(c, fromTapeName, targetTapeName, rule, 0);};
        auto undo = [targetTapeName](Config & c, Action::BasicAction &)
          {simpleBufferWrite(c, targetTapeName, "", 0);};
        auto appliable = [fromTapeName,rule](Config & c, Action::BasicAction &)
          {return isRuleAppliable(c, fromTapeName, 0, rule);};
        Action::BasicAction basicAction =
          {Action::BasicAction::Type::Write, rule, apply, undo, appliable};
    
        sequence.emplace_back(basicAction);
      }
      else if(std::string(b1) == "NOTFOUND")
      {
      }
      else if(std::string(b1) == "NOTHING")
      {
      }
      else if(std::string(b1) == "EPSILON")
      {
      }
      else if(std::string(b1) == "ERROR")
      {
        auto apply = [](Config &, Action::BasicAction &)
          {fprintf(stderr, "ERROR\n");};
        auto undo = [](Config &, Action::BasicAction &)
          {};
        auto appliable = [](Config &, Action::BasicAction &)
          {return true;};
        Action::BasicAction basicAction =
          {Action::BasicAction::Type::Push, "", apply, undo, appliable};
    
        sequence.emplace_back(basicAction);
      }
      else if(std::string(b1) == "CORRECT")
      {
        auto apply = [](Config &, Action::BasicAction &)
          {fprintf(stderr, "CORRECT\n");};
        auto undo = [](Config &, Action::BasicAction &)
          {};
        auto appliable = [](Config &, Action::BasicAction &)
          {return true;};
        Action::BasicAction basicAction =
          {Action::BasicAction::Type::Push, "", apply, undo, appliable};
    
        sequence.emplace_back(basicAction);
      }
      else if(std::string(b1) == "SHIFT")
      {
        auto apply = [](Config & c, Action::BasicAction &)
          {c.stackPush(c.head);};
        auto undo = [](Config & c, Action::BasicAction &)
          {c.stackPop();};
        auto appliable = [](Config & c, Action::BasicAction &)
          {return c.head < (int)c.tapes[0].ref.size()-1;};
        Action::BasicAction basicAction =
          {Action::BasicAction::Type::Push, "", apply, undo, appliable};
    
        sequence.emplace_back(basicAction);
      }
      else if(std::string(b1) == "REDUCE")
      {
        auto apply = [](Config & c, Action::BasicAction & ba)
          {ba.data = std::to_string(c.stackTop());
           c.stackPop();};
        auto undo = [](Config & c, Action::BasicAction & ba)
          {c.stackPush(std::stoi(ba.data));};
        auto appliable = [](Config & c, Action::BasicAction &)
          {return !c.stackEmpty() && !c.getTape("GOV")[c.stackTop()].empty();};
        Action::BasicAction basicAction =
          {Action::BasicAction::Type::Pop, "", apply, undo, appliable};
    
        sequence.emplace_back(basicAction);
      }
      else if(std::string(b1) == "LEFT")
      {
        auto apply = [](Config & c, Action::BasicAction &)
          {
            int b0 = c.head;
            int s0 = c.stackTop();
            simpleBufferWrite(c, "GOV", std::to_string(b0-s0), s0-b0);
          };
        auto undo = [](Config & c, Action::BasicAction &)
          {
            int b0 = c.head;
            int s0 = c.stackTop();
            simpleBufferWrite(c, "GOV", "", s0-b0);
          };
        auto appliable = [](Config & c, Action::BasicAction &)
          {
            if (c.stackEmpty())
              return false;
            int b0 = c.head;
            int s0 = c.stackTop();
            return simpleBufferWriteAppliable(c, "GOV", s0-b0);
          };
        Action::BasicAction basicAction =
          {Action::BasicAction::Type::Write, "", apply, undo, appliable};
    
        sequence.emplace_back(basicAction);
    
        if (sscanf(name.c_str(), "%s %s", b1, b2) == 2)
        {
          auto apply2 = [b2](Config & c, Action::BasicAction &)
            {
              int b0 = c.head;
              int s0 = c.stackTop();
              simpleBufferWrite(c, "LABEL", b2, s0-b0);
            };
          auto undo2 = [](Config & c, Action::BasicAction &)
            {
              int b0 = c.head;
              int s0 = c.stackTop();
              simpleBufferWrite(c, "LABEL", "", s0-b0);
            };
          auto appliable2 = [](Config & c, Action::BasicAction &)
            {
              if (c.stackEmpty())
                return false;
              int b0 = c.head;
              int s0 = c.stackTop();
              return simpleBufferWriteAppliable(c, "LABEL", s0-b0);
            };
          Action::BasicAction basicAction2 =
            {Action::BasicAction::Type::Write, b2, apply2, undo2, appliable2};
    
          sequence.emplace_back(basicAction2);
        }
    
        auto apply3 = [](Config & c, Action::BasicAction & ba)
          {
            ba.data = std::to_string(c.stackTop());
            c.stackPop();
          };
        auto undo3 = [](Config & c, Action::BasicAction & ba)
          {
            c.stackPush(std::stoi(ba.data));
          };
        auto appliable3 = [](Config & c, Action::BasicAction &)
          {
            if (c.stackEmpty())
              return false;
            return !c.isFinal() && c.head < (int)c.tapes[0].ref.size()-1;
          };
        Action::BasicAction basicAction3 =
          {Action::BasicAction::Type::Pop, b1, apply3, undo3, appliable3};
    
        sequence.emplace_back(basicAction3);
      }
      else if(std::string(b1) == "RIGHT")
      {
        auto apply = [](Config & c, Action::BasicAction &)
          {
            int b0 = c.head;
            int s0 = c.stackTop();
            simpleBufferWrite(c, "GOV", std::to_string(s0-b0), 0);
          };
        auto undo = [](Config & c, Action::BasicAction &)
          {
            simpleBufferWrite(c, "GOV", "", 0);
          };
        auto appliable = [](Config & c, Action::BasicAction &)
          {
            return !c.stackEmpty() && simpleBufferWriteAppliable(c, "GOV", 0);
          };
        Action::BasicAction basicAction =
          {Action::BasicAction::Type::Write, "", apply, undo, appliable};
    
        sequence.emplace_back(basicAction);
    
        if (sscanf(name.c_str(), "%s %s", b1, b2) == 2)
        {
          auto apply2 = [b2](Config & c, Action::BasicAction &)
            {
              simpleBufferWrite(c, "LABEL", b2, 0);
            };
          auto undo2 = [](Config & c, Action::BasicAction &)
            {
              simpleBufferWrite(c, "LABEL", "", 0);
            };
          auto appliable2 = [](Config & c, Action::BasicAction &)
            {
              return simpleBufferWriteAppliable(c, "LABEL", 0);
            };
          Action::BasicAction basicAction2 =
            {Action::BasicAction::Type::Write, b2, apply2, undo2, appliable2};
    
          sequence.emplace_back(basicAction2);
        }
    
        auto apply3 = [](Config & c, Action::BasicAction &)
          {
            c.stackPush(c.head);
          };
        auto undo3 = [](Config & c, Action::BasicAction &)
          {
            c.stackPop();
          };
        auto appliable3 = [](Config & c, Action::BasicAction &)
          {
            return !c.isFinal() && c.head < (int)c.tapes[0].ref.size()-1;
          };
        Action::BasicAction basicAction3 =
          {Action::BasicAction::Type::Push, b1, apply3, undo3, appliable3};
    
        sequence.emplace_back(basicAction3);
      }
      else if(std::string(b1) == "EOS")
      {
        auto apply0 = [b2](Config & c, Action::BasicAction &)
          {
            int b0 = c.head;
            int s0 = c.stackTop();
            simpleBufferWrite(c, ProgramParameters::sequenceDelimiterTape, ProgramParameters::sequenceDelimiter, s0-b0);
          };
        auto undo0 = [](Config & c, Action::BasicAction)
          {
            int b0 = c.head;
            int s0 = c.stackTop();
            simpleBufferWrite(c, ProgramParameters::sequenceDelimiterTape, "", s0-b0);
          };
        auto appliable0 = [](Config & c, Action::BasicAction &)
          {
            return !c.isFinal() && !c.stackEmpty();
          };
        Action::BasicAction basicAction0 =
          {Action::BasicAction::Type::Write, "", apply0, undo0, appliable0};
    
        sequence.emplace_back(basicAction0);
    
        auto apply = [](Config & c, Action::BasicAction & ba)
          {
            auto & govs = c.getTape("GOV");
            int b0 = c.head;
            int rootIndex = -1;
            for (int i = c.stackSize()-1; i >= 0; i--)
            {
              auto s = c.stackGetElem(i);
              if (govs.hyp[s].empty() || govs.hyp[s] == "0")
              {
                if (rootIndex == -1)
                  rootIndex = s;
                else
                {
                  simpleBufferWrite(c, "GOV", std::to_string(rootIndex - s), s-b0);
                  ba.data += "+"+s-b0;
                }
              }
            }
    
            simpleBufferWrite(c, "GOV", "0", rootIndex-b0);
          };
        auto undo = [](Config & c, Action::BasicAction & ba)
          {
            auto & govs = c.getTape("GOV");
            int b0 = c.head;
            for (int i = c.stackSize()-1; i >= 0; i--)
            {
              auto s = c.stackGetElem(i);
              if (govs.hyp[s] == "0")
              {
                simpleBufferWrite(c, "GOV", "", s-b0);
                break;
              }
            }
            auto deps = split(ba.data, '+');
            for (auto s : deps)
              simpleBufferWrite(c, "GOV", "", std::stoi(s));
            ba.data.clear();
          };
        auto appliable = [](Config & c, Action::BasicAction &)
          {
            return !c.stackEmpty();
          };
        Action::BasicAction basicAction =
          {Action::BasicAction::Type::Write, "", apply, undo, appliable};
    
        sequence.emplace_back(basicAction);
    
        auto apply2 = [b2](Config & c, Action::BasicAction & ba)
          {
            auto & labels = c.getTape("LABEL");
            int b0 = c.head;
            int rootIndex = -1;
    
            for (int i = c.stackSize()-1; i >= 0; i--)
            {
              auto s = c.stackGetElem(i);
              if (labels.hyp[s].empty())
              {
                if (rootIndex == -1)
                {
                  rootIndex = 0;
                  simpleBufferWrite(c, "LABEL", "root", s-b0);
                }
                else
                {
                  simpleBufferWrite(c, "LABEL", "_", s-b0);
                  ba.data += "+"+std::to_string(s-b0);
                }
              }
            }
          };
        auto undo2 = [](Config & c, Action::BasicAction & ba)
          {
            auto & labels = c.getTape("LABEL");
            int b0 = c.head;
    
            for (int i = c.stackSize()-1; i >= 0; i--)
            {
              auto s = c.stackGetElem(i);
              if (labels.hyp[s] == "root")
              {
                simpleBufferWrite(c, "LABEL", "", s-b0);
                break;
              }
            }
            auto deps = split(ba.data, '+');
            for (auto & dep : deps)
              simpleBufferWrite(c, "LABEL", "", std::stoi(dep));
          };
        auto appliable2 = [](Config & c, Action::BasicAction &)
          {
            return !c.stackEmpty();
          };
        Action::BasicAction basicAction2 =
          {Action::BasicAction::Type::Write, "", apply2, undo2, appliable2};
    
        sequence.emplace_back(basicAction2);
    
        auto apply4 = [b2](Config & c, Action::BasicAction & ba)
          {
            ba.data = "";
            for (int i = c.stackSize()-1; i >= 0; i--)
            {
              auto s = c.stackGetElem(i);
              ba.data += std::to_string(s) + " ";
            }
    
            while (!c.stackEmpty())
              c.stackPop();
          };
        auto undo4 = [](Config & c, Action::BasicAction & ba)
          {
            auto elems = split(ba.data);
            for (auto elem : elems)
              c.stackPush(std::stoi(elem));
          };
        auto appliable4 = [](Config & c, Action::BasicAction &)
          {
            return !c.isFinal() && !c.stackEmpty();
          };
        Action::BasicAction basicAction4 =
          {Action::BasicAction::Type::Pop, "", apply4, undo4, appliable4};
    
        sequence.emplace_back(basicAction4);
      }
      else if(std::string(b1) == "BACK")
      {
        if (sscanf(name.c_str(), "%s %s", b1, b2) != 2)
          invalidNameAndAbort(ERRINFO);
    
        if (isNum(b2))
        {
          int dist = std::stoi(b2);
    
          auto apply = [dist](Config & c, Action::BasicAction &)
            {
              static auto undoOneTime = [](Config & c)
              {
                while (true)
                {
                  auto a = c.pastActions.pop();
                  if (ProgramParameters::debug)
                    fprintf(stderr, "Undoing... <%s>\n", a.second.name.c_str());
                  a.second.undoOnlyStack(c);
    
                  if (a.first == "tagger")
                    return;
                }
              };
    
              static auto undoForReal = [](Config & c)
              {
                while (true)
                {
                  auto a = c.pastActions.pop();
                  if (ProgramParameters::debug)
                    fprintf(stderr, "Undoing... <%s>\n", a.second.name.c_str());
    
                  if (a.first == "tagger")
                  {
                    a.second.undo(c);
                    return;
                  }
                  a.second.undoOnlyStack(c);
                }
              };
    
              undoOneTime(c);
              for (int i = 0; i < dist-1; i++)
                undoOneTime(c);
    
              undoForReal(c);
            };
          auto undo = [dist](Config &, Action::BasicAction &)
            {
            };
          auto appliable = [dist](Config &, Action::BasicAction &)
            {
              return true;
            };
          Action::BasicAction basicAction =
            {Action::BasicAction::Type::Write, "", apply, undo, appliable};
    
          sequence.emplace_back(basicAction);
        }
        else
        {
          invalidNameAndAbort(ERRINFO);
        }
      }
      else
        invalidNameAndAbort(ERRINFO);
    
      return sequence;
    }
    
    void ActionBank::simpleBufferWrite(Config & config, const std::string & tapeName, 
      const std::string & value, int relativeIndex)
    {
      auto & tape = config.getTape(tapeName);
    
      int index = config.head + relativeIndex;
    
      tape.hyp[index] = value;
    }
    
    bool ActionBank::simpleBufferWriteAppliable(Config & config,
      const std::string & tapeName, int relativeIndex)
    {
      auto & tape = config.getTape(tapeName);
    
      int index = config.head + relativeIndex;
    
      if (index == (int)tape.hyp.size()-1)
        return true;
    
      return (!(index < 0 || index >= (int)tape.hyp.size()));
    }
    
    bool ActionBank::isRuleAppliable(Config & config,
      const std::string & tapeName, int relativeIndex, const std::string & rule)
    {
      if (!simpleBufferWriteAppliable(config, tapeName, relativeIndex))
        return false;
      return ruleIsAppliable(config.getTape(tapeName)[config.head+relativeIndex], rule);
    }
    
    void ActionBank::writeRuleResult(Config & config, const std::string & fromTapeName, const std::string & targetTapeName, const std::string & rule, int relativeIndex)
    {
      auto & fromTape = config.getTape(fromTapeName);
      auto & toTape = config.getTape(targetTapeName);
    
      auto & from = fromTape.ref[config.head + relativeIndex];
    
      toTape.hyp[config.head + relativeIndex] = applyRule(from, rule);
    }
    
    int ActionBank::getLinkLength(const Config & c, const std::string & action)
    {
      auto splitted = split(action, ' ');
      auto & name = splitted[0];
      if (name == "LEFT" || name == "RIGHT" || name == "EOS")
      {
        if (c.stackEmpty())
        {
          fprintf(stderr, "ERROR (%s) : stack is empty. Aborting.\n", ERRINFO);
          exit(1);
        }
    
        int stackIndex = c.stackGetElem(0);
        return std::abs(c.head - stackIndex);
      }
    
      return 0;
    }