OKlibrary  0.2.1.6
ParsingResultSequences.hpp
Go to the documentation of this file.
00001 // Oliver Kullmann, 3.6.2005 (Swansea)
00002 /* Copyright 2005 - 2007, 2009, 2011 Oliver Kullmann
00003 This file is part of the OKlibrary. OKlibrary is free software; you can redistribute
00004 it and/or modify it under the terms of the GNU General Public License as published by
00005 the Free Software Foundation and included in this library; either version 3 of the
00006 License, or any later version. */
00007 
00008 #ifndef PARSINGRESULTSEQUENCES_uJnBv45
00009 #define PARSINGRESULTSEQUENCES_uJnBv45
00010 
00011 #include <iterator>
00012 #include <string>
00013 
00014 #include <boost/spirit/include/classic_core.hpp>
00015 #include <boost/spirit/include/classic_file_iterator.hpp>
00016 #include <boost/spirit/include/classic_position_iterator.hpp>
00017 #include <boost/filesystem/path.hpp>
00018 #include <boost/lexical_cast.hpp>
00019 
00020 #include <OKlib/Programming/Parsing/ParserBase.hpp>
00021 
00022 #include <OKlib/Experimentation/Competition/SingleResult.hpp>
00023 #include <OKlib/Experimentation/Competition/ParsingSingleResult.hpp>
00024 
00025 namespace OKlib {
00026   namespace SATCompetition {
00027 
00028     template <class ParserResult, class OutputIterator>
00029     class ParserResultSequence : public ::OKlib::Parser::ParserBase<typename ParserResult::char_type, typename ParserResult::ParseIterator> {
00030       typedef typename ParserResult::ParseIterator ParseIterator;
00031       OutputIterator& begin;
00032       typedef typename ParserResult::result_type Result;
00033       Result r;
00034       ParserResult p;
00035       struct action {
00036         OutputIterator& begin;
00037         Result& r;
00038         action(OutputIterator& begin, Result& r) : begin(begin), r(r) {}
00039         void operator() (ParseIterator, ParseIterator) const {
00040           *begin++ = r;
00041         }
00042       };
00043     public :
00044       ParserResultSequence(OutputIterator& begin) : begin(begin), p(r) {
00045         this -> parser_ = +((p.parser() >> boost::spirit::eol_p)[action(begin, r)]);
00046       }
00047     };
00048 
00049     template <class ParserResult, class OutputIterator>
00050     // ToDo: Conceptualisation
00051     // ParserResult is a parser for results
00052     // OutputIterator::value_type is Result
00053     // ToDo: It seems better to have the two operators in different specialisations.
00054     // ToDo: Making functor classes (with corresponding type traits) out of it.
00055     struct Copy_results {
00056 
00057       typedef typename ParserResult::ParseIterator ParseIterator;
00058       typedef boost::spirit::parse_info<ParseIterator> parse_info_it;
00059       typedef typename ParserResult::char_type char_type;
00060       typedef boost::spirit::parse_info<const char_type*> parse_info_c;
00061 
00062       parse_info_it operator() (const ParseIterator begin_in, const ParseIterator end_in, OutputIterator begin_out) {
00063         ParserResultSequence<ParserResult, OutputIterator> p(begin_out);
00064         return boost::spirit::parse(begin_in, end_in, p.parser());
00065       }
00066       template <typename PIterator>
00067       parse_info_c operator() (const PIterator begin_in, OutputIterator begin_out) {
00068         ParserResultSequence<ParserResult, OutputIterator> p(begin_out);
00069         return boost::spirit::parse(begin_in, p.parser());
00070       }
00071       
00072     };
00073 
00074     template <class ParserResult, class OutputIterator>
00075     inline typename Copy_results<ParserResult, OutputIterator>::parse_info_it copy_results(const typename ParserResult::ParseIterator begin_in, const typename ParserResult::ParseIterator end_in, const OutputIterator begin_out) {
00076       return Copy_results<ParserResult, OutputIterator>()(begin_in, end_in, begin_out);
00077     }
00078     template <class ParserResult, typename PIterator, class OutputIterator>
00079     inline typename Copy_results<ParserResult, OutputIterator>::parse_info_c copy_results(const PIterator begin_in, const OutputIterator begin_out) {
00080       return Copy_results<ParserResult, OutputIterator>()(begin_in, begin_out);
00081     }
00082 
00083     // ----------------------------------------------
00084 
00085     template <template <typename Result, typename CharT, typename ParseIterator, class ParserExtension> class ParserResult, class OutputIterator, class Result_ = Result, template <typename CharT, typename ParseIterator> class ParserExtension = ParserEmpty>
00086     struct Copy_results_from_file {
00087 
00088       typedef char char_type; // ToDo: to generalise
00089       typedef boost::spirit::file_iterator<char_type> file_iterator;
00090       typedef boost::spirit::position_iterator<file_iterator> ParseIterator;
00091       typedef boost::spirit::parse_info<ParseIterator> parse_info_f;
00092       typedef ParserResult<Result_, char_type, ParseIterator, ParserExtension<char_type, ParseIterator> > Parser;
00093 
00094       parse_info_f operator() (const boost::filesystem::path& filename, OutputIterator begin_out) const {
00095         const std::string native_filename(filename.string());
00096         file_iterator file_begin(native_filename.c_str());
00097         if (not file_begin)
00098           throw ParserError("Error when opening " + native_filename);
00099         const file_iterator file_end(file_begin.make_end());
00100         const ParseIterator parse_begin(file_begin, file_end, native_filename);
00101         const ParseIterator parse_end;
00102         return copy_results<Parser>(parse_begin, parse_end, begin_out);
00103       }
00104 
00105     };
00106 
00107     // ----------------------------------------------
00108 
00109     template <template <typename Result, typename CharT, typename ParseIterator, class ParserExtension = ParserEmpty<CharT, ParseIterator> > class ParserResult, template <typename Value> class Container, class Result_ = Result, template <typename CharT, typename ParseIterator> class ParserExtension = ParserEmpty>
00110     struct Copy_results_from_file_to_container {
00111 
00112       typedef Result_ result_type;
00113       typedef Container<result_type> container_type;
00114       typedef std::back_insert_iterator<container_type> output_iterator_type;
00115       typedef Copy_results_from_file<ParserResult, output_iterator_type, result_type, ParserExtension> copy_type;
00116       typedef typename copy_type::ParseIterator parse_iterator_type;
00117       typedef typename copy_type::parse_info_f info_type;
00118 
00119       Copy_results_from_file_to_container (const boost::filesystem::path& filename, container_type& C) {
00120         const info_type info(copy_type()(filename, output_iterator_type(C)));
00121         if (not info.full) {
00122           const parse_iterator_type it(info.stop);
00123           typedef boost::spirit::file_position position_type;
00124           const position_type pos(it.get_position());
00125           throw ParserError("Parse error in file " + pos.file + " at line " + boost::lexical_cast<std::string>(pos.line) + " and column " +  boost::lexical_cast<std::string>(pos.column));
00126         }
00127       }
00128       
00129     };
00130 
00131   }
00132 
00133 }
00134 
00135 #endif