首页 > 解决方案 > C++ AST 设计,修改向上转换的节点成员以更改子节点的最佳方法

问题描述

我需要一些关于我的 AST 设计的建议。我正在为一个简单的解释器使用一个非常典型的 AST 节点系统。

在这一点上,我正在尝试实现简单的常量传播。这涉及到节点树的转换,这导致对我的 AST 最佳设计的一些混淆,特别是如何从向上转换的节点叶子访问类成员。

class Node {
public:

    Node* parentNode;
    std::vector<Node*> childNodes;
    Node() {}
};


class Var : public Node {
public:

    std::string identfier;
    Var();
    Var(std::string cidentfier) {
        identfier = cidentfier;
    }

};

class Assign : public Node {
public:

    Node* right;
    Var* left;
    
    Assign();
    Assign(Var* cleft, Node* cright) {
        cleft->parentNode = this;
        cright->parentNode = this;
        left = cleft;
        right = cright;
        childNodes.push_back(cleft);
        childNodes.push_back(cright);
    }
};


假设我有一个看起来大致像的分配节点x = y

Var* leftNode = new Var("x");
Var* rightNode = new Var("y");

Node* assignNode = new AssignNode(leftNode, rightNode); 

现在我想用新的 Var 节点 (z) 替换分配节点 (y) 的右侧,这样我的新表达式看起来像这样x = z。但是,我仅通过 make upgetNodeToBeReplaced()函数引用了 (y) Var 节点。

Node* &rightNode = getNodeToBeReplaced(); //returns y
Node* assignNode = rightNode->parentNode; //returns assign node with x = y

Var* replacementNode = new Var("z");

我需要将assignNode' 的right成员更改replacementNode为以修改树(也将replacementNode' 的父级更改为,assignNode但这相当微不足道)。

问题是,当 assignNode 被向上转换时,访问assignNode's指针的最佳方法是什么,因此它是一个对象。我不想做任何昂贵的垂头丧气的回馈。rightNodeAssign*

*assignNode->right = *replacementNode; // can't be done as assignNode is upcasted to Node*

我可以修改的唯一一点信息是指向存储在childNodes每个节点拥有的向量中的类成员的指针。

因此,此代码适用于此目的。

Node* &rightNode = getNodeToBeReplaced(); //returns y
Node* assignNode = rightNode->parentNode; //returns assign node with x = y

auto &parentChild = std::find(assignNode->childNodes.begin(), assignNode->childNodes.end(), rightNode);

Var* replacementNode = new Var("z");

*replacementNode->parentNode = *assignNode;
**toBeReplacedParentChild = *replacementNode;

但是我不确定这是否是好的 AST 设计。如果不是所有的类成员都被推送到childNodes向量,那么替换将不起作用。谁能提出一个更好的解决方案来修改和跟踪 AST 中的子节点?

标签: c++nodesabstract-syntax-treeupcasting

解决方案


推荐阅读