Создание собственного дерева выражений в духе: ци (без Utree или Boost :: Variant)

Прежде всего, если гораздо проще использовать Boost Variant или Utree, то я с ними соглашаюсь и постараюсь решить свои проблемы с ними в другой теме. Тем не менее, я бы очень хотел иметь возможность построить дерево, как у меня ниже.

Фон, игнорируйте, если вы хотите перейти непосредственно к вопросу: я хотел бы иметь возможность построить дерево выражений, которое анализирует что-то вроде

"({a} == 0) && ({b} > 5)"

или стандартное математическое выражение

"(2 * a) + b"

Затем я определю, что такое a и b, прежде чем оценивать свое дерево, примерно так:

a = 10;
double val = myExpression->Evaluate();

Моя проблема возникает, когда я пытаюсь создать попытку анализа строки в моем дереве выражений. Я использую абстрактный классВыражение» который потом выводитПеременная ","Константа» а также "Binary» выражения (это также будет делать унарные, но это не должно влиять на мою проблему. У меня продолжают возникать проблемы с добавлением к дереву, используя мои правила, поэтому я явно делаю что-то не так. У меня с трудом складывается голова вокруг атрибутов.

Мое дерево выглядит следующим образом (Tree.h):

class BinaryExpression;
typedef double (*func)(double, double);

class Expression
{
public:
    virtual double Evaluate() = 0;
};

class BinaryExpression : public Expression
{
private:
    Expression* lhs;
    Expression* rhs;
    func method;

    double Evaluate();

public:
    BinaryExpression(void);
    BinaryExpression(char op, Expression* lhs, Expression* rhs);
    BinaryExpression(char op);
    void operator()(Expression* lhs, Expression* rhs);
};

class ConstantExpression : public Expression
{
private:
    double value;
public:
    ConstantExpression(void);
    ConstantExpression(char op);
    ConstantExpression(double val);

    double Evaluate();
};

// Require as many types as there are fields in expression?
static double a;
static double b;
class VariableExpression : public Expression
{
private:
    char op;

public:
    VariableExpression(char op);

    double Evaluate();
};

BOOST_FUSION_ADAPT_STRUCT(
    BinaryExpression,
    (Expression*, lhs)
    (Expression*, rhs)
    (func, method)
)

BOOST_FUSION_ADAPT_STRUCT(
    VariableExpression,
    (char, op)
)

BOOST_FUSION_ADAPT_STRUCT(
    ConstantExpression,
    (double, op)
)

Tree.cpp

typedef double (*func)(double, double);

/////////////////////////////////////////////////////////////////////////////
// BINARY EXPRESSION
////////////////////////////////////////////////////////////////////////////

BinaryExpression::BinaryExpression(void) {}

BinaryExpression::BinaryExpression(char op, Expression* lhs, Expression* rhs)
{
    this->lhs = lhs;
    this->rhs = rhs;

    // Example, methods are held in another header
    if (op == '+')
        method = Add;
    else if (op == '-')
        method = Subtract;

}

double BinaryExpression::Evaluate()
{
    return method(lhs->Evaluate(), rhs->Evaluate());
}

BinaryExpression::BinaryExpression(char op)
{
    if (op == '+')
        method = Add;
    else if (op == '-')
        method = Subtract;
}

void BinaryExpression::operator()(Expression* lhs, Expression* rhs)
{
    this->lhs = lhs;
    this->rhs = rhs;
}

/////////////////////////////////////////////////////////////////////////////
// CONSTANT EXPRESSION
////////////////////////////////////////////////////////////////////////////

ConstantExpression::ConstantExpression() {}

ConstantExpression::ConstantExpression(char op)
{
    this->value = op - 48;
}
ConstantExpression::ConstantExpression(double val)
{
    value = val;
}

double ConstantExpression::Evaluate()
{
    return value;
}

/////////////////////////////////////////////////////////////////////////////
// VARIABLE EXPRESSION
////////////////////////////////////////////////////////////////////////////

VariableExpression::VariableExpression(char op)
{
    this->op = op;
}

double VariableExpression::Evaluate()
{
    // a and b are defined in the header, and are used to fill in the variables we     want to evaluate
    if (op == 'a')
        return a;
    if (op == 'b')
        return b;
    return 0;
}

Теперь, если я создаю дерево вручную, все работает нормально, поэтому я не думаю, что есть проблема с его структурой.

Вот Grammar.h (Множество комментариев, где я пробовал разные вещи, я мог бы их удалить, но, возможно, стоит показать, что яЯ пробовал / где я хочу пойти с этим)

#include "Tree.h"

#include 
#include 

namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;

qi::_1_type _1;
qi::_2_type _2;

// Pass functions to boost
boost::phoenix::function plus = BinaryExpression('+');
boost::phoenix::function minus = BinaryExpression('-');

template 
struct ExpressionParser : qi::grammar
{
    ExpressionParser() : ExpressionParser::base_type(expression)
    {
        qi::_3_type _3;
        qi::_4_type _4;

        qi::char_type char_;
        qi::uint_type uint_;
        qi::_val_type _val;
        qi::raw_type raw;
        qi::lexeme_type lexeme;
        qi::alpha_type alpha;
        qi::alnum_type alnum;
        qi::bool_type bool_;
        qi::double_type double_;


        expression = //?
            additive_expr                       [_val = _1]
            ;

        //equality_expr = 
        //      relational_expr >> 
        //      *(lit("==") > relational_expr)      [/*Semantice action to add to tree*/]
        //      ;

        additive_expr =
            primary_expr >>
            ( '+' > primary_expr)               [plus(_val, _1)]   
            | ( '-' > primary_expr)             [minus(_val, _1)]
            ;
        // Also tried "_val = plus(_1, _2)"

        primary_expr =
            constant                                [_val = _1]
            | variable                          [_val = _1]
            //| '(' > expression > ')'          [_val = _1]
            ;

        string %=
            '{' >> *(char_ - '}') >> '}'
            ;

        // Returns ConstantExpression
        constant =
            double_                                 [_val = _1];

        // Returns VariableExpression
        variable =
            char_                                   [_val = _1]
            ;
    }

    // constant expression = double
    // variable expression = string
    qi::rule
        expression;

    qi::rule
        // eventually will deal with all these rules
        equality_expr,
        relational_expr,        
        logical_expr,
        additive_expr,
        multiplicative_expr,
        primary_expr
            ;

    qi::rule
        constant
        ;

    qi::rule
        variable
        ;

    qi::rule
        string
        ;
};

Так что это действительно взломано, но, надеюсь, это покажет, чего я пытаюсь достичь. Любые советы или советы будут очень признательны. Есть ли пример, когда кто-то построил такое дерево без использования варианта или utree.

Также извините, если я нарушил соглашение, и для моего форматирования, я попытался сделать его максимально читабельным.

Ответы на вопрос(1)

Ваш ответ на вопрос