ARTICLE DETAIL

资讯详情

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

编译原理课设实战:SLR(1)小型编译程序从源码到四元式生成

编译原理课设实战:SLR(1)小型编译程序从源码到四元式生成 简介这份资源面向学习编译原理、需要完成课程设计的高校学生围绕SLR(1)分析法实现一个小型编译程序解决从高级语言源程序到四元式程序翻译的实践问题。资源包共14个文件约22KB包含C语言源码、测试用例数据文件、汇编输出文件及说明文档等其中C源码为核心实现dat文件为待编译的源程序样例asm文件展示目标代码结果txt文档记录表达式分析过程与使用说明便于对照理解各阶段输出。目前已有2775人学习下载适合作为编译原理课设的起步参考。读者可从中获得SLR(1)分析表的构建思路、词法与语法分析流程、四元式生成与表达式分析过程的完整实现并借助测试样例验证程序正确性在此基础上自行改进优化加深对编译各阶段衔接的理解。1. 从一份课设压缩包说起SLR(1) 小型编译程序到底能跑出什么如果你正在上编译原理这门课大概率会遇到一个绕不开的课设实现一个小型编译程序。输入一段高级语言源程序输出四元式进阶一点还要再翻译成汇编。听起来像是一门课的全部精华被塞进了一个压缩包里实际上也确实如此。这份「实现一个小型编译程序.zip」就是一套完整的课设交付物里面包含了测试文件pas.dat、pas1.dat、pas2.dat、主程序 project_design.c、四元式与汇编程序的输出结果、表达式分析过程的中间文件testout.txt 系列以及一份 readme.txt。开发环境是 C 语言加 VS2019参考书是胡元义那本《编译原理教程第四版》。它解决的核心问题是把词法分析、语法分析、语义分析、中间代码生成这条链路真正串起来跑通而不是停留在卷子上手推 SLR(1) 分析表。适合谁正在做编译原理课设、想找一个能直接编译运行、又能对照修改的参考实现的人。如果你已经能默写 FIRST/FOLLOW 集但一到写代码就不知道从哪下手这份资源的价值就体现出来了。2. 拆开压缩包文件结构与 SLR(1) 分析表的落地形态2.1 每个文件在编译流水线里的位置拿到压缩包先别急着双击 project_design.c先把文件按角色分清楚。这份资源里的文件大致可以分成四类文件角色说明project_design.c主程序词法、语法、语义、四元式生成的主逻辑pas.dat / pas1.dat / pas2.dat输入源程序待编译的高级语言测试用例testout.txt / testout1.txt / testout2.txt输出结果四元式、汇编、表达式分析过程readme.txt说明使用方式和注意事项主程序是单文件结构这意味着你不需要配 CMake、不需要装额外依赖VS2019 新建一个空项目把 .c 拖进去就能编译。常见做法是先跑 pas.dat看 testout.txt 的输出是否和压缩包里自带的结果一致确认环境没问题再换 pas1.dat、pas2.dat 观察不同输入下的行为差异。2.2 SLR(1) 分析表在代码里长什么样SLR(1) 的核心是 ACTION 表和 GOTO 表。在这类课设实现里分析表通常不会真的让你手写一张几百行的二维数组而是用产生式集合加 FIRST/FOLLOW 集在运行时构造或者直接硬编码成结构体数组。我一般会先找到代码里定义产生式的地方通常长这样/* 产生式右部符号串-1 表示空串 */ int productions[][MAX_RHS] { {1, -1}, /* 0: S - E */ {2, 3, 4}, /* 1: E - E T */ {2}, /* 2: E - T */ {5, 6, 7}, /* 3: T - T * F */ {5}, /* 4: T - F */ {8, 2, 9}, /* 5: F - ( E ) */ {10} /* 6: F - id */ };这段数组就是语法规则的数字化表达。每个数字对应一个文法符号-1 代表 ε。逻辑说明SLR(1) 在归约时不仅看栈顶状态还要看当前输入符号是否在 FOLLOW 集里所以代码里一定有一个 follow 数组和 action 表的联合判断。参数说明MAX_RHS 是产生式右部最大长度实际项目里一般取 8 到 10 就够productions 的行数就是产生式总数改文法的时候这里必须同步改否则分析表对不上。2.3 从源程序到四元式的执行链路跑通一次完整流程建议按这个顺序操作用 VS2019 打开 project_design.c确认字符集设置为「使用多字节字符集」否则中文注释可能报错。把 pas.dat 放在工程目录下或者修改代码里的文件路径为绝对路径。编译运行观察控制台输出和 testout.txt 是否一致。如果一致把输入换成 pas1.dat重点看表达式分析过程有没有异常。最后看汇编输出部分选做内容如果没实现至少确认四元式是正确的。这里有个细节四元式的格式通常是 (op, arg1, arg2, result)。比如a b c * d会生成多条四元式乘号先算加号后算。你可以在 testout.txt 里逐行对照确认运算优先级和结合性有没有翻车。3. 把 project_design.c 跑起来编译、输入与输出对照3.1 VS2019 下的编译配置与常见报错VS2019 对 C 语言的老式写法比较宽容但有几个地方容易卡住。第一scanf会报 C4996 错误解决办法是在文件最上面加#define _CRT_SECURE_NO_WARNINGS。第二如果代码里用了gets同样需要禁用安全检查。第三文件路径如果写的是相对路径工作目录默认是工程目录而不是 .c 文件所在目录找不到 pas.dat 的时候先检查这一点。#define _CRT_SECURE_NO_WARNINGS #include stdio.h #include stdlib.h #include string.h /* 打开输入文件失败时给出明确提示 */ FILE* openSource(const char* filename) { FILE* fp fopen(filename, r); if (fp NULL) { printf(无法打开文件: %s请检查工作目录\n, filename); exit(1); } return fp; }逻辑说明这段代码解决的是「文件打不开但不知道原因」的问题。参数说明filename 传 pas.dat 时文件必须和可执行文件在同一目录或者在项目属性里把工作目录改成$(ProjectDir)。我一般会在打开文件后立刻打印一行确认信息避免后面分析到一半才发现读的是空文件。3.2 词法分析输出的 token 序列怎么验证词法分析是整条链路的第一关。常见做法是每读一个 token 就打印类型, 值然后和预期对照。比如begin x : 9 end应该输出保留字 begin、标识符 x、赋值号、数字 9、保留字 end。如果你发现标识符和保留字混在一起通常是关键字表没查全或者大小写处理有问题。/* 关键字表顺序查找即可课设规模不需要哈希 */ const char* keywords[] {begin, end, if, then, else, while, do, NULL}; int isKeyword(const char* s) { for (int i 0; keywords[i] ! NULL; i) { if (strcmp(s, keywords[i]) 0) return 1; } return 0; }逻辑说明先读一个单词再查关键字表命中就返回关键字类型否则按标识符处理。参数说明keywords 数组必须以 NULL 结尾循环才能正确终止。这个函数在每次识别出字母开头的串时调用调用前要先把串转成小写或者统一大小写策略否则Begin会被当成标识符。3.3 四元式生成与 testout.txt 的逐行对照四元式生成是必做部分的核心。以x : a b * c为例正确的四元式顺序应该是先算b * c再算a 临时变量最后赋值给 x。你可以在 testout.txt 里看到类似这样的序列(*, b, c, t1) (, a, t1, t2) (:, t2, -, x)对照的时候重点看三件事临时变量编号是否连续、运算顺序是否符合优先级、赋值四元式的 arg2 是否为空。如果顺序反了说明语法分析里的归约时机不对SLR(1) 的 ACTION 表可能在某个状态上选错了移进或归约动作。这时候回到分析表检查该状态下遇到运算符时是移进还是归约通常能定位到问题。4. 避坑与排查SLR(1) 课设里最容易翻车的五个地方4.1 现象编译通过但运行直接崩溃原因数组越界。SLR(1) 的状态栈和符号栈通常用固定大小数组源程序稍微长一点就溢出。解决把栈大小从 100 调到 1000或者在 push 之前加边界判断溢出时打印当前状态和符号再退出方便定位。4.2 现象四元式里出现大量重复临时变量原因表达式分析时没有正确释放临时变量编号或者每次归约都新建一个临时变量却没有复用。解决检查临时变量计数器是在哪里递增的通常应该在生成四元式的那一刻递增而不是在语法分析开始时统一分配。4.3 现象testout.txt 和压缩包自带结果不一致原因输入文件的换行符或空格差异导致词法分析多读或少读字符。解决用二进制模式打开文件或者在读字符时统一过滤\r。另外确认 pas.dat 没有被编辑器自动修改过编码。4.4 现象SLR(1) 分析表冲突移进归约报错原因文法不是 SLR(1) 文法或者 FIRST/FOLLOW 集计算有误。解决先用手算验证 FOLLOW 集再检查代码里 follow 数组的初始化。如果文法本身有冲突课设范围内通常可以通过改写文法消除左递归来解决。4.5 现象汇编输出部分为空或报错原因选做部分没有实现或者四元式到汇编的映射表不完整。解决先确认必做部分完全正确再对照参考书第十一章的源代码补全汇编生成。如果只是课设提交必做部分跑通已经能满足大部分要求。提示每次修改文法后一定要重新生成分析表并清空之前的输出文件否则旧结果会干扰判断。5. 进阶用法用 pas1.dat 和 pas2.dat 做回归验证5.1 把三组测试用例当成回归集pas.dat、pas1.dat、pas2.dat 这三组文件不是随便放的它们通常覆盖了不同的语法结构。我的习惯是每改一次代码就把三个输入依次跑一遍对比 testout.txt、testout1.txt、testout2.txt 的输出差异。如果只有 pas2.dat 出错说明问题出在它特有的语法结构上比如嵌套括号或者多重赋值。# 在工程目录下依次运行并保存输出方便 diff project_design.exe pas.dat myout.txt project_design.exe pas1.dat myout1.txt project_design.exe pas2.dat myout2.txt逻辑说明把标准输出重定向到文件再用文本对比工具和压缩包自带的结果比对。参数说明如果程序内部固定读 pas.dat需要先把输入文件名改成命令行参数或者手动替换文件内容。这一步做完你就能快速判断修改是否引入了回归。5.2 从四元式反推汇编的映射技巧选做部分要求把四元式翻译成汇编。常见做法是准备一张映射表加法对应 ADD乘法对应 MUL赋值对应 MOV。关键是临时变量要分配寄存器或内存地址。我一般会先给每个临时变量分配一个固定内存偏移然后逐条翻译四元式。这样即使寄存器分配做得粗糙至少能保证汇编程序逻辑正确。四元式操作符汇编指令备注ADD结果存入 result*MUL注意操作数顺序:MOVarg2 为空-SUB单目取负需单独处理5.3 验证方法手工推导一个小表达式的完整链路拿x : 2 3 * 4做手工验证。词法分析得到 id、赋值号、数字、加号、数字、乘号、数字。语法分析按 SLR(1) 移进归约先归约3 * 4为 F再归约 T再归约 E然后处理加法。四元式应该是(*, 3, 4, t1)、(, 2, t1, t2)、(:, t2, -, x)。如果你跑出来的顺序是(, 2, 3, t1)在前说明乘法没有优先归约检查分析表里乘号状态的 ACTION 项。从那以后我每次拿到这类课设压缩包都强制先跑通自带测试用例再动一行代码。这份资源的价值不在于代码写得多漂亮而在于它把 SLR(1) 从纸面推到了可运行的 C 程序让你能看到四元式一行行打出来。希望帮到你。本文还有配套的精品资源点击获取
返回列表