Commit 78e208f5 authored by 李晓奇's avatar 李晓奇

Merge branch 'master' of 202.38.79.174:compiler_staff/2022fall-compiler_cminus

parents 5b1dfa22 49c4e204
...@@ -34,14 +34,15 @@ ...@@ -34,14 +34,15 @@
30. $`\text{args} \rightarrow \text{arg-list}\ |\ \text{empty}`$ 30. $`\text{args} \rightarrow \text{arg-list}\ |\ \text{empty}`$
31. $`\text{arg-list} \rightarrow \text{arg-list}\ \textbf{,}\ \text{expression}\ |\ \text{expression}`$ 31. $`\text{arg-list} \rightarrow \text{arg-list}\ \textbf{,}\ \text{expression}\ |\ \text{expression}`$
## cminus-f 的语义 ## cminus-f 的语义
在上述语法规则中,我们定义了 `cminus-f` 语言的语法,接着,我们对照语法规则,给出相关的语义和解释。 在上述语法规则中,我们定义了 `cminus-f` 语言的语法,接着,我们对照语法规则,给出相关的语义和解释。
在阅读前,需要理解 `cminus-f` 主要源自于 C 语言,因此它的行为都会接近 C 语言。 在阅读前,需要理解 `cminus-f` 主要源自于 C 语言,因此它的行为都会接近 C 语言。
1. $`\text{program} \rightarrow \text{declaration-list}`$ 1. $`\text{program} \rightarrow \text{declaration-list}`$
2. $`\text{declaration-list} \rightarrow \text{declaration-list}\ \text{declaration}\ |\ \text{declaration}`$ 2. $`\text{declaration-list} \rightarrow \text{declaration-list}\ \text{declaration}\ |\ \text{declaration}`$
3. $`\text{declaration} \rightarrow \text{var-declaration}\ |\ \text{fun-declaration}`$ 3. $`\text{declaration} \rightarrow \text{var-declaration}\ |\ \text{fun-declaration}`$
一个`程序`由一系列`声明`组成,声明包括了`函数声明``变量声明`,它们可以以任意顺序排列。 一个`程序`由一系列`声明`组成,声明包括了`函数声明``变量声明`,它们可以以任意顺序排列。
...@@ -55,6 +56,7 @@ ...@@ -55,6 +56,7 @@
因为没有原型这个概念, `cminus-f` 不区分函数的声明和定义。 因为没有原型这个概念, `cminus-f` 不区分函数的声明和定义。
4. $`\text{var-declaration}\ \rightarrow \text{type-specifier}\ \textbf{ID}\ \textbf{;}\ |\ \text{type-specifier}\ \textbf{ID}\ \textbf{[}\ \textbf{INTEGER}\ \textbf{]}\ \textbf{;}`$ 4. $`\text{var-declaration}\ \rightarrow \text{type-specifier}\ \textbf{ID}\ \textbf{;}\ |\ \text{type-specifier}\ \textbf{ID}\ \textbf{[}\ \textbf{INTEGER}\ \textbf{]}\ \textbf{;}`$
5. $`\text{type-specifier} \rightarrow \textbf{int}\ |\ \textbf{float}\ |\ \textbf{void}`$ 5. $`\text{type-specifier} \rightarrow \textbf{int}\ |\ \textbf{float}\ |\ \textbf{void}`$
`cminus-f` 的基础类型只有整型(`int`)、浮点型(`float`)和 `void`。而在变量声明中,只有整型和浮点型可以使用,`void` 仅用于函数声明。 `cminus-f` 的基础类型只有整型(`int`)、浮点型(`float`)和 `void`。而在变量声明中,只有整型和浮点型可以使用,`void` 仅用于函数声明。
...@@ -66,8 +68,11 @@ ...@@ -66,8 +68,11 @@
一次只能声明一个变量。 一次只能声明一个变量。
6. $`\text{fun-declaration} \rightarrow \text{type-specifier}\ \textbf{ID}\ \textbf{(}\ \text{params}\ \textbf{)}\ \text{compound-stmt}`$ 6. $`\text{fun-declaration} \rightarrow \text{type-specifier}\ \textbf{ID}\ \textbf{(}\ \text{params}\ \textbf{)}\ \text{compound-stmt}`$
7. $`\text{params} \rightarrow \text{param-list}\ |\ \textbf{void}`$ 7. $`\text{params} \rightarrow \text{param-list}\ |\ \textbf{void}`$
8. $`\text{param-list} \rightarrow \text{param-list}\ ,\ \text{param}\ |\ \text{param}`$ 8. $`\text{param-list} \rightarrow \text{param-list}\ ,\ \text{param}\ |\ \text{param}`$
9. $`\text{param} \rightarrow \text{type-specifier}\ \textbf{ID}\ |\ \text{type-specifier}\ \textbf{ID}\ \textbf{[]}`$ 9. $`\text{param} \rightarrow \text{type-specifier}\ \textbf{ID}\ |\ \text{type-specifier}\ \textbf{ID}\ \textbf{[]}`$
`函数声明`包含了返回类型,标识符,由逗号分隔的`形参`列表,还有一个`复合语句` `函数声明`包含了返回类型,标识符,由逗号分隔的`形参`列表,还有一个`复合语句`
...@@ -93,11 +98,13 @@ ...@@ -93,11 +98,13 @@
`局部声明`拥有和`复合语句`中的`语句列表`一样的作用域,且其优先级高于任何同名的全局声明(常见的静态作用域) `局部声明`拥有和`复合语句`中的`语句列表`一样的作用域,且其优先级高于任何同名的全局声明(常见的静态作用域)
11. $`\text{local-declarations} \rightarrow \text{local-declarations var-declaration}\ |\ \text{empty}`$ 11. $`\text{local-declarations} \rightarrow \text{local-declarations var-declaration}\ |\ \text{empty}`$
12. $`\text{statement-list} \rightarrow \text{statement-list}\ \text{statement}\ |\ \text{empty}`$ 12. $`\text{statement-list} \rightarrow \text{statement-list}\ \text{statement}\ |\ \text{empty}`$
`局部声明``语句列表`都可以为空(empty表示空字符串,即$`\varepsilon`$) `局部声明``语句列表`都可以为空(empty表示空字符串,即$`\varepsilon`$)
13. $`\begin{aligned}\text{statement} \rightarrow\ &\text{expression-stmt}\\ &|\ \text{compound-stmt}\\ &|\ \text{selection-stmt}\\ &|\ \text{iteration-stmt}\\ &|\ \text{return-stmt}\end{aligned}`$ 13. $`\begin{aligned}\text{statement} \rightarrow\ &\text{expression-stmt}\\ &|\ \text{compound-stmt}\\ &|\ \text{selection-stmt}\\ &|\ \text{iteration-stmt}\\ &|\ \text{return-stmt}\end{aligned}`$
14. $`\text{expression-stmt} \rightarrow \text{expression}\ \textbf{;}\ |\ \textbf{;}`$ 14. $`\text{expression-stmt} \rightarrow \text{expression}\ \textbf{;}\ |\ \textbf{;}`$
`表达式语句`由一个可选的`表达式`(即可以没有`表达式`)和一个分号组成 `表达式语句`由一个可选的`表达式`(即可以没有`表达式`)和一个分号组成
...@@ -123,6 +130,7 @@ ...@@ -123,6 +130,7 @@
`return`会将程序的控制转移给当前函数的调用者,而$`\textbf{main}`$函数的`return`会使得程序终止 `return`会将程序的控制转移给当前函数的调用者,而$`\textbf{main}`$函数的`return`会使得程序终止
18. $`\text{expression} \rightarrow \text{var}\ \textbf{=}\ \text{expression}\ |\ \text{simple-expression}`$ 18. $`\text{expression} \rightarrow \text{var}\ \textbf{=}\ \text{expression}\ |\ \text{simple-expression}`$
19. $`\text{var} \rightarrow \textbf{ID}\ |\ \textbf{ID}\ \textbf{[}\ \text{expression} \textbf{]}`$ 19. $`\text{var} \rightarrow \textbf{ID}\ |\ \textbf{ID}\ \textbf{[}\ \text{expression} \textbf{]}`$
一个`表达式`可以是一个变量引用(即`var`)接着一个赋值符号(=)以及一个表达式,也可以是一个`简单表达式` 一个`表达式`可以是一个变量引用(即`var`)接着一个赋值符号(=)以及一个表达式,也可以是一个`简单表达式`
...@@ -138,10 +146,15 @@ ...@@ -138,10 +146,15 @@
`C` 中,赋值对象(即 `var` )必须是左值,而左值可以通过多种方式获得。`cminus-f`中,唯一的左值就是通过 `var` 的语法得到的,因此 `cminus-f` 通过语法限制了 `var` 为左值,而不是像 `C` 中一样通过类型检查,这也是为什么 `cminus-f` 中不允许进行指针算数。 `C` 中,赋值对象(即 `var` )必须是左值,而左值可以通过多种方式获得。`cminus-f`中,唯一的左值就是通过 `var` 的语法得到的,因此 `cminus-f` 通过语法限制了 `var` 为左值,而不是像 `C` 中一样通过类型检查,这也是为什么 `cminus-f` 中不允许进行指针算数。
20. $`\text{simple-expression} \rightarrow \text{additive-expression}\ \text{relop}\ \text{additive-expression}\ |\ \text{additive-expression}`$ 20. $`\text{simple-expression} \rightarrow \text{additive-expression}\ \text{relop}\ \text{additive-expression}\ |\ \text{additive-expression}`$
21. $`\text{relop}\ \rightarrow \textbf{<=}\ |\ \textbf{<}\ |\ \textbf{>}\ |\ \textbf{>=}\ |\ \textbf{==}\ |\ \textbf{!=}`$ 21. $`\text{relop}\ \rightarrow \textbf{<=}\ |\ \textbf{<}\ |\ \textbf{>}\ |\ \textbf{>=}\ |\ \textbf{==}\ |\ \textbf{!=}`$
22. $`\text{additive-expression} \rightarrow \text{additive-expression}\ \text{addop}\ \text{term}\ |\ \text{term}`$ 22. $`\text{additive-expression} \rightarrow \text{additive-expression}\ \text{addop}\ \text{term}\ |\ \text{term}`$
23. $`\text{addop} \rightarrow \textbf{+}\ |\ \textbf{-}`$ 23. $`\text{addop} \rightarrow \textbf{+}\ |\ \textbf{-}`$
24. $`\text{term} \rightarrow \text{term}\ \text{mulop}\ \text{factor}\ |\ \text{factor}`$ 24. $`\text{term} \rightarrow \text{term}\ \text{mulop}\ \text{factor}\ |\ \text{factor}`$
25. $`\text{mulop} \rightarrow \textbf{*}\ |\ \textbf{/}`$ 25. $`\text{mulop} \rightarrow \textbf{*}\ |\ \textbf{/}`$
一个`简单表达式`是一个`加法表达式`或者两个`加法表达式`的关系运算。当它是`加法表达式`时,它的值就是`加法表达式`的值。而当它是关系运算时,如果关系运算结果为真则值为整型值 1,反之则值为整型值 0。 一个`简单表达式`是一个`加法表达式`或者两个`加法表达式`的关系运算。当它是`加法表达式`时,它的值就是`加法表达式`的值。而当它是关系运算时,如果关系运算结果为真则值为整型值 1,反之则值为整型值 0。
...@@ -155,9 +168,13 @@ ...@@ -155,9 +168,13 @@
`因数`可以是一个括号包围的`表达式`(此时它的值是`表达式`的值),或者是一个`变量`(此时它的值是`变量`的值),或者是一个`函数调用`(此时它的值是`函数调用`的返回值),或者是一个`数字字面量`(此时它的值为该字面量的值)。当`因数`是数组变量时,除非此时它被用作一个`函数调用`中的数组参数,否则它必须要带有下标。 `因数`可以是一个括号包围的`表达式`(此时它的值是`表达式`的值),或者是一个`变量`(此时它的值是`变量`的值),或者是一个`函数调用`(此时它的值是`函数调用`的返回值),或者是一个`数字字面量`(此时它的值为该字面量的值)。当`因数`是数组变量时,除非此时它被用作一个`函数调用`中的数组参数,否则它必须要带有下标。
27. $`\text{integer} \rightarrow \textbf{INTEGER}`$ 27. $`\text{integer} \rightarrow \textbf{INTEGER}`$
28. $`\text{float} \rightarrow \textbf{FLOATPOINT}`$ 28. $`\text{float} \rightarrow \textbf{FLOATPOINT}`$
29. $`\text{call} \rightarrow \textbf{ID}\ \textbf{(}\ \text{args} \textbf{)}`$ 29. $`\text{call} \rightarrow \textbf{ID}\ \textbf{(}\ \text{args} \textbf{)}`$
30. $`\text{args} \rightarrow \text{arg-list}\ |\ \text{empty}`$ 30. $`\text{args} \rightarrow \text{arg-list}\ |\ \text{empty}`$
31. $`\text{arg-list} \rightarrow \text{arg-list}\ \textbf{,}\ \text{expression}\ |\ \text{expression}`$ 31. $`\text{arg-list} \rightarrow \text{arg-list}\ \textbf{,}\ \text{expression}\ |\ \text{expression}`$
`函数调用`由一个函数的`标识符`与一组括号包围的`实参`组成。`实参`可以为空,也可以是由逗号分隔的的`表达式`组成的列表,这些表达式代表着函数调用时,传给`形参`的值。`函数调用时``实参`数量和类型必须与`函数声明`中的`形参`一致,必要时需要进行类型转换。 `函数调用`由一个函数的`标识符`与一组括号包围的`实参`组成。`实参`可以为空,也可以是由逗号分隔的的`表达式`组成的列表,这些表达式代表着函数调用时,传给`形参`的值。`函数调用时``实参`数量和类型必须与`函数声明`中的`形参`一致,必要时需要进行类型转换。
...@@ -176,10 +193,10 @@ void neg_idx_except(void) {...} ...@@ -176,10 +193,10 @@ void neg_idx_except(void) {...}
* `outputFloat` 函数接受一个浮点参数,然后将它的值打印到标准输出,并输出换行符。 * `outputFloat` 函数接受一个浮点参数,然后将它的值打印到标准输出,并输出换行符。
* `neg_idx_except` 函数没有形参,执行后报错并退出 * `neg_idx_except` 函数没有形参,执行后报错并退出
除此之外,其它规则和 C 中类似,比如同一个作用域下不允许定义重名变量或函数(本次实验中不做要求) 除此之外,其它规则和 C 中类似,比如同一个作用域下不允许定义重名变量或函数(本次实验中不做要求)
## 提醒与补充 ## 提醒与补充
1. 本次实验存在五种情况下的类型转换 1. 本次实验存在五种情况下的类型转换
* 赋值时 * 赋值时
* 返回值类型和函数签名中的返回类型不一致时 * 返回值类型和函数签名中的返回类型不一致时
......
...@@ -135,6 +135,12 @@ PB20111654 李晓奇 ...@@ -135,6 +135,12 @@ PB20111654 李晓奇
后来发这里其实并没有问题,如果有返回值,在if或者else内部就返回了,并不会跳出去被默认返回扰乱。 后来发这里其实并没有问题,如果有返回值,在if或者else内部就返回了,并不会跳出去被默认返回扰乱。
- 最后一个测试文件能够正常执行,但是输出有错,
发现一个好的debug方法:
利用裁剪定位问题,即注释掉一部分,分别利用clang、cminusfc生成可执行文件,查看输出是否一致。
## 实验设计 ## 实验设计
请写明为了顺利完成本次实验,加入了哪些亮点设计,并对这些设计进行解释。 请写明为了顺利完成本次实验,加入了哪些亮点设计,并对这些设计进行解释。
......
...@@ -104,17 +104,18 @@ int main(int argc, char **argv) { ...@@ -104,17 +104,18 @@ int main(int argc, char **argv) {
output_stream.close(); output_stream.close();
if (!emit) { if (!emit) {
std::string lib_path = argv[0]; std::string lib_path = argv[0];
lib_path.erase(lib_path.rfind('/')) += "/libcminus_io.a"; auto idx = lib_path.rfind('/');
auto command_string = "clang -O0 -w "s + target_path + ".ll -o " + target_path + " " + lib_path; if (idx != std::string::npos)
std::cout << command_string << std::endl; lib_path.erase(lib_path.rfind('/'));
int re_code0 = std::system(command_string.c_str()); auto cmd_str = "clang -O0 -w "s + target_path + ".ll -o " + target_path + " -L" + lib_path + " -lcminus_io";
command_string = "rm "s + target_path + ".ll"; std::cout << cmd_str << std::endl;
int re_code1 = std::system(command_string.c_str()); int re_code0 = std::system(cmd_str.c_str());
cmd_str = "rm "s + target_path + ".ll";
int re_code1 = std::system(cmd_str.c_str());
if (re_code0 == 0 && re_code1 == 0) if (re_code0 == 0 && re_code1 == 0)
return 0; return 0;
else else
return 1; return 1;
} }
return 0; return 0;
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment