?
Ich habs nun irgendwie geschafft.
#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;
template<typename Iterator>
class math_parser : public qi::grammar<Iterator, qi::ascii::space_type>{
qi::rule<Iterator, qi::ascii::space_type> start;
qi::rule<Iterator, double, qi::ascii::space_type> term, fact, group;
qi::rule<Iterator> identifier;
void work(boost::fusion::vector<double, std::vector<boost::fusion::vector<char, double>>>& values){
result = boost::fusion::at_c<0>(values);
auto vec = boost::fusion::at_c<1>(values);
double value;
char op;
for(auto&& v : std::move(vec)){
op = boost::fusion::at_c<0>(v);
value = boost::fusion::at_c<1>(v);
switch(op){
case '+':
result += value;
break;
case '-':
result -= value;
break;
case '*':
result *= value;
break;
case '/':
result /= value;
}
}
}
public:
double result;
math_parser() : qi::grammar<Iterator, qi::ascii::space_type>(start){
identifier = qi::alpha >> *(qi::alnum);
term = qi::double_ | identifier;
fact = term | group;
group = qi::char_('(') >> start >> qi::char_(')');
start = (fact >> *((qi::char_('+') | qi::char_('-') | qi::char_('*') | qi::char_('/')) >> fact))
[std::bind(&math_parser::work, this, std::placeholders::_1)];
}
};
#include <iostream>
int main(){
std::string str = "(1)+2+3";
std::string::iterator it = str.begin();
math_parser<decltype(it)> parser;
qi::phrase_parse(it, str.end(), parser, qi::ascii::space);
std::cout << parser.result << '\n';
}
Da gibt es nur ein winziges Problem. Bei Expressions wie "1+2+3" klappt alles wundersam, jedoch, sobald ich die Klammern setze, werden diese Klammern mitberechnet. Was ich also suche, ist es, dem Parser "group" irgendwie mitzuteilen, was genau er zurückgeben soll. Wie mach ich das? Oder denke ich schon wieder in die falsche Richtung?