ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

编译原理期末试题解答拆解:从DFA到LR分析表的手推攻略

编译原理期末试题解答拆解:从DFA到LR分析表的手推攻略 简介吉林大学编译原理历年期末试题解答合集覆盖2003年至2015年十余套真题并额外包含唐敖庆班试题及部分回忆版面向在校本科生、考研复习者以及希望巩固编译原理核心知识的自学者。压缩包为单份PDF文档大小4.56MB共1个文件版面清晰、按年份与班级分章节编排便于快速定位与打印练习。已有2700余人学习说明其在校内外的参考价值。内容除完整试题外还包含知识点总结及标注『Done』的试题答案涉及词法分析、语法分析、语义分析、中间代码生成、代码优化、目标代码生成、错误处理与运行时系统等编译全过程重点章节。通过逐套研读与对照解答可深入理解LL(1)、LR(1)解析、类型检查、三地址码生成等关键考点有效提升解题与应试能力。1. 为什么说“吉林大学编译原理期末试题解答”是值得花两天吃透的资料编译原理这门课到了期末画风和其它科目完全不一样填空还能靠突击背一到综合推导题正规式转 DFA、构造 LR 分析表、生成三地址码每一道都是环环相扣的“计算题”背教材根本顶不住。你可能也搜过“编译原理清华大学出版社第三版第二章答案”“编译原理第三版答案”但这些课后题补的是知识点不是考场上那张卷子。吉林大学这份期末试题解答的价值恰恰在于它是一份完整的、带推演过程的考情样本你能从一份解答反推出老师出题的偏好、步骤给分的方式以及自己最薄弱的环节到底在哪。这篇笔记不抄题目、不复述某年某卷只做一件事告诉你这类“期末试题解答”应该怎么拆、怎么背、怎么避坑。适合两类人——离考试还有两三周的复习党和想把编译原理实验与期末卷打通来练的动手党。按下面的路径走两天时间足够把它榨干。2. 先读懂这张卷子从试题解答倒推考什么2.1 一张期末卷的真实结构题型、题量与时间分配先别急着看答案把整份解答按题型标一遍类别你会发现绝大多数编译原理期末卷的骨架是相近的。常见分布大概是这样题型占比建议用时考察目标填空与选择20%30%20 分钟术语、阶段划分、基本定义简答与论述15%20%25 分钟概念对比、架构设计理由综合推导40%50%70 分钟正规式、DFA、LL/LR、中间代码实验与流程题10%15%20 分钟词法分析、语法分析实验的关键步骤我一般拿到一份解答会先翻到综合推导部分看篇幅。如果一份解答里推导题占了一半以上的页面说明这是真期末卷的解答如果全是文字填空那大概率是精简版知识点整理参考价值会打折扣。吉大这类偏理论推导的卷子后两类题型是绝对大头而它们的给分点全在步骤上——正规式化简到哪一步、DFA 状态表怎么填、LR 项目集闭包怎么求每个环节都有分。这也是为什么只看最终答案的复习方法在编译原理上完全不适用。时间分配上我建议把 70 分钟的大头压在综合推导简答题控制在 25 分钟内因为简答往往背过就有分推导题一旦卡住就是 10 分 20 分地丢。拿到试卷先扫一遍推导题问的是什么文法、什么语义动作心里有个优先级再做填空。2.2 解答里反复出现的三类高频题为什么它们占走大半分数把一份完整解答的目录标题列出来你会发现高频考点永远是那三块词法分析、语法分析、语法制导翻译与中间代码。这跟“编译原理实验”里要做的东西一一对应——平时用 Java 或 C 写的 lab 是什么期末大题就考什么。你搜“java编译原理”这类词时看到的问题本质上都是同一件事实验语言用什么卷子就围着什么考。词法分析考的是一整条链给一个正规式画出 NFA用子集构造法转 DFA再做最小化最后识别一段程序里的单词。常见变形是把a*换成(a|b)*abb或者加入数字与字母的混合规则核心考点其实没变过。语法分析考两条线一条是自顶向下的 LL(1)要算 FIRST、FOLLOW、SELECT 集合填预测分析表另一条是自底向上的 LR 家族从 LR(0) 项目集规范族到 SLR(1) 分析表的构造。这两条线是推导题的大户几乎每份卷子都会各出一道大题。语法制导翻译则把前面两条线接起来给定一个产生式和一个属性文法写出语法制导定义再生成三地址码或四元式。这里考的不是你会不会编程而是你能不能把语义动作挂在语法树的正确节点上。这三块合起来占到卷面一半以上。所以我复习时给自己的底线是词法、语法、语法制导各能完整手推一道题再谈其它。2.3 教材答案和期末解答不是一回事两套资料怎么搭配用很多人把“编译原理清华大学出版社第三版第二章答案”当复习主线结果看完第二章的课后题在考场上还是懵。原因很简单教材第二章讲词法分析课后题把正规式到 DFA 的每个步骤都练得清清楚楚可期末卷上同样的考点会换成“带优先级”“带最长匹配”的变体不会照原题出。教材答案是帮你建立知识结构的期末试题解答才是告诉你知识怎么变成分数的。我常用的搭配节奏是第一天过教材课后题找回基本操作的感觉第二天对着期末解答看步骤不看结果把每道推导题自己推一遍第三天只做错题把第一次推不出来的环节当成薄弱点集中练。第三天的重点不是再做一遍而是把流程默写出来——你在考场上没有查询函数所有动作都得靠肌肉记忆。顺带说一句搜资料时你能看到山科大、吉大这些词一起出现在结果里说明大家找的其实是同一副题型骨架。不同学校的卷子侧重点可能有差异但词法、语法、语法制导这条主线不会变非吉大读者把这份解答当题型模板用也完全成立。3. 按题型吃透解答三道大题的手推模板3.1 词法分析题从正规式到 DFA 最小化的标准步骤词法分析大题的完整答题顺序是固定的按顺序写就不会漏步骤。以经典正规式(a|b)*abb为例标准解法分五步先写 NFA再做子集构造填 DFA 状态转移表然后合并等价状态求最小 DFA最后用识别样例验证。每一步都有对应的采分点跳步会直接丢分。NFA 构造这一步关键在于把闭包和连接算子拆干净。(a|b)*abb对应的 NFA 里*号作用在a|b这个整体上所以要先画一个可返回的分支再顺序接上abb三个字符的转移。一个常见错误是眼里只有a*结果把*画成只作用于 a整个状态图就错了。画完 NFA 后数一下状态数并标好编号这是后续子集构造的输入。子集构造法是把 NFA 的状态集合当成 DFA 的单个状态。从初始状态开始对每个输入符号求move闭包生成新的状态集。这一步我建议用表格记录格式是“状态集编号、对 a 的转移、对 b 的转移、是否含终态”。以(a|b)*abb为例从{0}出发经过 a 到达{1,2}填第一行再把{1,2}当新状态继续展开直到没有新状态出现。表的每一行就是一个 DFA 状态。填完转移表之后做最小化。最小化的第一步是先把终态和非终态分成两个组再按“对每个输入符号是否落在同一组”来分裂。这里最容易出错的是分裂时只看当前分组不在一个组的必须立刻切开。比如终态组{5}只有一个成员不可能再分但非终态组里如果有的状态读 b 到终态、有的不到就得分出两个新组。每轮分完都要重新检查直到各组成员稳定。最终每个组保留一个代表状态重画转移表就是最小 DFA。步骤产物常见错误NFA 构造状态图闭包作用范围画错子集构造DFA 转移表漏掉 ε 闭包最小化分组列表终态非终态没先分开验证单词识别路径直接跳步最后用abb从头走一遍状态转移能到达终态就说明最小化没做反。这一步一到两分钟但能拦住一半以上的低级失误。3.2 语法分析题LL(1) 与 LR 分析表的“背多分”写法语法分析大题得分率低不是因为难而是因为步骤多、写得乱。对付 LL(1) 题我有一套固定的书写顺序消除左递归、提取左因子、求 FIRST、求 FOLLOW、填预测分析表。每一步都有明确产出写清楚就有分。以表达式文法E - E T | T为例第一步必须先把左递归消掉写成E - T EE - T E | ε。这里有个高频坑很多人消完左递归不检查E的 ε 产生式导致后面 FIRST(E) 里漏掉 ε整个预测分析表跟着错。消递归后立刻用“非终结符的每个候选项首位能推导出的终结符”把 FIRST 集列出来再按“当 FIRST 含 ε 时看后面跟着什么”去推 FOLLOW。FOLLOW 的推导必须从开始符号E的$开始逐条扫描产生式右部凡是在某符号后面出现的终结符都要并入它的 FOLLOW。预测分析表的填法一句话就能说清对每个产生式A - α把A行、α的 FIRST 里的每个终结符列填入这个产生式如果 FIRST(α) 含 ε再把 FOLLOW(A) 里的终结符也填进A行。这张表填完LL(1) 部分就稳了。LR 家族的大题核心动作是构造项目集规范族。先把文法写成增广文法E - E然后从E - ·E开始对每个项目集求闭包如果点号后面是非终结符就把以它开头的所有产生式加进去直到不再增加。闭包求完再做转移点号越过一个符号进入下一个项目集。每个项目集标一个编号转移形成一张状态图再把“归约项目”行按照 FOLLOW 集填进 SLR(1) 分析表。这里我强烈建议把每个项目集单独列一行写不要把项目集和状态转移混画在一起阅卷时老师按项目集编号给分编号清晰比画得漂亮更重要。参数上记住一个硬经验SLR(1) 分析表的归约动作看的是 FOLLOWLR(1) 看的是向前看符号。如果你分不清该用哪个卷子上就写“采用 SLR(1) 方法”并严格按 FOLLOW 填至少方向不会错。3.3 语法制导翻译与中间代码三地址码的答题话术语法制导翻译题看起来像编程题实际上是一道“按规则填空”题。给定一个给赋值语句a b * c d生成的三地址码我要求自己的答题格式严格分成两段先写语法制导定义产生式 语义规则再写三地址码序列。语义规则写对了即使中间代码有个别编号错误也能拿大半分。以算术表达式为例产生式写成S - id EE - E1 E2E - E1 * E2每条规则的语义动作就是E.code E1.code || E2.code || gen(...)。实际生成三地址码时我对每个新运算都用一个带编号的临时变量从t1开始每生成一条指令编号只自增一次。t1 b * c t2 t1 d a t2上面就是a b * c d的三地址码。注意第一行把乘法放前面这就是优先级在语法树里的体现临时变量的编号从 t1 顺次递增中途不能跳号。写完代码后我还习惯在旁边标一行“四元式”的写法——(op, arg1, arg2, result)——因为很多卷子要求四元式输出多写一行不影响得分反而能补上漏答的格式分。答题话术上面对只要“写出语法制导定义”的问法更稳的写法是把属性分两类综合属性写在右部末尾继承属性放在左部符号上。比如E的code是综合属性传递到上一层的语义规则里拼接而id的名字属性是继承属性在S - id E里传给E。这样归类能让阅卷老师一眼看出你分得清两种属性。4. 藏在解答背面的三张表考前的裸记清单4.1 运算优先级表与文法二义性判断看一份期末解答的背面你会发现考得最碎的其实是运算符优先级和二义性判断。老师不会直接问“乘除几级”而是给你一个文法让你判断是否二义再写出它的优先级结构。这里有一张我每次考前都要默写一遍的表优先级运算符结合性高( )括号内优先中* /左结合低 -左结合这张表和文法设计是对应的加减法放在文法的最外层产生式乘除法放内层括号放最底层。如果你看到一个文法的产生式是E - E T | TT - T * F | FF - (E) | id那么它的优先级已经被结构定死不需要额外规则。反过来说如果文法写成E - E E | E * E | id这个文法就是二义的——同一个a b * c能画出两棵不同的语法树。答题时判断二义性的标准写法就是“构造一个能有两棵不同语法树的句子”不要只写“这文法有二义”五个字必须把两棵树的推导序列写出来。这个动作能直接命中采分点。判断优先级还有一个很玄学的盲区if-else悬挂问题。文法S - if E then S | if E then S else S | other是经典二义文法因为if a then if b then c else d的else可以挂到内层或外层。期末解答里一旦出现这个文法答案几乎必然是“二义用最近匹配规则解决”。看到条件语句直接往悬挂上想多半不会错。4.2 FIRST、FOLLOW、SELECT 的边界条件这部分是推导题里翻车率最高的环节我一共总结出三个边界条件每个都对应一个具体丢分场景。第一个边界是空串 ε。求 FIRST 时如果产生式右部是 ε那么 ε 属于该非终结符的 FIRST。但 ε 一旦进入 FIRSTSELECT 集就会跟着变——SELECT(A - α) 在 FIRST(α) 含 ε 时要并入 FOLLOW(A)。很多人算完 FIRST 就停结果 SELECT 表少填一行归约整个 LL(1) 分析表作废。第二个边界是产生式右部的非终结符可能推出空串。比如A - B c而 B 的 FIRST 含 ε那么 FIRST(A) 不只要 B 的 FIRST还要把 c 也并入。手推时最容易漏掉这种“间接空串传染”我在推每个集合时都会在纸上画一条从右到左的传播链哪个符号能推 ε 就标一个箭头箭头指向的下一个终结符都要进集合。第三个边界是 FOLLOW 传播没有尽头。FOLLOW 是从开始符号的$开始逐层向外推的A - B C时FOLLOW(B) 要并入 FIRST(C)如果 FIRST(C) 含 ε还要并入 FOLLOW(A)。这道传播链不能只扫一遍要反复扫描直到集合不再变化。我的习惯是每轮传播在集合旁边画一个勾没有新增成员就停防止卷子上出现“漏一个符号”的无谓扣分。4.3 从解答反推老师的给分点得分关键词为什么同一道题有人做对了过程还是拿不满分因为阅卷是按关键词踩点的不是看你结果对不对。我从解答里总结了一份“高分答案里一定会出现的词”NFA 状态编号、DFA 状态表、项目集闭包、FOLLOW 集合传播、临时变量重命名、运行栈变化。这些词在解答的步骤段落里出现的密度能直接反映这份资料是否贴合采分点。判断一份解答质量的办法也很简单看中间步骤里有没有“状态”“集合”“编号”这类过程性标注。如果一份解答从头到尾只写“结果为……”没有任何中间推导那就是给书后答案的复读不是合格期末解答。拿它复习你能知道自己错了但永远不知道错在哪个动作上。5. 排查与避坑五个高频翻车点从现象到解决5.1 正规式闭包范围画错NFA 状态数翻倍现象把(a|b)*abb画成先画 a 再画 b状态图拆成两条独立路径识别结果永远多一步。原因眼里盯着a*的星号忽略了括号把整个a|b包住了。解决构造 NFA 前先用括号把正规式拆成树星号作用在哪个子树就圈哪个子树再动手画状态。画完数一下状态数如果多余“每个符号一个主状态”的直觉范围立即回查括号树。5.2 FIRST 集手推时把候选项和集合混在一起现象FIRST(A) 写出一长串终结符但分不清分别来自哪条产生式后续预测分析表填错整行。原因直接把所有产生式右部首字符塞进集合丢失了“哪个候选项贡献哪个终结符”的对应关系。解决用表格分列——每一行写一条产生式A - α单独算FIRST(α)再并入FIRST(A)。这样做即使最终集合错一两个阅卷也能看见你的推导路径保留步骤分。5.3 LR 项目集闭包漏掉增广文法的初始项目现象构造 LR(0) 项目集时状态 0 只有两个项目每次一归约就找不到接受状态。原因忘记先把文法写成增广文法漏了S - ·S。解决第一步永远先写增广文法再求闭包。闭包规则里点号后是非终结符就把该非终结符的所有产生式加入直到闭包稳定。写出闭包后再做转移状态 0 的初始项目写不齐后面全盘皆错。5.4 临时变量编号乱跳三地址码被倒扣分现象三地址码里 t2 还没定义就出现 t3或者相邻两条指令的编号从左到右不连续。原因生成代码时按“脑子里先算出结果再填编号”而不是“每写一条指令申请一个编号”。解决定死一个动作——每生成一条形如t a op b的指令临时变量编号只递增一次一条指令用完编号下一条才能用下一个号。写得慢一点但每一行都是有效答案。5.5 实验流程题直接空白试卷最后一道大题弃答现象试卷最后的“简述词法分析实验流程”“画出语法分析树构造过程”整块空白。原因平时跑实验是拿现成框架填空没记住流程里的关键步骤考场上只能写关键词拼凑。解决考前把实验报告压缩成一张流程小抄——词法分析按“正规式 → NFA → DFA → 识别器”四步写语法分析按“文法 → FIRST/FOLLOW → 分析表 → 匹配输入串”四步写符号表按“插入 → 查询 → 冲突处理”三步写。不用抄代码只要把每一步在干什么读出来默写三遍就能应急。6. 考前三天用一份解答给自己出一套镜像试卷考前最有效的动作不是把解答再看一遍而是把它变成一张镜像试卷。做法很简单把每道题的题干数字和符号换掉考点不变。比如解答里是(a|b)*abb你就改成(a|b)*ba解答里是E - E T | T你就改成E - E * T | T解答里生成a b * c d的三地址码你就改成x y * z w。每改一道立刻在纸上按解答里的步骤顺序推一遍推完直接对照解答的步骤结构看自己卡在哪一步。镜像维度原题可能长这样我改成的自测题词法分析(ab)*abb 转 DFA语法分析表达式文法 LL(1)去掉乘法层的表达式文法中间代码a b * ca b c * d这套方法的关键是“对照步骤不对照结果”。做错了不要紧看的是你第一步消左递归有没有乖乖写、项目集闭包有没有按顺序展开。只要步骤结构完整答案错误也能及格步骤跳步正确答案也拿不满分。一套镜像卷做完不超过两小时值回票价。卡壳的地方用记号笔标出来那就是考前最后一天该看的东西。顺手把这一页的得分关键词背一遍——NFA 状态编号、项目集闭包、FOLLOW 传播、临时变量编号这四个词在卷子上出现的频率极高。我个人的习惯是拿到任何一份期末解答第一件事永远是翻到推导题步骤里数状态编号和集合标注数得出来才值得看下去。这个习惯帮我避开了不少“只有结论、没有过程”的注水材料。希望这个拆解思路也能帮你在考前几天把一份解答用出真题的效果。本文还有配套的精品资源点击获取
返回列表