Skip to content

Commit 61944a6

Browse files
authored
Merge pull request #44 from arcsysu/feat/format
Feat:文档格式修改功能
2 parents 3906676 + 5e180d9 commit 61944a6

51 files changed

Lines changed: 4974 additions & 1812 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
site/
44
build/
55
env/
6+
node_modules/

.markdownlint-cli2.jsonc

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"customRules": ["mkdocs-material-linter"],
3+
"config": {
4+
"default": false,
5+
6+
// The docs in this repo intentionally use inline HTML, long lines, and a variety of Markdown patterns.
7+
// Keep linting focused on MkDocs Material structural correctness (admonitions/tabs/code blocks).
8+
"MD013": false,
9+
"MD033": false,
10+
"MD045": false,
11+
"MD046": false,
12+
13+
// Do not require YAML front matter on every page.
14+
"material-meta-tags": false,
15+
16+
"material-admonition-types": true,
17+
"material-admonition-indentation": true,
18+
"material-admonition-empty": true,
19+
"material-admonition-empty-title": true,
20+
"material-content-tabs": true,
21+
"material-code-annotations": true,
22+
"material-navigation-structure": false,
23+
"material-shell-language-standardization": true,
24+
"material-bundle-exec-shell-type": true,
25+
"material-blank-lines-spacing": false,
26+
"material-code-block-syntax": false
27+
}
28+
}

.prettierrc

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"proseWrap": "always",
3+
"arrowParens": "always",
4+
"parser": "markdown",
5+
"spaceAroundAlphabet": true,
6+
"spaceAroundNumber": true,
7+
"spaceAroundCode": true,
8+
"spaceAroundLink": true,
9+
"noDuplicatePunctuation": false,
10+
"noSpaceAroundFullwidth": true,
11+
"noSpaceBetweenNumberUnit": ["%", "°C", "°"],
12+
13+
"plugins": ["prettier-plugin-zh"],
14+
15+
"overrides": [
16+
{
17+
"files": "**/*.md",
18+
"options": {
19+
"embeddedLanguageFormatting": "off"
20+
}
21+
}
22+
]
23+
}

docs/QA.md

Lines changed: 78 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,26 @@
44

55
## 环境配置
66

7-
#### 1.WSL 环境下使用 `systemctl`指令报错:`System has not been booted with systemd as init system (PID 1). Can’t operate.`
7+
#### 1.WSL 环境下使用 `systemctl` 指令报错: `System has not been booted with systemd as init system (PID 1). Can’t operate.`
88

9-
由于部分 WSL 使用 `SysV init`而非 `systemd`管理服务,解决方法是使用 `service`指令代替 `systemctl`指令。
9+
由于部分 WSL 使用 `SysV init` 而非 `systemd` 管理服务,解决方法是使用 `service`
10+
指令代替 `systemctl` 指令。
1011

1112
#### 2.如何更新代码仓库: 请在终端依次输入以下指令
1213

1314
(注意:你的终端所在目录应在实验代码文件夹根目录下,如果你不确定,请新建终端)
1415

