Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
2
2022fall-Compiler_CMinus
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
李晓奇
2022fall-Compiler_CMinus
Commits
78e208f5
Commit
78e208f5
authored
Oct 28, 2022
by
李晓奇
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of 202.38.79.174:compiler_staff/2022fall-compiler_cminus
parents
5b1dfa22
49c4e204
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
109 additions
and
85 deletions
+109
-85
Documentations/common/cminusf.md
Documentations/common/cminusf.md
+95
-78
Reports/3-ir-gen/report.md
Reports/3-ir-gen/report.md
+6
-0
src/cminusfc/cminusfc.cpp
src/cminusfc/cminusfc.cpp
+8
-7
No files found.
Documentations/common/cminusf.md
View file @
78e208f5
...
@@ -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.
本次实验存在五种情况下的类型转换
*
赋值时
*
赋值时
*
返回值类型和函数签名中的返回类型不一致时
*
返回值类型和函数签名中的返回类型不一致时
...
...
Reports/3-ir-gen/report.md
View file @
78e208f5
...
@@ -135,6 +135,12 @@ PB20111654 李晓奇
...
@@ -135,6 +135,12 @@ PB20111654 李晓奇
后来发这里其实并没有问题,如果有返回值,在if或者else内部就返回了,并不会跳出去被默认返回扰乱。
后来发这里其实并没有问题,如果有返回值,在if或者else内部就返回了,并不会跳出去被默认返回扰乱。
-
最后一个测试文件能够正常执行,但是输出有错,
发现一个好的debug方法:
利用裁剪定位问题,即注释掉一部分,分别利用clang、cminusfc生成可执行文件,查看输出是否一致。
## 实验设计
## 实验设计
请写明为了顺利完成本次实验,加入了哪些亮点设计,并对这些设计进行解释。
请写明为了顺利完成本次实验,加入了哪些亮点设计,并对这些设计进行解释。
...
...
src/cminusfc/cminusfc.cpp
View file @
78e208f5
...
@@ -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
;
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment