хочется передизайнить немного...
От: Аноним  
Дата: 19.06.08 09:23
Оценка:
здравствуйте, уважаемые форумчане. занимаюсь самообразованием, и натолкнулся на заковырку...
хочется спросить, насколько оптимально следующее решение:
class CNode {
public:
    virtual ~CNode() {}
    virtual CValue getValue() const = 0;
    virtual void setValue(const CValue &value) = 0;
    virtual void traverse() {};
protected:
    CNode() {};
};
typedef boost::shared_ptr<CNode> CNodePtr;

class CValueNode : public CNode {  //для хранения какой-либо величины
    CValue _value;
public:
    CValueNode(const CValue &value): _value(value) {};
    CValue getValue() const {
        return _value;
    }
    void setValue(const CValue &value) {
        _value = value;
    }
};

class CVariableNode : public CNode { //для хранения узла "переменная"

    CVariablePtr _pVariablePtr;
public:
    CVariableNode(CVariablePtr &pVariablePtr): CNode(), _pVariablePtr(pVariablePtr) {};
    CValue getValue() const {

        if (!_pVariablePtr->initialized()) {
            throw CRunTimeException(_pVariablePtr->getName() + " not initialized");
        }

        return _pVariablePtr->getValue();
    }
    void setValue(const CValue &value) {

        _pVariablePtr->setValue(value);
    }
};

//а вот далее мне не нравится...
class CAssignNode : public CNode {
    CNodePtr _pVariablePtr;
    CNodePtr _pNode;
public:
    CAssignNode(const CNodePtr &pVariablePtr, const CNodePtr &pNode): _pVariablePtr(pVariablePtr), _pNode(pNode) {};
    void traverse() {
        _pNode->traverse();
        _pVariablePtr->setValue( _pNode->getValue() );
    }
    CValue getValue() const {        //(1)по логике инструкция присваивания не имеет возвращаемого значения, так как же быть?   //do not use it
       ???// return _pVariablePtr->getValue();
    }
    void setValue(const CValue &value) {   //(2)инструкции присваивания невозможно установить значение (нарушение семантики) 
        //do not use it
        ???//_pVariablePtr->setValue(value);
    }
};
std::stack( CNodePtr ) _stack;

при синтаксическом разборе каждый построенный узел "инструкции" помещается в _stack. к примеру инструкция присваивания схематически выглядит так:
1. считали переменную, создали для нее нод, запушили (push) его в наш _stack
2. считали оператор присваивания
3. считали выражение, создали для него нод, запушили (push) его в наш _stack
4. считали символ завершения инструкции
5. если все окей, то pop-им запушенные на шагах 1 и 3 ноды из _stack, создаем нод CAssignNode, передав в его конструктор вытащенные из _stack два нода как lhs и rhs узлы, и пушым его в _stack. на д. момент в стеке будет находиться только один нод.

т.е. смысл таков, что и ноды, и сами инструкции оперирующие lhs и rhs "работают" на одном стэке нодов, и в конце разбора текущей инструкции (то бишь, стэйтмента), у нас наш стек будет содержать ровно один нод. таким образом, весь блок возможных инструкций можно представить как class CStatementList : public CNode, что очень прельщает, ибо по завершению синтаксич. разбора у нас в стеке будет лежать лишь _один_ нод -- список стэйтментов, пробежав который, мы тем самым проинтерпретируем программу.
все хорошо, но жутко не нравится выделенные комментами два избыточных метода в CAssignStatement (то что, CAssignStatement не может иметь геттеров и сеттеров, думаю, понятно, отсюда и появление этого топика .
ежели для семаники "statement" создать отдельный класс, в котором будет только метод void traverse(), то непонятно, каким образом хранить в стэке _stack объекты обоих классов (объектов класса CNode, которые по мере разбора выливаются в объекты CStatement). не хотелось бы злоупотреблять dynamic-cast-ом... что же сделать... завести второй стэк — стэк инструкций, куда закидывать пропарсенные инструкции? душа просит все же как-то все увязать в текущем положении вещей. или же забить что для CAssignStatement (ну и для ему подобных далее) мы вынуждены имплементировать геттер и сеттер (ведь один фик мы не будем их вызывать в ходе своей программы)?

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