├── .gitignore ├── README.md ├── SysY语言定义.pdf ├── SysY运行时库.pdf ├── lab1 ├── gcc │ ├── hello.c │ ├── help │ ├── makefile │ ├── p1.c │ ├── p2.c │ ├── simple │ └── simple.c ├── lab1_2020.pdf ├── 预备工作1 - 了解你的编译器.pptx ├── 预备工作实验报告.docx └── 预备工作实验报告.pdf ├── lab2 ├── asm │ ├── main.S │ ├── main.c │ ├── makefile │ └── mymain.S ├── lab2_2020.pdf ├── 预备工作2 - 汇编编程.pptx ├── 预备工作实验报告.docx └── 预备工作实验报告.pdf ├── lab3 ├── expr.tab.c ├── expr.tab.h ├── expr.y ├── lab3_2020.pdf ├── makefile ├── operator.tab.c ├── operator.tab.h ├── operator.y └── 预备工作3 - 熟悉辅助工具.pptx ├── lab4 ├── lab4_2020.pdf ├── lex.yy.c ├── makefile ├── sysy.l ├── sysy.l.txt ├── sysycc.l ├── testin ├── testin_plus └── 实现词法分析器.pptx ├── lab5 ├── .vscode │ └── settings.json ├── Makefile ├── bin │ └── .gitkeep ├── lab5_2020.pdf ├── src │ ├── common.h │ ├── main.cpp │ ├── main.l │ ├── main.y │ ├── pch.h │ ├── tree.cpp │ ├── tree.h │ ├── type.cpp │ └── type.h └── tests │ ├── 0.c │ ├── 1.c │ ├── 2.c │ ├── 3.c │ └── test.c ├── lab6 ├── .gitignore ├── Makefile ├── bin │ └── .gitkeep ├── lab6_2020.pdf ├── src │ ├── common.h │ ├── lexer.cpp │ ├── lexer.l │ ├── main.cpp │ ├── parser.cpp │ ├── parser.h │ ├── parser.output │ ├── parser.y │ ├── pch.h │ ├── tree.cpp │ ├── tree.h │ ├── type.cpp │ └── type.h ├── test.out └── test │ ├── 1 │ ├── .gitkeep │ ├── 00_main.c │ ├── 00_main.in │ ├── 01_basic_out.c │ ├── 01_basic_out.in │ ├── 02_var_out.c │ ├── 02_var_out.in │ ├── 03_basic_in.c │ ├── 03_basic_in.in │ ├── 04_if.c │ ├── 04_if.in │ ├── 05_if_notin.c │ ├── 05_if_notin.in │ ├── 06_if_else.c │ ├── 06_if_else.in │ ├── 07_if_else_notin.c │ ├── 07_if_else_notin.in │ ├── 08_expr_add.c │ ├── 08_expr_add.in │ ├── 09_expr_sub.c │ ├── 09_expr_sub.in │ ├── 10_expr_mul.c │ ├── 10_expr_mul.in │ ├── 11_expr_div.c │ ├── 11_expr_div.in │ ├── 12_expr_mod.c │ ├── 12_expr_mod.in │ ├── 13_expr_minus.c │ ├── 13_expr_minus.in │ ├── 14_expr_eq.c │ ├── 14_expr_eq.in │ ├── 15_expr_gr.c │ ├── 15_expr_gr.in │ ├── 16_expr_lr.c │ ├── 16_expr_lr.in │ ├── 17_expr_ge.c │ ├── 17_expr_ge.in │ ├── 18_expr_le.c │ ├── 18_expr_le.in │ ├── 19_expr_ne.c │ ├── 19_expr_ne.in │ ├── 20_expr_or.c │ ├── 20_expr_or.in │ ├── 21_expr_and.c │ ├── 21_expr_and.in │ ├── 22_expr_not.c │ ├── 22_expr_not.in │ ├── 23_loop_while.c │ ├── 23_loop_while.in │ ├── 24_loop_for.c │ ├── 24_loop_for.in │ ├── 25_comment.c │ ├── 25_comment.in │ ├── 26_multi_var.c │ ├── 26_multi_var.in │ ├── 27_char.c │ ├── 27_char.in │ ├── 28_prior_1.c │ ├── 28_prior_1.in │ ├── 29_prior_2.c │ ├── 29_prior_2.in │ ├── 30_prior_3.c │ ├── 30_prior_3.in │ ├── 31_prior_4.c │ ├── 31_prior_4.in │ ├── 32_prior_5.c │ ├── 32_prior_5.in │ ├── 33_expr_multi_assign.c │ ├── 33_expr_multi_assign.in │ ├── 34_if_else_multista.c │ ├── 34_if_else_multista.in │ ├── 35_while_if.c │ ├── 35_while_if.in │ ├── 36_if_complex_expr.c │ ├── 36_if_complex_expr.in │ ├── 37_neg_div_mod.c │ └── 37_neg_div_mod.in │ ├── 2 │ ├── .gitkeep │ ├── 00_multi_scope.c │ ├── 00_multi_scope.in │ ├── 01_const.c │ ├── 01_const.in │ ├── 02_hex.c │ ├── 02_hex.in │ ├── 03_oct.c │ ├── 03_oct.in │ ├── 04_array.c │ ├── 04_array.in │ ├── 05_multi_array.c │ ├── 05_multi_array.in │ ├── 06_struct.c │ ├── 06_struct.in │ ├── 07_pointer.c │ ├── 07_pointer.in │ ├── 08_var_assign.c │ └── 08_var_assign.in │ ├── 3 │ ├── .gitkeep │ ├── 00_break.c │ ├── 00_break.in │ ├── 01_continue.c │ ├── 01_continue.in │ ├── 02_multi_param_io.c │ ├── 02_multi_param_io.in │ ├── 03_func_1.c │ ├── 03_func_1.in │ ├── 04_func_2.c │ ├── 04_func_2.in │ ├── 05_func_3.c │ ├── 05_func_3.in │ ├── 06_func_4.c │ └── 06_func_4.in │ ├── 4 │ ├── .gitkeep │ ├── 00_sort_1.c │ ├── 00_sort_1.in │ ├── 01_sort_2.c │ ├── 01_sort_2.in │ ├── 02_path.c │ ├── 02_path.in │ ├── 03_matrix_tran.c │ ├── 03_matrix_tran.in │ ├── 04_conv.c │ ├── 04_conv.in │ ├── 05_fft.c │ ├── 05_fft.in │ ├── 06_fft_2.c │ └── 06_fft_2.in │ └── type_check │ ├── .gitkeep │ ├── 00_var_def.c │ ├── 01_var_re.c │ ├── 02_bool.c │ ├── 03_str.c │ ├── 04_var_usebeforedef.c │ ├── 05_var_scope.c │ ├── 06_const_assign.c │ ├── 07_const_without_init.c │ ├── 08_break_continue_outof_cycle.c │ ├── 09_func_param_num.c │ ├── 10_func_param_type.c │ └── 11_func_return.c ├── utils.pdf └── 上机大作业总体要求.doc /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Object files 5 | *.o 6 | *.ko 7 | *.obj 8 | *.elf 9 | 10 | # Linker output 11 | *.ilk 12 | *.map 13 | *.exp 14 | 15 | # Precompiled Headers 16 | *.gch 17 | *.pch 18 | 19 | # Libraries 20 | *.lib 21 | *.a 22 | *.la 23 | *.lo 24 | 25 | # Shared objects (inc. Windows DLLs) 26 | *.dll 27 | *.so 28 | *.so.* 29 | *.dylib 30 | 31 | # Executables 32 | *.exe 33 | *.out 34 | *.app 35 | *.i*86 36 | *.x86_64 37 | *.hex 38 | 39 | # Debug files 40 | *.dSYM/ 41 | *.su 42 | *.idb 43 | *.pdb 44 | 45 | # Kernel Module Compile Results 46 | *.mod* 47 | *.cmd 48 | .tmp_versions/ 49 | modules.order 50 | Module.symvers 51 | Mkfile.old 52 | dkms.conf 53 | 54 | # vscode 55 | launch.json 56 | tasks.json 57 | 58 | # 59 | *.mp4 60 | 资料/ 61 | *.zip 62 | temp 63 | ~$* -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Luczy Compiler - 小辣稽编译器 2 | 小辣稽的编译原理大作业-简化的c语言编译器 3 | 4 | # 项目概要 5 | 分6个部分,逐步实现一个基于简化的c的语言:SysY语言的编译器(将SysY编译到x86汇编)。SysY语言支持int,bool,string三种基本数据类型,支持if-else,for,while等基本流程控制语句。 6 | 7 | 在我的实现中,还支持指针、数组、函数调用,变量的内存分配在栈上进行。 8 | 9 | ### 项目分为六个部分 10 | - Lab1 11 | 探索现有的GCC编译器,看看它干了些什么,了解一下接下来的工作大体内容 12 | 13 | - lab2 14 | 自己动手翻译一个c写成的代码到汇编,并且和GCC产生的汇编对比 15 | 16 | - lab3 17 | 利用词法分析工具Bison写一个简单的词法分析器,将一个计算式由中缀翻译为后缀 18 | 19 | - lab4 20 | 实现SysY语言的词法分析器 21 | 22 | - lab5 23 | 实现SysY语言的语法分析器,并与词法分析器结合,将源码翻译为AST语法树 24 | 25 | - lab6 26 | 实现编译器前端 `LSCC (Luczydoge Simplified C Compiler)` 将c代码翻译到汇编代码 27 | 28 | # 如何使用 29 | 30 | > 请先参照本代码库根目录下的util.pdf安装配置环境,需要在Linux上使用,需要安装gcc(g++), flex, bison, qemu等工具 31 | 32 | ```bash 33 | # 下载代码 34 | git clone https://github.com/MilkyBoat/compilor_experiment.git 35 | # 进入项目目录,lab6是最终成型的编译器前端 36 | cd compilor_experiment/lab6 37 | # 用gcc编译器编译编译器[\doge] 38 | make 39 | # main.out是得到的编译器,默认编译输出到命令行,使用>来重定向到汇编文件 40 | ./main.out c语言代码文件名 > result.s 41 | # 得到的是32位AT&T格式的x86汇编,使用gcc进行后端编译的时候要加-m32选项 42 | gcc result.s -m32 -o result.out 43 | # 使用qemu模拟运行32位程序 44 | qemu-i386 result.out 45 | ``` 46 | 47 | 在`./lab6/test`目录下有大量的测试样例可供运行,lab6内置了由助教提供的测试程序,该测试程序代码库链接:[https://github.com/gilsaia/lab6_test](https://github.com/gilsaia/lab6_test) ,在`lab6`目录下使用`make run`指令可以查看所有测试样例的测试结果 48 | 49 | # 编译器支持的语法说明 50 | 这个编译器支持如下的语法: 51 | 52 | ### 1. 类型 53 | 54 | - 基本数据类型:`int`、`char`、`bool`、`void`。 55 | 56 | 基本数据类型可以在变量声明与函数声明中使用,可以作为函数返回值或者函数参数类型。为简单起见,目前所有基本数据类型都占用4字节。 57 | 58 | - 特殊数据类型:`string`、`notype`。 59 | 60 | 特殊数据类型不可以被写入代码。 61 | 62 | `string`类型只会自动成为任何常量字符串(写入代码的)的数据类型,且`string`不能参与运算,不能被修改,目前唯一能够使用字符串的地方是基本输入输出语句(`printf` `scanf`)。 63 | 64 | `void`仅可以在函数类型中使用,虽然可以将其声明为变量类型,但是这会使得该变量不能被除基本输入输出语句(`printf` `scanf`)以外的任何函数或运算符使用。 65 | 66 | `notype`是所有statement语句的类型,仅在编译器内部使用 67 | 68 | ```c 69 | int a = 9; 70 | char b = '\n'; 71 | bool c = true; 72 | void func() { 73 | ; 74 | } 75 | printf("%d\n", a); 76 | ``` 77 | 78 | - 指针:任何基本数据类型可以通过在声明时加上`*`或`&`来使之成为指针型变量,该变量将一定只占用4字节。不过目前非`int`型指针不能进行加减等运算。 79 | ```c 80 | int *a = 0x0; 81 | int *b = 0x4; 82 | a++; 83 | a == b; // 该表达式为真 84 | ``` 85 | 86 | - 数组:任意维度数组。 87 | 88 | 声明时的类型可以为基本数据类型或基本类型指针,必须在声明时用字面常数指定每一个维度的尺寸,如`int a[3][4][5]`。声明时可以初始化,但是只能使用一维大括号顺序初始化,如果初始化值数量与数组定义不吻合,将优先从前向后赋值,局部变量中数组声明时,初始化值溢出的部分可能导致严重的运行时错误(此处未进行类型检查)。如`int a[2][3] = {1, 2, 3, 4, 5, 6, 7}`,如果是全局变量声明,`7` 将被舍弃,如果是局部变量声明,初始化值 `7`,将会溢出到内存堆栈原有内存空间的外部,可能产生未知错误。 89 | 90 | 访问时可以使用任意`int`型表达式作为下标参与运算,但是,如果运算维度和定义维度不同,返回的将不是指针而是后续维度下标为`0`的数值,如对于三维数组 `a`,有 `a[2][1] == a[2][1][0]`。 91 | 92 | ```c 93 | // 正确的声明与使用 94 | int a[2][3][4]; 95 | a[1][2][1] = 4; 96 | int x = a[1][2][2]; 97 | // 以下代码会导致b被赋值为a[0][0][0] 98 | int* b = a; 99 | // 正确的声明时初始化 100 | int c[2][3] = {1, 2, 3, 4, 5, 6}; 101 | // 以下的初始化会产生语法错误(不能使用多维初始化) 102 | // int errArrayInit[2][3] = {{1, 2, 3}, {4, 5, 6}}; 103 | // 以下两句初始化语句等价(默认初始化到0) 104 | int d[2][3] = {1, 2, 3}; 105 | int e[2][3] = {1, 2, 3, 0, 0, 0}; 106 | // 以下两句初始化语句等价(全局变量声明中过多的初始值会被丢弃) 107 | int globalArray1[2][3] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; 108 | int globalArray2[2][3] = {1, 2, 3, 4, 5, 6}; 109 | // 以下语句将会导致未知错误,且编译器无法检查出来 110 | int main() { 111 | // 4 和 5将会溢出到栈上,修改附近内存值,直到产生segment fault 112 | int localArray[3] = {1, 2, 3, 4, 5}; 113 | return 0; 114 | } 115 | ``` 116 | 117 | - 函数:函数只能定义,不能声明。 118 | 119 | ```c 120 | // 正确的定义 121 | int func1(int a, int* b) { 122 | return (a + *b); 123 | } 124 | // 不支持函数声明语句,这会产生语法错误 125 | // int func2(int a); 126 | int main() { 127 | int* a = 0x0; 128 | func1(1, a); 129 | int b = func3(3); 130 | return 0; 131 | } 132 | // 主函数之后定义的函数也能正常使用 133 | int func3(int a) { 134 | return a + 1; 135 | } 136 | ``` 137 | 138 | ### 2. 运算符 139 | 140 | 这里列出了所有支持的运算符 141 | 142 | | 运算符 | 名称 | 说明 | 143 | | --- | --- | --- | 144 | | `+` | 加 | [1] | 145 | | `+` | 正号 | [1] | 146 | | `-` | 减 | [1] | 147 | | `-` | 负号 | [1] | 148 | | `*` | 乘 | [1] | 149 | | `/` | 除 | [1] | 150 | | `%` | 取模 | [1] | 151 | | `=` | 赋值 | [3] | 152 | | `+=` | 加等于 | [1] | 153 | | `-=` | 减等于 | [1] | 154 | | `*=` | 乘等于 | [1] | 155 | | `/=` | 除等于 | [1] | 156 | | `++` | 自增 | [1] | 157 | | `--` | 自减 | [1] | 158 | | `&&` | 逻辑与 | [2] | 159 | | `\|\|` | 逻辑或 | [2] | 160 | | `!` | 逻辑非 | [2] | 161 | | `==` | 判断相等 | [3] | 162 | | `!=` | 不等于 | [3] | 163 | | `>` | 大于 | [1] | 164 | | `<` | 小于 | [1] | 165 | | `>=` | 大于等于 | [1] | 166 | | `<=` | 小于等于 | [1] | 167 | 168 | - [1] 仅用于`int`类型或`int`指针之间 169 | - [2] 仅用于`bool`类型或逻辑表达式之间 170 | - [3] 任意类型,但是左右操作数类型必须一致 171 | 172 | 注意: 本编译器中,指针的`&`与`*`不是运算符,它们只能直接作用在标识符上而不能作用在表达式上,如 173 | ``` c 174 | // 正确示例 175 | int a = 9; 176 | int* b = &a; 177 | printf('%d\n', *b); 178 | 179 | // 错误示例 180 | int a = 9; 181 | int* b = &(a + 1); 182 | printf('%d\n', *b); 183 | ``` 184 | 185 | 后者将会导致语法错误 186 | 187 | ### 3. 流程控制语句 188 | 189 | 以下为支持的流程控制语句 190 | 191 | `condition`为逻辑表达式,也可以是数值表达式,编译器将自动强制类型转换(这是整个编译器唯一可以的强制类型转换) 192 | 193 | `block`为语句块,可以是单个`statement`(不加大括号) 194 | 195 | `expression`为表达式,可以是任何变量、常量、字面常量、运算语句,不限类型 196 | 197 | - `if` (`condition`) `block` 198 | 199 | - `if` (`condition`) `block` `else` `block` 200 | 201 | - `while` (`condition`) `block` 202 | 203 | - `for` (`expression`; `condition`; `expression`) `block` 204 | 205 | - `for` (`variable` `declaration`; `condition`; `expression`) `block` 206 | 207 | # 用到的工具与大致原理 208 | 209 | 1. 词法分析:`lex`,这里使用的是linux上的`flex` 210 | 211 | 这一过程完成了单词`token`的提取。如果代码中有八进制或十六进制字面常量,这一步将全部转换到十进制 212 | 213 | 2. 语法分析:`yacc`,这里使用的是linux上的`bison` 214 | 215 | 这一过程先使用`bison`构造`LALR`分析表,然后表驱动翻译c代码到抽象语法树。在`./lab6/src/type.h`中,解除第17行`#define AST`的注释,将能够在最终生成的汇编代码开头看到语法树的样子。 216 | 217 | 此外,这一步还完成了标识符作用域的分析,将检查标识符重定义和未定义等错误。 218 | 219 | 3. 语义分析:`./lab6/src/tree.cpp`中的`typecheck()`函数 220 | 221 | 主要是重新遍历语法树,进行类型检查和检查诸如`break`、`continue`是否处于循环体内部等语法分析难以检查的语法错误。 222 | 223 | 4. 中间代码生成:`./lab6/src/tree.cpp`中的`genCode()`函数 224 | 225 | 这里递归的将语法树翻译到`AT&T`格式的`32`位`x86`架构汇编代码。 226 | 227 | 5. 机器码生成:`gcc` :dog: 228 | 229 | 是的,这个项目只是前端,并没有完整的实现一个编译器,最后的机器码生成仍然需要GCC编译器。 230 | 231 | 6. 运行程序 `qmue` 232 | 233 | 参见`lab6`的`MakeFile`,这个项目生成的可执行文件是32位的,不能直接在64位上运行,需要硬件模拟器`qemu`,使用时输入`qemu-i386 ./main.out`即可运行刚刚生成的可执行文件。 234 | 235 | -------------------------------------------------------------------------------- /SysY语言定义.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/SysY语言定义.pdf -------------------------------------------------------------------------------- /SysY运行时库.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/SysY运行时库.pdf -------------------------------------------------------------------------------- /lab1/gcc/hello.c: -------------------------------------------------------------------------------- 1 | #include 2 | void main() { 3 | printf("helloworld!\n"); 4 | } -------------------------------------------------------------------------------- /lab1/gcc/help: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab1/gcc/help -------------------------------------------------------------------------------- /lab1/gcc/makefile: -------------------------------------------------------------------------------- 1 | .PHONY: pre, ast, ir, asm, obj, exe, antiobj, antiexe 2 | 3 | default: 4 | cc -O0 -o simple.out simple.c 5 | 6 | pre: 7 | cc -E -o simple.i simple.c 8 | 9 | # 生成`simple.c.003t.original` 10 | ast: 11 | cc -fdump-tree-original-raw simple.c 12 | 13 | # 会生成多个阶段的文件 (.dot),可以被 graphviz 可视化,可以直接使用 vscode 插件 14 | # (Graphviz (dot) language support for Visual Studio Code)。 15 | # 此时的可读性还很强。`simple.c.011t.cfg.dot` 16 | cfg: 17 | cc -O0 -fdump-tree-all-graph simple.c 18 | 19 | # 此时可读性不好,简要了解各阶段更迭过程即可。 20 | ir: 21 | cc -O0 -fdump-rtl-all-graph simple.c 22 | 23 | asm: 24 | cc -O0 -S -masm=att -o simple.S simple.i 25 | 26 | obj: 27 | cc -O0 -c -o simple.o simple.S 28 | 29 | antiobj: 30 | objdump -d simple.o > simple-anti-obj.S 31 | nm simple.o > simple-nm-obj.txt 32 | 33 | exe: 34 | cc -O0 -o simple.out simple.o 35 | 36 | antiexe: 37 | objdump -d simple.out > simple-anti-exe.S 38 | nm simple.out > simple-nm-exe.txt 39 | 40 | clean: 41 | -rm *.c.* 42 | 43 | clean-all: 44 | -rm *.c.* *.o *.S *.i *.dot *.out *.txt 45 | -------------------------------------------------------------------------------- /lab1/gcc/p1.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | int i, n, f; 6 | 7 | scanf("%d", &n); 8 | i = 2; 9 | f = 1; 10 | while (i <= n) 11 | { 12 | f = f * i; 13 | i = i + 1; 14 | } 15 | printf("%d\n", f); 16 | } 17 | -------------------------------------------------------------------------------- /lab1/gcc/p2.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | int a, b, i, t, n; 6 | 7 | a = 0; 8 | b = 1; 9 | i = 1; 10 | scanf("%d", &n); 11 | printf("%d ", b); 12 | while (i < n) 13 | { 14 | t = b; 15 | b = a + b; 16 | printf("%d ", b); 17 | a = t; 18 | i = i + 1; 19 | } 20 | printf("\n"); 21 | } 22 | -------------------------------------------------------------------------------- /lab1/gcc/simple: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab1/gcc/simple -------------------------------------------------------------------------------- /lab1/gcc/simple.c: -------------------------------------------------------------------------------- 1 | void main() { 2 | int n = 100; 3 | while(n > 0) 4 | n--; 5 | } 6 | -------------------------------------------------------------------------------- /lab1/lab1_2020.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab1/lab1_2020.pdf -------------------------------------------------------------------------------- /lab1/预备工作1 - 了解你的编译器.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab1/预备工作1 - 了解你的编译器.pptx -------------------------------------------------------------------------------- /lab1/预备工作实验报告.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab1/预备工作实验报告.docx -------------------------------------------------------------------------------- /lab1/预备工作实验报告.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab1/预备工作实验报告.pdf -------------------------------------------------------------------------------- /lab2/asm/main.S: -------------------------------------------------------------------------------- 1 | .file "main.c" 2 | .text 3 | .globl x 4 | .data 5 | .align 4 6 | .type x, @object 7 | .size x, 4 8 | x: 9 | .long 1 10 | .globl n 11 | .bss 12 | .align 4 13 | .type n, @object 14 | .size n, 4 15 | n: 16 | .zero 4 17 | .section .rodata 18 | .LC0: 19 | .string "%d" 20 | .LC1: 21 | .string "%d\n" 22 | .text 23 | .globl main 24 | .type main, @function 25 | main: 26 | .LFB0: 27 | .cfi_startproc 28 | leal 4(%esp), %ecx 29 | .cfi_def_cfa 1, 0 30 | andl $-16, %esp 31 | pushl -4(%ecx) 32 | pushl %ebp 33 | .cfi_escape 0x10,0x5,0x2,0x75,0 34 | movl %esp, %ebp 35 | pushl %ebx 36 | pushl %ecx 37 | .cfi_escape 0xf,0x3,0x75,0x78,0x6 38 | .cfi_escape 0x10,0x3,0x2,0x75,0x7c 39 | call __x86.get_pc_thunk.bx 40 | addl $_GLOBAL_OFFSET_TABLE_, %ebx 41 | subl $8, %esp 42 | leal n@GOTOFF(%ebx), %eax 43 | pushl %eax 44 | leal .LC0@GOTOFF(%ebx), %eax 45 | pushl %eax 46 | call __isoc99_scanf@PLT 47 | addl $16, %esp 48 | jmp .L2 49 | .L3: 50 | movl n@GOTOFF(%ebx), %eax 51 | leal -1(%eax), %edx 52 | movl %edx, n@GOTOFF(%ebx) 53 | movl x@GOTOFF(%ebx), %edx 54 | imull %edx, %eax 55 | movl %eax, x@GOTOFF(%ebx) 56 | .L2: 57 | movl n@GOTOFF(%ebx), %eax 58 | testl %eax, %eax 59 | jg .L3 60 | movl x@GOTOFF(%ebx), %eax 61 | subl $8, %esp 62 | pushl %eax 63 | leal .LC1@GOTOFF(%ebx), %eax 64 | pushl %eax 65 | call printf@PLT 66 | addl $16, %esp 67 | nop 68 | leal -8(%ebp), %esp 69 | popl %ecx 70 | .cfi_restore 1 71 | .cfi_def_cfa 1, 0 72 | popl %ebx 73 | .cfi_restore 3 74 | popl %ebp 75 | .cfi_restore 5 76 | leal -4(%ecx), %esp 77 | .cfi_def_cfa 4, 4 78 | ret 79 | .cfi_endproc 80 | .LFE0: 81 | .size main, .-main 82 | .section .text.__x86.get_pc_thunk.bx,"axG",@progbits,__x86.get_pc_thunk.bx,comdat 83 | .globl __x86.get_pc_thunk.bx 84 | .hidden __x86.get_pc_thunk.bx 85 | .type __x86.get_pc_thunk.bx, @function 86 | __x86.get_pc_thunk.bx: 87 | .LFB1: 88 | .cfi_startproc 89 | movl (%esp), %ebx 90 | ret 91 | .cfi_endproc 92 | .LFE1: 93 | .ident "GCC: (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0" 94 | .section .note.GNU-stack,"",@progbits 95 | -------------------------------------------------------------------------------- /lab2/asm/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | int x = 1; 3 | int n = 0; 4 | int mult(int a, int b){ 5 | return a * b; 6 | } 7 | void main(){ 8 | scanf("%d", &n); 9 | while(n>0){ 10 | x = mult(x, n); 11 | n--; 12 | } 13 | printf("%d\n", x); 14 | } 15 | -------------------------------------------------------------------------------- /lab2/asm/makefile: -------------------------------------------------------------------------------- 1 | .PHONY: asm, my, clean 2 | 3 | default: 4 | cc -O0 -m32 -o main.out main.c 5 | 6 | asm: 7 | cc -O0 -m32 -S -o main.S main.c 8 | 9 | my: 10 | cc -O0 -m32-march=i386 -o mymain.out mymain.S 11 | qemu-i386 mymain.out 12 | 13 | clean: 14 | -rm *.out 15 | -------------------------------------------------------------------------------- /lab2/asm/mymain.S: -------------------------------------------------------------------------------- 1 | # 函数 mult 2 | .text 3 | .globl mult 4 | .type mult, @function 5 | mult: 6 | movl 4(%esp), %eax 7 | imull 8(%esp), %eax 8 | ret 9 | 10 | # 全局变量 11 | .globl x 12 | .data 13 | .align 4 14 | .type x, @object 15 | .size x, 4 16 | x: 17 | .long 1 18 | .globl n 19 | .bss 20 | .align 4 21 | .type n, @object 22 | .size n, 4 23 | n: 24 | .zero 4 25 | 26 | # 常量 27 | .section .rodata 28 | STR0: 29 | .string "%d" 30 | STR1: 31 | .string "%d\n" 32 | 33 | # 主函数 34 | .text 35 | .globl main 36 | .type main, @function 37 | main: 38 | # scanf("%d", &n); 39 | pushl $n 40 | pushl $STR0 41 | call scanf 42 | addl $8, %esp 43 | L1: 44 | # end if n<=0 45 | movl n, %eax 46 | cmpl $0, %eax 47 | jle L2 48 | # calculate x * n 49 | pushl x 50 | pushl n 51 | call mult 52 | addl $8, %esp 53 | # x = x * n; 54 | movl %eax, x 55 | # n--; 56 | subl $1, n 57 | jmp L1 58 | L2: 59 | # printf("%d\n", x); 60 | pushl x 61 | pushl $STR1 62 | call printf 63 | addl $8, %esp 64 | # return 0; 65 | xorl %eax, %eax 66 | ret 67 | # 可执行堆栈段 68 | .section .note.GNU-stack,"",@progbits 69 | -------------------------------------------------------------------------------- /lab2/lab2_2020.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab2/lab2_2020.pdf -------------------------------------------------------------------------------- /lab2/预备工作2 - 汇编编程.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab2/预备工作2 - 汇编编程.pptx -------------------------------------------------------------------------------- /lab2/预备工作实验报告.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab2/预备工作实验报告.docx -------------------------------------------------------------------------------- /lab2/预备工作实验报告.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab2/预备工作实验报告.pdf -------------------------------------------------------------------------------- /lab3/expr.tab.h: -------------------------------------------------------------------------------- 1 | /* A Bison parser, made by GNU Bison 3.0.4. */ 2 | 3 | /* Bison interface for Yacc-like parsers in C 4 | 5 | Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . */ 19 | 20 | /* As a special exception, you may create a larger work that contains 21 | part or all of the Bison parser skeleton and distribute that work 22 | under terms of your choice, so long as that work isn't itself a 23 | parser generator using the skeleton or a modified version thereof 24 | as a parser skeleton. Alternatively, if you modify or redistribute 25 | the parser skeleton itself, you may (at your option) remove this 26 | special exception, which will cause the skeleton and the resulting 27 | Bison output files to be licensed under the GNU General Public 28 | License without this special exception. 29 | 30 | This special exception was added by the Free Software Foundation in 31 | version 2.2 of Bison. */ 32 | 33 | #ifndef YY_YY_EXPR_TAB_H_INCLUDED 34 | # define YY_YY_EXPR_TAB_H_INCLUDED 35 | /* Debug traces. */ 36 | #ifndef YYDEBUG 37 | # define YYDEBUG 0 38 | #endif 39 | #if YYDEBUG 40 | extern int yydebug; 41 | #endif 42 | 43 | /* Token type. */ 44 | #ifndef YYTOKENTYPE 45 | # define YYTOKENTYPE 46 | enum yytokentype 47 | { 48 | NUMBER = 258, 49 | ID = 259, 50 | ADD = 260, 51 | MINUS = 261, 52 | MUL = 262, 53 | DIV = 263, 54 | UMINUS = 264 55 | }; 56 | #endif 57 | 58 | /* Value type. */ 59 | #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED 60 | typedef int YYSTYPE; 61 | # define YYSTYPE_IS_TRIVIAL 1 62 | # define YYSTYPE_IS_DECLARED 1 63 | #endif 64 | 65 | 66 | extern YYSTYPE yylval; 67 | 68 | int yyparse (void); 69 | 70 | #endif /* !YY_YY_EXPR_TAB_H_INCLUDED */ 71 | -------------------------------------------------------------------------------- /lab3/expr.y: -------------------------------------------------------------------------------- 1 | %{ 2 | #include 3 | #include 4 | #include 5 | #ifndef YYSTYPE 6 | #define YYSTYPE char* 7 | #endif 8 | char idStr [50]; 9 | char numStr[50]; 10 | int yylex (); 11 | extern int yyparse(); 12 | FILE* yyin; 13 | void yyerror(const char* s ); 14 | %} 15 | 16 | %token NUMBER 17 | %token ID 18 | %token ADD 19 | %token MINUS 20 | %token MUL 21 | %token DIV 22 | %left ADD MINUS 23 | %left MUL DIV 24 | %right UMINUS 25 | 26 | 27 | %% 28 | 29 | 30 | lines : lines expr '\n' { printf("%s\n", $2); } 31 | | lines '\n' 32 | | 33 | ; 34 | 35 | expr : expr ADD expr { $$ = (char*)malloc(strlen($1) + strlen($3) + 1); strcpy($$,$1); strcat($$,$3); strcat($$,"+"); } 36 | | expr MINUS expr { $$ = (char*)malloc(strlen($1) + strlen($3) + 1); strcpy($$,$1); strcat($$,$3); strcat($$,"-"); } 37 | | expr MUL expr { $$ = (char*)malloc(strlen($1) + strlen($3) + 1); strcpy($$,$1); strcat($$,$3); strcat($$,"*"); } 38 | | expr DIV expr { $$ = (char*)malloc(strlen($1) + strlen($3) + 1); strcpy($$,$1); strcat($$,$3); strcat($$,"/"); } 39 | | '(' expr')' { (char*)malloc(strlen($2) + 1); strcpy($$, $2); strcat($$," ");} 40 | | NUMBER { $$ = (char*)malloc(strlen($1) + 1); strcpy($$, $1); strcat($$," ");} 41 | | ID { $$ = (char*)malloc(strlen($1) + 1); strcpy($$, $1); strcat($$," ");} 42 | ; 43 | 44 | 45 | %% 46 | 47 | 48 | // programs section 49 | int yylex() 50 | { 51 | // place your token retrieving code here 52 | char t; 53 | while (1) { 54 | t = getchar (); 55 | if (t == ' ' || t== '\t') 56 | ; 57 | else if (( t >= '0' && t <= '9' )) { 58 | int ti = 0; 59 | while (( t >= '0' && t <= '9' )) { 60 | numStr[ti] = t; 61 | t = getchar(); 62 | ti++; 63 | } 64 | numStr[ti] = '\0'; 65 | yylval = numStr; 66 | ungetc(t , stdin); 67 | return NUMBER; 68 | } 69 | else if ((t>='a' && t<='z') || (t>='A' && t<='Z') || (t=='_')) { 70 | int ti=0; 71 | while ((t>='a' && t<='z') ||(t>='A' && t<='Z') || (t=='_') || (t>='0' && t<='9')) { 72 | idStr[ti]=t; 73 | ti++; 74 | t = getchar(); 75 | } 76 | idStr[ti]='\0'; 77 | yylval = idStr; 78 | ungetc(t, stdin); 79 | return ID; 80 | } 81 | else if (t=='+'){ 82 | return ADD; 83 | } 84 | else if (t=='-'){ 85 | return MINUS; 86 | } 87 | else if (t=='*'){ 88 | return MUL; 89 | } 90 | else if (t=='/'){ 91 | return DIV; 92 | } 93 | else { 94 | return t; 95 | } 96 | } 97 | } 98 | 99 | int main(void) 100 | { 101 | yyin = stdin; 102 | do { 103 | yyparse(); 104 | } while (!feof(yyin)); 105 | return 0; 106 | } 107 | 108 | void yyerror(const char* s) { 109 | fprintf (stderr , "Parse error : %s\n", s ); 110 | exit (1); 111 | } 112 | -------------------------------------------------------------------------------- /lab3/lab3_2020.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab3/lab3_2020.pdf -------------------------------------------------------------------------------- /lab3/makefile: -------------------------------------------------------------------------------- 1 | 2 | operator: 3 | bison -d operator.y 4 | gcc -o operator.out operator.tab.c 5 | 6 | expr: 7 | bison -d expr.y 8 | gcc -o expr.out expr.tab.c 9 | 10 | clean: 11 | -rm -f *.c *.h *.out operator expr 12 | -------------------------------------------------------------------------------- /lab3/operator.tab.h: -------------------------------------------------------------------------------- 1 | /* A Bison parser, made by GNU Bison 3.0.4. */ 2 | 3 | /* Bison interface for Yacc-like parsers in C 4 | 5 | Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . */ 19 | 20 | /* As a special exception, you may create a larger work that contains 21 | part or all of the Bison parser skeleton and distribute that work 22 | under terms of your choice, so long as that work isn't itself a 23 | parser generator using the skeleton or a modified version thereof 24 | as a parser skeleton. Alternatively, if you modify or redistribute 25 | the parser skeleton itself, you may (at your option) remove this 26 | special exception, which will cause the skeleton and the resulting 27 | Bison output files to be licensed under the GNU General Public 28 | License without this special exception. 29 | 30 | This special exception was added by the Free Software Foundation in 31 | version 2.2 of Bison. */ 32 | 33 | #ifndef YY_YY_OPERATOR_TAB_H_INCLUDED 34 | # define YY_YY_OPERATOR_TAB_H_INCLUDED 35 | /* Debug traces. */ 36 | #ifndef YYDEBUG 37 | # define YYDEBUG 0 38 | #endif 39 | #if YYDEBUG 40 | extern int yydebug; 41 | #endif 42 | 43 | /* Token type. */ 44 | #ifndef YYTOKENTYPE 45 | # define YYTOKENTYPE 46 | enum yytokentype 47 | { 48 | ADD = 258, 49 | SUB = 259, 50 | MUL = 260, 51 | DIV = 261, 52 | NUM = 262, 53 | UMINUS = 263 54 | }; 55 | #endif 56 | 57 | /* Value type. */ 58 | #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED 59 | typedef int YYSTYPE; 60 | # define YYSTYPE_IS_TRIVIAL 1 61 | # define YYSTYPE_IS_DECLARED 1 62 | #endif 63 | 64 | 65 | extern YYSTYPE yylval; 66 | 67 | int yyparse (void); 68 | 69 | #endif /* !YY_YY_OPERATOR_TAB_H_INCLUDED */ 70 | -------------------------------------------------------------------------------- /lab3/operator.y: -------------------------------------------------------------------------------- 1 | %{ 2 | #include 3 | #include 4 | #ifndef YYSTYPE 5 | #define YYSTYPE double 6 | #endif 7 | int yylex (); 8 | extern int yyparse(); 9 | FILE* yyin; 10 | void yyerror(const char* s); 11 | %} 12 | 13 | %token ADD 14 | %token SUB 15 | %token MUL 16 | %token DIV 17 | %token NUM 18 | 19 | %left ADD SUB 20 | %left MUL DIV 21 | 22 | %right UMINUS 23 | 24 | %% 25 | 26 | 27 | lines : lines expr ';' { printf("%f\n", $2); } 28 | | lines ';' 29 | | 30 | ; 31 | 32 | expr : expr ADD expr { $$ = $1 + $3; } 33 | | expr SUB expr { $$ = $1 - $3; } 34 | | expr MUL expr { $$ = $1 * $3; } 35 | | expr DIV expr { $$ = $1 / $3; } 36 | | '(' expr')' { $$ = $2; } 37 | | SUB expr %prec UMINUS { $$ = -$2; } 38 | | NUM { $$ = $1; } 39 | ; 40 | 41 | 42 | %% 43 | 44 | // programs section 45 | 46 | int yylex() 47 | { 48 | // place your token retrieving code here 49 | 50 | // return getchar(); 51 | 52 | char t; 53 | 54 | t = getchar(); 55 | switch (t) { 56 | case '+': 57 | return ADD; 58 | case '-': 59 | return SUB; 60 | case '*': 61 | return MUL; 62 | case '/': 63 | return DIV; 64 | default: 65 | ungetc(t , stdin); 66 | } 67 | 68 | while (1) { 69 | t = getchar(); 70 | if (t == ' ' || t == '\t' || t == '\n'){ 71 | //do nothing 72 | } else if (isdigit(t)) { 73 | yylval = 0; 74 | while (isdigit(t)) { 75 | yylval = yylval * 10 + t - '0'; 76 | t = getchar(); 77 | } 78 | ungetc(t , stdin); 79 | return NUM; 80 | } else { 81 | return t; 82 | } 83 | } 84 | } 85 | 86 | int main(void) 87 | { 88 | yyin = stdin ; 89 | do { 90 | yyparse(); 91 | } while (!feof(yyin)); 92 | return 0; 93 | } 94 | 95 | void yyerror(const char* s) 96 | { 97 | fprintf (stderr , "Parse error : %s\n", s ); 98 | exit (1); 99 | } 100 | -------------------------------------------------------------------------------- /lab3/预备工作3 - 熟悉辅助工具.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab3/预备工作3 - 熟悉辅助工具.pptx -------------------------------------------------------------------------------- /lab4/lab4_2020.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab4/lab4_2020.pdf -------------------------------------------------------------------------------- /lab4/makefile: -------------------------------------------------------------------------------- 1 | .PHONY: lc, lcc, lcfp, lccfp, lcfp, lccfp, clean 2 | lc: 3 | flex sysy.l 4 | gcc lex.yy.c -o lc.out 5 | ./lc.out 6 | lcc: 7 | flex -+ sysycc.l 8 | g++ lex.yy.cc -o lcc.out 9 | ./lcc.out 10 | lcf: 11 | flex sysy.l 12 | gcc lex.yy.c -o lcf.out 13 | ./lcf.out 4 | } 5 | %{ 6 | int id_num = 0; 7 | char id_list[100][20]; 8 | %} 9 | 10 | commentbegin "/*" 11 | commentelement .|\n 12 | commentend "*/" 13 | %x COMMENT 14 | commentlinebegin "//" 15 | commentlineelement . 16 | commentlineend \n 17 | %x COMMENTLINE 18 | 19 | LPAREN "(" 20 | RPAREN ")" 21 | LBRACE "{" 22 | RBRACE "}" 23 | SEMICOLON ";" 24 | 25 | EQ "==" 26 | GRAEQ ">=" 27 | LESEQ "<=" 28 | NEQ "!=" 29 | ASSIGN "=" 30 | PLUSASSIGN "+=" 31 | MINUSASSIGN "-=" 32 | MULASSIGN "*=" 33 | DIVASSIGN "/=" 34 | GRA ">" 35 | LES "<" 36 | PLUS "+" 37 | MINUS "-" 38 | MUL "*" 39 | DIV "/" 40 | MOD "%" 41 | AND "&&" 42 | OR "||" 43 | NOT "!" 44 | 45 | CONST "const" 46 | VOID "void" 47 | IF "if" 48 | ELSE "else" 49 | WHILE "while" 50 | BREAK "break" 51 | CONTINUE "continue" 52 | RETURN "return" 53 | INT "int" 54 | 55 | OCTNUMBER 0[0-7]+ 56 | DECNUMBER -?[0-9]+ 57 | HEXNUMBER 0[Xx][0-9a-fA-F]+ 58 | ID [a-zA-Z_][a-zA-Z0-9_]* 59 | 60 | FORMATCHAR [\r\n\t ]+ 61 | 62 | %% 63 | 64 | {FORMATCHAR} {;} 65 | {LPAREN} {fprintf(yyout, "%12s%8s\n", "LPAREN", yytext);} 66 | {RPAREN} {fprintf(yyout, "%12s%8s\n", "RPAREN", yytext);} 67 | {LBRACE} {fprintf(yyout, "%12s%8s\n", "LBRACE", yytext);} 68 | {RBRACE} {fprintf(yyout, "%12s%8s\n", "RBRACE", yytext);} 69 | {SEMICOLON} {fprintf(yyout, "%12s%8s\n", "SEMICOLON", yytext);} 70 | 71 | {ASSIGN} {fprintf(yyout, "%12s%8s\n", "ASSIGN", yytext);} 72 | {PLUSASSIGN} {fprintf(yyout, "%12s%8s\n", "PLUSASSIGN", yytext);} 73 | {MINUSASSIGN} {fprintf(yyout, "%12s%8s\n", "MINUSASSIGN", yytext);} 74 | {MULASSIGN} {fprintf(yyout, "%12s%8s\n", "MULASSIGN", yytext);} 75 | {DIVASSIGN} {fprintf(yyout, "%12s%8s\n", "DIVASSIGN", yytext);} 76 | {EQ} {fprintf(yyout, "%12s%8s\n", "EQ", yytext);} 77 | {NEQ} {fprintf(yyout, "%12s%8s\n", "NEQ", yytext);} 78 | {GRA} {fprintf(yyout, "%12s%8s\n", "GRA", yytext);} 79 | {LES} {fprintf(yyout, "%12s%8s\n", "LES", yytext);} 80 | {GRAEQ} {fprintf(yyout, "%12s%8s\n", "GRAEQ", yytext);} 81 | {LESEQ} {fprintf(yyout, "%12s%8s\n", "LESEQ", yytext);} 82 | {PLUS} {fprintf(yyout, "%12s%8s\n", "PLUS", yytext);} 83 | {MINUS} {fprintf(yyout, "%12s%8s\n", "MINUS", yytext);} 84 | {MUL} {fprintf(yyout, "%12s%8s\n", "MUL", yytext);} 85 | {DIV} {fprintf(yyout, "%12s%8s\n", "DIV", yytext);} 86 | {MOD} {fprintf(yyout, "%12s%8s\n", "MOD", yytext);} 87 | {AND} {fprintf(yyout, "%12s%8s\n", "AND", yytext);} 88 | {OR} {fprintf(yyout, "%12s%8s\n", "OR", yytext);} 89 | {NOT} {fprintf(yyout, "%12s%8s\n", "NOT", yytext);} 90 | 91 | {CONST} {fprintf(yyout, "%12s%8s\n", "CONST", yytext);} 92 | {VOID} {fprintf(yyout, "%12s%8s\n", "VOID", yytext);} 93 | {IF} {fprintf(yyout, "%12s%8s\n", "IF", yytext);} 94 | {ELSE} {fprintf(yyout, "%12s%8s\n", "ELSE", yytext);} 95 | {WHILE} {fprintf(yyout, "%12s%8s\n", "WHILE", yytext);} 96 | {BREAK} {fprintf(yyout, "%12s%8s\n", "BREAK", yytext);} 97 | {CONTINUE} {fprintf(yyout, "%12s%8s\n", "CONTINUE", yytext);} 98 | {RETURN} {fprintf(yyout, "%12s%8s\n", "RETURN", yytext);} 99 | 100 | {INT} {fprintf(yyout, "%12s%8s\n", "INT", yytext);} 101 | 102 | {OCTNUMBER} {fprintf(yyout, "%12s%8s%8s\n", "OCTNUMBER", yytext, yytext);} 103 | {DECNUMBER} {fprintf(yyout, "%12s%8s%8s\n", "DECNUMBER", yytext, yytext);} 104 | {HEXNUMBER} {fprintf(yyout, "%12s%8s%8s\n", "HEXNUMBER", yytext, yytext);} 105 | {ID} { 106 | _Bool id_match = 0; 107 | int id = 0; 108 | for (int i = 0; i < id_num; i++) { 109 | if (strcmp(yytext, id_list[i])==0) { 110 | id_match = 1; 111 | id = i; 112 | break; 113 | } 114 | } 115 | if (!id_match) { 116 | id = id_num; 117 | strcpy(id_list[id], yytext); 118 | id_num++; 119 | } 120 | fprintf(yyout, "%12s%8s%8d\n", "ID", yytext, id); 121 | } 122 | 123 | {commentbegin} {BEGIN COMMENT;} 124 | {commentelement} {} 125 | {commentend} {BEGIN INITIAL;} 126 | {commentlinebegin} {BEGIN COMMENTLINE;} 127 | {commentlineelement} {} 128 | {commentlineend} {BEGIN INITIAL;} 129 | 130 | %% 131 | 132 | int main() { 133 | yylex(); 134 | return 0; 135 | } 136 | -------------------------------------------------------------------------------- /lab4/sysy.l.txt: -------------------------------------------------------------------------------- 1 | %option noyywrap 2 | %top{ 3 | #include 4 | } 5 | %{ 6 | int id_num = 0; 7 | char id_list[100][20]; 8 | %} 9 | 10 | commentbegin "/*" 11 | commentelement .|\n 12 | commentend "*/" 13 | %x COMMENT 14 | commentlinebegin "//" 15 | commentlineelement . 16 | commentlineend \n 17 | %x COMMENTLINE 18 | 19 | LPAREN "(" 20 | RPAREN ")" 21 | LBRACE "{" 22 | RBRACE "}" 23 | SEMICOLON ";" 24 | 25 | EQ "==" 26 | GRAEQ ">=" 27 | LESEQ "<=" 28 | NEQ "!=" 29 | ASSIGN "=" 30 | PLUSASSIGN "+=" 31 | MINUSASSIGN "-=" 32 | MULASSIGN "*=" 33 | DIVASSIGN "/=" 34 | GRA ">" 35 | LES "<" 36 | PLUS "+" 37 | MINUS "-" 38 | MUL "*" 39 | DIV "/" 40 | MOD "%" 41 | AND "&&" 42 | OR "||" 43 | NOT "!" 44 | 45 | CONST "const" 46 | VOID "void" 47 | IF "if" 48 | ELSE "else" 49 | WHILE "while" 50 | BREAK "break" 51 | CONTINUE "continue" 52 | RETURN "return" 53 | INT "int" 54 | 55 | OCTNUMBER 0[0-7]+ 56 | DECNUMBER -?[0-9]+ 57 | HEXNUMBER 0[Xx][0-9a-fA-F]+ 58 | ID [a-zA-Z_][a-zA-Z0-9_]* 59 | 60 | FORMATCHAR [\r\n\t ]+ 61 | 62 | %% 63 | 64 | {FORMATCHAR} {;} 65 | {LPAREN} {fprintf(yyout, "%12s%8s\n", "LPAREN", yytext);} 66 | {RPAREN} {fprintf(yyout, "%12s%8s\n", "RPAREN", yytext);} 67 | {LBRACE} {fprintf(yyout, "%12s%8s\n", "LBRACE", yytext);} 68 | {RBRACE} {fprintf(yyout, "%12s%8s\n", "RBRACE", yytext);} 69 | {SEMICOLON} {fprintf(yyout, "%12s%8s\n", "SEMICOLON", yytext);} 70 | 71 | {ASSIGN} {fprintf(yyout, "%12s%8s\n", "ASSIGN", yytext);} 72 | {PLUSASSIGN} {fprintf(yyout, "%12s%8s\n", "PLUSASSIGN", yytext);} 73 | {MINUSASSIGN} {fprintf(yyout, "%12s%8s\n", "MINUSASSIGN", yytext);} 74 | {MULASSIGN} {fprintf(yyout, "%12s%8s\n", "MULASSIGN", yytext);} 75 | {DIVASSIGN} {fprintf(yyout, "%12s%8s\n", "DIVASSIGN", yytext);} 76 | {EQ} {fprintf(yyout, "%12s%8s\n", "EQ", yytext);} 77 | {NEQ} {fprintf(yyout, "%12s%8s\n", "NEQ", yytext);} 78 | {GRA} {fprintf(yyout, "%12s%8s\n", "GRA", yytext);} 79 | {LES} {fprintf(yyout, "%12s%8s\n", "LES", yytext);} 80 | {GRAEQ} {fprintf(yyout, "%12s%8s\n", "GRAEQ", yytext);} 81 | {LESEQ} {fprintf(yyout, "%12s%8s\n", "LESEQ", yytext);} 82 | {PLUS} {fprintf(yyout, "%12s%8s\n", "PLUS", yytext);} 83 | {MINUS} {fprintf(yyout, "%12s%8s\n", "MINUS", yytext);} 84 | {MUL} {fprintf(yyout, "%12s%8s\n", "MUL", yytext);} 85 | {DIV} {fprintf(yyout, "%12s%8s\n", "DIV", yytext);} 86 | {MOD} {fprintf(yyout, "%12s%8s\n", "MOD", yytext);} 87 | {AND} {fprintf(yyout, "%12s%8s\n", "AND", yytext);} 88 | {OR} {fprintf(yyout, "%12s%8s\n", "OR", yytext);} 89 | {NOT} {fprintf(yyout, "%12s%8s\n", "NOT", yytext);} 90 | 91 | {CONST} {fprintf(yyout, "%12s%8s\n", "CONST", yytext);} 92 | {VOID} {fprintf(yyout, "%12s%8s\n", "VOID", yytext);} 93 | {IF} {fprintf(yyout, "%12s%8s\n", "IF", yytext);} 94 | {ELSE} {fprintf(yyout, "%12s%8s\n", "ELSE", yytext);} 95 | {WHILE} {fprintf(yyout, "%12s%8s\n", "WHILE", yytext);} 96 | {BREAK} {fprintf(yyout, "%12s%8s\n", "BREAK", yytext);} 97 | {CONTINUE} {fprintf(yyout, "%12s%8s\n", "CONTINUE", yytext);} 98 | {RETURN} {fprintf(yyout, "%12s%8s\n", "RETURN", yytext);} 99 | 100 | {INT} {fprintf(yyout, "%12s%8s\n", "INT", yytext);} 101 | 102 | {OCTNUMBER} {fprintf(yyout, "%12s%8s%8s\n", "OCTNUMBER", yytext, yytext);} 103 | {DECNUMBER} {fprintf(yyout, "%12s%8s%8s\n", "DECNUMBER", yytext, yytext);} 104 | {HEXNUMBER} {fprintf(yyout, "%12s%8s%8s\n", "HEXNUMBER", yytext, yytext);} 105 | {ID} { 106 | _Bool id_match = 0; 107 | int id = 0; 108 | for (int i = 0; i < id_num; i++) { 109 | if (strcmp(yytext, id_list[i])==0) { 110 | id_match = 1; 111 | id = i; 112 | break; 113 | } 114 | } 115 | if (!id_match) { 116 | id = id_num; 117 | strcpy(id_list[id], yytext); 118 | id_num++; 119 | } 120 | fprintf(yyout, "%12s%8s%8d\n", "ID", yytext, id); 121 | } 122 | 123 | {commentbegin} {BEGIN COMMENT;} 124 | {commentelement} {} 125 | {commentend} {BEGIN INITIAL;} 126 | {commentlinebegin} {BEGIN COMMENTLINE;} 127 | {commentlineelement} {} 128 | {commentlineend} {BEGIN INITIAL;} 129 | 130 | %% 131 | 132 | int main() { 133 | yylex(); 134 | return 0; 135 | } 136 | -------------------------------------------------------------------------------- /lab4/sysycc.l: -------------------------------------------------------------------------------- 1 | %option noyywrap 2 | %top{ 3 | #include 4 | #include 5 | 6 | } 7 | %{ 8 | int chars=0,words=0,lines=0; 9 | %} 10 | 11 | word [a-zA-Z]+ 12 | line \n 13 | char . 14 | 15 | %% 16 | 17 | {word} {words++;chars+=strlen(yytext);} 18 | {line} {lines++;} 19 | {char} {chars++;} 20 | 21 | %% 22 | 23 | int main() { 24 | 25 | yyFlexLexer lexer; 26 | lexer.yylex(); 27 | std::cout< result.txt 32 | 33 | 1: lex yacc main 34 | ./bin/main tests/1.c > result.txt 35 | 36 | 2: lex yacc main 37 | ./bin/main tests/2.c > result.txt 38 | 39 | 3: lex yacc main 40 | ./bin/main tests/3.c > result.txt 41 | -------------------------------------------------------------------------------- /lab5/bin/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab5/bin/.gitkeep -------------------------------------------------------------------------------- /lab5/lab5_2020.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab5/lab5_2020.pdf -------------------------------------------------------------------------------- /lab5/src/common.h: -------------------------------------------------------------------------------- 1 | #ifndef COMMON_H 2 | #define COMMON_H 3 | 4 | #include "pch.h" 5 | using std::cerr; 6 | using std::cout; 7 | using std::endl; 8 | using std::string; 9 | using std::list; 10 | using std::map; 11 | using std::stack; 12 | using std::unordered_map; 13 | #define YYSTYPE TreeNode * 14 | 15 | #include "./tree.h" 16 | #include "./main.tab.h" 17 | 18 | #endif -------------------------------------------------------------------------------- /lab5/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include 3 | 4 | extern TreeNode *root; 5 | extern FILE *yyin; 6 | extern int yyparse(); 7 | 8 | using namespace std; 9 | int main(int argc, char *argv[]) 10 | { 11 | if (argc == 2) 12 | { 13 | FILE *fin = fopen(argv[1], "r"); 14 | if (fin != nullptr) 15 | { 16 | yyin = fin; 17 | } 18 | else 19 | { 20 | cerr << "failed to open file: " << argv[1] << endl; 21 | } 22 | } 23 | yyparse(); 24 | if (root != NULL) 25 | { 26 | root->genNodeId(); 27 | root->printAST(); 28 | } 29 | return 0; 30 | } -------------------------------------------------------------------------------- /lab5/src/main.l: -------------------------------------------------------------------------------- 1 | %option nounput 2 | %{ 3 | #include "common.h" 4 | #include "main.tab.h" // yacc header 5 | 6 | int lineno = 1; 7 | 8 | %} 9 | 10 | BLOCKCOMMENT_BEGIN "/*" 11 | BLOCKCOMMENT_ELE . 12 | BLOCKCOMMENT_LINE \n 13 | BLOCKCOMMENT_END "*/" 14 | %x BLOCKCOMMENT 15 | LINECOMMENT \/\/[^\n]* 16 | EOL (\r\n|\r|\n) 17 | WHILTESPACE [[:blank:]] 18 | 19 | OCTINT 0[0-7]+ 20 | DECINT -?[0-9]+ 21 | HEXINT 0[Xx][0-9a-fA-F]+ 22 | 23 | BOOL (true)|(false) 24 | STRING \"[^(\")]*\" 25 | CHAR \'.?\' 26 | 27 | IDENTIFIER [[:alpha:]_][[:alpha:][:digit:]_]* 28 | 29 | %% 30 | 31 | {BLOCKCOMMENT_BEGIN} {BEGIN BLOCKCOMMENT;} 32 | {BLOCKCOMMENT_ELE} {} 33 | {BLOCKCOMMENT_LINE} {lineno++;} 34 | {BLOCKCOMMENT_END} {BEGIN INITIAL;} 35 | {LINECOMMENT} {} 36 | 37 | "int" return T_INT; 38 | "bool" return T_BOOL; 39 | "char" return T_CHAR; 40 | "void" return T_VOID; 41 | 42 | "&" return ADDR; 43 | 44 | "(" return LPAREN; 45 | ")" return RPAREN; 46 | "[" return LBRACKET; 47 | "]" return RBRACKET; 48 | "{" return LBRACE; 49 | "}" return RBRACE; 50 | "," return COMMA; 51 | ";" return SEMICOLON; 52 | 53 | "==" return EQ; 54 | ">=" return GRAEQ; 55 | "<=" return LESEQ; 56 | "!=" return NEQ; 57 | "=" return ASSIGN; 58 | "+=" return PLUSASSIGN; 59 | "-=" return MINUSASSIGN; 60 | "*=" return MULASSIGN; 61 | "/=" return DIVASSIGN; 62 | "++" return INC; 63 | "--" return DEC; 64 | ">" return GRA; 65 | "<" return LES; 66 | "+" return PLUS; 67 | "-" return MINUS; 68 | "*" return MUL; 69 | "/" return DIV; 70 | "%" return MOD; 71 | "&&" return AND; 72 | "||" return OR; 73 | "!" return NOT; 74 | 75 | "const" return CONST; 76 | "if" return IF_; 77 | "else" return ELSE; 78 | "while" return WHILE_; 79 | "for" return FOR_; 80 | "break" return BREAK; 81 | "continue" return CONTINUE; 82 | "return" return RETURN; 83 | 84 | "printf" { 85 | nodePrintf->var_name = "printf"; 86 | nodePrintf->var_scope = "1"; 87 | yylval = nodePrintf; 88 | return IDENTIFIER; 89 | }; 90 | "scanf" { 91 | nodeScanf->var_name = "scanf"; 92 | nodeScanf->var_scope = "1"; 93 | yylval = nodeScanf; 94 | return IDENTIFIER; 95 | }; 96 | 97 | {BOOL} { 98 | TreeNode* node = new TreeNode(lineno, NODE_CONST); 99 | node->type = TYPE_BOOL; 100 | node->b_val = strcmp("false", yytext); 101 | yylval = node; 102 | return BOOL; 103 | } 104 | 105 | {OCTINT} { 106 | TreeNode* node = new TreeNode(lineno, NODE_CONST); 107 | node->type = TYPE_INT; 108 | node->int_val = strtol(yytext, NULL, 8); 109 | yylval = node; 110 | return INTEGER; 111 | } 112 | 113 | {DECINT} { 114 | TreeNode* node = new TreeNode(lineno, NODE_CONST); 115 | node->type = TYPE_INT; 116 | node->int_val = atoi(yytext); 117 | yylval = node; 118 | return INTEGER; 119 | } 120 | 121 | {HEXINT} { 122 | TreeNode* node = new TreeNode(lineno, NODE_CONST); 123 | node->type = TYPE_INT; 124 | node->int_val = strtol(yytext, NULL, 16); 125 | yylval = node; 126 | return INTEGER; 127 | } 128 | 129 | {CHAR} { 130 | TreeNode* node = new TreeNode(lineno, NODE_CONST); 131 | node->type = TYPE_CHAR; 132 | node->ch_val = yytext[1]; 133 | yylval = node; 134 | return CHAR; 135 | } 136 | 137 | {STRING} { 138 | TreeNode* node = new TreeNode(lineno, NODE_CONST); 139 | node->type = TYPE_STRING; 140 | string text = yytext; 141 | node->str_val = text.substr(1, text.length()-2); 142 | yylval = node; 143 | return STRING; 144 | } 145 | 146 | {IDENTIFIER} { 147 | TreeNode* node = new TreeNode(lineno, NODE_VAR); 148 | node->var_name = string(yytext); 149 | yylval = node; 150 | #ifdef ID_TOKEN_DEBUG 151 | cout << "% get IDENTIFIER :" << yytext < 变量名列表 14 | multimap idNameList = { 15 | {"scanf", "1"}, 16 | {"printf", "1"} 17 | }; 18 | // map <<标识符名称, 作用域>, 结点指针> 变量列表 19 | map, TreeNode*> idList = { 20 | {make_pair("scanf", "1"), nodeScanf}, 21 | {make_pair("printf", "1"), nodePrintf} 22 | }; 23 | 24 | int yylex(); 25 | int yyerror( char const * ); 26 | int scopeCmp(string preScope, string varScope); 27 | void scopePush(); 28 | void scopePop(); 29 | %} 30 | 31 | // 类型 32 | %token T_CHAR T_INT T_STRING T_BOOL T_VOID 33 | 34 | // 取地址运算符 35 | %token ADDR; 36 | 37 | // 赋值运算符 38 | %token ASSIGN PLUSASSIGN MINUSASSIGN MULASSIGN DIVASSIGN 39 | 40 | // 括号分号逗号 41 | %token SEMICOLON COMMA LPAREN RPAREN LBRACE RBRACE LBRACKET RBRACKET 42 | 43 | // 关键字 44 | %token CONST IF_ ELSE WHILE_ FOR_ BREAK CONTINUE RETURN 45 | 46 | // 比较运算符 47 | %token EQ GRAEQ LESEQ NEQ GRA LES 48 | 49 | // 普通计算 50 | %token PLUS MINUS MUL DIV MOD AND OR NOT INC DEC 51 | 52 | // 特殊单词 53 | %token IDENTIFIER INTEGER CHAR BOOL STRING 54 | 55 | %left EQ 56 | 57 | %% 58 | 59 | program 60 | : decl {root->addChild($1);} 61 | | funcDef {root->addChild($1);} 62 | | program decl {root->addChild($2);} 63 | | program funcDef {root->addChild($2);} 64 | ; 65 | 66 | // ---------------- 类型与复合标识符 ------------------- 67 | 68 | basicType 69 | : T_INT {$$ = new TreeNode(lineno, NODE_TYPE); $$->type = TYPE_INT;} 70 | | T_CHAR {$$ = new TreeNode(lineno, NODE_TYPE); $$->type = TYPE_CHAR;} 71 | | T_BOOL {$$ = new TreeNode(lineno, NODE_TYPE); $$->type = TYPE_BOOL;} 72 | | T_VOID {$$ = new TreeNode(lineno, NODE_TYPE); $$->type = TYPE_VOID;} 73 | ; 74 | 75 | // ------ 复合标识符,包含指针与数组,在变量声明外使用 ----- 76 | compIdentifier 77 | : pIdentifier {$$ = $1;} 78 | | arrayIdentifier {$$ = $1;} 79 | ; 80 | 81 | // 指针标识符 82 | pIdentifier 83 | : identifier {$$ = new TreeNode($1);} 84 | | MUL pIdentifier {$$ = $2; $$->pointLevel++;} 85 | | ADDR pIdentifier { 86 | $$ = $2; 87 | $$->pointLevel--; 88 | #ifdef POINT_DEBUG 89 | cout << "$ pIdentifier : " << $$->var_name 90 | << ", pointlevel : " << $$->pointLevel << endl; 91 | #endif 92 | } 93 | ; 94 | 95 | // 数组标识符 96 | arrayIdentifier 97 | : pIdentifier LBRACKET expr RBRACKET { 98 | $$ = new TreeNode(lineno, NODE_OP); 99 | $$->optype = OP_INDEX; 100 | $$->addChild($1); 101 | $$->addChild($3); 102 | } 103 | | arrayIdentifier LBRACKET expr RBRACKET { 104 | $$ = new TreeNode(lineno, NODE_OP); 105 | $$->optype = OP_INDEX; 106 | $$->addChild($1); 107 | $$->addChild($3); 108 | } 109 | ; 110 | 111 | identifier 112 | : IDENTIFIER { 113 | $$ = $1; 114 | int idNameCount = idNameList.count($$->var_name); 115 | int declCnt = 0; 116 | int minDefDis = MAX_SCOPE_STACK; 117 | 118 | // 搜索变量是否已经声明 119 | auto it = idNameList.find($$->var_name); 120 | int resScoptCmp; 121 | while (idNameCount--) { 122 | resScoptCmp = scopeCmp(presentScope, it->second); 123 | if (resScoptCmp >= 0){ 124 | // 寻找最近的定义 125 | if (resScoptCmp < minDefDis) { 126 | minDefDis = resScoptCmp; 127 | $$ = idList[make_pair(it->first, it->second)]; 128 | } 129 | declCnt++; 130 | } 131 | it++; 132 | } 133 | if (declCnt == 0) { 134 | string t = "Undeclared identifier :'" + $1->var_name + "', scope : " + to_string(resScoptCmp); 135 | yyerror(t.c_str()); 136 | } 137 | }; 138 | 139 | // --------- 声明用标识符 ---------- 140 | declCompIdentifier 141 | : pDeclIdentifier {$$ = $1;} 142 | | constArrayIdentifier {$$ = $1;} 143 | ; 144 | 145 | pDeclIdentifier 146 | : declIdentifier {$$ = new TreeNode($1);} 147 | | MUL pDeclIdentifier {$$ = $2; $$->pointLevel++;} 148 | | ADDR pDeclIdentifier {$$ = $2; $$->pointLevel--;} 149 | ; 150 | 151 | // 常量数组标识符(仅供声明使用) 152 | constArrayIdentifier 153 | : pDeclIdentifier LBRACKET INTEGER RBRACKET { 154 | $$ = $1; 155 | $$->type = new Type(VALUE_ARRAY); 156 | $$->type->elementType = $1->type->type; 157 | $$->type->dimSize[$$->type->dim] = $3->int_val; 158 | $$->type->dim++; 159 | } 160 | | constArrayIdentifier LBRACKET INTEGER RBRACKET { 161 | $$ = $1; 162 | $$->type->dimSize[$$->type->dim] = $3->int_val; 163 | $$->type->dim++; 164 | } 165 | ; 166 | 167 | declIdentifier 168 | : IDENTIFIER { 169 | $$ = $1; 170 | $$->var_scope = presentScope; 171 | #ifdef ID_REDUCE_DEBUG 172 | cout<<"$ reduce declIdentifier : "<<$$->var_name<<", at scope :"<var_name, $$->var_scope)) != 0) { 175 | string t = "Redeclared identifier : " + $$->var_name; 176 | yyerror(t.c_str()); 177 | } 178 | idNameList.insert(make_pair($$->var_name, $$->var_scope)); 179 | idList[make_pair($$->var_name, $$->var_scope)] = $$; 180 | } 181 | ; 182 | 183 | // ---------------- 常变量声明 ------------------- 184 | 185 | decl 186 | : constDecl {$$ = $1;} 187 | | varDecl {$$ = $1;} 188 | ; 189 | 190 | constDecl 191 | : CONST basicType constDefs SEMICOLON { 192 | $$ = new TreeNode(lineno, NODE_STMT); 193 | $$->stype = STMT_CONSTDECL; 194 | $$->type = $2->type; 195 | $$->addChild($2); 196 | $$->addChild($3); 197 | }; 198 | 199 | // 连续常量定义 200 | constDefs 201 | : constDef {$$ = new TreeNode(lineno, NODE_VARLIST); $$->addChild($1);} 202 | | constDefs COMMA constDef {$$ = $1; $$->addChild($3);} 203 | ; 204 | 205 | constDef 206 | : pDeclIdentifier ASSIGN INTEGER {$$ = new TreeNode(lineno, NODE_OP); $$->optype = OP_ASSIGN; $$->addChild($1); $$->addChild($3);} 207 | | constArrayIdentifier ASSIGN LBRACE ArrayInitVal RBRACE {$$ = new TreeNode(lineno, NODE_OP); $$->optype = OP_ASSIGN; $$->addChild($1); $$->addChild($4);} 208 | ; 209 | 210 | // 数组初始化值 211 | ArrayInitVal 212 | : INTEGER {$$ = new TreeNode(lineno, NODE_VARLIST); $$->addChild($1);} 213 | | ArrayInitVal COMMA INTEGER {$$ = $1; $$->addChild($3);} 214 | ; 215 | 216 | varDecl 217 | : basicType varDefs SEMICOLON { 218 | $$ = new TreeNode(lineno, NODE_STMT); 219 | $$->stype = STMT_DECL; 220 | $$->type = $1->type; 221 | $$->addChild($1); 222 | $$->addChild($2); 223 | } 224 | ; 225 | 226 | // 连续变量定义 227 | varDefs 228 | : varDef {$$ = new TreeNode(lineno, NODE_VARLIST); $$->addChild($1);} 229 | | varDefs COMMA varDef {$$ = $1; $$->addChild($3);} 230 | ; 231 | 232 | varDef 233 | : declCompIdentifier {$$ = $1;} 234 | | declCompIdentifier ASSIGN expr { 235 | $$ = new TreeNode(lineno, NODE_OP); 236 | $$->optype = OP_ASSIGN; 237 | $$->addChild($1); 238 | $$->addChild($3); 239 | } 240 | | constArrayIdentifier ASSIGN LBRACE ArrayInitVal RBRACE { 241 | $$ = new TreeNode(lineno, NODE_OP); 242 | $$->optype = OP_ASSIGN; 243 | $$->addChild($1); 244 | $$->addChild($4); 245 | } 246 | ; 247 | 248 | // ---------------- 函数声明 ------------------- 249 | 250 | funcDef 251 | : basicType pDeclIdentifier funcLPAREN funcFParams RPAREN LBRACE blockItems RBRACE { 252 | $$ = new TreeNode(lineno, NODE_STMT); 253 | $$->stype = STMT_DECL; 254 | $$->addChild($1); 255 | $$->addChild($2); 256 | TreeNode* params = new TreeNode(lineno, NODE_VARLIST); 257 | params->addChild($4); 258 | $$->addChild(params); 259 | TreeNode* funcBlock = new TreeNode(lineno, NODE_STMT); 260 | funcBlock->stype = STMT_BLOCK; 261 | funcBlock->addChild($7); 262 | $$->addChild(funcBlock); 263 | scopePop(); 264 | } 265 | | basicType pDeclIdentifier funcLPAREN RPAREN LBRACE blockItems RBRACE { 266 | $$ = new TreeNode(lineno, NODE_STMT); 267 | $$->stype = STMT_DECL; 268 | $$->addChild($1); 269 | $$->addChild($2); 270 | $$->addChild(new TreeNode(lineno, NODE_VARLIST)); 271 | TreeNode* funcBlock = new TreeNode(lineno, NODE_STMT); 272 | funcBlock->stype = STMT_BLOCK; 273 | funcBlock->addChild($6); 274 | $$->addChild(funcBlock); 275 | scopePop(); 276 | } 277 | ; 278 | 279 | funcLPAREN : LPAREN {scopePush();}; 280 | 281 | funcFParams 282 | : funcFParam {$$ = $1;} 283 | | funcFParams COMMA funcFParam {$$ = $1; $$->addSibling($3);} 284 | ; 285 | 286 | funcFParam 287 | : basicType pDeclIdentifier {$$ = new TreeNode(lineno, NODE_PARAM); $$->addChild($1); $$->addChild($2);} 288 | ; 289 | 290 | // ---------------- 语句块 ------------------- 291 | 292 | block 293 | : blockLBRACE blockItems blockRBRACE { 294 | $$ = new TreeNode(lineno, NODE_STMT); 295 | $$->stype = STMT_BLOCK; 296 | $$->addChild($2); 297 | }; 298 | 299 | blockLBRACE : LBRACE {scopePush();} 300 | blockRBRACE : RBRACE {scopePop();} 301 | 302 | blockItems 303 | : blockItem {$$ = $1;} 304 | | blockItems blockItem {$$ = $1; $$->addSibling($2);} 305 | ; 306 | 307 | blockItem 308 | : decl {$$ = $1;} 309 | | stmt {$$ = $1;} 310 | ; 311 | 312 | stmt_ 313 | : LBRACE blockItems RBRACE { 314 | $$ = new TreeNode(lineno, NODE_STMT); 315 | $$->stype = STMT_BLOCK; 316 | $$->addChild($2); 317 | } 318 | | stmt {$$ = $1;} 319 | ; 320 | 321 | stmt 322 | : SEMICOLON {$$ = new TreeNode(lineno, NODE_STMT); $$->stype = STMT_SKIP;} 323 | | expr SEMICOLON {$$ = $1;} 324 | | block {$$ = $1;} 325 | | compIdentifier ASSIGN expr SEMICOLON { 326 | $$ = new TreeNode(lineno, NODE_OP); 327 | $$->optype = OP_ASSIGN; 328 | $$->addChild($1); 329 | $$->addChild($3); 330 | #ifdef ASSIGN_DEBUG 331 | cout << "$ reduce ASSIGN at scope : " << presentScope << ", at line " << lineno << endl; 332 | #endif 333 | } 334 | | compIdentifier PLUSASSIGN expr SEMICOLON { 335 | $$ = new TreeNode(lineno, NODE_OP); 336 | $$->optype = OP_ADDASSIGN; 337 | $$->addChild($1); 338 | $$->addChild($3); 339 | } 340 | | compIdentifier MINUSASSIGN expr SEMICOLON { 341 | $$ = new TreeNode(lineno, NODE_OP); 342 | $$->optype = OP_SUBASSIGN; 343 | $$->addChild($1); 344 | $$->addChild($3); 345 | } 346 | | compIdentifier MULASSIGN expr SEMICOLON { 347 | $$ = new TreeNode(lineno, NODE_OP); 348 | $$->optype = OP_MULASSIGN; 349 | $$->addChild($1); 350 | $$->addChild($3); 351 | } 352 | | compIdentifier DIVASSIGN expr SEMICOLON { 353 | $$ = new TreeNode(lineno, NODE_OP); 354 | $$->optype = OP_DIVASSIGN; 355 | $$->addChild($1); 356 | $$->addChild($3); 357 | } 358 | 359 | | IF LPAREN cond RPAREN stmt_ ELSE stmt_ { 360 | $$ = new TreeNode(lineno, NODE_STMT); 361 | $$->stype = STMT_IFELSE; 362 | $$->addChild($3); 363 | $$->addChild($5); 364 | $$->addChild($7); 365 | scopePop(); 366 | #ifdef IFELSE_DEBUG 367 | cout << "$ reduce IF-ELSE at scope : " << presentScope << ", at line " << lineno << endl; 368 | #endif 369 | } 370 | | IF LPAREN cond RPAREN stmt_ { 371 | $$ = new TreeNode(lineno, NODE_STMT); 372 | $$->stype = STMT_IF; 373 | $$->addChild($3); 374 | $$->addChild($5); 375 | scopePop(); 376 | #ifdef IF_DEBUG 377 | cout << "$ reduce IF at scope : " << presentScope << ", at line " << lineno << endl; 378 | #endif 379 | } 380 | | WHILE LPAREN cond RPAREN stmt_ { 381 | $$ = new TreeNode(lineno, NODE_STMT); 382 | $$->stype = STMT_WHILE; 383 | $$->addChild($3); 384 | $$->addChild($5); 385 | scopePop(); 386 | #ifdef WHILE 387 | cout << "$ reduce WHILE at scope : " << presentScope << ", at line " << lineno << endl; 388 | #endif 389 | } 390 | | FOR LPAREN basicType varDefs SEMICOLON cond SEMICOLON expr RPAREN stmt_ { 391 | $$ = new TreeNode(lineno, NODE_STMT); 392 | $$->stype = STMT_FOR; 393 | TreeNode* forDecl = new TreeNode(lineno, NODE_STMT); 394 | forDecl->stype = STMT_DECL; 395 | forDecl->addChild($3); 396 | forDecl->addChild($4); 397 | $$->addChild(forDecl); 398 | $$->addChild($6); 399 | $$->addChild($8); 400 | $$->addChild($10); 401 | scopePop(); 402 | } 403 | | FOR LPAREN expr SEMICOLON cond SEMICOLON expr RPAREN stmt_ { 404 | $$ = new TreeNode(lineno, NODE_STMT); 405 | $$->stype = STMT_FOR; 406 | $$->addChild($3); 407 | $$->addChild($5); 408 | $$->addChild($7); 409 | $$->addChild($9); 410 | scopePop(); 411 | } 412 | 413 | | BREAK SEMICOLON {$$ = new TreeNode(lineno, NODE_STMT); $$->stype = STMT_BREAK;} 414 | | CONTINUE SEMICOLON{$$ = new TreeNode(lineno, NODE_STMT); $$->stype = STMT_CONTINUE;} 415 | | RETURN SEMICOLON {$$ = new TreeNode(lineno, NODE_STMT); $$->stype = STMT_RETURN;} 416 | | RETURN expr SEMICOLON {$$ = new TreeNode(lineno, NODE_STMT); $$->stype = STMT_RETURN; $$->addChild($2);} 417 | ; 418 | 419 | IF : IF_ {scopePush();}; 420 | WHILE : WHILE_ {scopePush();}; 421 | FOR : FOR_ {scopePush();}; 422 | 423 | // ---------------- 表达式 ------------------- 424 | 425 | expr 426 | : andExpr {$$ = new TreeNode(lineno, NODE_EXPR); $$->addChild($1);} 427 | ; 428 | 429 | cond 430 | : LOrExpr {$$ = new TreeNode(lineno, NODE_EXPR); $$->addChild($1);} 431 | ; 432 | 433 | andExpr 434 | : mulExpr {$$ = $1;} 435 | | andExpr PLUS mulExpr {$$ = new TreeNode(lineno, NODE_OP); $$->optype = OP_ADD; $$->addChild($1); $$->addChild($3);} 436 | | andExpr MINUS mulExpr {$$ = new TreeNode(lineno, NODE_OP); $$->optype = OP_SUB; $$->addChild($1); $$->addChild($3);} 437 | ; 438 | 439 | // factor 440 | mulExpr 441 | : unaryExpr {$$ = $1;} 442 | | mulExpr MUL unaryExpr {$$ = new TreeNode(lineno, NODE_OP); $$->optype = OP_MUL; $$->addChild($1); $$->addChild($3);} 443 | | mulExpr DIV unaryExpr {$$ = new TreeNode(lineno, NODE_OP); $$->optype = OP_DIV; $$->addChild($1); $$->addChild($3);} 444 | | mulExpr MOD unaryExpr {$$ = new TreeNode(lineno, NODE_OP); $$->optype = OP_MOD; $$->addChild($1); $$->addChild($3);} 445 | ; 446 | 447 | // 一元表达式 448 | unaryExpr 449 | : primaryExpr {$$ = $1;} 450 | | PLUS expr {$$ = new TreeNode(lineno, NODE_OP); $$->optype = OP_POS; $$->addChild($2);} 451 | | MINUS expr {$$ = new TreeNode(lineno, NODE_OP); $$->optype = OP_NAG; $$->addChild($2);} 452 | | NOT cond {$$ = new TreeNode(lineno, NODE_OP); $$->optype = OP_NOT; $$->addChild($2);} 453 | | pIdentifier INC {$$ = new TreeNode(lineno, NODE_OP); $$->optype = OP_INC; $$->addChild($1);} 454 | | pIdentifier DEC {$$ = new TreeNode(lineno, NODE_OP); $$->optype = OP_DEC; $$->addChild($1);} 455 | ; 456 | 457 | // 基本表达式 458 | primaryExpr 459 | : LPAREN expr RPAREN {$$ = $2;} 460 | | pIdentifier LPAREN funcRParams RPAREN { 461 | $$ = new TreeNode(lineno, NODE_STMT); 462 | $$->stype = STMT_FUNCALL; 463 | $$->addChild($1); 464 | $$->addChild($3); 465 | #ifdef FUNCALL_DEBUG 466 | cout << "$ reduce function call at scope : " << presentScope << ", at line " << lineno << endl; 467 | #endif 468 | } 469 | | pIdentifier LPAREN RPAREN { 470 | $$ = new TreeNode(lineno, NODE_STMT); 471 | $$->stype = STMT_FUNCALL; 472 | $$->addChild($1); 473 | #ifdef FUNCALL_DEBUG 474 | cout << "$ reduce function call at scope : " << presentScope << ", at line " << lineno << endl; 475 | #endif 476 | } 477 | | compIdentifier {$$ = new TreeNode(lineno, NODE_EXPR); $$->addChild($1);} 478 | | INTEGER {$$ = new TreeNode(lineno, NODE_EXPR); $$->addChild($1);} 479 | | BOOL {$$ = new TreeNode(lineno, NODE_EXPR); $$->addChild($1);} 480 | | CHAR {$$ = new TreeNode(lineno, NODE_EXPR); $$->addChild($1);} 481 | | STRING {$$ = new TreeNode(lineno, NODE_EXPR); $$->addChild($1);} 482 | ; 483 | 484 | // 函数实参列表 485 | funcRParams 486 | : expr {$$ = new TreeNode(lineno, NODE_VARLIST); $$->addChild($1);} 487 | | funcRParams COMMA expr {$$ = $1; $$->addChild($3);} 488 | ; 489 | 490 | // 或表达式 491 | LOrExpr 492 | : LAndExpr {$$ = $1;} 493 | | LOrExpr OR LAndExpr {$$ = new TreeNode(lineno, NODE_OP); $$->optype = OP_OR; $$->addChild($1); $$->addChild($3);} 494 | ; 495 | 496 | // 与 497 | LAndExpr 498 | : eqExpr {$$ = $1;} 499 | | LAndExpr AND eqExpr {$$ = new TreeNode(lineno, NODE_OP); $$->optype = OP_AND; $$->addChild($1); $$->addChild($3);} 500 | ; 501 | 502 | // 相等关系 503 | eqExpr 504 | : relExpr {$$ = $1;} 505 | | eqExpr EQ relExpr {$$ = new TreeNode(lineno, NODE_OP); $$->optype = OP_EQ; $$->addChild($1); $$->addChild($3);} 506 | | eqExpr NEQ relExpr {$$ = new TreeNode(lineno, NODE_OP); $$->optype = OP_NEQ; $$->addChild($1); $$->addChild($3);} 507 | ; 508 | 509 | // 相对关系 510 | relExpr 511 | : expr {$$ = $1;} 512 | | relExpr GRA expr {$$ = new TreeNode(lineno, NODE_OP); $$->optype = OP_GRA; $$->addChild($1); $$->addChild($3);} 513 | | relExpr LES expr {$$ = new TreeNode(lineno, NODE_OP); $$->optype = OP_LES; $$->addChild($1); $$->addChild($3);} 514 | | relExpr GRAEQ expr {$$ = new TreeNode(lineno, NODE_OP); $$->optype = OP_GRAEQ; $$->addChild($1); $$->addChild($3);} 515 | | relExpr LESEQ expr {$$ = new TreeNode(lineno, NODE_OP); $$->optype = OP_LESEQ; $$->addChild($1); $$->addChild($3);} 516 | ; 517 | 518 | %% 519 | 520 | int yyerror(char const * message) 521 | { 522 | cout << "error: " << message << ", at line " << lineno << endl; 523 | return -1; 524 | } 525 | 526 | /* 527 | * 作用域比较函数 int scopeCmp (string, string) 528 | * 529 | * 输入参数: 530 | * presScope: 当前变量所处的作用域 531 | * varScope: 希望进行比较的已声明变量作用域 532 | * 533 | * 返回值: 534 | * 0: 作用域相同, 535 | * 若为变量声明语句,为变量重定义。 536 | * >0: 已声明变量作用域在当前作用域外层,返回作用域距离(堆栈层数) 537 | * 若为声明语句,不产生冲突,当前变量为新定义变量, 538 | * 若为使用语句,当前变量为新定义变量。 539 | * -1:已声明变量作用域在当前作用域内层, 540 | * 若为声明语句,不可能出现这种情况, 541 | * 若为使用语句,不产生冲突。 542 | * -2:两个作用域互不包含,任何情况下都不会互相干扰 543 | */ 544 | int scopeCmp(string presScope, string varScope) { 545 | unsigned int plen = presScope.length(), vlen = varScope.length(); 546 | unsigned int minlen = min(plen, vlen); 547 | if (presScope.substr(0, minlen) == varScope.substr(0, minlen)) { 548 | if (plen >= vlen) 549 | return plen - vlen; 550 | else 551 | return -1; 552 | } 553 | return -2; 554 | } 555 | 556 | void scopePush() { 557 | presentScope += max_scope_id; 558 | max_scope_id = SCOPT_ID_BASE; 559 | top++; 560 | #ifdef SCOPE_DEBUG 561 | cout << "* push -> " << presentScope << ", at line " << lineno << endl; 562 | #endif 563 | } 564 | 565 | void scopePop() { 566 | max_scope_id = presentScope[top] + 1; 567 | presentScope = presentScope.substr(0, presentScope.length() - 1); 568 | top--; 569 | #ifdef SCOPE_DEBUG 570 | cout << "* pop -> " << presentScope << ", at line " << lineno << endl; 571 | #endif 572 | } 573 | -------------------------------------------------------------------------------- /lab5/src/pch.h: -------------------------------------------------------------------------------- 1 | #ifndef PCH_H 2 | #define PCH_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /lab5/src/tree.cpp: -------------------------------------------------------------------------------- 1 | #include "tree.h" 2 | using namespace std; 3 | 4 | TreeNode::TreeNode(int lineno, NodeType type) { 5 | this->lineno = lineno; 6 | this->nodeType = type; 7 | this->pointLevel = 0; 8 | } 9 | 10 | TreeNode::TreeNode(TreeNode* node) { 11 | this->lineno = node->lineno; 12 | this->nodeType = node->nodeType; 13 | this->optype = node->optype; 14 | this->stype = node->stype; 15 | this->type = node->type; 16 | this->int_val = node->int_val; 17 | this->ch_val = node->ch_val; 18 | this->b_val = node->b_val; 19 | this->str_val = node->str_val; 20 | this->var_name = node->var_name; 21 | this->var_scope = node->var_scope; 22 | this->pointLevel = node->pointLevel; 23 | } 24 | 25 | void TreeNode::addChild(TreeNode* child) { 26 | if (this->child == nullptr) { 27 | this->child = child; 28 | } 29 | else { 30 | this->child->addSibling(child); 31 | } 32 | } 33 | 34 | void TreeNode::addSibling(TreeNode* sibling){ 35 | TreeNode* p = this; 36 | while (p->sibling != nullptr) { 37 | p = p->sibling; 38 | } 39 | p->sibling = sibling; 40 | } 41 | 42 | void TreeNode::genNodeId() { 43 | static unsigned int maxid = 0; 44 | this->nodeID = maxid++; 45 | if (this->child) 46 | this->child->genNodeId(); 47 | if (this->sibling) 48 | this->sibling->genNodeId(); 49 | } 50 | 51 | void TreeNode::printAST() { 52 | printNodeInfo(); 53 | printChildrenId(); 54 | cout << endl; 55 | TreeNode *p = this->child; 56 | while (p != nullptr) { 57 | p->printAST(); 58 | p = p->sibling; 59 | } 60 | } 61 | 62 | void TreeNode::printNodeInfo() { 63 | cout << "@" << this->nodeID << "\t"; 64 | cout << "line " << lineno << "\t"; 65 | cout << nodeType2String(this->nodeType); 66 | this->printSpecialInfo(); 67 | } 68 | 69 | void TreeNode::printChildrenId() { 70 | cout << ",\tchild:"; 71 | TreeNode *p = this->child; 72 | if (p == nullptr) 73 | cout << "-"; 74 | while (p) { 75 | cout << "\t@" << p->nodeID; 76 | p = p->sibling; 77 | } 78 | cout << "\t"; 79 | } 80 | 81 | void TreeNode::printSpecialInfo() { 82 | switch(this->nodeType){ 83 | case NODE_CONST: 84 | cout << ", "; 85 | this->printConstVal(); 86 | break; 87 | case NODE_VAR: 88 | cout << ",\tname: "; 89 | if (this->pointLevel != 0) { 90 | // 为指针类型添加前缀(*和&) 91 | string prefix = this->pointLevel > 0 ? "*" : "&"; 92 | for (int i=0; i < abs(this->pointLevel); i++) 93 | cout << prefix; 94 | } 95 | cout << var_name << ",\tscope: "; 96 | for (unsigned int i = 0; i < var_scope.length(); i++) 97 | cout << var_scope[i] << " "; 98 | break; 99 | case NODE_EXPR: 100 | break; 101 | case NODE_STMT: 102 | cout << ", " << sType2String(this->stype) << "\t"; 103 | if (this->stype == STMT_DECL) { 104 | if (this->child && this->child->sibling && this->child->sibling->type) 105 | cout << this->child->sibling->type->getTypeInfo() << "\t"; 106 | } 107 | break; 108 | case NODE_TYPE: 109 | cout << ", " << this->type->getTypeInfo(); 110 | break; 111 | case NODE_OP: 112 | cout << ", " << opType2String(this->optype) << "\t"; 113 | break; 114 | default: 115 | break; 116 | } 117 | } 118 | 119 | string TreeNode::nodeType2String (NodeType type){ 120 | switch (type) 121 | { 122 | case NODE_BOOL: 123 | return ""; 124 | case NODE_CONST: 125 | return ""; 126 | case NODE_VAR: 127 | return ""; 128 | case NODE_EXPR: 129 | return ""; 130 | case NODE_TYPE: 131 | return ""; 132 | case NODE_STMT: 133 | return ""; 134 | case NODE_PROG: 135 | return ""; 136 | case NODE_VARLIST: 137 | return ""; 138 | case NODE_PARAM: 139 | return "function format parameter"; 140 | case NODE_OP: 141 | return ""; 142 | default: 143 | return ""; 144 | } 145 | } 146 | 147 | string TreeNode::sType2String(StmtType type) { 148 | switch (type) 149 | { 150 | case STMT_SKIP: 151 | return "skip"; 152 | case STMT_DECL: 153 | return "declaration"; 154 | case STMT_CONSTDECL: 155 | return "const declaration"; 156 | case STMT_FUNCALL: 157 | return "function call"; 158 | case STMT_BLOCK: 159 | return "block"; 160 | case STMT_IF: 161 | return "if"; 162 | case STMT_IFELSE: 163 | return "if with else"; 164 | case STMT_WHILE: 165 | return "while"; 166 | case STMT_FOR: 167 | return "for"; 168 | case STMT_RETURN: 169 | return "return"; 170 | case STMT_CONTINUE: 171 | return "continue"; 172 | case STMT_BREAK: 173 | return "break"; 174 | default: 175 | return "?"; 176 | } 177 | } 178 | 179 | string TreeNode::opType2String(OperatorType type) { 180 | switch (type) 181 | { 182 | case OP_EQ: 183 | return "equal"; 184 | case OP_NEQ: 185 | return "not equal"; 186 | case OP_GRAEQ: 187 | return "grater equal"; 188 | case OP_LESEQ: 189 | return "less equal"; 190 | case OP_ASSIGN: 191 | return "assign"; 192 | case OP_ADDASSIGN: 193 | return "add assign"; 194 | case OP_SUBASSIGN: 195 | return "sub assign"; 196 | case OP_MULASSIGN: 197 | return "multiply assign"; 198 | case OP_DIVASSIGN: 199 | return "divide assign"; 200 | case OP_GRA: 201 | return "grater"; 202 | case OP_LES: 203 | return "less"; 204 | case OP_INC: 205 | return "auto increment"; 206 | case OP_DEC: 207 | return "auto decrement"; 208 | case OP_ADD: 209 | return "add"; 210 | case OP_SUB: 211 | return "sub"; 212 | case OP_POS: 213 | return "positive"; 214 | case OP_NAG: 215 | return "nagative"; 216 | case OP_MUL: 217 | return "multiply"; 218 | case OP_DIV: 219 | return "divide"; 220 | case OP_MOD: 221 | return "Modulo"; 222 | case OP_NOT: 223 | return "not"; 224 | case OP_AND: 225 | return "and"; 226 | case OP_OR: 227 | return "or"; 228 | case OP_INDEX: 229 | return "index"; 230 | default: 231 | return "?"; 232 | } 233 | } 234 | 235 | void TreeNode::printConstVal() { 236 | if (this->nodeType == NODE_CONST){ 237 | cout << this->type->getTypeInfo() << ":"; 238 | switch (this->type->type) 239 | { 240 | case VALUE_BOOL: 241 | if (this->b_val) 242 | cout << "true"; 243 | else 244 | cout << "fasle"; 245 | break; 246 | case VALUE_CHAR: 247 | cout << ch_val; 248 | break; 249 | case VALUE_INT: 250 | cout << int_val; 251 | break; 252 | case VALUE_STRING: 253 | cout << str_val; 254 | break; 255 | default: 256 | cout << "-"; 257 | break; 258 | } 259 | } 260 | } 261 | -------------------------------------------------------------------------------- /lab5/src/tree.h: -------------------------------------------------------------------------------- 1 | #ifndef TREE_H 2 | #define TREE_H 3 | 4 | #include "pch.h" 5 | #include "type.h" 6 | 7 | enum NodeType 8 | { 9 | NODE_OP, 10 | NODE_BOOL, 11 | NODE_CONST, 12 | NODE_VAR, 13 | NODE_TYPE, 14 | 15 | NODE_PROG, 16 | NODE_STMT, 17 | NODE_EXPR, 18 | NODE_VARLIST, 19 | NODE_PARAM, 20 | }; 21 | 22 | enum OperatorType 23 | { 24 | OP_EQ, // == 25 | OP_NEQ, // != 26 | OP_GRAEQ, // >= 27 | OP_LESEQ, // <= 28 | OP_ADDASSIGN, // += 29 | OP_SUBASSIGN, // -= 30 | OP_MULASSIGN, // *= 31 | OP_DIVASSIGN, // /= 32 | OP_ASSIGN, // = 33 | OP_GRA, // > 34 | OP_LES, // < 35 | OP_INC, // ++ 36 | OP_DEC, // -- 37 | OP_ADD, // + 38 | OP_SUB, // - 39 | OP_POS, // + (一元运算符) 40 | OP_NAG, // - (一元运算符) 41 | OP_MUL, // * 42 | OP_DIV, // / 43 | OP_MOD, // % 44 | OP_NOT, // ! 45 | OP_AND, // && 46 | OP_OR, // || 47 | OP_INDEX, // [] 下标运算符 48 | }; 49 | 50 | enum StmtType { 51 | STMT_SKIP, 52 | STMT_BLOCK, 53 | STMT_DECL, 54 | STMT_CONSTDECL, 55 | STMT_FUNCALL, 56 | STMT_IFELSE, 57 | STMT_IF, 58 | STMT_WHILE, 59 | STMT_FOR, 60 | STMT_RETURN, 61 | STMT_CONTINUE, 62 | STMT_BREAK, 63 | }; 64 | 65 | struct TreeNode { 66 | public: 67 | int nodeID; 68 | int lineno; 69 | NodeType nodeType; 70 | 71 | TreeNode* child = nullptr; 72 | TreeNode* sibling = nullptr; 73 | 74 | TreeNode(int lineno, NodeType type); 75 | TreeNode(TreeNode* node); // 仅用于叶节点拷贝,函数不复制子节点,也不复制子节点指针 76 | void addChild(TreeNode*); 77 | void addSibling(TreeNode*); 78 | 79 | void printNodeInfo(); 80 | void printChildrenId(); 81 | 82 | void printAST(); // 先输出自己 + 孩子们的id;再依次让每个孩子输出AST。 83 | void printSpecialInfo(); 84 | void printConstVal(); 85 | 86 | void genNodeId(); 87 | 88 | public: 89 | OperatorType optype; 90 | StmtType stype; // 如果是表达式 91 | Type* type; // 变量、类型、表达式结点,有类型。 92 | int int_val; 93 | char ch_val; 94 | bool b_val; 95 | string str_val; 96 | string var_name; 97 | string var_scope; // 变量作用域标识符 98 | int pointLevel; 99 | 100 | public: 101 | static string nodeType2String (NodeType type); 102 | static string opType2String (OperatorType type); 103 | static string sType2String (StmtType type); 104 | }; 105 | 106 | static TreeNode* nodeScanf = new TreeNode(0, NODE_VAR); 107 | static TreeNode* nodePrintf = new TreeNode(0, NODE_VAR); 108 | 109 | #endif -------------------------------------------------------------------------------- /lab5/src/type.cpp: -------------------------------------------------------------------------------- 1 | #include "type.h" 2 | 3 | Type::Type(ValueType valueType) { 4 | this->type = valueType; 5 | this->paramNum = 0; 6 | this->dim = 0; 7 | } 8 | 9 | string Type::getTypeInfo() { 10 | return getTypeInfo(this->type); 11 | } 12 | 13 | string Type::getTypeInfo(ValueType type) { 14 | switch(type) { 15 | case VALUE_BOOL: 16 | return "bool"; 17 | case VALUE_INT: 18 | return "int"; 19 | case VALUE_CHAR: 20 | return "char"; 21 | case VALUE_STRING: 22 | return "string"; 23 | case VALUE_ARRAY: 24 | if (this->dim > 0) { 25 | string buf = getTypeInfo(this->elementType); 26 | for (unsigned int i = 0; i < dim && i < MAX_ARRAY_DIM; i++) { 27 | buf += "[" + to_string(dimSize[i]) + "]"; 28 | } 29 | return buf; 30 | } 31 | return ""; 32 | case VALUE_VOID: 33 | return "void"; 34 | default: 35 | return "?"; 36 | } 37 | } 38 | 39 | void Type::addParam(Type* param){ 40 | this->paramType[paramNum++] = param; 41 | } 42 | 43 | void Type::addRet(Type* t){ 44 | this->retType = t; 45 | } 46 | -------------------------------------------------------------------------------- /lab5/src/type.h: -------------------------------------------------------------------------------- 1 | #ifndef TYPESYSTEM_H 2 | #define TYPESYSTEM_H 3 | #include "./pch.h" 4 | using namespace std; 5 | 6 | #define MAX_PARAM 16 7 | #define MAX_ARRAY_DIM 8 8 | #define MAX_SCOPE_STACK 32 9 | #define SCOPT_ID_BASE '1' 10 | 11 | // #define DEBUG 12 | #ifdef DEBUG 13 | // #define SCOPE_DEBUG 14 | // #define ID_TOKEN_DEBUG 15 | #define ID_REDUCE_DEBUG 16 | #define DECL_DEBUG 17 | // #define POINT_DEBUG 18 | // #define ASSIGN_DEBUG 19 | // #define IF_DEBUG 20 | // #define IFELSE_DEBUG 21 | // #define WHILE_DEBUG 22 | // #define FUNCALL_DEBUG 23 | #endif 24 | 25 | enum ValueType 26 | { 27 | VALUE_BOOL, 28 | VALUE_INT, 29 | VALUE_CHAR, 30 | VALUE_STRING, 31 | VALUE_VOID, 32 | VALUE_ARRAY, 33 | COMPOSE_STRUCT, 34 | COMPOSE_UNION, 35 | COMPOSE_FUNCTION 36 | }; 37 | 38 | class Type 39 | { 40 | public: 41 | ValueType type; 42 | Type(ValueType valueType); 43 | 44 | public: 45 | /* 如果你要设计复杂类型系统的话,可以修改这一部分 */ 46 | ValueType* childType; // for union or struct 47 | 48 | unsigned short paramNum; // for function 49 | Type* paramType[MAX_PARAM]; 50 | Type* retType; 51 | 52 | unsigned int dim; // for array 53 | ValueType elementType; 54 | int dimSize[MAX_ARRAY_DIM]; 55 | 56 | void addChild(Type* t); 57 | void addParam(Type* t); 58 | void addRet(Type* t); 59 | public: 60 | ValueType* sibling; 61 | public: 62 | string getTypeInfo(); 63 | string getTypeInfo(ValueType type); 64 | }; 65 | 66 | // 设置几个常量Type,可以节省空间开销 67 | static Type* TYPE_INT = new Type(VALUE_INT); 68 | static Type* TYPE_CHAR = new Type(VALUE_CHAR); 69 | static Type* TYPE_BOOL = new Type(VALUE_BOOL); 70 | static Type* TYPE_STRING = new Type(VALUE_STRING); 71 | static Type* TYPE_VOID = new Type(VALUE_VOID); 72 | 73 | int getSize(Type* type); 74 | 75 | #endif -------------------------------------------------------------------------------- /lab5/tests/0.c: -------------------------------------------------------------------------------- 1 | int a=0; 2 | int b=2; 3 | if(!2==3){ 4 | int a=2; 5 | a=a+2; 6 | } 7 | while(a==b){ 8 | printf(a); 9 | } -------------------------------------------------------------------------------- /lab5/tests/1.c: -------------------------------------------------------------------------------- 1 | /* 2 | I'm level 1 test. 3 | */ 4 | void main() { 5 | int *e; 6 | int a, s; 7 | a = 10; 8 | s = 0; 9 | char ch; 10 | scanf("%d", &ch); 11 | while(a>0 && a<=10 || a%100==10 && !a==10) { 12 | a -= 1; 13 | int a; 14 | a = 10; 15 | s += a; 16 | if(-s < -10) { 17 | printf("result is: %d\n", s); 18 | int b; 19 | b = 10; 20 | for(int i=0; i[%d][%d] %d\t",m3.id, i, j, m3.arr[i][j]); 22 | } 23 | printf("\n"); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /lab5/tests/3.c: -------------------------------------------------------------------------------- 1 | /* I'm level 3 test, With no runtime */ 2 | int s = 0; 3 | int f(int x, int y) { 4 | s += x*x + y*y; 5 | return s; 6 | } 7 | void main(){ 8 | int i=0; 9 | int a=1, b=1; 10 | int line; 11 | scanf("%d", &line); 12 | if(line > 10000) line = 10000; 13 | while(true) { 14 | if(f(a++, b++) asmTest.s 56 | gcc asmTest.s -m32 -o asmTest.out 57 | qemu-i386 asmTest.out 58 | 59 | std: 60 | for file in $(basename $(shell find test/?/*.c)); \ 61 | do \ 62 | touch -a $$file.in; \ 63 | done 64 | 65 | different: 66 | for file in $(basename $(shell find test/?/*.c)); \ 67 | do \ 68 | cp -u $$file.c $$file.sy; \ 69 | done 70 | 71 | clean: 72 | rm -f src/lexer.cpp src/parser.cpp src/parser.h src/pch.h.gch $(TARGET) *.o ./bin/* 73 | rm -f src/*.output 74 | rm -rf test/*/*.out test/*/*.output 75 | 76 | clean-complete:clean 77 | rm -rf test/*/*.s test/*/*.res test/*/*.sy test/*/*.output 78 | -------------------------------------------------------------------------------- /lab6/bin/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab6/bin/.gitkeep -------------------------------------------------------------------------------- /lab6/lab6_2020.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab6/lab6_2020.pdf -------------------------------------------------------------------------------- /lab6/src/common.h: -------------------------------------------------------------------------------- 1 | #ifndef COMMON_H 2 | #define COMMON_H 3 | 4 | #include "pch.h" 5 | using std::cerr; 6 | using std::cout; 7 | using std::endl; 8 | using std::string; 9 | using std::list; 10 | using std::map; 11 | using std::stack; 12 | using std::unordered_map; 13 | #define YYSTYPE TreeNode * 14 | 15 | #include "./tree.h" 16 | #include "./parser.h" 17 | 18 | #endif -------------------------------------------------------------------------------- /lab6/src/lexer.l: -------------------------------------------------------------------------------- 1 | %option nounput 2 | %{ 3 | #include "common.h" 4 | 5 | int lineno = 1; 6 | 7 | %} 8 | 9 | BLOCKCOMMENT_BEGIN "/*" 10 | BLOCKCOMMENT_ELE . 11 | BLOCKCOMMENT_LINE \n 12 | BLOCKCOMMENT_END "*/" 13 | %x BLOCKCOMMENT 14 | LINECOMMENT \/\/[^\n]* 15 | EOL (\r\n|\r|\n) 16 | WHILTESPACE [[:blank:]] 17 | 18 | OCTINT 0[0-7]+ 19 | DECINT [0-9]+ 20 | HEXINT 0[Xx][0-9a-fA-F]+ 21 | 22 | BOOL (true)|(false) 23 | STRING \"[^(\")]*\" 24 | CHAR \'\\?.\' 25 | 26 | IDENTIFIER [[:alpha:]_][[:alpha:][:digit:]_]* 27 | 28 | %% 29 | 30 | {BLOCKCOMMENT_BEGIN} {BEGIN BLOCKCOMMENT;} 31 | {BLOCKCOMMENT_ELE} {} 32 | {BLOCKCOMMENT_LINE} {lineno++;} 33 | {BLOCKCOMMENT_END} {BEGIN INITIAL;} 34 | {LINECOMMENT} {} 35 | 36 | "int" return T_INT; 37 | "bool" return T_BOOL; 38 | "char" return T_CHAR; 39 | "void" return T_VOID; 40 | 41 | "&" return ADDR; 42 | 43 | "(" return LPAREN; 44 | ")" return RPAREN; 45 | "[" return LBRACKET; 46 | "]" return RBRACKET; 47 | "{" return LBRACE; 48 | "}" return RBRACE; 49 | "," return COMMA; 50 | ";" return SEMICOLON; 51 | 52 | "==" return EQ; 53 | ">=" return GRAEQ; 54 | "<=" return LESEQ; 55 | "!=" return NEQ; 56 | "=" return ASSIGN; 57 | "+=" return PLUSASSIGN; 58 | "-=" return MINUSASSIGN; 59 | "*=" return MULASSIGN; 60 | "/=" return DIVASSIGN; 61 | "++" return INC; 62 | "--" return DEC; 63 | ">" return GRA; 64 | "<" return LES; 65 | "+" return PLUS; 66 | "-" return MINUS; 67 | "*" return MUL; 68 | "/" return DIV; 69 | "%" return MOD; 70 | "&&" return AND; 71 | "||" return OR; 72 | "!" return NOT; 73 | 74 | "const" return CONST; 75 | "if" return IF_; 76 | "else" return ELSE; 77 | "while" return WHILE_; 78 | "for" return FOR_; 79 | "break" return BREAK; 80 | "continue" return CONTINUE; 81 | "return" return RETURN; 82 | 83 | "printf" { 84 | nodePrintf->var_name = "printf"; 85 | nodePrintf->var_scope = "1"; 86 | yylval = nodePrintf; 87 | return IDENTIFIER; 88 | }; 89 | "scanf" { 90 | nodeScanf->var_name = "scanf"; 91 | nodeScanf->var_scope = "1"; 92 | yylval = nodeScanf; 93 | return IDENTIFIER; 94 | }; 95 | 96 | {BOOL} { 97 | TreeNode* node = new TreeNode(lineno, NODE_CONST); 98 | node->type = TYPE_BOOL; 99 | node->b_val = strcmp("false", yytext); 100 | yylval = node; 101 | return BOOL; 102 | } 103 | 104 | {OCTINT} { 105 | TreeNode* node = new TreeNode(lineno, NODE_CONST); 106 | node->type = TYPE_INT; 107 | node->int_val = strtol(yytext, NULL, 8); 108 | yylval = node; 109 | return INTEGER; 110 | } 111 | 112 | {DECINT} { 113 | TreeNode* node = new TreeNode(lineno, NODE_CONST); 114 | node->type = TYPE_INT; 115 | node->int_val = atoi(yytext); 116 | yylval = node; 117 | return INTEGER; 118 | } 119 | 120 | {HEXINT} { 121 | TreeNode* node = new TreeNode(lineno, NODE_CONST); 122 | node->type = TYPE_INT; 123 | node->int_val = strtol(yytext, NULL, 16); 124 | yylval = node; 125 | return INTEGER; 126 | } 127 | 128 | {CHAR} { 129 | TreeNode* node = new TreeNode(lineno, NODE_CONST); 130 | node->type = TYPE_CHAR; 131 | // 支持转义字符 132 | if (yytext[1] == '\\') { 133 | switch (yytext[2]) { 134 | case 'a': 135 | node->ch_val = 7; 136 | break; 137 | case 'b': 138 | node->ch_val = 8; 139 | break; 140 | case 'f': 141 | node->ch_val = 12; 142 | break; 143 | case 'n': 144 | node->ch_val = 10; 145 | break; 146 | case 'r': 147 | node->ch_val = 13; 148 | break; 149 | case 't': 150 | node->ch_val = 9; 151 | break; 152 | case 'v': 153 | node->ch_val = 11; 154 | break; 155 | case '\\': 156 | node->ch_val = 92; 157 | break; 158 | case '\'': 159 | node->ch_val = 39; 160 | break; 161 | case '"': 162 | node->ch_val = 34; 163 | break; 164 | case '?': 165 | node->ch_val = 63; 166 | break; 167 | default: 168 | node->ch_val = 0; 169 | break; 170 | } 171 | } 172 | else { 173 | node->ch_val = yytext[1]; 174 | } 175 | yylval = node; 176 | return CHAR; 177 | } 178 | 179 | {STRING} { 180 | TreeNode* node = new TreeNode(lineno, NODE_CONST); 181 | node->type = TYPE_STRING; 182 | string text = yytext; 183 | node->str_val = text.substr(1, text.length()-2); 184 | yylval = node; 185 | return STRING; 186 | } 187 | 188 | {IDENTIFIER} { 189 | TreeNode* node = new TreeNode(lineno, NODE_VAR); 190 | node->var_name = string(yytext); 191 | yylval = node; 192 | #ifdef ID_TOKEN_DEBUG 193 | cout << "% get IDENTIFIER :" << yytext < 3 | 4 | extern TreeNode *root; 5 | extern FILE *yyin; 6 | extern int yyparse(); 7 | bool parserError = false; 8 | bool typeError = false; 9 | 10 | using namespace std; 11 | int main(int argc, char *argv[]) { 12 | if (argc >= 2) { 13 | FILE *fin = fopen(argv[1], "r"); 14 | if (fin != nullptr) { 15 | yyin = fin; 16 | } 17 | else { 18 | cerr << "failed to open file: " << argv[1] << endl; 19 | } 20 | } 21 | 22 | InitIOFunctionNode(); 23 | yyparse(); 24 | 25 | if (parserError) 26 | return 0; 27 | 28 | root->genNodeId(); 29 | #ifdef AST 30 | cout << "# -------------------------" << endl; 31 | root->printAST(); 32 | cout << "# -------------------------" << endl; 33 | #endif 34 | root->typeCheck(); 35 | 36 | if (typeError) 37 | return 0; 38 | 39 | root->genCode(); 40 | 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /lab6/src/parser.h: -------------------------------------------------------------------------------- 1 | /* A Bison parser, made by GNU Bison 3.0.4. */ 2 | 3 | /* Bison interface for Yacc-like parsers in C 4 | 5 | Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . */ 19 | 20 | /* As a special exception, you may create a larger work that contains 21 | part or all of the Bison parser skeleton and distribute that work 22 | under terms of your choice, so long as that work isn't itself a 23 | parser generator using the skeleton or a modified version thereof 24 | as a parser skeleton. Alternatively, if you modify or redistribute 25 | the parser skeleton itself, you may (at your option) remove this 26 | special exception, which will cause the skeleton and the resulting 27 | Bison output files to be licensed under the GNU General Public 28 | License without this special exception. 29 | 30 | This special exception was added by the Free Software Foundation in 31 | version 2.2 of Bison. */ 32 | 33 | #ifndef YY_YY_SRC_PARSER_H_INCLUDED 34 | # define YY_YY_SRC_PARSER_H_INCLUDED 35 | /* Debug traces. */ 36 | #ifndef YYDEBUG 37 | # define YYDEBUG 0 38 | #endif 39 | #if YYDEBUG 40 | extern int yydebug; 41 | #endif 42 | 43 | /* Token type. */ 44 | #ifndef YYTOKENTYPE 45 | # define YYTOKENTYPE 46 | enum yytokentype 47 | { 48 | T_CHAR = 258, 49 | T_INT = 259, 50 | T_STRING = 260, 51 | T_BOOL = 261, 52 | T_VOID = 262, 53 | ADDR = 263, 54 | ASSIGN = 264, 55 | PLUSASSIGN = 265, 56 | MINUSASSIGN = 266, 57 | MULASSIGN = 267, 58 | DIVASSIGN = 268, 59 | SEMICOLON = 269, 60 | COMMA = 270, 61 | LPAREN = 271, 62 | RPAREN = 272, 63 | LBRACE = 273, 64 | RBRACE = 274, 65 | LBRACKET = 275, 66 | RBRACKET = 276, 67 | CONST = 277, 68 | IF_ = 278, 69 | ELSE = 279, 70 | WHILE_ = 280, 71 | FOR_ = 281, 72 | BREAK = 282, 73 | CONTINUE = 283, 74 | RETURN = 284, 75 | EQ = 285, 76 | GRAEQ = 286, 77 | LESEQ = 287, 78 | NEQ = 288, 79 | GRA = 289, 80 | LES = 290, 81 | PLUS = 291, 82 | MINUS = 292, 83 | MUL = 293, 84 | DIV = 294, 85 | MOD = 295, 86 | AND = 296, 87 | OR = 297, 88 | NOT = 298, 89 | INC = 299, 90 | DEC = 300, 91 | IDENTIFIER = 301, 92 | INTEGER = 302, 93 | CHAR = 303, 94 | BOOL = 304, 95 | STRING = 305 96 | }; 97 | #endif 98 | 99 | /* Value type. */ 100 | #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED 101 | typedef int YYSTYPE; 102 | # define YYSTYPE_IS_TRIVIAL 1 103 | # define YYSTYPE_IS_DECLARED 1 104 | #endif 105 | 106 | 107 | extern YYSTYPE yylval; 108 | 109 | int yyparse (void); 110 | 111 | #endif /* !YY_YY_SRC_PARSER_H_INCLUDED */ 112 | -------------------------------------------------------------------------------- /lab6/src/parser.y: -------------------------------------------------------------------------------- 1 | %{ 2 | #include "common.h" 3 | #define YYSTYPE TreeNode * 4 | 5 | TreeNode* root = new TreeNode(0, NODE_PROG); 6 | extern int lineno; 7 | 8 | extern bool parserError; 9 | 10 | // max_scope_id 是堆栈下一层结点的最大编号 11 | unsigned char max_scope_id = SCOPT_ID_BASE; 12 | string presentScope = "1"; 13 | unsigned int top = 0; 14 | 15 | // multimap <标识符名称, 作用域> 变量名列表 16 | extern multimap idNameList; 17 | // map <<标识符名称, 作用域>, 结点指针> 变量列表 18 | extern map, TreeNode*> idList; 19 | 20 | // 用于检查continue和break是否在循环内部 21 | bool inCycle = false; 22 | 23 | int yylex(); 24 | int yyerror( char const * ); 25 | int scopeCmp(string preScope, string varScope); 26 | void scopePush(); 27 | void scopePop(); 28 | %} 29 | 30 | // 类型 31 | %token T_CHAR T_INT T_STRING T_BOOL T_VOID 32 | 33 | // 取地址运算符 34 | %token ADDR; 35 | 36 | // 赋值运算符 37 | %token ASSIGN PLUSASSIGN MINUSASSIGN MULASSIGN DIVASSIGN 38 | 39 | // 括号分号逗号中括号 40 | %token SEMICOLON COMMA LPAREN RPAREN LBRACE RBRACE LBRACKET RBRACKET 41 | 42 | // 关键字 43 | %token CONST IF_ ELSE WHILE_ FOR_ BREAK CONTINUE RETURN 44 | 45 | // 比较运算符 46 | %token EQ GRAEQ LESEQ NEQ GRA LES 47 | 48 | // 普通计算 49 | %token PLUS MINUS MUL DIV MOD AND OR NOT INC DEC 50 | 51 | // 特殊单词 52 | %token IDENTIFIER INTEGER CHAR BOOL STRING 53 | 54 | %left EQ 55 | 56 | %% 57 | 58 | program 59 | : decl {root->addChild($1);} 60 | | funcDef {root->addChild($1);} 61 | | program decl {root->addChild($2);} 62 | | program funcDef {root->addChild($2);} 63 | ; 64 | 65 | // ---------------- 类型与复合标识符 ------------------- 66 | 67 | basicType 68 | : T_INT {$$ = new TreeNode(lineno, NODE_TYPE); $$->type = TYPE_INT;} 69 | | T_CHAR {$$ = new TreeNode(lineno, NODE_TYPE); $$->type = TYPE_CHAR;} 70 | | T_BOOL {$$ = new TreeNode(lineno, NODE_TYPE); $$->type = TYPE_BOOL;} 71 | | T_VOID {$$ = new TreeNode(lineno, NODE_TYPE); $$->type = TYPE_VOID;} 72 | ; 73 | 74 | literalConst 75 | : INTEGER {$$ = new TreeNode(lineno, NODE_EXPR); $$->addChild($1);} 76 | | BOOL {$$ = new TreeNode(lineno, NODE_EXPR); $$->addChild($1);} 77 | | CHAR {$$ = new TreeNode(lineno, NODE_EXPR); $$->addChild($1);} 78 | | STRING {$$ = new TreeNode(lineno, NODE_EXPR); $$->addChild($1);} 79 | ; 80 | 81 | // ------ 复合标识符,包含指针与数组,在变量声明外使用 ----- 82 | compIdentifier 83 | : pIdentifier {$$ = $1;} 84 | | arrayIdentifier { 85 | $$ = $1; 86 | // 归约完成,清除下标计数器,为下一次做准备 87 | $$->child->type->visitDim = 0; 88 | } 89 | ; 90 | 91 | // 指针标识符 92 | pIdentifier 93 | : identifier {$$ = new TreeNode($1);} 94 | | MUL pIdentifier {$$ = $2; $$->pointLevel++;} 95 | | ADDR pIdentifier { 96 | $$ = $2; 97 | $$->pointLevel--; 98 | if ($$->pointLevel < -2) { 99 | yyerror("Continuous addr operator"); 100 | } 101 | } 102 | ; 103 | 104 | // 数组标识符 105 | arrayIdentifier 106 | : pIdentifier LBRACKET expr RBRACKET { 107 | $$ = new TreeNode(lineno, NODE_OP); 108 | $$->optype = OP_INDEX; 109 | $$->addChild($1); 110 | 111 | // 计算数组偏移量倍数 112 | int biasRate = 1; 113 | for (unsigned int i = $1->type->visitDim + 1; i < $1->type->dim; i++) { 114 | biasRate *= $1->type->dimSize[i]; 115 | } 116 | TreeNode* biasNode; 117 | if (biasRate == 1) { 118 | // 偏移倍数为1时省略乘法结点 119 | biasNode = $3; 120 | } 121 | else { 122 | biasNode = new TreeNode(lineno, NODE_OP); 123 | biasNode->optype = OP_MUL; 124 | biasNode->addChild($3); 125 | TreeNode* biasRateExpr = new TreeNode(lineno, NODE_EXPR); 126 | TreeNode* biasRateConst = new TreeNode(lineno, NODE_CONST); 127 | biasRateConst->type = TYPE_INT; 128 | biasRateConst->int_val = biasRate; 129 | biasRateExpr->addChild(biasRateConst); 130 | biasNode->addChild(biasRateExpr); 131 | } 132 | $1->type->visitDim++; 133 | 134 | $$->addChild(biasNode); 135 | } 136 | | arrayIdentifier LBRACKET expr RBRACKET { 137 | $$ = $1; 138 | TreeNode* newBiasNode = new TreeNode(lineno, NODE_OP); 139 | newBiasNode->optype = OP_ADD; 140 | newBiasNode->addChild($$->child->sibling); 141 | $$->child->sibling = newBiasNode; 142 | 143 | // 计算数组偏移量倍数 144 | int biasRate = 1; 145 | for (unsigned int i = $$->child->type->visitDim + 1; i < $$->child->type->dim; i++) { 146 | biasRate *= $$->child->type->dimSize[i]; 147 | } 148 | 149 | TreeNode* biasNode; 150 | if (biasRate == 1) { 151 | // 偏移倍数为1时省略乘法结点 152 | biasNode = $3; 153 | } 154 | else { 155 | biasNode->optype = OP_MUL; 156 | biasNode->addChild($3); 157 | TreeNode* biasRateExpr = new TreeNode(lineno, NODE_EXPR); 158 | TreeNode* biasRateConst = new TreeNode(lineno, NODE_CONST); 159 | biasRateConst->type = TYPE_INT; 160 | biasRateConst->int_val = biasRate; 161 | biasRateExpr->addChild(biasRateConst); 162 | biasNode->addChild(biasRateExpr); 163 | } 164 | $$->child->type->visitDim++; 165 | newBiasNode->addChild(biasNode); 166 | } 167 | ; 168 | 169 | identifier 170 | : IDENTIFIER { 171 | $$ = $1; 172 | int idNameCount = idNameList.count($$->var_name); 173 | int declCnt = 0; 174 | int minDefDis = MAX_SCOPE_STACK; 175 | 176 | // 搜索变量是否已经声明 177 | auto it = idNameList.find($$->var_name); 178 | int resScoptCmp; 179 | while (idNameCount--) { 180 | resScoptCmp = scopeCmp(presentScope, it->second); 181 | if (resScoptCmp >= 0){ 182 | // 寻找最近的定义 183 | if (resScoptCmp < minDefDis) { 184 | minDefDis = resScoptCmp; 185 | $$ = idList[make_pair(it->first, it->second)]; 186 | } 187 | declCnt++; 188 | } 189 | it++; 190 | } 191 | if (declCnt == 0) { 192 | string t = "Undeclared identifier :'" + $1->var_name + "', scope : " + to_string(resScoptCmp); 193 | yyerror(t.c_str()); 194 | } 195 | }; 196 | 197 | // --------- 声明用标识符 ---------- 198 | declCompIdentifier 199 | : pDeclIdentifier {$$ = $1;} 200 | | arrayDeclIdentifier {$$ = $1;} 201 | ; 202 | 203 | pDeclIdentifier 204 | : declIdentifier {$$ = $1;} 205 | | MUL pDeclIdentifier {$$ = $2; $$->type->pointLevel++;} 206 | | ADDR pDeclIdentifier {$$ = $2; $$->type->pointLevel--;} 207 | ; 208 | 209 | // 常量数组标识符(仅供声明使用) 210 | arrayDeclIdentifier 211 | : pDeclIdentifier LBRACKET INTEGER RBRACKET { 212 | $$ = $1; 213 | $$->type->type = VALUE_ARRAY; 214 | $$->type->elementType = $1->type->type; 215 | $$->type->dimSize[$$->type->dim] = $3->int_val; 216 | $$->type->dim++; 217 | } 218 | | arrayDeclIdentifier LBRACKET INTEGER RBRACKET { 219 | $$ = $1; 220 | $$->type->dimSize[$$->type->dim] = $3->int_val; 221 | $$->type->dim++; 222 | } 223 | ; 224 | 225 | declIdentifier 226 | : IDENTIFIER { 227 | $$ = $1; 228 | $$->var_scope = presentScope; 229 | $$->type = new Type(NOTYPE); 230 | #ifdef ID_REDUCE_DEBUG 231 | cout<<"# $ reduce declIdentifier : "<<$$->var_name<<", at scope :"<var_name, $$->var_scope)) != 0) { 234 | string t = "Redeclared identifier : " + $$->var_name; 235 | yyerror(t.c_str()); 236 | } 237 | idNameList.insert(make_pair($$->var_name, $$->var_scope)); 238 | idList[make_pair($$->var_name, $$->var_scope)] = $$; 239 | } 240 | ; 241 | 242 | // ---------------- 常变量声明 ------------------- 243 | 244 | decl 245 | : constDecl {$$ = $1;} 246 | | varDecl {$$ = $1;} 247 | ; 248 | 249 | constDecl 250 | : CONST basicType constDefs SEMICOLON { 251 | $$ = new TreeNode(lineno, NODE_STMT); 252 | $$->stype = STMT_CONSTDECL; 253 | $$->type = TYPE_NONE; 254 | $$->addChild($2); 255 | $$->addChild($3); 256 | TreeNode* p = $3->child; 257 | while(p != nullptr) { 258 | p->child->type->copy($2->type); 259 | p->child->type->constvar = true; 260 | p = p->sibling; 261 | } 262 | }; 263 | 264 | // 连续常量定义 265 | constDefs 266 | : constDef {$$ = new TreeNode(lineno, NODE_VARLIST); $$->addChild($1);} 267 | | constDefs COMMA constDef {$$ = $1; $$->addChild($3);} 268 | ; 269 | 270 | constDef 271 | : pDeclIdentifier ASSIGN literalConst { 272 | $$ = new TreeNode(lineno, NODE_OP); 273 | $$->optype = OP_DECLASSIGN; 274 | $$->addChild($1); 275 | $$->addChild($3); 276 | } 277 | | arrayDeclIdentifier ASSIGN LBRACE ArrayInitVal RBRACE { 278 | $$ = new TreeNode(lineno, NODE_OP); 279 | $$->optype = OP_DECLASSIGN; 280 | $$->addChild($1); 281 | $$->addChild($4); 282 | } 283 | ; 284 | 285 | // 数组初始化值 286 | ArrayInitVal 287 | : literalConst {$$ = new TreeNode(lineno, NODE_VARLIST); $$->addChild($1);} 288 | | ArrayInitVal COMMA literalConst {$$ = $1; $$->addChild($3);} 289 | ; 290 | 291 | varDecl 292 | : basicType varDefs SEMICOLON { 293 | $$ = new TreeNode(lineno, NODE_STMT); 294 | $$->stype = STMT_DECL; 295 | $$->type = TYPE_NONE; 296 | $$->addChild($1); 297 | $$->addChild($2); 298 | TreeNode* p = $2->child; 299 | while(p != nullptr) { 300 | if (p->nodeType == NODE_OP) { 301 | p->child->type->copy($1->type); 302 | } 303 | else { 304 | p->type->copy($1->type); 305 | } 306 | p = p->sibling; 307 | } 308 | #ifdef DECL_DEBUG 309 | cout << "# $ reduce varDecl type = " << $1->type->getTypeInfo() << endl; 310 | // $$->printAST(); 311 | #endif 312 | } 313 | ; 314 | 315 | // 连续变量定义 316 | varDefs 317 | : varDef {$$ = new TreeNode(lineno, NODE_VARLIST); $$->addChild($1);} 318 | | varDefs COMMA varDef {$$ = $1; $$->addChild($3);} 319 | ; 320 | 321 | varDef 322 | : declCompIdentifier {$$ = $1;} 323 | | declCompIdentifier ASSIGN expr { 324 | $$ = new TreeNode(lineno, NODE_OP); 325 | $$->optype = OP_DECLASSIGN; 326 | $$->addChild($1); 327 | $$->addChild($3); 328 | } 329 | | arrayDeclIdentifier ASSIGN LBRACE ArrayInitVal RBRACE { 330 | $$ = new TreeNode(lineno, NODE_OP); 331 | $$->optype = OP_DECLASSIGN; 332 | $$->addChild($1); 333 | $$->addChild($4); 334 | } 335 | ; 336 | 337 | // ---------------- 函数声明 ------------------- 338 | 339 | funcDef 340 | : basicType pDeclIdentifier funcLPAREN funcFParams RPAREN LBRACE blockItems RBRACE { 341 | $$ = new TreeNode(lineno, NODE_STMT); 342 | $$->stype = STMT_FUNCDECL; 343 | $2->type->type = COMPOSE_FUNCTION; 344 | TreeNode* param = $4; 345 | while (param != nullptr) { 346 | $2->type->paramType[$2->type->paramNum] = param->child->type; 347 | $2->type->paramNum++; 348 | param = param->sibling; 349 | } 350 | $2->type->retType = $1->type; 351 | $$->addChild($1); 352 | $$->addChild($2); 353 | TreeNode* params = new TreeNode(lineno, NODE_VARLIST); 354 | params->addChild($4); 355 | $$->addChild(params); 356 | TreeNode* funcBlock = new TreeNode(lineno, NODE_STMT); 357 | funcBlock->stype = STMT_BLOCK; 358 | funcBlock->addChild($7); 359 | $$->addChild(funcBlock); 360 | scopePop(); 361 | } 362 | | basicType pDeclIdentifier funcLPAREN RPAREN LBRACE blockItems RBRACE { 363 | $$ = new TreeNode(lineno, NODE_STMT); 364 | $$->stype = STMT_FUNCDECL; 365 | $2->type->type = COMPOSE_FUNCTION; 366 | $2->type->retType = $1->type; 367 | $$->addChild($1); 368 | $$->addChild($2); 369 | $$->addChild(new TreeNode(lineno, NODE_VARLIST)); 370 | TreeNode* funcBlock = new TreeNode(lineno, NODE_STMT); 371 | funcBlock->stype = STMT_BLOCK; 372 | funcBlock->addChild($6); 373 | $$->addChild(funcBlock); 374 | scopePop(); 375 | } 376 | ; 377 | 378 | funcLPAREN : LPAREN {scopePush();}; 379 | 380 | funcFParams 381 | : funcFParam {$$ = $1;} 382 | | funcFParams COMMA funcFParam {$$ = $1; $$->addSibling($3);} 383 | ; 384 | 385 | funcFParam 386 | : basicType pDeclIdentifier { 387 | $$ = new TreeNode(lineno, NODE_PARAM); 388 | $$->addChild($1); 389 | $$->addChild($2); 390 | $2->type->copy($1->type); 391 | } 392 | ; 393 | 394 | // ---------------- 语句块 ------------------- 395 | 396 | block 397 | : blockLBRACE blockItems blockRBRACE { 398 | $$ = new TreeNode(lineno, NODE_STMT); 399 | $$->stype = STMT_BLOCK; 400 | $$->addChild($2); 401 | }; 402 | 403 | blockLBRACE : LBRACE {scopePush();} 404 | blockRBRACE : RBRACE {scopePop();} 405 | 406 | blockItems 407 | : blockItem {$$ = $1;} 408 | | blockItems blockItem {$$ = $1; $$->addSibling($2);} 409 | ; 410 | 411 | blockItem 412 | : decl {$$ = $1;} 413 | | stmt {$$ = $1;} 414 | ; 415 | 416 | stmt_ 417 | : LBRACE blockItems RBRACE { 418 | $$ = new TreeNode(lineno, NODE_STMT); 419 | $$->stype = STMT_BLOCK; 420 | $$->addChild($2); 421 | } 422 | | stmt {$$ = $1;} 423 | ; 424 | 425 | stmt 426 | : SEMICOLON {$$ = new TreeNode(lineno, NODE_STMT); $$->stype = STMT_SKIP;} 427 | | expr SEMICOLON {$$ = $1;} 428 | | block {$$ = $1;} 429 | | IF LPAREN cond RPAREN stmt_ ELSE stmt_ { 430 | $$ = new TreeNode(lineno, NODE_STMT); 431 | $$->stype = STMT_IFELSE; 432 | $$->addChild($3); 433 | $$->addChild($5); 434 | $$->addChild($7); 435 | scopePop(); 436 | #ifdef IFELSE_DEBUG 437 | cout << "# $ reduce IF-ELSE at scope : " << presentScope << ", at line " << lineno << endl; 438 | #endif 439 | } 440 | | IF LPAREN cond RPAREN stmt_ { 441 | $$ = new TreeNode(lineno, NODE_STMT); 442 | $$->stype = STMT_IF; 443 | $$->addChild($3); 444 | $$->addChild($5); 445 | scopePop(); 446 | #ifdef IF_DEBUG 447 | cout << "% # $ reduce IF at scope : " << presentScope << ", at line " << lineno << endl; 448 | #endif 449 | } 450 | | WHILE LPAREN cond RPAREN stmt_ { 451 | $$ = new TreeNode(lineno, NODE_STMT); 452 | $$->stype = STMT_WHILE; 453 | $$->addChild($3); 454 | $$->addChild($5); 455 | inCycle = false; 456 | scopePop(); 457 | #ifdef WHILE 458 | cout << "# $ reduce WHILE at scope : " << presentScope << ", at line " << lineno << endl; 459 | #endif 460 | } 461 | | FOR LPAREN basicType varDefs SEMICOLON cond SEMICOLON expr RPAREN stmt_ { 462 | $$ = new TreeNode(lineno, NODE_STMT); 463 | $$->stype = STMT_FOR; 464 | TreeNode* forDecl = new TreeNode(lineno, NODE_STMT); 465 | forDecl->stype = STMT_DECL; 466 | forDecl->addChild($3); 467 | TreeNode* p = $4->child; 468 | while (p) { 469 | if (p->nodeType == NODE_OP) { 470 | p->child->type->copy($3->type); 471 | } 472 | else { 473 | p->type->copy($3->type); 474 | } 475 | p = p->sibling; 476 | } 477 | forDecl->addChild($4); 478 | $$->addChild(forDecl); 479 | $$->addChild($6); 480 | $$->addChild($8); 481 | $$->addChild($10); 482 | inCycle = false; 483 | scopePop(); 484 | } 485 | | FOR LPAREN expr SEMICOLON cond SEMICOLON expr RPAREN stmt_ { 486 | $$ = new TreeNode(lineno, NODE_STMT); 487 | $$->stype = STMT_FOR; 488 | $$->addChild($3); 489 | $$->addChild($5); 490 | $$->addChild($7); 491 | $$->addChild($9); 492 | inCycle = false; 493 | scopePop(); 494 | } 495 | 496 | | BREAK SEMICOLON { 497 | if (!inCycle) { 498 | yyerror("break statement outside loop"); 499 | } 500 | $$ = new TreeNode(lineno, NODE_STMT); 501 | $$->stype = STMT_BREAK; 502 | $$->type = TYPE_NONE; 503 | } 504 | | CONTINUE SEMICOLON{ 505 | if (!inCycle) { 506 | yyerror("continue statement outside loop"); 507 | } 508 | $$ = new TreeNode(lineno, NODE_STMT); 509 | $$->stype = STMT_CONTINUE; 510 | $$->type = TYPE_NONE; 511 | } 512 | | RETURN SEMICOLON {$$ = new TreeNode(lineno, NODE_STMT); $$->stype = STMT_RETURN; $$->type = TYPE_NONE;} 513 | | RETURN expr SEMICOLON {$$ = new TreeNode(lineno, NODE_STMT); $$->stype = STMT_RETURN; $$->addChild($2); $$->type = TYPE_NONE;} 514 | ; 515 | 516 | IF : IF_ {scopePush();}; 517 | WHILE : WHILE_ {inCycle = true; scopePush();}; 518 | FOR : FOR_ {inCycle = true; scopePush();}; 519 | 520 | // ---------------- 表达式 ------------------- 521 | 522 | expr 523 | : addExpr {$$ = $1;} 524 | | compIdentifier ASSIGN expr { 525 | $$ = new TreeNode(lineno, NODE_OP); 526 | $$->optype = OP_ASSIGN; 527 | $$->addChild($1); 528 | $$->addChild($3); 529 | #ifdef ASSIGN_DEBUG 530 | cout << "# $ reduce ASSIGN at scope : " << presentScope << ", at line " << lineno << endl; 531 | // $$->printAST(); 532 | #endif 533 | } 534 | | compIdentifier PLUSASSIGN expr { 535 | $$ = new TreeNode(lineno, NODE_OP); 536 | $$->optype = OP_ADDASSIGN; 537 | $$->addChild($1); 538 | $$->addChild($3); 539 | } 540 | | compIdentifier MINUSASSIGN expr { 541 | $$ = new TreeNode(lineno, NODE_OP); 542 | $$->optype = OP_SUBASSIGN; 543 | $$->addChild($1); 544 | $$->addChild($3); 545 | } 546 | | compIdentifier MULASSIGN expr { 547 | $$ = new TreeNode(lineno, NODE_OP); 548 | $$->optype = OP_MULASSIGN; 549 | $$->addChild($1); 550 | $$->addChild($3); 551 | } 552 | | compIdentifier DIVASSIGN expr { 553 | $$ = new TreeNode(lineno, NODE_OP); 554 | $$->optype = OP_DIVASSIGN; 555 | $$->addChild($1); 556 | $$->addChild($3); 557 | } 558 | ; 559 | 560 | cond 561 | : LOrExpr {$$ = $1;} 562 | ; 563 | 564 | addExpr 565 | : mulExpr {$$ = $1;} 566 | | addExpr PLUS mulExpr {$$ = new TreeNode(lineno, NODE_OP); $$->optype = OP_ADD; $$->addChild($1); $$->addChild($3);} 567 | | addExpr MINUS mulExpr {$$ = new TreeNode(lineno, NODE_OP); $$->optype = OP_SUB; $$->addChild($1); $$->addChild($3);} 568 | ; 569 | 570 | // factor 571 | mulExpr 572 | : unaryExpr {$$ = $1;} 573 | | mulExpr MUL unaryExpr {$$ = new TreeNode(lineno, NODE_OP); $$->optype = OP_MUL; $$->addChild($1); $$->addChild($3);} 574 | | mulExpr DIV unaryExpr {$$ = new TreeNode(lineno, NODE_OP); $$->optype = OP_DIV; $$->addChild($1); $$->addChild($3);} 575 | | mulExpr MOD unaryExpr {$$ = new TreeNode(lineno, NODE_OP); $$->optype = OP_MOD; $$->addChild($1); $$->addChild($3);} 576 | ; 577 | 578 | // 一元表达式 579 | unaryExpr 580 | : primaryExpr {$$ = $1;} 581 | | NOT cond {$$ = new TreeNode(lineno, NODE_OP); $$->optype = OP_NOT; $$->addChild($2);} 582 | | PLUS primaryExpr {$$ = new TreeNode(lineno, NODE_OP); $$->optype = OP_POS; $$->addChild($2);} 583 | | MINUS primaryExpr {$$ = new TreeNode(lineno, NODE_OP); $$->optype = OP_NAG; $$->addChild($2);} 584 | | pIdentifier INC {$$ = new TreeNode(lineno, NODE_OP); $$->optype = OP_INC; $$->addChild($1);} 585 | | pIdentifier DEC {$$ = new TreeNode(lineno, NODE_OP); $$->optype = OP_DEC; $$->addChild($1);} 586 | ; 587 | 588 | // 基本表达式 589 | primaryExpr 590 | : literalConst {$$ = $1;} 591 | | LPAREN expr RPAREN {$$ = $2;} 592 | | LPAREN cond RPAREN {$$ = $2;} 593 | | pIdentifier LPAREN funcRParams RPAREN { 594 | $$ = new TreeNode(lineno, NODE_FUNCALL); 595 | $$->addChild($1); 596 | $$->addChild($3); 597 | #ifdef FUNCALL_DEBUG 598 | cout << "# $ reduce function call at scope : " << presentScope << ", at line " << lineno << endl; 599 | #endif 600 | } 601 | | pIdentifier LPAREN RPAREN { 602 | $$ = new TreeNode(lineno, NODE_FUNCALL); 603 | $$->addChild($1); 604 | $$->addChild(new TreeNode(lineno, NODE_VARLIST)); 605 | #ifdef FUNCALL_DEBUG 606 | cout << "# $ reduce function call at scope : " << presentScope << ", at line " << lineno << endl; 607 | #endif 608 | } 609 | | compIdentifier {$$ = new TreeNode(lineno, NODE_EXPR); $$->addChild($1);} 610 | ; 611 | 612 | // 函数实参列表 613 | funcRParams 614 | : expr {$$ = new TreeNode(lineno, NODE_VARLIST); $$->addChild($1);} 615 | | funcRParams COMMA expr {$$ = $1; $$->addChild($3);} 616 | ; 617 | 618 | // 或表达式 619 | LOrExpr 620 | : LAndExpr {$$ = $1;} 621 | | LAndExpr OR LOrExpr {$$ = new TreeNode(lineno, NODE_OP); $$->optype = OP_OR; $$->addChild($1); $$->addChild($3);} 622 | ; 623 | 624 | // 与 625 | LAndExpr 626 | : eqExpr {$$ = $1;} 627 | | eqExpr AND LAndExpr {$$ = new TreeNode(lineno, NODE_OP); $$->optype = OP_AND; $$->addChild($1); $$->addChild($3);} 628 | ; 629 | 630 | // 相等关系 631 | eqExpr 632 | : relExpr {$$ = $1;} 633 | | relExpr EQ eqExpr {$$ = new TreeNode(lineno, NODE_OP); $$->optype = OP_EQ; $$->addChild($1); $$->addChild($3);} 634 | | relExpr NEQ eqExpr {$$ = new TreeNode(lineno, NODE_OP); $$->optype = OP_NEQ; $$->addChild($1); $$->addChild($3);} 635 | ; 636 | 637 | // 相对关系 638 | relExpr 639 | : expr {$$ = $1;} 640 | | relExpr GRA expr {$$ = new TreeNode(lineno, NODE_OP); $$->optype = OP_GRA; $$->addChild($1); $$->addChild($3);} 641 | | relExpr LES expr {$$ = new TreeNode(lineno, NODE_OP); $$->optype = OP_LES; $$->addChild($1); $$->addChild($3);} 642 | | relExpr GRAEQ expr {$$ = new TreeNode(lineno, NODE_OP); $$->optype = OP_GRAEQ; $$->addChild($1); $$->addChild($3);} 643 | | relExpr LESEQ expr {$$ = new TreeNode(lineno, NODE_OP); $$->optype = OP_LESEQ; $$->addChild($1); $$->addChild($3);} 644 | ; 645 | 646 | %% 647 | 648 | int yyerror(char const * message) 649 | { 650 | cout << "error: " << message << ", at line " << lineno << endl; 651 | parserError = true; 652 | #ifdef EXIT_AT_GRAMMA_ERROR 653 | exit(0); 654 | #else 655 | return 0; 656 | #endif 657 | } 658 | 659 | /* 660 | * 作用域比较函数 int scopeCmp (string, string) 661 | * 662 | * 输入参数: 663 | * presScope: 当前变量所处的作用域 664 | * varScope: 希望进行比较的已声明变量作用域 665 | * 666 | * 返回值: 667 | * 0: 作用域相同, 668 | * 若为变量声明语句,为变量重定义。 669 | * >0: 已声明变量作用域在当前作用域外层,返回作用域距离(堆栈层数) 670 | * 若为声明语句,不产生冲突,当前变量为新定义变量, 671 | * 若为使用语句,当前变量为新定义变量。 672 | * -1:已声明变量作用域在当前作用域内层, 673 | * 若为声明语句,不可能出现这种情况, 674 | * 若为使用语句,不产生冲突。 675 | * -2:两个作用域互不包含,任何情况下都不会互相干扰 676 | */ 677 | int scopeCmp(string presScope, string varScope) { 678 | unsigned int plen = presScope.length(), vlen = varScope.length(); 679 | unsigned int minlen = min(plen, vlen); 680 | if (presScope.substr(0, minlen) == varScope.substr(0, minlen)) { 681 | if (plen >= vlen) 682 | return plen - vlen; 683 | else 684 | return -1; 685 | } 686 | return -2; 687 | } 688 | 689 | void scopePush() { 690 | presentScope += max_scope_id; 691 | max_scope_id = SCOPT_ID_BASE; 692 | top++; 693 | #ifdef SCOPE_DEBUG 694 | cout << "* push -> " << presentScope << ", at line " << lineno << endl; 695 | #endif 696 | } 697 | 698 | void scopePop() { 699 | max_scope_id = presentScope[top] + 1; 700 | presentScope = presentScope.substr(0, presentScope.length() - 1); 701 | top--; 702 | #ifdef SCOPE_DEBUG 703 | cout << "* pop -> " << presentScope << ", at line " << lineno << endl; 704 | #endif 705 | } 706 | 707 | /* 708 | * 变量作用域切换只会发生在以下地方: 709 | * 710 | * 函数体 type funcName ( params ) block 711 | * ↑ push ↑ pop 712 | * 713 | * block块 { stmts } 714 | * ↑ push ↑ pop 715 | * 716 | * if语句 IF ( cond ) block 717 | * ↑ push ↑ pop 718 | * 719 | * IF ( cond ) block ELSE block 720 | * ↑ push ↑ pop 721 | * 722 | * while语句 WHILE ( cond ) block 723 | * ↑ push ↑ pop 724 | * 725 | * for语句 FOR ( expr ; cond ; expr ) block 726 | * ↑ push ↑ pop 727 | * 728 | * FOR ( decl ; cond ; expr ) block 729 | * ↑ push ↑ pop 730 | * 731 | * 可得作用域推进表: 732 | * 733 | * push: 734 | * IF 735 | * WHILE 736 | * FOR 737 | * funcLPAREN 738 | * pop: 739 | * ifStmt(代码段尾部) 740 | * whileStmt(代码段尾部) 741 | * forStmt(代码段尾部) 742 | * funcDef(代码段尾部) 743 | */ 744 | -------------------------------------------------------------------------------- /lab6/src/pch.h: -------------------------------------------------------------------------------- 1 | #ifndef PCH_HPP 2 | #define PCH_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /lab6/src/tree.h: -------------------------------------------------------------------------------- 1 | #ifndef TREE_H 2 | #define TREE_H 3 | 4 | #include "pch.h" 5 | #include "type.h" 6 | 7 | enum NodeType 8 | { 9 | NODE_OP, 10 | NODE_CONST, 11 | NODE_VAR, 12 | NODE_FUNCALL, 13 | 14 | NODE_PROG, 15 | NODE_STMT, 16 | NODE_EXPR, 17 | NODE_TYPE, 18 | NODE_VARLIST, 19 | NODE_PARAM, 20 | }; 21 | 22 | enum OperatorType 23 | { 24 | OP_EQ, // == 25 | OP_NEQ, // != 26 | OP_GRAEQ, // >= 27 | OP_LESEQ, // <= 28 | OP_ADDASSIGN, // += 29 | OP_SUBASSIGN, // -= 30 | OP_MULASSIGN, // *= 31 | OP_DIVASSIGN, // /= 32 | OP_DECLASSIGN, // = (仅在常变量声明赋值时使用) 33 | OP_ASSIGN, // = 34 | OP_GRA, // > 35 | OP_LES, // < 36 | OP_INC, // ++ 37 | OP_DEC, // -- 38 | OP_ADD, // + 39 | OP_SUB, // - 40 | OP_POS, // + (一元运算符) 41 | OP_NAG, // - (一元运算符) 42 | OP_MUL, // * 43 | OP_DIV, // / 44 | OP_MOD, // % 45 | OP_NOT, // ! 46 | OP_AND, // && 47 | OP_OR, // || 48 | OP_INDEX, // [] 下标运算符 49 | }; 50 | 51 | enum StmtType { 52 | STMT_SKIP, 53 | STMT_BLOCK, 54 | STMT_DECL, 55 | STMT_CONSTDECL, 56 | STMT_FUNCDECL, 57 | STMT_IFELSE, 58 | STMT_IF, 59 | STMT_WHILE, 60 | STMT_FOR, 61 | STMT_RETURN, 62 | STMT_CONTINUE, 63 | STMT_BREAK, 64 | }; 65 | 66 | struct Label { 67 | string true_label; 68 | string false_label; 69 | string begin_label; 70 | string next_label; 71 | }; 72 | 73 | struct TreeNode { 74 | public: 75 | int lineno; 76 | 77 | // -------------- 语法树构造 ---------------- 78 | 79 | TreeNode* child = nullptr; 80 | TreeNode* sibling = nullptr; 81 | 82 | NodeType nodeType; 83 | OperatorType optype;// 运算符类型 84 | StmtType stype; // 表达式类型 85 | Type* type; // 变量、类型、表达式结点,有类型。 86 | int int_val; 87 | char ch_val; 88 | bool b_val; 89 | string str_val; 90 | string var_name; 91 | string var_scope; // 变量作用域标识符 92 | int pointLevel; 93 | 94 | TreeNode(int lineno, NodeType type); 95 | TreeNode(TreeNode* node); // 仅用于叶节点拷贝,函数不复制子节点,也不复制子节点指针 96 | void addChild(TreeNode*); 97 | void addSibling(TreeNode*); 98 | int getChildNum(); 99 | int getVal(); 100 | 101 | int nodeID; 102 | void genNodeId(); 103 | 104 | // -------------- 输出语法树 ---------------- 105 | 106 | void printAST(); 107 | void printNodeInfo(); 108 | void printChildrenId(); 109 | void printSpecialInfo(); 110 | void printConstVal(); 111 | 112 | // -------------- 类型检查 ---------------- 113 | 114 | void typeCheck(); 115 | void findReturn(vector &retList); 116 | 117 | // ------------- asm 代码生成 ------------- 118 | 119 | int node_seq = 0; 120 | int temp_var_seq = 0; 121 | Label label; 122 | 123 | void gen_header(); 124 | void gen_var_decl(); 125 | void gen_str(); 126 | 127 | string new_label(); 128 | void get_label(); 129 | 130 | void genCode(); 131 | 132 | // 传入标识符结点或OP_INDEX数组下标结点指针, 133 | // 返回它在汇编中的变量表示。 134 | // 注意:如果传入下标运算符结点,务必保证 135 | // 此时的eax寄存器已经完成了偏移量的计算, 136 | // 即先执行了OP_INDEX结点的右子树的genCode() 137 | string getVarNameCode(TreeNode* p); 138 | 139 | public: 140 | static string nodeType2String (NodeType type); 141 | static string opType2String (OperatorType type); 142 | static string sType2String (StmtType type); 143 | }; 144 | 145 | void InitIOFunctionNode(); 146 | static TreeNode *nodeScanf = new TreeNode(0, NODE_VAR); 147 | static TreeNode* nodePrintf = new TreeNode(0, NODE_VAR); 148 | 149 | extern bool typeError; 150 | 151 | #endif 152 | -------------------------------------------------------------------------------- /lab6/src/type.cpp: -------------------------------------------------------------------------------- 1 | #include "type.h" 2 | 3 | Type::Type(ValueType valueType) { 4 | this->type = valueType; 5 | this->paramNum = 0; 6 | this->constvar = false; 7 | this->retType = nullptr; 8 | this->dim = 0; 9 | this->visitDim = 0; 10 | } 11 | 12 | void Type::copy(Type* a) { 13 | this->type = a->type; 14 | this->constvar = a->constvar; 15 | if (a->paramNum) { 16 | this->paramNum = a->paramNum; 17 | for (unsigned short i=0;iparamNum;i++) { 18 | this->paramType[i] = a->paramType[i]; 19 | } 20 | this->retType = a->retType; 21 | } 22 | if (a->dim) { 23 | this->dim = a->dim; 24 | this->elementType = a->elementType; 25 | for (unsigned int i=0;idim;i++) { 26 | this->dimSize[i] = a->dimSize[i]; 27 | } 28 | } 29 | } 30 | 31 | string Type::getTypeInfo() { 32 | return getTypeInfo(this->type); 33 | } 34 | 35 | string Type::getTypeInfo(ValueType type) { 36 | switch(type) { 37 | case VALUE_BOOL: 38 | return "bool"; 39 | case VALUE_INT: 40 | return "int"; 41 | case VALUE_CHAR: 42 | return "char"; 43 | case VALUE_STRING: 44 | return "string"; 45 | case VALUE_ARRAY: 46 | if (this->dim > 0) { 47 | string buf = getTypeInfo(this->elementType); 48 | for (unsigned int i = 0; i < dim && i < MAX_ARRAY_DIM; i++) { 49 | buf += "[" + to_string(dimSize[i]) + "]"; 50 | } 51 | return buf; 52 | } 53 | return ""; 54 | case VALUE_VOID: 55 | return "void"; 56 | case NOTYPE: 57 | return "no type"; 58 | default: 59 | return "?"; 60 | } 61 | } 62 | 63 | void Type::addParam(Type* param){ 64 | this->paramType[paramNum++] = param; 65 | } 66 | 67 | void Type::addRet(Type* t){ 68 | this->retType = t; 69 | } 70 | 71 | int Type::getSize() { 72 | int size = 1; 73 | int eleSize; 74 | switch (type) 75 | { 76 | case VALUE_BOOL: 77 | case VALUE_INT: 78 | case VALUE_CHAR: 79 | case VALUE_STRING: 80 | return 4; 81 | case VALUE_ARRAY: 82 | eleSize = 4; 83 | for (unsigned int i = 0; i < dim; i++) 84 | size *= dimSize[i]; 85 | return eleSize * size; 86 | default: 87 | return 0; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /lab6/src/type.h: -------------------------------------------------------------------------------- 1 | #ifndef TYPESYSTEM_H 2 | #define TYPESYSTEM_H 3 | #include "./pch.h" 4 | 5 | using namespace std; 6 | 7 | #define MAX_PARAM 16 8 | #define MAX_ARRAY_DIM 8 9 | #define MAX_SCOPE_STACK 32 10 | #define SCOPT_ID_BASE '1' 11 | 12 | // #define EXIT_AT_GRAMMA_ERROR 13 | 14 | // #define DEBUG 15 | #ifdef DEBUG 16 | 17 | // #define AST 18 | // #define PARSER_DEBUG 19 | #ifdef PARSER_DEBUG 20 | // #define SCOPE_DEBUG 21 | // #define ID_REDUCE_DEBUG 22 | // #define DECL_DEBUG 23 | // #define POINT_DEBUG 24 | // #define ASSIGN_DEBUG 25 | // #define IF_DEBUG 26 | // #define IFELSE_DEBUG 27 | // #define WHILE_DEBUG 28 | // #define FUNCALL_DEBUG 29 | #endif 30 | // #define typeCheck_debug 31 | // #define childNumdebug 32 | // #define varDeclDebug 33 | 34 | #endif 35 | 36 | enum ValueType 37 | { 38 | NOTYPE, 39 | VALUE_BOOL, 40 | VALUE_INT, 41 | VALUE_CHAR, 42 | VALUE_STRING, 43 | VALUE_VOID, 44 | VALUE_ARRAY, 45 | COMPOSE_FUNCTION 46 | }; 47 | 48 | class Type 49 | { 50 | public: 51 | bool constvar; 52 | ValueType type; 53 | Type(ValueType valueType); 54 | // 将b复制到自己中 55 | void copy(Type* a); 56 | 57 | public: 58 | int pointLevel = 0; 59 | 60 | unsigned short paramNum; // for function 61 | Type* paramType[MAX_PARAM]; 62 | Type* retType; 63 | void addParam(Type* t); 64 | void addRet(Type* t); 65 | 66 | unsigned int dim; // for array 67 | ValueType elementType; 68 | int dimSize[MAX_ARRAY_DIM]; 69 | // 下一次使用下标运算符会访问的维度 70 | unsigned int visitDim = 0; 71 | 72 | int getSize(); 73 | 74 | public: 75 | string getTypeInfo(); 76 | string getTypeInfo(ValueType type); 77 | }; 78 | 79 | // 设置几个常量Type,可以节省空间开销 80 | static Type* TYPE_INT = new Type(VALUE_INT); 81 | static Type* TYPE_CHAR = new Type(VALUE_CHAR); 82 | static Type* TYPE_BOOL = new Type(VALUE_BOOL); 83 | static Type* TYPE_STRING = new Type(VALUE_STRING); 84 | static Type* TYPE_VOID = new Type(VALUE_VOID); 85 | static Type* TYPE_NONE = new Type(NOTYPE); 86 | 87 | int getSize(Type* type); 88 | 89 | #endif -------------------------------------------------------------------------------- /lab6/test.out: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab6/test.out -------------------------------------------------------------------------------- /lab6/test/1/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab6/test/1/.gitkeep -------------------------------------------------------------------------------- /lab6/test/1/00_main.c: -------------------------------------------------------------------------------- 1 | int main(){ 2 | return 0; 3 | } -------------------------------------------------------------------------------- /lab6/test/1/00_main.in: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab6/test/1/00_main.in -------------------------------------------------------------------------------- /lab6/test/1/01_basic_out.c: -------------------------------------------------------------------------------- 1 | int main(){ 2 | printf("test\n"); 3 | return 0; 4 | } -------------------------------------------------------------------------------- /lab6/test/1/01_basic_out.in: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab6/test/1/01_basic_out.in -------------------------------------------------------------------------------- /lab6/test/1/02_var_out.c: -------------------------------------------------------------------------------- 1 | int main(){ 2 | int a; 3 | a=10; 4 | printf("test:%d\n",a); 5 | return 0; 6 | } -------------------------------------------------------------------------------- /lab6/test/1/02_var_out.in: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab6/test/1/02_var_out.in -------------------------------------------------------------------------------- /lab6/test/1/03_basic_in.c: -------------------------------------------------------------------------------- 1 | int main(){ 2 | int a; 3 | scanf("%d",&a); 4 | printf("test:%d\n",a); 5 | return 0; 6 | } -------------------------------------------------------------------------------- /lab6/test/1/03_basic_in.in: -------------------------------------------------------------------------------- 1 | 10 -------------------------------------------------------------------------------- /lab6/test/1/04_if.c: -------------------------------------------------------------------------------- 1 | int main(){ 2 | int a; 3 | scanf("%d",&a); 4 | if(a>0){ 5 | a-=20; 6 | } 7 | printf("test:%d\n",a); 8 | return 0; 9 | } -------------------------------------------------------------------------------- /lab6/test/1/04_if.in: -------------------------------------------------------------------------------- 1 | 12 -------------------------------------------------------------------------------- /lab6/test/1/05_if_notin.c: -------------------------------------------------------------------------------- 1 | int main(){ 2 | int a; 3 | scanf("%d",&a); 4 | if(a>0){ 5 | a-=20; 6 | } 7 | printf("test:%d\n",a); 8 | return 0; 9 | } -------------------------------------------------------------------------------- /lab6/test/1/05_if_notin.in: -------------------------------------------------------------------------------- 1 | -13 -------------------------------------------------------------------------------- /lab6/test/1/06_if_else.c: -------------------------------------------------------------------------------- 1 | int main(){ 2 | int a; 3 | a=10; 4 | if(a>9){ 5 | a-=20; 6 | }else{ 7 | a+=15; 8 | } 9 | printf("test:%d\n",a); 10 | return 0; 11 | } -------------------------------------------------------------------------------- /lab6/test/1/06_if_else.in: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab6/test/1/06_if_else.in -------------------------------------------------------------------------------- /lab6/test/1/07_if_else_notin.c: -------------------------------------------------------------------------------- 1 | int main(){ 2 | int a; 3 | a=10; 4 | if(a>16){ 5 | a-=20; 6 | }else{ 7 | a+=15; 8 | } 9 | printf("test:%d\n",a); 10 | return 0; 11 | } -------------------------------------------------------------------------------- /lab6/test/1/07_if_else_notin.in: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab6/test/1/07_if_else_notin.in -------------------------------------------------------------------------------- /lab6/test/1/08_expr_add.c: -------------------------------------------------------------------------------- 1 | int main(){ 2 | int a; 3 | int b; 4 | scanf("%d",&a); 5 | scanf("%d",&b); 6 | int c; 7 | c=a+b; 8 | printf("test:%d\n",c); 9 | return 0; 10 | } -------------------------------------------------------------------------------- /lab6/test/1/08_expr_add.in: -------------------------------------------------------------------------------- 1 | 156 2 | 245 -------------------------------------------------------------------------------- /lab6/test/1/09_expr_sub.c: -------------------------------------------------------------------------------- 1 | int main(){ 2 | int a; 3 | int b; 4 | scanf("%d",&a); 5 | scanf("%d",&b); 6 | int c; 7 | c=a-b; 8 | printf("test:%d\n",c); 9 | return 0; 10 | } -------------------------------------------------------------------------------- /lab6/test/1/09_expr_sub.in: -------------------------------------------------------------------------------- 1 | 100 2 | 1 -------------------------------------------------------------------------------- /lab6/test/1/10_expr_mul.c: -------------------------------------------------------------------------------- 1 | int main(){ 2 | int a; 3 | int b; 4 | scanf("%d",&a); 5 | scanf("%d",&b); 6 | int c; 7 | c=a*b; 8 | printf("test:%d\n",c); 9 | return 0; 10 | } -------------------------------------------------------------------------------- /lab6/test/1/10_expr_mul.in: -------------------------------------------------------------------------------- 1 | 14 2 | 27 -------------------------------------------------------------------------------- /lab6/test/1/11_expr_div.c: -------------------------------------------------------------------------------- 1 | int main(){ 2 | int a; 3 | int b; 4 | scanf("%d",&a); 5 | scanf("%d",&b); 6 | int c; 7 | c=a/b; 8 | printf("test:%d\n",c); 9 | return 0; 10 | } -------------------------------------------------------------------------------- /lab6/test/1/11_expr_div.in: -------------------------------------------------------------------------------- 1 | 37 2 | 19 -------------------------------------------------------------------------------- /lab6/test/1/12_expr_mod.c: -------------------------------------------------------------------------------- 1 | int main(){ 2 | int a; 3 | int b; 4 | scanf("%d",&a); 5 | scanf("%d",&b); 6 | int c; 7 | c=a%b; 8 | printf("test:%d\n",c); 9 | return 0; 10 | } -------------------------------------------------------------------------------- /lab6/test/1/12_expr_mod.in: -------------------------------------------------------------------------------- 1 | 64 2 | 27 -------------------------------------------------------------------------------- /lab6/test/1/13_expr_minus.c: -------------------------------------------------------------------------------- 1 | int main(){ 2 | int a; 3 | scanf("%d",&a); 4 | int c; 5 | c=-a; 6 | printf("test:%d\n",c); 7 | return 0; 8 | } -------------------------------------------------------------------------------- /lab6/test/1/13_expr_minus.in: -------------------------------------------------------------------------------- 1 | -120 -------------------------------------------------------------------------------- /lab6/test/1/14_expr_eq.c: -------------------------------------------------------------------------------- 1 | int main(){ 2 | int a; 3 | int b; 4 | scanf("%d",&a); 5 | scanf("%d",&b); 6 | if(a==b){ 7 | printf("Success\n"); 8 | }else{ 9 | printf("Failed\n"); 10 | } 11 | return 0; 12 | } -------------------------------------------------------------------------------- /lab6/test/1/14_expr_eq.in: -------------------------------------------------------------------------------- 1 | 120 2 | 120 -------------------------------------------------------------------------------- /lab6/test/1/15_expr_gr.c: -------------------------------------------------------------------------------- 1 | int main(){ 2 | int a; 3 | int b; 4 | scanf("%d",&a); 5 | scanf("%d",&b); 6 | if(a>b){ 7 | printf("Success\n"); 8 | }else{ 9 | printf("Failed\n"); 10 | } 11 | return 0; 12 | } -------------------------------------------------------------------------------- /lab6/test/1/15_expr_gr.in: -------------------------------------------------------------------------------- 1 | 120 2 | -120 -------------------------------------------------------------------------------- /lab6/test/1/16_expr_lr.c: -------------------------------------------------------------------------------- 1 | int main(){ 2 | int a; 3 | int b; 4 | scanf("%d",&a); 5 | scanf("%d",&b); 6 | if(a=b){ 7 | printf("Success\n"); 8 | }else{ 9 | printf("Failed\n"); 10 | } 11 | return 0; 12 | } -------------------------------------------------------------------------------- /lab6/test/1/17_expr_ge.in: -------------------------------------------------------------------------------- 1 | -1 2 | -1 -------------------------------------------------------------------------------- /lab6/test/1/18_expr_le.c: -------------------------------------------------------------------------------- 1 | int main(){ 2 | int a; 3 | int b; 4 | scanf("%d",&a); 5 | scanf("%d",&b); 6 | if(a<=b){ 7 | printf("Success\n"); 8 | }else{ 9 | printf("Failed\n"); 10 | } 11 | return 0; 12 | } -------------------------------------------------------------------------------- /lab6/test/1/18_expr_le.in: -------------------------------------------------------------------------------- 1 | -1 2 | 0 -------------------------------------------------------------------------------- /lab6/test/1/19_expr_ne.c: -------------------------------------------------------------------------------- 1 | int main(){ 2 | int a; 3 | int b; 4 | scanf("%d",&a); 5 | scanf("%d",&b); 6 | if(a!=b){ 7 | printf("Success\n"); 8 | }else{ 9 | printf("Failed\n"); 10 | } 11 | return 0; 12 | } -------------------------------------------------------------------------------- /lab6/test/1/19_expr_ne.in: -------------------------------------------------------------------------------- 1 | 1024 2 | 256 -------------------------------------------------------------------------------- /lab6/test/1/20_expr_or.c: -------------------------------------------------------------------------------- 1 | int main(){ 2 | int a; 3 | int b; 4 | scanf("%d",&a); 5 | scanf("%d",&b); 6 | if((a==b)||(a!=b)){ 7 | printf("Success\n"); 8 | }else{ 9 | printf("Failed\n"); 10 | } 11 | return 0; 12 | } -------------------------------------------------------------------------------- /lab6/test/1/20_expr_or.in: -------------------------------------------------------------------------------- 1 | 0 2 | 1 -------------------------------------------------------------------------------- /lab6/test/1/21_expr_and.c: -------------------------------------------------------------------------------- 1 | int main(){ 2 | int a; 3 | int b; 4 | scanf("%d",&a); 5 | scanf("%d",&b); 6 | if((ab)){ 7 | printf("Failed\n"); 8 | }else{ 9 | printf("Success\n"); 10 | } 11 | return 0; 12 | } -------------------------------------------------------------------------------- /lab6/test/1/21_expr_and.in: -------------------------------------------------------------------------------- 1 | 0 2 | 2 -------------------------------------------------------------------------------- /lab6/test/1/22_expr_not.c: -------------------------------------------------------------------------------- 1 | int main(){ 2 | int a; 3 | int b; 4 | scanf("%d",&a); 5 | scanf("%d",&b); 6 | if(!(a!=b)){ 7 | printf("Success\n"); 8 | }else{ 9 | printf("Failed\n"); 10 | } 11 | return 0; 12 | } -------------------------------------------------------------------------------- /lab6/test/1/22_expr_not.in: -------------------------------------------------------------------------------- 1 | 0 2 | 0 -------------------------------------------------------------------------------- /lab6/test/1/23_loop_while.c: -------------------------------------------------------------------------------- 1 | int main(){ 2 | int a; 3 | scanf("%d",&a); 4 | while(a>0){ 5 | a=a-1; 6 | printf("In Loop\n"); 7 | } 8 | printf("End Loop\n"); 9 | return 0; 10 | } -------------------------------------------------------------------------------- /lab6/test/1/23_loop_while.in: -------------------------------------------------------------------------------- 1 | 30 -------------------------------------------------------------------------------- /lab6/test/1/24_loop_for.c: -------------------------------------------------------------------------------- 1 | int main(){ 2 | int a; 3 | for(a=0;a<200;a=a+1){ 4 | printf("In Loop\n"); 5 | } 6 | printf("End Loop\n"); 7 | return 0; 8 | } -------------------------------------------------------------------------------- /lab6/test/1/24_loop_for.in: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab6/test/1/24_loop_for.in -------------------------------------------------------------------------------- /lab6/test/1/25_comment.c: -------------------------------------------------------------------------------- 1 | // comment line 2 | int main(){ 3 | int a; 4 | a=2; 5 | /** 6 | * a=15; 7 | * if(a<2){ 8 | * a=0; 9 | * }else{ 10 | * printf("Test Comment\n"); 11 | * } 12 | **/ 13 | printf("Test:%d\n",a); 14 | return 0; 15 | } -------------------------------------------------------------------------------- /lab6/test/1/25_comment.in: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab6/test/1/25_comment.in -------------------------------------------------------------------------------- /lab6/test/1/26_multi_var.c: -------------------------------------------------------------------------------- 1 | int main(){ 2 | int a,b,c; 3 | scanf("%d",&a); 4 | scanf("%d",&b); 5 | scanf("%d",&c); 6 | printf("%d ",a); 7 | printf("%d ",b); 8 | printf("%d\n",c); 9 | return 0; 10 | } -------------------------------------------------------------------------------- /lab6/test/1/26_multi_var.in: -------------------------------------------------------------------------------- 1 | 104 2 | 205 3 | 306 -------------------------------------------------------------------------------- /lab6/test/1/27_char.c: -------------------------------------------------------------------------------- 1 | int main(){ 2 | char s='9'; 3 | char t='\t'; 4 | char a='t'; 5 | char r='\n'; 6 | t='a'; 7 | printf("%c",s); 8 | printf("%c",t); 9 | printf("%c",a); 10 | printf("%c",r); 11 | printf("%c",t); 12 | return 0; 13 | } -------------------------------------------------------------------------------- /lab6/test/1/27_char.in: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab6/test/1/27_char.in -------------------------------------------------------------------------------- /lab6/test/1/28_prior_1.c: -------------------------------------------------------------------------------- 1 | int a; 2 | int b; 3 | int c; 4 | int main(){ 5 | a = 16; 6 | b = 2; 7 | c = 30; 8 | int d; 9 | d = a+b*c; 10 | printf("%d\n",d); 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /lab6/test/1/28_prior_1.in: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab6/test/1/28_prior_1.in -------------------------------------------------------------------------------- /lab6/test/1/29_prior_2.c: -------------------------------------------------------------------------------- 1 | int main() { 2 | int a; 3 | a = 20; 4 | int b; 5 | b = 5; 6 | int c; 7 | c = 6; 8 | int d; 9 | d = -4; 10 | a = a + c * d - b % (a + d) / a; 11 | printf("%d",a); 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /lab6/test/1/29_prior_2.in: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab6/test/1/29_prior_2.in -------------------------------------------------------------------------------- /lab6/test/1/30_prior_3.c: -------------------------------------------------------------------------------- 1 | int main () { 2 | int a; 3 | int b; 4 | int c; 5 | a = 1; 6 | b = 4; 7 | c = 28; 8 | int t; 9 | if (c + a != b) { 10 | t = c % -b; 11 | printf("%d\n",t); 12 | } 13 | if (b - c == a) { 14 | t = c%b+b; 15 | printf("%d\n",t); 16 | } 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /lab6/test/1/30_prior_3.in: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab6/test/1/30_prior_3.in -------------------------------------------------------------------------------- /lab6/test/1/31_prior_4.c: -------------------------------------------------------------------------------- 1 | int main () { 2 | int a; 3 | int b; 4 | int c; 5 | int d; 6 | a = 3; 7 | b = 8; 8 | c = -4; 9 | d = 15; 10 | int t; 11 | if (d % (b - a) != 0 && a > 0 || d % 3 == 0 && c > 0) { 12 | t = d + c - -b; 13 | printf("%d",t); 14 | } 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /lab6/test/1/31_prior_4.in: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab6/test/1/31_prior_4.in -------------------------------------------------------------------------------- /lab6/test/1/32_prior_5.c: -------------------------------------------------------------------------------- 1 | int main () { 2 | int a; 3 | int b; 4 | a = -2; 5 | b = 1; 6 | a = a - -b + -(a + b) % -(a - b); 7 | printf("%d\n",a); 8 | return 0; 9 | } 10 | -------------------------------------------------------------------------------- /lab6/test/1/32_prior_5.in: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab6/test/1/32_prior_5.in -------------------------------------------------------------------------------- /lab6/test/1/33_expr_multi_assign.c: -------------------------------------------------------------------------------- 1 | int main(){ 2 | int a; 3 | int b; 4 | a=b=3; 5 | printf("%d",a); 6 | printf("%d",b); 7 | return 0; 8 | } -------------------------------------------------------------------------------- /lab6/test/1/33_expr_multi_assign.in: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab6/test/1/33_expr_multi_assign.in -------------------------------------------------------------------------------- /lab6/test/1/34_if_else_multista.c: -------------------------------------------------------------------------------- 1 | int main(){ 2 | int a=10; 3 | if(a>9){ 4 | a=a-10; 5 | a=a%6; 6 | }else{ 7 | a=2; 8 | a=a-30; 9 | } 10 | printf("Test:%d\n",a); 11 | return 0; 12 | } -------------------------------------------------------------------------------- /lab6/test/1/34_if_else_multista.in: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab6/test/1/34_if_else_multista.in -------------------------------------------------------------------------------- /lab6/test/1/35_while_if.c: -------------------------------------------------------------------------------- 1 | int main(){ 2 | int a; 3 | a = 0; 4 | int b; 5 | b = 0; 6 | while (a < 100) { 7 | if (a == 5) { 8 | b = 25; 9 | }else if (a == 10) { 10 | b = 42; 11 | }else { 12 | b = a * 2; 13 | } 14 | a = a + 1; 15 | } 16 | printf("%d\n",a); 17 | printf("%d\n",b); 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /lab6/test/1/35_while_if.in: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab6/test/1/35_while_if.in -------------------------------------------------------------------------------- /lab6/test/1/36_if_complex_expr.c: -------------------------------------------------------------------------------- 1 | int main () { 2 | int a; 3 | int b; 4 | int c; 5 | int d; 6 | int result; 7 | a = 5; 8 | b = 5; 9 | c = 1; 10 | d = -2; 11 | result = 2; 12 | if ((d * 1 / 2) < 0 || (a - b) != 0 && (c + 3) % 2 != 0) { 13 | printf("%d\n",result); 14 | } 15 | if ((d % 2 + 67) < 0 || (a - b) != 0 && (c + 2) % 2 != 0) { 16 | result = 4; 17 | printf("%d\n",result); 18 | } 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /lab6/test/1/36_if_complex_expr.in: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab6/test/1/36_if_complex_expr.in -------------------------------------------------------------------------------- /lab6/test/1/37_neg_div_mod.c: -------------------------------------------------------------------------------- 1 | int main(){ 2 | int a; 3 | int b; 4 | a=-100020; 5 | b=-3; 6 | int c; 7 | int d; 8 | c=a/b; 9 | d=a%b; 10 | printf("test:%d %d\n",c,d); 11 | return 0; 12 | } -------------------------------------------------------------------------------- /lab6/test/1/37_neg_div_mod.in: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab6/test/1/37_neg_div_mod.in -------------------------------------------------------------------------------- /lab6/test/2/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab6/test/2/.gitkeep -------------------------------------------------------------------------------- /lab6/test/2/00_multi_scope.c: -------------------------------------------------------------------------------- 1 | int a=10; 2 | int main(){ 3 | int a; 4 | a=1; 5 | for(int i=0;i<10;i=i+1){ 6 | int a=i*10+i%3; 7 | printf("Test %d %d\n",i,a); 8 | } 9 | printf("Test %d\n",a); 10 | return 0; 11 | } -------------------------------------------------------------------------------- /lab6/test/2/00_multi_scope.in: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab6/test/2/00_multi_scope.in -------------------------------------------------------------------------------- /lab6/test/2/01_const.c: -------------------------------------------------------------------------------- 1 | const int at=10; 2 | int main(){ 3 | printf("Test:%d\n",at); 4 | return 0; 5 | } -------------------------------------------------------------------------------- /lab6/test/2/01_const.in: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab6/test/2/01_const.in -------------------------------------------------------------------------------- /lab6/test/2/02_hex.c: -------------------------------------------------------------------------------- 1 | int main(){ 2 | int a=0xffffffff; 3 | if(a==-1){ 4 | printf("True!\n"); 5 | }else{ 6 | printf("False!\n"); 7 | } 8 | return 0; 9 | } -------------------------------------------------------------------------------- /lab6/test/2/02_hex.in: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab6/test/2/02_hex.in -------------------------------------------------------------------------------- /lab6/test/2/03_oct.c: -------------------------------------------------------------------------------- 1 | int main(){ 2 | int a=037777777777; 3 | if(a==-1){ 4 | printf("True!\n"); 5 | }else{ 6 | printf("False!\n"); 7 | } 8 | return 0; 9 | } -------------------------------------------------------------------------------- /lab6/test/2/03_oct.in: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab6/test/2/03_oct.in -------------------------------------------------------------------------------- /lab6/test/2/04_array.c: -------------------------------------------------------------------------------- 1 | int a[10]; 2 | int main(){ 3 | for(int i=0;i<10;i=i+1){ 4 | a[i]=i+1; 5 | } 6 | for(int i=0;i<10;i=i+1){ 7 | printf("%d\n",a[i]); 8 | } 9 | return 0; 10 | } -------------------------------------------------------------------------------- /lab6/test/2/04_array.in: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab6/test/2/04_array.in -------------------------------------------------------------------------------- /lab6/test/2/05_multi_array.c: -------------------------------------------------------------------------------- 1 | int a[10][10]; 2 | int main(){ 3 | for(int i=0;i<10;i=i+1){ 4 | for(int j=0;j<10;j=j+1){ 5 | a[i][j]=i*j+i+j; 6 | } 7 | } 8 | for(int i=0;i<10;i=i+1){ 9 | for(int j=0;j<10;j=j+1){ 10 | printf("%d\n",a[i][j]); 11 | } 12 | } 13 | return 0; 14 | } -------------------------------------------------------------------------------- /lab6/test/2/05_multi_array.in: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab6/test/2/05_multi_array.in -------------------------------------------------------------------------------- /lab6/test/2/06_struct.c: -------------------------------------------------------------------------------- 1 | struct Node{ 2 | int num; 3 | int id; 4 | }; 5 | int main(){ 6 | for(int i=0;i<10;i=i+1){ 7 | struct Node s; 8 | s.num=i*2; 9 | s.id=i; 10 | printf("%d ",s.num); 11 | printf("%d\n",s.id); 12 | } 13 | return 0; 14 | } -------------------------------------------------------------------------------- /lab6/test/2/06_struct.in: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab6/test/2/06_struct.in -------------------------------------------------------------------------------- /lab6/test/2/07_pointer.c: -------------------------------------------------------------------------------- 1 | int main(){ 2 | int *point; 3 | for(int i=0;i<10;i=i+1){ 4 | int a=i+10; 5 | point=&a; 6 | printf("%d\n",*point); 7 | } 8 | return 0; 9 | } -------------------------------------------------------------------------------- /lab6/test/2/07_pointer.in: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab6/test/2/07_pointer.in -------------------------------------------------------------------------------- /lab6/test/2/08_var_assign.c: -------------------------------------------------------------------------------- 1 | int main(){ 2 | int a=20,b,c=16; 3 | scanf("%d",&b); 4 | printf("Test:%d",a); 5 | printf(" %d",b); 6 | printf(" %d\n",c); 7 | return 0; 8 | } -------------------------------------------------------------------------------- /lab6/test/2/08_var_assign.in: -------------------------------------------------------------------------------- 1 | 156 -------------------------------------------------------------------------------- /lab6/test/3/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab6/test/3/.gitkeep -------------------------------------------------------------------------------- /lab6/test/3/00_break.c: -------------------------------------------------------------------------------- 1 | int main(){ 2 | for(int i=0;i<10;i=i+1){ 3 | printf("Test:%d\n",i); 4 | if(i>5){ 5 | printf("Break\n"); 6 | break; 7 | } 8 | } 9 | return 0; 10 | } -------------------------------------------------------------------------------- /lab6/test/3/00_break.in: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab6/test/3/00_break.in -------------------------------------------------------------------------------- /lab6/test/3/01_continue.c: -------------------------------------------------------------------------------- 1 | int main(){ 2 | for(int i=0;i<10;i=i+1){ 3 | printf("%d\n",i); 4 | if(i<5){ 5 | printf("Continue\n"); 6 | continue; 7 | } 8 | break; 9 | } 10 | return 0; 11 | } -------------------------------------------------------------------------------- /lab6/test/3/01_continue.in: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab6/test/3/01_continue.in -------------------------------------------------------------------------------- /lab6/test/3/02_multi_param_io.c: -------------------------------------------------------------------------------- 1 | int main(){ 2 | int a,b,c; 3 | scanf("%d %d %d",&a,&b,&c); 4 | printf("%d %d %d\n",a,b,c); 5 | return 0; 6 | } -------------------------------------------------------------------------------- /lab6/test/3/02_multi_param_io.in: -------------------------------------------------------------------------------- 1 | 16 20 36 -------------------------------------------------------------------------------- /lab6/test/3/03_func_1.c: -------------------------------------------------------------------------------- 1 | int a; 2 | 3 | int myFunc(int a, int b, int c) { 4 | a = 2; 5 | { 6 | int c; 7 | c = 0; 8 | if (c != 0) { 9 | return 0; 10 | } 11 | } 12 | while (b > 0) { 13 | b = b - 1; 14 | } 15 | return (a)+(b); 16 | } 17 | 18 | int main() { 19 | a = (3); 20 | int b; 21 | b = myFunc(1, 2, 1); 22 | printf("%d\n",a+b); 23 | return 0; 24 | } -------------------------------------------------------------------------------- /lab6/test/3/03_func_1.in: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab6/test/3/03_func_1.in -------------------------------------------------------------------------------- /lab6/test/3/04_func_2.c: -------------------------------------------------------------------------------- 1 | int func1() { 2 | int a; 3 | a = 1; 4 | return a; 5 | } 6 | 7 | int func2() { 8 | int a; 9 | a = 2; 10 | return a; 11 | } 12 | 13 | int func3() { 14 | int a; 15 | a = 4; 16 | return a; 17 | } 18 | 19 | int func4() { 20 | int a; 21 | { 22 | int b; 23 | b = 8; 24 | a = b; 25 | } 26 | { 27 | int b; 28 | b = 16; 29 | a = a + b; 30 | } 31 | return a; 32 | } 33 | 34 | int main() { 35 | int a; 36 | int b; 37 | int c; 38 | a = 32; 39 | b = 32; 40 | c = 32; 41 | 42 | printf("%d\n",func1()+func2()+func3()+func4()+a+b+c); 43 | return 0; 44 | } -------------------------------------------------------------------------------- /lab6/test/3/04_func_2.in: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab6/test/3/04_func_2.in -------------------------------------------------------------------------------- /lab6/test/3/05_func_3.c: -------------------------------------------------------------------------------- 1 | int fact(int n) { 2 | if (n == 0) { 3 | return 1; 4 | } 5 | int nn; 6 | nn = n-1; 7 | return (n * fact(nn)); 8 | } 9 | 10 | int main() { 11 | int n; 12 | n = 4; 13 | printf("%d\n",fact(n)); 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /lab6/test/3/05_func_3.in: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab6/test/3/05_func_3.in -------------------------------------------------------------------------------- /lab6/test/3/06_func_4.c: -------------------------------------------------------------------------------- 1 | int a; 2 | int r; 3 | int fac(int x) 4 | { 5 | if (x <2) 6 | return 1; 7 | a = x - 1; 8 | r = fac(a); 9 | r = x * r; 10 | return r; 11 | } 12 | 13 | int main(){ 14 | int a; 15 | a = 5; 16 | printf("%d\n",fac(a)); 17 | return 0; 18 | } -------------------------------------------------------------------------------- /lab6/test/3/06_func_4.in: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab6/test/3/06_func_4.in -------------------------------------------------------------------------------- /lab6/test/4/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab6/test/4/.gitkeep -------------------------------------------------------------------------------- /lab6/test/4/00_sort_1.c: -------------------------------------------------------------------------------- 1 | int n; 2 | int Merge(int array[], int low, int middle, int high) 3 | { 4 | int n1; 5 | n1 = middle - low + 1; 6 | int n2; 7 | n2 = high - middle; 8 | int L[10]; 9 | int R[10]; 10 | int i; 11 | i = 0; 12 | int j; 13 | j = 0; 14 | 15 | while(i < n1){ 16 | L[i] = array[i + low]; 17 | i = i + 1; 18 | } 19 | while(j < n2){ 20 | R[j] = array[j + middle +1]; 21 | j = j + 1; 22 | } 23 | i = 0; 24 | j = 0; 25 | int k; 26 | k = low; 27 | while(i!=n1 && j!= n2) 28 | { 29 | if(L[i] < R[j] + 1){ 30 | array[k] = L[i]; 31 | k = k + 1; 32 | i = i + 1; 33 | } 34 | else{ 35 | array[k] = R[j]; 36 | k = k + 1; 37 | j = j + 1; 38 | } 39 | } 40 | while(i < n1){ 41 | array[k] = L[i]; 42 | k = k + 1; 43 | i = i + 1; 44 | 45 | } 46 | while(j < n2){ 47 | array[k] = R[j]; 48 | k = k + 1; 49 | j = j + 1; 50 | } 51 | return 0; 52 | } 53 | 54 | int MergeSort(int array[], int p, int q) 55 | { 56 | if(p < q) 57 | { 58 | int mid; 59 | mid = (p+q)/2; 60 | int tmp; 61 | tmp = MergeSort(array, p, mid); 62 | tmp = mid + 1; 63 | tmp = MergeSort(array, tmp, q); 64 | tmp = Merge(array,p, mid, q); 65 | } 66 | return 0; 67 | } 68 | 69 | int main(){ 70 | n = 10; 71 | int a[10]; 72 | a[0]=4;a[1]=3;a[2]=9;a[3]=2;a[4]=0; 73 | a[5]=1;a[6]=6;a[7]=5;a[8]=7;a[9]=8; 74 | int i; 75 | i = 0; 76 | int tmp; 77 | tmp = n - 1; 78 | i = MergeSort(a, i, tmp); 79 | while (i < n) { 80 | tmp = a[i]; 81 | printf("%d",tmp); 82 | tmp = 10; 83 | printf("%c",tmp); 84 | i = i + 1; 85 | } 86 | return 0; 87 | } 88 | -------------------------------------------------------------------------------- /lab6/test/4/00_sort_1.in: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab6/test/4/00_sort_1.in -------------------------------------------------------------------------------- /lab6/test/4/01_sort_2.c: -------------------------------------------------------------------------------- 1 | int n; 2 | int swap (int array[], int i, int j){ 3 | int temp; 4 | temp = array[i]; 5 | array[i] = array[j]; 6 | array[j] = temp; 7 | return 0; 8 | } 9 | int heap_ajust(int arr[], int start, int end) { 10 | int dad; 11 | dad = start; 12 | int son; 13 | son = dad * 2 + 1; 14 | while (son < end + 1) { // 15 | if (son < end && arr[son] < arr[son + 1]) 16 | son = son + 1; 17 | if (arr[dad] > arr[son]) 18 | return 0; 19 | else { 20 | dad = swap(arr,dad,son); 21 | dad = son; 22 | son = dad * 2 + 1; 23 | } 24 | } 25 | return 0; 26 | } 27 | int heap_sort(int arr[], int len) { 28 | int i; 29 | int tmp; 30 | i = len / 2 - 1; 31 | while ( i > -1) { 32 | tmp = len - 1; 33 | tmp = heap_ajust(arr, i, tmp); 34 | i = i - 1; 35 | } 36 | i = len - 1; 37 | while ( i > 0) { 38 | int tmp0; 39 | tmp0 = 0; 40 | tmp = swap(arr,tmp0,i); 41 | tmp = i - 1; 42 | tmp = heap_ajust(arr, tmp0, tmp); 43 | i = i-1; 44 | } 45 | return 0; 46 | } 47 | 48 | int main(){ 49 | n = 10; 50 | int a[10]; 51 | a[0]=4;a[1]=3;a[2]=9;a[3]=2;a[4]=0; 52 | a[5]=1;a[6]=6;a[7]=5;a[8]=7;a[9]=8; 53 | int i; 54 | i = 0; 55 | i = heap_sort(a, n); 56 | while (i < n) { 57 | int tmp; 58 | tmp = a[i]; 59 | printf("%d",tmp); 60 | tmp = 10; 61 | printf("%c",tmp); 62 | i = i + 1; 63 | } 64 | return 0; 65 | } 66 | -------------------------------------------------------------------------------- /lab6/test/4/01_sort_2.in: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab6/test/4/01_sort_2.in -------------------------------------------------------------------------------- /lab6/test/4/02_path.c: -------------------------------------------------------------------------------- 1 | int uniquePaths(int m, int n) { 2 | if(m == 1 || n == 1) 3 | return 1; 4 | 5 | int dp[9]; 6 | int i; 7 | int j; 8 | i = 0; 9 | while(i -1){ 20 | j=n-2; 21 | while(j > -1){ 22 | dp[i*3+j] = dp[(i+1)*3+j] + dp[i*3+j+1]; 23 | j = j - 1; 24 | } 25 | i = i - 1; 26 | } 27 | return dp[0]; 28 | } 29 | int main(){ 30 | int res; 31 | int n; 32 | n=3; 33 | res = uniquePaths(n, n); 34 | printf("%d\n",res); 35 | return 0; 36 | } -------------------------------------------------------------------------------- /lab6/test/4/02_path.in: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/lab6/test/4/02_path.in -------------------------------------------------------------------------------- /lab6/test/4/03_matrix_tran.c: -------------------------------------------------------------------------------- 1 | int M; 2 | int L; 3 | int N; 4 | 5 | int tran(int a0[],int a1[], int a2[],int b0[],int b1[],int b2[],int c0[],int c1[],int c2[]) 6 | { 7 | int i; 8 | i=0; 9 | c1[2]=a2[1]; 10 | c2[1]=a1[2]; 11 | c0[1]=a1[0]; 12 | c0[2]=a2[0]; 13 | c1[0]=a0[1]; 14 | c2[0]=a0[2]; 15 | c1[1]=a1[1]; 16 | c2[2]=a2[2]; 17 | c0[0]=a0[0]; 18 | 19 | return 0; 20 | 21 | } 22 | 23 | int main() 24 | { 25 | N=3; 26 | M=3; 27 | L=3; 28 | int a0[3];int a1[3]; int a2[3];int b0[3];int b1[3];int b2[3];int c0[6];int c1[3];int c2[3]; 29 | int i; 30 | i=0; 31 | while(i max) num = num - max; 19 | while (num < 0) num = num + max; 20 | return num; 21 | } 22 | 23 | int reduce(int kernelid, int x, int y){ 24 | if (kernelid == 0) 25 | return checkrange(x+y); 26 | if (kernelid == 1) { 27 | // x ^ y; 28 | int ret = 0; 29 | int i = 1; 30 | while (i < max){ 31 | if (x / i % 2 == y / i % 2) 32 | ret = ret * 2; 33 | else 34 | ret = ret * 2 + 1; 35 | i = i * 2; 36 | } 37 | return ret; 38 | } 39 | if (kernelid == 2) 40 | if (x > y) return x; 41 | else return y; 42 | if (kernelid == 3){ 43 | // return x | y; 44 | 45 | int ret = 0; 46 | int i = 1; 47 | while (i < max){ 48 | if (x / i % 2 == 1 || y / i % 2 == 1) 49 | ret = ret * 2 + 1; 50 | else 51 | ret = ret * 2; 52 | i = i * 2; 53 | } 54 | return ret; 55 | } 56 | if (kernelid == 4){ 57 | // return x & y; 58 | int ret = 0; 59 | int i = 1; 60 | while (i < max){ 61 | if (x / i % 2 == 1 && y / i % 2 == 1) 62 | ret = ret * 2 + 1; 63 | else 64 | ret = ret * 2; 65 | i = i * 2; 66 | } 67 | return ret; 68 | } 69 | return 0; 70 | } 71 | 72 | int getvalue(int array[], int n, int m, int x, int y){ 73 | if (x < 0 || y < 0 || x >= n || y >= m) return 0; 74 | return array[x * m + y]; 75 | } 76 | 77 | int convn(int kernelid, int input[], int output[], int n, int m, int c){ 78 | int i = 0; 79 | int j = 0; 80 | int x, y, curr; 81 | const int true = 1; 82 | while (true == true){ 83 | j = 0; 84 | while (true == true){ 85 | curr = 0; 86 | x = i - c / 2; 87 | while (true == true){ 88 | y = j - c / 2; 89 | while (true == true){ 90 | curr = reduce(kernelid, curr, getvalue(input, n, m, x, y)); 91 | y = y + 1; 92 | if (y >= j + c / 2) break; 93 | } 94 | x = x + 1; 95 | if (x >= i + c / 2) break; 96 | } 97 | output[i * m + j] = curr; 98 | j = j + 1; 99 | if (j >= m) break; 100 | } 101 | i = i + 1; 102 | if (i >= n) break; 103 | } 104 | return 0; 105 | } 106 | 107 | int a[10000000]; 108 | int b[10000000]; 109 | int kernelid[10000]; 110 | 111 | void memmove(int dst[], int src[], int n){ 112 | int i = 0; 113 | while (i < n){ 114 | dst[i] = src[i]; 115 | i = i + 1; 116 | } 117 | } 118 | 119 | int main(){ 120 | int c = getint(), n = getint(), m = getint(); 121 | getarray(a); 122 | int task = getarray(kernelid); 123 | 124 | int i = 0; 125 | while (i < task){ 126 | convn(kernelid[i], a, b, n, m, c); 127 | memmove(a, b, n * m); 128 | i = i + 1; 129 | } 130 | 131 | putarray(n * m, a); 132 | return 0; 133 | } -------------------------------------------------------------------------------- /lab6/test/4/05_fft.c: -------------------------------------------------------------------------------- 1 | const int mod = 998244353; 2 | int d; 3 | int getint(){int t; scanf("%d",&t); return t; } 4 | int getch(){char c; scanf("%c",&c); return (int)c; } 5 | int getarray(int a[]){ 6 | int n; 7 | scanf("%d",&n); 8 | for(int i=0;i 4) 8 | break; 9 | } 10 | if (a < 4) 11 | continue; 12 | else 13 | break; 14 | return 0; 15 | } -------------------------------------------------------------------------------- /lab6/test/type_check/09_func_param_num.c: -------------------------------------------------------------------------------- 1 | int func (int a, int b, int c) { 2 | return a + b * c; 3 | } 4 | int main () { 5 | int a = 3, b = 4, c = 8; 6 | func(a, b); 7 | return 0; 8 | } -------------------------------------------------------------------------------- /lab6/test/type_check/10_func_param_type.c: -------------------------------------------------------------------------------- 1 | int func (int a, int b, int c) { 2 | return a + b * c; 3 | } 4 | int main () { 5 | int a = 3, b = 4; 6 | char c = '5'; 7 | func(a, b, c); 8 | return 0; 9 | } -------------------------------------------------------------------------------- /lab6/test/type_check/11_func_return.c: -------------------------------------------------------------------------------- 1 | int func1 () { 2 | return '3'; 3 | } 4 | void func2 () { 5 | return 0; 6 | } 7 | int func3 () { 8 | ; 9 | } 10 | int main () { 11 | return 0; 12 | } -------------------------------------------------------------------------------- /utils.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/utils.pdf -------------------------------------------------------------------------------- /上机大作业总体要求.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilkyBoat/compilor_experiment/9aa0af86f52f8641866d197fa2952d1ac5cfc99c/上机大作业总体要求.doc --------------------------------------------------------------------------------