我已经编写了一个LR(1)解析器,该解析器可以将语法语言成功地解析为具体语法树的字符串,但是我现在正在尝试构建抽象语法树。我正在为AST节点使用继承设计:struct ASTNode { virtual Type typeCheck() = 0;}struct IDNode : public ASTNode { string name; ...}struct INTNode : public ASTNode { int value; ...}struct BOPNode : public ASTNode { ASTNode *pLeft; ASTNode *pRight; ...}struct Add_BOPNode : public BOPNode { ...}struct ParamNode : public ASTNode { string name; ASTNode *pTypeSpecifier; ...}struct ParamListNode : public ASTNode { vector<ParamNode*> params; ...}struct FuncDec : public ASTNode { string functionName; ASTNode *pFunctionBody; ASTNode *pReturnType; ASTNode *pParams; ...}当我在LR(1)解析器中执行精简时,我会根据用于精简的规则生成一个新节点。对于大多数节点而言,这非常简单,但是我不确定采用干净的方法来实现包含其他节点列表的节点。以上面的ParamListNode为例:struct stack_item { int state; int token; string data; ASTNode *node;};/// rule = the number of the rule being reduced on/// rhs = the items on the right-hand side of the ruleASTNode* makeNode(int rule, vector<stack_item> rhs) { switch(rule) { /// <expr> ::= <expr> '+' <term> case 1: return new Add_BOPNode(rhs[0].node, rhs[2].node); /// <param> ::= IDENT(data) ':' <type> case 2: return new ParamNode(rhs[0].data, rhs[2].node); /// <param_list> ::= <param> case 3: return new ParamList(rhs[0].node); /// <param_list> ::= <param_list> ',' <param> case 4: { auto list = dynamic_cast<ParamListNode*>(rhs[0].node); list->params.push_back(rhs[2].node); return list; } ... }}由于生成节点需要返回ASTNode的子类,因此我必须创建一个子类,该子类将每个子节点都包含一个vector 。但是,由于并非每个节点都需要是列表结构,因此在访问内部列表之前,必须对子类进行dynamic_cast 。我觉得应该有一种更清洁的方式来处理子节点列表,而不必依赖dynamic_cast 。另一个问题是关于FuncDec节点的。它具有pParams,应该是ParamList(或直接为vector ),但是要做到这一点,我必须将传入的ASTNode动态_cast 到ParamList或Param节点。再说一次,我觉得应该有一种不使用dynamic_cast 的方法,但是我想不到。另外,如果您对我如何更好地构建或实现任何其他建议,将不胜感激:) 最佳答案 我的LRSTAR Parser Generator通过仅使用一个类Node创建一个抽象语法树(AST)。每个节点具有相同的结构,指向 token 的指针(如果是叶节点,则在符号表中)以及指向父节点,子节点和下一个节点的指针。下一个指针允许您具有节点列表(父节点有多个子节点)。多年来效果很好。在AST处理期间,与节点相关联的功能负责节点的处理。例如,加法函数将执行与减法函数不同的操作。函数是不同的,而不是每种类型都有不同的类的节点。这是我使用的节点结构: class Node { public: int id; // Node id number int prod; // Production (rule) number int sti; // Symbol-table index (perm or temp var). int prev; // Previous node. int next; // Next node. int line; // Line number. int child; // Child node. int parent; // Parent node. };关于c++ - 在LR解析过程中构造AST,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/35509898/
10-11 09:16