Week 1 - Introduction¶
RoadMap¶
Lab 课大致安排:
- 有多个 Projects,最终任务是写一个类C语言的编译器,我们会将这个大任务拆成多个 Projects,并提供 Hints。
-
每个 Project 之间是串联在一起的。即你在上个 Project 写的代码会在下一个 Project 中用到。
所以,请保持你代码的良好结构。
-
每个 Project 都具有相同的结构:
- 我们提供的 Framework
- 你需要自行完成的 Implementation
-
每个 Project 都将由自动评测脚本进行评测,所以千万不要改 Framework 的接口!
搭建环境¶
参考 环境配置
什么是 ANTLR¶
ChatGPT said:
ANTLR(ANother Tool for Language Recognition)是一个功能强大的 语法解析器生成工具,常用于构建编译器、解释器、DSL(领域特定语言)、代码分析工具等。它的主要作用是将 文法规则 转换成可以在目标语言(如 Java、C#, Python, JavaScript 等)中运行的 词法分析器(Lexer) 和 语法分析器(Parser)。
什么是文法规则¶
具体而言,我们可以可以把 文法规则 想象成 语言的“说明书” 或 造句的规矩。
在自然语言里,我们有语法,比如:
-
主语 + 谓语 + 宾语 -
“我 吃 苹果” ✅
同样,编程语言 或 数据格式 也有自己的规则,用来规定哪些符号组合是合法的。
抽象的来说,文法规则通常用来描述:
-
词汇层次:最小的语法单元,比如数字、单词、符号。
-
结构层次:这些词汇如何组合成更大的结构,比如“表达式”“语句”“程序”。
换句话说:
-
文法规则是一组形式化的 生产规则,规定了“从哪些符号出发,能一步步生成一个完整的合法句子”。
-
这些规则通常用 递归 方式定义,可以无限扩展。
Project Zero¶
Project Zero is released!
ANTLR 配置¶
首先,从 https://github.com/sqlab-sustech/CS323-Compilers-2025F-Projects/ clone 代码,并切换到 project0-fake1 分支:
$ git clone https://github.com/sqlab-sustech/CS323-Compilers-2025F-Projects/
$ cd CS323-Compilers-2025F-Projects
$ git checkout project0-fake1
随后,在 IDEA 中打开这个文件夹,你应该看到如下目录结构:

设置 Java SDK 版本为 21。
使用 Makefile 编译 ANTLR 语法文件¶
我们之前说,ANTLR 是一套 语法解析器生成工具,它可以针对某个给定的语法文件(形式语言学的上下文中,语法和文法绝大多数情况下指的是同一回事,两个术语可以互换使用),生成一些可以处理该语法的代码。
项目根目录中有一个 Calc1.g4 文件,它是一个 ANTLR 的语法文件,在项目根目录下执行 make,我们可以注意到在 src/main/java 下面多了 generated.Calc1 这个包,里面有若干 .java 文件。这些代码就是 ANTLR 工具针对 Calc1.g4 这个语法生成的代码。

再执行 make clean 我们会发现 generated/ 目录被删除了。
安装 IDEA 的 ANTLR 插件¶
打开 Settings,找到 Plugin,在 Marketplace 里搜索 ANTLR v4,安装开发者为 "Terence Parr" 的那个插件。

在 Calc1.g4 文件上点右键,在菜单栏中点 "Configure ANTLR",打开配置框,并按照如下配置:

在 Calc1.g4 文件上点右键,在菜单栏中点 "Generate ANTLR Recognizer",我们会注意到在 src/main/java/generated/Calc1 下面出现了同样的文件。
调用 ANTLR 生成的解析器¶
将 Main.java 覆盖为如下内容,如果遇到了依赖问题,使用 Maven 解决依赖问题。
import generated.Calc1.Calc1Lexer;
import generated.Calc1.Calc1Parser;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.*;
public class Main {
public static void main(String[] args) {
// 把要解析的字符串喂给 ANTLR
CharStream input = CharStreams.fromString("1 + 2");
// 词法分析器
Calc1Lexer lexer = new Calc1Lexer(input);
// Token 流
CommonTokenStream tokens = new CommonTokenStream(lexer);
// 语法分析器
Calc1Parser parser = new Calc1Parser(tokens);
// 从规则 'expression' 开始解析
ParseTree tree = parser.expr();
// 把树打印出来看看
System.out.println(tree.toStringTree(parser));
}
}
然后,运行该 Main 类,Console 会输出:
这就表示 ANTLR 构建的解析器成功把 1 + 2 拆成了一棵语法树,至于第一句报错是什么意思,我们会在后续 Lexer 中讲解。
暂时看不懂树长什么样没关系,后面我们会慢慢讲到它背后的含义。