

//
//  BnfParser おためし
//
//  BNF と XML は 而さん が作成されたものをほぼそのままパクっています．
//  http://tamachan.club.kyutech.ac.jp/~gridbug/spirit/spirit04.html
//
//  この test03_2.cpp では，test03.cpp を改良して
//  想定通りの解析が行えるようにしています．
//  BNFの改良ではなく，コールバックを改良しています．
//

#include <fstream>
#include <string>
#include <cstdio>

#include "../bnf.hpp"

using namespace std;

//
//   ルールがマッチする毎に呼ばれるコールバック関数
//

static string name_buf = ""; // タグ名を一応ここにバッファしておきます．

bool matched_callback(
    void * _str,
    char const * _rn,
    int start,
    int length)
{
  string rulename = _rn;
  string& str = *(static_cast<string*>(_str));
  
  if (length < 0)
  {
    // メタ情報は，このサンプルでは無視します
  }
  else if (rulename == "emptyelem_name_r"
      || rulename == "etag_name_r"
      || rulename == "stag_name_r")
  {
    // まだ何を表す名前なのか決定できないので
    // とりあえず，バッファだけしておきます
    name_buf = str.substr(start, length);
  }

  // 空要素のタグの解析が完了した？
  else if (rulename == "emptyelem")
  {
    printf("<%s/>\n", name_buf.c_str());
  }
  // 終了タグ？
  else if (rulename == "etag")
  {
    printf("</%s>\n", name_buf.c_str());
  }
  // 開始タグ？
  else if (rulename == "stag")
  {
    printf("<%s>\n", name_buf.c_str());
  }

  return true;  // 今のところ，戻り値は使われません．何を返してもよいです．
}

// ファイルから読み込み
string fromfile(char const * fname)
{
  ifstream file (fname);
  string buf;
  buf.assign(istreambuf_iterator<char>(file),
      istreambuf_iterator<char>());
  file.close();
  
  return buf;
}


// おためし
int main()
{
  try
  {
    string rule = fromfile("t03_xml.bnf");
    string data = fromfile("t03_xml.xml");

    bnf::BnfParser c = rule.c_str();

    c.parse(
        data.c_str(),
        "xml",
        &data,
        matched_callback);

  }
  catch(...)
  {
    puts("something wrong");
  }
}

/*
  出力結果

<Window>
<Editbox/>
<StaticText/>
<Listbox>
<String/>
<Icon/>
</Listbox>
</Window>

*/


