C++ 中的抽象语法树表示
Posted
技术标签:
【中文标题】C++ 中的抽象语法树表示【英文标题】:Abstract Syntax Tree representation in C++ 【发布时间】:2013-08-12 13:45:19 【问题描述】:我已经有了创建标记列表的标记器接口。我有解析器的工作机制。它真的很独特,就像一个魅力。我唯一想念的是 AST 的基本结构。树、节点和语句应如何在抽象级别表示。我不需要任何实现,只需快速了解它在类层次结构中的外观如何? 我正在研究一种面向对象的语言。是的,我已经意识到我需要两种类型的陈述。一些返回值的“表达式”类型语句和一个不返回的指令流控制类型语句。 非常感谢。
【问题讨论】:
我建议查看 CLANG/LLVM 项目。非常可靠的开源编译器,有很多用途。它将帮助您入门,并且挖掘他们的论坛/代码将提供比堆栈溢出帖子中的任何人都更好的答案。 clang.llvm.org/docs/InternalsManual.html @ChrisCM:Clang 的一个问题,他们所谓的AST
实际上是ABT
,即 bindings(此标识符在这里声明,类型这个变量是 X) 已经解决。在两阶段算法 1/ 生成 AST 2/ 解析绑定中实际执行此操作更容易。
一个正确的澄清,但我认为在使用它作为理解语法树的起点的范围内是不必要的。你需要的节点类型、结构、语句等……在这两种方案中都是相似的,而这正是 OP 好奇的地方。
@MatthieuM 什么是ABT
?
@HelloGoodbye:这是我所知道的抽象绑定树的最佳名称。也就是说,一个富含语义信息的 AST:解析名称,输入表达式和变量,...
【参考方案1】:
如果你的语言是命令式的/类 c 语言,常见的场景是顶层结构被分成 2 个超类型:
表达式 声明程序是一个语句列表,它本身就是一个语句。
您可能希望拥有一个扩展语句基类的语句类型类。
一个典型的场景是这样的:
语句块(语句列表) ite (if then else) for(一个 for 循环及其初始化语句列表、检查表达式、增量语句和块 while(类似,但只检查表达式 变量声明 赋值(包括 += -= ++ --,您可以使用运算符字段、lval 和 rval 将所有内容包装在一个类中) 函数调用(无效一)对于表达式:
Bop(二元运算,任何有 2 个操作数和 1 个运算符,即 + - * / % | & && || == Uop(一元运算,任何有 1 个操作数和 1 个运算符,即 ~ !) 函数调用(非空函数) 条件表达式(exp ? true val : false val)拥有这 2 个抽象(表达式和语句)的好处是,在您的所有类中,您将拥有抽象类型,并且将能够使用访问者模式访问 AST。
例如,一些类看起来像这样(伪代码):
class Ite extends Statement
Expression condition;
Statement ifBranch;
Statement elseBranch;
class Bop extends Expression
BOperator operator; // +, -. * or whatever
Expression left; // Left operand
Expression right; // Right operand
class StatementBlock extends Statement
List<Statement> statements;
class Assignment extends Statement
AOperator assignOp; // = += -= etc.
LVal lvalue; // The lvalue cannot be an arbitrary expression, you will usually have a specific type for it
Expression rvalue; // Right value
此外,您将需要某种方式来表示 类型(对于 AST,仅静态类型就足够了,如果您的项目还需要实现一些后端,那么您还需要一些动态类型)。
如果您不打算支持需要大小信息的固定大小数组,通常可以使用一些枚举指定静态类型。如果你想要固定大小的数组,大小,你可以实现一个类型的类,并让数组类型保存额外的大小信息。
enum Type
CHAR,
SHORT,
INT,
LONG,
FLOAT,
DOUBLE,
ARRAY
class Float extends StaticType
final Type type = Type.FLOAT;
class Array extends StaticArray
final Type type = Type.ARRAY;
int size;
然后,您将为 AST 中的每种类型实例化一个 StaticType 实例,例如当用户声明一个变量时。如果您计划在将来进行静态类型检查,您也可以使用相同的层次结构。
至于以 AST 形式运行/解释代码,您将需要一个 Memory 来保存包含有关运行时内存信息的堆栈/堆。此时,您需要将值与其类型信息一起存储。
【讨论】:
我应该如何将它们排列在树形层次结构中?我需要某种“AST”和“ASTNode”类来遍历整个树。 在我的解决方案中,您实际上并不需要所有节点都属于同一类型。您将拥有一个 StatementBlock 根,它将包含 Statement 的列表。这些语句将包含其类定义的子树。如您所见,我以递归方式定义了 AST 层次结构,因此您可以使用模式访问者非常简单地浏览整个树。这是一种非常面向对象的方法,如果您不想使用继承,您可以让所有 ASTNode 节点的类型由枚举表示,而不是为每个节点类型设置不同的类。 问题是如果我需要 Statement 类型,我将不知道派生的类型。我只会知道这是一个声明而已。 为此,您必须使用一种非常强大的设计模式,称为 pattern visitor!在这里查看我的另一个答案,如果这是您第一次看到它,您将需要一些时间来理解:***.com/questions/16165640/… 其实我并没有建议返回 Class 类型的对象,只是将您将在您的语言中使用的 type 包装为一个名为 Type 的抽象类。我根本没有使用反射,一切都可以在 C++ 中完美运行!以上是关于C++ 中的抽象语法树表示的主要内容,如果未能解决你的问题,请参考以下文章