2025 北航编译原理期中期末题目回顾
本文章主要记录了2025秋季学期北航编译原理课程实验上机期中期末的回忆题目~
题目均由本人回忆记录,可能与原题稍有偏差,但大体思路一致
期中题目
1. 新增 elif 文法:
具体新增文法如下:
1 | Stmt -> 'if' '(' Cond ')'Stmt |
解题思路:
- 词法分析阶段识别 elif 为一个保留关键字,建立 ELIFTK。
- 语法分析阶段,对于 IfStmt 语法结构,新增一个 list 用来装 elif,里面每一个单元涵盖 Cond 和 Stmt。在 toString 的时候,先对 if 语句进行 toString,然后看有没有 elif,如果有的话就仿照 if 的 toString 操作去写就可以。最后对 else 进行处理。
2. 新增 functionDef 文法:
具体新增文法如下:
1 | FuncDef → FuncType Ident '(' [FuncFParams] ')' Block |
解题思路:
词法分析不用改
语法分析阶段,首先新增一个新的语法节点,然后将 FuncDef 设置为接口,原来的 FuncDef 和新增的都实现这个接口。两个 FuncDef 的不同之处就是一个是 Block 一个是 ;
在识别有没有 FuncFParams 的时候,在看后面 Token 是不是
{的时候,还要看是不是;,如果是的话说明没有 FuncFParams 并且缺少右小括号。然后在检查完右小括号后,根据下一个 Token 是{还是;决定返回的语法节点类型。
期末题目
1. 新增 cin 文法:
具体新增文法规则如下:
1 | 语句 Stmt → 'cin' '>>' LVal; // 新增 cin 文法,错误类型为i,h |
其功能等价于:LVal = getint() ,即读入一个 int 类型的数,然后存储在 LVal 中。
错误类型为 i:缺少分号,h:LVal 为 const 不可赋值。
解题思路:
- 在词法分析阶段解析 cin 为 CINTK,解析 >> 为 SHR。
- 在语法分析阶段,为 cin 文法新增 AST 节点类型 CinStmt,其内部只需存储一个 LVal 即可。在 parseStmt 的时候,如果当前 token 是 CINTK,则调用 parseCinStmt 方法。parseCinStmt 方法:先跳过 cin 和 >> ,然后调用 parseLVal 返回 LVal 用于构建 CinStmt。最后检查有没有分号,没有报 i 错误。
- 在语义分析阶段,在 checkStmt 中,如果是 CinStmt 则调用 checkCinStmt。该方法内部先 getLVal 拿到左值,然后去符号表里拿到 varSymbol,如果 varSymbol.isConst 是真,则报 h 错误。然后再调用 checkLVal 方法去检查 LVal(若 LVal 未定义则在 checkLVal 中报错,不在 checkCinStmt 里报错)。
- 在中间代码生成阶段,如果是 CinStmt,则调用 buildCinStmt 方法。该方法首先 new CallInst 去调用 getint 库函数,然后得到其 Value,然后 getLVal 得到 LVal,用 getLValPtr 得到 LVal 的指针,最后 new StoreInst 将 getint Value 存储到 LVal 指针处即可。
- 后端代码生成不用改。
2. 新增 -> 文法:
具体新增文法规则如下:
1 | 乘除模表达式 MulExp → UnaryExp | MulExp ('*' | '/' | '%' | '->') UnaryExp // 新增 '->' 运算 |
解题思路:
- 在词法分析阶段解析 -> 为 LEFTTORIGHTTK。
- 在语法分析阶段,在解析 MulExp 的时候,如果遇到 (‘*’ | ‘/‘ | ‘%’ | ‘->’) 运算符,就添加语法成分,最后正常返回 MulExp 语法节点。这里只要添加一个 else if 特判是不是 LEFTTOTIGHTTK 就可以。
- 在语义分析阶段,不用改。
- 在中间代码生成阶段,如果是 LEFTTORIGHTTK,则调用 buildLRTK 方法。该方法有两种实现方式:
- 第一种比较简单,利用等差数列求和公式,只需要计算出 ((a + b) * (b - a + 1)) / 2 即可。计算方法就根据计算顺序生成对应的计算语句,然后返回最后的计算结果 Token 即可。
- 第二种方法是利用循环来计算。可以写一个 for 循环,循环开始为 a,终止为 b,循环体内的语句就是累加当前值,最后返回累加值即可。方法为创建三个 BasicBlock,第一个为条件块,第二个为语句块,第三个为结束块。首先创建临时变量 i,并赋初值为 a,然后跳转到条件块,生成条件为 i <= b,若满足条件则跳转到语句块,不满足则跳转到结束块。然后跳转到语句块,累加 i 的值,然后无条件跳转到条件块。最后将当前块移至结束块即可。
- 后端代码生成不用改。
3. 代码优化
直接提交课下代码优化的版本进行评测,有两个测试点。按照测试点的 cycle 数进行排名给分。
一般来说课下的代码优化能过,那么课上这两个点就能过。
然后还需要提交代码优化前后中间代码和目标代码的 txt 版本,别忘了交
4. 问答题
针对给出的示例代码提出很多问题,要结合代码进行文字解释。重点都是 mips 代码生成的问题。
有印象的问题是:
- 在 mips 函数传参的时候,前四个参数要通过 $a0 - $a3 传递,第五个参数是如何传递的?
- 还考了一个跟函数有关的,具体忘了
总结
同学们好好复习,期中比较简单,期末要上点小强度。
一般来说,期末只需要改 llvm 中端就行了,如果 llvm 不新增指令,那么 mips 完全不用改。为了预防 llvm 有新增指令,需要提前准备一些方案,我能想到的 llvm 新增指令就是新增一些运算指令类型,比如新增异或、与运算、或运算之类的。这些就仿照加减法正常做就可以。
可以打印纸质资料带进去,建议先把预测到的问题问一下 AI ,让 AI 生成详细的更改指导,最后打印出来带进考场看。
有问题可加微信:zhaojiyuan0721