15-
```bash
16-
git stash # 将当前未提交的修改暂时储藏
17-
git pull # 从远程仓库拉取新的实验代码
18-
git stash pop # 恢复先前暂时储藏的修改
16+
```shell
17+
git stash # 将当前未提交的修改暂时储藏
18+
git pull # 从远程仓库拉取新的实验代码
19+
git stash pop # 恢复先前暂时储藏的修改
1920
```
2021

2122
#### 3.MacOS + VSCode 如何进入单步调试
2223

2324
1. 安装 VSCode 插件 `CodeLLDB`
2425
![codeLLDB](images/QA/codelldb.png)
25-
2.`.vscode/launch.json`中加入以下配置
26+
2. `.vscode/launch.json` 中加入以下配置
2627

2728
```json
2829
{
@@ -35,21 +36,22 @@ git stash pop # 恢复先前暂时储藏的修改
3536
}
3637
```
3738

38-
![launch.json](images/QA/VSClaunch.png) 3. 打上断点,在`测试`插件中对单个测例进行单步调试
39-
![alt text](images/QA/debug.png)
39+
![launch.json](images/QA/VSClaunch.png) 3. 打上断点,在 `测试`
40+
插件中对单个测例进行单步调试 ![alt text](images/QA/debug.png)
4041

4142
## 实验一
4243

4344
#### 1.在 task1 中存在部分 Loc 要求输出相对路径,部分 Loc 要求输出绝对路径,是否需要针对不同要求编写不同方式的 print_token?
4445

45-
![alt text](images/QA/task1.1_1.png)
46-
![alt text](images/QA/task1.1_2.png)
46+
![alt text](images/QA/task1.1_1.png) ![alt text](images/QA/task1.1_2.png)
4747
答:相对路径与绝对路径的区别并不是 print_token()函数导致的,而是由于 clang 预处理时输出格式不同所导致的(详见 task0-answer 生成的预处理源代码,路径为 build/test/task0/\*),词法规则中对预处理信息的处理可以提供文件路径信息,可以关注预处理信息中的最后一条。
4848

4949
#### 2.预处理文件中没有关于源文件的行号信息,如何识别出词法单元出现在源文件中的位置?是否需要额外编写脚本?
5050

5151
答:关于源文件的行号信息,需要从预处理文件中的预处理信息中获取,无需额外编写脚本
52-
例如# 1 "./basic/000_main.sysu.c" 2:其中'#'右边的数字 1 即下一行有效内容出现在对应源文件中的行数(可自行比对预处理后的源文件与标准输出 answer.txt),此后的行号/列号信息需要自行维护
52+
例如#
53+
1 "./basic/000_main.sysu.c"
54+
2:其中'#'右边的数字 1 即下一行有效内容出现在对应源文件中的行数(可自行比对预处理后的源文件与标准输出 answer.txt),此后的行号/列号信息需要自行维护
5355
如图是 003 样例的源文件,预处理文件和答案,起始行并不是 1
5456
![alt text](images/QA/task1.2_1.png)
5557

@@ -65,7 +67,8 @@ git stash pop # 恢复先前暂时储藏的修改
6567
答:
6668

6769
1. 预处理信息应选取最后一个地址
68-
2. 因为在"sylib.h"头文件中,"void \_sysy_starttime..."为第 10 行;预处理信息第九行的意思是下一行的词法单元处于源文件中的行号
70+
2. 因为在"sylib.h"头文件中,"void
71+
\_sysy_starttime..."为第 10 行;预处理信息第九行的意思是下一行的词法单元处于源文件中的行号
6972
3. 地址后的数字与输出无关,可忽略
7073

7174
## 实验二
@@ -76,61 +79,98 @@ git stash pop # 恢复先前暂时储藏的修改
7679

7780
在解释这个问题前,需要说明如下事项。在 task2 中,我们既可以使用“递归”的文法,也可以使用“直接”的文法。例如 expression 的这两种写法都是可以的:
7881

79-
```bash
82+
```shell
8083
assignment_expression | expression Comma assignment_expression
8184
assignment_expression (Comma assignment_expression)*
8285
```
8386

84-
但是在 task2 中,需要注意,你的 g4 的文法会影响 `ctx->assignment_expression()` 的返回类型:
87+
但是在 task2 中,需要注意,你的 g4 的文法会影响 `ctx->assignment_expression()`
88+
的返回类型:
8589

86-
文法是 `assignment_expression | expression Comma assignment_expression` 时,`ctx->assignment_expression()` 是单个的指针;
90+
文法是 `assignment_expression | expression Comma assignment_expression` 时,
91+
`ctx->assignment_expression()` 是单个的指针;
8792

88-
文法是 `assignment_expression (Comma assignment_expression)*` 时,`ctx->assignment_expression()` 是一个 vector ,里面存放一堆指针。
93+
文法是 `assignment_expression (Comma assignment_expression)*` 时,
94+
`ctx->assignment_expression()` 是一个 vector,里面存放一堆指针。
8995

9096
怎么回事呢?这是因为助教们的脚本会根据你的文法,在 SYsUParser.h 中自动生成相应的类型。
9197

92-
比如 `assignment_expression (Comma assignment_expression)*` ,因为里面 assignment_expression 的数量是不确定的,所以需要用 vector ,`ctx->assignment_expression()` 便是一个 vector ,与此同时, expression 将会有许多的孩子分支, `auto children = ctx->children;` 之后, `children[0]``children[2]``children[4]` ...便对应各个 assignment_expression 节点。
98+
比如
99+
`assignment_expression (Comma assignment_expression)*`,因为里面 assignment_expression 的数量是不确定的,所以需要用 vector,
100+
`ctx->assignment_expression()`
101+
便是一个 vector,与此同时,expression 将会有许多的孩子分支,
102+
`auto children = ctx->children;` 之后, `children[0]``children[2]`
103+
`children[4]` ...便对应各个 assignment_expression 节点。
93104

