/*! @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;
}