问题描述
我看过很多有关单遍和多遍编译器的文章,我认为 One Pass编译器的基本部分是
但是我有一个问题,我无法理解。 Expression如何在单遍编译器(不使用AST)
中工作让我们以1 + 2 / 3
为例。假设您需要为此生成汇编代码。创建解析器后,如何从中生成程序集? (直接)汇编代码如何生成而没有任何错误?
您可以举例说明吗?请告诉我这个问题是否有问题。我是Stackoverflow的新手:)
解决方法
单次编译器处理a=b*c[i]+d*e;
之类的最简单方法是处理遇到的每个令牌:
-
a
生成代码以将a
的地址压入堆栈 -
=
记录以下事实:堆栈中的最高项目将用作任务的目标。 -
b
生成代码以将b
的地址压入堆栈 -
*
生成代码以弹出(b
)的地址,在那里获取对象并将其推送。 - 还要记录一个事实,即堆栈上的最高位将被用作乘法的左操作数。
-
c
生成代码以将c
的地址压入堆栈 -
[
记录以下事实:堆栈中的最高项将是[
的左操作数,并评估以下表达式 -
i
生成代码以将i
的地址压入堆栈 -
]
生成代码以弹出(i
)的地址,在那里获取对象并将其推送。 - 还要弹出堆栈中的两个项目(
i
的值和c
的地址,添加它们,然后将结果压入 -
+
生成代码以弹出(c[i]
)的地址,在那里获取对象,然后将其推送 - 还生成代码以弹出前两个值(
c[i]
和b
),将它们相乘并推入结果 - 还要记录一个事实,即栈顶的项目将是
+
的左操作数 -
d
生成代码以将d
的地址压入堆栈 -
*
生成代码以弹出地址,在那里获取对象,然后将其推送。 - 还要记录一个事实,即堆栈上的最高位将被用作乘法的左操作数。
-
e
生成代码以将e
的地址压入堆栈 - (语句结尾):生成代码以弹出(
e
的地址),在那里获取对象并将其推送 - 还生成代码以弹出前两个值(
e
和d
),将它们相乘并推入结果 - 还生成代码以弹出前两个值(
d*e
和b*c[i]
),添加它们并推送结果 - 还生成代码以弹出值(
b*c[i]+d*e
)和地址a
并将值存储到地址
请注意,在许多平台上,如果将以推送结束的操作的代码生成推迟到生成下一个操作之前,并且如果紧随推送之后的弹出窗口与它们合并,则性能可能会大大提高。此外,让编译器记录赋值运算符的左侧为a
的事实,而不是生成用于推送该地址的代码,然后让赋值运算符直接存储到{ {1}},而不是先计算地址,然后将其用于存储。另一方面,所描述的方法将能够为直到要处理的机器代码的确切字节的所有内容生成机器代码,而不必跟踪将要解开的未决操作之外的其他内容。