用 Python 从零开始写一个简单的解释器(3)
admin
2023-07-30 22:58:31
0

到目前为止,我们已经为解释器写了一个词法分析器和 一个解析器组合子库。在这里,我们会创建抽象语法树(AST)的数据结构,使用组合子库写一个解析器,组合子库可以实现将词法分析器返回的标记列表转换为一个抽象语法树(AST)。

定义抽象语法树(AST)

在我们正式写解析器之前,需要定义清楚解析器输出的数据结构。我们将以类的形式实现这个数据结构。IMP语言的每个语法元素都有一个对应的类。这些类的对象各自代表了抽象语法树(AST)的一个结点。

IMP 中有三种结构:算术表达式(用于计算数字)、布尔表达式(用于为if-else和while语句计算条件)、声明语句。我们将从算术表达式开始,因为另外两种都依赖于它们。

算术表达式可能是下列三种之一:

  • 文字型整型常量,比如42;
  • 变量,比如x;
  • 二进制操作,比如x+42

这些组成了其他的算术表达式。

我们也可以用括号将表达式分组,像(x+2)*3。这并不是另一种不同的表达式,而是一种解析表达式的方式。

我们将为这三种形式定义三个类,加上为一般算术表达式定义的基类。现在,这些类除了存储数据并没有太多的功能。包含了__repr__函数,我们就可以在调试时打印抽象语法树(AST)。所有的AST类从继承自Equality,这样我们可以比较两个AST对象是不是相同的。这对于测试很有用。

123456789101112131415161718192021222324252627 from equality import * class Aexp(Equality):    pass class IntAexp(Aexp):    def __init__(self, i):        self.i = i     def __repr__(self):        return \’IntAexp(%d)\’ % self.i class VarAexp(Aexp):    def __init__(self, name):        self.name = name     def __repr__(self):        return \’VarAexp(%s)\’ % self.name class BinopAexp(Aexp):    def __init__(self, op, left, right):        self.op = op        self.left = left        self.right = right     def __repr__(self):        return \’BinopAexp(%s, %s, %s)\’ % (self.op, self.left, self.right)

