我已經開始在C++中編寫多態遞歸下降解析器。但是我遇到了一個問題。這些課程都設置這樣的:多態抽象語法樹(遞歸下降解析器):不可能?
class Node {
public:
std::vector<Node*> children;
};
class NodeBinary : public Node {
public:
Node* left;
Node* right;
};
class NodeUnary : public Node {
public:
Node* operand;
};
class NodeVar : public Node {
public:
std::string string;
NodeVar(std::string str) : string(str) {};
};
class NodeNumber : public Node {
public:
signed long number;
NodeNumber(signed long n) : number(n) {};
};
// etc.
然後像NodeDeclaration
,NodeCall
,NodeNot
,NodeAssignment
,NodePlus
,NodeMinus
,NodeIf
等類將繼承無論是從Node
或東西少通用像NodeBinary
或NodeUnary
。
但是,其中一些需要更具體的操作數。 NodeAssignment
總是需要一個var和一個數字/表達式。因此,我將不得不將Node *留在NodeVar * left和NodeExpr *上。問題來自諸如NodePlus
之類的問題。左邊可以是NodeVar
或NodeExpr
!而根節點也有類似的問題:在頂層解析以將子節點添加到根節點時,如何判斷子節點是否爲NodeExpr
,NodePlus
,NodeIf
等?
我可以讓所有的節點都有一個枚舉「類型」,它說明了它是什麼類型,但那麼有什麼好點的多態繼承樹呢?
這個問題通常如何解決?
我明白你的意思了,但我的問題的一部分是如何能夠告訴即使是在一個NodeValue中,如果它是一個數字或變量被使用,它的區別(例如,在一個左右可以是值或變量的加號中)? – Accumulator
@accumulator:面向對象設計的本質是每個對象都做它被要求做的事情。如果你需要向對象詢問它爲了做什麼而做的事情,那麼你沒有正確地將行爲封裝到對象中。 – rici
那麼什麼是可以是var或val的東西的正確封裝? – Accumulator