/* ---------------------------------------------------------------------------- * 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 #include #include #include #include #include #include namespace bf = boost::fusion; namespace qi = boost::spirit::qi; namespace gtsam { typedef qi::grammar> base_grammar; struct QPSParser::MPSGrammar: base_grammar { typedef std::vector Chars; QPSVisitor * rqp_; boost::function const&)> setName; boost::function const &)> addRow; boost::function< void(bf::vector const &)> rhsSingle; boost::function< void( bf::vector)> rhsDouble; boost::function< void(bf::vector const &)> rangeSingle; boost::function< void( bf::vector)> rangeDouble; boost::function< void(bf::vector)> colSingle; boost::function< void( bf::vector const &)> colDouble; boost::function< void(bf::vector const &)> addQuadTerm; boost::function< void( bf::vector const &)> addBound; boost::function< void(bf::vector 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, char()> character; qi::rule, Chars()> word, title; qi::rule > 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 begin(stream); boost::spirit::basic_istream_iterator last; if (!parse(begin, last, MPSGrammar(&rawData)) || begin != last) { throw QPSParserException(); } return rawData.makeQP(); } }