#include <iostream>
#include <iomanip>
#include <stdexcept>
#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;
template <typename Parser, typename ... Args>
void ParseOrDie(const std::string& input, const Parser& p, Args&& ... args)
{
std::string::const_iterator begin = input.begin(), end = input.end();
bool ok = qi::parse(begin, end, p, std::forward<Args>(args) ...);
if (!ok || begin != end) {
std::cout << "Unparseable: "
<< std::quoted(std::string(begin, end)) << std::endl;
throw std::runtime_error("Parse error");
}
}
class ArithmeticGrammar1 : public qi::grammar<
std::string::const_iterator>
{
public:
using Iterator = std::string::const_iterator;
ArithmeticGrammar1()
: ArithmeticGrammar1::base_type(start)
{
start = qi::int_;
}
qi::rule<Iterator> start;
};
void test1()
{
std::string input = "12345";
ArithmeticGrammar1 g;
ParseOrDie(input, g);
}
class ArithmeticGrammar2 : public qi::grammar<
std::string::const_iterator,
int()>
{
public:
using Iterator = std::string::const_iterator;
ArithmeticGrammar2() : ArithmeticGrammar2::base_type(start)
{
start %= qi::int_;
}
qi::rule<Iterator, int()> start;
};
void test2()
{
std::string input = "12345";
int out_int;
ParseOrDie(input, ArithmeticGrammar2(), out_int);
std::cout << "test2() parse result: "
<< out_int << std::endl;
}
class ArithmeticGrammar3 : public qi::grammar<std::string::const_iterator, int()>
{
public:
using Iterator = std::string::const_iterator;
ArithmeticGrammar3() : ArithmeticGrammar3::base_type(start)
{
start = product >> *('+' >> product);
product = factor >> *('*' >> factor);
factor = qi::int_ | group;
group = '(' >> start >> ')';
}
qi::rule<Iterator, int()> start, group, product, factor;
};
void test3()
{
std::string input = "1+2*3";
int out_int;
ParseOrDie(input, ArithmeticGrammar3(), out_int);
std::cout << "test3() parse result: "
<< out_int << std::endl;
}
template <typename Parser, typename Skipper, typename ... Args>
void PhraseParseOrDie(
const std::string& input, const Parser& p, const Skipper& s,
Args&& ... args)
{
std::string::const_iterator begin = input.begin(), end = input.end();
boost::spirit::qi::phrase_parse(
begin, end, p, s, std::forward<Args>(args) ...);
if (begin != end) {
std::cout << "Unparseable: "
<< std::quoted(std::string(begin, end)) << std::endl;
throw std::runtime_error("Parse error");
}
}
class ArithmeticGrammar4 : public qi::grammar<
std::string::const_iterator,
int(),
qi::space_type>
{
public:
using Iterator = std::string::const_iterator;
ArithmeticGrammar4() : ArithmeticGrammar4::base_type(start)
{
start = product >> *('+' >> product);
product = factor >> *('*' >> factor);
factor = qi::int_ | group;
group = '(' >> start >> ')';
}
qi::rule<Iterator, int(), qi::space_type> start, group, product, factor;
};
void test4(std::string input)
{
int out_int;
PhraseParseOrDie(
input,
ArithmeticGrammar4(),
qi::space,
out_int);
std::cout << "test4() parse result: "
<< out_int << std::endl;
}
int main(int argc, char* argv[])
{
test1();
test2();
test3();
test4(argc >= 2 ? argv[1] : "1 + 2 * 3");
return 0;
}