Skip to content

Commit efcb42e

Browse files
committed
for 2026 spring: rename 2025 -> 2026, changed schedule
1 parent 0a8803c commit efcb42e

File tree

8 files changed

+32
-32
lines changed

8 files changed

+32
-32
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ int qsort(int a[], int l, int r) {
2222
}
2323
```
2424
25-
2025 年秋季学期基本沿用了往年《编译原理》课程的语法规范。为了贴合课程教学内容,提升训练效果,课程组设计了比较完善的编译器框架,包括词法分析、语法分析、语义分析、中间代码生成、数据流分析、寄存器分配、目标平台汇编代码生成等步骤。每个 step 同学们都会面对一个完整的编译器流程,但不必担心,实验开始的几个 step 涉及的编译器框架知识都比较初级,随着课程实验的深入,将会循序渐进地引入各个编译器功能模块,并通过文档对相关技术进行分析介绍,便于同学们实现相关编译功能模块。
25+
2026 年春季学期基本沿用了往年《编译原理》课程的语法规范。为了贴合课程教学内容,提升训练效果,课程组设计了比较完善的编译器框架,包括词法分析、语法分析、语义分析、中间代码生成、数据流分析、寄存器分配、目标平台汇编代码生成等步骤。每个 step 同学们都会面对一个完整的编译器流程,但不必担心,实验开始的几个 step 涉及的编译器框架知识都比较初级,随着课程实验的深入,将会循序渐进地引入各个编译器功能模块,并通过文档对相关技术进行分析介绍,便于同学们实现相关编译功能模块。
2626
2727
## 实验起点和基本要求
2828
@@ -83,7 +83,7 @@ stage6 为进阶关卡,如果你依然学有余力,你可以在这里实现
8383
`prepare.sh` 是在测试前会运行的准备脚本,包括安装所需的依赖(python),如果你想添加新的依赖或者修改编译流程,请修改此文件。
8484
在 CI 中会检查是否通过所有测例及是否有提交报告,只有通过所有测例且提交报告,才会被视为通过 CI。
8585
86-
我们只接受 pdf 格式的实验报告。你需要将报告放在仓库的 `./reports/<branch-name>.pdf` 路径,比如 stage 1 的实验报告需要放在 `stage-1` 这个 branch 下的 `./reports/stage-1.pdf`。
86+
我们只接受 pdf 格式的实验报告。你需要将报告放在仓库的 `./reports/<branch-name>.pdf` 路径,比如 stage 1 的实验报告需要放在 `stage-1` 这个 branch 下的 `./reports/stage-1.pdf`,parser stage 的实验报告放在 `parser-stage` 分支下的 `./reports/parser-stage.pdf`
8787
实验报告中需要包括:
8888
* 你的学号姓名
8989
* 简要叙述,为了完成这个 stage 你做了哪些工作(即你的实验内容)

docs/misc/schedule.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,26 @@
33
所有截止时间均为所标日期的23:59:59(UTC+8),即第二天0点之前,如有特殊情况将会在网络学堂通知。
44

55
## 必做部分:
6-
- 第三周周日(10.5):Stage 0 截止 熟悉框架和基础知识 (占比:0%)
6+
- 第三周周日(3.15):Stage 0 截止 熟悉框架和基础知识 (占比:0%)
77
- stage 0 不需要你编写任何代码,stage 0的思考题请与stage 1一起提交。
88

9-
- 第四周周日(10.12):Stage 1 截止 常量表达式(占比:7%)
9+
- 第四周周日(3.22):Stage 1 截止 常量表达式(占比:7%)
1010

11-
- 第六周周日(10.26):Stage 2 截止 变量和作用域(占比:7%)
11+
- 第六周周日(4.5):Stage 2 截止 变量和作用域(占比:7%)
1212

13-
- 第八周周日(11.9):Parser Stage 截止 手动语法分析器(占比:7%)
13+
- 第八周周日(4.19):Parser Stage 截止 手动语法分析器(占比:7%)
1414

15-
- 第十周周日(11.23):Stage 3 截止 控制语句(占比:7%)
15+
- 第十一周周四(5.7):Stage 3 截止 控制语句(占比:7%)
1616

17-
- 第十四周周日(12.21):Stage 4 截止 函数(占比:7%)
18-
- 函数部分由于难度较大,给大家预留了四周时间,请大家不要等到最后一周再开始。
17+
- 第十四周周六(5.30):Stage 4 截止 函数(占比:7%)
18+
- 函数部分由于难度较大,给大家预留了三周多时间,请大家不要等到最后一周再开始。
1919

2020
## 选做部分:
2121
选做部分难度较大,且时间较紧,同学可能需要提前一些开始才能保证完成。
2222

23-
- 第十五周周日(12.28):Stage 5 截止 全局变量和数组(占比:7%)
23+
- 第十五周周日(6.7):Stage 5 截止 全局变量和数组(占比:7%)
2424

25-
- 第十六周周日(1.4):Stage 6 截止 寄存器分配与代码优化(占比:8%)
25+
- 第十六周周日(6.14):Stage 6 截止 寄存器分配与代码优化(占比:8%)
2626

2727

2828
## 补交政策

docs/step0/intro.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# 实验环境简介
22

3-
2025 年秋季学期,助教给大家提供了服务器。同学们可以选择使用我们已经配置好的机器,节省一定的时间花费。
3+
2026 年春季学期,助教给大家提供了服务器。同学们可以选择使用我们已经配置好的机器,节省一定的时间花费。
44

55
服务器环境如下:
66
- Ubuntu 23.04
@@ -15,8 +15,8 @@
1515
1. 如何使用 ssh 登陆服务器?
1616
```bash
1717
ssh username@ip -p port
18-
# 假如你的账号为 2023000001,服务器 ip 地址为 192.168.1.1,端口为 223,则命令为:
19-
ssh 2023000001@192.168.1.1 -p 223
18+
# 假如你的账号为 2024000001,服务器 ip 地址为 192.168.1.1,端口为 223,则命令为:
19+
ssh 2024000001@192.168.1.1 -p 223
2020
```
2121
2. 建议配置 ssh 免密登录,方便大家使用服务器,然后在服务器上运行。你可以参考[这里](https://blog.csdn.net/qq_51447496/article/details/132089964)。
2222

docs/step0/testing.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@
66
77
1. 按照本文档的前几节([RISCV 环境配置](./riscv_env.md)[实验框架环境配置](./env.md))配置好实验环境。
88

9-
2. 助教已经为每位同学在 git.tsinghua.edu.cn 创建了一个仓库,其中 minidecaf 的[测例仓库](https://git.tsinghua.edu.cn/compiler/2025/minidecaf-tests)为其中的一个子模块,你可以通过以下指令来在克隆主仓库的同时克隆子模块 `git clone --recursive <repository>`
9+
2. 助教已经为每位同学在 git.tsinghua.edu.cn 创建了一个仓库,其中 minidecaf 的[测例仓库](https://git.tsinghua.edu.cn/compiler/2026/minidecaf-tests)为其中的一个子模块,你可以通过以下指令来在克隆主仓库的同时克隆子模块 `git clone --recursive <repository>`
1010
由于测例仓库会有所更新,在克隆之后你需要在主仓库目录下使用 `git submodule update --remote --merge` 来手动更新。
1111

1212
> 注意:由于子模块使用 ssh 链接,你需要将你的 ssh 公钥添加到你的 git.tsinghua 账号上,才能将其克隆下来。
1313
14-
3. 按照[测例](https://git.tsinghua.edu.cn/compiler/2025/minidecaf-tests)的 README 运行测试 step1,实验框架给出的初始代码可以通过 step1 的所有测例。
14+
3. 按照[测例](https://git.tsinghua.edu.cn/compiler/2026/minidecaf-tests)的 README 运行测试 step1,实验框架给出的初始代码可以通过 step1 的所有测例。
1515

1616
测试运行的 **输出结果** 大致如下。
1717

docs/step1/example.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
```C
88
int main() {
9-
return 2025;
9+
return 2026;
1010
}
1111
```
1212

@@ -30,7 +30,7 @@ MiniDecaf 源文件 --------> 字节流 -----------> AST -----------------------
3030

3131
当程序读入程序的字符流之后,它首先会被 lexer 处理,并被转化为如下形式的一个 Token 流:
3232

33-
`Int Identifier("main") LParen RParen LBrace Return Integer(2025) Semi RBrace`
33+
`Int Identifier("main") LParen RParen LBrace Return Integer(2026) Semi RBrace`
3434

3535
`frontend/lexer/lex.py`文件中你可以看到每个 Token 是如何定义的,每个`token`都会以`t_`开头。如`t_Semi = ";"`代表分号被解析以后会转化为 `Semi` 这个Token。而对于一些复杂的 Token,我们需要在`lexer`中定义一个正则表达式来匹配它,lex中通过定义一个函数来实现正则匹配。以匹配整数为例,函数的第一行`r"[0-9]+" `代表匹配用到的正则表达式,而函数的参数`t`则是被匹配得到的字符串,我们通过python中的类型转换将其变为一个整数,你可以在文件中看到以下代码:
3636

@@ -50,7 +50,7 @@ Program
5050
|- (ident) Identifier("main")
5151
|- (body) Block
5252
|- (children[0]) Return
53-
|- (expr) IntLiteral(2025)
53+
|- (expr) IntLiteral(2026)
5454
```
5555

