/*! @file

   $Id$
*/
//       1         2         3         4         5         6         7         8
// 45678901234567890123456789012345678901234567890123456789012345678901234567890

// kompilieren mit g++ spirit.cxx -o spirit

#include <boost/spirit.hpp>
#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>
#include <iostream>
#include <map>
#include <algorithm>

using namespace boost::spirit;
using namespace boost;
using namespace std;

class SortFootnotes { //========================================================
 public: //--------------------------------------------------------------------
   SortFootnotes(char const*const filename): //................................
       num(1), fndef(false), tag(0), begin_of_line(true), result(false) {
     file_iterator<> first(filename);
     if (!first) return;
     file_iterator<> last = first.make_end();
     result =
       parse
       (first, last, /* Follows Grammar in EBNF like Syntax: */
        *(('[' >> ulong_p[bind(&SortFootnotes::fn, this, _1)] >> ']')
          |
          ((eol_p>>"@footnote:">>eol_p)
           [bind(&SortFootnotes::delim, this, _1, _2)])
          |
          (eol_p[bind(&SortFootnotes::newline, this, _1, _2)])
          |
          (anychar_p[bind(&SortFootnotes::txt, this, _1)]))
        >> end_p[bind(&SortFootnotes::end, this, _1, _2)],
        nothing_p).full;
   }
   bool success() { //.........................................................
     return result;
   }
 private: // types ------------------------------------------------------------
   typedef map<unsigned long, unsigned long> NumMap;
   typedef map<unsigned long, std::string> DefMap;
 private: // variables --------------------------------------------------------
   int num;
   NumMap nummap;
   DefMap defmap;
   bool fndef;
   std::string line;
   unsigned long tag;
   bool begin_of_line;
   uint_parser<unsigned long, 10, 1, -1> ulong_p;
   bool result;
 private: // methods, parser callbacks ----------------------------------------
   void delim(file_iterator<> begin, file_iterator<> end) { // delimiter ......
     fndef = true;
     copy(begin, end, ostream_iterator<char>(cout));
   }
   void txt(char v) { // any character ........................................
     if (fndef)
       line+=v;
     else
       cout<<v;
   }
   void newline(file_iterator<> begin, file_iterator<> end) { // new line .....
     if (fndef && tag) {
       defmap[tag] = line+string(begin, end);
       begin_of_line = true;
     } else
       copy(begin, end, ostream_iterator<char>(cout<<line));
     line.clear();
   }
   void fn(unsigned long v) { // footnote .....................................
     if (nummap.insert(make_pair(v, num)).second) ++num;
     if (fndef)
       if (begin_of_line) {
         tag=nummap[v];
         begin_of_line=false;
       } else
         line+='['+lexical_cast<std::string>(nummap[v])+']';
     else
       cout<<'['<<nummap[v]<<']';
   }
   void end(file_iterator<>, file_iterator<>) { // end of input ...............
     for (DefMap::const_iterator it(defmap.begin()); it!=defmap.end(); ++it)
       cout<<'['<<it->first<<']'<<it->second;
   }
};
int main(const int argv, char const*const*const argc) { //======================
 bool result(true);
 for (int i(1); i<argv; ++i) result=result&&(SortFootnotes(argc[i]).success());
 return result ? 0 : 1;
}