Contents

2026BUAA编译原理期中考试题目回顾

题目

以下内容为回忆版
新增文法如下:

// 新增MatchExp
PrimaryExp -> '(' Exp ')' | LVal | Number | MatchExp   
MatchExp -> 'match' '(' Cond ')' '{' { MatchArm } '}'
MatchArm -> 'when' Number '->' Exp ';' | 'otherwise' '->' Exp ';' // 保证otherwise只有一个

// 新增Unless语句
Stmt -> ...| 'unless' '(' Cond ')' Stmt |...

新增Token如下:

Token Content
MATCHTK match
WHENTK when
OTHERWISETK otherwise
UNLESSTK unless
ARROW ->

一个可能的题解

以下内容基于本人的CPP实现,不代表通用情况

  1. 词法分析阶段,在Token列表中注册新增Token
  2. 语法分析阶段
    • 注册新增类MatchExp和MatchArm,新增解析函数parseMatchExp()和parseMatchArm(),在isExpStart()中新增MATCHTK,在parsePrimaryExp()中新增判断并调用parseMatchExp(),随后递归下降完成parseMatchExp()和parseMatchArm()
    • 扩展解析函数parseStmt(),在isStmtStart()中新增UNLESSTK,在parseStmt()中新增判断并递归下降完成对unless语句的解析。

考场上写出来的Bug

  1. 在parsePrimaryExp()中判断类型时,只写了if(type == MatchExp),而没有在前面根据peek()的类型对type进行赋值(天知道我debug了多久……因为我的type默认是Number,我真的很奇怪他到底怎么跳转到parseNumber然后抛出异常没有Number的,反正终于在和clion没有许可证每过半小时就自动退出软件和为了跳过step into进入c++头文件而点击step over结果点过头直接跳到异常的斗争中定位到了bug啊啊啊啊啊)
  2. ‘->‘识别成’-’:我对两个字符的运算符的判断方法是在宏定义时就将他们写在前面,后面展开成数组时也在前面,匹配时就优先匹配了两个字符的运算符,但是我忘记了这个事情……这个bug还是比较好改的。
  3. 没有在isExpStart()中新增MATCHTK:这个在题干中有提示,但是貌似没有看到而且忘记改的不止我一个……而且令我百思不得其解的是我应该改了isStmtStart(),为什么能想起来一个而想不起来另一个,还是说这个我也没想起来但是侥幸测试点没有这个(不是没有可能,因为这个函数没有改只会影响switch case语句中case:和default:后面是一个unless语句),还是说我并没有通过全部的测试点而我以为我通过了……算了算了,洗洗睡吧。