C++ 抽象树与解析器树

C++ 抽象树与解析器树,c++,parsing,boost,abstract-syntax-tree,boost-spirit,C++,Parsing,Boost,Abstract Syntax Tree,Boost Spirit,我需要您的意见,以便在生成解析器树(ST)和生成抽象语法树(AST)之间选择最佳的替代方案。背景是: 我想解析像C这样的语言(只是C的一个子集,做了一些修改,使它更面向伪代码),但不是为了在其他输出语言/文件中翻译它,而是为了执行它的语句,以动画化它的执行过程(我使用Qt绘制)。这个C子集的一个特性是它支持嵌套作用域。关于我在ST和AST之间的选择,我的疑问来自符号表。总体思路是(使用Boost.spirit): 通过自定义Boost.spirit解析器解析源代码文件 语义操作生成一个语法树,只

我需要您的意见,以便在生成解析器树(ST)和生成抽象语法树(AST)之间选择最佳的替代方案。背景是:

我想解析像C这样的语言(只是C的一个子集,做了一些修改,使它更面向伪代码),但不是为了在其他输出语言/文件中翻译它,而是为了执行它的语句,以动画化它的执行过程(我使用Qt绘制)。这个C子集的一个特性是它支持嵌套作用域。关于我在ST和AST之间的选择,我的疑问来自符号表。总体思路是(使用Boost.spirit):

  • 通过自定义Boost.spirit解析器解析源代码文件
  • 语义操作生成一个语法树,只是源代码语法树的一个副本(也可以是Boost.spirit内部语法树的一个副本,但有我自己的类和结构)。因此,没有AST
  • 拿着这个ST,程序按照如下自顶向下的方向读取这个语法树:
  • 执行第一句话
  • 上载带有新(句子结果)值的符号表
  • 将符号表的实际状态保存在程序状态堆栈中
  • 直到ST完全处理完毕
  • 为读取和绘制程序状态堆栈的算法设置动画
  • 两个理由:

  • 如果我使用AST,在解析之后,我会丢失有关变量声明及其类型等的信息。因此,我必须通过解析器的语义操作来处理符号表,这使得解析器的编写和理解变得复杂。此外,我必须始终使用包含所有变量的符号表,而不考虑实际范围(如果我在范围I中,则只需要范围I,I-1,…,1;而不是整个算法中的所有范围)。这会消耗内存
  • 在我的程序状态堆栈中,我只需要实际作用域和先前作用域的变量,以避免通过动画使算法的可理解性复杂化。如果使用ST,则必须先删除所有不需要的符号,然后才能将其保存到堆栈中。这需要时间
  • 具有控制范围的静态符号表比动态符号表更难设计和使用。静态符号表必须具有每个作用域的标识符(例如),并将树的每个节点与每个标识符关联起来。动态符号表更容易工作,因为如果我在范围I中,只需要两个“向量”(可能是一个双队列和一个堆栈):

    • 包含符号及其相关信息的容器(双队列?):容器中的最后一个变量是最近声明的变量
    • 整数的容器(堆栈),显示每个作用域的开始(双队列的索引)
    例如,对于范围i:

    • 容器1:[x y z x a b z f a z]
    • 容器2:[03 6 8]
    如果我离开范围I,我只需要擦除最后一个整数和从位置8到末尾的符号。这棵树保持原样

  • 由于我必须在执行时间内执行每个句子,因此ST有助于我执行

  • 两个问题:

  • 那哪个更好
  • 是否存在任何形式来提取内在精神之树或定制它以避免复制
    我认为您需要的是一个抽象语义图(ASG),它表示程序的语义(与语法相反)。您可以做的是:

  • 将源解析为AST,然后
  • 将AST转换为ASG,最后
  • 遍历ASG以执行实际代码

  • 另外,我想说你确实可以构建一个不太抽象的AST;例如,我目前正在构建自己的脚本语言解释器,AST将包含变量名(这对于调试解析器/解释器以及解析的程序本身非常有用)。

    您刚刚提醒我丢失了什么(几乎)当我不得不转到C时:|如果你在这里有语法和基本的实现,这将是可以远程回答的。另外,“为读取和绘制程序状态堆栈的算法设置动画”意味着什么。我有一种预感,描述已经预先假定了一个特定的实现。我现在看到的是“不是一个真正的问题”(因为没有具体的要求,只有松散的想法)和“过于本地化”(因为“隐含的要求”(动画(?),具体的范围观念)不太可能在将来与其他人相关。这是一个有点背景的理论/设计问题。这不是一个实现问题。任何关于编译器的书都谈到AST,因为自定义创建解析器树(在本书中说)是由于程序创建了两倍于解析器树的源代码丢失(解析器的树本身和您生成的副本)。但我问这本书是否有这样的上下文(解释)的理由,我认为这个问题是明确的和相关的。@sehe动画在这里不相关。事实上,出于“动画目的”(无论要求如何)我只需要将源迭代器范围与相关的标记一起存储,类似于二进制文件上的“调试信息”,但在解析树上