#include"mkf_book.hpp"
#include"mkf_identifier.hpp"
#include<cstdlib>




void
Book::
append(const char*  id, Element&&  el)
{
  sub_definitions.emplace_back(id,std::move(el));
}


void
Book::
make(const std::string&  s)
{
  auto  p = s.data();

  const char*  last = nullptr;

  bool  lost_first = false;

    while(*p)
    {
      auto  last = p;

        if(lost_first)
        {
          sub_definitions.emplace_back(p);
        }

      else
        {
          main_definition.reset(p);

          lost_first = true;
        }


      skip_space(p);

        if(p == last)
        {
          report;
          printf("**loop**%s\n",p);
          break;
        }
    }
}


void
Book::
clear()
{
  sub_definitions.clear();
}


const Definition*
Book::
find(const Identifier&  id) const
{
    for(auto&  def: sub_definitions)
    {
        if(def.get_identifier() == id)
        {
          return &def;
        }
    }


  return nullptr;
}


Node
Book::
parse(const std::string&  s) const
{
  Node  root;

  auto        p0 =    s.data();
  auto  const p1 = p0+s.size();

    while(p0 < p1)
    {
      auto  child = new Node(&main_definition);

      auto  p = p0;

      CompareContext  ctx(p,p1,child);

        if(!compare(ctx,main_definition))
        {
          delete child;

          printf("一致する定義がありませんでした。以下は残りのテキスト\n");
          printf("%s\n",p0);
          printf("残りのテキスト終わり\n");

          auto  nd = subparse(p0);

          nd.print();

          break;
        }


        if(p0 == p)
        {
          report;
          printf("**looping**");
          break;
        }


      p0 = p;

      root.append(child);
    }


  return std::move(root);
}


Node
Book::
subparse(const std::string&  s) const
{
  Node  root;

  auto        p0 =    s.data();
  auto  const p1 = p0+s.size();

    while(p0 < p1)
    {
      const char*  p_max = p0;

      Node*  child_max = nullptr;

        for(auto&  def: sub_definitions)
        {
          const char*  p = p0;

          auto  child = new Node(&def);

          CompareContext  ctx(p,p1,child);

            if(compare(ctx,def))
            {
              p_max = p;
              child_max = child;

              break;
            }


          delete child;
        }


        if(!child_max)
        {
          printf("一致する定義がありませんでした。以下は残りのテキスト\n");
          printf("%s\n",p0);
          printf("残りのテキスト終わり\n");


          break;
        }


        if(p0 == p_max)
        {
          report;
          printf("**looping**");
          break;
        }


      p0 = p_max;

      root.append(child_max);
    }


  return std::move(root);
}


void
Book::
print() const
{
  printf("book has a main definition.\n");

  main_definition.print();

  printf("\n");

  printf("book has %4d sub definitions.\n",sub_definitions.size());

  printf("--------\n");

    for(auto&  def: sub_definitions)
    {
      def.print();

      printf("\n");
    }


  printf("--------\n");
}




