多态抽象语法树(递归下降解析器):不可能? 我已经开始在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. 类节点{ 公众: 性病媒儿童; }; 类NodeBinary:公共节点{ 公众: 节点*左; 节点*右; }; 类nodenuary:公共节点{ 公众: 节点*操作数; }; 类NodeVar:公共节点{ 公众: std::字符串; NodeVar(std::string str):string(str){}; }; 类节点枚举器:公共节点{ 公众: 签名长数; NodeNumber(有符号长n):数(n){}; }; //等等。
然后像多态抽象语法树(递归下降解析器):不可能? 我已经开始在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. 类节点{ 公众: 性病媒儿童; }; 类NodeBinary:公共节点{ 公众: 节点*左; 节点*右; }; 类nodenuary:公共节点{ 公众: 节点*操作数; }; 类NodeVar:公共节点{ 公众: std::字符串; NodeVar(std::string str):string(str){}; }; 类节点枚举器:公共节点{ 公众: 签名长数; NodeNumber(有符号长n):数(n){}; }; //等等。,c++,parsing,polymorphism,abstract-syntax-tree,recursive-descent,C++,Parsing,Polymorphism,Abstract Syntax Tree,Recursive Descent,然后像nodeclaration,NodeCall,NodeNot,NodeAssignment,NodePlus,NodeMinus,NodeIf等类将继承自Node,或者继承自NodeBinary或NodeUnary>等非通用类 但是,其中一些采用更具体的操作数NodeAssignment始终采用一个var和一个数字/表达式。所以我必须将Node*left覆盖到NodeVar*left和NodeExpr*right。问题出现在NodePlus之类的东西上。左侧可以是NodeVar或NodeE
nodeclaration
,NodeCall
,NodeNot
,NodeAssignment
,NodePlus
,NodeMinus
,NodeIf
等类将继承自Node
,或者继承自NodeBinary
或NodeUnary>等非通用类
但是,其中一些采用更具体的操作数NodeAssignment
始终采用一个var和一个数字/表达式。所以我必须将Node*left覆盖到NodeVar*left和NodeExpr*right。问题出现在NodePlus
之类的东西上。左侧可以是NodeVar
或NodeExpr
!根节点也有一个类似的问题:在顶层解析以将子节点添加到根节点时,如何判断子节点是NodeExpr
、是NodePlus
、是NodeIf
等
我可以让所有节点都有一个枚举“类型”,说明它是什么类型,但是拥有一个好的多态继承树又有什么意义呢
这个问题通常是如何解决的???如果您对AST节点使用类继承,则需要像任何面向对象设计一样创建适当的继承层次结构
因此,例如,NodeAssignment
(可能是NodeStatement
的专门化)需要包含NodeLValue
(其中NodeVariable
是专门化)和NodeValue
。通常,左值(即您可以指定的对象)是值的子集,因此NodeLValue
将是NodeValue
的特化。等等您的二进制运算符节点将包含left
和right
成员,这两个成员都是NodeValue
基本对象(我希望NodeValue
是纯虚拟的,具有大量特定的专门化)
如果坚持使用递归下降解析器,则每个解析函数都需要返回节点
的适当子类,以便解析赋值左侧的函数在逻辑上返回一个NodeLValue*
,准备插入NodeAssignment
构造函数。(坦白地说,我会在所有这些类名中去掉节点
这个词。把它们都放在名称空间节点:
中,省得自己打字。)我明白你的意思,但我的部分问题是,即使在NodeValue中(例如,在加号中,左和右可以是值或变量),人们如何区分它们之间的差异如果使用的是一个数字还是一个变量?@acculator:面向对象设计的本质是每个对象都做它被要求做的事情。如果您需要询问对象它是什么以便为它做些什么,那么您没有正确地将行为封装到对象中。那么对于可以是var或val的对象,正确的封装是什么?@acculator:如果对象可以是var或val,那么它必须是val,因为它可以做val所能做的一切,在这种情况下,你不能要求做任何其他事情。这就是为什么我说var必须从val派生:var是一个val,它还可以做其他事情(比如被赋值)