数式や定数に関しては基本的に「operator」で参照して実行できています。文字列に関しても「operator」で参照できるので、「put()」を再現してみようと試してみたのですが、「operator」の文字列の参照の仕方では下のソースの二重斜線の部分が二項演算子としてコンパイルされてしまいエラーが出てしまいます。
// test1.cpp : コンソール アプリケーションのエントリ ポイントを定義します。
//
#include "stdafx.h"
#include <algorithm>
#include <cmath>
#include <limits>
#include <iterator>
#include <iostream>
#include <stdio.h>
#include <boost/fusion/tuple.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace qi = boost::spirit::qi;
namespace exprgrammar {
namespace {
class lazy_pow_ //「^」の演算
{
public:
double operator()(double x, double y) const
{
return std::pow(x, y);
}
};
class lazy_puts_ //「put」の実験(文字列の扱い)
{
public:
int operator[](char *x) const
{
return puts(x);
}
};
class lazy_onefunc_ //引数1つのやつ
{
public:
template <typename F, typename A1>
A1 operator()(F f, A1 a1) const
{
return f(a1);
}
};
}
//メイン処理
template <typename S, typename Iterator>
struct grammar :public qi::grammar<Iterator, S(), qi::space_type>
{
// 定数
struct constant_ :public qi::symbols<typename std::iterator_traits<Iterator>::value_type, S>
{
constant_()
{
this->add
(_T("e"), 2.718281828459)
(_T("pi"), 3.141592653589)
;
}
} constant;
// 引数1つのやつ
struct onefunc_ :public qi::symbols<typename std::iterator_traits<Iterator>::value_type, S(*)(S)>
{
onefunc_()
{
this->add
("cos", static_cast<S(*)(S)>(&std::cos))
("sin", static_cast<S(*)(S)>(&std::sin))
("tan", static_cast<S(*)(S)>(&std::tan))
;
}
} onefunc;
qi::rule<Iterator, S(), qi::space_type> expression, term, factor, primary;
qi::rule<Iterator, char(), qi::space_type> character;
grammar() : grammar::base_type(expression)
{
using boost::spirit::qi::real_parser;
using boost::spirit::qi::real_policies;
real_parser<S, real_policies<S> > real;
using qi::_1;
using qi::_2;
using qi::no_case;
using qi::_val;
boost::phoenix::function<lazy_pow_> lazy_pow;
boost::phoenix::function<lazy_puts_> lazy_puts;
boost::phoenix::function<lazy_onefunc_> lazy_onefunc;
expression = term[_val = _1] >> *(('+' >> term[_val += _1])
| ('-' >> term[_val -= _1]))
;
term = factor[_val = _1] >> *(('*' >> factor[_val *= _1])
| ('/' >> factor[_val /= _1]))
;
factor = primary[_val = _1] >> *('^' >> factor[_val = lazy_pow(_val, _1)])
;
primary = real[_val = _1]
| ('(' >> expression[_val = _1] >> _T(')'))
| ('-' >> primary[_val = -_1])
| ('+' >> primary[_val = _1])
| (no_case[onefunc] >> '(' >> expression >> ')')[_val = lazy_onefunc(_1, _2)] //引数1つ
| (no_case[constant])[_val = _1] //定数
//| ("puts(" >> character >> ')')[_val = lazy_puts[_1]] //文字列の実験
;
character = '"' >> *(qi::char_)[_val = _1] >> '"' //文字の読み込み
;
}
};
}
int main(void) {
std::string str;
std::string::const_iterator first, last;
exprgrammar::grammar<double, std::string::const_iterator> c;
double Result;
while (1) //無限ループ
{
std::cin >> str;
first = str.begin(); last = str.end(); //先頭と末尾の取得
bool success = qi::phrase_parse(first, last, c,qi::space, Result);
if ((success) && (first == last)) {
std::cout << "Result: " << Result << std::endl;
}// 計算結果が出力される
else break;
}
system("pause"); //キー入力待ち
return 0;
}
環境は「windows7」で「Visual Stadio 2015」です。