gtsam/gtsam_unstable/linear/QPSParser.cpp

140 lines
6.0 KiB
C++

/* ----------------------------------------------------------------------------
* GTSAM Copyright 2010, Georgia Tech Research Corporation,
* Atlanta, Georgia 30332-0415
* All Rights Reserved
* Authors: Frank Dellaert, et al. (see THANKS for the full author list)
* See LICENSE for the license information
* -------------------------------------------------------------------------- */
/**
* @file QPParser.cpp
* @author Ivan Dario Jimenez
* @date 3/5/16
*/
#define BOOST_SPIRIT_USE_PHOENIX_V3 1
#include <gtsam_unstable/linear/QPSParser.h>
#include <gtsam_unstable/linear/QPSParserException.h>
#include <gtsam_unstable/linear/QPSVisitor.h>
#include <boost/spirit/include/qi.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/phoenix/bind.hpp>
#include <boost/spirit/include/classic.hpp>
namespace bf = boost::fusion;
namespace qi = boost::spirit::qi;
namespace gtsam {
typedef qi::grammar<boost::spirit::basic_istream_iterator<char>> base_grammar;
struct QPSParser::MPSGrammar: base_grammar {
typedef std::vector<char> Chars;
QPSVisitor * rqp_;
boost::function<void(bf::vector<Chars, Chars, Chars> const&)> setName;
boost::function<void(bf::vector<Chars, char, Chars, Chars, Chars> const &)> addRow;
boost::function<
void(bf::vector<Chars, Chars, Chars, Chars, Chars, double, Chars> const &)> rhsSingle;
boost::function<
void(
bf::vector<Chars, Chars, Chars, Chars, Chars, double, Chars, Chars,
Chars, double>)> rhsDouble;
boost::function<
void(bf::vector<Chars, Chars, Chars, Chars, Chars, double, Chars> const &)> rangeSingle;
boost::function<
void(
bf::vector<Chars, Chars, Chars, Chars, Chars, double, Chars, Chars,
Chars, double>)> rangeDouble;
boost::function<
void(bf::vector<Chars, Chars, Chars, Chars, Chars, double, Chars>)> colSingle;
boost::function<
void(
bf::vector<Chars, Chars, Chars, Chars, double, Chars, Chars, Chars,
double> const &)> colDouble;
boost::function<
void(bf::vector<Chars, Chars, Chars, Chars, Chars, double, Chars> const &)> addQuadTerm;
boost::function<
void(
bf::vector<Chars, Chars, Chars, Chars, Chars, Chars, Chars, double> const &)> addBound;
boost::function<
void(bf::vector<Chars, Chars, Chars, Chars, Chars, Chars, Chars> const &)> addBoundFr;
MPSGrammar(QPSVisitor * rqp) :
base_grammar(start), rqp_(rqp), setName(
boost::bind(&QPSVisitor::setName, rqp, ::_1)), addRow(
boost::bind(&QPSVisitor::addRow, rqp, ::_1)), rhsSingle(
boost::bind(&QPSVisitor::addRHS, rqp, ::_1)), rhsDouble(
boost::bind(&QPSVisitor::addRHSDouble, rqp, ::_1)), rangeSingle(
boost::bind(&QPSVisitor::addRangeSingle, rqp, ::_1)), rangeDouble(
boost::bind(&QPSVisitor::addRangeDouble, rqp, ::_1)), colSingle(
boost::bind(&QPSVisitor::addColumn, rqp, ::_1)), colDouble(
boost::bind(&QPSVisitor::addColumnDouble, rqp, ::_1)), addQuadTerm(
boost::bind(&QPSVisitor::addQuadTerm, rqp, ::_1)), addBound(
boost::bind(&QPSVisitor::addBound, rqp, ::_1)), addBoundFr(
boost::bind(&QPSVisitor::addBoundFr, rqp, ::_1)) {
using namespace boost::spirit;
using namespace boost::spirit::qi;
character = lexeme[alnum | '_' | '-' | '.'];
title = lexeme[character >> *(blank | character)];
word = lexeme[+character];
name = lexeme[lit("NAME") >> *blank >> title >> +space][setName];
row = lexeme[*blank >> character >> +blank >> word >> *blank][addRow];
rhs_single = lexeme[*blank >> word >> +blank >> word >> +blank >> double_
>> *blank][rhsSingle];
rhs_double = lexeme[(*blank >> word >> +blank >> word >> +blank >> double_
>> +blank >> word >> +blank >> double_)[rhsDouble] >> *blank];
range_single = lexeme[*blank >> word >> +blank >> word >> +blank >> double_
>> *blank][rangeSingle];
range_double = lexeme[(*blank >> word >> +blank >> word >> +blank >> double_
>> +blank >> word >> +blank >> double_)[rangeDouble] >> *blank];
col_single = lexeme[*blank >> word >> +blank >> word >> +blank >> double_
>> *blank][colSingle];
col_double = lexeme[*blank
>> (word >> +blank >> word >> +blank >> double_ >> +blank >> word
>> +blank >> double_)[colDouble] >> *blank];
quad_l = lexeme[*blank >> word >> +blank >> word >> +blank >> double_
>> *blank][addQuadTerm];
bound = lexeme[(*blank >> word >> +blank >> word >> +blank >> word >> +blank
>> double_)[addBound] >> *blank];
bound_fr = lexeme[*blank >> word >> +blank >> word >> +blank >> word
>> *blank][addBoundFr];
rows = lexeme[lit("ROWS") >> *blank >> eol >> +(row >> eol)];
rhs = lexeme[lit("RHS") >> *blank >> eol
>> +((rhs_double | rhs_single) >> eol)];
cols = lexeme[lit("COLUMNS") >> *blank >> eol
>> +((col_double | col_single) >> eol)];
quad = lexeme[lit("QUADOBJ") >> *blank >> eol >> +(quad_l >> eol)];
bounds = lexeme[lit("BOUNDS") >> +space >> *((bound | bound_fr) >> eol)];
ranges = lexeme[lit("RANGES") >> +space
>> *((range_double | range_single) >> eol)];
end = lexeme[lit("ENDATA") >> *space];
start = lexeme[name >> rows >> cols >> rhs >> -ranges >> bounds >> quad
>> end];
}
qi::rule<boost::spirit::basic_istream_iterator<char>, char()> character;
qi::rule<boost::spirit::basic_istream_iterator<char>, Chars()> word, title;
qi::rule<boost::spirit::basic_istream_iterator<char> > row, end, col_single,
col_double, rhs_single, rhs_double, range_single, range_double, ranges,
bound, bound_fr, bounds, quad, quad_l, rows, cols, rhs, name, start;
};
QP QPSParser::Parse() {
QPSVisitor rawData;
std::fstream stream(fileName_.c_str());
stream.unsetf(std::ios::skipws);
boost::spirit::basic_istream_iterator<char> begin(stream);
boost::spirit::basic_istream_iterator<char> last;
if (!parse(begin, last, MPSGrammar(&rawData)) || begin != last) {
throw QPSParserException();
}
return rawData.makeQP();
}
}