我已经开始在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
!并且根节点也有类似的问题:在顶层解析以将子节点添加到root时,如何判断子节点是NodeExpr
,NodePlus
还是{{1}等等......?
我可以让所有节点都有一个枚举“类型”,说明它是什么类型,但那么有一个很好的多态继承树的意义呢?
这个问题通常是如何解决的?
答案 0 :(得分:0)
如果您正在为AST节点使用类继承,则需要创建适当的继承层次结构,就像任何面向对象的设计一样。
因此,例如,NodeAssignment
(可能是NodeStatement
的特化)需要包含NodeLValue
(其中NodeVariable
是专业化)和NodeValue
。像往常一样,LValues(即您可以分配的内容)是值的子集,因此NodeLValue
将是NodeValue
的特化。等等。您的二元运算符节点将包含left
和right
个成员,这两个成员都是NodeValue
个基础对象(我希望NodeValue
是纯虚拟的,具有大量特定的特。)
如果你坚持使用递归下降解析器,每个解析函数都需要返回Node
的适当子类,以便解析赋值左侧的函数在逻辑上返回{{1准备插入NodeLValue*
构造函数。 (坦率地说,我在所有这些类名中抛弃了NodeAssignment
这个词。将它们全部放入命名空间Node
并节省一些打字。)