[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。
早速コードから。
今回は電卓です。整数の四則演算(括弧付き)が出来ます。
とりあえずとあるサイトから拝借したspiritのバージョン1のコードを修正してみました。
今回は前回のコードとそんなに変わっていないので全部一気に。
#pragma warning(disable:4512) //代入演算子を生成できません。
#pragma warning(disable:4100) //引数は関数の本体部で 1 度も参照されません。#include <iostream>
#include <string>
#include <stack>#include <boost/bind.hpp>
#include <boost/spirit/home/qi.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>template<typename String>
struct Calc : boost::spirit::qi::grammar<typename String::const_iterator, boost::spirit::ascii::space_type>{
typedef typename String::const_iterator Iterator;Calc() : Calc::base_type(expression){
using namespace boost;using namespace boost::spirit;
namespace sp_arg = boost::spirit::arg_names;// 構文定義
group = '(' >> expression >> ')';
factor = int_[bind(&Calc::PUSH, this, _1)] | group;
term = factor >> *( ('*' >> factor)[bind(&Calc::MUL, this)] | ('/' >> factor)[bind(&Calc::DIV, this)] );
expression = term >> *( ('+' >> term)[bind(&Calc::ADD, this)] | ('-' >> term)[bind(&Calc::SUB, this)] );
};
boost::spirit::qi::rule<Iterator, boost::spirit::ascii::space_type> expression;
boost::spirit::qi::rule<Iterator, boost::spirit::ascii::space_type> term;
boost::spirit::qi::rule<Iterator, boost::spirit::ascii::space_type> factor;
boost::spirit::qi::rule<Iterator, boost::spirit::ascii::space_type> group;std::stack<int> stack;
int GetResult(){
int i = stack.top();
Reset();
return i;
}void Reset(){
std::stack<int> empty;
std::swap(empty, stack);
}void PUSH(int i){
stack.push(i);
}void ADD(){
int a = stack.top();
stack.pop();
int b = stack.top();
stack.pop();stack.push(b + a);
}void SUB(){
int a = stack.top();
stack.pop();
int b = stack.top();
stack.pop();stack.push(b - a);
}void MUL(){
int a = stack.top();
stack.pop();
int b = stack.top();
stack.pop();stack.push(b * a);
}
void DIV(){
int a = stack.top();
stack.pop();
int b = stack.top();
stack.pop();stack.push(b / a);
}};
int main(void)
{
Calc<std::string> calc;std::string str;
while (getline(std::cin, str))
{
if (str.empty() || str[0] == 'q' || str[0] == 'Q')
break;std::string::const_iterator it = str.begin();
std::string::const_iterator end = str.end();bool result = phrase_parse(it, end, calc, boost::spirit::ascii::space);
if (result && it == end)
{
std::cout << "-------------------------\n";
std::cout << "Parsing succeeded\n";
std::cout << str << " Parses OK: " << std::endl;
std::cout << calc.GetResult() << std::endl;
}
else if(result)
{
std::cout << "-------------------------\n";
std::cout << "Parsing succeeded\n";
std::cout << std::string(str.begin(), it) << " Parses OK: " << std::endl;
std::cout << calc.GetResult() << std::endl;
std::cout << std::string(it, end) << " amari" << std::endl;
}
else
{
std::cout << "-------------------------\n";
std::cout << "Parsing failed\n";
std::cout << "-------------------------\n";
calc.Reset();
}
}return 0;
}
気になるのはこの部分。
group = '(' >> expression >> ')';
factor = int_[bind(&Calc::PUSH, this, _1)] | group;
term = factor >> *( ('*' >> factor)[bind(&Calc::MUL, this)] | ('/' >> factor)[bind(&Calc::DIV, this)] );
expression = term >> *( ('+' >> term)[bind(&Calc::ADD, this)] | ('-' >> term)[bind(&Calc::SUB, this)] );
何とかphoenixだけでうまく書く方法はないのでしょうか……
色々考えてみたのですが、思いつきませんでした。
//2009-10-25追記
コードの修正(mutableとconstの勘違い)