1

我正在学习编译器并为一种处理两种类型的简单语言创建代码生成器:字符和整数。

在扫描仪扫描用户输入然后由解析器解析后,我得到了输入的 AST 表示。我已经为一种更简单的语言生成了代码,它只处理带有整数、运算符和变量的表达式。

然而,使用这种新语言,我有时会得到一个类型声明的子树,如下所示:

(IS TYPE (x) (INT))

其中说 x 是 INT 类型。

我的代码生成器中是否应该存在处理这些类型声明的案例?或者这只是为了让语义分析器进行类型检查,所以我应该假设已经检查了类型并忽略树的这一部分并简单地为 x 赋值?

4

2 回答 2

1

这两种情况都是可能的,您需要更多地描述您的语言,看看您是否真的需要将该功能添加到您的代码生成器中,或者因为不必要而跳过它,并避免在设计编程语言这个困难而有趣的主题上做额外的工作.

您是“代码生成器”一个程序,它以编程语言(可能是小语言)作为输入代码接收并以另一种编程语言(可能是小语言)输出代码吗?

这个工具通常被称为“翻译器”。

你是“代码生成器”一个程序,它接收一种编程语言作为输入并像编程语言一样输出汇编程序/字节码?

这个工具通常被称为“编译器”。

注意:“pile”是“stack”的同义词。

通常是 AST,存储操作或函数调用的类型。例如,在 c 中:

...
int a = 3;
int b = 5;
float c = (float)(a * b);
...

最后一行,生成与此类似的 AST,(其他行跳过 AST):

..................................................................
..................................................................
......................+--------------+............................
......................|    [root]    |............................
......................| (no type) =  |............................
......................+------+-------+............................
.............................|....................................
.................+-----------+------------+.......................
.................|........................|.......................
...........+-----+-----+....+-------------+-------------+.........
...........| (int) c   |....| (float) (cast operation)  |.........
...........+-----------+....+-------------+-------------+.........
..........................................|.......................
....................................+-----+-----+.................
....................................| (int) ()  |.................
....................................+-----+-----+.................  
..........................................|.......................
....................................+-----+-----+.................
....................................| (int) *   |.................
....................................+-----+-----+.................
..........................................|.......................
..............................+-----------+-----------+...........
..............................|.......................|...........
........................+-----+-----+...........+-----+-----+.....
........................| (int)  a  |...........| (float) b |.....
........................+-----------+...........+-----------+.....
..................................................................
..................................................................

请注意,“(float)”将其转换为运算符或函数,类似于您的问题。

祝你好运。

于 2011-11-18T18:27:40.237 回答
1

如果这是一个声明

(IS TYPE (x) (INT))

那么 x 应该放在内存中。在 C 和自动变量的情况下,局部自动变量在堆栈上分配。要分配所需的堆栈大小,您应该知道所有本地变量的大小和大小来自类型。

如果此变量存储在寄存器中,您应该选择所需大小的寄存器(考虑 x86 与:AL、AX、EAX、RAX - 具有不同大小的相同寄存器),如果您的目标有这样的。

此外,当 AST 中存在模棱两可的操作时,需要 type,它可以对不同的数据大小(例如 char、short、int 或 8 位、16 位、32 位等)进行操作。对于一些汇编程序,数据的大小被编码到指令本身;所以 codegen 应该记住变量的大小。

或者,如果操作类型未记录在 AST 中,则 ADD:

(ADD (x) (y))

可能意味着浮点数和整数加法(ADDFADD指令),因此在 codegen 中需要 x 和 y 类型来选择正确的变体。

于 2011-11-18T16:29:10.957 回答