94-
另一个例子, `assignment_expression | expression Comma assignment_expression` ,里面 assignment_expression 的数量是确定的1,于是 `ctx->assignment_expression()` 便是单个的指针,与此同时, expression 的孩子分支要么只有一个,要么有三个(跟你写的文法是呼应的)。
105+
另一个例子,
106+
`assignment_expression | expression Comma assignment_expression`,里面 assignment_expression 的数量是确定的 1,于是
107+
`ctx->assignment_expression()`
108+
便是单个的指针,与此同时,expression 的孩子分支要么只有一个,要么有三个(跟你写的文法是呼应的)。
95109

96-
现在回到标题的问题,为什么一元表达式不能用非递归型的 `(unary_operator)* postfix_expression` 呢?这其实是助教的问题,因为助教在一些已实现的代码里,是按照 `ctx->unary_operator()` 是单个的指针写的代码,但是如果你把文法改成 `(unary_operator)* postfix_expression` ,就会使得 `ctx->unary_operator()` 变成一个 vector 了,于是助教们写的代码会炸。
110+
现在回到标题的问题,为什么一元表达式不能用非递归型的
111+
`(unary_operator)* postfix_expression`
112+
呢?这其实是助教的问题,因为助教在一些已实现的代码里,是按照
113+
`ctx->unary_operator()` 是单个的指针写的代码,但是如果你把文法改成
114+
`(unary_operator)* postfix_expression`,就会使得 `ctx->unary_operator()`
115+
变成一个 vector 了,于是助教们写的代码会炸。
97116

98-
就结果而言,对一元表达式,建议使用“递归”的文法 `unary_expression : postfix_expression | unary_operator unary_expression;`。当然对于其他大多数文法规则,你用“递归”的文法或者“直接”的文法都可以!注意一下上述的“是否是vector”的问题即可。
117+
就结果而言,对一元表达式,建议使用“递归”的文法
118+
`unary_expression : postfix_expression | unary_operator unary_expression;`。当然对于其他大多数文法规则,你用“递归”的文法或者“直接”的文法都可以!注意一下上述的“是否是 vector”的问题即可。
99119

100120
#### 2.关于 `children[i]``ctx->assignment_expression()` 的区别
101121

102-
以文法 `expression : assignment_expression (Comma assignment_expression)* ;` 为例,
122+
以文法 `expression : assignment_expression (Comma assignment_expression)* ;`
123+
为例,
103124

104125
```cpp
105126
auto children = ctx->children;
106127
for(int i=0;i<children.size();i+=2)children[i];
107128
```
108129

109-
这样取出的偶数位置的 `children[i]` 便对应各个 `assignment_expression` 节点,但需注意类型转换,因为 `children[i]` 还不是 `ast::Assignment_expressionContext*` 类型,照葫芦画瓢可以写出类似的代码:
130+
这样取出的偶数位置的 `children[i]` 便对应各个 `assignment_expression`
131+
节点,但需注意类型转换,因为 `children[i]` 还不是
132+
`ast::Assignment_expressionContext*` 类型,照葫芦画瓢可以写出类似的代码:
110133

111134
```cpp
112135
node->rht = self(dynamic_cast<ast::Assignment_expressionContext*>(children[i]));
113136
```
114137

115138
这里稍微介绍一下这个 self 是做什么的:
116139

117-
在task2中,你会用到大量的 `make<???>()` ,这个 make 函数的功能是向系统申请一小块内存空间,然后返回一个指向该实空间的指针,例如 `auto ret = make<CallExpr>();`
140+
在 task2 中,你会用到大量的
141+
`make<???>()`,这个 make 函数的功能是向系统申请一小块内存空间,然后返回一个指向该实空间的指针,例如
142+
`auto ret = make<CallExpr>();`
118143

119-
我们的函数诸如 `Expr* Ast2Asg::operator()(ast::Postfix_expressionContext* ctx)` ,返回的便是这个 ret 指针,但重点是这个 ret 指针指向了一个实空间,这个实空间正是我们通过调用 `make<???>()` 申请得到的。
144+
我们的函数诸如
145+
`Expr* Ast2Asg::operator()(ast::Postfix_expressionContext* ctx)`,返回的便是这个 ret 指针,但重点是这个 ret 指针指向了一个实空间,这个实空间正是我们通过调用
146+
`make<???>()` 申请得到的。
120147

121-
我们用到的许多 self 就是诸如 `Expr* Ast2Asg::operator()(ast::Postfix_expressionContext* ctx)` 的函数中的某一种。总之, `self(???)` 返回一个指针,但具有实际价值的,是这个指针指向的实空间。
148+
我们用到的许多 self 就是诸如
149+
`Expr* Ast2Asg::operator()(ast::Postfix_expressionContext* ctx)`
150+
的函数中的某一种。总之, `self(???)`
151+
返回一个指针,但具有实际价值的,是这个指针指向的实空间。
122152

