Last active
August 29, 2015 14:03
-
-
Save alextsui05/01bab6a46cbcfe3eba34 to your computer and use it in GitHub Desktop.
polynomial parser using boost spirit
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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