LINUX.ORG.RU

Помогите с boost::spirit


0

0

Пытаюсь разобраться со спиритом, но чего-то не могу собрать код с его использованием, может кто подскажет что я делаю не так?

calc.h:
#ifndef CALC_H
#define CALC_H

#include <boost/spirit/core.hpp>
#include <stack>

class Calc
{
	public:
		double evaluate(char *expr);

		void do_push_value(double x){};
		void do_add(char const*, char const*){};
		void do_subt(char const*, char const*){};
		void do_mult(char const*, char const*){};
		void do_div(char const*, char const*){};
		void do_pow(char const*, char const*){};
		void do_neg(char const*, char const*){};
		void do_cos(char const*, char const*){};
		void do_sin(char const*, char const*){};
		
		struct calculator : public boost::spirit::grammar<calculator>
		{
			template <typename ScannerT>
			struct definition
			{
				definition(calculator const&)
				{
					expression
						=   term
						>> *(   ('+' >> term)[&Calc::do_add]
						|   ('-' >> term)[&Calc::do_subt]
						)
					;
					term
						=   factor
						>> *(   ('*' >> factor)[&Calc::do_mult]
						|   ('/' >> factor)[&Calc::do_div]
						|   ('^' >> factor)[&Calc::do_pow]
						)
					;
					factor
						=   boost::spirit::real_p[&Calc::do_push_value]
						|   '(' >> expression >> ')'
						|   ('-' >> factor)[&Calc::do_neg]
						|   ("cos" >> factor)[&Calc::do_cos]
						|   ("sin" >> factor)[&Calc::do_sin]
						|   ('+' >> factor)
					;
				}
				boost::spirit::rule<ScannerT> expression, term, factor;
				boost::spirit::rule<ScannerT> const& start() const { return expression; }
			};
		} calc;

		std::stack<double> stack;
};

#endif // CALC_H


calc.cpp:
#include "calc.h"

using namespace boost::spirit;

...
double Calc::evaluate(char* expr)
{
	parse_info<> info = parse(expr, calc, space_p);
};
..
★★

Вот что говорит g++

[light@book calc]$ make
/usr/include/boost/spirit/core/scanner/scanner.hpp: In static member function ‘static void boost::spirit::attributed_action_policy<boost::spirit::nil_t>::call(const ActorT&, boost::spirit::nil_t, const IteratorT&, const IteratorT&) [with ActorT = void (Calc::*)(const char*, const char*), IteratorT = const char*]’: 
...                                                                                                           
calc.cpp:44:   instantiated from here
/usr/include/boost/spirit/core/scanner/scanner.hpp:130: ошибка: must use ‘.*’ or ‘->*’ to call pointer-to-member function in ‘actor (...)’
make: *** [calc.o] Ошибка 1

Delay ★★
() автор топика

static void do_push_value(double x){};
static void do_add(char const*, char const*){};
static void do_subt(char const*, char const*){};
static void do_mult(char const*, char const*){};
static void do_div(char const*, char const*){};
static void do_pow(char const*, char const*){};
static void do_neg(char const*, char const*){};
static void do_cos(char const*, char const*){};
static void do_sin(char const*, char const*){};

или boost::function если объект нужен

anonymous
()

Если юзать только стандартную библиотеку -- вместо указателей на методы &Calc::do_smthng нужно использовать что-то вроде std::bind1st(std::mem_fun(&Calc::do_smthng), this). Ну или, как сказали выше, буст.

А вообще, boost::spirit -- это зло!:)

V_L_A_D ★★
()
Ответ на: комментарий от V_L_A_D

ок, всем спасибо но я уже сам разобрался, проблема действительно в том, что нельзя получить указатель на не статические методы класса. Переделал так:
struct do_add
{
	do_add(dstack* st)
	{
		m_st = st;
	};
	void operator()(char const*, char const*) const
	{
		double a = m_st->top();
		m_st->pop();
		double b = m_st->top();
		m_st->pop();
		m_st->push(a + b);
	}
	dstack *m_st;
};
ну и
struct calculator : public grammar<calculator>
{
	calculator()
	{ 
		m_st = new dstack; 
	};
	~calculator()
	{ 
		delete m_st; 
	};
	double result()
	{
		return m_st->top();
	}

	dstack *m_st;

	template <typename ScannerT>
	struct definition
	{
		definition(calculator const& self)
		{
			expression
				=   term
				>> *(   ('+' >> term)[do_add(self.m_st)]
				|   ('-' >> term)[do_subt(self.m_st)]
				)
			;
			term
				=   factor
				>> *(   ('*' >> factor)[do_mult(self.m_st)]
				|   ('/' >> factor)[do_div(self.m_st)]
				|   ('^' >> factor)[do_pow(self.m_st)]
				)
			;
			factor
				=   real_p[do_push( self.m_st )]
				|   '(' >> expression >> ')'
				|   ('-' >> factor)[do_neg(self.m_st)]
				|   ("cos" >> factor)[do_cos(self.m_st)]
				|   ("sin" >> factor)[do_sin(self.m_st)]
				|   ('+' >> factor)
			;
		}
		rule<ScannerT> expression, term, factor;
		rule<ScannerT> const& start() const { return expression; }
	};
};

Delay ★★
() автор топика
Ответ на: комментарий от anonymous

> Альтернативы?

Куча генераторов, начиная от Lex/Yacc.

> IMHO вполне приличный инструмент.

По слухам реалистичные парсеры компилятся жутко долго.

Legioner ★★★★★
()
Ответ на: комментарий от Legioner

>По слухам реалистичные парсеры компилятся жутко долго.

А каким сексуальным становится процесс дебага... :)

V_L_A_D ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.