布尔表达式有一点复杂。它分为四种:

  • 关系式表达(如x < 10
  • 与表达式(如x < 10 and y > 20
  • 或表达式
  • 非表达式

关系表达式的左边和右边都是算术表达式。“与”,“或”和“非”的左右两边都是布尔表达式。限制类型可以帮助我们避免类似 “x<10 and 30” 这样的无意义的表达式。

1234567891011121314151617 class Bexp(Equality):    pass class RelopBexp(Bexp):    def __init__(self, op, left, right):        ... class AndBexp(Bexp):    def __init__(self, left, right):        ...class OrBexp(Bexp):    def __init__(self, left, right):        ... class NotBexp(Bexp):    def __init__(self, exp):        ...

声明语句既可以包含算术表达式,也可以包含布尔表达式。声明语句也分为四种:赋值语句、复合语句、条件语句以及循环语句。

123456789101112131415161718 class Statement(Equality):    pass class AssignStatement(Statement):    def __init__(self, name, aexp):         ... class CompoundStatement(Statement):    def __init__(self, first, second):        ... class IfStatement(Statement):    def __init__(self, condition, true_stmt, false_stmt):        ... class WhileStatement(Statement):    def bole.com/category/feedback/trans-team/\”>翻译组。

到目前为止,我们已经为解释器写了一个词法分析器和 一个解析器组合子库。在这里,我们会创建抽象语法树(AST)的数据结构,使用组合子库写一个解析器,组合子库可以实现将词法分析器返回的标记列表转换为一个抽象语法树(AST)。

定义抽象语法树(AST)

在我们正式写解析器之前,需要定义清楚解析器输出的数据结构。我们将以类的形式实现这个数据结构。IMP语言的每个语法元素都有一个对应的类。这些类的对象各自代表了抽象语法树(AST)的一个结点。

IMP 中有三种结构:算术表达式(用于计算数字)、布尔表达式(用于为if-else和while语句计算条件)、声明语句。我们将从算术表达式开始,因为另外两种都依赖于它们。

算术表达式可能是下列三种之一:

  • 文字型整型常量,比如42;
  • 变量,比如x;
  • 二进制操作,比如x+42

这些组成了其他的算术表达式。

我们也可以用括号将表达式分组,像(x+2)*3。这并不是另一种不同的表达式,而是一种解析表达式的方式。

我们将为这三种形式定义三个类,加上为一般算术表达式定义的基类。现在,这些类除了存储数据并没有太多的功能。包含了__repr__函数,我们就可以在调试时打印抽象语法树(AST)。所有的AST类从继承自Equality,这样我们可以比较两个AST对象是不是相同的。这对于测试很有用。

123456789101112131415161718192021222324252627 from equality import * class Aexp(Equality):    pass class IntAexp(Aexp):    def __init__(self, i):        self.i = i     def __repr__(self):        return \’IntAexp(%d)\’ % self.i class VarAexp(Aexp):    def __init__(self, name):        self.name = name     def __repr__(self):        return \’VarAexp(%s)\’ % self.name class BinopAexp(Aexp):    def __init__(self, op, left, right):        self.op = op        self.left = left        self.right = right     def __repr__(self):        return \’BinopAexp(%s, %s, %s)\’ % (self.op, self.left, self.right)

布尔表达式有一点复杂。它分为四种:

  • 关系式表达(如x < 10
  • 与表达式(如x < 10 and y > 20
  • 或表达式
  • 非表达式

关系表达式的左边和右边都是算术表达式。“与”,“或”和“非”的左右两边都是布尔表达式。限制类型可以帮助我们避免类似 “x<10 and 30” 这样的无意义的表达式。

1234567891011121314151617 class Bexp(Equality):    pass class RelopBexp(Bexp):    def __init__(self, op, left, right):        ... class AndBexp(Bexp):    def __init__(self, left, right):        ...class OrBexp(Bexp):    def __init__(self, left, right):        ... class NotBexp(Bexp):    def __init__(self, exp):        ...

声明语句既可以包含算术表达式,也可以包含布尔表达式。声明语句也分为四种:赋值语句、复合语句、条件语句以及循环语句。

123456789101112131415161718 class Statement(Equality):    pass class AssignStatement(Statement):    def __init__(self, name, aexp):         ... class CompoundStatement(Statement):    def __init__(self, first, second):        ... class IfStatement(Statement):    def __init__(self, condition, true_stmt, false_stmt):        ... class WhileStatement(Statement):    def >):        self.name = name     def __repr__(self):        return \’VarAexp(%s)\’ % self.name

相关内容

热门资讯

Mobi、epub格式电子书如... 在wps里全局设置里有一个文件关联,打开,勾选电子书文件选项就可以了。
500 行 Python 代码... 语法分析器描述了一个句子的语法结构,用来帮助其他的应用进行推理。自然语言引入了很多意外的歧义,以我们...
定时清理删除C:\Progra... C:\Program Files (x86)下面很多scoped_dir开头的文件夹 写个批处理 定...
scoped_dir32_70... 一台虚拟机C盘总是莫名奇妙的空间用完,导致很多软件没法再运行。经过仔细检查发现是C:\Program...
65536是2的几次方 计算2... 65536是2的16次方:65536=2⁶ 65536是256的2次方:65536=256 6553...
小程序支付时提示:appid和... [Q]小程序支付时提示:appid和mch_id不匹配 [A]小程序和微信支付没有进行关联,访问“小...
pycparser 是一个用... `pycparser` 是一个用 Python 编写的 C 语言解析器。它可以用来解析 C 代码并构...
微信小程序使用slider实现... 众所周知哈,微信小程序里面的音频播放是没有进度条的,但最近有个项目呢,客户要求音频要有进度条控制,所...
Apache Doris 2.... 亲爱的社区小伙伴们,我们很高兴地向大家宣布,Apache Doris 2.0.0 版本已于...
python清除字符串里非数字... 本文实例讲述了python清除字符串里非数字字符的方法。分享给大家供大家参考。具体如下: impor...