123-
回归正题,介绍完 `children[i]` ,再来介绍 `ctx->assignment_expression()`
153+
回归正题,介绍完 `children[i]`,再来介绍 `ctx->assignment_expression()`
124154

125-
调用 `auto list=ctx->assignment_expression()` ,返回一个 vector , list 里面便装着一堆 `assignment_expression`。通过 `for(int i = 0; i < list.size(); i++)list[i];` 可以访问 `expression` 的每一个 `assignment_expression` 孩子。注意我们不需要像 children 那样访问0、2、4、6这样的位置,因为 `ctx->assignment_expression()` 返回一个 vector ,里面只装了 `assignment_expression` ,而不会装有 Comma。
155+
调用
156+
`auto list=ctx->assignment_expression()`,返回一个 vector,list 里面便装着一堆
157+
`assignment_expression`。通过 `for(int i = 0; i < list.size(); i++)list[i];`
158+
可以访问 `expression` 的每一个 `assignment_expression`
159+
孩子。注意我们不需要像 children 那样访问 0、2、4、6 这样的位置,因为
160+
`ctx->assignment_expression()` 返回一个 vector,里面只装了
161+
`assignment_expression`,而不会装有 Comma。
126162

127-
在编写代码时,需注意 `list[i]``self(list[i])` 的区别。前文已提到了 `self(???)` 的作用, `self(???)` 实际上会调用我们写的那些函数,返回一个指针,这个指针指向一个 make 出来的实空间。而 `list[i]` 仅是在遍历 ctx 的孩子。我们的 task2 要做的就是让指针们指向正确的 make 出来的实空间,这个实空间往往也具备一些指针成员,指向其他的实空间。这样指来指去,把实空间和指针安排好后,就构建好了 asg 语法图。
163+
在编写代码时,需注意 `list[i]``self(list[i])` 的区别。前文已提到了
164+
`self(???)` 的作用, `self(???)`
165+
实际上会调用我们写的那些函数,返回一个指针,这个指针指向一个 make 出来的实空间。而
166+
`list[i]`
167+
仅是在遍历 ctx 的孩子。我们的 task2 要做的就是让指针们指向正确的 make 出来的实空间,这个实空间往往也具备一些指针成员,指向其他的实空间。这样指来指去,把实空间和指针安排好后,就构建好了 asg 语法图。
128168

129169
#### 3.关于函数定义的若干问题
130170

131-
一种能够减少你的工作量的g4文法如下
171+
一种能够减少你的工作量的 g4 文法如下
132172

133-
```bash
173+
```shell
134174
parameter_list
135175
: parameter_declaration (Comma parameter_declaration)*
136176
;
@@ -149,7 +189,8 @@ function_definition
149189

150190
为了便于后文你理解“类型”与“限定”,此处稍作提及。
151191

152-
你可能在代码中见过一个叫 `specs` 的变量,是 `SpecQual` 类型。`SpecQual` 类型包含“类型spec”与“是否限定qual”两项内容。
192+
你可能在代码中见过一个叫 `specs` 的变量,是 `SpecQual` 类型。 `SpecQual`
193+
类型包含“类型 spec”与“是否限定 qual”两项内容。
153194

154195
下文的函数定义的代码中含有详细的注释解析,可以帮助你理解这部分具有复杂层次的内容,代码仅供参考,同学们也可以有其他实现方式。
155196

