Есть набор сложных формул, кодирующих биты. Операции все логические:| Код | 1 = 2 & 3 ^ (!5 | 4) #bit[1] = (bit[2] & bit[3]) ^ (!bit[5] | bit[4]) .... |
Хочу распарсить правую часть с помощью спирита. Взял пример калькулятора и немного его модифицировал:| Код | struct Calculator : boost::spirit::grammar< Calculator > { Calculator() {} typedef unsigned Type; typedef boost::shared_ptr<Operation::Base<Type> > OperationPtr;
struct ValueClosure : public boost::spirit::closure<ValueClosure, OperationPtr> { member1 value; };
// Following is the grammar definition. template <typename ScannerT> struct definition { definition(Calculator const& self) { using namespace boost::spirit; using namespace phoenix; literal = int_p[bind(&definition::createBit, literal, arg1)]; group = '(' >> expression[group.value = arg1] >> ')'; factor = literal[factor.value = arg1] | group[factor.value = arg1]; term = factor[term.value = arg1] >> *('!' >> factor[bind(&definition::createNot, term, arg1)]);
expression = term[expression.value = arg1] >> *('&' >> term[bind(&definition::createAnd, expression, arg1)] ) >> *('^' >> term[bind(&definition::createXor, expression, arg1)] ) >> *('|' >> term[bind(&definition::createOr, expression, arg1)] ) ;
//statement = expression[bind(&calculator::do_print)(self, arg1)] >> end_p; }
boost::spirit::rule<ScannerT> const& start() const { return statement; } private: boost::spirit::rule<ScannerT> statement; typedef boost::spirit::rule<ScannerT, ValueClosure::context_t> Context; Context expression, factor, group, literal, term;
static void createBit(Context &context, Type n) { context.value = OperationPtr( new Operation::Bit<Type>(n) ); } static void createNot(Context &context, OperationPtr op) { context.value = OperationPtr( new Operation::Not<Type>(op) ); } static void createAnd(Context &context, OperationPtr op2) { context.value = OperationPtr( new Operation::And<Type>(context.value(), op2) ); } static void createXor(Context &context, OperationPtr op2) { context.value = OperationPtr( new Operation::Xor<Type>(context.value(), op2) ); } static void createOr(Context &context, OperationPtr op2) { context.value = OperationPtr( new Operation::Or<Type>(context.value(), op2) ); } }; }; |
При попытке компиляции выдается страшная ошибка, что мол где-то внутри спирита void функция попыталась вернуть значение. Проблема пропадает, если закоментировать все определения правил. Но смысла в этом нет. Operation::Base - это абстрактный класс операции. Некоторые потомки принимают 1, а некоторые 2 параметра. В принципе, это несущественно. В принципе, Base - это нод дерева операций. Т.е. задача - построить дерево, которое будет обходиться каждый раз, когда мне то понадобится. Использование парсера для конечной обработки данных не подходит, так как данных очень много.
ошибки можно увидеть тут: http://pastebin.com/m1ad57c76 |