我已经有了tokenizer接口,可以创建一个令牌列表。我有解析器的工作机制。它真的很独特,就像一个魅力。我唯一想念的是AST的基本结构。如何在抽象级别上表示树,节点和语句。我不需要任何实现只是快速了解它应该在类层次结构中看起来如何? 我正在研究面向对象的语言。是的,我已经意识到我将需要两种类型的陈述。一些值返回“表达式”类型语句和一个非返回的指令流控制类型语句。 非常感谢你。
答案 0 :(得分:15)
如果您的语言是命令式/类似c,那么常见的场景是从顶级层次结构分为两种超类型开始:
该程序是一个语句列表,它本身就是一个语句。
您可能希望为扩展语句基类的语句类型设置一个类。
典型情况如下:
表达式:
拥有这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,只有静态类型就足够了,如果你计划实现一些后端,你也需要一些动态类型)。
如果您不打算支持需要大小信息的固定大小数组,则通常可以使用某些枚举指定静态类型。如果你想要带有size的固定大小数组,你可以为类实现一个类,并让数组类型保存额外的大小信息。
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表单中的代码,您将需要一个内存,它将包含一个包含运行时内存信息的堆栈/堆。此时,您需要将值与其类型信息一起存储。