├── FAQ.md ├── README-git.md ├── README.md ├── assignment.md ├── c1interpreter ├── .gitignore ├── CMakeLists.txt ├── Libs_for_c1i_ref │ ├── ld-linux-x86-64.so.2 │ ├── libSystem.B.dylib │ ├── libantlr4-runtime.4.7.1.dylib │ ├── libantlr4-runtime.so.4.7.1 │ ├── libc++.1.dylib │ ├── libc.so.6 │ ├── libdl.so.2 │ ├── libgcc_s.so.1 │ ├── libm.so.6 │ ├── libncurses.5.4.dylib │ ├── libpthread.so.0 │ ├── libstdc++.so.6 │ └── libz.1.dylib ├── README.md ├── c1i_ref_mac ├── c1i_ref_ubuntu └── src │ ├── assembly_builder.cpp │ ├── assembly_builder.h │ ├── main.cpp │ ├── runtime.cpp │ ├── runtime.h │ └── runtime │ ├── io.c │ └── io.h ├── c1recognizer ├── CMakeLists.txt ├── Libs_for_c1r_ref │ ├── ld-linux-x86-64.so.2 │ ├── libSystem.B.dylib │ ├── libantlr4-runtime.4.7.1.dylib │ ├── libantlr4-runtime.so.4.7.1 │ ├── libc++.1.dylib │ ├── libc.so.6 │ ├── libgcc_s.so.1 │ ├── libm.so.6 │ └── libstdc++.so.6 ├── README.md ├── c1r_ref_mac ├── c1r_ref_ubuntu ├── c1recognizer-config.cmake.in ├── cmake │ └── ExternalAntlr4Cpp.cmake ├── grammar │ ├── C1Lexer.g4 │ └── C1Parser.g4 ├── include │ └── c1recognizer │ │ ├── error_reporter.h │ │ ├── recognizer.h │ │ └── syntax_tree.h ├── src │ ├── error_listener.cpp │ ├── error_listener.h │ ├── error_reporter.cpp │ ├── recognizer.cpp │ ├── syntax_tree.cpp │ ├── syntax_tree_builder.cpp │ └── syntax_tree_builder.h └── test │ ├── main.cpp │ ├── syntax_tree_serializer.hpp │ └── test_cases │ ├── declarations.c1 │ ├── exp_example.c1 │ ├── expr.c1 │ ├── lexical_tokens.c1 │ └── simple.c1 ├── hwevalstd.xlsx ├── labEvalStd(Reference).md ├── llvm-irgen-example ├── README.md └── llvm-irgen-example.cpp └── testcases ├── c1i ├── t01_opif.c1 ├── t02_arrwhile.c1 ├── t03_if.c1 ├── t04_relops.c1 ├── t05_unary.c1 ├── t06_func.c1 ├── t07_ops.c1 ├── t08_opsIO.c1 ├── t09_arr.c1 └── t10_block.c1 └── c1r ├── test10_bracket_expr.c1 ├── test11_relops.c1 ├── test12_simple_ifelse.c1 ├── test13_nested_ifelse.c1 ├── test14_while.c1 ├── test15_func.c1 ├── test1_int_decl.c1 ├── test2_float_decl.c1 ├── test3_const_decl.c1 ├── test4_array_decl.c1 ├── test5_blockstmt_decl.c1 ├── test6_simple_assign_expr.c1 ├── test7_unary_expr.c1 ├── test8_binary_expr.c1 └── test9_arr_index_expr.c1 /FAQ.md: -------------------------------------------------------------------------------- 1 | # FAQ 2 | 3 | 4 | 5 | 6 | - `1. ssh/git相关` 7 | - `2. HW相关` 8 | - `3. Lab相关` 9 | - `new` 10 | - `4. 其他系统/平台/环境等相关` 11 | - `5. 课程资源` 12 | - `6. 目录结构` 13 | 14 | 15 | 16 | ## 1. ssh/git相关 17 | 18 | 1.1 服务器是否外网ip可以访问? 19 | > 可以, 不限于校园网ip 20 | 21 | 1.2 把私钥弄丢了怎么办? 22 | > 重新生成,发给助教 23 | 24 | 1.3.1 生成了公私钥之后,怎么ssh到服务器上的git? 25 | > 可以配置~/.ssh/config文件,配置方式如: 26 | 27 | ``` text 28 | Host pc 29 | HostName 202.38.79.111 30 | User git 31 | Port 13022 32 | IdentityFile path/to/your/id_rsa 33 | ``` 34 | 35 | >或者 36 | 37 | ``` bash 38 | eval $(ssh-agent -s) 39 | ssh-add path/to/your/id_rsa 40 | ``` 41 | 42 | 1.3.2 如果提示权限太open怎么办? 43 | > 这个error指的是私钥的权限太open,不够安全, 可以用`ll`查看,用`chmod` 修改,一般`chmod 600`是推荐的权限. 44 | 45 | 1.3.3 如果要求填入下面这样的密码怎么办? 46 | 47 | ``` bash 48 | git@202.38.79.111's password: 49 | ``` 50 | 51 | > 这个提示是让你填写我们服务器上的git用户的密码.说明你的公私钥的登录方式发生了错误,一般情况下是你的私钥没有配置正确.(极少数情况下是老师的公钥没配置正确).配置方式参照前两个问题. 52 | 53 | 54 | 1.3.4 对于助教反馈的`reply.md`,没有通过`git branch -r` 看到鸭? 55 | > 记得先git pull. 56 | > 对于git的用法,务必参考你们git库下面的REAMDME-git!!!!!!! 57 | 58 | ### ~~new~~ [10.10 updated.] 59 | 60 | 1.4 不能git add *吗?为什么? 61 | > 如果没有配置gitignore的话,不建议这样做. 62 | > add * means add all files in the current directory, except for files, whose name begin with a dot. This is your shell functionality and Git only ever receives a list of files. 63 | 64 | 65 | 66 | ## 2. HW相关 67 | 68 | 2.1 作业的程序有语言要求吗? 69 | 70 | > 默认要求是C,但也可以在向老师/助教提供充分的说明(比如如何快速的编译,运行)的条件下,提交其他语言的程序. 71 | 72 | 2.2 第二个作业有程序的复杂度要求吗? 73 | > 如果没有明确的要求,就没有要去. 74 | 75 | 2.3 词法分析那题的输入输出格式具体有什么要求 76 | > 对于作业hw(而非实验lab),我们没有用自动化的测试工具进行测试.输入输出格式没有具体要求,向大家开放.大家可以自行设计.唯一的要求是将输入输出格式在说明文档,在这次是readme.md里面进行必要的说明,只要求语言人性化一点,助教可以马上看懂即可. 77 | 78 | 2.4 不同编译选项输出的汇编码要贴到answer吗? 79 | > 可以不贴,但需要给出必要的描述.可以贴,但需要必要的注释,不建议大段的粘贴. 80 | 81 | 2.5 平时这种小实验是独立做了就满分吗? 82 | > 嗯,但是会指出存在的问题. 83 | 84 | 2.6 提交到git的目录结构? 85 | > 就是子目录下的`README.md`是写对目录里文件的使用,`answer.md`是写对作业中问题的回答和分析。写readme的目的是希望让你们养成在发布的文件夹上写说明的习惯 86 | 87 | 2.7 现在才给评价标准是不是晚了点? 88 | > 我们的评价标准是根据第一次大家的提交发现的问题总结的.目的是为了让大家在之后的lab/hw提交中知道标准. 89 | 90 | ### ~~new~~ [9.21 updated.] 91 | 92 | 2.8 纸质作业交到哪里?什么时候交? 93 | > 纸质作业交到讲桌旁边的白色小桌子上,截止日期当天上课前交. 94 | 95 | ### ~~new~~ [10.10 updated.] 96 | 97 | 2.9 说语言是否正规是什么意思啊,什么叫正规? 98 | > "语言正规" -> "语言能用正规式表示" 99 | 100 | 2.10 HW4-1作业\epsilon是空集的意思吗? 101 | > 是的 102 | 103 | 104 | 105 | ### ~~new~~ [11.3 updated.] 106 | 107 | 2.11 作业19题 `F->F*|a|b` 的*是一个符号还是闭包? 108 | > 就是终结符 *,还没到语义的层次. 109 | 110 | 2.12 怎么这几次作业分级了?分数怎么算? 111 | > 作业评分分为了ABC三个等级,最后的分数是一样的,等级划分是为了更好地关心大家的学习情况.也希望各位同学认真对待平常的作业 112 | 113 | 114 | 115 | 116 | ## 3. Lab相关 117 | 118 | 3.1 antlr用4.5行吗?因为想直接apt解决,apt里的最新版本是4.5.3? 119 | > 严格按照文档要求来,之后实验批改是半自动的,不要因为版本问题给自己和助教找麻烦。 120 | 121 | 3.2 怎么确认装好了llvm? 122 | > 可以写个简单的程序,用安装好的目录的clang编译一下. 123 | 124 | 3.3 lab1的ddl是什么时候? 125 | > 老师没有明确给出ddl的实验,至少会在一周之后以后才截止.但是根据往年的经验,你做得越早,效果越好! 126 | 127 | 3.4 llvm打包错误是什么意思? 128 | > 这个是去年助教的说法,我去问一下.[to be continued.] 129 | 130 | 3.5 能不能解释一下C1语言中Identifier,IntConst,FloatConst的自然语言定义?参考的文件打不开. 131 | > 今年我们的C1是参照标准的C99进行修改的,参照的这个pdf文件,我们放在了qq群文件里.在这里建议大家学会科学上网.科大LUG(Linux User Group)是个分享技术的好平台,大家可以去交流/学习一下. 132 | 133 | 3.6 编译llvm的时候卡住是不是意味着又爆内存了? 134 | > 这个可以通过top/htop等指令查看内存的使用情况. 135 | 136 | 3.7 执行antlr4指令之后提示 Error: Could not find or load main class org.antlr.v4.Tool什么意思? 137 | > CLASSPATH变量没有配置好,或者配置好了,但是没有更新Shell,可以source sh, 或者重新打开该shell. 138 | > 配置方式:把.jar文件本身的路径放到CLASSPATH里 139 | 140 | ### ~~new~~ [9.21 updated.] 141 | 142 | 3.8 '\\'除了注释中需要考虑吗? 143 | > 不需要,我们在本次实验中只考虑注释中的'\\'. 144 | 145 | 3.9 ft_测试是要 lexer 报错退出吗? 146 | > 可以报error,也可以是其他的识别错误的例子.测试样例不需要想的很复杂.这个我们的要求不是很严格,你言之有理即可. 147 | 148 | 3.10 整型常理忽略后缀的话,八进制不就包含在十进制的表达中了,都不用分那么细了吧? 149 | > 并不,017是八进制,而且文法中0是八进制,二者并无重合. 150 | 151 | 3.11 ISO/IEC为什么没有提到负整型常量啊? 152 | > 看文法.运算符. 153 | 154 | 3.12 虚拟机编译安装llvm时候 内存不足卡住怎么办? 155 | > make -j1, 单线程占用的内存少.然后多分配内存. 156 | > make -j的话,会按照你给虚拟机分配的cpu,自动多线程。多线程会占用更多的内存 157 | 158 | 3.13 请问下3e4这种应该被看做是int还是float啊? 159 | > 看文法. 160 | 161 | 3.14 C1语言不用识别字符串的吗? 162 | > 看文档.没有字符串这个类型. 163 | 164 | 3.15 请问token中没有预定义注释,我们是自己新建一个token吗? 165 | > 注释是给人看的,编译器不需要注释,所以就就直接扔掉了. ('->skip') 166 | 167 | 3.16 关于注释中'\\'的其他问题? 168 | > 不建议大家过度的考虑由于反斜杠导致错误情况,错误的测试用例应该根据同学们之前编写程序的经验去构造,而不是凭空的去构造。错误用例不再数量多少,关键是要能够反映出大家的思考。 169 | 170 | 3.17 像x=09这种这种问题,antlr会识别成0和9两个intconst,而不是报错,这种类型的错误是不是要留到语法的部分处理? 171 | > 是的. 172 | 173 | ### ~~new~~ [10.10 updated.] 174 | 175 | 3.18 请问token中只有IntConst一个整常数,那所以八进制十进制十六进制都共用这一个token吗? 176 | > 是的 177 | 178 | 3.19 /*没闭合要怎么做啊,是直接识别成除号和乘号吗? 179 | > 是的.得等语法阶段处理. 180 | 181 | 3.20 lab1-2要看的论文放在哪里? 182 | > [LL-star-PLDI11](http://www.antlr.org/papers/LL-star-PLDI11.pdf) 183 | > [Adaptive LL(*) Parsing](https://dl.acm.org/ft_gateway.cfm?id=2660202&ftid=1506866&dwn=1&CFID=17892232&CFTOKEN=9d3af2ee44ada410-60234D49-93D0-37F6-F814006BAFD6CD54) 184 | 185 | 3.21 对于lab1-2的建议? 186 | > 建议先用比C1更小的语言来实验、阅读论文并回答问题。对于Antlr的特征及机制理解,尽量用能反映特征的最小语言来实验。要结合生成的parser源码来理解 187 | 188 | 3.22 lab1-2可以引入其它的文法规则吗,比如C1Parser.g4原文件上没有的RelOp? 189 | > 可以 190 | 191 | 3.23 GitCommit的评价标准是什么样的? 192 | > commit message不能太短,然后没有提交无用文件 193 | 194 | 3.24 GitCommit的参考是怎样的呢? 195 | > 参考的某同学的版本如下: 196 | ``` 197 | Date: Mon Sep 24 16:46:57 2018 +0800 198 | [lab1-1] Add docs 199 | Date: Mon Sep 24 15:36:05 2018 +0800 200 | [lab1-1] Add many test cases 201 | Date: Mon Sep 24 15:21:40 2018 +0800 202 | [lab1-1] Fix LineComment (multi-line cases, v0.0.2) 203 | Date: Mon Sep 24 14:03:41 2018 +0800 204 | [lab1-1] Finish C1Lexer.g4 (v0.0.1) 205 | Date: Mon Sep 24 13:59:51 2018 +0800 206 | [lab1-1] Add lexer test scripts & simple test cases 207 | Date: Mon Sep 24 13:49:09 2018 +0800 208 | [lab1-1] Add c1recognizer skeleton 209 | ``` 210 | 211 | 3.25 lab应该提交到哪个分支呢? 212 | > master分支,但是这个规定也有一部分是因为我们的设计给大家带来的不必要的麻烦.后面应该不会每次多弄一个reply的分支了 213 | 214 | 3.26 E是不是0分鸭? 215 | > 不一定,等级和分数的关系,应该期末才会确定(当然不会告诉你们,目的是不让你们把精力花在一分两分的计较上) 216 | 217 | 3.27 lab1-2的设计描述文件到底是放在doc下还是lab1-answer下? 218 | > doc下,lab1-answer下只放3个问题的回答和可能有的相应的图片文件 219 | 220 | 3.28 tokens里面有notequal为什么测试要输出“!=”? 221 | > 直接是字符串匹配(只有一个alternative)的token都是直接输出字符串 222 | 223 | 3.29 lab1-1的reply里的answer指的是? 224 | > answer指的是lab1-1*.md文档内容评价 225 | 226 | 3.30 lab1-1的function部分的ABCDE等级划分标准是? 227 | > 共25个测试用例,正确率100%为A,正确率每降低25%降一档 228 | 229 | 3.31 parser文件可以为了消除左递归改变生成规则吗,这样生成的树会不会不一样? 230 | > 可以,会,但是parser的测试采用人工测试. 231 | 232 | 3.32 第二次评测1-1的提交是10/15吗? 233 | > 是的.使用10月15号22:00前最后一次提交的版本进行检测 234 | 235 | 3.33 空在parser里怎么表达? 236 | > 可以用问号,可以用 什么都不写,比如 a : ; 或者 a : | IntConst; 237 | 238 | 3.34 lab1-2的参考输出里面的EOF没有输出? 239 | > 看antlr4的[官方parser rules](https://github.com/ANTLR/antlr4/blob/master/doc/parser-rules.md) 240 | 241 | 3.35 lab1-2的自动评测会要求语法树和预期输出一模一样吗? 242 | > 不会.我们用人工检查. 243 | 244 | 3.36 话说markdown怎么在代码框中插入数学公式,$$好像不行? 245 | > lqx同学:[Markdown中插入数学公式的方法] 246 | (https://blog.csdn.net/xiahouzuoxin/article/details/26478179) 247 | 248 | 249 | ### ~~new~~ [11.3 updated.] 250 | 251 | 3.37 LL(*)论文里面的predicate到底是什么东西? 252 | 253 | > 翻译成语义断言(semantic predicate)).两种断言都是用于产生式预测的,断言都是用host language实现的. 254 | 255 | 3.38 话说LL regular是什么呀? 256 | > LL*里有LL regular文法的定义,做题应该是够用的 257 | 258 | 3.39 lyp:给大家推荐个工具画状态图,graphviz 259 | > 赞👍 260 | 261 | 3.40 zzh:typora作为markdown编辑器画图也很棒,跨平台,支持各种状态图,流程图语法! 262 | > 赞👍 263 | 264 | 3.41 那个,1-1第二次评分的话,那个push message的评分是怎么给的呢? 265 | > 跟1-2一起push 266 | 267 | 3.42 1-3里说的对于项目文件组织的理解,是指c1recognizer这个目录下的文件还是build出的那些文件? 268 | > c1recognizer这个目录下的文件 269 | 270 | 3.43 c1r_ref_(ubuntu/mac)怎么使用,是作为可执行文件直接执行吗?? 271 | > 如果你有了依赖库,并且放在了lib的path下面,是可以的. 272 | 273 | 3.44 我运行不了,它告诉我缺少antlr runtime 274 | > Libs_for_c1r_ref.zip群文件(也上传到了GitHub)是你们运行c1r_ref_(ubuntu/mac)的时候可能需要的动态库,可以ldd c1r_ref_(ubuntu/mac)然后看一下还缺哪些库(一般就只缺antlr的一个库),然后放在ldd(或者otool -L)输出结果中,那些已经有的库对应的目录下面(可以ln 过去) 275 | 276 | 3.45 1-3每次make的时候都很慢是为什么捏? 277 | > 这是因为每次make的时候都会有为了更新外部依赖库而导致的不必要的网络请求.(比如你暂时没网还想做实验) 278 | > 所以我们改了一下CMakeLists.txt.如果不想每次make的时候都update一下外部依赖库,就改用GitHub最新上传的CMakeLists.txt.执行cmake的参数不变 279 | 280 | 3.46 1-3的检查会如何进行?和1-2一样人眼检查还是严格的diff? 281 | > 最后的检查将通过严格比较参考的二进制文件输出和你的输出来进行评测 282 | 283 | 284 | 3.47 1-3的实验没有头绪? 285 | > 先参考我们给出的`syntax_tree_builder::visitExp`下面的各种注释指引. 286 | 287 | 3.48 a[5]={1,2}这种情况我们需要考虑并且在后面3个填充0吗? 288 | > 不需要,我们这一步只是为了构造语法树.最后评测按照参考的二进制文件输出. 289 | 290 | 3.49 那个block_syntax里面怎么只有stmt_syntax啊?好像整个syntax tree.h里都没有decl那一片? 291 | > var_def_stmt_syntax就够了,这里的数据结构的实现不需要和我们的理论的文法定义严格一致,只需要最后功能实现一致即可.这个实现的选择其实更利于实现. 292 | 293 | 294 | 3.50 std::bad_cast的错误指什么?antlrcpp::Any又是干嘛的? 295 | > 这个问题可以从`syntax_tree_builder.cpp`的注释中得到解答. 296 | ```c++ 297 | // Returns antlrcpp::Any, which is constructable from any type. 298 | // However, you should be sure you use the same type for packing and depacking the `Any` object. 299 | // Or a std::bad_cast exception will rise. 300 | // This function always returns an `Any` object containing a `expr_syntax *`. 301 | antlrcpp::Any syntax_tree_builder::visitExp(C1Parser::ExpContext *ctx){ 302 | ... 303 | } 304 | ``` 305 | 306 | 3.51 lab1-3中的ptr_list应该怎么赋值啊?用vector的方法push_back(visit(e).as<*_syntax>())报错说没有匹配的函数。 307 | > 查看ptr_list的定义.参考`syntax_tree.h`(如果你配了vscode,那么可以通过快捷键直接查看定义) 308 | ``` c++ 309 | // Use unique postd::stringtype to reference stored objects 310 | template 311 | using ptr = std::shared_ptr; 312 | 313 | // List of reference of type 314 | template 315 | using ptr_list = std::vector>; 316 | ``` 317 | > 参数外面再加一个ptr()的类型转换(也可以这么叫...)即可. 318 | 319 | 3.52 std::shared_ptr是指针吗?干嘛的呢? 320 | > std::shared_ptr是智能指针的一个,可以参考[这篇知乎回答](https://www.zhihu.com/question/20368881),可以暂时理解为为了更方便管理而对普通指针进行封装的新的类型. 321 | 322 | 323 | 3.53 对于c++的类型转换(static_cast,dynamic_cast)不太懂? 324 | > 可以参考这篇博客[C++ 中static_cast、dynamic_cast总结](https://www.jianshu.com/p/5163a2678171)学习一下 325 | 326 | 3.54 而在我们的代码中,dynamic_cast在哪里用呢? 327 | > 如果你的editor有IntelliSense,那么在C1Parser::BlockContext *ctx的成员中找到children,而这时你可能需要通过判断children这个std::vector的元素的具体类型,来判断这里是decl还是stmt.这时可以用下面这行代码进行判断. 328 | ```c++ 329 | //... 330 | if (auto stmt = dynamic_cast(subtree)){} 331 | //... 332 | ``` 333 | 334 | 3.55 可是对于智能指针,向下转换时用dynamic_cast编译不能通过啊? 335 | > 用`dynamic_pointer_cast` 336 | 337 | 338 | 339 | ### new [11.29 updated] 340 | 341 | 3.56 lab1-3刚开始做还没补全代码时是否可以完成编译? 342 | 343 | > 可以,不过要确保源文件是最新版本的。部分同学因为syntax-tree-build.cpp不是最新的而导致项目不能编译。后续需要改进源码发布流程。 344 | 345 | 3.57 adaptivePredict调用execDFA,那需要分析execDFA这个函数吗? 346 | 347 | > 简单分析即可。 348 | 349 | 3.58 visitExp的初始代码也是不全的吧? 350 | 351 | > 是的,同学们需要自己补全。 352 | 353 | 3.59 lab1-3的第二题是要分析运行时代码的具体情况还是概述antlr面对的各种错误和恢复策略? 354 | 355 | > 概述即可。 356 | 357 | 3.60 对于未标明长度的数组,antlr会自动根据初始化信息补充用作表明长度的exp? 358 | 359 | > 文法中数组长度表达式是可选的,但是lab1-3的实验软件包中syntax_tree_serializer.cpp会根据初始化列表的长度输出数组长度,即便源文件中是缺省的。 360 | 361 | 3.61 可以为了判断使用了哪个产生式加标签(导致要修改 syntax_tree_builder.h)吗 362 | 363 | > 不可以 364 | 365 | 3.62 话说c1r_ref_* 和CMakelists.txt可以更新助教的修改吧? 366 | 367 | > 不可以 368 | 369 | 3.63 浮点数输出结果和 c1r_ref 不一致,需要处理吗? 370 | 371 | > 这一步对于浮点数的精读,用stof和stod都算对.检查的时候diff的结果我们会check一下 372 | 373 | 3.64 如何查找方法定义 374 | 375 | > 推荐vscode,配置intellisense。使用定义查找前需要先构建项目。 376 | 377 | 3.65 部分同学编译项目后,会出现部分成员方法找不到定义的问题 378 | 379 | > 之前lab1-2/lab1-1实现的词法文件、语法文件与项目源码不兼容,检查词法文件和语法文件 380 | 381 | 3.66 为什么constdef,vardef,decl,funcdef的context类型不能转换成bool类型,而constdecl,verdel及其他都可以啊,不能转换的话可以通过什么别的方式判断吗? 382 | 383 | > 问题在于对各头文件中的结构定义没有理清就开始写代码,其中有些是指针,有些是容器对象,指针作为标量是可以存在于if语句的条件表达式中的,而容器对象不是标量。 384 | 385 | 3.67 如果vardecl用var_def_stmt_syntax结构实现的话,vardecl下的vardef怎么办? 386 | 387 | > 用的vector实现的vardecl,然后vardef用var_def_stmt_syntax构造vector中的每一个元素 388 | 389 | 3.68 对于std::any类型的使用问题 390 | 391 | > 参见https://en.cppreference.com/w/cpp/utility/any 392 | 393 | 3.69 运行lab1-3参考程序出现“libantlr4-runtime.so.4.7.1: cannot open shared object file: No such file or directory” 394 | 395 | > 临时修改环境变量LD_LIBRARY_PATH,将缺失的动态库路径添加到该环境变量中 396 | 397 | 3.70 C1Parser.h里,如果StmtContext里同时出现了StmtContext* stmt(size_t i) std::vector stmt()会不会出问题 398 | 399 | > 不会,两个方法的签名不一样 400 | 401 | 3.71 llvm ir里面的phi应该怎么理解呢? 402 | 403 | > https://llvm.org/docs/LangRef.html#phi-instruction ,另外课堂上在静态单赋值一节会具体介绍phi的作用 404 | 405 | 3.72 这次实验的仓库里是不是不能包括c1r_ref文件,Libs_for_c1r_ref之类的内容 406 | 407 | > 不包括 408 | 409 | 3.73 lab2-1不用写实验报告吗 410 | 411 | > 不用,lab2-1写出源程序结构和IR代码之间的映射关系,这对开展lab2-2是一个有意义的事先梳理。写文档不是为了写给助教或老师看的 412 | 413 | 3.74 2-1交cmakelists行不行 414 | 415 | > 可以,文档已说明 416 | 417 | 3.75 使用虚拟机编译llvm出现问题 418 | 419 | > 可以考虑虚拟机资源不够的问题,为虚拟机分配更多的资源后重新尝试编译 420 | 421 | 3.76 要求自动生成的ll和自己写的ll完全一致吗….BB顺序不一样可以吗 422 | 423 | > 可以 424 | 425 | 3.77 lab2-1没有文档要求,那可以把文档push到仓库里吗? 426 | 427 | > 可以 428 | 429 | 3.78 lab2-1要给代码加注释吗? 430 | 431 | > 适当的充分的注释 432 | 433 | 3.79 assembly_builder.h的内容可以修改吗 434 | 435 | > 不可以 436 | 437 | 3.80 没有visit expr_syntax函数,难道要为每个含expr_syntax成员的结构都单独处理吗? 438 | 439 | > 仔细阅读syntax_tree.h中各类型的定义 440 | 441 | 3.81 取模运算要求两边都是int吧? 442 | 443 | > 参考c 444 | 445 | 3.81 lab2-2是不是要判断有没有缺main函数 446 | 447 | > 要,目前C1不支持跨文件链接 448 | 449 | 3.82 计算常量表达式的时候,如果除数为零应该怎么处理?mod的时候,如果有运算数是浮点数,又要怎么处理? 450 | 451 | > 参考程序没有实现全部的语义检查,那你可以自行添加合理的语义检查并报错。最终的检查不是比较输出的llvm IR文件,而是比较ll文件编译后的可执行文件输出是否正确。 452 | 453 | 3.82 初始化数组的时候如果超过数组的大小是否要报错?比如int a[1]={1,2}这种,gcc会报warning,然后会忽略多余的初始化数 454 | 455 | > **无论对于何种声明,当出现数组声明时,你都需要检查数组长度是否不小于初始化列表长度;若小于,则应通过`err.error`报错。** 456 | > 457 | > 此处报错的原因是 clang 和 gcc 的行为是忽视超出部分并报 warning,简化要求起见,报错即可。 458 | 459 | 3.83 上一个实验说不会考虑int a[]={1,2,3,..}这种情形,这个实验lab2-2要考虑吗? 460 | 461 | > 不考虑 462 | 463 | 3.84 处理左值时如果const_expected为真时报错,那作为右值给数组赋初值时呢?下面的那个例子(比如const int m = 1; int a[m] = {m}; 后面两个m都当做是非法的)。第二个m是作为右值的,要报错吗?(c1ref和gcc编译似乎是不会报错的) 464 | 465 | > 的确是右值,但是这里是全局变量声明,实验规定全局变量的初始化必须使用常量表达式。文档中有相关解释,请仔细阅读文档 466 | 467 | 3.85 话说在cond里面,遇到float和int比较,要把int转换成float吗 468 | 469 | > 要转换 470 | 471 | 3.86 builder.createSItoFP已经执行了,但是在输出的lr代码里面没看见 472 | 473 | > IR的创建需要遵顼SSA格式,输入和输出Value不要用同一个变量 474 | 475 | 3.87 用a[1.2]这种作死的表达式也会出现段错误哎 是不是这里也应该要判断一下 476 | 477 | > 要判断 478 | 479 | 3.88 Value* 怎么提取它里面的值?需要用来和数组的初始值数量比较 480 | 481 | > 如果一个是constexpr_expected的话,他的值应该存储到int_const_result或float_const_result,Value的值是抽象的,你不应该去提取它实际的值 482 | 483 | 484 | 485 | ## 4. 其他系统/平台/环境等相关 486 | 487 | 4.1 64位机器没办法运行32位的程序怎么办? 488 | > wsl一般情况下只支持64位.ubuntu可以通过`apt-get install gcc-multilib` 489 | 490 | 4.2 linux可以查看xlsl文件? 491 | > 可以.openoffice, soffice 492 | 493 | 4.3 `top`指令里的buff/cache是什么? 494 | > 记得谷歌,谷歌之后,你会发现 [linux - What do the "buff/cache" and "avail mem" fields in top](https://unix.stackexchange.com/questions/390518/what-do-the-buff-cache-and-avail-mem-fields-in-top-mean) 这一条,然后发现: 495 | 496 | ``` text 497 | [buffers] 498 | Memory used by kernel buffers (Buffers in /proc/meminfo) 499 | [cache] 500 | Memory used by the page cache and slabs (Cached and SReclaimable in /proc/meminfo) 501 | [buff/cache] 502 | Sum of buffers and cache 503 | ``` 504 | 505 | ### ~~new~~ [10.10 updated.] 506 | 507 | 4.4 llvm-build可以删掉吗?竟然有44.1GB? 508 | > 其实可以在编译安装的时候选择release,并确定目标架构,这样就会占用很少的资源.但是我们建议大家用release,不确定目标架构,甚至安利debug,目的就是让大家体验一次比较大的工程的编译过程. 509 | 510 | 4.5 Wsl上是不是不能用grun -gui啊? 511 | > 可以折腾wsl上的gui,但是这一阶段建议用mac或者完整的linux系统(而不是子系统) 512 | 513 | 514 | ## 5. 课程资源 515 | 516 | 5.1 bison-examples.zip解压缩不了? 517 | > 通过快压可以..... 518 | 519 | 5.2 老师上课放的例子在主页的什么位置? 520 | > 在bison-examples同一个[页面]()下面,叫flex-examples. 521 | 522 | ### ~~new~~ [10.10 updated.] 523 | 524 | 5.3 web全称是? 525 | > 计院方向课 -> [课程主页](http://staff.ustc.edu.cn/~jpq/courses/webinfo.html) 526 | 527 | 5.4 "lab1-1的九个维度上的评价标准"在哪里呀?在github上没找到 528 | > https://github.com/ustc-compiler/2018fall/blob/master/labEvalStd(Reference).md 529 | 530 | 5.5 那么有什么好玩又有趣的编译相关的课外活动可以参加的吗? 531 | # **有感兴趣在龙芯平台上开展编译器优化、JS引擎的垃圾收集优化的同学可以私信张老师!! 虽然大家对编译优化的知识还不太了解,但是可以通过具体的问题和平时的研讨与实战来领悟和提升。希望咱们能为构筑国家基础软硬件生态系统尽一份力。** 532 | 533 | 534 | 535 | ### ~~new~~ [11.3 updated.] 536 | 537 | 5.6 请问习题课的ppt在哪里捏?ppt有错误咩?? 538 | > [老师主页](http://staff.ustc.edu.cn/~yuzhang/compiler/index.html)的schedule一栏上.具体链接为: 539 | > - [TA1_H1](http://staff.ustc.edu.cn/~yuzhang/compiler/2018f/lectures/TA1-e.pdf) 540 | > - [TA1_Lab1-1](http://staff.ustc.edu.cn/~yuzhang/compiler/2018f/lectures/TA1-p.pdf) 541 | > - [TA2_H2-H6](http://staff.ustc.edu.cn/~yuzhang/compiler/2018f/lectures/TA2.pdf) 542 | 543 | 5.7 连接gitbook的时候提示:"您的链接不安全"怎么办? 544 | > 这是因为gitbook的htpps暂时过期导致的,这种时候如果你信任这个网址的话,可以"添加信任",或者选择继续访问,针对浏览器的不同操作略有不同. 545 | 546 | 547 | 548 | 549 | 550 | 551 | ## 6. 目录结构 552 | 553 | ### 6.1 HW 目录结构 554 | 555 | 6.1.1 HW1 556 | ``` text 557 | - 558 | | H1 559 | | c 560 | | readme.md 561 | | *.c 562 | | Makefile / *.sh 563 | | lexer 564 | | readme.md 565 | | *.c 566 | | Makefile / *.sh 567 | | answer.md 568 | ... 569 | ``` 570 | 571 | ### 6.2 Lab 目录结构 572 | 573 | 6.2.1 Lab1-1 574 | ``` text 575 | - 576 | | c1recognizer 复制自公共仓库的 c1recognizer 项目,请勿遗漏内容。 577 | | cmake/ 578 | >> | grammar/ 修改其中的 C1Lexer.g4 579 | | include/c1recognizer/ 580 | | src/ 581 | >> | test/test_cases/lexer/ 增加你的测试程序 582 | >> | doc/ 增加文档描述实验中遇到的问题、分析和设计,文件名前缀为lab1-1 583 | | 其他已有的文件 584 | ``` 585 | 586 | ### ~~new~~ [10.10 updated.] 587 | 6.2.2 Lab1-2 588 | ``` text 589 | - 590 | | lab1-answer 591 | | lab1-2.* 回答lab1-2的问题1--问题3 592 | | 其他被引用图像文件 593 | | c1recognizer 复制自公共仓库的 c1recognizer 项目。请勿遗漏内容。 594 | | cmake/ 595 | >> | grammar/ 修改其中的 C1Parser.g4 596 | | include/c1recognizer/ 597 | | src/ 598 | >> | test/test_cases/ 补充你的测试程序 599 | >> | doc/ 增加文档描述实验中遇到的问题、分析和设计,文件名前缀为lab1-2. 600 | | 其他已有的文件 601 | ``` 602 | 603 | 604 | 605 | ### ~~new~~ [11.3 updated.] 606 | 6.2.2 Lab1-3 607 | ``` text 608 | 609 | - 610 | | lab1-answer 611 | | lab1-2.* 612 | >> | lab1-3.md 回答Lab1-3的问题 613 | | c1recognizer 复制自公共仓库的 c1recognizer 项目,请勿遗漏内容。 614 | | cmake/ 615 | | grammar/ 616 | | include/c1recognizer/ 617 | >> | src/ 修改完善recognizer.cpp和syntax_tree_builder.cpp 618 | >> | test/test_cases/ 如果有更多的测试程序,可以在其中补充 619 | >> | doc/ 增加lab1-3.md记录主要任务一节要求的内容 620 | | 其他已有的文件 621 | ``` -------------------------------------------------------------------------------- /README-git.md: -------------------------------------------------------------------------------- 1 | Tips on how to use GIT 2 | =================================================== 3 | written by Yu Zhang (clarazhang@gmail.com) 4 | updated by King Zevin (king.zevin@qq.com) 5 | 6 | 7 | 1. Useful URLs: 8 | http://gitref.org/ 9 | http://www.kernel.org/pub/software/scm/git/docs/ 10 | http://blog.csdn.net/csdlbn/article/details/5834002 11 | https://www.liaoxuefeng.com 12 | 13 | 2. Useful GIT Commands 14 | 15 | - Clone a repository named git-repo 16 | git clone git@202.38.79.111:git-repo 17 | 18 | - Configure your git to set some brief alias command names 19 | You can edit .gitconfig file in your home directory, 20 | which may contains: 21 | 22 | [alias] 23 | up = pull 24 | st = status 25 | di = diff 26 | ci = !sh -c 'git pull && git commit "$@" && git push' - 27 | syn = !git pull && git push[gui] 28 | [user] 29 | email = yourname@youremail 30 | 31 | - Add files to a repo 32 | cd git-repo 33 | git branch -a // list all local/remote branches in git-repo 34 | git log // list commit logs of the current branch 35 | git add files // add files to the current branch 36 | 37 | - Find other commands 38 | git help 39 | 40 | - Check what you have done on the current branch 41 | git status -s 42 | 43 | - Track your changes: 44 | git diff --no-prefix >patchfile // save changes into a patchfile 45 | patch -p0 < patchfile // apply a patch 46 | patch -p0 -R < patchfile // reverse a patch 47 | 48 | - Commit your changes to the local repo 49 | git commit -am 'info about this revision' 50 | 51 | You can modify your commit if it is wrong: 52 | git commit --amend 53 | 54 | - Commit your changes to the remote repo 55 | git push origin 56 | or 57 | git push origin branchname 58 | 59 | - Undo your commits permanently 60 | git reflog // check the status of your local branch 61 | git reset --hard HEAD@{1} // select one revision to reset 62 | 63 | - Switch to other branch 64 | git checkout -b newlocalbranch remotebranch 65 | git checkout existedlocalbranch 66 | 67 | - Delete a local/remote branch 68 | git branch -D localbranch 69 | git branch -rD remotebranch 70 | 71 | 3. Wonderful git plugin for zsh 72 | 73 | - Zsh is a shell designed for interactive use, although it is also a powerful scripting language. 74 | 75 | - With the oh-my-zsh(https://github.com/robbyrussell/oh-my-zsh), you can get the git plugin for zsh automatically. There are lots of useful aliases, such as 76 | 77 | ga = for git add 78 | gp = for git push 79 | gl = for git pull 80 | gd = for git diff 81 | gst = for git status 82 | glg = for git log 83 | 84 | - What's more, you'll get a most beautiful terminal which may show the current status for the PWD(if there is a git repository). (Actually, My favorite theme is the 'ys', which you can get through oh-my-zsh.) 85 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Compiler at USTC in 2018 Fall 2 | 3 | This is a repository to store project toolkit for Compiler class at USTC in 2018 Fall. 4 | 5 | [Course homepage](http://staff.ustc.edu.cn/~yuzhang/compiler/2018f/info.html) 6 | 7 | ## Assignments 8 | - [Assignments](https://github.com/ustc-compiler/2018fall/blob/master/assignment.md) 9 | - [HW的评价标准](https://github.com/ustc-compiler/2018fall/blob/master/hwevalstd.xlsx) 10 | 11 | ## Projects 12 | - [实验环境配置](https://clarazhang.gitbooks.io/compiler-f2018/content/environment.html) 13 | - [实验评价标准(参考)](https://github.com/ustc-compiler/2018fall/blob/master/labEvalStd(Reference).md) 14 | - [简易的git引导](https://github.com/ustc-compiler/2018fall/blob/master/README-git.md) 15 | - Lab1: 16 | - [基于 ANTLR v4 的 C1 词法与语法分析器](https://github.com/ustc-compiler/2018fall/tree/master/c1recognizer) 17 | - [实验说明与要求](https://clarazhang.gitbooks.io/compiler-f2018/content/parser.html) 18 | - Lab2: 19 | - C1 语言的 LLVM IR 代码生成器(to be updated) 20 | - [LLVM-IRGEN-EXAMPLE](https://github.com/ustc-compiler/2018fall/tree/master/llvm-irgen-example) 21 | - [实验说明与要求](https://clarazhang.gitbooks.io/compiler-f2018/content/llvmIRGen.html) 22 | 23 | ## FAQs 24 | - [FAQs for the first 9 weeks (up to 11.3)](https://github.com/ustc-compiler/2018fall/blob/master/FAQ.md) 25 | -------------------------------------------------------------------------------- /assignment.md: -------------------------------------------------------------------------------- 1 | # Assignments 2 | 3 | 对网络提交(包括Git仓库和发送至助教)的作业,截止时间统一为所述日期22时整。 4 | 5 | 对纸质提交的作业,截止时间统一为所述日期课前。 6 | 7 | 8 | | Date | Homework | Project | HW Due | Proj Due | 9 | | :--------- | :---------------- | :--------------------------------------- | :------------ | :--------- | 10 | | 11.26, Mon | [H10-1](#h10-1) | | 12.3, Mon | | 11 | | 11.19, Mon | [H9](#h9) | [Lab2-2](https://clarazhang.gitbooks.io/compiler-f2018/content/llvmIRGen.html#212-lab2-2实验要求和提交细则) | 11.26, Mon | 12.2 Sun | 12 | | 11.8, Thu | | [Lab2-1](https://clarazhang.gitbooks.io/compiler-f2018/content/llvmIRGen.html#211-lab2-1预热实验)| | 11.19, Mon | 13 | | 11.5, Mon | [H8-1](#h8-1) | | 11.12, Mon | | 14 | | 10.25, Mon | [H7-2](#h7-2) | [Lab1-3](https://clarazhang.gitbooks.io/compiler-f2018/content/parser.html#lab1-3-生成-ast-的-c1-解析器) | 10.29, Mon | 11.12, Mon | 15 | | 10.22, Mon | [H7-1](#h7-1) | | 10.29, Mon | | 16 | | 10.18, Thu | [H6-2](#h6-2) | | 10.22, Mon | | 17 | | 10.15, Mon | [H6-1](#h6-1) | | 10.22, Mon | | 18 | | 10.11, Thu | [H5](#h5) | [Lab1-2](https://clarazhang.gitbooks.io/compiler-f2018/content/parser.html#Lab1-2-c1-的语法分析) | 10.15, Mon | 10.15, Mon | 19 | | 10.8, Mon | | [Lab1-2](https://clarazhang.gitbooks.io/compiler-f2018/content/parser.html#Lab1-2-c1-的语法分析) | | 10.15, Mon | 20 | | 9.29, Sat | [H4-2](#h4-2) | [Lab1-2](https://clarazhang.gitbooks.io/compiler-f2018/content/parser.html#Lab1-2-c1-的语法分析) | 10.8, Mon | 10.15, Mon | 21 | | 9.27, Thu | [H4-1](#h4-1) | | 10.8, Mon | - | 22 | | 9.20, Thu | [H3-2](#h3-1) | [Lab1-1](https://clarazhang.gitbooks.io/compiler-f2018/content/parser.html) | 9.27, Thu | 9.24, Mon | 23 | | 9.17, Mon | [H3-1](#h3-1) | [Lab1-1](https://clarazhang.gitbooks.io/compiler-f2018/content/parser.html) | 9.27, Thu | 9.24, Mon | 24 | | 9.13, Thu | ~~[H2-2](#h2-2)~~ | [Environment](https://clarazhang.gitbooks.io/compiler-f2018/content/environment.html) | ~~9.17, Mon~~ | - | 25 | | 9.10, Mon | [H2-1](#h2-1) | None | 9.17, Mon | - | 26 | | 9.6, Thu | [H1](#h1) | None | 9.9, Sun | - | 27 | | 9.3, Mon | [H0](#h0) | None | 9.6, Thu | - | 28 | 29 | ## 习题课课件 30 | 31 | 32 | ## Homework 33 | 34 | ### H0 35 | 36 | 使用`ssh-keygen`生成公私钥,并将公钥发送至助教张宇翔。命名应为`名的全拼-姓的全拼.pub`(名和姓的全拼均小写),请按照自己的姓名修改文件名。 37 | 38 | ### H1 39 | ** 40 | 本次作业请在git仓库中`HW/H1`中添加文件`answer.md`并附上**源程序文件**以及编译和运行程序的 `Makefile` 文件或**shell脚本**来回答问题。 41 | 42 | 1. 安装一个具备完善GNU工具链的环境,如任意Linux发行版/Windows Subsystem for Linux/MacOS(至少你要一个brew); 43 | 44 | 2. 在你安装的环境下,练习使用GCC/Clang,结合使用-E(预处理器,结果大致阅读了解,在作业中指出做了哪些类型的变换)、-S、-c、-o、-m32/64参数,观察程序编译后输出的代码。请: 45 | - 在`HW/H1/c`中添加你的源程序、`Makefile`、shell脚本等 46 | - 在`HW/H1/c`中添加`readme.md`中说明该目录下的文件及子目录和使用方式 47 | - 在`HW/H1/answer.md`中回答本题,指出你的源代码在`HW/H1`中的位置、不同编译选项下输出的汇编码,并对汇编码加注释 48 | - **注释**至少要说明不同汇编命令的含义、源程序中的变量以及中间结果在汇编码中的对应 49 | 50 | 3. 根据[课件](http://staff.ustc.edu.cn/~yuzhang/compiler/2017f/lectures/lexicalAnalysis.pdf)第16页的NFA,手工编写能识别输入串中多个满足NFA的记号的词法分析程序,写出<==><、a<=b的识别过程。**注意**:非关系运算符识别输出为other。**高级要求**:能输出每个记号对应在字符流中的起止位置。请: 51 | - 将源代码、`Makefile`、shell脚本等存档在在`HW/H1/lexer`目录中 52 | - 在`HW/H1/lexer`中添加`readme.md`中说明该目录下的文件及子目录和使用方式(包括Building和Usage) 53 | - 在`HW/H1/answer.md`中给出在做这一题的主要考虑、问题以及解答 54 | - 关于**编程语言**,默认是C语言。希望学生在提交作业时不要把检查者当成专家,要提供脚本和说明,告诉检查者怎么快速编译运行你写的程序以及程序中的要点 55 | 56 | 57 | **注意** 58 | 59 | - 临时文件和编译生成的目标文件、可执行程序不要提交到库中。 60 | - `.md`是现在最常用的简单样式说明用途的文本格式之一Markdown的后缀名,你们应大致了解Markdown的排版方式,以合理的形式展现代码。关于Markdown的使用可以参考[GitHub Guide: Mastering Markdown](https://guides.github.com/features/mastering-markdown),你也可以自行查找一些资料来了解这一Markup Language的使用方式。 61 | - 自行查找 Makefile 文件的编写,也可以参考 [bison-examples](http://staff.ustc.edu.cn/~yuzhang/compiler/proj/bison-examples.zip) 中的 Makefile 62 | - 评价标准见 [github](https://github.com/ustc-compiler/2018fall/blob/master/hwevalstd.xlsx) 63 | 64 | ### H2-1 65 | Book 2.3\(c\), 2.4\(c\)\(e\), 2.7\(c\) (注: 手工构造NFA和DFA, 用算法将NFA变换成DFA,再构造最简的DFA) 66 | 67 | ### ~~H2-2~~ 68 | ~~Book 3.2~~ 69 | 70 | ### H3-1 71 | Book 3.2 72 | 73 | ``` 74 | 3.2 考虑文法 75 | S --> aSbS | bSaS | \epsilon 76 | (a) 为句子abab构造两个不同的最左推导,以此说明该文法是二义的。 77 | (b) 为abab构造对应的最右推导。 78 | (c) 为abab构造对应的分析树。 79 | (d) 这个文法产生的语言是什么? 80 | ``` 81 | ### H3-2 82 | Book 3.4 3.6(d), (f)a的个数比b的个数多的串 3.8(a) 83 | 84 | ``` 85 | 3.4 文法 86 | R --> R '|' R | R R | R | ( R ) | a | b 87 | 产生字母表{a, b}上所有不含 \epsilon 的正规式。注意,第一条竖线加了引号,它是正规式的或运算符号,而不是文法产生式右部各选择之间的分隔符,另外在这儿是一个普通的终结符。该文法是二义的。 88 | (a) 证明该文法产生字母表{a, b}上的所有正规式。 89 | (b) 为该文法写一个等价的非二义文法。它给予算符、连接和 | 的优先级和结合性同2.2节中定义的一致。 90 | (c) 按上面两个文法构造句子ab | ba的分析树。 91 | 92 | 3.6 为字母表\Sigma = {a, b}上的下列每个语言设计一个文法,其中哪些语言是正规的? 93 | (d) 不含abb作为子串的所有串。 94 | (f) a的个数比b的个数多的串。 95 | 96 | 3.8 (a) 消除习题3.1文法的左递归。 97 | 注:习题3.1的文法如下 98 | S --> (L) | a L --> L,S | S 99 | ``` 100 | 101 | ### H4-1 102 | Book 3.12 103 | 104 | ``` 105 | 3.12 下面的文法是否为 LL(1)文法?说明理由。 106 | S --> A B | P Q x A --> x y B --> b c 107 | P --> d P | \epsilon Q --> a Q | \epsilon 108 | ``` 109 | 110 | ### H4-2 111 | - Book 3.11 112 | 113 | ``` 114 | 3.11 构造下面文法的 LL(1)分析表。 115 | S --> a B S | b A S | \epsilon 116 | A --> b A A | a 117 | B --> a B B | b 118 | ``` 119 | - 阅读并理解 [PL/0编译器](http://staff.ustc.edu.cn/~yuzhang/compiler/2012s/pl0.zip) ([PL/0说明文档](http://staff.ustc.edu.cn/~yuzhang/compiler/old_pl0project.pdf)), 叙述PL/0编译器中test函数的作用及它的三个参数的含义, 并举例说明第二个参数带来的好处和引起的问题。 120 | 121 | ### H5 122 | Book 3.19 3.20 123 | 124 | ``` 125 | 3.19 考虑下面的文法 126 | E --> E + T | T 127 | T --> T F | F 128 | F --> F* | a | b 129 | (a) 为此文法构造SLR分析表。 130 | (b) 为此文法构造LALR分析表。 131 | 132 | 3.20 证明下面的文法 133 | S --> S A | A 134 | A --> a 135 | 是SLR(1)文法,但不是LL(1)文法。 136 | ``` 137 | 138 | ### H6-1 139 | Book 3.27 3.31 3.33 3.37 140 | 141 | ``` 142 | 3.27 文法G的产生式如下: 143 | S --> I | R I --> d | I d R --> WpF 144 | W --> Wd | \epsilon F --> F d | d 145 | (a) 令d表示任意数字,p表示十进制小数点,那么非终结符S, I, R, W和F在编程语言中分别表示什么? 146 | (b) 该文法是LR(1 )文法吗?为什么? 147 | 148 | 3.31 下面两个文法中哪一个不是LR(1)文法?对非LR(1)的那个文法,给出那个有移进‑归约冲突的规范的LR(1)项目集。 149 | S --> a A c S --> a A c 150 | A --> A b b | b A --> b A b | b 151 | 152 | 3.33 为语言 153 | L = {a^{m}b^{n} | 0<= m <= 2n}(即a的个数不超过b的个数的两倍) 154 | 写三个文法,它们分别是LR(1)的、二义的和非二义且非LR(1)的。 155 | 注: a^{m}b^{n} 为在latex中的公式表示方法,表示m个a后跟n个b 156 | 157 | 3.37 下面是一个二义文法 158 | S --> AS | b 159 | A --> S A | a 160 | 如果为该文法构造LR分析表,则一定存在某些有分析动作冲突的条目,它们是哪些?假定分析表这样来使用:出现冲突时,不确定地选择一个可能的动作。给出对于输入abab所有可能的动作序列。 161 | ``` 162 | ### H6-2 163 | Book 4.3 164 | 165 | ``` 166 | 4.3 为文法 167 | S --> ( L ) | a 168 | L --> L , S | S 169 | (a) 写一个语法制导定义,它输出括号的对数。 170 | (b) 写一个语法制导定义,它输出括号嵌套的最大深度。 171 | ``` 172 | 173 | ### H7-1 174 | Book 4.12(b) 并写出相应的语法制导定义、预测翻译器 175 | 176 | ``` 177 | 4.12 为文法 178 | S --> ( L ) | a 179 | L --> L , S | S 180 | (b) 分别写出相应的语法制导定义、翻译方案以及预测翻译器,它打印出每个a在句子中是第几个字符。例如,当句子是(a,(a,(a,a),(a)))时,打印的结果是 2 5 8 10 14。 181 | ``` 182 | 183 | ### H7-2 184 | Book 4.12(b) 写出自下而上分析的栈操作代码 185 | 186 | ### H8-1 187 | Book 5.7 5.12 5.15 5.17 188 | 189 | ``` 190 | 5.7 下列文法定义字面常量表的表。符号的解释和图5.2文法的那些相同,增加了类型list,它表示类型T的元素表;增加了nil,表示空表,其元素可以是任何类型。 191 | P --> D; E 192 | D --> D; D | id : T 193 | T --> list of T | char | integer 194 | E --> (L) | literal | num | id | nil 195 | L --> E, L | E 196 | 写一个类似5.3节中的翻译方案,以确定表达式(E )和表(L)的类型。 197 | 198 | 5.12 拓展5.3.3节的类型检查,使之能包含记录。有关记录部分的类型和记录域引用表达式的语法如下: 199 | T --> record fields end 200 | fields --> fields; field | field 201 | field --> id : T 202 | E --> E.id 203 | 204 | 5.15 找出下列表达式的最一般的合一代换: 205 | (a) (pointer (\alpha)) x (\beta --> \gamma ) 206 | (b) \beta X (\gamma --> \delta ) 207 | 如果(b)的\delta 是\alpha 呢? 208 | 209 | 5.17 效仿例5.5,推导下面map的多态类型: 210 | map : \forall \alpha. \forall \beta. ( (\alpha-->\beta)x list(\alpha)) --> list (\beta) 211 | map的ML定义是 212 | fun map (f, l ) = 213 | if null (l ) then nil 214 | else cons (f (hd (l)), map (f, tl (l ) ) ); 215 | 在这个函数体中,内部定义的标识符的类型是: 216 | null : \forall \alpha.list(\alpha) --> boolean; 217 | nil : \forall \alpha.list(\alpha); 218 | cons : \forall \alpha.(\alpha x list(\alpha)) --> list(\alpha); 219 | hd : \forall \alpha.list(\alpha) \alpha; 220 | tl : \forall \alpha. list(\alpha) --> list(\alpha); 221 | ``` 222 | ### H9 223 | Book 7.9(汇编码有更新) 7.10(题目有扩充) 7.17 224 | 225 | 注:本次作业提交到git仓库中的`HW/H9`目录下 226 | ``` 227 | 7.9 下面的C语言程序 228 | main() { 229 | int i,j; 230 | while ( (i || j) && (j > 5) ) { 231 | i = j; 232 | } 233 | } 234 | 在x86/Linux系统上编译生成的汇编代码如下(编译器版本见汇编代码最后一行): 235 | .file "ex7-9.c" 236 | .text 237 | .globl main 238 | .type main, @function 239 | main: 240 | .LFB0: 241 | pushl %ebp 242 | movl %esp, %ebp 243 | subl $16, %esp 244 | jmp .L2 245 | .L5: 246 | movl -4(%ebp), %eax 247 | movl %eax, -8(%ebp) 248 | .L2: 249 | cmpl $0, -8(%ebp) 250 | jne .L3 251 | cmpl $0, -4(%ebp) 252 | jne .L3 253 | cmpl $0, -4(%ebp) 254 | je .L4 255 | .L3: 256 | cmpl $5, -4(%ebp) 257 | jg .L5 258 | .L4: 259 | movl $0, %eax 260 | leave 261 | ret 262 | .LFE0: 263 | .size main, .-main 264 | .ident "GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.5) 5.4.0 20160609" 265 | 在该汇编代码中有关的指令后加注释,将源程序中的操作和生成的汇编代码对应起来,以判断确实是用短路计算方式来完成布尔表达式计算的。 266 | 267 | 7.10 下面是一个C语言程序和在x86/Linux系统上编译(版本较低的GCC编译器,并且未使用优化)该程序得到的汇编代码(为便于理解,略去了和讨论本问题无关的部分,并改动了一个地方)。 268 | main() { 269 | long i,j; 270 | if ( j ) 271 | i++; 272 | else 273 | while ( i ) j++; 274 | } 275 | 编译产生的汇编代码如下: 276 | main: 277 | pushl %ebp 278 | movl %esp,%ebp 279 | subl $8,%esp 280 | cmpl $0,-8(%ebp) 281 | je .L2 282 | incl -4(%ebp) 283 | jmp .L3 284 | .L2: 285 | .L4: 286 | cmpl $0,-4(%ebp) 287 | jne .L6 288 | jmp .L5 289 | .L6: 290 | incl -8(%ebp) 291 | jmp .L4 292 | .L5: 293 | .L3: 294 | .L1: 295 | leave 296 | ret 297 | 298 | (a) 为什么会出现一条指令前有多个标号的情况,如.L2和.L4,还有.L5、.L3和.L1?从控制流语句的中间代码结构加以解释。 299 | (b) 每个函数都有这样的标号.L1,它可能的作用是什么,为什么本函数没有引用该标号的地方? 300 | (c) 如果用较新的gcc版本(如gcc5.4.0)使用-m32 选项进行编译,产生的汇编代码如下。请说明L3~L5的含义,为什么没有L1和L2标号,分析可能的原因。 301 | .file "ex7-10.c" 302 | .text 303 | .globl main 304 | .type main, @function 305 | main: 306 | .LFB0: 307 | pushl %ebp 308 | movl %esp, %ebp 309 | subl $16, %esp 310 | cmpl $0, -8(%ebp) 311 | je .L4 312 | addl $1, -4(%ebp) 313 | jmp .L3 314 | .L5: 315 | addl $1, -8(%ebp) 316 | .L4: 317 | cmpl $0, -4(%ebp) 318 | jne .L5 319 | .L3: 320 | movl $0, %eax 321 | leave 322 | ret 323 | .LFE0: 324 | .size main, .-main 325 | .ident "GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.5) 5.4.0 20160609" 326 | 327 | 7.17 C语言和Java语言的数组声明和数组元素引用的语法形式同7.3.节讨论的不一样,例如float A[10][20]和A[i+1][j-1],并且每一维的下界都是0。若适应这种情况的赋值语句的文法如下: 328 | S --> L := E 329 | E --> E + E | (E ) | L 330 | L --> L [E ] | id 331 | (a)重新设计7.3.2节数组元素的地址计算公式,以方便编译器产生数组元素地址计算的中间代码。不要忘记每一维的下界都是0。 332 | (b)重新设计数组元素地址计算的翻译方案。只需写出产生式L --> L [E ] | id的翻译方案,但要能和7.3.3节中产生式S --> L := E和E --> E + E | (E ) | L的翻译方案衔接。若翻译方案中引入新的函数调用,要解释这些函数的含义。 333 | ``` 334 | ### H10-1 335 | Book 6.18 (有修改) 自行设计的题目及解答(要求见下面) 336 | 337 | 6.18 下面是一个C语言程序: 338 | ``` 339 | main() { 340 | long i; 341 | long a[0][4]; 342 | long j; 343 | i = 4; j = 8; 344 | printf(“%d, %ld\n”, sizeof(a), a[0][0]); 345 | } 346 | ``` 347 | 虽然出现long a[0][4]这样的声明,但在x86/Linux系统上,用编译器GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.5) 5.4.0 20160609/Linux (egcs-1.1.2 release)编译时,该程序能够通过编译并生成目标代码。下面是用gcc -m32 -S 编译该程序产生的汇编代码: 348 | 349 | ``` 350 | .file "ex6-18.c" 351 | .section .rodata 352 | .LC0: 353 | .string "%d, %ld\n" 354 | .text 355 | .globl main 356 | .type main, @function 357 | main: 358 | .LFB0: 359 | .cfi_startproc 360 | leal 4(%esp), %ecx 361 | .cfi_def_cfa 1, 0 362 | andl $-16, %esp 363 | pushl -4(%ecx) 364 | pushl %ebp 365 | .cfi_escape 0x10,0x5,0x2,0x75,0 366 | movl %esp, %ebp 367 | pushl %ecx 368 | .cfi_escape 0xf,0x3,0x75,0x7c,0x6 369 | subl $20, %esp 370 | movl %gs:20, %eax 371 | movl %eax, -12(%ebp) 372 | xorl %eax, %eax 373 | movl $4, -24(%ebp) 374 | movl $8, -20(%ebp) 375 | movl -16(%ebp), %eax 376 | subl $4, %esp 377 | pushl %eax 378 | pushl $0 379 | pushl $.LC0 380 | call printf 381 | addl $16, %esp 382 | movl $0, %eax 383 | movl -12(%ebp), %edx 384 | xorl %gs:20, %edx 385 | je .L3 386 | call __stack_chk_fail 387 | .L3: 388 | movl -4(%ebp), %ecx 389 | .cfi_def_cfa 1, 0 390 | leave 391 | .cfi_restore 5 392 | leal -4(%ecx), %esp 393 | .cfi_def_cfa 4, 4 394 | ret 395 | .cfi_endproc 396 | .LFE0: 397 | .size main, .-main 398 | .ident "GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.5) 5.4.0 20160609" 399 | .section .note.GNU-stack,"",@progbits 400 | ``` 401 | 请回答下面三个问题: 402 | - a) sizeof(a)的值是多少,请说明理由。 403 | - b) 请画出main函数的活动记录布局,结合活动记录布局,指出 a[0][0]的值是多少。 404 | - c) 上述汇编代码中的`.cfi_*` 是[Dwarf](http://www.logix.cz/michal/devel/gas-cfi/dwarf-2.0.0.pdf)的Call frame information相关的调试信息。请说明上述汇编码中这些调试信息的含义。 405 | 406 | 自己出2个题目并给出解答(需要用简短的程序体现你的题目,需要指出题目考核的知识点,2个题目在知>识点上要有区分度) 407 | 408 | **提交说明**: 409 | 本次作业提交到git库的 `HW/H10` 目录下,该目录下至少包含以下内容 410 | 411 | - `answer.md` 412 | 413 | 存放题目与解答(需要在其中说明你所使用的机器配置、操作系统及版本、编译器及版本 414 | 、使用的编译选项,test目录下的内容说明,以及对于各个题目及解答) 415 | 416 | - `test/` 417 | 418 | 存放关联的 C 源程序、汇编程序、用于快速编译和产生汇编/可执行程序的脚本等等 419 | 420 | -------------------------------------------------------------------------------- /c1interpreter/.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | build 3 | src/grammar/* 4 | !src/grammar/*.g4 5 | !src/grammar/*.sh 6 | !src/grammar/*.ps1 7 | -------------------------------------------------------------------------------- /c1interpreter/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED(VERSION 3.5) 2 | 3 | add_definitions(-DFULL_IMPL) 4 | 5 | SET (CMAKE_CXX_STANDARD 14) 6 | 7 | find_package(c1recognizer) 8 | include_directories(${C1RECOGNIZER_INCLUDE_DIRS}) 9 | link_directories(${C1RECOGNIZER_LIBRARY_DIRS}) 10 | 11 | # Import LLVM 12 | find_package(LLVM REQUIRED CONFIG) 13 | message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") 14 | message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") 15 | llvm_map_components_to_libnames(llvm_libs core mcjit native) 16 | 17 | include_directories(${LLVM_INCLUDE_DIRS}) 18 | add_definitions(${LLVM_DEFINITIONS}) 19 | 20 | include_directories(dependency/c1recognizer/include) 21 | add_executable(c1i 22 | src/main.cpp 23 | src/assembly_builder.cpp 24 | src/runtime.cpp 25 | src/runtime/io.c 26 | src/assembly_builder.h 27 | src/runtime.h 28 | src/runtime/io.h) 29 | target_link_libraries(c1i ${C1RECOGNIZER_LIBS} ${llvm_libs}) 30 | -------------------------------------------------------------------------------- /c1interpreter/Libs_for_c1i_ref/ld-linux-x86-64.so.2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustc-compiler/2018fall/706d23b868ee41bc315bc2a9d75e0a9972c338ef/c1interpreter/Libs_for_c1i_ref/ld-linux-x86-64.so.2 -------------------------------------------------------------------------------- /c1interpreter/Libs_for_c1i_ref/libSystem.B.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustc-compiler/2018fall/706d23b868ee41bc315bc2a9d75e0a9972c338ef/c1interpreter/Libs_for_c1i_ref/libSystem.B.dylib -------------------------------------------------------------------------------- /c1interpreter/Libs_for_c1i_ref/libantlr4-runtime.4.7.1.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustc-compiler/2018fall/706d23b868ee41bc315bc2a9d75e0a9972c338ef/c1interpreter/Libs_for_c1i_ref/libantlr4-runtime.4.7.1.dylib -------------------------------------------------------------------------------- /c1interpreter/Libs_for_c1i_ref/libantlr4-runtime.so.4.7.1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustc-compiler/2018fall/706d23b868ee41bc315bc2a9d75e0a9972c338ef/c1interpreter/Libs_for_c1i_ref/libantlr4-runtime.so.4.7.1 -------------------------------------------------------------------------------- /c1interpreter/Libs_for_c1i_ref/libc++.1.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustc-compiler/2018fall/706d23b868ee41bc315bc2a9d75e0a9972c338ef/c1interpreter/Libs_for_c1i_ref/libc++.1.dylib -------------------------------------------------------------------------------- /c1interpreter/Libs_for_c1i_ref/libc.so.6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustc-compiler/2018fall/706d23b868ee41bc315bc2a9d75e0a9972c338ef/c1interpreter/Libs_for_c1i_ref/libc.so.6 -------------------------------------------------------------------------------- /c1interpreter/Libs_for_c1i_ref/libdl.so.2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustc-compiler/2018fall/706d23b868ee41bc315bc2a9d75e0a9972c338ef/c1interpreter/Libs_for_c1i_ref/libdl.so.2 -------------------------------------------------------------------------------- /c1interpreter/Libs_for_c1i_ref/libgcc_s.so.1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustc-compiler/2018fall/706d23b868ee41bc315bc2a9d75e0a9972c338ef/c1interpreter/Libs_for_c1i_ref/libgcc_s.so.1 -------------------------------------------------------------------------------- /c1interpreter/Libs_for_c1i_ref/libm.so.6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustc-compiler/2018fall/706d23b868ee41bc315bc2a9d75e0a9972c338ef/c1interpreter/Libs_for_c1i_ref/libm.so.6 -------------------------------------------------------------------------------- /c1interpreter/Libs_for_c1i_ref/libncurses.5.4.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustc-compiler/2018fall/706d23b868ee41bc315bc2a9d75e0a9972c338ef/c1interpreter/Libs_for_c1i_ref/libncurses.5.4.dylib -------------------------------------------------------------------------------- /c1interpreter/Libs_for_c1i_ref/libpthread.so.0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustc-compiler/2018fall/706d23b868ee41bc315bc2a9d75e0a9972c338ef/c1interpreter/Libs_for_c1i_ref/libpthread.so.0 -------------------------------------------------------------------------------- /c1interpreter/Libs_for_c1i_ref/libstdc++.so.6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustc-compiler/2018fall/706d23b868ee41bc315bc2a9d75e0a9972c338ef/c1interpreter/Libs_for_c1i_ref/libstdc++.so.6 -------------------------------------------------------------------------------- /c1interpreter/Libs_for_c1i_ref/libz.1.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustc-compiler/2018fall/706d23b868ee41bc315bc2a9d75e0a9972c338ef/c1interpreter/Libs_for_c1i_ref/libz.1.dylib -------------------------------------------------------------------------------- /c1interpreter/README.md: -------------------------------------------------------------------------------- 1 | # C1 Language Interpreter 2 | 3 | ## Introduction 4 | 5 | Two parts are included: 6 | 7 | 1. `assembly_builder`: Build assembly from AST, with LLVM `IRBuilder`. 8 | 1. `jit_driver`: Execute assembly with the help of Just-In-Time compiling. Currently all in `main.cpp`. 9 | 10 | As a CLI tool, `c1i` is capable of compiling C1 code into LLVM IR, print it and execute it. 11 | 12 | ## Build 13 | 14 | Use CMake for building this project. `c1recognizer` and LLVM installations are required. 15 | -------------------------------------------------------------------------------- /c1interpreter/c1i_ref_mac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustc-compiler/2018fall/706d23b868ee41bc315bc2a9d75e0a9972c338ef/c1interpreter/c1i_ref_mac -------------------------------------------------------------------------------- /c1interpreter/c1i_ref_ubuntu: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustc-compiler/2018fall/706d23b868ee41bc315bc2a9d75e0a9972c338ef/c1interpreter/c1i_ref_ubuntu -------------------------------------------------------------------------------- /c1interpreter/src/assembly_builder.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "assembly_builder.h" 3 | 4 | #include 5 | 6 | using namespace llvm; 7 | using namespace c1_recognizer::syntax_tree; 8 | 9 | void assembly_builder::visit(assembly &node) 10 | { 11 | } 12 | 13 | void assembly_builder::visit(func_def_syntax &node) 14 | { 15 | } 16 | 17 | void assembly_builder::visit(cond_syntax &node) 18 | { 19 | } 20 | 21 | void assembly_builder::visit(binop_expr_syntax &node) 22 | { 23 | } 24 | 25 | void assembly_builder::visit(unaryop_expr_syntax &node) 26 | { 27 | } 28 | 29 | void assembly_builder::visit(lval_syntax &node) 30 | { 31 | } 32 | 33 | void assembly_builder::visit(literal_syntax &node) 34 | { 35 | } 36 | 37 | void assembly_builder::visit(var_def_stmt_syntax &node) 38 | { 39 | } 40 | 41 | void assembly_builder::visit(assign_stmt_syntax &node) 42 | { 43 | } 44 | 45 | void assembly_builder::visit(func_call_stmt_syntax &node) 46 | { 47 | } 48 | 49 | void assembly_builder::visit(block_syntax &node) 50 | { 51 | } 52 | 53 | void assembly_builder::visit(if_stmt_syntax &node) 54 | { 55 | } 56 | 57 | void assembly_builder::visit(while_stmt_syntax &node) 58 | { 59 | } 60 | 61 | void assembly_builder::visit(empty_stmt_syntax &node) 62 | { 63 | } 64 | -------------------------------------------------------------------------------- /c1interpreter/src/assembly_builder.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _C1_ASSEMBLY_BUILDER_H_ 3 | #define _C1_ASSEMBLY_BUILDER_H_ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include 21 | #include 22 | 23 | #include "runtime.h" 24 | 25 | class assembly_builder : public c1_recognizer::syntax_tree::syntax_tree_visitor 26 | { 27 | virtual void visit(c1_recognizer::syntax_tree::assembly &node) override; 28 | virtual void visit(c1_recognizer::syntax_tree::func_def_syntax &node) override; 29 | virtual void visit(c1_recognizer::syntax_tree::cond_syntax &node) override; 30 | virtual void visit(c1_recognizer::syntax_tree::binop_expr_syntax &node) override; 31 | virtual void visit(c1_recognizer::syntax_tree::unaryop_expr_syntax &node) override; 32 | virtual void visit(c1_recognizer::syntax_tree::lval_syntax &node) override; 33 | virtual void visit(c1_recognizer::syntax_tree::literal_syntax &node) override; 34 | virtual void visit(c1_recognizer::syntax_tree::var_def_stmt_syntax &node) override; 35 | virtual void visit(c1_recognizer::syntax_tree::assign_stmt_syntax &node) override; 36 | virtual void visit(c1_recognizer::syntax_tree::func_call_stmt_syntax &node) override; 37 | virtual void visit(c1_recognizer::syntax_tree::block_syntax &node) override; 38 | virtual void visit(c1_recognizer::syntax_tree::if_stmt_syntax &node) override; 39 | virtual void visit(c1_recognizer::syntax_tree::while_stmt_syntax &node) override; 40 | virtual void visit(c1_recognizer::syntax_tree::empty_stmt_syntax &node) override; 41 | 42 | llvm::LLVMContext &context; 43 | llvm::IRBuilder<> builder; 44 | std::unique_ptr module; 45 | std::unique_ptr runtime; 46 | 47 | llvm::Value *value_result; 48 | int int_const_result; 49 | double float_const_result; 50 | bool is_result_int; 51 | 52 | llvm::Function *current_function; 53 | int bb_count; 54 | 55 | bool lval_as_rval; 56 | bool in_global; 57 | bool constexpr_expected; 58 | 59 | c1_recognizer::error_reporter &err; 60 | bool error_flag; 61 | 62 | public: 63 | assembly_builder(llvm::LLVMContext &ctx, c1_recognizer::error_reporter &error_stream) 64 | : context(ctx), builder(ctx), err(error_stream) {} 65 | 66 | void build(std::string name, std::shared_ptr tree) 67 | { 68 | // Initialize environment. 69 | module = std::make_unique(name, context); 70 | runtime = std::make_unique(module.get()); 71 | 72 | enter_scope(); 73 | for (auto t : runtime->get_language_symbols()) 74 | { 75 | llvm::GlobalValue *val; 76 | std::string name; 77 | bool is_function; 78 | bool is_const; 79 | bool is_array; 80 | bool is_int; 81 | std::tie(name, val, is_function, is_const, is_array, is_int) = t; 82 | if (is_function) 83 | functions[name] = static_cast(val); 84 | else 85 | declare_variable(name, val, is_const, is_array, is_int); 86 | } 87 | 88 | lval_as_rval = true; 89 | in_global = true; 90 | constexpr_expected = false; 91 | error_flag = false; 92 | // Start building by starting iterate over the syntax tree. 93 | tree->accept(*this); 94 | // Finish by clear IRBuilder's insertion point and moving away built module. 95 | builder.ClearInsertionPoint(); 96 | exit_scope(); 97 | if (error_flag) 98 | { 99 | module.release(); 100 | runtime.release(); 101 | } 102 | } 103 | 104 | std::unique_ptr get_module() { return std::move(module); } 105 | std::unique_ptr get_runtime_info() { return std::move(runtime); } 106 | 107 | private: 108 | void enter_scope() { variables.emplace_front(); } 109 | 110 | void exit_scope() { variables.pop_front(); } 111 | 112 | std::tuple lookup_variable(std::string name) 113 | { 114 | for (auto m : variables) 115 | if (m.count(name)) 116 | return m[name]; 117 | return std::make_tuple((llvm::Value *)nullptr, false, false, true); 118 | } 119 | 120 | bool declare_variable(std::string name, llvm::Value *var_ptr, bool is_const, bool is_array, bool is_int) 121 | { 122 | if (variables.front().count(name)) 123 | return false; 124 | variables.front()[name] = std::make_tuple(var_ptr, is_const, is_array, is_int); 125 | return true; 126 | } 127 | 128 | std::deque>> variables; 129 | 130 | std::unordered_map functions; 131 | }; 132 | 133 | #endif 134 | -------------------------------------------------------------------------------- /c1interpreter/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | #include "assembly_builder.h" 14 | 15 | using namespace llvm; 16 | using namespace std; 17 | using namespace c1_recognizer; 18 | using namespace syntax_tree; 19 | using namespace std::literals::string_literals; 20 | 21 | int main(int argc, char **argv) 22 | { 23 | char *in_file = nullptr; 24 | bool emit_llvm = false; 25 | for (int i = 1; i < argc; ++i) 26 | if ("-emit-llvm"s == argv[i]) 27 | emit_llvm = true; 28 | else if ("-h"s == argv[i] || "--help"s == argv[i]) 29 | { 30 | cout << "Usage: c1i [-emit-llvm] ." << endl; 31 | return 0; 32 | } 33 | else if (argv[i][0] == '-') 34 | { 35 | cerr << "Unknown option '" << argv[i] << "'." << endl; 36 | return 1; 37 | } 38 | else 39 | { 40 | if (!in_file) 41 | in_file = argv[i]; 42 | else 43 | { 44 | cerr << "Multiple input file specified. Compiling multiple sources is not supported in C1." << endl; 45 | return 1; 46 | } 47 | } 48 | 49 | if (!in_file) 50 | { 51 | cerr << "Input file expected." << endl; 52 | return 1; 53 | } 54 | 55 | ifstream in_stream(in_file); 56 | recognizer c1r(in_stream); 57 | 58 | error_reporter err(cerr); 59 | if (!c1r.execute(err)) 60 | { 61 | cerr << "Parsing failed. Exiting." << endl; 62 | return 2; 63 | } 64 | 65 | auto ast = c1r.get_syntax_tree(); 66 | 67 | string name = in_file; 68 | name = name.substr(name.find_last_of("/\\") + 1); 69 | 70 | LLVMContext llvm_ctx; 71 | assembly_builder builder(llvm_ctx, err); 72 | builder.build(name, ast); 73 | auto module = builder.get_module(); 74 | auto runtime = builder.get_runtime_info(); 75 | 76 | if (!module) 77 | { 78 | cerr << "Semantic failed. Exiting." << endl; 79 | return 3; 80 | } 81 | 82 | if (emit_llvm) 83 | module->print(outs(), nullptr); 84 | else 85 | { 86 | auto entry_func = module->getFunction("main"); 87 | if (!entry_func) 88 | { 89 | cerr << "No 'main' function presented. Exiting." << endl; 90 | return 4; 91 | } 92 | 93 | InitializeNativeTarget(); 94 | InitializeNativeTargetAsmPrinter(); 95 | InitializeNativeTargetAsmParser(); 96 | 97 | for (auto t : runtime->get_runtime_symbols()) 98 | sys::DynamicLibrary::AddSymbol(get<0>(t), get<1>(t)); 99 | 100 | string error_info; 101 | unique_ptr engine(EngineBuilder(move(module)) 102 | .setEngineKind(EngineKind::JIT) 103 | .setErrorStr(&error_info) 104 | .create()); 105 | if (!engine) 106 | { 107 | cerr << "EngineBuilder failed: " << error_info << endl; 108 | return 4; 109 | } 110 | engine->runFunction(entry_func, {}); 111 | } 112 | 113 | return 0; 114 | } 115 | -------------------------------------------------------------------------------- /c1interpreter/src/runtime.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "runtime.h" 4 | #include "runtime/io.h" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace std; 11 | using namespace llvm; 12 | 13 | runtime_info::runtime_info(Module *module) 14 | { 15 | input_ivar = new GlobalVariable(*module, 16 | Type::getInt32Ty(module->getContext()), 17 | false, 18 | GlobalValue::ExternalLinkage, 19 | ConstantInt::get(Type::getInt32Ty(module->getContext()), 0), 20 | "input_ivar"); 21 | input_fvar = new GlobalVariable(*module, 22 | Type::getDoubleTy(module->getContext()), 23 | false, 24 | GlobalValue::ExternalLinkage, 25 | ConstantFP::get(Type::getDoubleTy(module->getContext()), 0), 26 | "input_fvar"); 27 | output_ivar = new GlobalVariable(*module, 28 | Type::getInt32Ty(module->getContext()), 29 | false, 30 | GlobalValue::ExternalLinkage, 31 | ConstantInt::get(Type::getInt32Ty(module->getContext()), 0), 32 | "output_ivar"); 33 | output_fvar = new GlobalVariable(*module, 34 | Type::getDoubleTy(module->getContext()), 35 | false, 36 | GlobalValue::ExternalLinkage, 37 | ConstantFP::get(Type::getDoubleTy(module->getContext()), 0), 38 | "output_fvar"); 39 | auto inputInt_impl = Function::Create(FunctionType::get(Type::getVoidTy(module->getContext()), 40 | {Type::getInt32PtrTy(module->getContext())}, 41 | false), 42 | GlobalValue::LinkageTypes::ExternalLinkage, 43 | "inputInt_impl", 44 | module); 45 | auto inputFloat_impl = Function::Create(FunctionType::get(Type::getVoidTy(module->getContext()), 46 | {Type::getDoublePtrTy(module->getContext())}, 47 | false), 48 | GlobalValue::LinkageTypes::ExternalLinkage, 49 | "inputFloat_impl", 50 | module); 51 | auto outputInt_impl = Function::Create(FunctionType::get(Type::getVoidTy(module->getContext()), 52 | {Type::getInt32PtrTy(module->getContext())}, 53 | false), 54 | GlobalValue::LinkageTypes::ExternalLinkage, 55 | "outputInt_impl", 56 | module); 57 | auto outputFloat_impl = Function::Create(FunctionType::get(Type::getVoidTy(module->getContext()), 58 | {Type::getDoublePtrTy(module->getContext())}, 59 | false), 60 | GlobalValue::LinkageTypes::ExternalLinkage, 61 | "outputFloat_impl", 62 | module); 63 | 64 | IRBuilder<> builder(module->getContext()); 65 | 66 | inputInt_func = Function::Create(FunctionType::get(Type::getVoidTy(module->getContext()), {}, false), 67 | GlobalValue::LinkageTypes::ExternalLinkage, 68 | "inputInt", 69 | module); 70 | builder.SetInsertPoint(BasicBlock::Create(module->getContext(), "entry", inputInt_func)); 71 | builder.CreateCall(inputInt_impl, {input_ivar}); 72 | builder.CreateRetVoid(); 73 | 74 | inputFloat_func = Function::Create(FunctionType::get(Type::getVoidTy(module->getContext()), {}, false), 75 | GlobalValue::LinkageTypes::ExternalLinkage, 76 | "inputFloat", 77 | module); 78 | builder.SetInsertPoint(BasicBlock::Create(module->getContext(), "entry", inputFloat_func)); 79 | builder.CreateCall(inputFloat_impl, {input_fvar}); 80 | builder.CreateRetVoid(); 81 | 82 | outputInt_func = Function::Create(FunctionType::get(Type::getVoidTy(module->getContext()), {}, false), 83 | GlobalValue::LinkageTypes::ExternalLinkage, 84 | "outputInt", 85 | module); 86 | builder.SetInsertPoint(BasicBlock::Create(module->getContext(), "entry", outputInt_func)); 87 | builder.CreateCall(outputInt_impl, {output_ivar}); 88 | builder.CreateRetVoid(); 89 | 90 | outputFloat_func = Function::Create(FunctionType::get(Type::getVoidTy(module->getContext()), {}, false), 91 | GlobalValue::LinkageTypes::ExternalLinkage, 92 | "outputFloat", 93 | module); 94 | builder.SetInsertPoint(BasicBlock::Create(module->getContext(), "entry", outputFloat_func)); 95 | builder.CreateCall(outputFloat_impl, {output_fvar}); 96 | builder.CreateRetVoid(); 97 | } 98 | 99 | using namespace string_literals; 100 | 101 | vector> runtime_info::get_language_symbols() 102 | { 103 | return { 104 | make_tuple("input_ivar"s, input_ivar, false, false, false, true), 105 | make_tuple("input_fvar"s, input_fvar, false, false, false, false), 106 | make_tuple("output_ivar"s, output_ivar, false, false, false, true), 107 | make_tuple("output_fvar"s, output_fvar, false, false, false, false), 108 | make_tuple("inputInt"s, inputInt_func, true, false, false, true), 109 | make_tuple("inputFloat"s, inputFloat_func, true, false, false, false), 110 | make_tuple("outputInt"s, outputInt_func, true, false, false, true), 111 | make_tuple("outputFloat"s, outputFloat_func, true, false, false, false)}; 112 | } 113 | 114 | vector> runtime_info::get_runtime_symbols() 115 | { 116 | return { 117 | make_tuple("inputInt_impl"s, (void *)&::inputInt), 118 | make_tuple("inputFloat_impl"s, (void *)&::inputFloat), 119 | make_tuple("outputInt_impl"s, (void *)&::outputInt), 120 | make_tuple("outputFloat_impl"s, (void *)&::outputFloat) }; 121 | } 122 | -------------------------------------------------------------------------------- /c1interpreter/src/runtime.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _C1_RUNTIME_H_ 3 | #define _C1_RUNTIME_H_ 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | class runtime_info 13 | { 14 | llvm::GlobalVariable *input_ivar; 15 | llvm::GlobalVariable *input_fvar; 16 | llvm::GlobalVariable *output_ivar; 17 | llvm::GlobalVariable *output_fvar; 18 | llvm::Function *inputInt_func; 19 | llvm::Function *inputFloat_func; 20 | llvm::Function *outputInt_func; 21 | llvm::Function *outputFloat_func; 22 | 23 | public: 24 | runtime_info(llvm::Module *module); 25 | 26 | std::vector> get_language_symbols(); 27 | 28 | std::vector> get_runtime_symbols(); 29 | }; 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /c1interpreter/src/runtime/io.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "io.h" 4 | 5 | void inputInt(int *i) 6 | { 7 | scanf("%d", i); 8 | } 9 | 10 | void inputFloat(double *f) 11 | { 12 | scanf("%lf", f); 13 | } 14 | 15 | void outputInt(int *i) 16 | { 17 | printf("%d\n", *i); 18 | } 19 | 20 | void outputFloat(double *f) 21 | { 22 | printf("%lf\n", *f); 23 | } 24 | -------------------------------------------------------------------------------- /c1interpreter/src/runtime/io.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _C1_RUNTIME__IO_H 3 | #define _C1_RUNTIME__IO_H 4 | 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | 9 | void inputInt(int *); 10 | void inputFloat(double *); 11 | void outputInt(int *); 12 | void outputFloat(double *); 13 | 14 | #ifdef __cplusplus 15 | } 16 | #endif 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /c1recognizer/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | 3 | add_definitions(-DFULL_IMPL) 4 | 5 | set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} 6 | PROPERTY EP_UPDATE_DISCONNECTED 1) 7 | 8 | list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) 9 | 10 | # compiler must be 11 or 14 11 | set(CMAKE_CXX_STANDARD 14) 12 | 13 | # set variable pointing to the antlr tool that supports C++ 14 | set(ANTLR4CPP_JAR_LOCATION "NOT-FOUND" CACHE STRING "ANTLR v4 JAR file location. Used by antlr4cpp.") 15 | 16 | # add external build for antlrcpp 17 | include(ExternalAntlr4Cpp) 18 | 19 | # add antrl4cpp artifacts to project environment 20 | include_directories(${ANTLR4CPP_INCLUDE_DIRS}) 21 | link_directories(${ANTLR4CPP_LIBS}) 22 | message(STATUS "Found antlr4cpp libs: ${ANTLR4CPP_LIBS} and includes: ${ANTLR4CPP_INCLUDE_DIRS} ") 23 | 24 | # Call macro to add lexer and grammar to your build dependencies. 25 | antlr4cpp_process_grammar(c1_recognizer c1_recognizer 26 | ${CMAKE_CURRENT_SOURCE_DIR}/grammar/C1Lexer.g4 27 | ${CMAKE_CURRENT_SOURCE_DIR}/grammar/C1Parser.g4) 28 | 29 | include(ExternalProject) 30 | ExternalProject_Add(rapidjson 31 | PREFIX ${CMAKE_BINARY_DIR}/externals/rapidjson 32 | GIT_REPOSITORY https://github.com/Tencent/rapidjson.git 33 | GIT_TAG v1.1.0 34 | GIT_SUBMODULES "" 35 | CONFIGURE_COMMAND "" 36 | BUILD_COMMAND "" 37 | UPDATE_COMMAND "" 38 | INSTALL_COMMAND "") 39 | ExternalProject_Get_Property(rapidjson DOWNLOAD_DIR) 40 | set(rapidjson_include_dirs ${DOWNLOAD_DIR}/rapidjson/include) 41 | 42 | # include generated files in project environment 43 | include_directories(${antlr4cpp_include_dirs_c1_recognizer}) 44 | include_directories(include) 45 | 46 | # add generated grammar to c1_recognizer binary target 47 | add_library(c1recognizer 48 | src/error_listener.cpp 49 | src/error_reporter.cpp 50 | src/syntax_tree.cpp 51 | src/syntax_tree_builder.cpp 52 | src/recognizer.cpp 53 | ${antlr4cpp_src_files_c1_recognizer}) 54 | add_dependencies(c1recognizer antlr4cpp antlr4cpp_generation_c1_recognizer) 55 | target_link_libraries(c1recognizer antlr4-runtime) 56 | 57 | include_directories(${rapidjson_include_dirs}) 58 | add_executable(c1r_test test/main.cpp) 59 | add_dependencies(c1r_test c1recognizer rapidjson) 60 | target_link_libraries(c1r_test c1recognizer) 61 | 62 | install( 63 | TARGETS c1recognizer 64 | RUNTIME DESTINATION bin 65 | LIBRARY DESTINATION lib 66 | ARCHIVE DESTINATION lib) 67 | 68 | install(DIRECTORY include/c1recognizer DESTINATION include) 69 | 70 | install(DIRECTORY ${ANTLR4CPP_LIBS}/ DESTINATION lib) 71 | 72 | configure_file(c1recognizer-config.cmake.in c1recognizer-config.cmake @ONLY) 73 | 74 | install(FILES ${CMAKE_CURRENT_BINARY_DIR}/c1recognizer-config.cmake DESTINATION cmake) 75 | -------------------------------------------------------------------------------- /c1recognizer/Libs_for_c1r_ref/ld-linux-x86-64.so.2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustc-compiler/2018fall/706d23b868ee41bc315bc2a9d75e0a9972c338ef/c1recognizer/Libs_for_c1r_ref/ld-linux-x86-64.so.2 -------------------------------------------------------------------------------- /c1recognizer/Libs_for_c1r_ref/libSystem.B.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustc-compiler/2018fall/706d23b868ee41bc315bc2a9d75e0a9972c338ef/c1recognizer/Libs_for_c1r_ref/libSystem.B.dylib -------------------------------------------------------------------------------- /c1recognizer/Libs_for_c1r_ref/libantlr4-runtime.4.7.1.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustc-compiler/2018fall/706d23b868ee41bc315bc2a9d75e0a9972c338ef/c1recognizer/Libs_for_c1r_ref/libantlr4-runtime.4.7.1.dylib -------------------------------------------------------------------------------- /c1recognizer/Libs_for_c1r_ref/libantlr4-runtime.so.4.7.1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustc-compiler/2018fall/706d23b868ee41bc315bc2a9d75e0a9972c338ef/c1recognizer/Libs_for_c1r_ref/libantlr4-runtime.so.4.7.1 -------------------------------------------------------------------------------- /c1recognizer/Libs_for_c1r_ref/libc++.1.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustc-compiler/2018fall/706d23b868ee41bc315bc2a9d75e0a9972c338ef/c1recognizer/Libs_for_c1r_ref/libc++.1.dylib -------------------------------------------------------------------------------- /c1recognizer/Libs_for_c1r_ref/libc.so.6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustc-compiler/2018fall/706d23b868ee41bc315bc2a9d75e0a9972c338ef/c1recognizer/Libs_for_c1r_ref/libc.so.6 -------------------------------------------------------------------------------- /c1recognizer/Libs_for_c1r_ref/libgcc_s.so.1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustc-compiler/2018fall/706d23b868ee41bc315bc2a9d75e0a9972c338ef/c1recognizer/Libs_for_c1r_ref/libgcc_s.so.1 -------------------------------------------------------------------------------- /c1recognizer/Libs_for_c1r_ref/libm.so.6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustc-compiler/2018fall/706d23b868ee41bc315bc2a9d75e0a9972c338ef/c1recognizer/Libs_for_c1r_ref/libm.so.6 -------------------------------------------------------------------------------- /c1recognizer/Libs_for_c1r_ref/libstdc++.so.6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustc-compiler/2018fall/706d23b868ee41bc315bc2a9d75e0a9972c338ef/c1recognizer/Libs_for_c1r_ref/libstdc++.so.6 -------------------------------------------------------------------------------- /c1recognizer/README.md: -------------------------------------------------------------------------------- 1 | # C1 Language Recognizer (Reference Version) 2 | 3 | A C1 language recognizer library built on ANTLR v4, which constructs an abstract syntax tree on given source input. 4 | 5 | ## Build Requirement 6 | 7 | * CMake 3.5 or later 8 | * Any GCC compatible C++ compiler, C++ 11 must be supported 9 | * Any java runtime environment (JRE), preferring version for Java 8 10 | * pkg-config 11 | * uuid-dev 12 | 13 | If you have the patience to configure those correctly on Windows, using Windows as the expirement platform is okay. 14 | Otherwise please choose one of the easy-to-use Linux distributions. (Note: Windows Subsystem for Linux will work fine) 15 | 16 | For example, installing those in Ubuntu with `apt`: 17 | 18 | ```bash 19 | sudo apt install cmake g++ openjdk-8-jre-headless pkg-config uuid-dev 20 | ``` 21 | 22 | Also, it would take a while to build it for the first time. This is because it needs to build the dependency antlr4cpp. 23 | And parallel building won't work on it; it seems that CMake is the one to be blamed. 24 | 25 | Besides these, you're also expected to download an ANTLR complete jar file. This is expected throughout this project. 26 | You may find it from [ANTLR v4 Official Site](http://www.antlr.org/). 27 | 28 | ## Building 29 | 30 | For first time building: 31 | ```bash 32 | mkdir build 33 | cd build 34 | cmake -DCMAKE_BUILD_TYPE=Debug -DANTLR4CPP_JAR_LOCATION=/path/to/your/antlr.jar .. 35 | make 36 | cmake .. 37 | make -j 38 | ``` 39 | 40 | After that, each time you have any modification, simply do 41 | ```bash 42 | make -j 43 | ``` 44 | 45 | To avoid UI unresponding, you may want to replace `-j` option with `-jN`, where `N` is parallel task number you expecting. 46 | 47 | ## ANTLRv4 Usage 48 | 49 | For the building work, I've setup the whole CMake project that will work easily as described above. 50 | 51 | And for the most special, magic and wonderful part of ANTLR, visualization, follow these: 52 | 53 | * Rail-road or ADT graphs: Using Visual Studio Code will be the best choice. Have ANTLR plugin installed, you'll gonna 54 | find those options when you right-click on the editor. 55 | * Testing grammars (including parse tree visualization): 56 | > If you'd like to see GUI rather than console-printed parse tree, you'll need to first install JDK on your host 57 | > system (Windows or Linux, DO NOT use WSL here if you don't have sufficient knowledge on configuring X11 58 | > environment, which is needed for the GUI to show up). However if you don't want the GUI version visualized parse 59 | > tree, just ignore this tip. 60 | 61 | First of all, you need to ensure `.` and ANTLR v4 JAR file exists in your CLASSPATH. 62 | * In PowerShell, it is `$env:CLASSPATH`. 63 | * In Linux-like shells, it is `$CLASSPATH`. 64 | 65 | Then, use ANTLR to generate `.java` source files from grammar files. 66 | ```sh 67 | java org.antlr.v4.Tool *.g4 68 | ``` 69 | 70 | After that, compile generated sources. 71 | ```sh 72 | javac *.java 73 | ``` 74 | 75 | Then, use the `grun` tool comes with antlr to test your grammars. 76 | ```sh 77 | # Testing lexer 78 | java org.antlr.v4.gui.TestRig C1Lexer tokens -tokens ../../test/test_cases/simple.c1 79 | # Testing lexer + parser, GUI version parse tree 80 | java org.antlr.v4.gui.TestRig C1 compilationUnit -gui ../../test/test_cases/simple.c1 81 | # Testing lexer + parser, console printed version parse tree 82 | java org.antlr.v4.gui.TestRig C1 compilationUnit -tree ../../test/test_cases/simple.c1 83 | ``` 84 | -------------------------------------------------------------------------------- /c1recognizer/c1r_ref_mac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustc-compiler/2018fall/706d23b868ee41bc315bc2a9d75e0a9972c338ef/c1recognizer/c1r_ref_mac -------------------------------------------------------------------------------- /c1recognizer/c1r_ref_ubuntu: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustc-compiler/2018fall/706d23b868ee41bc315bc2a9d75e0a9972c338ef/c1recognizer/c1r_ref_ubuntu -------------------------------------------------------------------------------- /c1recognizer/c1recognizer-config.cmake.in: -------------------------------------------------------------------------------- 1 | 2 | set(C1RECOGNIZER_INCLUDE_DIRS "@CMAKE_INSTALL_PREFIX@/include") 3 | set(C1RECOGNIZER_LIBRARY_DIRS "@CMAKE_INSTALL_PREFIX@/lib") 4 | set(C1RECOGNIZER_LIBS c1recognizer antlr4-runtime) 5 | -------------------------------------------------------------------------------- /c1recognizer/cmake/ExternalAntlr4Cpp.cmake: -------------------------------------------------------------------------------- 1 | # -*- mode:cmake -*- 2 | # 3 | # This Cmake file is for those using a superbuild Cmake Pattern, it 4 | # will download the tools and build locally 5 | # 6 | # use 2the antlr4cpp_process_grammar to support multiple grammars in the 7 | # same project 8 | # 9 | # - Getting quicky started with Antlr4cpp 10 | # 11 | # Here is how you can use this external project to create the antlr4cpp 12 | # demo to start your project off. 13 | # 14 | # create your project source folder somewhere. e.g. ~/srcfolder/ 15 | # + make a subfolder cmake 16 | # + Copy this file to srcfolder/cmake 17 | # + cut below and use it to create srcfolder/CMakeLists.txt, 18 | # + from https://github.com/DanMcLaughlin/antlr4/tree/master/runtime/Cpp/demo Copy main.cpp, TLexer.g4 and TParser.g4 to ./srcfolder/ 19 | # 20 | # next make a build folder e.g. ~/buildfolder/ 21 | # from the buildfolder, run cmake ~/srcfolder; make 22 | # 23 | ############################################################### 24 | # # minimum required CMAKE version 25 | # CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12.2 FATAL_ERROR) 26 | # 27 | # LIST( APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake ) 28 | # 29 | # # compiler must be 11 or 14 30 | # SET (CMAKE_CXX_STANDARD 11) 31 | # 32 | # # set variable pointing to the antlr tool that supports C++ 33 | # set(ANTLR4CPP_JAR_LOCATION /home/user/antlr4-4.5.4-SNAPSHOT.jar) 34 | # # add external build for antlrcpp 35 | # include( ExternalAntlr4Cpp ) 36 | # # add antrl4cpp artifacts to project environment 37 | # include_directories( ${ANTLR4CPP_INCLUDE_DIRS} ) 38 | # link_directories( ${ANTLR4CPP_LIBS} ) 39 | # message(STATUS "Found antlr4cpp libs: ${ANTLR4CPP_LIBS} and includes: ${ANTLR4CPP_INCLUDE_DIRS} ") 40 | # 41 | # # Call macro to add lexer and grammar to your build dependencies. 42 | # antlr4cpp_process_grammar(demo antlrcpptest 43 | # ${CMAKE_CURRENT_SOURCE_DIR}/TLexer.g4 44 | # ${CMAKE_CURRENT_SOURCE_DIR}/TParser.g4) 45 | # # include generated files in project environment 46 | # include_directories(${antlr4cpp_include_dirs_antlrcpptest}) 47 | # 48 | # # add generated grammar to demo binary target 49 | # add_executable(demo main.cpp ${antlr4cpp_src_files_antlrcpptest}) 50 | # add_dependencies(demo antlr4cpp antlr4cpp_generation_antlrcpptest) 51 | # target_link_libraries(demo antlr4-runtime) 52 | # 53 | ############################################################### 54 | 55 | CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12.2) 56 | PROJECT(antlr4cpp_fetcher CXX) 57 | INCLUDE(ExternalProject) 58 | FIND_PACKAGE(Git REQUIRED) 59 | 60 | # only JRE required 61 | FIND_PACKAGE(Java COMPONENTS Runtime REQUIRED) 62 | 63 | ############ Download and Generate runtime ################# 64 | set(ANTLR4CPP_EXTERNAL_ROOT ${CMAKE_BINARY_DIR}/externals/antlr4cpp) 65 | 66 | # external repository 67 | # GIT_REPOSITORY https://github.com/antlr/antlr4.git 68 | set(ANTLR4CPP_EXTERNAL_REPO "https://github.com/antlr/antlr4.git") 69 | set(ANTLR4CPP_EXTERNAL_TAG "4.7.1") 70 | 71 | if(NOT EXISTS "${ANTLR4CPP_JAR_LOCATION}") 72 | message(FATAL_ERROR "Unable to find antlr tool. ANTLR4CPP_JAR_LOCATION:${ANTLR4CPP_JAR_LOCATION}") 73 | endif() 74 | 75 | # default path for source files 76 | if (NOT ANTLR4CPP_GENERATED_SRC_DIR) 77 | set(ANTLR4CPP_GENERATED_SRC_DIR ${CMAKE_BINARY_DIR}/antlr4cpp_generated_src) 78 | endif() 79 | 80 | # !TODO! This should probably check with Cmake Find first? 81 | # set(ANTLR4CPP_JAR_LOCATION ${ANTLR4CPP_EXTERNAL_ROOT}/${ANTLR4CPP_JAR_NAME}) 82 | # 83 | # !TODO! Ensure Antlr tool available - copy from internet 84 | # 85 | # # !TODO! this shold be calculated based on the tags 86 | # if (NOT ANTLR4CPP_JAR_NAME) 87 | # # default location to find antlr Java binary 88 | # set(ANTLR4CPP_JAR_NAME antlr4-4.5.4-SNAPSHOT.jar) 89 | # endif() 90 | # 91 | # if(NOT EXISTS "${ANTLR4CPP_JAR_LOCATION}") 92 | # # download Java tool if not installed 93 | # ExternalProject_ADD( 94 | # #--External-project-name------ 95 | # antlrtool 96 | # #--Core-directories----------- 97 | # PREFIX ${ANTLR4CPP_EXTERNAL_ROOT} 98 | # #--Download step-------------- 99 | # DOWNLOAD_DIR ${ANTLR4CPP_EXTERNAL_ROOT} 100 | # DOWNLOAD_COMMAND "" 101 | # # URL http://www.antlr.org/download/${ANTLR4CPP_JAR_NAME} 102 | # # antlr4-4.5.4-SNAPSHOT.jar 103 | # # GIT_TAG v4.5.4 104 | # TIMEOUT 10 105 | # LOG_DOWNLOAD ON 106 | # #--Update step---------- 107 | # # UPDATE_COMMAND ${GIT_EXECUTABLE} pull 108 | # #--Patch step---------- 109 | # # PATCH_COMMAND sh -c "cp /scripts/CMakeLists.txt " 110 | # #--Configure step------------- 111 | # CMAKE_ARGS "" 112 | # CONFIGURE_COMMAND "" 113 | # LOG_CONFIGURE ON 114 | # #--Build step----------------- 115 | # BUILD_COMMAND "" 116 | # LOG_BUILD ON 117 | # #--Install step--------------- 118 | # INSTALL_COMMAND "" 119 | # ) 120 | # # Verify Antlr Available 121 | # if(NOT EXISTS "${ANTLR4CPP_JAR_LOCATION}") 122 | # message(FATAL_ERROR "Unable to find ANTLR4CPP_JAR_LOCATION:${ANTLR4CPP_JAR_LOCATION} -> ${ANTLR4CPP_JAR_NAME} not in ${ANTLR4CPP_DIR} ") 123 | # endif() 124 | # endif() 125 | 126 | # download runtime environment 127 | ExternalProject_ADD( 128 | #--External-project-name------ 129 | antlr4cpp 130 | #--Depend-on-antrl-tool----------- 131 | # DEPENDS antlrtool 132 | #--Core-directories----------- 133 | PREFIX ${ANTLR4CPP_EXTERNAL_ROOT} 134 | #--Download step-------------- 135 | GIT_REPOSITORY ${ANTLR4CPP_EXTERNAL_REPO} 136 | # GIT_TAG ${ANTLR4CPP_EXTERNAL_TAG} 137 | TIMEOUT 10 138 | LOG_DOWNLOAD ON 139 | #--Update step---------- 140 | UPDATE_COMMAND ${GIT_EXECUTABLE} pull 141 | #--Patch step---------- 142 | # PATCH_COMMAND sh -c "cp /scripts/CMakeLists.txt " 143 | #--Configure step------------- 144 | CONFIGURE_COMMAND ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Release -DANTLR4CPP_JAR_LOCATION=${ANTLR4CPP_JAR_LOCATION} -DBUILD_SHARED_LIBS=ON -BUILD_TESTS=OFF -DCMAKE_INSTALL_PREFIX:PATH= -DCMAKE_SOURCE_DIR:PATH=/runtime/Cpp /runtime/Cpp 145 | LOG_CONFIGURE ON 146 | #--Build step----------------- 147 | # BUILD_COMMAND ${CMAKE_MAKE_PROGRAM} 148 | LOG_BUILD ON 149 | #--Install step--------------- 150 | # INSTALL_COMMAND "" 151 | # INSTALL_DIR ${CMAKE_BINARY_DIR}/ 152 | #--Install step--------------- 153 | # INSTALL_COMMAND "" 154 | ) 155 | 156 | ExternalProject_Get_Property(antlr4cpp INSTALL_DIR) 157 | 158 | list(APPEND ANTLR4CPP_INCLUDE_DIRS ${INSTALL_DIR}/include/antlr4-runtime) 159 | foreach(src_path misc atn dfa tree support) 160 | list(APPEND ANTLR4CPP_INCLUDE_DIRS ${INSTALL_DIR}/include/antlr4-runtime/${src_path}) 161 | endforeach(src_path) 162 | 163 | set(ANTLR4CPP_LIBS "${INSTALL_DIR}/lib") 164 | 165 | # antlr4_shared ${INSTALL_DIR}/lib/libantlr4-runtime.so 166 | # antlr4_static ${INSTALL_DIR}/lib/libantlr4-runtime.a 167 | 168 | ############ Generate runtime ################# 169 | # macro to add dependencies to target 170 | # 171 | # Param 1 project name 172 | # Param 1 namespace (postfix for dependencies) 173 | # Param 2 Lexer file (full path) 174 | # Param 3 Parser File (full path) 175 | # 176 | # output 177 | # 178 | # antlr4cpp_src_files_{namespace} - src files for add_executable 179 | # antlr4cpp_include_dirs_{namespace} - include dir for generated headers 180 | # antlr4cpp_generation_{namespace} - for add_dependencies tracking 181 | 182 | macro(antlr4cpp_process_grammar 183 | antlr4cpp_project 184 | antlr4cpp_project_namespace 185 | antlr4cpp_grammar_lexer 186 | antlr4cpp_grammar_parser) 187 | 188 | if(EXISTS "${ANTLR4CPP_JAR_LOCATION}") 189 | message(STATUS "Found antlr tool: ${ANTLR4CPP_JAR_LOCATION}") 190 | else() 191 | message(FATAL_ERROR "Unable to find antlr tool. ANTLR4CPP_JAR_LOCATION:${ANTLR4CPP_JAR_LOCATION}") 192 | endif() 193 | 194 | add_custom_target("antlr4cpp_generation_${antlr4cpp_project_namespace}" 195 | COMMAND 196 | ${CMAKE_COMMAND} -E make_directory ${ANTLR4CPP_GENERATED_SRC_DIR} 197 | COMMAND 198 | "${Java_JAVA_EXECUTABLE}" -jar "${ANTLR4CPP_JAR_LOCATION}" -Werror -Dlanguage=Cpp -listener -visitor -o "${ANTLR4CPP_GENERATED_SRC_DIR}/${antlr4cpp_project_namespace}" -package ${antlr4cpp_project_namespace} "${antlr4cpp_grammar_lexer}" "${antlr4cpp_grammar_parser}" 199 | WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" 200 | DEPENDS "${antlr4cpp_grammar_lexer}" "${antlr4cpp_grammar_parser}" 201 | ) 202 | 203 | # Find all the input files 204 | FILE(GLOB generated_files ${ANTLR4CPP_GENERATED_SRC_DIR}/${antlr4cpp_project_namespace}/*.cpp) 205 | 206 | # export generated cpp files into list 207 | foreach(generated_file ${generated_files}) 208 | list(APPEND antlr4cpp_src_files_${antlr4cpp_project_namespace} ${generated_file}) 209 | set_source_files_properties( 210 | ${generated_file} 211 | PROPERTIES 212 | COMPILE_FLAGS -Wno-overloaded-virtual 213 | ) 214 | endforeach(generated_file) 215 | message(STATUS "Antlr4Cpp ${antlr4cpp_project_namespace} Generated: ${generated_files}") 216 | 217 | # export generated include directory 218 | set(antlr4cpp_include_dirs_${antlr4cpp_project_namespace} ${ANTLR4CPP_GENERATED_SRC_DIR}/${antlr4cpp_project_namespace}) 219 | message(STATUS "Antlr4Cpp ${antlr4cpp_project_namespace} include: ${ANTLR4CPP_GENERATED_SRC_DIR}/${antlr4cpp_project_namespace}") 220 | 221 | endmacro() 222 | -------------------------------------------------------------------------------- /c1recognizer/grammar/C1Lexer.g4: -------------------------------------------------------------------------------- 1 | lexer grammar C1Lexer; 2 | 3 | tokens { 4 | Comma, 5 | SemiColon, 6 | Assign, 7 | LeftBracket, 8 | RightBracket, 9 | LeftBrace, 10 | RightBrace, 11 | LeftParen, 12 | RightParen, 13 | If, 14 | Else, 15 | While, 16 | Const, 17 | Equal, 18 | NonEqual, 19 | Less, 20 | Greater, 21 | LessEqual, 22 | GreaterEqual, 23 | Plus, 24 | Minus, 25 | Multiply, 26 | Divide, 27 | Modulo, 28 | 29 | Int, 30 | Float, 31 | Void, 32 | 33 | Identifier, 34 | IntConst, 35 | FloatConst 36 | } 37 | 38 | LeftParen: '('; 39 | RightParen: ')'; 40 | 41 | Plus: '+' ; 42 | Minus: '-' ; 43 | Multiply: '*' ; 44 | Divide: '/' ; 45 | Modulo: '%' ; 46 | 47 | WhiteSpace: [ \t\r\n]+ -> skip; -------------------------------------------------------------------------------- /c1recognizer/grammar/C1Parser.g4: -------------------------------------------------------------------------------- 1 | parser grammar C1Parser; 2 | options { tokenVocab = C1Lexer; } 3 | 4 | compilationUnit: ; 5 | decl: ; 6 | constdecl: ; 7 | constdef: ; 8 | vardecl: ; 9 | vardef: ; 10 | funcdef: ; 11 | block: ; 12 | stmt: ; 13 | lval: ; 14 | cond: ; 15 | exp: 16 | (Plus | Minus) exp 17 | | exp (Multiply | Divide | Modulo) exp 18 | | exp (Plus | Minus) exp 19 | | LeftParen exp RightParen 20 | | number 21 | ; 22 | number: ; 23 | -------------------------------------------------------------------------------- /c1recognizer/include/c1recognizer/error_reporter.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _C1_ERROR_REPORTER_H_ 3 | #define _C1_ERROR_REPORTER_H_ 4 | 5 | #include 6 | 7 | namespace c1_recognizer 8 | { 9 | 10 | class error_reporter 11 | { 12 | public: 13 | error_reporter(std::ostream &error_stream); 14 | 15 | void error(size_t line, size_t charPositionInLine, const std::string &msg); 16 | void warn(size_t line, size_t charPositionInLine, const std::string &msg); 17 | 18 | protected: 19 | virtual void report(size_t line, size_t charPositionInLine, const std::string &msg, const std::string &prefix); 20 | 21 | private: 22 | std::ostream &err; 23 | }; 24 | } 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /c1recognizer/include/c1recognizer/recognizer.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _C1_RECOGNIZER_H_ 3 | #define _C1_RECOGNIZER_H_ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace antlr4 11 | { 12 | class ANTLRInputStream; 13 | } 14 | 15 | namespace c1_recognizer 16 | { 17 | 18 | class recognizer 19 | { 20 | public: 21 | recognizer() = delete; 22 | recognizer(const std::string &input_string); 23 | recognizer(std::istream &input_stream); 24 | 25 | bool execute(error_reporter &_err); 26 | std::shared_ptr get_syntax_tree(); 27 | 28 | ~recognizer(); 29 | 30 | private: 31 | std::shared_ptr ast; 32 | antlr4::ANTLRInputStream *input; 33 | std::string source; 34 | }; 35 | } 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /c1recognizer/include/c1recognizer/syntax_tree.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _C1_SYNTAX_TREE_H_ 3 | #define _C1_SYNTAX_TREE_H_ 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | namespace c1_recognizer 10 | { 11 | namespace syntax_tree 12 | { 13 | // Use unique postd::stringtype to reference stored objects 14 | template 15 | using ptr = std::shared_ptr; 16 | 17 | // List of reference of type 18 | template 19 | using ptr_list = std::vector>; 20 | 21 | // Enumerations 22 | enum class relop 23 | { 24 | equal = 0, 25 | non_equal, 26 | less, 27 | less_equal, 28 | greater, 29 | greater_equal 30 | }; 31 | 32 | enum class binop 33 | { 34 | plus = 0, 35 | minus, 36 | multiply, 37 | divide, 38 | modulo 39 | }; 40 | 41 | enum class unaryop 42 | { 43 | plus = 0, 44 | minus 45 | }; 46 | 47 | // Forward declaration 48 | struct syntax_tree_node; 49 | struct assembly; 50 | struct global_def_syntax; 51 | struct func_def_syntax; 52 | struct cond_syntax; 53 | 54 | struct expr_syntax; 55 | struct binop_expr_syntax; 56 | struct unaryop_expr_syntax; 57 | struct lval_syntax; 58 | struct literal_syntax; 59 | 60 | struct stmt_syntax; 61 | struct var_def_stmt_syntax; 62 | struct assign_stmt_syntax; 63 | struct func_call_stmt_syntax; 64 | struct block_syntax; 65 | struct if_stmt_syntax; 66 | struct while_stmt_syntax; 67 | 68 | struct syntax_tree_visitor; 69 | 70 | // Virtual base of all kinds of syntax tree nodes. 71 | struct syntax_tree_node 72 | { 73 | int line; 74 | int pos; 75 | // Used in syntax_tree_visitor. Irrelevant to syntax tree generation. 76 | virtual void accept(syntax_tree_visitor &visitor) = 0; 77 | }; 78 | 79 | // Root node of an ordinary syntax tree. 80 | struct assembly : syntax_tree_node 81 | { 82 | ptr_list global_defs; 83 | virtual void accept(syntax_tree_visitor &visitor) override final; 84 | }; 85 | 86 | // Virtual base of lobal definitions, function or variable one. 87 | struct global_def_syntax : virtual syntax_tree_node 88 | { 89 | virtual void accept(syntax_tree_visitor &visitor) override = 0; 90 | }; 91 | 92 | // Function definition. 93 | struct func_def_syntax : global_def_syntax 94 | { 95 | std::string name; 96 | ptr body; 97 | virtual void accept(syntax_tree_visitor &visitor) override final; 98 | }; 99 | 100 | // Condition expression. (Not actually treated as expression, enough for C1) 101 | struct cond_syntax : syntax_tree_node 102 | { 103 | relop op; 104 | ptr lhs, rhs; 105 | virtual void accept(syntax_tree_visitor &visitor) override final; 106 | }; 107 | 108 | // Virtual base of expressions. 109 | struct expr_syntax : virtual syntax_tree_node 110 | { 111 | virtual void accept(syntax_tree_visitor &visitor) = 0; 112 | }; 113 | 114 | // Expression like `lhs op rhs`. 115 | struct binop_expr_syntax : expr_syntax 116 | { 117 | binop op; 118 | ptr lhs, rhs; 119 | virtual void accept(syntax_tree_visitor &visitor) override final; 120 | }; 121 | 122 | // Expression like `op rhs`. 123 | struct unaryop_expr_syntax : expr_syntax 124 | { 125 | unaryop op; 126 | ptr rhs; 127 | virtual void accept(syntax_tree_visitor &visitor) override final; 128 | }; 129 | 130 | // Expression like `ident` or `ident[exp]`. 131 | struct lval_syntax : expr_syntax 132 | { 133 | std::string name; 134 | ptr array_index; // nullptr if not indexed as array 135 | virtual void accept(syntax_tree_visitor &visitor) override final; 136 | }; 137 | 138 | // Expression constructed by a literal number. 139 | struct literal_syntax : expr_syntax 140 | { 141 | bool is_int; 142 | int intConst; 143 | double floatConst; 144 | virtual void accept(syntax_tree_visitor &visitor) override final; 145 | }; 146 | 147 | // Virtual base for statements. 148 | struct stmt_syntax : virtual syntax_tree_node 149 | { 150 | virtual void accept(syntax_tree_visitor &visitor) = 0; 151 | }; 152 | 153 | // Variable definition. Multiple of this would be both a statement and a global definition; however, itself only 154 | // represents a single variable definition. 155 | struct var_def_stmt_syntax : stmt_syntax, global_def_syntax 156 | { 157 | bool is_constant; 158 | bool is_int; 159 | std::string name; 160 | ptr array_length; // nullptr for non-array variables 161 | ptr_list initializers; 162 | virtual void accept(syntax_tree_visitor &visitor) override final; 163 | }; 164 | 165 | // Assignment statement. 166 | struct assign_stmt_syntax : stmt_syntax 167 | { 168 | ptr target; 169 | ptr value; 170 | virtual void accept(syntax_tree_visitor &visitor) override final; 171 | }; 172 | 173 | // Function call statement. 174 | struct func_call_stmt_syntax : stmt_syntax 175 | { 176 | std::string name; 177 | virtual void accept(syntax_tree_visitor &visitor) override final; 178 | }; 179 | 180 | // Block statement. 181 | struct block_syntax : stmt_syntax 182 | { 183 | ptr_list body; 184 | virtual void accept(syntax_tree_visitor &visitor) override final; 185 | }; 186 | 187 | // If statement. 188 | struct if_stmt_syntax : stmt_syntax 189 | { 190 | ptr pred; 191 | ptr then_body; 192 | ptr else_body; 193 | virtual void accept(syntax_tree_visitor &visitor) override final; 194 | }; 195 | 196 | // While statement. 197 | struct while_stmt_syntax : stmt_syntax 198 | { 199 | ptr pred; 200 | ptr body; 201 | virtual void accept(syntax_tree_visitor &visitor) override final; 202 | }; 203 | 204 | // Empty statement (aka a single ';'). 205 | struct empty_stmt_syntax : stmt_syntax 206 | { 207 | virtual void accept(syntax_tree_visitor &visitor) override final; 208 | }; 209 | 210 | // Visitor base type 211 | class syntax_tree_visitor 212 | { 213 | public: 214 | virtual void visit(assembly &node) = 0; 215 | virtual void visit(func_def_syntax &node) = 0; 216 | virtual void visit(cond_syntax &node) = 0; 217 | virtual void visit(binop_expr_syntax &node) = 0; 218 | virtual void visit(unaryop_expr_syntax &node) = 0; 219 | virtual void visit(lval_syntax &node) = 0; 220 | virtual void visit(literal_syntax &node) = 0; 221 | virtual void visit(var_def_stmt_syntax &node) = 0; 222 | virtual void visit(assign_stmt_syntax &node) = 0; 223 | virtual void visit(func_call_stmt_syntax &node) = 0; 224 | virtual void visit(block_syntax &node) = 0; 225 | virtual void visit(if_stmt_syntax &node) = 0; 226 | virtual void visit(while_stmt_syntax &node) = 0; 227 | virtual void visit(empty_stmt_syntax &node) = 0; 228 | }; 229 | } // end namespace syntax_tree 230 | } // end namespace c1_recognizer 231 | 232 | #endif 233 | -------------------------------------------------------------------------------- /c1recognizer/src/error_listener.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "error_listener.h" 3 | 4 | using namespace antlr4; 5 | using namespace c1_recognizer; 6 | 7 | error_listener::error_listener(error_reporter &_err) : err(_err), count(0) {} 8 | 9 | void error_listener::syntaxError(Recognizer *, Token *, size_t line, size_t charPositionInLine, const std::string &msg, 10 | std::exception_ptr) 11 | { 12 | err.error(line, charPositionInLine, msg); 13 | count++; 14 | } 15 | 16 | int error_listener::get_errors_count() { return count; } 17 | -------------------------------------------------------------------------------- /c1recognizer/src/error_listener.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _C1_ERROR_LISTENER_H_ 3 | #define _C1_ERROR_LISTENER_H_ 4 | 5 | #include 6 | #include 7 | 8 | namespace c1_recognizer 9 | { 10 | 11 | class error_listener : public antlr4::BaseErrorListener 12 | { 13 | public: 14 | error_listener(error_reporter &_err); 15 | 16 | virtual void syntaxError(antlr4::Recognizer *recognizer, antlr4::Token *offendingSymbol, size_t line, 17 | size_t charPositionInLine, const std::string &msg, std::exception_ptr e) override; 18 | 19 | int get_errors_count(); 20 | 21 | private: 22 | error_reporter &err; 23 | int count; 24 | }; 25 | } 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /c1recognizer/src/error_reporter.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | using namespace c1_recognizer; 5 | 6 | error_reporter::error_reporter(std::ostream &error_stream) : err(error_stream) {} 7 | 8 | void error_reporter::error(size_t line, size_t charPositionInLine, const std::string &msg) 9 | { 10 | report(line, charPositionInLine, msg, "Error"); 11 | } 12 | 13 | void error_reporter::warn(size_t line, size_t charPositionInLine, const std::string &msg) 14 | { 15 | report(line, charPositionInLine, msg, "Warning"); 16 | } 17 | 18 | void error_reporter::report(size_t line, size_t charPositionInLine, const std::string &msg, const std::string &prefix) 19 | { 20 | err << prefix << " at position " << line << ":" << charPositionInLine << " " << msg << std::endl; 21 | } 22 | -------------------------------------------------------------------------------- /c1recognizer/src/recognizer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "syntax_tree_builder.h" 7 | #include "error_listener.h" 8 | 9 | using namespace c1_recognizer; 10 | using namespace syntax_tree; 11 | 12 | using namespace antlr4; 13 | using namespace antlrcpp; 14 | 15 | recognizer::recognizer(const std::string &input_string) : ast(nullptr) 16 | { 17 | input = new ANTLRInputStream(input_string); 18 | } 19 | 20 | recognizer::recognizer(std::istream &input_stream) : ast(nullptr) 21 | { 22 | input = new ANTLRInputStream(input_stream); 23 | } 24 | 25 | std::shared_ptr recognizer::get_syntax_tree() { return ast; } 26 | 27 | recognizer::~recognizer() 28 | { 29 | delete input; 30 | } 31 | 32 | bool recognizer::execute(error_reporter &_err) 33 | { 34 | C1Lexer lexer(input); 35 | CommonTokenStream tokens(&lexer); 36 | C1Parser parser(&tokens); 37 | 38 | error_listener listener(_err); 39 | parser.removeErrorListeners(); 40 | parser.addErrorListener(&listener); 41 | 42 | // Change the `exp` to the non-terminal name you want to examine as the top level symbol. 43 | // It should be `compilationUnit` for final submission. 44 | auto tree = parser.exp(); 45 | 46 | if (listener.get_errors_count() > 0) 47 | return false; 48 | 49 | syntax_tree_builder ast_builder(_err); 50 | ast = ast_builder(tree); 51 | return true; 52 | } 53 | -------------------------------------------------------------------------------- /c1recognizer/src/syntax_tree.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "c1recognizer/syntax_tree.h" 3 | 4 | using namespace c1_recognizer::syntax_tree; 5 | 6 | void assembly::accept(syntax_tree_visitor &visitor) { visitor.visit(*this); } 7 | void func_def_syntax::accept(syntax_tree_visitor &visitor) { visitor.visit(*this); } 8 | void cond_syntax::accept(syntax_tree_visitor &visitor) { visitor.visit(*this); } 9 | void binop_expr_syntax::accept(syntax_tree_visitor &visitor) { visitor.visit(*this); } 10 | void unaryop_expr_syntax::accept(syntax_tree_visitor &visitor) { visitor.visit(*this); } 11 | void lval_syntax::accept(syntax_tree_visitor &visitor) { visitor.visit(*this); } 12 | void literal_syntax::accept(syntax_tree_visitor &visitor) { visitor.visit(*this); } 13 | void var_def_stmt_syntax::accept(syntax_tree_visitor &visitor) { visitor.visit(*this); } 14 | void assign_stmt_syntax::accept(syntax_tree_visitor &visitor) { visitor.visit(*this); } 15 | void func_call_stmt_syntax::accept(syntax_tree_visitor &visitor) { visitor.visit(*this); } 16 | void block_syntax::accept(syntax_tree_visitor &visitor) { visitor.visit(*this); } 17 | void if_stmt_syntax::accept(syntax_tree_visitor &visitor) { visitor.visit(*this); } 18 | void while_stmt_syntax::accept(syntax_tree_visitor &visitor) { visitor.visit(*this); } 19 | void empty_stmt_syntax::accept(syntax_tree_visitor &visitor) { visitor.visit(*this); } 20 | -------------------------------------------------------------------------------- /c1recognizer/src/syntax_tree_builder.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "syntax_tree_builder.h" 3 | #include 4 | 5 | using namespace c1_recognizer; 6 | using namespace c1_recognizer::syntax_tree; 7 | 8 | syntax_tree_builder::syntax_tree_builder(error_reporter &_err) : err(_err) {} 9 | 10 | antlrcpp::Any syntax_tree_builder::visitCompilationUnit(C1Parser::CompilationUnitContext *ctx) 11 | { 12 | } 13 | 14 | antlrcpp::Any syntax_tree_builder::visitDecl(C1Parser::DeclContext *ctx) 15 | { 16 | } 17 | 18 | antlrcpp::Any syntax_tree_builder::visitConstdecl(C1Parser::ConstdeclContext *ctx) 19 | { 20 | } 21 | 22 | antlrcpp::Any syntax_tree_builder::visitConstdef(C1Parser::ConstdefContext *ctx) 23 | { 24 | } 25 | 26 | antlrcpp::Any syntax_tree_builder::visitVardecl(C1Parser::VardeclContext *ctx) 27 | { 28 | } 29 | 30 | antlrcpp::Any syntax_tree_builder::visitVardef(C1Parser::VardefContext *ctx) 31 | { 32 | } 33 | 34 | antlrcpp::Any syntax_tree_builder::visitFuncdef(C1Parser::FuncdefContext *ctx) 35 | { 36 | } 37 | 38 | antlrcpp::Any syntax_tree_builder::visitBlock(C1Parser::BlockContext *ctx) 39 | { 40 | } 41 | 42 | antlrcpp::Any syntax_tree_builder::visitStmt(C1Parser::StmtContext *ctx) 43 | { 44 | } 45 | 46 | antlrcpp::Any syntax_tree_builder::visitLval(C1Parser::LvalContext *ctx) 47 | { 48 | } 49 | 50 | antlrcpp::Any syntax_tree_builder::visitCond(C1Parser::CondContext *ctx) 51 | { 52 | } 53 | 54 | // Returns antlrcpp::Any, which is constructable from any type. 55 | // However, you should be sure you use the same type for packing and depacking the `Any` object. 56 | // Or a std::bad_cast exception will rise. 57 | // This function always returns an `Any` object containing a `expr_syntax *`. 58 | antlrcpp::Any syntax_tree_builder::visitExp(C1Parser::ExpContext *ctx) 59 | { 60 | // Get all sub-contexts of type `exp`. 61 | auto expressions = ctx->exp(); 62 | // Two sub-expressions presented: this indicates it's a expression of binary operator, aka `binop`. 63 | if (expressions.size() == 2) 64 | { 65 | auto result = new binop_expr_syntax; 66 | // Set line and pos. 67 | result->line = ctx->getStart()->getLine(); 68 | result->pos = ctx->getStart()->getCharPositionInLine(); 69 | // visit(some context) is equivalent to calling corresponding visit method; dispatching is done automatically 70 | // by ANTLR4 runtime. For this case, it's equivalent to visitExp(expressions[0]). 71 | // Use reset to set a new pointer to a std::shared_ptr object. DO NOT use assignment; it won't work. 72 | // Use `.as()' to get value from antlrcpp::Any object; notice that this Type must match the type used in 73 | // constructing the Any object, which is constructed from (usually pointer to some derived class of 74 | // syntax_node, in this case) returning value of the visit call. 75 | result->lhs.reset(visit(expressions[0]).as()); 76 | // Check if each token exists. 77 | // Returnd value of the calling will be nullptr (aka NULL in C) if it isn't there; otherwise non-null pointer. 78 | if (ctx->Plus()) 79 | result->op = binop::plus; 80 | if (ctx->Minus()) 81 | result->op = binop::minus; 82 | if (ctx->Multiply()) 83 | result->op = binop::multiply; 84 | if (ctx->Divide()) 85 | result->op = binop::divide; 86 | if (ctx->Modulo()) 87 | result->op = binop::modulo; 88 | result->rhs.reset(visit(expressions[1]).as()); 89 | return static_cast(result); 90 | } 91 | // Otherwise, if `+` or `-` presented, it'll be a `unaryop_expr_syntax`. 92 | if (ctx->Plus() || ctx->Minus()) 93 | { 94 | auto result = new unaryop_expr_syntax; 95 | result->line = ctx->getStart()->getLine(); 96 | result->pos = ctx->getStart()->getCharPositionInLine(); 97 | if (ctx->Plus()) 98 | result->op = unaryop::plus; 99 | if (ctx->Minus()) 100 | result->op = unaryop::minus; 101 | result->rhs.reset(visit(expressions[0]).as()); 102 | return static_cast(result); 103 | } 104 | // In the case that `(` exists as a child, this is an expression like `'(' expressions[0] ')'`. 105 | if (ctx->LeftParen()) 106 | return visit(expressions[0]); // Any already holds expr_syntax* here, no need for dispatch and re-patch with casting. 107 | // If `number` exists as a child, we can say it's a literal integer expression. 108 | if (auto number = ctx->number()) 109 | return visit(number); 110 | } 111 | 112 | antlrcpp::Any syntax_tree_builder::visitNumber(C1Parser::NumberContext *ctx) 113 | { 114 | auto result = new literal_syntax; 115 | if (auto intConst = ctx->IntConst()) 116 | { 117 | result->is_int = true; 118 | result->line = intConst->getSymbol()->getLine(); 119 | result->pos = intConst->getSymbol()->getCharPositionInLine(); 120 | auto text = intConst->getSymbol()->getText(); 121 | if (text[0] == '0' && (text[1] == 'x' || text[1] == 'X')) // Hexadecimal 122 | result->intConst = std::stoi(text, nullptr, 16); // std::stoi will eat '0x' 123 | /* you need to add other situations here */ 124 | 125 | return static_cast(result); 126 | } 127 | // else FloatConst 128 | else 129 | { 130 | return static_cast(result); 131 | } 132 | } 133 | 134 | ptr syntax_tree_builder::operator()(antlr4::tree::ParseTree *ctx) 135 | { 136 | auto result = visit(ctx); 137 | if (result.is()) 138 | return ptr(result.as()); 139 | if (result.is()) 140 | return ptr(result.as()); 141 | if (result.is()) 142 | return ptr(result.as()); 143 | if (result.is()) 144 | return ptr(result.as()); 145 | if (result.is()) 146 | return ptr(result.as()); 147 | if (result.is()) 148 | return ptr(result.as()); 149 | if (result.is()) 150 | return ptr(result.as()); 151 | if (result.is()) 152 | return ptr(result.as()); 153 | if (result.is()) 154 | return ptr(result.as()); 155 | if (result.is()) 156 | return ptr(result.as()); 157 | if (result.is()) 158 | return ptr(result.as()); 159 | if (result.is()) 160 | return ptr(result.as()); 161 | if (result.is()) 162 | return ptr(result.as()); 163 | if (result.is()) 164 | return ptr(result.as()); 165 | if (result.is()) 166 | return ptr(result.as()); 167 | if (result.is()) 168 | return ptr(result.as()); 169 | if (result.is()) 170 | return ptr(result.as()); 171 | return nullptr; 172 | } 173 | -------------------------------------------------------------------------------- /c1recognizer/src/syntax_tree_builder.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _C1_SYNTAX_TREE_BUILDER_H_ 3 | #define _C1_SYNTAX_TREE_BUILDER_H_ 4 | 5 | #include "c1recognizer/syntax_tree.h" 6 | #include "C1ParserBaseVisitor.h" 7 | #include 8 | 9 | namespace c1_recognizer 10 | { 11 | namespace syntax_tree 12 | { 13 | class syntax_tree_builder : public C1ParserBaseVisitor 14 | { 15 | public: 16 | syntax_tree_builder(error_reporter &_err); 17 | 18 | virtual antlrcpp::Any visitCompilationUnit(C1Parser::CompilationUnitContext *ctx) override; 19 | virtual antlrcpp::Any visitDecl(C1Parser::DeclContext *ctx) override; 20 | virtual antlrcpp::Any visitConstdecl(C1Parser::ConstdeclContext *ctx) override; 21 | virtual antlrcpp::Any visitConstdef(C1Parser::ConstdefContext *ctx) override; 22 | virtual antlrcpp::Any visitVardecl(C1Parser::VardeclContext *ctx) override; 23 | virtual antlrcpp::Any visitVardef(C1Parser::VardefContext *ctx) override; 24 | virtual antlrcpp::Any visitFuncdef(C1Parser::FuncdefContext *ctx) override; 25 | virtual antlrcpp::Any visitBlock(C1Parser::BlockContext *ctx) override; 26 | virtual antlrcpp::Any visitStmt(C1Parser::StmtContext *ctx) override; 27 | virtual antlrcpp::Any visitLval(C1Parser::LvalContext *ctx) override; 28 | virtual antlrcpp::Any visitCond(C1Parser::CondContext *ctx) override; 29 | virtual antlrcpp::Any visitExp(C1Parser::ExpContext *ctx) override; 30 | virtual antlrcpp::Any visitNumber(C1Parser::NumberContext *ctx) override; 31 | 32 | ptr operator()(antlr4::tree::ParseTree *ctx); 33 | 34 | private: 35 | error_reporter &err; 36 | }; 37 | } 38 | } 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /c1recognizer/test/main.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include "syntax_tree_serializer.hpp" 10 | 11 | int main(int argc, char **argv) 12 | { 13 | if (argc < 2) 14 | { 15 | std::cerr << "Usage: c1r_test ." << std::endl; 16 | return -1; 17 | } 18 | 19 | std::ifstream input(argv[1]); 20 | c1_recognizer::recognizer rcg(input); 21 | c1_recognizer::error_reporter reporter(std::cerr); 22 | 23 | if (!rcg.execute(reporter)) 24 | return 1; 25 | 26 | std::shared_ptr ast = rcg.get_syntax_tree(); 27 | 28 | rapidjson::StringBuffer s; 29 | rapidjson::PrettyWriter writer(s); 30 | c1_recognizer::syntax_tree::syntax_tree_serializer serializer(writer); 31 | serializer.serialize(*ast); 32 | 33 | std::cout << s.GetString() << std::endl; 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /c1recognizer/test/syntax_tree_serializer.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _C1_TEST_SYNTAX_TREE_SERIALIZER_ 3 | #define _C1_TEST_SYNTAX_TREE_SERIALIZER_ 4 | 5 | #include 6 | 7 | namespace c1_recognizer 8 | { 9 | namespace syntax_tree 10 | { 11 | 12 | std::string relop_name_map[] = {"equal", "non_equal", "less", "less_equal", "greater", "greater_equal"}; 13 | std::string binop_name_map[] = {"plus", "minus", "multiply", "divide", "modulo"}; 14 | std::string unaryop_name_map[] = {"plus", "minus"}; 15 | 16 | template 17 | class syntax_tree_serializer : public syntax_tree_visitor 18 | { 19 | public: 20 | syntax_tree_serializer(Writer &w) : writer(w) {} 21 | 22 | void serialize(syntax_tree_node &tree) 23 | { 24 | tree.accept(*this); 25 | } 26 | 27 | virtual void visit(assembly &tree) override 28 | { 29 | writer.StartObject(); 30 | writer.Key("type"); 31 | writer.String("assembly"); 32 | writer.Key("line"); 33 | writer.Int(tree.line); 34 | writer.Key("pos"); 35 | writer.Int(tree.pos); 36 | writer.Key("global_defs"); 37 | writer.StartArray(); 38 | for (auto def : tree.global_defs) 39 | def->accept(*this); 40 | writer.EndArray(); 41 | writer.EndObject(); 42 | } 43 | 44 | virtual void visit(func_def_syntax &tree) override 45 | { 46 | writer.StartObject(); 47 | writer.Key("type"); 48 | writer.String("func_def_syntax"); 49 | writer.Key("line"); 50 | writer.Int(tree.line); 51 | writer.Key("pos"); 52 | writer.Int(tree.pos); 53 | writer.Key("name"); 54 | writer.String(tree.name.c_str()); 55 | writer.Key("body"); 56 | tree.body->accept(*this); 57 | writer.EndObject(); 58 | } 59 | 60 | virtual void visit(cond_syntax &tree) override 61 | { 62 | writer.StartObject(); 63 | writer.Key("type"); 64 | writer.String("cond_syntax"); 65 | writer.Key("line"); 66 | writer.Int(tree.line); 67 | writer.Key("pos"); 68 | writer.Int(tree.pos); 69 | writer.Key("op"); 70 | writer.String(relop_name_map[int(tree.op)].c_str()); 71 | writer.Key("lhs"); 72 | tree.lhs->accept(*this); 73 | writer.Key("rhs"); 74 | tree.rhs->accept(*this); 75 | writer.EndObject(); 76 | } 77 | 78 | virtual void visit(binop_expr_syntax &tree) override 79 | { 80 | writer.StartObject(); 81 | writer.Key("type"); 82 | writer.String("binop_expr_syntax"); 83 | writer.Key("line"); 84 | writer.Int(tree.line); 85 | writer.Key("pos"); 86 | writer.Int(tree.pos); 87 | writer.Key("op"); 88 | writer.String(binop_name_map[int(tree.op)].c_str()); 89 | writer.Key("lhs"); 90 | tree.lhs->accept(*this); 91 | writer.Key("rhs"); 92 | tree.rhs->accept(*this); 93 | writer.EndObject(); 94 | } 95 | 96 | virtual void visit(unaryop_expr_syntax &tree) override 97 | { 98 | writer.StartObject(); 99 | writer.Key("type"); 100 | writer.String("unaryop_expr_syntax"); 101 | writer.Key("line"); 102 | writer.Int(tree.line); 103 | writer.Key("pos"); 104 | writer.Int(tree.pos); 105 | writer.Key("op"); 106 | writer.String(unaryop_name_map[int(tree.op)].c_str()); 107 | writer.Key("rhs"); 108 | tree.rhs->accept(*this); 109 | writer.EndObject(); 110 | } 111 | 112 | virtual void visit(lval_syntax &tree) override 113 | { 114 | writer.StartObject(); 115 | writer.Key("type"); 116 | writer.String("lval_syntax"); 117 | writer.Key("line"); 118 | writer.Int(tree.line); 119 | writer.Key("pos"); 120 | writer.Int(tree.pos); 121 | writer.Key("name"); 122 | writer.String(tree.name.c_str()); 123 | if (tree.array_index) 124 | { 125 | writer.Key("array_index"); 126 | tree.array_index->accept(*this); 127 | } 128 | writer.EndObject(); 129 | } 130 | 131 | virtual void visit(literal_syntax &tree) override 132 | { 133 | writer.StartObject(); 134 | writer.Key("type"); 135 | writer.String("literal_syntax"); 136 | writer.Key("line"); 137 | writer.Int(tree.line); 138 | writer.Key("pos"); 139 | writer.Int(tree.pos); 140 | writer.Key("is_int"); 141 | writer.Bool(tree.is_int); 142 | writer.Key("value"); 143 | if(tree.is_int) 144 | writer.Int(tree.intConst); 145 | else 146 | writer.Double(tree.floatConst); 147 | writer.EndObject(); 148 | } 149 | 150 | virtual void visit(var_def_stmt_syntax &tree) override 151 | { 152 | writer.StartObject(); 153 | writer.Key("type"); 154 | writer.String("var_def_stmt_syntax"); 155 | writer.Key("line"); 156 | writer.Int(tree.line); 157 | writer.Key("pos"); 158 | writer.Int(tree.pos); 159 | writer.Key("is_const"); 160 | writer.Bool(tree.is_constant); 161 | writer.Key("is_int"); 162 | writer.Bool(tree.is_int); 163 | writer.Key("name"); 164 | writer.String(tree.name.c_str()); 165 | if (tree.array_length) 166 | { 167 | writer.Key("array_length"); 168 | tree.array_length->accept(*this); 169 | writer.Key("array_initializers"); 170 | writer.StartArray(); 171 | for (auto init : tree.initializers) 172 | init->accept(*this); 173 | writer.EndArray(); 174 | } 175 | else if (tree.initializers.size() > 0) 176 | { 177 | writer.Key("vardef_initializer"); 178 | tree.initializers[0]->accept(*this); 179 | } 180 | writer.EndObject(); 181 | } 182 | 183 | virtual void visit(assign_stmt_syntax &tree) override 184 | { 185 | writer.StartObject(); 186 | writer.Key("type"); 187 | writer.String("assign_stmt_syntax"); 188 | writer.Key("line"); 189 | writer.Int(tree.line); 190 | writer.Key("pos"); 191 | writer.Int(tree.pos); 192 | writer.Key("target"); 193 | tree.target->accept(*this); 194 | writer.Key("value"); 195 | tree.value->accept(*this); 196 | writer.EndObject(); 197 | } 198 | 199 | virtual void visit(func_call_stmt_syntax &tree) override 200 | { 201 | writer.StartObject(); 202 | writer.Key("type"); 203 | writer.String("func_call_stmt_syntax"); 204 | writer.Key("line"); 205 | writer.Int(tree.line); 206 | writer.Key("pos"); 207 | writer.Int(tree.pos); 208 | writer.Key("name"); 209 | writer.String(tree.name.c_str()); 210 | writer.EndObject(); 211 | } 212 | 213 | virtual void visit(block_syntax &tree) override 214 | { 215 | writer.StartObject(); 216 | writer.Key("type"); 217 | writer.String("block_syntax"); 218 | writer.Key("line"); 219 | writer.Int(tree.line); 220 | writer.Key("pos"); 221 | writer.Int(tree.pos); 222 | writer.Key("body"); 223 | writer.StartArray(); 224 | for (auto stmt : tree.body) 225 | stmt->accept(*this); 226 | writer.EndArray(); 227 | writer.EndObject(); 228 | } 229 | 230 | virtual void visit(if_stmt_syntax &tree) override 231 | { 232 | writer.StartObject(); 233 | writer.Key("type"); 234 | writer.String("if_stmt_syntax"); 235 | writer.Key("line"); 236 | writer.Int(tree.line); 237 | writer.Key("pos"); 238 | writer.Int(tree.pos); 239 | writer.Key("pred"); 240 | tree.pred->accept(*this); 241 | writer.Key("thenbody"); 242 | tree.then_body->accept(*this); 243 | if (tree.else_body) 244 | { 245 | writer.Key("elsebody"); 246 | tree.else_body->accept(*this); 247 | } 248 | writer.EndObject(); 249 | } 250 | 251 | virtual void visit(while_stmt_syntax &tree) override 252 | { 253 | writer.StartObject(); 254 | writer.Key("type"); 255 | writer.String("while_stmt_syntax"); 256 | writer.Key("line"); 257 | writer.Int(tree.line); 258 | writer.Key("pos"); 259 | writer.Int(tree.pos); 260 | writer.Key("pred"); 261 | tree.pred->accept(*this); 262 | writer.Key("body"); 263 | tree.body->accept(*this); 264 | writer.EndObject(); 265 | } 266 | 267 | virtual void visit(empty_stmt_syntax &tree) override 268 | { 269 | writer.StartObject(); 270 | writer.Key("type"); 271 | writer.String("empty_stmt_syntax"); 272 | writer.Key("line"); 273 | writer.Int(tree.line); 274 | writer.Key("pos"); 275 | writer.Int(tree.pos); 276 | writer.EndObject(); 277 | } 278 | 279 | private: 280 | Writer &writer; 281 | }; 282 | } 283 | } 284 | 285 | #endif 286 | -------------------------------------------------------------------------------- /c1recognizer/test/test_cases/declarations.c1: -------------------------------------------------------------------------------- 1 | 2 | int v1, v2 = 3; 3 | int a1[3]; 4 | int a2[3] = {1, 2}; 5 | int a3[] = {1, 2, 3, 4}; 6 | const int c1 = 3, a4[2] = {1, 2}; 7 | 8 | void main() 9 | { 10 | int v1, v2 = 3; 11 | int a1[3]; 12 | int a2[3] = {1, 2}; 13 | int a3[] = {1, 2, 3, 4}; 14 | const int c1 = 3, a4[2] = {1, 2}; 15 | } 16 | -------------------------------------------------------------------------------- /c1recognizer/test/test_cases/exp_example.c1: -------------------------------------------------------------------------------- 1 | 0x1 + 0xf 2 | -------------------------------------------------------------------------------- /c1recognizer/test/test_cases/expr.c1: -------------------------------------------------------------------------------- 1 | const int e1 = 1 + 2; 2 | const int e2 = 1 - 2; 3 | const int e3 = 1 * 3; 4 | const int e4 = 4 / 2; 5 | const int e5 = 1 % 2; 6 | const int e6 = +1; 7 | const int e7 = -1; 8 | const int e8 = 1 + 2 * 3; 9 | const int e9 = (1 + 2) * 3; 10 | const int e10[] = {e1, e2, e3}; 11 | const int e11 = e10[e1]; 12 | -------------------------------------------------------------------------------- /c1recognizer/test/test_cases/lexical_tokens.c1: -------------------------------------------------------------------------------- 1 | void main() { 2 | const int v[1] = {1}; // line comment test 3 | int i = v[0]; // line comment \ 4 | cross line 5 | if(i > 0) i = 1; 6 | else i = -1; 7 | i = (i + 1 - 1) * 3 / 2 % 3; 8 | while (i > 0) i = i - 1; 9 | while (i < 0) i = i - 1; 10 | while (i == 0) i = i - 1; /* block 11 | comment */ 12 | while (i != 0) i = i - 1; 13 | while (i >= 0) i = i - 1; 14 | while (i <= 0) i = i - 1; 15 | i = 0x1234FeDc; 16 | } -------------------------------------------------------------------------------- /c1recognizer/test/test_cases/simple.c1: -------------------------------------------------------------------------------- 1 | int i = 0; 2 | void main() 3 | { 4 | i = 1; 5 | } 6 | -------------------------------------------------------------------------------- /hwevalstd.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustc-compiler/2018fall/706d23b868ee41bc315bc2a9d75e0a9972c338ef/hwevalstd.xlsx -------------------------------------------------------------------------------- /labEvalStd(Reference).md: -------------------------------------------------------------------------------- 1 | # 实验评价标准(参考) 2 | 3 | - `1.概述` 4 | - `2.Lab1-1的评价标准` 5 | - `3.Lab1-2的评价标准` 6 | - `4.Lab1-3的评价标准` 7 | - `5.Lab2-1的评价标准` 8 | 9 | 10 | 11 | 12 | ## 1.概述 13 | 14 | 我们对于实验的评价标准,是在HW1的时候给出的评价标准的基础上进行补充的.分为以下九个维度: 15 | 16 | - 目录结构 17 | - 文档说明 18 | - 项目构建 19 | - 代码风格 20 | - 功能实现 21 | - Git提交 22 | - 测试样例 23 | - 回答与总结 24 | - 延迟提交 25 | 26 | 27 | 28 | ## 2.Lab1-1的评价标准 29 | 30 | 针对Lab1-1的具体情况,九个维度的具体要求如下: 31 | 32 | - 目录结构 : 严格按照实验要求,必要的文件不可缺少,因为测试使用的自动化的脚本.目录结构如下: 33 | 34 | ``` text 35 | - 36 | | c1recognizer 复制自公共仓库的 c1recognizer 项目,请勿遗漏内容。 37 | | cmake/ 38 | >> | grammar/ 修改其中的 C1Lexer.g4 39 | | include/c1recognizer/ 40 | | src/ 41 | >> | test/test_cases/lexer/ 增加你的测试程序 42 | >> | doc/ 增加文档描述实验中遇到的问题、分析和设计,文件名前缀为lab1-1 43 | | 其他已有的文件 44 | ``` 45 | 46 | - 文档说明(忽略) : 本次实验不需要额外的README.md等说明, 忽略. 47 | - 项目构建(忽略) : 本次实验不需要额外的Makefile等,忽略. 48 | - 代码风格 : 本次实验只需要修改C1Lexer.g4, 只需要添加测试样例,希望各位做到文法结构清晰,单行长度合理,缩进合理,最终的目的是方便阅读. 49 | - 功能实现 : 本次实验需要按照要求的文法进行.g4的修改.我们会针对需要识别的各种token设置合理充足的测试样例,并进行自动化测试.当然这部分你们只需要写出尽可能准确的.g4.对于注释的反斜杠的需求考核,在整个评价中占比不是很大,你们可以自行权衡. 50 | - Git提交 : git log 需要言之有物,合理而简洁,没有额外的文件提交.不要把其他多余的文件,比如说*.java, *.class, *.tokens也提交上来. 51 | - 测试样例 : 不需要想出太多的测试样例,只需要一些简洁精准的测试样例,关键是反映出你的思考. 52 | - 回答与总结 : 在c1recognizer/doc/目录下增加文档,描述本次实验中的设计(包括但不限于:标识符、整型常量、浮点型常量、注释,还有设计出的正确和错误的测试样例等),还有遇到的问题、分析以及解决方案等。注意文档的命名前缀为lab1-1,文档内容不要太长,在保持内容充足的情况下简练。 53 | - 延迟提交 : 如果延迟提交,会根据延迟的时间长度,对最后的评价结果大打折扣. 54 | 55 | 56 | 57 | 58 | ## 3.Lab1-2的评价标准 59 | 60 | 针对Lab1-2的具体情况,九个维度的具体要求如下: 61 | 62 | - 目录结构 : 严格按照实验要求.目录结构如下: 63 | 64 | ``` text 65 | - 66 | | lab1-answer 67 | | lab1-2.* 回答lab1-2的问题1--问题3 68 | | 其他被引用图像文件 69 | | c1recognizer 复制自公共仓库的 c1recognizer 项目。请勿遗漏内容。 70 | | cmake/ 71 | >> | grammar/ 修改其中的 C1Parser.g4 72 | | include/c1recognizer/ 73 | | src/ 74 | >> | test/test_cases/ 补充你的测试程序 75 | >> | doc/ 增加文档描述实验中遇到的问题、分析和设计,文件名前缀为lab1-2. 76 | | 其他已有的文件 77 | ``` 78 | - 功能实现 : 本次实验需要按照要求的文法进行.g4的修改.我们会针对需要识别的各种token设置合理充足的测试样例,并进行自动化测试.当然这部分你们只需要写出尽可能准确的.g4.对于注释的反斜杠的需求考核,在整个评价中占比不是很大,你们可以自行权衡. 79 | - 回答与总结 : 80 | - c1recognizer/doc/lab1-2.* 增加文档描述实验中遇到的问题、分析和设计,文件名前缀为lab1-2.文档内容不要太长,在保持内容充足的情况下简练。 81 | - lab1-answer/lab1-2* 增加回答lab1-2的问题1--问题3的解答,文件名前缀为lab1-2,以及可能的被引用图像文件 82 | 83 | 其他类似于`Lab1-1的评价标准` 84 | 85 | 86 | 87 | ## 4.Lab1-3的评价标准 88 | 89 | 针对Lab1-3的具体情况,九个维度的具体要求如下: 90 | 91 | - 目录结构 : 严格按照实验要求.目录结构如下: 92 | 93 | ``` text 94 | - 95 | | lab1-answer 96 | | lab1-2.* 97 | >> | lab1-3.md 回答Lab1-3的问题 98 | | c1recognizer 复制自公共仓库的 c1recognizer 项目,请勿遗漏内容。 99 | | cmake/ 100 | | grammar/ 101 | | include/c1recognizer/ 102 | >> | src/ 修改完善recognizer.cpp和syntax_tree_builder.cpp 103 | >> | test/test_cases/ 如果有更多的测试程序,可以在其中补充 104 | >> | doc/ 描述实验中遇到的问题、分析和设计,增加lab1-3.md记录主要任务一节要求的内容 105 | | 其他已有的文件 106 | ``` 107 | 108 | - 代码风格 : 注意添加充分的,必要的注释!!!注意缩进,注意变量名的合理性.总的来说就是增加代码的可读性. 109 | - 回答与总结 : 110 | - 在c1recognizer/doc/lab1-3.md 增加lab1-3.md记录主要任务一节要求的内容,描述实验中遇到的问题、分析和设计. 111 | - 在lab1-answer/lab1-3.md 增加lab1-3.md回答Lab1-3的问题的解答. 112 | 113 | 其他类似于`Lab1-2的评价标准` 114 | 115 | 116 | 117 | ## 5.Lab2-1的评价标准 118 | 119 | 针对Lab2-1的具体情况,九个维度的具体要求如下: 120 | 121 | - 目录结构 : 严格按照实验要求,目录结构如下: 122 | 123 | ``` text 124 | - 125 | | lab2 126 | | Makefile/CMakeLists.txt 你编写的自动构建脚本等 127 | | README.md 简单说明如何运行你的自动构建脚本 128 | | fib.ll 你手动编写的.ll //注意添加充分的,适当的充分的注释!!! 129 | | gen_fib.cpp 构建.ll的.cpp //注意添加充分的,适当的充分的注释!!! 130 | | c1recognizer 之前的lab1 131 | | HW 132 | | lab1-answer 133 | ``` 134 | 135 | - 文档说明 : README.md - 简单说明如何运行你的自动构建脚本. 136 | - 项目构建 : 以Makefile或CMakeLists.txt的形式编写的自动构建脚本. 137 | - 代码风格 : 注意添加充分的,适当的充分的注释!!!注意缩进,注意变量名的合理性.总的来说就是增加代码的可读性.希望养成好的代码风格!!!!!!!!!!!!!!!!!! 138 | - 功能实现 : 最后运行正确,返回值正确 139 | - Git提交 : git log 需要言之有物,合理而简洁,没有额外的文件提交 140 | - 测试样例(忽略) : 141 | - 回答与总结(忽略) : 142 | - 延迟提交 : 如果延迟提交,会根据延迟的时间长度,对最后的评价结果大打折扣. 143 | -------------------------------------------------------------------------------- /llvm-irgen-example/README.md: -------------------------------------------------------------------------------- 1 | 2 | # LLVM IRGen Example 3 | 4 | In this example, a C++ source code generating below LLVM IR through LLVM IRGen module is presented: 5 | 6 | ``` 7 | ; ModuleID = 'foo_dead_recursive_loop' 8 | source_filename = "foo_dead_recursive_loop" 9 | 10 | define void @foo() { 11 | entry: 12 | call void @foo() 13 | ret void 14 | } 15 | ``` 16 | 17 | You can build it with command as below once you have llvm developing libraries installed. 18 | 19 | ```sh 20 | c++ llvm-irgen-example.cpp -o llvm-irgen-example `llvm-config --cxxflags --ldflags --libs --system-libs` 21 | ``` 22 | -------------------------------------------------------------------------------- /llvm-irgen-example/llvm-irgen-example.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | using namespace llvm; 15 | 16 | int main() 17 | { 18 | LLVMContext context; 19 | IRBuilder<> builder(context); 20 | 21 | auto module = new Module("foo_dead_recursive_loop", context); 22 | 23 | auto func = Function::Create(FunctionType::get(Type::getVoidTy(context), std::vector(), false), 24 | GlobalValue::LinkageTypes::ExternalLinkage, 25 | "foo", module); 26 | auto bb = BasicBlock::Create(context, "entry", func); 27 | builder.SetInsertPoint(bb); 28 | builder.CreateCall(func, {}); 29 | builder.CreateRetVoid(); 30 | builder.ClearInsertionPoint(); 31 | 32 | module->print(outs(), nullptr); 33 | delete module; 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /testcases/c1i/t01_opif.c1: -------------------------------------------------------------------------------- 1 | void main() { 2 | int x=3; 3 | float y=3.1; 4 | if (y-x < 0.1) 5 | x = y; 6 | else 7 | y = x; 8 | x = x * (x+2*x); 9 | } 10 | -------------------------------------------------------------------------------- /testcases/c1i/t02_arrwhile.c1: -------------------------------------------------------------------------------- 1 | void main() { 2 | int i = 9, j = 3, a[10*(10/10)]={1,2,3}; 3 | while (i > j - 3 ) { 4 | a[i]=j; 5 | j = j + 1; 6 | i = i - 1; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /testcases/c1i/t03_if.c1: -------------------------------------------------------------------------------- 1 | void main() { 2 | int i = 8*3-2, j = i - 1; 3 | 4 | if ( i == j ) i = 3; 5 | else if ( i > 10) i = j*2-i; 6 | else i = i; 7 | } 8 | -------------------------------------------------------------------------------- /testcases/c1i/t04_relops.c1: -------------------------------------------------------------------------------- 1 | void main() { 2 | const float a = 3; 3 | const int ia = 3; 4 | int i = ia, j; 5 | float b = a; 6 | 7 | if ( i == ia ) j = 1; 8 | if ( i != ia ) j = 0; 9 | if ( i >= ia ) j = 1; 10 | if ( i > ia ) j = 0; 11 | if ( i < ia ) j = 0; 12 | if ( i <= ia ) j = 1; 13 | 14 | if ( b - ia > 0 ) { 15 | j = 1; 16 | if ( b - ia < 0.000001 ) j = 11; 17 | else j = 12; 18 | } else { 19 | j = 2; 20 | if ( ia - b < 0.000001 ) j = 21; 21 | else j = 22; 22 | } 23 | 24 | if ( b - a < 0.000001 ) j = 3; 25 | else j = 30; 26 | 27 | // float point numbers cannot be compared by == or !== 28 | if ( b == a ) j = 31; 29 | if ( b != a ) j = 32; 30 | } 31 | -------------------------------------------------------------------------------- /testcases/c1i/t05_unary.c1: -------------------------------------------------------------------------------- 1 | void main() { 2 | int x; 3 | float y; 4 | 5 | x = +9; 6 | x = -x; 7 | x = -(x * 1); 8 | x = -(x * -1); 9 | x = -(-x * -1); 10 | x = -(-1 * x); 11 | y = -x; 12 | y = -(y * 1); 13 | y = -(y * -1); 14 | y = -(-y * -1); 15 | y = -(-1 * y); 16 | } 17 | -------------------------------------------------------------------------------- /testcases/c1i/t06_func.c1: -------------------------------------------------------------------------------- 1 | int in_fib; 2 | int ret_fib; 3 | void fib() { 4 | if (in_fib == 0) ret_fib = 0; 5 | else if (in_fib == 1) ret_fib = 1; 6 | else { 7 | int self_in = in_fib; 8 | in_fib = self_in - 1; 9 | fib(); 10 | int tmp = ret_fib; 11 | in_fib = self_in - 2; 12 | fib(); 13 | ret_fib = tmp + ret_fib; 14 | } 15 | } 16 | 17 | void main() { 18 | in_fib = 10; 19 | fib(); 20 | output_ivar = ret_fib; 21 | outputInt(); 22 | } 23 | -------------------------------------------------------------------------------- /testcases/c1i/t07_ops.c1: -------------------------------------------------------------------------------- 1 | void main() { 2 | int x; 3 | x = 7; 4 | 5 | x = x * (x / x); 6 | x = x * x / x; 7 | x = x % x + x; 8 | x = x + x % x; 9 | x = x + x % x / x; 10 | x = x + x % (x / x); 11 | } 12 | -------------------------------------------------------------------------------- /testcases/c1i/t08_opsIO.c1: -------------------------------------------------------------------------------- 1 | void main() { 2 | int x; 3 | inputInt(); 4 | x = input_ivar; 5 | 6 | x = x * (x / x); 7 | output_ivar = x; 8 | outputInt(); 9 | x = x * x / x; 10 | output_ivar = x; 11 | outputInt(); 12 | x = x % x + x; 13 | output_ivar = x; 14 | outputInt(); 15 | x = x + x % x; 16 | output_ivar = x; 17 | outputInt(); 18 | x = x + x % x / x; 19 | output_ivar = x; 20 | outputInt(); 21 | x = x + x % (x / x); 22 | output_ivar = x; 23 | outputInt(); 24 | } 25 | -------------------------------------------------------------------------------- /testcases/c1i/t09_arr.c1: -------------------------------------------------------------------------------- 1 | void main() { 2 | const int N=10; 3 | int x, j=1; 4 | int a[10] = {1}; 5 | while ( j < N) { 6 | a[j] = a[j-1] + 1; 7 | a[j*1] = a[j/j+j*1-1]; 8 | j = j + 1; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /testcases/c1i/t10_block.c1: -------------------------------------------------------------------------------- 1 | int i = 10, j = 10; 2 | float a = 10; 3 | void main() { 4 | int i = j-1; 5 | output_fvar = a; 6 | outputFloat(); 7 | { 8 | float i = a; 9 | a = i + a; 10 | output_fvar = a; 11 | outputFloat(); 12 | } 13 | { 14 | int i = j-2; 15 | a = a + i; 16 | output_fvar = a; 17 | outputFloat(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /testcases/c1r/test10_bracket_expr.c1: -------------------------------------------------------------------------------- 1 | 2 | void main() { 3 | int x; 4 | // brackets 5 | x = x + (x + 2); 6 | } 7 | -------------------------------------------------------------------------------- /testcases/c1r/test11_relops.c1: -------------------------------------------------------------------------------- 1 | 2 | void main() { 3 | int i = 0, j = 1; 4 | 5 | // if, relops 6 | if (i > 0) i = 0; 7 | if (i < 0) i = 0; 8 | if (i >= 0) i = 0; 9 | if (i <= 0) i = 0; 10 | if (i == 0) i = 0; 11 | if (i != 0) i = 0; 12 | } 13 | -------------------------------------------------------------------------------- /testcases/c1r/test12_simple_ifelse.c1: -------------------------------------------------------------------------------- 1 | 2 | void main() { 3 | int i = 0, j = 1; 4 | 5 | // if-else with block body 6 | if (j != 0) { 7 | i = j + 1; 8 | j = i + 1; 9 | } else { 10 | j = i + 1; 11 | i = i + 1; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /testcases/c1r/test13_nested_ifelse.c1: -------------------------------------------------------------------------------- 1 | 2 | void main() { 3 | int i = 0, j = 1; 4 | 5 | // if-else if-else 6 | if (i == 10) i = 20; 7 | else if (i > 10) i = i * 2; 8 | else i = 19; 9 | } 10 | -------------------------------------------------------------------------------- /testcases/c1r/test14_while.c1: -------------------------------------------------------------------------------- 1 | 2 | void main() { 3 | int i = 0, j = 1; 4 | 5 | // while with block body 6 | while (j > i) { 7 | j = j - 1; 8 | i = i + 1; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /testcases/c1r/test15_func.c1: -------------------------------------------------------------------------------- 1 | 2 | int in_fib; 3 | int ret_fib; 4 | void fib() { 5 | if (in_fib == 0) ret_fib = 0; 6 | else if (in_fib == 1) ret_fib = 0; 7 | else { 8 | int self_in = in_fib; 9 | in_fib = self_in - 1; 10 | fib(); 11 | int tmp = ret_fib; 12 | in_fib = self_in - 2; 13 | fib(); 14 | ret_fib = tmp + ret_fib; 15 | } 16 | } 17 | 18 | void main() { 19 | in_fib = 10; 20 | fib(); 21 | output_var = ret_fib; 22 | output(); 23 | } 24 | -------------------------------------------------------------------------------- /testcases/c1r/test1_int_decl.c1: -------------------------------------------------------------------------------- 1 | int v1; 2 | int v2, v3, v4, v5; 3 | int v6 = 3; 4 | int v7, v8 = 0, v9 = 0x123456; 5 | 6 | -------------------------------------------------------------------------------- /testcases/c1r/test2_float_decl.c1: -------------------------------------------------------------------------------- 1 | float v1; 2 | float v2, v3, v4, v5; 3 | float v6 = 1.0; 4 | float v7, v8 = 2., v9 = .3; 5 | 6 | -------------------------------------------------------------------------------- /testcases/c1r/test3_const_decl.c1: -------------------------------------------------------------------------------- 1 | const int c1 = 3; 2 | const int c2 = 1, c3 = 0x123456; 3 | const float c3 = 1.; 4 | const float c4 = .2, c5 = 3.0; 5 | -------------------------------------------------------------------------------- /testcases/c1r/test4_array_decl.c1: -------------------------------------------------------------------------------- 1 | int a1[2]; 2 | int a2[2] = {1, 2}; 3 | int a3[3] = {1, 2}; 4 | const int ca1[2] = {1, 2}; 5 | -------------------------------------------------------------------------------- /testcases/c1r/test5_blockstmt_decl.c1: -------------------------------------------------------------------------------- 1 | 2 | void main() { 3 | int v1; 4 | int v2, v3, v4, v5; 5 | int v6 = 3; 6 | int v7, v8 = 900913, v9 = 0x123456; 7 | 8 | const int c1 = 3; 9 | const int c2 = 1, c3 = 0x123456; 10 | 11 | int a1[2]; 12 | int a2[2] = {1, 2}; 13 | int a3[3] = {1, 2}, a4[3] = {1, 3}; 14 | const int ca1[2] = {1, 2}, ca2[7] = {1, 2, 3, 1, 3, 2}; 15 | } 16 | -------------------------------------------------------------------------------- /testcases/c1r/test6_simple_assign_expr.c1: -------------------------------------------------------------------------------- 1 | 2 | void main() { 3 | int x; 4 | // lval 5 | x = 1; 6 | // simple 7 | x = 2 + 3; 8 | x = 4 - 5; 9 | x = 6 * 7; 10 | x = 8 / 9; 11 | } 12 | -------------------------------------------------------------------------------- /testcases/c1r/test7_unary_expr.c1: -------------------------------------------------------------------------------- 1 | 2 | void main() { 3 | int x; 4 | // unary 5 | x = -x; 6 | x = +1; 7 | } 8 | -------------------------------------------------------------------------------- /testcases/c1r/test8_binary_expr.c1: -------------------------------------------------------------------------------- 1 | 2 | void main() { 3 | int x; 4 | // simple with lval 5 | x = x + 1; 6 | x = x - 1; 7 | x = x * 2; 8 | x = x / 3; 9 | } 10 | -------------------------------------------------------------------------------- /testcases/c1r/test9_arr_index_expr.c1: -------------------------------------------------------------------------------- 1 | 2 | void main() { 3 | int x; 4 | // array index 5 | int a[1] = {2}; 6 | x = a[0]; 7 | x = 1 + a[0]; 8 | } 9 | --------------------------------------------------------------------------------