5656
得到的 AST 也就是 `main.py``step_parse` 这一函数里 `parser.parse(...)` 的输出。
@@ -91,7 +91,7 @@ def p_function_def(p):
9191

9292
```asm
9393
main: # main 函数入口标签
94-
_T0 = 2025 # 为立即数 2025 分配一个临时变量
94+
_T0 = 2026 # 为立即数 2026 分配一个临时变量
9595
return _T0 # 返回
9696
```
9797

@@ -107,7 +107,7 @@ main: # main 函数入口标签
107107

108108
1. 如何将一个立即数装载到指定寄存器中?
109109

110-
RISC-V 提供了 li <reg> <imm32> 指令来支持加载一个 32 位立即数到指定寄存器中,其中 <reg> 表示寄存器名,<imm32> 表示立即数值,如:`li t0, 2025`,就是将立即数 2025 加载到寄存器 t0 中。
110+
RISC-V 提供了 li <reg> <imm32> 指令来支持加载一个 32 位立即数到指定寄存器中,其中 <reg> 表示寄存器名,<imm32> 表示立即数值,如:`li t0, 2026`,就是将立即数 2026 加载到寄存器 t0 中。
111111

112112
2. 如何设置返回值?
113113

@@ -121,7 +121,7 @@ main: # main 函数入口标签
121121
.text # 代码段
122122
.global main # 声明全局符号 main
123123
main: # 主函数入口符号
124-
li t0, 2025 # 加载立即数 2025 到 t0 寄存器中
124+
li t0, 2026 # 加载立即数 2026 到 t0 寄存器中
125125
mv a0, t0 # 将返回值放到 a0 寄存器中
126126
ret # 返回
127127
```

docs/step10/example.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
本实验指导使用的例子为:
44

55
```C
6-
int x = 2025;
6+
int x = 2026;
77
int main() { return x; }
88
```
99
@@ -37,7 +37,7 @@ main:
3737
3838
> 需要说明的是,你也可以把两条指令合并为一条指令,直接加载全局变量的值,但分为两条指令的方式可扩展性更好些。
3939
40-
请注意,翻译所得的 TAC 代码中没有为全局变量赋予初始值(2025)。可以将变量的初始值存放在变量符号对应的符号表里,在后端代码生成时**通过读取符号表得到初值**。此处给出的只是一种参考实现,大家也可以将全局变量的定义显式翻译为 TAC 代码,这样可以使中端与后端完全解耦。
40+
请注意,翻译所得的 TAC 代码中没有为全局变量赋予初始值(2026)。可以将变量的初始值存放在变量符号对应的符号表里,在后端代码生成时**通过读取符号表得到初值**。此处给出的只是一种参考实现,大家也可以将全局变量的定义显式翻译为 TAC 代码,这样可以使中端与后端完全解耦。
4141
4242
## 目标代码生成
4343
@@ -65,7 +65,7 @@ Step10 中目标代码生成的主要任务有:翻译中间代码,将全局
6565
.data
6666
.globl x
6767
x:
68-
.word 2025
68+
.word 2026
6969
```
7070

