- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我已经编写了一个 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 rule
ASTNode* 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 直接),但要做到这一点,我必须 dynamic_cast<> 传入的 ASTNode 到 ParamList 或 Param 节点。同样,我觉得应该有一种不使用 dynamic_cast<> 的方法,但我想不出一个。
此外,如果您对我如何更好地构建或实现任何东西有任何其他建议,我们将不胜感激:)
最佳答案
我的 LRSTAR Parser Generator仅使用一个类 Node.js 创建抽象语法树 (AST)。每个节点都是相同的结构,一个指向 token 的指针(如果是叶节点,则在符号表中),以及指向父节点、子节点和下一个节点的指针。 next 指针允许您拥有节点列表(父节点的多个子节点)。这多年来一直运作良好。
在 AST 的处理过程中,与节点关联的函数负责节点的处理。例如,add 函数将执行与 subtract 函数不同的操作。功能不同,而不是每种类型都有不同的类的节点。
这是我使用的节点结构:
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/
我对以下内容感到困惑quote来自维基百科: In other words, if a language was reasonable enough to allow an efficient one
我正在努力研究解析器理论,但我一直在不同的来源中找到相同的示例。语法大致如下(简化): E = T E = E + T T = 0..9 所以假设字符串 2 + 2 将被这样解析(“|”将堆栈与提醒分
PUSH{lr}的等效指令是什么?和 POP{lr}在 ARM Arch64 指令集中。 是 STR X30, [SP, #8]正确的 ?你能解释一下保持堆栈对齐的概念吗?我对 ARMv8 比较陌生,
是否有一个很好的在线资源,其中包含一些主要解析算法(LL(1)、LR(1)、LR(0)、LALR(1))的语法集合?我发现了许多属于这些家族的单独语法,但据我所知,没有什么好的资源可以让人编写大量示例
我使用IAR编译例程,但在ARM A7上运行错误;然后当我打开 IAR 生成的 .lst 文件时,我得到了以下问题。 它是一个ISR,首先push {r3, r4, r5, lr},但是POP {r0
我想知道 LR 属性解析器可以做什么以及它是如何实现的。 yacc 生成的解析器允许在属性源是使用 $0、$-1 等规范语法位于左侧的兄弟时继承属性。使用 S -> A B B 将能够从 A 继承一个
我想使用“merc_timer_handle_t”来记录loadrunner中的时间,但是当我创建场景时,LR给出错误消息:“第15行靠近“MasterT”的语法错误” . 我想知道如何使用“merc
我正在使用 ray RLlib 库在 5 排游戏中训练多智能体训练器。这是零和环境,所以我有代理人行为退化的问题(总是赢得第一个代理人,5 步获胜)。我有一个想法以这种方式改变代理人的学习率:首先训练
我是 Graphviz 的新手,尝试使用如下所示从左到右布局一些节点: digraph g { graph [ rankdir = "LR" ]; node [ fontsize = "16", f
LR(1) 解析器可以解析这种类型的语法吗? S -> SA | A A -> aSb | ab 我正在尝试编写一个实现此类解析器的 Java 程序,但我只能在没有左递归的语法上获得正确的结果。 最
从历史上看,LALR(1) 解析器比 LR(1) 解析器更受青睐,因为 LR(1) 解析器生成的大量状态需要资源。很难相信这仍然是当今计算环境中的一个问题。情况仍然如此,还是现代编译器现在使用规范的
我是编译主题的新手,刚刚开始自下而上解析的练习。 我一直坚持以下问题。 为以下文法建立一个LR(0)解析表: 1) E –> E + T 2) E –> T 3) T –> (E) 4) T –> i
我有一个我无法解决的 LR(1) 冲突语法;然而,语法应该是明确的。我将首先使用五个标记在简化语法上演示问题:(, ), {}, , 和 id。 EBNF 看起来像这样: args = (
假设 G(增强语法): E' - > E E - > E+T|T T - > T*F|F F - > (E)|id 因此,在 dfa 的创建级别之一中,我已经达到了这一点:(龙书中的 I6)
我经常看到以 lr 指针终止的 ARM 堆栈跟踪(阅读:Android NDK 堆栈跟踪),如下所示: #00 pc 001c6c20 /data/data/com.audia.dev
我使用的是 ARM Cortex-M4 处理器。据我了解,LR(链接寄存器)存储当前执行函数的返回地址。但是,内联和/或裸函数会影响它吗? 我正在努力实现简单的多任务处理。我想写一些代码来保存执行上下
我正在尝试为一种将用于生成其他文件的模板(配置)文件构建一个简单的 LR 解析器。我已经阅读和阅读了有关 LR 解析器的信息,但我似乎无法理解它!我知道有一个解析栈,一个状态栈和一个解析表。 toke
我在理解LR(1)-项目中的超前原理方面遇到困难。如何计算超前集? 例如,我有以下语法: S -> AB A -> aAb | b B -> d 然后,第一个状态将如下所示: S -> .AB , {
我正在学习“Engineering a Compiler, 2nd Edition”。我知道什么是LR(1)文法,但我在这本书中找不到运算符优先文法。 然后我从图书馆借了《编译器——原理、技术和工具》
我至少读过十几遍维基百科的解释,但我仍然对 LR(0) 解析器如何离开状态 0 感到困惑。 Wikipedia's example, with its explanation, says : The
我是一名优秀的程序员,十分优秀!