抽象树与解析树
Abstract tree vs parser tree
本文关键字:抽象 更新时间:2023-10-16
我需要你的意见,以便在生成解析器树(ST)和生成抽象语法树(AST)之间选择最佳替代方案。这是上下文:
我想解析像C这样的语言(只是C的一个子集,做了一些更改,使其更面向伪代码),但不是为了将其翻译成其他输出语言/文件,而是为了执行其语句,以动画化其执行过程(我使用Qt绘制)。这个C子集的一个特点是它启用了嵌套的作用域。我对我在ST和AST之间的选择产生了怀疑,这源于符号表。总体思路是(使用BoostSpirit):
- 通过自定义Boost.espirit解析器解析源代码文件
- 语义操作产生一个语法树,只是源代码语法树的副本(或者,BoostSpirit内部语法树的一个副本,但有我自己的类和结构)。因此,没有AST
- 有了这个ST,程序按照自上而下的方向读取这个语法树,如下所示:
- 执行第一句话
- 上传带有新(句子结果)值的符号表
- 将符号表的实际状态保存在程序状态堆栈中
- 至3.1,直到ST完全处理完毕
- 为算法读取和绘制程序状态堆栈制作动画
两个原因:
- 如果我使用AST,在解析后,我会丢失有关变量声明及其类型等的信息。因此,我必须通过解析器的语义操作来处理符号表,这使解析器的编写和理解变得复杂。此外,无论实际作用域如何,我都必须始终使用具有所有变量的符号表(如果我在作用域I中,则只需要作用域I,I-1,…,1;而不是整个算法中的所有作用域)。这会消耗内存
- 在我的程序状态堆栈中,我只需要实际作用域和以前作用域的变量,以免通过动画使算法的可理解性复杂化。如果我使用ST,在将其保存到堆栈中之前,我必须删除所有不需要的符号。这需要时间
-
具有控制范围的静态符号表比动态符号表更难设计和使用。静态符号表必须为每个作用域都有一个标识符(例如),并将树的每个节点与每个标识符关联起来。动态符号表更容易工作,因为如果我在范围I中,只需要两个"向量"(可能是一个双队列和一个堆栈):
- 一个包含符号及其相关信息的容器(双队列?):容器中的最后一个变量是最近的声明变量
- 整数的容器(堆栈),显示每个作用域的开头(双队列的索引)
例如,对于作用域i:
- 容器1:[x y z x a b z f a z]
- 容器2:[0 3 6 8]
如果我离开范围I,只需要擦除最后一个整数和从位置8到末尾的符号。这棵树保持不变。
-
由于我必须在执行时间内执行每一句话,ST有助于我的执行。
两个问题:
- 哪个更好
- 存在任何形式来提取精神的内部树,或者为了不复制而定制它
我认为您正在寻找的是一个抽象语义图(ASG),它表示程序的语义(与语法相反)。你能做的是:
- 将源解析为AST,然后
- 将AST转换为ASG,最后
- 遍历ASG以执行实际代码
此外,我想说,您确实可以构建一个AST,它不是也抽象;例如,我目前正在构建自己的脚本语言解释器,AST将包含变量名(这对于调试解析器/解释器以及解析后的程序本身非常有用)。
相关文章:
- 无法创建抽象类的实例
- 如何定义一个纯抽象基类
- 派生类是否可以在抽象工厂设计模式中具有数据成员
- 用pybind11包装C++抽象类时出错
- 如何处理从一个对象传递到另一个在C++中具有公共抽象类的对象的消息
- 有没有办法按值将纯抽象类的所有子类传递给 C++ 中的函数?
- 抽象类错误,请参阅声明" "是抽象的
- 将自定义函数传递到基抽象类中以延迟执行
- 命名参数习惯用法和(抽象)基类
- 打印抽象对象 c++
- 如何在从抽象基派生的类中实现相同的方法?
- 将包含抽象类和普通类C++包导出到 Python
- C++:处理抽象类中的错误时出现问题
- C ++如何在原始抽象类中创建一个函数,该函数接受派生类的输入
- C++抽象的字节序是中立的吗?
- 在 C++ 中使用另一个头文件中的抽象类
- ATL::CComContainedObject<contained>: C2259 无法实例化抽象类
- C++:从抽象类重写纯虚拟运算符重载
- 让编译器告诉什么确切的纯虚拟方法使结构抽象?
- 位集元素迭代的抽象