7171
上例中,.data 表示输出到 data 数据段;.globl x 声明 x 为全局符号;.word 后是一个 4 字节整数,是 x 符号对应的初始值。

docs/step2/example.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ neg t1, t0
5757

5858
> 关于实现细节,对应的代码位置在下面给出,代码中提供注释供大家学习。
5959
60-
相比于step 0, 我们实现了把返回值从一个整数(如:`2025``1`)变成单目表达式(如:`-1`),则在这一步中你可能需要进行以下操作(实际上这些实现已经在框架里提供):
60+
相比于step 0, 我们实现了把返回值从一个整数(如:`2026``1`)变成单目表达式(如:`-1`),则在这一步中你可能需要进行以下操作(实际上这些实现已经在框架里提供):
6161

6262
首先,我们应该把 `-` 看作一个符号,而不应该将 `-1` 看作一个整体,因为我们还可能遇到 `-x` 这种求一个变量的相反数的操作,如果将其分开处理则会增加我们的工作量。因此我们需要在词法分析中加入对 `-` 的处理。
6363

docs/step5/example.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
```C
66
int main() {
7-
int x = 2025;
7+
int x = 2026;
88
return x;
99
}
1010
```
@@ -31,12 +31,12 @@ int main() {
3131

3232
```C
3333
int main() {
34-
int x = 2025;
34+
int x = 2026;
3535
return x + y;
3636
}
3737
```
3838

39-
那么在扫描到加法操作的 AST 结点时,会依次检查该操作的两个操作数 x 和 y。这两个操作数均为变量标识符,因此我们需要到符号表中搜索 x 和 y 对应的符号。符号 x 可以在符号表中找到(我们在扫描 `int x = 2025;` 这条语句后已经为其定义),而 y 无法找到,因此编译器需要在扫描到 y 对应的结点时报错。
39+
那么在扫描到加法操作的 AST 结点时,会依次检查该操作的两个操作数 x 和 y。这两个操作数均为变量标识符,因此我们需要到符号表中搜索 x 和 y 对应的符号。符号 x 可以在符号表中找到(我们在扫描 `int x = 2026;` 这条语句后已经为其定义),而 y 无法找到,因此编译器需要在扫描到 y 对应的结点时报错。
4040

4141
符号表总是和作用域相关的。例如,在 C 语言中,我们可以在全局作用域中定义名为 "a" 的全局变量,同时在 main 函数中定义名为 "a" 的局部变量,这并不产生冲突。不过由于本节还无需支持全局变量和块语句,同学们不用考虑这一点,只考虑 main 函数作用域对应的单张符号表即可。
4242

@@ -54,7 +54,7 @@ int main() {
5454

5555
```assembly
5656
main:
57-
_T1 = 2025
57+
_T1 = 2026
5858
_T0 = _T1
5959
return _T0
6060
```
@@ -69,7 +69,7 @@ main:
6969

7070
从中间代码可以看出,尽管我们引入了变量的概念,但是在比较低级的中间代码上,数据的存储和传递仍然是基于虚拟寄存器进行的。由于 MiniDecaf 语言中的基本类型只有 int 型,而 TAC 里的临时变量也是 32 位整数,因此,我们可以把 MiniDecaf 局部变量和 TAC 临时变量对应起来。
7171

72-
在扫描到 `int x = 2025;` 这条语句时,中间代码先把立即数 2025 加载到临时变量 _T1 中,然后再把 _T1 的值赋给临时变量 _T0,此时 _T0 已经成为了变量 x 的“替身”。每次需要用到变量 x 的值时,我们都会去访问 _T0。例如,测例中直接用返回 _T0 代替了返回变量 x 的值。因此,为了在后续使用变量 x 时能快速找到 _T0 这个临时变量,在符号表中存储 x 这个符号时,应当为该符号设置一个成员,存储 x 对应的临时变量。每当在 AST 上扫描到一个变量标识符结点时,我们都直接调用该变量对应的临时变量作为结点的返回值。
72+
在扫描到 `int x = 2026;` 这条语句时,中间代码先把立即数 2026 加载到临时变量 _T1 中,然后再把 _T1 的值赋给临时变量 _T0,此时 _T0 已经成为了变量 x 的“替身”。每次需要用到变量 x 的值时,我们都会去访问 _T0。例如,测例中直接用返回 _T0 代替了返回变量 x 的值。因此,为了在后续使用变量 x 时能快速找到 _T0 这个临时变量,在符号表中存储 x 这个符号时,应当为该符号设置一个成员,存储 x 对应的临时变量。每当在 AST 上扫描到一个变量标识符结点时,我们都直接调用该变量对应的临时变量作为结点的返回值。
7373

7474
请注意 `frontend/symbol/varsymbol.py` 中,变量符号的定义里有该变量对应的 TAC 临时变量成员。
7575

@@ -81,7 +81,7 @@ main:
8181
.text
8282
.global main
8383
main:
84-
li t1, 2025
84+
li t1, 2026
8585
mv t0, t1 # 我们使用 mv 指令来翻译中间表示里的 ASSIGN 指令
8686
mv a0, t0
8787
ret

0 commit comments

Comments
 (0)