0

私は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. 

そしてNodeDeclarationNodeCallNodeNotNodeAssignmentNodePlusNodeMinusNodeIfなどのようなクラスがNodeからかNodeBinaryまたはNodeUnaryのようにそれほど一般的な何かのいずれかを継承します。

しかし、その中にはさらに特定のオペランドがあります。 NodeAssignmentは常にvarと数値/式をとります。だから私はNode * leftをNodeVar * leftとNodeExpr * rightにオーバーライドする必要があります。問題はNodePlusのようなもので起こります。左はNodeVarまたはNodeExprです。ルートノードにも同様の問題があります。ルートノードに子ノードを追加するために最上位レベルで解析するとき、子供がNodeExprNodePlusNodeIfなどであるかどうかをどのようにして知ることができますか?

すべてのノードにはどのタイプの列挙型の「型」があるかもしれませんが、いい多形の継承ツリーを持つ点は何でしょうか?

この問題は通常どのように解決されていますか?

答えて

0

ASTノードにクラス継承を使用する場合は、オブジェクト指向設計と同様に、適切な継承階層を作成する必要があります。

したがって、たとえば、NodeAssignmentは(おそらくNodeStatementの特殊化である)NodeLValueNodeVariableが専門となっている)を含有する必要があるとNodeValue。いつものように、LValues(つまり割り当てることができるもの)はValuesのサブセットなので、NodeLValueNodeValueの特殊化になります。等々。あなたは再帰下降パーサを使う、という場合は、あなたのバイナリ演算子ノードはNodeValueベースオブジェクトですどちらもleftrightメンバー、(私はNodeValueは、特定の専門分野の数が多いと、仮想純粋であることが予想されます。)

が含まれていますそれぞれの解析関数はNodeの適切なサブクラスを返さなければならないので、割り当ての左側を解析する関数は論理的にNodeLValue*を返し、NodeAssignmentコンストラクタに挿入する準備ができます。 (という名前のクラス名はすべて入れておきましょう。名前空間node::に名前を入れて、タイプを保存してください)

+0

私の問題の一部は、その差は、たとえNodeValueであっても、使用されている数値や変数の場合は、プラスとなります(たとえば、左と右は値または変数になります)。 – Accumulator

+0

@accumulator:オブジェクト指向設計の本質は、すべてのオブジェクトが何をすべきかを実行することです。オブジェクトのために何かをするためにオブジェクトを要求する必要がある場合、オブジェクトに正しく動作をカプセル化していません。 – rici

+0

次に、varまたはvalになる可能性があるものに対して、適切なカプセル化は何ですか? – Accumulator

関連する問題