Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
polynomial parser using boost spirit
#include <iostream>
#include <string>
#include <complex>
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/io.hpp>
#include <boost/bind.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace client
{
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
struct term
{
boost::optional<int> coefficient;
boost::optional<int> x_exponent;
boost::optional<int> y_exponent;
};
void print( const term& tt )
{
int coefficient = (tt.coefficient)? *tt.coefficient : 1;
int x_exponent = (tt.x_exponent)? *tt.x_exponent : 0;
int y_exponent = (tt.y_exponent)? *tt.y_exponent : 0;
std::cout << "term\n";
std::cout << " coefficient: " << coefficient << "\n"
<< " x_exponent: " << x_exponent << "\n"
<< " y_exponent: " << y_exponent << "\n";
}
}
namespace client
{
template <typename Iterator>
struct polynomial_parser : qi::grammar<Iterator,
std::vector<term>(),
ascii::space_type>
{
polynomial_parser() : polynomial_parser::base_type(start)
{
namespace phx = boost::phoenix;
using qi::int_;
using qi::lit;
using qi::double_;
using qi::lexeme;
using ascii::char_;
using qi::_val;
using qi::eps;
exponent %= '^' >> int_;
x_term %= 'x' >> ( exponent | eps[_val = 1] );
y_term %= 'y' >> ( exponent | eps[_val = 1] );
poly_term = eps[_val = term()]
>>
-int_[phx::bind(&term::coefficient, _val) = qi::_1]
>>
-x_term[phx::bind(&term::x_exponent, _val) = qi::_1]
>>
-y_term[phx::bind(&term::y_exponent, _val) = qi::_1]
;
negative_poly_term = eps[_val = term()] >>
(
int_[phx::bind(&term::coefficient, _val) = -1 * qi::_1]
| eps[phx::bind(&term::coefficient, _val) = -1]
) >>
-x_term[phx::bind(&term::x_exponent, _val) = qi::_1]
>>
-y_term[phx::bind(&term::y_exponent, _val) = qi::_1]
;
start = eps[_val = std::vector<term>()]
>> poly_term[phx::push_back(_val, qi::_1)]
>> *(
('+' >> poly_term[phx::push_back(_val, qi::_1)])
|
('-' >> negative_poly_term[phx::push_back(_val, qi::_1)])
)
;
}
qi::rule<Iterator, int(), ascii::space_type> exponent;
qi::rule<Iterator, int(), ascii::space_type> x_term;
qi::rule<Iterator, int(), ascii::space_type> y_term;
qi::rule<Iterator, term(), ascii::space_type> poly_term;
qi::rule<Iterator, term(), ascii::space_type> negative_poly_term;
qi::rule<Iterator, std::vector<term>(), ascii::space_type> start;
};
}
////////////////////////////////////////////////////////////////////////////
// Main program
////////////////////////////////////////////////////////////////////////////
int
main()
{
std::cout << "/////////////////////////////////////////////////////////\n\n";
std::cout << "\t\tA polynomial parser for Spirit...\n\n";
std::cout << "/////////////////////////////////////////////////////////\n\n";
std::cout
<< "Give me a polynomial with terms of the form :"
<< "\"A*x^Ny^M\", where A, N, and M are integers\n";
std::cout << "Type [q or Q] to quit\n\n";
using boost::spirit::ascii::space;
typedef std::string::const_iterator iterator_type;
typedef client::polynomial_parser<iterator_type> polynomial_parser;
polynomial_parser pparser;
std::string str;
while (getline(std::cin, str))
{
if (str.empty() || str[0] == 'q' || str[0] == 'Q')
break;
std::vector<client::term> poly;
client::term term;
std::string::const_iterator iter = str.begin();
std::string::const_iterator end = str.end();
bool r = phrase_parse(iter, end, pparser, space, poly);
if (r && iter == end)
{
std::cout << boost::fusion::tuple_open('[');
std::cout << boost::fusion::tuple_close(']');
std::cout << boost::fusion::tuple_delimiter(", ");
std::cout << "-------------------------\n";
std::cout << "Parsing succeeded\n";
for ( std::vector< client::term >::iterator it = poly.begin( );
it != poly.end( ); ++it )
{
client::print( *it );
}
std::cout << "\n-------------------------\n";
}
else
{
std::cout << "-------------------------\n";
std::cout << "Parsing failed\n";
std::cout << "-------------------------\n";
}
}
std::cout << "Bye... :-) \n\n";
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment