I have a strange problem with a calculator made using boost::spirit. This calculator is supposed to take a string as argument representing a series of arithmetical expressio
I'm pretty sure you might have been rearranging stuff in your rules. In fact, the %=
auto-rule expression assignments won't work because the synthesized type of the parser expression doesn't resemble an int
.
Basically, you'd change
factor %= (simple >> '*' >> factor)[ _val = _1 * _2 ]
| (simple >> '/' >> factor)[ _val = _1 / _2 ]
| (simple >> '%' >> factor)[ _val = _1 % _2 ]
| simple;
expr %= (factor >> '+' >> expr)[ _val = _1 + _2 ]
| (factor >> '-' >> expr)[ _val = _1 - _2 ]
| factor;
into
factor = (simple >> '*' >> factor)[ _val = _1 * _2 ]
| (simple >> '/' >> factor)[ _val = _1 / _2 ]
| (simple >> '%' >> factor)[ _val = _1 % _2 ]
| (simple) [_val = _1 ];
expr = (factor >> '+' >> expr)[ _val = _1 + _2 ]
| (factor >> '-' >> expr)[ _val = _1 - _2 ]
| (factor) [_val = _1 ];
I have fixed up some small issues and created a SSCCE of your post that works, as far as I can tell 1:
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/karma.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace sp = boost::spirit;
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
namespace karma = boost::spirit::karma;
namespace phx = boost::phoenix;
namespace Damaris {
template <typename Iterator, typename SymTable>
struct Calc : qi::grammar<Iterator, std::vector<int>(), ascii::space_type>
{
qi::rule<Iterator, std::vector<int>(), ascii::space_type> start;
qi::rule<Iterator, int(), ascii::space_type> expr;
qi::rule<Iterator, int(), ascii::space_type> qmark;
qi::rule<Iterator, int(), ascii::space_type> factor;
qi::rule<Iterator, int(), ascii::space_type> simple;
qi::rule<Iterator, std::string(), ascii::space_type> identifier;
qi::rule<Iterator, int(SymTable), ascii::space_type> value;
Calc(SymTable &sym) : Calc::base_type(start)
{
using namespace qi;
identifier = lexeme[( alpha | '_') >> *( alnum | '_')];
value = identifier[ _val = _r1[_1] ];
simple = ('(' >> expr >> ')')
| int_
| value(boost::phoenix::ref(sym));
factor = (simple >> '*' >> factor)[ _val = _1 * _2 ]
| (simple >> '/' >> factor)[ _val = _1 / _2 ]
| (simple >> '%' >> factor)[ _val = _1 % _2 ]
| (simple) [_val = _1 ];
expr = (factor >> '+' >> expr)[ _val = _1 + _2 ]
| (factor >> '-' >> expr)[ _val = _1 - _2 ]
| (factor) [_val = _1 ];
qmark = char_('?')[ _val = -1 ];
start = qmark
| (expr % ',');
BOOST_SPIRIT_DEBUG_NODE(start);
BOOST_SPIRIT_DEBUG_NODE(qmark);
BOOST_SPIRIT_DEBUG_NODE(expr);
BOOST_SPIRIT_DEBUG_NODE(factor);
BOOST_SPIRIT_DEBUG_NODE(simple);
BOOST_SPIRIT_DEBUG_NODE(value);
BOOST_SPIRIT_DEBUG_NODE(identifier);
}
};
}
int main(int argc, const char *argv[])
{
typedef std::map<std::string, int> SymTable;
SymTable symbols;
Damaris::Calc<std::string::const_iterator, SymTable> calc(symbols);
symbols["TheAnswerToLifeUniverse"] = 100;
symbols["Everything"] = -58;
std::string input = "3*4+5/4, TheAnswerToLifeUniverse + Everything";
std::string::const_iterator f(input.begin()), l(input.end());
std::vector<int> data;
if (qi::phrase_parse(f,l,calc,ascii::space,data))
std::cout << "output: " << karma::format(karma::int_ % ", " << karma::eol, data);
else
std::cout << "problem: '" << std::string(f,l) << "'\n";
return 0;
}
Output:
output: 13, 42
1 gcc 4.6.1, boost 1_48