ページ 11

文字列の参照の他の方法

Posted: 2016年9月20日(火) 23:49
by いろは
初めまして。今、「boost spirit」を用いて簡単なスクリプト言語の作成に挑戦しており、とりあえずコンソールで実験しています。
数式や定数に関しては基本的に「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;
}
そこで、「operator」以外での文字列の参照の仕方や、二項演算子としてコンパイルされない方法がわかる方教えてください。
環境は「windows7」で「Visual Stadio 2015」です。

Re: 文字列の参照の他の方法

Posted: 2016年9月27日(火) 00:26
by いろは
すみませんが、自力で解決できました。
考えてくださった方、ありがとうございます。