I\'m trying to extend the calculator example so that instead of parsing and evaluating an algebraic expression, the parser will determine if an algebraic statement is true o
The simplest thing that could work, if you ask me would be http://liveworkspace.org/code/1fvc8x$0
equation = (expression >> "=" >> expression) [ _val = _1 == _2 ];
This will parse two expressions, and the returned attribute is a bool
that indicates whether both expressions evaluated to the same value.
The demonstration program
int main()
{
doParse("1 + 2 * 3 = 7");
doParse("1 + 2 * 3 = 8");
}
prints
parse success
result: true
parse success
result: false
#include <boost/fusion/adapted.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace qi = boost::spirit::qi;
namespace phx = boost::phoenix;
typedef unsigned attr_t;
template <typename It, typename Skipper = qi::space_type>
struct calculator : qi::grammar<It, bool(), Skipper>
{
calculator() : calculator::base_type(equation)
{
using qi::uint_;
using qi::_val;
using qi::_1;
using qi::_2;
equation = (expression >> "=" >> expression) [ _val = _1 == _2 ];
expression =
term [_val = _1]
>> *( ('+' >> term [_val = _val + _1])
| ('-' >> term [_val = _val - _1])
);
term =
factor [_val = _1]
>> *( ('*' >> factor [_val = _val * _1])
| ('/' >> factor [_val = _val / _1])
);
factor =
uint_ [_val = _1]
| '(' >> expression [_val = _1] >> ')'
| ('-' >> factor [_val = -_1])
| ('+' >> factor [_val = _1]);
}
private:
qi::rule<It, unsigned(), Skipper> expression, term, factor;
qi::rule<It, bool(), Skipper> equation;
};
bool doParse(const std::string& input)
{
typedef std::string::const_iterator It;
auto f(begin(input)), l(end(input));
calculator<It, qi::space_type> p;
bool result;
try
{
bool ok = qi::phrase_parse(f,l,p,qi::space,result);
if (ok)
{
std::cout << "parse success\n";
std::cout << "result: " << std::boolalpha << result << "\n";
}
else std::cerr << "parse failed: '" << std::string(f,l) << "'\n";
if (f!=l) std::cerr << "trailing unparsed: '" << std::string(f,l) << "'\n";
return ok;
} catch(const qi::expectation_failure<It>& e)
{
std::string frag(e.first, e.last);
std::cerr << e.what() << "'" << frag << "'\n";
}
return false;
}
int main()
{
doParse("1 + 2 * 3 = 7");
doParse("1 + 2 * 3 = 8");
}