Skip to content

编译原理实验报告

:material-circle-edit-outline: 约 850 个字 :material-clock-time-two-outline: 预计阅读时间 3 分钟

实验一:词法与语法分析 2025 年 3 月 15 日

姓名:俞仲炜 学号:3220104929

功能清单

词法分析

词法分析的目的是将源代码解析成一个个 token,即词法分析的最小单元,表示一个程序有意义的最小分割。

我们借助了 Flex 来生成语法分析器的具体代码,使用该工具的代码位于 lexer.l 文件中。解析源代码的具体形式主要是识别特定的字符串并执行返回 token 的动作,识别字符串使用了正则表达式进行匹配,当然更多还是直接匹配。

语法分析

由词法分析得到的 token 序列需要进一步的解析,具体而言我们需要判断一串 tokens 是否合法,合法则生成对应的语法树,否则报错。合法即指符合我们简化后的 SysY 语言文法。

在生成语法分析器之前,我们需要先在 tree.hpp 中补充语法树结点类,使得语法树能完整生成。

我们借助了 Bison 来生成语法分析器的具体代码,使用该工具的代码位于 parser.y 文件中。解析 token 的具体形式主要是为工具提供一个上下文无关文法,我们需要简化后的 SysY 语言文法根据列出所有产生式,并在对应的产生式执行相应的语法树结点构建、传递的动作,由此在语法分析的过程中同步生成对应的语法树结点、构建语法树。

语法树打印

语法分析结束后,我们只需在 main.cpp 文件的 main 函数中通过调用 root->print_tree() 即可打印出语法树。

亮点摘选

在处理数组时,我选择了将数组的维度单独作为一个结点进行处理,保持原 VarDef 类以避免“牵一发而动全身”,见下图中的 NDArr 对应的产生式:

image-20250315194649810

NDArr 借助左递归实现对任意维度的识别,并使用 DimDef 类内部的 vector 变量动态存储维度信息,然后在 VarDef 中增加一个指向 DimDef 的指针,完成对数组维度信息的存储。

此外,我稍微修改了 yyerror 函数,让报错更具体一点点:

image-20250315200612757

输出示例:

image-20250315200109527

AI 使用情况

在本次实验中,我在处理 tree.hpp 以及 debug 时借助了 GitHub copilot。在处理 tree.hpp 时,由于对 C++不熟练,我借助其学习 C++语法,以此理解该文件的内容。

image-20250315192743482

在 debug 过程中,我也借助了 AI 帮我分析错误的原因,但并没有直接使用 AI 修正的代码,因为经测试基本都是错的。

image-20250315193045541

此外,在 tree.hpp 中,我借助 AI 生成了 to_stringget_children 这两个相对不重要的函数的具体代码。

建议与想法

一开始不知道这个实验要具体干什么,花了很多时间入门。新的实验领域必然是需要额外的时间去入门的,但入门的指引或许可以更完善,毕竟不是所有同学都有能力很顺利地靠自己入门,因为和同学聊天时发现其他同学也或多或少有类似情况。也希望这个实验能越来越好。