// Example how to use Boost Spirit to parse and _evaluate_ a simple arithmetic // grammar. Evaluation is added by amending rules with semantic actions. #include #include #include #include #include #include namespace qi = boost::spirit::qi; /******************************************************************************/ // Arithmetic parser with semantic actions which calculate the arithmetic // expression's result // Helper to run a parser, check for errors, and capture the results. template 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) ...); if (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, // define grammar to return an integer ... which we will calculate from the // expression int(), qi::space_type> { public: using Iterator = std::string::const_iterator; ArithmeticGrammar1() : ArithmeticGrammar1::base_type(start) { start = // first component: product, and transfer the result of product // (qi::_1) to the result of this rule (start, qi::_val). product [qi::_val = qi::_1] // zero or more components: add result of product (qi::_1) to the // result of this rule (qi::_val). >> *('+' >> product [qi::_val += qi::_1]); // product is defined in same way as start, but with multiplication product = factor [qi::_val = qi::_1] >> *('*' >> factor [qi::_val *= qi::_1]); // factor is either option, both return an int, and with "%=" is // equivalent to [qi::_val = qi::_1] in both cases. factor %= qi::int_ | group; // group's result is identical to start. again "%=" is a shortcut group %= '(' >> start >> ')'; } // each rule also returns an integer qi::rule start, group, product, factor; }; void test1(std::string input) { int out_int; PhraseParseOrDie(input, ArithmeticGrammar1(), qi::space, out_int); std::cout << "test1() parse result: " << out_int << std::endl; } /******************************************************************************/ int main(int argc, char* argv[]) { test1(argc >= 2 ? argv[1] : "1 + 2 * 3"); return 0; } /******************************************************************************/