@@ -158,13 +199,13 @@ FunctionDecl*
158199
Ast2Asg::operator()(ast::Function_definitionContext* ctx){
159200
auto ret = make<FunctionDecl>();
160201
mCurrentFunc = ret;
161-
202+
162203
auto type = make<Type>();
163204
ret->type = type;
164-
205+
165206
auto sq = self(ctx->declaration_specifiers());
166207
type->spec = sq.first, type->qual = sq.second;
167-
208+
168209
auto [texp, name] = self(ctx->direct_declarator(), nullptr);//右侧调用的函数为 std::pair<TypeExpr*, std::string> Ast2Asg::operator()(ast::Direct_declaratorContext* ctx, TypeExpr* sub)
169210
//这里解释一下texp的类型,即TypeExpr*,你可以简单认为他是处理数组定义的,例如对于int a[5][3],TypeExpr*负责记录这些维度的长度
170211
//那么texp作为一个指针类型,即TypeExpr*类型,这个指针若非空,是要指向一个实空间的,一个例子便是指向 make<ArrayType>(); 的实空间
@@ -193,7 +234,7 @@ Ast2Asg::operator()(ast::Function_definitionContext* ctx){
193234
//ret存放函数名name,函数实现body,以及一个参数列表(含有参数名字)
194235

195236
//注:我们不考虑int a[2][4](int b=10,char c[3]);这种带默认值的
196-
237+
197238
Symtbl localDecls(self);
198239

199240
if(auto plist = ctx->parameter_list()){
@@ -220,7 +261,7 @@ Ast2Asg::operator()(ast::Function_definitionContext* ctx){
220261
ret->body = self(ctx->compound_statement());
221262
}
222263
}
223-
264+
224265
return ret;
225266
}
226267
```

docs/README.md

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1-
21
# YatCC: Yat Compiler Course
32

4-
中山大学[编译课程](https://yatcc-ai.com)实验。
3+
中山大学 [编译课程](https://yatcc-ai.com) 实验。
54

6-
YatCC 是中山大学编译的实验框架。基于 YatCC 编译实践体系,中山大学[计算机学院](https://cse.sysu.edu.cn/)[国家超算广州中心](http://www.nscc-gz.cn/)联合开发了智能编译教学实践平台 [YatCC-AI](https://yatcc-ai.com)(Yat Compiler Construction with AI)。YatCC-AI 结合国产超算资源与 DeepSeek 等大模型,为《编译原理》和《编译器构造实验》课程提供全新的智能化学习体验。平台深度融合高性能计算(HPC)和人工智能(AI)技术,通过云端容器化环境、AI辅助开发和实时反馈机制,全面优化实践环节,帮助学生掌握编译领域核心知识,接触前沿编译技术与实际应用场景,从而提升工程实践能力与科研创新能力。
5+
YatCC 是中山大学编译的实验框架。基于 YatCC 编译实践体系,中山大学
6+
[计算机学院](https://cse.sysu.edu.cn/)
7+
[国家超算广州中心](http://www.nscc-gz.cn/) 联合开发了智能编译教学实践平台
8+
[YatCC-AI](https://yatcc-ai.com)(Yat Compiler Construction with
9+
AI)。YatCC-AI 结合国产超算资源与 DeepSeek 等大模型,为《编译原理》和《编译器构造实验》课程提供全新的智能化学习体验。平台深度融合高性能计算(HPC)和人工智能(AI)技术,通过云端容器化环境、AI 辅助开发和实时反馈机制,全面优化实践环节,帮助学生掌握编译领域核心知识,接触前沿编译技术与实际应用场景,从而提升工程实践能力与科研创新能力。
710

8-
相比传统编译实验,YatCC-AI 通过一站式在线集成开发环境和 DeepSeek 等大模型接入,为学生提供覆盖编译实验全过程的层次化智能体验,包括:知识问答推理(**LLM4Chatting**)、代码开发调试(**LLM4Coding**)、编译前沿探索(**LLM4Compiling**)。
9-
此外,平台提供云端代码仓库和统一的实验环境配置,大幅简化本地环境搭建带来的繁琐和复杂度,避免因实验环境差异带来的问题,使学生能够更加专注于编译核心技术的学习与实践。
11+
相比传统编译实验,YatCC-AI 通过一站式在线集成开发环境和 DeepSeek 等大模型接入,为学生提供覆盖编译实验全过程的层次化智能体验,包括:知识问答推理(**LLM4Chatting**)、代码开发调试(**LLM4Coding**)、编译前沿探索(**LLM4Compiling**)。此外,平台提供云端代码仓库和统一的实验环境配置,大幅简化本地环境搭建带来的繁琐和复杂度,避免因实验环境差异带来的问题,使学生能够更加专注于编译核心技术的学习与实践。
1012

1113
与此同时,YatCC 实验框架还具有以下特点与优势:
1214

@@ -24,9 +26,9 @@ YatCC 实验共由 6 个任务组成:
2426

2527
| | 实验内容 | 预期用时 |
2628
| :---: | :----------: | :------: |
27-
| Task0 | 环境准备 | 1周 |
28-
| Task1 | 词法分析 | 2周 |
29-
| Task2 | 语法分析 | 4周 |
30-
| Task3 | 中间代码生成 | 4周 |
31-
| Task4 | 中间代码优化 | 6周 |
32-
| Task5 | 后端代码生成 | 4周 |
29+
| Task0 | 环境准备 | 1 周 |
30+
| Task1 | 词法分析 | 2 周 |
31+
| Task2 | 语法分析 | 4 周 |
32+
| Task3 | 中间代码生成 | 4 周 |
33+
| Task4 | 中间代码优化 | 6 周 |
34+
| Task5 | 后端代码生成 | 4 周 |

0 commit comments

Comments
 (0)