├── .gitignore ├── .vscode └── settings.json ├── LICENSE ├── Makefile ├── README.md ├── ast.c ├── ast.h ├── data.h ├── declaration.c ├── declaration.h ├── definations.h ├── generator.c ├── generator.h ├── generator_core.c ├── generator_core.h ├── generator_core_arm.c ├── helper.c ├── helper.h ├── incdir.h ├── include ├── ctype.h ├── errno.h ├── fcntl.h ├── stddef.h ├── stdio.h ├── stdlib.h ├── string.h └── unistd.h ├── interpreter.c ├── interpreter.h ├── main.c ├── optimizer.c ├── optimizer.h ├── parser.c ├── parser.h ├── scan.c ├── scan.h ├── statement.c ├── statement.h ├── symbol_table.c ├── symbol_table.h ├── test ├── assert │ ├── out.input001.zc │ ├── out.input002.zc │ ├── out.input003.zc │ ├── out.input004.zc │ ├── out.input005.zc │ ├── out.input006.zc │ ├── out.input007.zc │ ├── out.input008.zc │ ├── out.input009.zc │ ├── out.input010.zc │ ├── out.input011.zc │ ├── out.input012.zc │ ├── out.input013.zc │ ├── out.input014.zc │ ├── out.input015.zc │ ├── out.input016.zc │ ├── out.input017.zc │ ├── out.input018.zc │ ├── out.input019.zc │ ├── out.input020.zc │ ├── out.input021.zc │ ├── out.input022.zc │ ├── out.input023.zc │ ├── out.input024.zc │ ├── out.input025.zc │ ├── out.input026.zc │ ├── out.input027.zc │ ├── out.input028.zc │ ├── out.input029.zc │ ├── out.input030.zc │ ├── out.input053.zc │ ├── out.input054.zc │ ├── out.input055.zc │ ├── out.input058.zc │ ├── out.input062.zc │ ├── out.input063.zc │ ├── out.input067.zc │ ├── out.input070.zc │ ├── out.input071.zc │ ├── out.input074.zc │ ├── out.input080.zc │ ├── out.input081.zc │ ├── out.input082.zc │ ├── out.input083.zc │ ├── out.input084.zc │ ├── out.input088.zc │ ├── out.input089.zc │ ├── out.input090.zc │ ├── out.input091.zc │ ├── out.input099.zc │ ├── out.input100.zc │ ├── out.input101.zc │ ├── out.input106.zc │ ├── out.input107.zc │ ├── out.input108.zc │ ├── out.input109.zc │ ├── out.input110.zc │ ├── out.input111.zc │ ├── out.input112.zc │ ├── out.input113.zc │ ├── out.input114.zc │ ├── out.input115.zc │ ├── out.input116.zc │ ├── out.input117.zc │ ├── out.input119.zc │ ├── out.input120.zc │ ├── out.input121.zc │ ├── out.input122.zc │ ├── out.input123.zc │ ├── out.input125.zc │ ├── out.input127.zc │ ├── out.input128.zc │ ├── out.input130.zc │ ├── out.input131.zc │ ├── out.input132.zc │ ├── out.input133.zc │ ├── out.input134.zc │ ├── out.input135.zc │ ├── out.input136.zc │ ├── out.input137.zc │ ├── out.input138.zc │ ├── out.input139.zc │ ├── out.input140.zc │ ├── out.input143.zc │ ├── out.input144.zc │ ├── out.input145.zc │ ├── out.input146.zc │ ├── out.input147.zc │ ├── out.input148.zc │ ├── out.input149.zc │ ├── out.input150.zc │ ├── out.input151.zc │ ├── out.input152.zc │ └── out.input153.zc ├── error │ ├── error.input031.zc │ ├── error.input032.zc │ ├── error.input033.zc │ ├── error.input035.zc │ ├── error.input036.zc │ ├── error.input037.zc │ ├── error.input038.zc │ ├── error.input039.zc │ ├── error.input040.zc │ ├── error.input041.zc │ ├── error.input042.zc │ ├── error.input043.zc │ ├── error.input044.zc │ ├── error.input045.zc │ ├── error.input046.zc │ ├── error.input047.zc │ ├── error.input048.zc │ ├── error.input049.zc │ ├── error.input050.zc │ ├── error.input051.zc │ ├── error.input052.zc │ ├── error.input056.zc │ ├── error.input057.zc │ ├── error.input059.zc │ ├── error.input060.zc │ ├── error.input061.zc │ ├── error.input064.zc │ ├── error.input065.zc │ ├── error.input066.zc │ ├── error.input068.zc │ ├── error.input069.zc │ ├── error.input072.zc │ ├── error.input073.zc │ ├── error.input075.zc │ ├── error.input076.zc │ ├── error.input077.zc │ ├── error.input078.zc │ ├── error.input079.zc │ ├── error.input085.zc │ ├── error.input086.zc │ ├── error.input087.zc │ ├── error.input092.zc │ ├── error.input093.zc │ ├── error.input094.zc │ ├── error.input095.zc │ ├── error.input096.zc │ ├── error.input098.zc │ ├── error.input102.zc │ ├── error.input103.zc │ ├── error.input104.zc │ ├── error.input105.zc │ ├── error.input118.zc │ ├── error.input124.zc │ ├── error.input126.zc │ ├── error.input129.zc │ ├── error.input141.zc │ └── error.input142.zc ├── input001.zc ├── input002.zc ├── input003.zc ├── input004.zc ├── input005.zc ├── input006.zc ├── input007.zc ├── input008.zc ├── input009.zc ├── input010.zc ├── input011.zc ├── input012.zc ├── input013.zc ├── input014.zc ├── input015.zc ├── input016.zc ├── input017.zc ├── input018.zc ├── input019.zc ├── input020.zc ├── input021.zc ├── input022.zc ├── input023.zc ├── input024.zc ├── input025.zc ├── input026.zc ├── input027.zc ├── input028.zc ├── input029.zc ├── input030.zc ├── input031.zc ├── input032.zc ├── input033.zc ├── input035.zc ├── input036.zc ├── input037.zc ├── input038.zc ├── input039.zc ├── input040.zc ├── input041.zc ├── input042.zc ├── input043.zc ├── input044.zc ├── input045.zc ├── input046.zc ├── input047.zc ├── input048.zc ├── input049.zc ├── input050.zc ├── input051.zc ├── input052.zc ├── input053.zc ├── input054.zc ├── input055.zc ├── input056.zc ├── input057.zc ├── input058.zc ├── input059.zc ├── input060.zc ├── input061.zc ├── input062.zc ├── input063.zc ├── input064.zc ├── input065.zc ├── input066.zc ├── input067.zc ├── input068.zc ├── input069.zc ├── input070.zc ├── input071.zc ├── input072.zc ├── input073.zc ├── input074.zc ├── input075.zc ├── input076.zc ├── input077.zc ├── input078.zc ├── input079.zc ├── input080.zc ├── input081.zc ├── input082.zc ├── input083.zc ├── input084.zc ├── input085.zc ├── input086.zc ├── input087.zc ├── input088.zc ├── input089.zc ├── input090.zc ├── input091.zc ├── input092.zc ├── input093.zc ├── input094.zc ├── input095.zc ├── input096.zc ├── input098.zc ├── input099.zc ├── input100.zc ├── input101.zc ├── input102.zc ├── input103.zc ├── input104.zc ├── input105.zc ├── input106.zc ├── input107.zc ├── input108.zc ├── input109.zc ├── input110.zc ├── input111.zc ├── input112.zc ├── input113.zc ├── input114.zc ├── input115.zc ├── input116.zc ├── input117.zc ├── input118.zc ├── input119.zc ├── input120.zc ├── input121.zc ├── input122.zc ├── input123.zc ├── input124.zc ├── input125.zc ├── input126.zc ├── input127.zc ├── input128.zc ├── input129.zc ├── input130.zc ├── input131.zc ├── input132.zc ├── input133.zc ├── input134.zc ├── input135.zc ├── input136.zc ├── input137.zc ├── input138.zc ├── input139.zc ├── input140.zc ├── input141.zc ├── input142.zc ├── input143.zc ├── input144.zc ├── input145.zc ├── input146.zc ├── input147.zc ├── input148.zc ├── input149.zc ├── input150.zc ├── input151.zc ├── input152.zc ├── input153.zc ├── make_test └── run_test ├── types.c └── types.h /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.s 3 | out.s 4 | out 5 | *.out 6 | scanner 7 | parser 8 | parser0 9 | parser1 10 | parser2 11 | parser.dSYM/ 12 | .vscode/ 13 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "__tuple": "cpp", 4 | "array": "cpp", 5 | "definations.h": "c", 6 | "data.h": "c", 7 | "generator.h": "c", 8 | "stdio.h": "c", 9 | "statement.h": "c", 10 | "generator_core.h": "c", 11 | "declaraion.h": "c", 12 | "helper.h": "c", 13 | "symbol_table.h": "c" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Jiang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC= cc 2 | DEBUG= -T 3 | 4 | COMMON= parser.c interpreter.c main.c \ 5 | scan.c ast.c generator.c statement.c \ 6 | helper.c symbol_table.c types.c declaration.c \ 7 | optimizer.c 8 | 9 | HSRCS= data.h parser.h interpreter.h \ 10 | scan.h ast.h generator.h statement.h \ 11 | helper.h symbol_table.h types.h declaration.h \ 12 | optimizer.h 13 | 14 | SRCS= $(COMMON) generator_core.c 15 | ARM_SRCS= $(COMMON) generator_core_arm.c 16 | TEST_CASE_NAME= 153 17 | TEST_CASE= test/input$(TEST_CASE_NAME).zc 18 | INCLUDE_DIRECTORY= /tmp/include 19 | BINARAY_DIRECTORY= /tmp 20 | 21 | incdir.h: 22 | echo "#define INCDIR \"$(INCLUDE_DIRECTORY)\"" > incdir.h 23 | 24 | clean: 25 | rm -f parser parser0 parser1 parser2 parser_arm *.o *.s out test/out *.out test/*.s 26 | 27 | install: parser 28 | sudo mkdir -p $(INCLUDE_DIRECTORY) 29 | sudo rsync -a include/. $(INCLUDE_DIRECTORY) 30 | sudo cp parser $(BINARAY_DIRECTORY) 31 | sudo chmod +x $(BINARAY_DIRECTORY)/parser 32 | 33 | parser: $(SRCS) $(HSRCS) 34 | $(CC) -o parser -g $(SRCS) 35 | 36 | parser_arm: $(ARM_SRCS) $(HSRCS) 37 | $(CC) -o parser -g $(ARM_SRCS) 38 | cp parser_arm parser 39 | 40 | gen: test/make_test 41 | (cd test; chmod +x make_test; ./make_test) 42 | 43 | test: install test/run_test 44 | (cd test; chmod +x run_test; ./run_test) 45 | 46 | test_arm: parser_arm test/run_test 47 | (cd test; chmod +x run_test; ./run_test) 48 | 49 | t: parser $(TEST_CASE) 50 | ./parser -o out $(TEST_CASE) 51 | ./out 52 | 53 | t0: parser0 $(TEST_CASE) 54 | ./parser0 -o out $(TEST_CASE) 55 | ./out 56 | 57 | t_arm: parser_arm $(TEST_CASE) $(LIB) 58 | ./parser -o out $(TEST_CASE) 59 | ./out 60 | 61 | # 编译自举 62 | test0: install test/run_test parser0 63 | (cd test; chmod +x run_test; ./run_test 0) 64 | 65 | triple: parser1 66 | size parser[01] 67 | 68 | quad: parser2 69 | size parser[012] 70 | 71 | parser2: parser1 $(SRCS) $(HSRCS) 72 | ./parser1 -o parser2 $(SRCS) 73 | 74 | parser1: parser0 $(SRCS) $(HSRCS) 75 | ./parser0 -o parser1 $(SRCS) 76 | 77 | parser0: install $(SRCS) $(HSRCS) 78 | ./parser -o parser0 $(SRCS) 79 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # zcc 2 | 3 | 以下是该项目的总结文章 4 | 5 | - [zcc-编译器开发总结-part1-前言](https://strugglebak.github.io/2022/06/05/zcc-%E7%BC%96%E8%AF%91%E5%99%A8%E5%BC%80%E5%8F%91%E6%80%BB%E7%BB%93-part1-%E5%89%8D%E8%A8%80/) 6 | - [zcc-编译器开发总结-part2-Front-End](https://strugglebak.github.io/2022/06/06/zcc-%E7%BC%96%E8%AF%91%E5%99%A8%E5%BC%80%E5%8F%91%E6%80%BB%E7%BB%93-part2-Front-End/) 7 | - [zcc-编译器开发总结-part3-Back-End](https://strugglebak.github.io/2022/06/06/zcc-%E7%BC%96%E8%AF%91%E5%99%A8%E5%BC%80%E5%8F%91%E6%80%BB%E7%BB%93-part3-Back-End/) 8 | - [zcc-编译器开发总结-part4-Middle-End](https://strugglebak.github.io/2022/06/06/zcc-%E7%BC%96%E8%AF%91%E5%99%A8%E5%BC%80%E5%8F%91%E6%80%BB%E7%BB%93-part4-Middle-End/) 9 | - [zcc-编译器开发总结-part5-链接和加载流程](https://strugglebak.github.io/2022/06/06/zcc-%E7%BC%96%E8%AF%91%E5%99%A8%E5%BC%80%E5%8F%91%E6%80%BB%E7%BB%93-part5-%E9%93%BE%E6%8E%A5%E5%92%8C%E5%8A%A0%E8%BD%BD%E6%B5%81%E7%A8%8B/) 10 | 11 | zero c compiler,一个从零开始写的编译器,不仅仅为了学习编译原理 12 | 13 | > 命名规范如下 14 | 15 | - 类型大写首字母驼峰 16 | - 变量和函数名小写下划线 17 | - 常量大写下划线 18 | - 驼峰和下划线不混用 19 | 20 | ## 优势 21 | 22 | 由于是用 c 写的编译 c 代码的编译器,项目中并 **没有采用任何第三方的 `.so` 动态链接库或者是 `.a` 静态链接库**,有也只是用了标准库里面的函数,所以基本遵从 "**从零开始写**" 这一原则 23 | 24 | ## Features 25 | 26 | - [x] 支持 基本的汇编代码生成 27 | - [x] 支持 全局/局部 变量解析 28 | - [x] 支持 `if`/`while`/`for`/`switch` 语句的解析 29 | - [x] 支持 `struct`/`union`/`sizeof`/`static`/`extern` 等关键字声明的语句的解析 30 | - [x] 支持 全局/局部 的 数组/指针 变量的赋值与被赋值 31 | - [x] 支持 函数声明/定义 32 | - [x] 支持 函数参数的解析 33 | - [x] 支持 部分不带括号的 `return` 语句 34 | - [x] 支持 打印 AST 35 | - [x] 支持 first time 自举编译 36 | 37 | ## 用法和调试 38 | 39 | ```bash 40 | git clone git@github.com:strugglebak/zcc.git 41 | cd zcc 42 | # 先安装 build 依赖 43 | sudo apt-get install build-essential 44 | # make install 需要权限 45 | make clean && make install 46 | 47 | ./parser your_c_code.zc 48 | ``` 49 | 50 | ## 测试 51 | 52 | ```bash 53 | make clean && make test 54 | ``` 55 | 56 | ## Roadmaps 57 | 58 | - [ ] 完善 ARM 后端相关汇编代码生成 59 | - [ ] 完善 `BNF` 语法(这里可能会使用一些 ``BNF` 工具来做) 60 | - [ ] 支持 `...` token 的解析,用来检查函数的实参和形参个数 61 | - [ ] 支持 `short` 类型解析 62 | - [ ] 优化寄存器分配策略 63 | - [ ] 优化 AST 结构 64 | - [ ] 汇编代码生成优化 65 | - [ ] 增加 Debugging 输出 66 | - [ ] 支持在其他平台运行编译器 67 | 68 | ## 协议 69 | 70 | [MIT](./LICENSE) 71 | -------------------------------------------------------------------------------- /ast.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "definations.h" 5 | #include "helper.h" 6 | 7 | struct ASTNode *create_ast_node( 8 | int operation, 9 | int primitive_type, 10 | struct ASTNode *left, 11 | struct ASTNode *middle, 12 | struct ASTNode *right, 13 | int integer_value, 14 | struct SymbolTable *symbol_table, 15 | struct SymbolTable *composite_type 16 | ) { 17 | struct ASTNode *node; 18 | 19 | node = (struct ASTNode *) malloc(sizeof(struct ASTNode)); 20 | if (node == NULL) 21 | error("Unable to malloc in function make_ast_node"); 22 | 23 | node->operation = operation; 24 | node->primitive_type = primitive_type; 25 | node->left = left; 26 | node->middle = middle; 27 | node->right = right; 28 | node->ast_node_integer_value = integer_value; 29 | node->symbol_table = symbol_table; 30 | node->composite_type = composite_type; 31 | 32 | return (node); 33 | } 34 | 35 | // 创建一个子节点 36 | struct ASTNode *create_ast_leaf( 37 | int operation, 38 | int primitive_type, 39 | int integer_value, 40 | struct SymbolTable *symbol_table, 41 | struct SymbolTable *composite_type 42 | ) { 43 | return ( 44 | create_ast_node( 45 | operation, 46 | primitive_type, 47 | NULL, NULL, NULL, 48 | integer_value, 49 | symbol_table, 50 | composite_type 51 | ) 52 | ); 53 | } 54 | 55 | struct ASTNode *create_ast_left_node( 56 | int operation, 57 | int primitive_type, 58 | struct ASTNode *left, 59 | int integer_value, 60 | struct SymbolTable *symbol_table, 61 | struct SymbolTable *composite_type 62 | ) { 63 | return ( 64 | create_ast_node( 65 | operation, 66 | primitive_type, 67 | left, NULL, NULL, 68 | integer_value, 69 | symbol_table, 70 | composite_type 71 | ) 72 | ); 73 | } 74 | -------------------------------------------------------------------------------- /ast.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __AST_H__ 3 | #define __AST_H__ 4 | 5 | struct ASTNode *create_ast_node( 6 | int operation, 7 | int primitive_type, 8 | struct ASTNode *left, 9 | struct ASTNode *middle, 10 | struct ASTNode *right, 11 | int integer_value, 12 | struct SymbolTable *symbol_table, 13 | struct SymbolTable *composite_type 14 | ); 15 | struct ASTNode *create_ast_leaf( 16 | int operation, 17 | int primitive_type, 18 | int integer_value, 19 | struct SymbolTable *symbol_table, 20 | struct SymbolTable *composite_type 21 | ); 22 | struct ASTNode *create_ast_left_node( 23 | int operation, 24 | int primitive_type, 25 | struct ASTNode *left, 26 | int integer_value, 27 | struct SymbolTable *symbol_table, 28 | struct SymbolTable *composite_type 29 | ); 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /data.h: -------------------------------------------------------------------------------- 1 | #ifndef __DATA_H__ 2 | #define __DATA_H__ 3 | 4 | #include 5 | #include "definations.h" 6 | 7 | #ifndef extern_ 8 | #define extern_ extern 9 | #endif 10 | 11 | #define TEXT_LENGTH 512 12 | #define SYMBOL_TABLE_ENTRIES_NUMBER 1024 13 | #define TOKEN_STRING_NUMBER 128 14 | 15 | extern char *token_strings[]; 16 | extern_ int line; 17 | extern_ int start_line; 18 | extern_ int putback_buffer; 19 | extern_ FILE *input_file; 20 | extern_ FILE *output_file; 21 | extern_ char *global_output_filename; 22 | extern_ char *global_input_filename; 23 | extern_ struct Token token_from_file; 24 | extern_ struct Token look_ahead_token; 25 | extern_ char text_buffer[TEXT_LENGTH + 1]; 26 | extern_ int loop_level; // 嵌套的循环的层级 27 | extern_ int switch_level; // 嵌套的 switch 的层级 28 | 29 | extern_ int output_dump_ast; 30 | extern_ int output_keep_assembly_file; 31 | extern_ int output_keep_object_file; 32 | extern_ int output_binary_file; 33 | extern_ int output_verbose; 34 | extern_ int output_dump_symbol_table; 35 | 36 | extern_ struct SymbolTable *current_function_symbol_id; // 当前函数 37 | extern_ struct SymbolTable *global_head, *global_tail; // 全局变量和函数 38 | extern_ struct SymbolTable *local_head, *local_tail; // 局部变量 39 | extern_ struct SymbolTable *parameter_head, *parameter_tail; // 局部参数 40 | extern_ struct SymbolTable *composite_head, *composite_tail; // 复合变量 41 | extern_ struct SymbolTable *temp_member_head, *temp_member_tail; // struct/union 成员的临时 symbol table 指针 42 | extern_ struct SymbolTable *struct_head, *struct_tail; // struct symbol table 指针 43 | extern_ struct SymbolTable *union_head, *union_tail; // union symbol table 指针 44 | extern_ struct SymbolTable *enum_head, *enum_tail; // enum symbol table 指针 45 | extern_ struct SymbolTable *typedef_head, *typedef_tail; // typedef symbol table 指针 46 | 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /declaration.h: -------------------------------------------------------------------------------- 1 | #ifndef __DECLARATION_H__ 2 | #define __DECLARATION_H__ 3 | 4 | 5 | int is_new_symbol( 6 | struct SymbolTable *t, 7 | int storage_class, 8 | int primitive_type, 9 | struct SymbolTable *composite_type 10 | ); 11 | 12 | int convert_token_2_primitive_type( 13 | struct SymbolTable **composite_type, 14 | int *storage_class 15 | ); 16 | int convert_multiply_token_2_primitive_type(int primitive_type); 17 | int convert_literal_token_2_integer_value(int primitive_type); 18 | int convert_type_casting_token_2_primitive_type(struct SymbolTable **composite_type); 19 | 20 | int parse_typedef_declaration(struct SymbolTable **composite_type); 21 | int parse_type_of_typedef_declaration(char *name, struct SymbolTable **composite_type); 22 | struct SymbolTable *parse_function_declaration( 23 | int primitive_type, 24 | char *function_name, 25 | struct SymbolTable *composite_type, 26 | int storage_class 27 | ); 28 | int parse_declaration_list( 29 | struct SymbolTable **composite_type, 30 | int storage_class, 31 | int end_token, 32 | int end_token_2, 33 | struct ASTNode **glue_tree 34 | ); 35 | void parse_global_declaration(void); 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /definations.h: -------------------------------------------------------------------------------- 1 | #ifndef __DEFINATIONS_H__ 2 | #define __DEFINATIONS_H__ 3 | 4 | #include "incdir.h" 5 | 6 | #define A_OUT "a.out" 7 | #define AS_CMD "as -o " 8 | #define LD_CMD "cc -o " 9 | #define CPP_CMD "cpp -nostdinc -isystem " 10 | 11 | enum { 12 | TOKEN_EOF, 13 | 14 | // 二元操作符 15 | TOKEN_ASSIGN, // = 赋值操作 16 | // +=, -=, *=, /= 17 | TOKEN_ASSIGN_PLUS, TOKEN_ASSIGN_MINUS, TOKEN_ASSIGN_MULTIPLY, TOKEN_ASSGIN_DIVIDE, TOKEN_ASSGIN_MOD, 18 | TOKEN_QUESTION, // \? 19 | TOKEN_LOGIC_AND, // && 20 | TOKEN_LOGIC_OR, // || 21 | TOKEN_OR, TOKEN_XOR, TOKEN_AMPERSAND, // | ^ & 22 | TOKEN_COMPARE_EQUALS, 23 | TOKEN_COMPARE_NOT_EQUALS, 24 | TOKEN_COMPARE_LESS_THAN, 25 | TOKEN_COMPARE_GREATER_THAN, 26 | TOKEN_COMPARE_LESS_EQUALS, 27 | TOKEN_COMPARE_GREATER_EQUALS, 28 | TOKEN_LEFT_SHIFT, // << 29 | TOKEN_RIGHT_SHIFT, // >> 30 | TOKEN_PLUS, TOKEN_MINUS, TOKEN_MULTIPLY, TOKEN_DIVIDE, TOKEN_MOD, 31 | 32 | // 其他操作符 33 | TOKEN_INCREASE, // ++ 34 | TOKEN_DECREASE, // -- 35 | TOKEN_INVERT, // ~ 36 | TOKEN_LOGIC_NOT, // \ ! 37 | 38 | // 类型关键字 39 | TOKEN_VOID, // void 40 | TOKEN_CHAR, // char 41 | TOKEN_INT, // int 42 | TOKEN_LONG, // long 43 | 44 | // 其他关键字 45 | TOKEN_IF, // if 46 | TOKEN_ELSE, // else 47 | TOKEN_WHILE, // while 48 | TOKEN_FOR, // for 49 | TOKEN_RETURN, // return 50 | TOKEN_STRUCT, // struct 51 | TOKEN_UNION, // union 52 | TOKEN_ENUM, // enum 53 | TOKEN_TYPEDEF, // typedef 54 | TOKEN_EXTERN, // extern 55 | TOKEN_BREAK, // break 56 | TOKEN_CONTINUE, // continue 57 | TOKEN_SWITCH, // switch 58 | TOKEN_CASE, // case 59 | TOKEN_DEFAULT, // default 60 | TOKEN_SIZEOF, // sizeof 61 | TOKEN_STATIC, // static 62 | 63 | // 结构化 token 64 | TOKEN_INTEGER_LITERAL, 65 | TOKEN_STRING_LITERAL, // 字符串 66 | TOKEN_SEMICOLON,// 分号 ; 67 | TOKEN_IDENTIFIER, // 标识符 68 | TOKEN_LEFT_BRACE, // { 69 | TOKEN_RIGHT_BRACE, // } 70 | TOKEN_LEFT_PAREN, // ( 71 | TOKEN_RIGHT_PAREN, // ) 72 | TOKEN_LEFT_BRACKET, // [ 73 | TOKEN_RIGHT_BRACKET, // ] 74 | 75 | TOKEN_COMMA, // , 76 | TOKEN_DOT, // . 77 | TOKEN_ARROW, // -> 78 | TOKEN_COLON // : 79 | }; 80 | 81 | struct Token { 82 | int token; 83 | int integer_value; 84 | char *token_string; 85 | }; 86 | 87 | // AST 节点类型 88 | enum { 89 | AST_ASSIGN = 1, // 赋值语句 90 | AST_ASSIGN_PLUS, AST_ASSIGN_MINUS, AST_ASSIGN_MULTIPLY, AST_ASSIGN_DIVIDE, AST_ASSIGN_MOD, 91 | AST_TERNARY, // 三元操作符 92 | AST_LOGIC_AND, AST_LOGIC_OR, 93 | AST_OR, AST_XOR, AST_AMPERSAND, 94 | AST_COMPARE_EQUALS, 95 | AST_COMPARE_NOT_EQUALS, 96 | AST_COMPARE_LESS_THAN, 97 | AST_COMPARE_GREATER_THAN, 98 | AST_COMPARE_LESS_EQUALS, 99 | AST_COMPARE_GREATER_EQUALS, 100 | AST_LEFT_SHIFT, AST_RIGHT_SHIFT, 101 | AST_PLUS, AST_MINUS, AST_MULTIPLY, AST_DIVIDE, AST_MOD, 102 | 103 | AST_INTEGER_LITERAL, 104 | AST_STRING_LITERAL, 105 | AST_IDENTIFIER, // 普通标识符 106 | AST_GLUE, 107 | 108 | AST_IF, 109 | AST_WHILE, 110 | AST_FUNCTION, 111 | AST_WIDEN, 112 | AST_RETURN, 113 | AST_BREAK, 114 | AST_CONTINUE, 115 | AST_SWITCH, 116 | AST_CASE, 117 | AST_DEFAULT, 118 | AST_TYPE_CASTING, // 类型强制转换 119 | 120 | AST_FUNCTION_CALL, 121 | AST_DEREFERENCE_POINTER, // 间接引用指针 122 | AST_IDENTIFIER_ADDRESS, // 指针变量地址 123 | AST_SCALE, 124 | 125 | AST_PRE_INCREASE, 126 | AST_PRE_DECREASE, 127 | AST_POST_INCREASE, 128 | AST_POST_DECREASE, 129 | AST_NEGATE, 130 | AST_INVERT, 131 | AST_LOGIC_NOT, 132 | AST_TO_BE_BOOLEAN 133 | }; 134 | 135 | // Primitive types 原始类型 136 | enum { 137 | PRIMITIVE_NONE, 138 | PRIMITIVE_VOID = 16, 139 | PRIMITIVE_CHAR = 32, 140 | PRIMITIVE_INT = 48, 141 | PRIMITIVE_LONG = 64, 142 | PRIMITIVE_STRUCT = 80, 143 | PRIMITIVE_UNION = 96 144 | }; 145 | 146 | // Structural types 结构类型 147 | enum { 148 | STRUCTURAL_VARIABLE, 149 | STRUCTURAL_FUNCTION, 150 | STRUCTURAL_ARRAY 151 | }; 152 | 153 | enum { 154 | STORAGE_CLASS_GLOBAL = 1, 155 | STORAGE_CLASS_LOCAL, 156 | STORAGE_CLASS_EXTERN, 157 | STORAGE_CLASS_STATIC, 158 | STORAGE_CLASS_FUNCTION_PARAMETER, 159 | STORAGE_CLASS_STRUCT, 160 | STORAGE_CLASS_UNION, 161 | STORAGE_CLASS_MEMBER, 162 | STORAGE_CLASS_ENUM_TYPE, 163 | STORAGE_CLASS_ENUM_VALUE, 164 | STORAGE_CLASS_TYPEDEF 165 | }; 166 | 167 | // 符号表,目前作用是支持变量 168 | // 组成单向链表 169 | // 1. 全局变量以及函数(global variable/function) 170 | // 2. 对于当前函数来说的局部变量(local variable) 171 | // 3. 对于当前函数来说的局部参数(local parameter) 172 | // 4. 定义的结构体(struct) 173 | // 5. 定义的联合体(union) 174 | // 6. 定义的枚举以及其对应的值(enum) 175 | struct SymbolTable { 176 | char *name; // 每个变量的名字 177 | int primitive_type; // 每个变量的原始类型 178 | int structural_type;// 每个变量的结构类型 179 | int storage_class; 180 | int size; // 在 symbol 中元素的个数 181 | 182 | // 对于函数,为参数的个数 183 | // 对于结构体,为结构体的 field 的个数 184 | int element_number; 185 | 186 | // 对于 STRUCTURAL_FUNCTION 来说的 end label 187 | #define symbol_table_end_label symbol_table_position 188 | 189 | // 本地变量相对于栈基指针的负向距离 190 | int symbol_table_position; 191 | 192 | int *init_value_list; // 初始化值列表 193 | struct SymbolTable *next; // 下一个 symbol table 的指针 194 | struct SymbolTable *member; // 指向第一个函数参数、第一个 struct/union/enum 的 member 成员的 symbol table 指针 195 | struct SymbolTable *composite_type; // 指向复合类型 symbol table 的指针 196 | }; 197 | 198 | struct ASTNode { 199 | // 操作符 + - * / 200 | int operation; 201 | int primitive_type; // 对应 void/char/int... 202 | int rvalue; // boolean, 是否是右值节点,1 为 true, 0 为 false 203 | struct ASTNode *left; 204 | struct ASTNode *middle; 205 | struct ASTNode *right; 206 | struct SymbolTable *symbol_table; 207 | struct SymbolTable *composite_type; // 指向复合类型 symbol table 的指针 208 | 209 | #define ast_node_integer_value ast_node_scale_size 210 | int ast_node_scale_size; 211 | }; 212 | 213 | // 如果在 generator.c 中的 interpret_ast_with_register 214 | // 函数没有 register id 返回了,就用这个标志位 215 | enum { 216 | NO_REGISTER = -1, 217 | NO_LABEL = 0 218 | }; 219 | 220 | #endif 221 | -------------------------------------------------------------------------------- /generator.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "data.h" 5 | #include "ast.h" 6 | #include "generator.h" 7 | #include "generator_core.h" 8 | #include "helper.h" 9 | 10 | // 这个 label 是为了在汇编 code 中生成类似 L1, L2 的代码用的 11 | // 目的是为了代码间的跳转 12 | // 比如 jmp L1, jmp L2 之类去执行 13 | static int label_id = 1; 14 | int generate_label() { 15 | return (label_id++); 16 | } 17 | 18 | static int interpret_if_ast_with_register( 19 | struct ASTNode *node, 20 | int loop_start_label, 21 | int loop_end_label 22 | ) { 23 | int label_start, label_end; 24 | 25 | label_start = generate_label(); 26 | if (node->right) label_end = generate_label(); 27 | 28 | // 解析 if 中的 condition 条件语句,并生成对应的汇编代码 29 | // 这个条件语句最终的执行的结果是 0,并跳转到 label_false 存在的地方 30 | // 这里可以把 label_false 这个整型数值当作一个 register_index 给到对应的寄存器做处理 31 | interpret_ast_with_register(node->left, label_start, NO_LABEL, NO_LABEL, node->operation); 32 | generate_clearable_registers(NO_REGISTER); 33 | 34 | // 解析 true 部分的 statements,并生成对应汇编代码 35 | interpret_ast_with_register(node->middle, NO_LABEL, loop_start_label, loop_end_label, node->operation); 36 | generate_clearable_registers(NO_REGISTER); 37 | 38 | // 如果有 ELSE 分支,则跳转到 label_end 39 | if (node->right) register_jump(label_end); 40 | 41 | // 开始写 label_start 定义的代码 42 | register_label(label_start); 43 | if (node->right) { 44 | interpret_ast_with_register(node->right, NO_LABEL, NO_LABEL, loop_end_label, node->operation); 45 | generate_clearable_registers(NO_REGISTER); 46 | register_label(label_end); 47 | } 48 | 49 | return (NO_REGISTER); 50 | } 51 | 52 | /** 53 | * 形成类似 54 | * Lstart: 55 | * evaluate condition 56 | jump to Lend if condition false 57 | statements 58 | jump to Lstart 59 | Lend: 60 | 这样的效果 61 | */ 62 | static int interpret_while_ast_with_register(struct ASTNode *node) { 63 | int label_start, label_end; 64 | 65 | label_start = generate_label(); 66 | label_end = generate_label(); 67 | 68 | // 先生成一个 Lstart 69 | register_label(label_start); 70 | 71 | // 解析 while 中的 condition 条件语句,并生成对应的汇编代码 72 | // evaluate condition 73 | // jump to Lend if condition false 74 | interpret_ast_with_register(node->left, label_end, label_start, label_end, node->operation); 75 | generate_clearable_registers(NO_REGISTER); 76 | 77 | // 解析 while 下面的复合语句 78 | // statements 79 | interpret_ast_with_register(node->right, NO_LABEL, label_start, label_end, node->operation); 80 | generate_clearable_registers(NO_REGISTER); 81 | 82 | // jump to Lstart 83 | register_jump(label_start); 84 | 85 | // 最后生成一个 Lend 86 | register_label(label_end); 87 | 88 | return (NO_REGISTER); 89 | } 90 | 91 | static int interpret_function_call_with_register(struct ASTNode *node) { 92 | struct ASTNode *glue_node = node->left; 93 | int register_index; 94 | int function_argument_number = 0; 95 | 96 | spill_all_register(); 97 | 98 | // 处理如下的 tree 99 | // AST_FUNCCALL 100 | // / 101 | // AST_GLUE 102 | // / \ 103 | // AST_GLUE expr4(4) 104 | // / \ 105 | // AST_GLUE expr3(3) 106 | // / \ 107 | // AST_GLUE expr2(2) 108 | // / \ 109 | // NULL expr1(1) 110 | while(glue_node) { 111 | // 先生成相关表达式的汇编代码 112 | register_index = interpret_ast_with_register(glue_node->right, NO_LABEL, NO_LABEL, NO_LABEL, glue_node->operation); 113 | // 将其复制到第 n 个函数参数中 114 | register_copy_argument(register_index, glue_node->ast_node_scale_size); 115 | // 保留第一个参数 116 | if (!function_argument_number) function_argument_number = glue_node->ast_node_scale_size; 117 | glue_node = glue_node->left; 118 | } 119 | 120 | return (register_function_call(node->symbol_table, function_argument_number)); 121 | } 122 | 123 | static int interpret_switch_ast_with_register(struct ASTNode *node) { 124 | int *case_value, *case_label, case_count = 0; 125 | int label_jump_start, label_end, label_default = 0; 126 | int i, register_index; 127 | struct ASTNode *c; 128 | 129 | // 为 case value 和与之对应的 case label 创建数组 130 | // 注意这里的 node 的 integer_value 存的是构建 case tree 时的 case_count 131 | // 也就是 case 的个数 132 | case_value = (int *) malloc((node->ast_node_integer_value + 1) * sizeof(int)); 133 | case_label = (int *) malloc((node->ast_node_integer_value + 1) * sizeof(int)); 134 | 135 | label_jump_start = generate_label(); 136 | label_end = generate_label(); 137 | label_default = label_end; 138 | 139 | // 先生成 switch 条件语句的汇编代码 140 | register_index = interpret_ast_with_register(node->left, NO_LABEL, NO_LABEL, NO_LABEL, 0); 141 | register_jump(label_jump_start); 142 | generate_clearable_registers(register_index); 143 | 144 | // 遍历 tree 的右节点,为每个 case 生成汇编代码 145 | for(i = 0, c = node->right; c; i++, c = c->right) { 146 | // 为每个 case 创建 label 147 | case_label[i] = generate_label(); 148 | case_value[i] = c->ast_node_integer_value; 149 | register_label(case_label[i]); 150 | if (c->operation == AST_DEFAULT) 151 | label_default = case_label[i]; 152 | else 153 | case_count++; 154 | 155 | // 为每个 case 生成汇编代码 156 | if (c->left) 157 | interpret_ast_with_register(c->left, NO_LABEL, NO_LABEL, label_end, 0); 158 | generate_clearable_registers(NO_REGISTER); 159 | } 160 | 161 | // 确保最后一个 case 跳过 switch 表 162 | register_jump(label_end); 163 | 164 | // 生成 switch 表和 end label 165 | register_switch(register_index, case_count, label_jump_start, case_label, case_value, label_default); 166 | register_label(label_end); 167 | return (NO_REGISTER); 168 | } 169 | 170 | // 生成三元运算符语句的汇编代码 171 | static int interpret_ternary_ast_with_register(struct ASTNode *node) { 172 | int label_start, label_end, register_index, expression_register_index; 173 | 174 | label_start = generate_label(); 175 | label_end = generate_label(); 176 | 177 | // 先产生条件语句的汇编,这个条件语句后面跟着是跳到 false 情况的 178 | interpret_ast_with_register( 179 | node->left, 180 | label_start, 181 | NO_LABEL, 182 | NO_LABEL, 183 | node->operation); 184 | 185 | // 弄一个寄存器来保存俩表达式的结果 186 | register_index = allocate_register(); 187 | 188 | // 生成 true 表达式的汇编以及 false label 189 | // 把结果放入上述的寄存器中 190 | expression_register_index = interpret_ast_with_register( 191 | node->middle, 192 | NO_LABEL, 193 | NO_LABEL, 194 | NO_LABEL, 195 | node->operation); 196 | register_move(expression_register_index, register_index); 197 | register_clear_register(expression_register_index); 198 | register_jump(label_end); 199 | register_label(label_start); 200 | 201 | // 生成 false 表达式的汇编以及 end label 202 | // 把结果放入上述的寄存器中 203 | expression_register_index = interpret_ast_with_register( 204 | node->right, 205 | NO_LABEL, 206 | NO_LABEL, 207 | NO_LABEL, 208 | node->operation); 209 | register_move(expression_register_index, register_index); 210 | register_clear_register(expression_register_index); 211 | register_label(label_end); 212 | 213 | return (register_index); 214 | } 215 | 216 | static int interpret_logic_and_or_ast_with_register(struct ASTNode *node) { 217 | int label_start = generate_label(); 218 | int label_end = generate_label(); 219 | int register_index ; 220 | 221 | register_index = interpret_ast_with_register( 222 | node->left, 223 | NO_LABEL, 224 | NO_LABEL, 225 | NO_LABEL, 226 | 0); 227 | register_to_be_boolean(register_index, node->operation, label_start); 228 | generate_clearable_registers(NO_REGISTER); 229 | 230 | register_index = interpret_ast_with_register( 231 | node->right, 232 | NO_LABEL, 233 | NO_LABEL, 234 | NO_LABEL, 235 | 0); 236 | register_to_be_boolean(register_index, node->operation, label_start); 237 | generate_clearable_registers(register_index); 238 | 239 | if (node->operation == AST_LOGIC_AND) { 240 | register_load_boolean(register_index, 1); 241 | register_jump(label_end); 242 | register_label(label_start); 243 | register_load_boolean(register_index, 0); 244 | } else { 245 | register_load_boolean(register_index, 0); 246 | register_jump(label_end); 247 | register_label(label_start); 248 | register_load_boolean(register_index, 1); 249 | } 250 | 251 | register_label(label_end); 252 | return (register_index); 253 | } 254 | 255 | /** 256 | * 这里主要将 ast 中的代码取出来,然后用汇编的方式进行值的加减乘除 257 | * 这里加减乘除后返回的是寄存器的标识 258 | * 259 | */ 260 | int interpret_ast_with_register( 261 | struct ASTNode *node, 262 | int if_label, 263 | int loop_start_label, 264 | int loop_end_label, 265 | int parent_ast_operation 266 | ) { 267 | int left_register = NO_REGISTER, right_register = NO_REGISTER; 268 | 269 | if (!node) return (NO_REGISTER); 270 | 271 | /** 272 | * 对于两种 ast 做特殊处理 273 | * 1. if 条件语句 274 | * IF 275 | / | \_______ 276 | / | \ 277 | cond (true stmt1) (false/end stmt2) 278 | 279 | 2. glue 复合语句(这个结构是为了把各种语句粘合起来) 280 | AST_GLUE 281 | / \ 282 | AST_GLUE stmt4 283 | / \ 284 | AST_GLUE stmt3 285 | / \ 286 | stmt1 stmt2 287 | 288 | 3. while 语句 289 | while 290 | / | \ 291 | / | \ 292 | cond NULL stmt 293 | */ 294 | switch (node->operation) { 295 | case AST_IF: 296 | return (interpret_if_ast_with_register(node, loop_start_label, loop_end_label)); 297 | case AST_GLUE: 298 | if (node->left) 299 | interpret_ast_with_register(node->left, if_label, loop_start_label, loop_end_label, node->operation); 300 | generate_clearable_registers(NO_REGISTER); 301 | if (node->right) 302 | interpret_ast_with_register(node->right, if_label, loop_start_label, loop_end_label, node->operation); 303 | generate_clearable_registers(NO_REGISTER); 304 | return (NO_REGISTER); 305 | case AST_WHILE: 306 | return (interpret_while_ast_with_register(node)); 307 | case AST_FUNCTION_CALL: 308 | return (interpret_function_call_with_register(node)); 309 | case AST_FUNCTION: 310 | register_function_preamble(node->symbol_table); 311 | interpret_ast_with_register(node->left, NO_LABEL, NO_LABEL, NO_LABEL, node->operation); 312 | register_function_postamble(node->symbol_table); 313 | return (NO_REGISTER); 314 | case AST_SWITCH: 315 | return (interpret_switch_ast_with_register(node)); 316 | case AST_TERNARY: 317 | return (interpret_ternary_ast_with_register(node)); 318 | case AST_LOGIC_AND: 319 | case AST_LOGIC_OR: 320 | return (interpret_logic_and_or_ast_with_register(node)); 321 | } 322 | 323 | if (node->left) 324 | left_register = interpret_ast_with_register(node->left, NO_LABEL, NO_LABEL, NO_LABEL, node->operation); 325 | if (node->right) 326 | right_register = interpret_ast_with_register(node->right, NO_LABEL, NO_LABEL, NO_LABEL, node->operation); 327 | 328 | switch (node->operation) { 329 | case AST_PLUS: 330 | return (register_plus(left_register, right_register)); 331 | case AST_MINUS: 332 | return (register_minus(left_register, right_register)); 333 | case AST_MULTIPLY: 334 | return (register_multiply(left_register, right_register)); 335 | case AST_DIVIDE: 336 | case AST_MOD: 337 | return (register_divide_and_mod(left_register, right_register, node->operation)); 338 | 339 | case AST_COMPARE_EQUALS: 340 | case AST_COMPARE_NOT_EQUALS: 341 | case AST_COMPARE_LESS_THAN: 342 | case AST_COMPARE_GREATER_THAN: 343 | case AST_COMPARE_LESS_EQUALS: 344 | case AST_COMPARE_GREATER_EQUALS: 345 | if (parent_ast_operation == AST_IF || 346 | parent_ast_operation == AST_WHILE || 347 | parent_ast_operation == AST_TERNARY) 348 | return (register_compare_and_jump( node->operation, left_register, right_register, if_label, node->primitive_type)); 349 | return (register_compare_and_set(node->operation, left_register, right_register, node->primitive_type)); 350 | case AST_RETURN: 351 | register_function_return(left_register, current_function_symbol_id); 352 | return (NO_REGISTER); 353 | 354 | case AST_INTEGER_LITERAL: 355 | return (register_load_interger_literal(node->ast_node_integer_value, node->primitive_type)); 356 | case AST_IDENTIFIER: 357 | // 类似于 * y 这种情况 358 | // | | 359 | // / \ 360 | // parent_ast_operation node 361 | if (node->rvalue || 362 | parent_ast_operation == AST_DEREFERENCE_POINTER) 363 | return (register_load_variable(node->symbol_table, node->operation)); 364 | return (NO_REGISTER); 365 | // a += b + c 366 | // 会被解析成如下 367 | // AST_PLUS 368 | // / \ 369 | // AST_IDENT AST_ADD 370 | // rval a / \ 371 | // AST_IDENT AST_IDENT 372 | // rval b rval c 373 | case AST_ASSIGN_PLUS: 374 | case AST_ASSIGN_MINUS: 375 | case AST_ASSIGN_MULTIPLY: 376 | case AST_ASSIGN_DIVIDE: 377 | case AST_ASSIGN_MOD: 378 | case AST_ASSIGN: 379 | // 处理前面 += -= *= /= %= 380 | switch (node->operation) { 381 | case AST_ASSIGN_PLUS: 382 | left_register = register_plus(left_register, right_register); 383 | node->right = node->left; 384 | break; 385 | case AST_ASSIGN_MINUS: 386 | left_register = register_minus(left_register, right_register); 387 | node->right = node->left; 388 | break; 389 | case AST_ASSIGN_MULTIPLY: 390 | left_register = register_multiply(left_register, right_register); 391 | node->right = node->left; 392 | break; 393 | case AST_ASSIGN_DIVIDE: 394 | left_register = register_divide_and_mod(left_register, right_register, AST_DIVIDE); 395 | node->right = node->left; 396 | break; 397 | case AST_ASSIGN_MOD: 398 | left_register = register_divide_and_mod(left_register, right_register, AST_MOD); 399 | node->right = node->left; 400 | break; 401 | } 402 | 403 | // 处理 = 404 | // 是赋值给一个变量还是给一个指针赋值? 405 | // x = y 406 | // *x = y 407 | // 在 parser 中 left 和 right 做了交换,所以这里要对 right 的 operation 做判断 408 | switch (node->right->operation) { 409 | case AST_IDENTIFIER: 410 | if (node->right->symbol_table->storage_class == STORAGE_CLASS_GLOBAL || 411 | node->right->symbol_table->storage_class == STORAGE_CLASS_EXTERN || 412 | node->right->symbol_table->storage_class == STORAGE_CLASS_STATIC) 413 | return (register_store_value_2_variable(left_register, node->right->symbol_table)); 414 | return (register_store_local_value_2_variable(left_register, node->right->symbol_table)); 415 | case AST_DEREFERENCE_POINTER: 416 | return (register_store_dereference_pointer(left_register, right_register, node->right->primitive_type)); 417 | default: 418 | error_with_digital("Can't AST_ASSIGN in interpret_ast_with_register, operation", node->operation); 419 | } 420 | 421 | // & 422 | case AST_IDENTIFIER_ADDRESS: 423 | // 这里也有可能是 struct/union 成员的访问 424 | if (node->symbol_table) 425 | return (register_load_identifier_address(node->symbol_table)); 426 | return (left_register); 427 | // * 428 | case AST_DEREFERENCE_POINTER: 429 | if (node->rvalue) 430 | return (register_dereference_pointer(left_register, node->left->primitive_type)); 431 | // 返回上一个回调交给 AST_ASSIGN 处理 432 | return (left_register); 433 | 434 | // 对 char/int/long 类型转换的处理 435 | case AST_WIDEN: 436 | return (register_widen(left_register, node->left->primitive_type, node->primitive_type)); 437 | // 对 char*/int*/long* 指针类型转换的处理 438 | case AST_SCALE: 439 | switch (node->ast_node_scale_size) { 440 | case 2: return (register_shift_left_by_constant(left_register, 1)); // 左移 1 位 441 | case 4: return (register_shift_left_by_constant(left_register, 2)); // 左移 2 位 442 | case 8: return (register_shift_left_by_constant(left_register, 3)); // 左移 3 位 443 | default: 444 | right_register = (register_load_interger_literal(node->ast_node_scale_size, PRIMITIVE_INT)); 445 | return (register_multiply(left_register, right_register)); 446 | } 447 | 448 | // 处理 string 449 | case AST_STRING_LITERAL: 450 | return (register_load_global_string(node->ast_node_integer_value)); 451 | 452 | case AST_AMPERSAND: 453 | return (register_and(left_register, right_register)); 454 | case AST_OR: 455 | return (register_or(left_register, right_register)); 456 | case AST_XOR: 457 | return (register_xor(left_register, right_register)); 458 | case AST_LEFT_SHIFT: 459 | return (register_shift_left(left_register, right_register)); 460 | case AST_RIGHT_SHIFT: 461 | return (register_shift_right(left_register, right_register)); 462 | case AST_POST_INCREASE: 463 | case AST_POST_DECREASE: 464 | return (register_load_variable(node->symbol_table, node->operation)); 465 | case AST_PRE_INCREASE: 466 | case AST_PRE_DECREASE: 467 | return (register_load_variable(node->left->symbol_table, node->operation)); 468 | case AST_NEGATE: 469 | return (register_negate(left_register)); 470 | case AST_INVERT: 471 | return (register_invert(left_register)); 472 | case AST_LOGIC_NOT: 473 | return (register_logic_not(left_register)); 474 | case AST_TO_BE_BOOLEAN: 475 | return (register_to_be_boolean(left_register, parent_ast_operation, if_label)); 476 | case AST_BREAK: 477 | register_jump(loop_end_label); 478 | return (NO_REGISTER); 479 | case AST_CONTINUE: 480 | register_jump(loop_start_label); 481 | return (NO_REGISTER); 482 | case AST_TYPE_CASTING: 483 | return (left_register); 484 | 485 | default: 486 | error_with_digital("Unknown AST operator", node->operation); 487 | } 488 | 489 | return (NO_REGISTER); 490 | } 491 | 492 | void generate_global_symbol(struct SymbolTable *t) { 493 | register_generate_global_symbol(t); 494 | } 495 | 496 | void generate_preamble_code() { 497 | register_preamble(); 498 | } 499 | 500 | void generate_postamble_code() { 501 | register_postamble(); 502 | } 503 | 504 | void generate_clearable_registers(int keep_register_index) { 505 | clear_all_registers(keep_register_index); 506 | } 507 | 508 | int generate_global_string_code(char *string_value, int is_append_string) { 509 | int label = generate_label(); 510 | register_generate_global_string(label, string_value, is_append_string); 511 | return (label); 512 | } 513 | 514 | void generate_global_string_code_end() { 515 | register_generate_global_string_end(); 516 | } 517 | 518 | void generate_reset_local_variables() { 519 | register_reset_local_variables(); 520 | } 521 | 522 | int generate_get_primitive_type_size(int primitive_type) { 523 | return (register_get_primitive_type_size(primitive_type)); 524 | } 525 | 526 | int generate_align(int primitive_type, int offset, int direction) { 527 | return (register_align(primitive_type, offset, direction)); 528 | } 529 | -------------------------------------------------------------------------------- /generator.h: -------------------------------------------------------------------------------- 1 | #ifndef __GENERATOR_H__ 2 | #define __GENERATOR_H__ 3 | 4 | int generate_label(); 5 | int interpret_ast_with_register( 6 | struct ASTNode *node, 7 | int if_label, 8 | int loop_start_label, 9 | int loop_end_label, 10 | int parent_ast_operation 11 | ); 12 | void generate_preamble_code(); 13 | void generate_postamble_code(); 14 | void generate_clearable_registers(int keep_register_index); 15 | int generate_global_string_code(char *string_value, int is_append_string); 16 | void generate_global_string_code_end(); 17 | void generate_global_symbol(struct SymbolTable *t); 18 | void generate_reset_local_variables(); 19 | int generate_get_primitive_type_size(int primitive_type); 20 | int generate_align(int primitive_type, int offset, int direction); 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /generator_core.h: -------------------------------------------------------------------------------- 1 | #ifndef __GENERATOR_CORE_H__ 2 | #define __GENERATOR_CORE_H__ 3 | 4 | 5 | void clear_all_registers(int keep_register_index); 6 | int allocate_register(); 7 | void register_clear_register(int register_index); 8 | void spill_all_register(); 9 | 10 | void register_preamble(); 11 | void register_postamble(); 12 | 13 | int register_load_interger_literal(int value, int primitive_type); 14 | int register_load_variable(struct SymbolTable *t, int operation); 15 | int register_plus(int left_register, int right_register); 16 | int register_minus(int left_register, int right_register); 17 | int register_multiply(int left_register, int right_register); 18 | int register_divide_and_mod( 19 | int left_register, 20 | int right_register, 21 | int operation 22 | ); 23 | 24 | int register_store_value_2_variable(int register_index, struct SymbolTable *t); 25 | int register_store_local_value_2_variable(int register_index, struct SymbolTable *t); 26 | void register_generate_global_symbol(struct SymbolTable *t); 27 | void register_generate_global_string( 28 | int label, 29 | char *string_value, 30 | int is_append_string 31 | ); 32 | void register_generate_global_string_end(); 33 | 34 | int register_compare_and_set( 35 | int ast_operation, 36 | int left_register, 37 | int right_register, 38 | int primitive_type 39 | ); 40 | int register_compare_and_jump( 41 | int ast_operation, 42 | int left_register, 43 | int right_register, 44 | int label, 45 | int primitive_type 46 | ); 47 | 48 | void register_label(int label); 49 | void register_jump(int label); 50 | 51 | 52 | void register_function_preamble(struct SymbolTable *t); 53 | void register_function_postamble(struct SymbolTable *t); 54 | 55 | int register_widen( 56 | int register_index, 57 | int old_primitive_type, 58 | int new_primitive_type); 59 | 60 | int register_get_primitive_type_size(int primitive_type); 61 | int register_function_call(struct SymbolTable *t, int argument_number); 62 | void register_function_return(int register_index, struct SymbolTable *t); 63 | 64 | int register_load_identifier_address(struct SymbolTable *t); 65 | int register_dereference_pointer(int register_index, int primitive_type); 66 | int register_store_dereference_pointer(int left_register, int right_register, int primitive_type); 67 | int register_shift_left_by_constant(int register_index, int value); 68 | 69 | int register_load_global_string(int label); 70 | 71 | int register_and(int left_register, int right_register); 72 | int register_or(int left_register, int right_register); 73 | int register_xor(int left_register, int right_register); 74 | int register_negate(int register_index); 75 | int register_invert(int register_index); 76 | int register_shift_left(int left_register, int right_register); 77 | int register_shift_right(int left_register, int right_register); 78 | int register_logic_not(int register_index); 79 | 80 | void register_load_boolean(int register_index, int value); 81 | int register_to_be_boolean(int register_index, int operation, int label); 82 | 83 | void register_reset_local_variables(); 84 | 85 | void register_text_section_flag(); 86 | void register_data_section_flag(); 87 | 88 | void register_copy_argument(int register_index, int argument_position); 89 | int register_align(int primitive_type, int offset, int direction); 90 | void register_switch( 91 | int register_index, 92 | int case_count, 93 | int label_jump_start, 94 | int *case_label, 95 | int *case_value, 96 | int label_default 97 | ); 98 | 99 | void register_move(int left_register, int right_register); 100 | 101 | 102 | #endif 103 | -------------------------------------------------------------------------------- /generator_core_arm.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "data.h" 5 | #include "definations.h" 6 | #include "helper.h" 7 | #include "generator_core.h" 8 | 9 | // 把大 int 类型数值放入内存中,用一个数组保存起来 10 | // postamble 会用到 11 | #define MAX_INTEGER_NUMBER 1024 12 | 13 | int integer_list[MAX_INTEGER_NUMBER] = { 0 }; 14 | static int integer_list_index = 0; 15 | 16 | static int free_registers[4] = { 1 }; 17 | static char *register_list[4] = { "r4", "r5", "r6", "r7" }; 18 | 19 | static char *compare_list[] = 20 | { "moveq", "movne", "movlt", "movgt", "movle", "movge" }; 21 | 22 | static char *inverted_compare_list[] = 23 | { "movne", "moveq", "movge", "movle", "movgt", "movlt" }; 24 | 25 | static char *inverted_branch_list[] = 26 | { "bne", "beq", "bge", "ble", "bgt", "blt" }; 27 | 28 | // none/void/char/int/long 29 | static int primitive_size[] = { 0, 0, 1, 4, 4, 4, 4, 4 }; 30 | 31 | void clear_all_registers(NO_REGISTER) { 32 | free_registers[0] = free_registers[1] = free_registers[2] = free_registers[3] = 1; 33 | } 34 | 35 | /** 36 | * 分配一个寄存器,返回这个寄存器对应的下标 37 | * 如果已经没有寄存器分配,则抛出异常 38 | */ 39 | static int allocate_register() { 40 | for (int i = 0; i < 4; i++) { 41 | if (free_registers[i]) { 42 | free_registers[i] = 0; 43 | return (i); 44 | } 45 | } 46 | 47 | error("Out of registers"); 48 | return (NO_REGISTER); 49 | } 50 | 51 | /** 52 | * 清空某个寄存器 53 | */ 54 | static void clear_register(int index) { 55 | if (free_registers[index]) 56 | error_with_digital("Error trying to clear registers", index); 57 | free_registers[index] = 1; 58 | } 59 | 60 | /** 61 | * 设置大 int 型数值在 label 下的 offset 62 | */ 63 | static void set_large_integer_offset(int value) { 64 | int offset = -1; 65 | for (int i = 0; i < integer_list_index; i++) { 66 | if (value == integer_list[i]) { 67 | offset = i * 4; 68 | break; 69 | } 70 | } 71 | // 如果不在列表中,则直接加入 72 | if (offset < 0) { 73 | offset = integer_list_index * 4; 74 | if (integer_list_index == MAX_INTEGER_NUMBER) 75 | error("Out of max integer number in set_large_integer_offset()"); 76 | integer_list[integer_list_index++] = value; 77 | } 78 | // 用 offset 写入 r3 这个寄存器 79 | fprintf(output_file, "\tldr\tr3, .L3+%d\n", offset); 80 | } 81 | 82 | /** 83 | * 设置变量在 label 下的 offset 84 | */ 85 | static void set_variable_offset(int symbol_table_index) { 86 | int offset = 0; 87 | for (int i = 0; i < symbol_table_index; i++) { 88 | if (symbol_table[i].structural_type == STRUCTURAL_VARIABLE) 89 | offset += 4; 90 | } 91 | // 用 offset 写入 r3 这个寄存器 92 | fprintf(output_file, "\tldr\tr3, .L2+%d\n", offset); 93 | } 94 | 95 | /** 96 | * 汇编前置代码,写入到 output_file 中 97 | */ 98 | void register_preamble() { 99 | clear_all_registers(NO_REGISTER); 100 | fputs("\t.text\n", output_file); 101 | } 102 | 103 | /** 104 | * 汇编后置代码,写入到 output_file 中 105 | */ 106 | void register_postamble() { 107 | fprintf(output_file, ".L2:\n"); 108 | for (int i = 0; i < global_symbol_table_index; i++) { 109 | if (symbol_table[i].structural_type == STRUCTURAL_VARIABLE) 110 | fprintf(output_file, "\t.word %s\n", symbol_table[i].name); 111 | } 112 | fprintf(output_file, ".L3:\n"); 113 | for (int i = 0; i < integer_list_index; i++) { 114 | fprintf(output_file, "\t.word %d\n", integer_list[i]); 115 | } 116 | } 117 | 118 | /** 119 | * 把 value 放入某个寄存器中,并返回该寄存器的下标 120 | */ 121 | int register_load_interger_literal(int value, int primitive_type) { 122 | int register_index = allocate_register(); 123 | if (value <= 1000) 124 | fprintf(output_file, "\tmov\t%s, #%d\n", register_list[register_index], value); 125 | else { 126 | set_large_integer_offset(value); 127 | fprintf(output_file, "\tldr\t%s, [r3]\n", register_list[register_index]); 128 | } 129 | return (register_index); 130 | } 131 | 132 | /** 133 | * 两个寄存器相加,并将其放入其中一个寄存器中 134 | */ 135 | int register_plus(int left_register, int right_register) { 136 | fprintf(output_file, 137 | "\tadd\t%s, %s, %s\n", 138 | register_list[right_register], 139 | register_list[left_register], 140 | register_list[right_register]); 141 | clear_register(left_register); 142 | return (right_register); 143 | } 144 | 145 | /** 146 | * 两个寄存器相减,并将其放入其中一个寄存器中 147 | */ 148 | int register_minus(int left_register, int right_register) { 149 | fprintf(output_file, 150 | "\tsub\t%s, %s, %s\n", 151 | register_list[left_register], 152 | register_list[left_register], 153 | register_list[right_register]); 154 | clear_register(right_register); 155 | return (left_register); 156 | } 157 | 158 | /** 159 | * 两个寄存器相乘,并将其放入其中一个寄存器中 160 | */ 161 | int register_multiply(int left_register, int right_register) { 162 | fprintf(output_file, 163 | "\tmul\t%s, %s, %s\n", 164 | register_list[right_register], 165 | register_list[left_register], 166 | register_list[right_register]); 167 | clear_register(left_register); 168 | return (right_register); 169 | } 170 | 171 | /** 172 | * 两个寄存器相除,这里处理比较麻烦 173 | * 先把值放入 rax 寄存器 174 | * 进行除法运算后,再从 rax 寄存器中把结果拿出来,放入 left_register 175 | */ 176 | int register_divide(int left_register, int right_register) { 177 | fprintf(output_file, "\tmov\tr0, %s\n", register_list[left_register]); 178 | fprintf(output_file, "\tmov\tr1, %s\n", register_list[right_register]); 179 | fprintf(output_file, "\tbl\t__aeabi_idiv\n"); 180 | fprintf(output_file, "\tmov\t%s, r0\n", register_list[left_register]); 181 | clear_register(right_register); 182 | return (left_register); 183 | } 184 | 185 | /** 186 | * 打印指定的寄存器 187 | */ 188 | void register_print(int register_index) { 189 | fprintf(output_file, "\tmov\tr0, %s\n", register_list[register_index]); 190 | fprintf(output_file, "\tbl\tregister_print\n"); 191 | fprintf(output_file, "\tnop\n"); 192 | clear_register(register_index); 193 | } 194 | 195 | /** 196 | * 将一个变量的值保存到寄存器中 197 | */ 198 | int register_load_value_from_variable(int symbol_table_index) { 199 | int register_index = allocate_register(); 200 | set_variable_offset(symbol_table_index); 201 | fprintf(output_file, "\tldr\t%s, [r3]\n", register_list[register_index]); 202 | return (register_index); 203 | } 204 | 205 | /** 206 | * 将寄存器中的值保存到一个变量中 207 | */ 208 | int register_store_value_2_variable(int register_index, int symbol_table_index) { 209 | struct SymbolTable t = symbol_table[symbol_table_index]; 210 | set_variable_offset(symbol_table_index); 211 | switch (t.primitive_type) { 212 | case PRIMITIVE_CHAR: 213 | fprintf(output_file, "\tstrb\t%s, [r3]\n", 214 | register_list[register_index]); 215 | break; 216 | case PRIMITIVE_INT: 217 | case PRIMITIVE_LONG: 218 | case PRIMITIVE_CHAR_POINTER: 219 | case PRIMITIVE_INT_POINTER: 220 | case PRIMITIVE_LONG_POINTER: 221 | fprintf(output_file, "\tstr\t%s, [r3]\n", 222 | register_list[register_index]); 223 | break; 224 | default: 225 | error_with_digital("Bad type in register_store_value_2_variable:", t.primitive_type); 226 | } 227 | return register_index; 228 | } 229 | 230 | /** 231 | * 创建全局变量 232 | */ 233 | void register_generate_global_symbol(int symbol_table_index) { 234 | struct SymbolTable t = symbol_table[symbol_table_index]; 235 | int primitive_type_size 236 | = register_get_primitive_type_size(t.primitive_type); 237 | fprintf(output_file, "\t.data\n" "\t.globl\t%s\n", t.name); 238 | fprintf(output_file, "%s:", t.name); 239 | for (int i = 0; i < t.size; i++) { 240 | switch(primitive_type_size) { 241 | case 1: fprintf(output_file, "\t.byte\t0\n"); break; 242 | case 4: fprintf(output_file, "\t.long\t0\n"); break; 243 | default: fatald("Unknown typesize in register_generate_global_symbol: ", primitive_type_size); 244 | } 245 | } 246 | } 247 | 248 | /** 249 | * 创建全局字符串 250 | */ 251 | void register_generate_global_string(int label, char *string_value) { 252 | register_label(label); 253 | for (char *p = string_value; *p; p++) { 254 | fprintf(output_file, "\t.byte\t%d\n", *p); 255 | } 256 | fprintf(output_file, "\t.byte\t0\n"); 257 | } 258 | 259 | /** 260 | * 比较两寄存器,如果是 true 则进行 set 261 | */ 262 | int register_compare_and_set( 263 | int ast_operation, 264 | int register_left, 265 | int register_right 266 | ) { 267 | if (ast_operation < AST_COMPARE_EQUALS 268 | || ast_operation > AST_COMPARE_GREATER_EQUALS) 269 | error("Bad ast operaion in register_compare_and_set function"); 270 | 271 | fprintf(output_file, "\tcmp\t%s, %s\n", 272 | register_list[register_right], 273 | register_list[register_left]); 274 | 275 | fprintf(output_file, "\t%s\t%s, #1\n", 276 | compare_list[ast_operation - AST_COMPARE_EQUALS], 277 | register_list[register_right]); 278 | 279 | fprintf(output_file, "\t%s\t%s, #0\n", 280 | inverted_compare_list[ast_operation - AST_COMPARE_EQUALS], 281 | register_list[register_right]); 282 | 283 | fprintf(output_file, "\tuxtb\t%s, %s\n", 284 | register_list[register_right], 285 | register_list[register_right]); 286 | 287 | clear_register(register_left); 288 | return register_right; 289 | } 290 | 291 | /** 292 | * 比较俩寄存器,如果是 false 则进行 jmp 293 | */ 294 | int register_compare_and_jump( 295 | int ast_operation, 296 | int register_left, 297 | int register_right, 298 | int label 299 | ) { 300 | if (ast_operation < AST_COMPARE_EQUALS 301 | || ast_operation > AST_COMPARE_GREATER_EQUALS) 302 | error("Bad ast operaion in register_compare_and_jump function"); 303 | 304 | fprintf(output_file, "\tcmp\t%s, %s\n", 305 | register_list[register_left], 306 | register_list[register_right]); 307 | fprintf(output_file, "\t%s\tL%d\n", 308 | inverted_branch_list[ast_operation - AST_COMPARE_EQUALS], 309 | label); 310 | 311 | clear_all_registers(NO_REGISTER); 312 | return NO_REGISTER; 313 | } 314 | 315 | /** 316 | * 创建 label 317 | */ 318 | void register_label(int label) { 319 | fprintf(output_file, "L%d:\n", label); 320 | } 321 | 322 | /** 323 | * 创建一个跳到 label 的 jmp 324 | */ 325 | void register_jump(int label) { 326 | fprintf(output_file, "\tb\tL%d\n", label); 327 | } 328 | 329 | /** 330 | * 解析函数定义的前置汇编代码 331 | */ 332 | void register_function_preamble(int symbol_table_index) { 333 | char *name = symbol_table[symbol_table_index].name; 334 | fprintf(output_file, 335 | "\t.text\n" 336 | "\t.globl\t%s\n" 337 | "\t.type\t%s, %%function\n" 338 | "%s:\n" "\tpush\t{fp, lr}\n" 339 | "\tadd\tfp, sp, #4\n" 340 | "\tsub\tsp, sp, #8\n" 341 | "\tstr\tr0, [fp, #-8]\n", 342 | name, name, name); 343 | } 344 | 345 | /** 346 | * 解析函数定义的后置汇编代码 347 | */ 348 | void register_function_postamble(int symbol_table_index) { 349 | struct SymbolTable t = symbol_table[symbol_table_index]; 350 | register_label(t.symbol_table_end_label); 351 | fputs("\tsub\tsp, fp, #4\n" 352 | "\tpop\t{fp, pc}\n" 353 | "\t.align\t2\n" 354 | , output_file); 355 | } 356 | 357 | /** 358 | * 从 old_primitive_type 转向 new_primitive_type 时扩大在寄存器中的值 359 | * 返回这个新的值 360 | */ 361 | int register_widen( 362 | int register_index, 363 | int old_primitive_type, 364 | int new_primitive_type) { 365 | return register_index; 366 | } 367 | 368 | /** 369 | * 给定一个 primitive type,返回其对应的字节数 370 | */ 371 | int register_get_primitive_type_size(int primitive_type) { 372 | if (primitive_type < PRIMITIVE_NONE || primitive_type > PRIMITIVE_LONG_POINTER) 373 | error("Bad type in register_get_primitive_type_size()"); 374 | return primitive_size[primitive_type]; 375 | } 376 | 377 | /** 378 | * 处理函数调用 function_call 379 | */ 380 | int register_function_call(int register_index, int symbol_table_index) { 381 | fprintf(output_file, "\tmov\tr0, %s\n", register_list[register_index]); 382 | fprintf(output_file, "\tbl\t%s\n", symbol_table[symbol_table_index].name); 383 | fprintf(output_file, "\tmov\t%s, r0\n", register_list[register_index]); 384 | return register_index; 385 | } 386 | 387 | /** 388 | * 处理函数返回 function_return 389 | */ 390 | void register_function_return(int register_index, int symbol_table_index) { 391 | struct SymbolTable t = symbol_table[symbol_table_index]; 392 | char *r = register_list[register_index]; 393 | fprintf(output_file, "\tmov\tr0, %s\n", r); 394 | register_jump(t.symbol_table_end_label); 395 | } 396 | 397 | int register_load_identifier_address(int symbol_table_index) { 398 | int register_index = allocate_register(); 399 | set_variable_offset(symbol_table_index); 400 | fprintf(output_file, "\tmov\t%s, r3\n", register_list[register_index]); 401 | return register_index; 402 | } 403 | 404 | int register_dereference_pointer(int register_index, int primitive_type) { 405 | char *r = register_list[register_index]; 406 | switch (primitive_type) { 407 | case PRIMITIVE_CHAR_POINTER: 408 | fprintf(output_file, "\tldrb\t%s, [%s]\n", r, r); 409 | break; 410 | case PRIMITIVE_INT_POINTER: 411 | case PRIMITIVE_LONG_POINTER: 412 | fprintf(output_file, "\tldr\t%s, [%s]\n", r, r); 413 | break; 414 | default: 415 | error_with_digital("Can't register_dereference_pointer on type:", primitive_type); 416 | } 417 | return register_index; 418 | } 419 | 420 | int register_store_dereference_pointer(int left_register, int right_register, int primitive_type) { 421 | char *lr = register_list[left_register]; 422 | char *rr = register_list[right_register]; 423 | switch (primitive_type) { 424 | case PRIMITIVE_CHAR: 425 | fprintf(output_file, "\tstrb\t%s, [%s]\n", lr, rr); 426 | break; 427 | case PRIMITIVE_INT: 428 | case PRIMITIVE_LONG: 429 | fprintf(output_file, "\tstr\t%s, [%s]\n", lr, rr); 430 | break; 431 | default: 432 | error_with_digital("Can't register_store_dereference_pointer on type:", primitive_type); 433 | } 434 | return left_register; 435 | } 436 | 437 | int register_shift_left_by_constant(int register_index, int value) { 438 | char *r = register_list[register_index]; 439 | fprintf(output_file, "\tlsl\t%s, %s, #%d\n", r, r, value); 440 | return register_index; 441 | } 442 | 443 | /** 444 | * 给定一个全局 string 的 label id,把它的地址加载进一个寄存器中 445 | */ 446 | int register_load_global_string(int label) { 447 | int register_index = allocate_register(); 448 | // fprintf(output_file, "\tleaq\tL%d(%%rip), %s\n", label, register_list[register_index]); 449 | return register_index; 450 | } 451 | -------------------------------------------------------------------------------- /helper.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "scan.h" 6 | #include "data.h" 7 | #include "definations.h" 8 | #include "helper.h" 9 | 10 | static int dump_label_id = 1; 11 | static int generate_dump_label(void) { 12 | return (dump_label_id++); 13 | } 14 | 15 | /** 16 | * 检查当前 token 是否为给到的标识符,如果不是则报错 17 | * 如果是则扫描下一个 token 18 | */ 19 | void verify_token_and_fetch_next_token(int token, char *wanted_identifier) { 20 | if (token_from_file.token != token) { 21 | error_with_message("Expected", wanted_identifier); 22 | } 23 | scan(&token_from_file); 24 | } 25 | 26 | void verify_semicolon() { 27 | verify_token_and_fetch_next_token(TOKEN_SEMICOLON, ";"); 28 | } 29 | void verify_colon() { 30 | verify_token_and_fetch_next_token(TOKEN_COLON, ":"); 31 | } 32 | 33 | void verify_identifier() { 34 | verify_token_and_fetch_next_token(TOKEN_IDENTIFIER, "identifier"); 35 | } 36 | 37 | void verify_if() { 38 | verify_token_and_fetch_next_token(TOKEN_IF, "if"); 39 | } 40 | 41 | void verify_while() { 42 | verify_token_and_fetch_next_token(TOKEN_WHILE, "while"); 43 | } 44 | 45 | void verify_for() { 46 | verify_token_and_fetch_next_token(TOKEN_FOR, "for"); 47 | } 48 | 49 | void verify_return() { 50 | verify_token_and_fetch_next_token(TOKEN_RETURN, "return"); 51 | } 52 | 53 | void verify_left_paren() { 54 | verify_token_and_fetch_next_token(TOKEN_LEFT_PAREN, "("); 55 | } 56 | 57 | void verify_right_paren() { 58 | verify_token_and_fetch_next_token(TOKEN_RIGHT_PAREN, ")"); 59 | } 60 | 61 | void verify_left_brace() { 62 | verify_token_and_fetch_next_token(TOKEN_LEFT_BRACE, "{"); 63 | } 64 | 65 | void verify_right_brace() { 66 | verify_token_and_fetch_next_token(TOKEN_RIGHT_BRACE, "}"); 67 | } 68 | 69 | void verify_left_bracket() { 70 | verify_token_and_fetch_next_token(TOKEN_LEFT_BRACKET, "["); 71 | } 72 | 73 | void verify_right_bracket() { 74 | verify_token_and_fetch_next_token(TOKEN_RIGHT_BRACKET, "]"); 75 | } 76 | 77 | void verify_comma() { 78 | verify_token_and_fetch_next_token(TOKEN_COMMA, ","); 79 | } 80 | 81 | 82 | 83 | void error(char *string) { 84 | fprintf(stderr, "%s on line %d of %s\n", string, line, global_input_filename); 85 | fclose(output_file); 86 | unlink(global_output_filename); 87 | exit(1); 88 | } 89 | 90 | void error_with_message(char *string, char *message) { 91 | fprintf(stderr, "%s:%s on line %d of %s\n", string, message, line, global_input_filename); 92 | fclose(output_file); 93 | unlink(global_output_filename); 94 | exit(1); 95 | } 96 | 97 | void error_with_digital(char *string, int digital) { 98 | fprintf(stderr, "%s:%d on line %d of %s\n", string, digital, line, global_input_filename); 99 | fclose(output_file); 100 | unlink(global_output_filename); 101 | exit(1); 102 | } 103 | 104 | void error_with_character(char *string, char character) { 105 | fprintf(stderr, "%s:%c on line %d of %s\n", string, character, line, global_input_filename); 106 | fclose(output_file); 107 | unlink(global_output_filename); 108 | exit(1); 109 | } 110 | 111 | // 递归打印 ast 112 | void dump_ast(struct ASTNode *n, int label, int level) { 113 | int label_false, label_start, label_end; 114 | struct SymbolTable *t = n->symbol_table; 115 | int i; 116 | 117 | switch (n->operation) { 118 | case AST_IF: 119 | label_false = generate_dump_label(); 120 | for (i = 0; i < level; i++) fprintf(stdout, " "); 121 | fprintf(stdout, "AST_IF"); 122 | if (n->right) { 123 | label_end = generate_dump_label(); 124 | fprintf(stdout, ", end L%d", label_end); 125 | } 126 | fprintf(stdout, "\n"); 127 | dump_ast(n->left, label_false, level+2); 128 | dump_ast(n->middle, NO_LABEL, level+2); 129 | if (n->right) dump_ast(n->right, NO_LABEL, level+2); 130 | return; 131 | case AST_WHILE: 132 | label_start = generate_dump_label(); 133 | for (i = 0; i < level; i++) fprintf(stdout, " "); 134 | fprintf(stdout, "AST_WHILE, start L%d\n", label_start); 135 | label_end = generate_dump_label(); 136 | dump_ast(n->left, label_end, level+2); 137 | dump_ast(n->right, NO_LABEL, level+2); 138 | return; 139 | } 140 | 141 | if (n->operation == AST_GLUE) level= -2; 142 | 143 | if (n->left) dump_ast(n->left, NO_LABEL, level+2); 144 | if (n->right) dump_ast(n->right, NO_LABEL, level+2); 145 | 146 | 147 | for (i = 0; i < level; i++) fprintf(stdout, " "); 148 | switch (n->operation) { 149 | case AST_GLUE: 150 | fprintf(stdout, "\n\n"); return; 151 | 152 | case AST_FUNCTION: 153 | fprintf(stdout, "AST_FUNCTION %s\n", t->name); return; 154 | case AST_FUNCTION_CALL: 155 | fprintf(stdout, "AST_FUNCCALL %s\n", t->name); return; 156 | case AST_RETURN: 157 | fprintf(stdout, "AST_RETURN\n"); return; 158 | case AST_PLUS: 159 | fprintf(stdout, "AST_PLUS\n"); return; 160 | case AST_MINUS: 161 | fprintf(stdout, "AST_MINUS\n"); return; 162 | case AST_MULTIPLY: 163 | fprintf(stdout, "AST_MULTIPLY\n"); return; 164 | case AST_DIVIDE: 165 | fprintf(stdout, "AST_DIVIDE\n"); return; 166 | case AST_COMPARE_EQUALS: 167 | fprintf(stdout, "AST_EQ\n"); return; 168 | case AST_COMPARE_NOT_EQUALS: 169 | fprintf(stdout, "AST_NE\n"); return; 170 | case AST_COMPARE_LESS_THAN: 171 | fprintf(stdout, "AST_LT\n"); return; 172 | case AST_COMPARE_GREATER_THAN: 173 | fprintf(stdout, "AST_GT\n"); return; 174 | case AST_COMPARE_LESS_EQUALS: 175 | fprintf(stdout, "AST_LE\n"); return; 176 | case AST_COMPARE_GREATER_EQUALS: 177 | fprintf(stdout, "AST_GE\n"); return; 178 | case AST_INTEGER_LITERAL: 179 | fprintf(stdout, "AST_INTLIT %d\n", n->ast_node_integer_value); return; 180 | case AST_STRING_LITERAL: 181 | fprintf(stdout, "AST_STRLIT rval label L%d\n", n->ast_node_integer_value); return; 182 | case AST_IDENTIFIER: 183 | if (n->rvalue) { 184 | fprintf(stdout, "AST_IDENT rval %s\n", t->name); 185 | } else { 186 | fprintf(stdout, "AST_IDENT %s\n", t->name); 187 | } 188 | return; 189 | case AST_ASSIGN: 190 | fprintf(stdout, "AST_ASSIGN\n"); return; 191 | case AST_IDENTIFIER_ADDRESS: 192 | fprintf(stdout, "AST_ADDR %s\n", t->name); return; 193 | case AST_DEREFERENCE_POINTER: 194 | if (n->rvalue) { 195 | fprintf(stdout, "AST_DEREF rval\n"); 196 | } else { 197 | fprintf(stdout, "AST_DEREF\n"); 198 | } 199 | return; 200 | case AST_WIDEN: 201 | fprintf(stdout, "AST_WIDEN\n"); return; 202 | case AST_SCALE: 203 | fprintf(stdout, "AST_SCALE %d\n", n->ast_node_scale_size); return; 204 | 205 | case AST_PRE_INCREASE: 206 | fprintf(stdout, "AST_PREINC %s\n", n->symbol_table->name); return; 207 | case AST_PRE_DECREASE: 208 | fprintf(stdout, "AST_PREDEC %s\n", n->symbol_table->name); return; 209 | case AST_POST_INCREASE: 210 | fprintf(stdout, "AST_POSTINC\n"); return; 211 | case AST_POST_DECREASE: 212 | fprintf(stdout, "AST_POSTDEC\n"); return; 213 | case AST_NEGATE: 214 | fprintf(stdout, "AST_NEGATE\n"); return; 215 | case AST_BREAK: 216 | fprintf(stdout, "AST_BREAK\n"); return; 217 | case AST_CONTINUE: 218 | fprintf(stdout, "AST_CONTINUE\n"); return; 219 | case AST_CASE: 220 | fprintf(stdout, "AST_CASE %d\n", n->ast_node_integer_value); return; 221 | case AST_DEFAULT: 222 | fprintf(stdout, "AST_DEFAULT\n"); return; 223 | case AST_SWITCH: 224 | fprintf(stdout, "AST_SWITCH\n"); return; 225 | case AST_TYPE_CASTING: 226 | fprintf(stdout, "AST_CAST %d\n", n->primitive_type); return; 227 | case AST_ASSIGN_PLUS: 228 | fprintf(stdout, "AST_ASPLUS\n"); return; 229 | case AST_ASSIGN_MINUS: 230 | fprintf(stdout, "AST_ASMINUS\n"); return; 231 | case AST_ASSIGN_MULTIPLY: 232 | fprintf(stdout, "AST_ASMULTIPLY\n"); return; 233 | case AST_ASSIGN_DIVIDE: 234 | fprintf(stdout, "AST_ASDIVIDE\n"); return; 235 | default: 236 | error_with_digital("Unknown dump_ast operator", n->operation); 237 | } 238 | } 239 | 240 | static void dump_single_symbol(struct SymbolTable *t, int indent) { 241 | int i; 242 | 243 | for (i = 0; i < indent; i++) printf(" "); 244 | switch (t->primitive_type & (~0xf)) { 245 | case PRIMITIVE_VOID: printf("void "); break; 246 | case PRIMITIVE_CHAR: printf("char "); break; 247 | case PRIMITIVE_INT: printf("int "); break; 248 | case PRIMITIVE_LONG: printf("long "); break; 249 | case PRIMITIVE_STRUCT: 250 | if (t->composite_type != NULL) { 251 | printf("struct %s ", t->composite_type->name); 252 | } else { 253 | printf("struct %s ", t->name); 254 | } 255 | break; 256 | case PRIMITIVE_UNION: 257 | if (t->composite_type != NULL) { 258 | printf("union %s ", t->composite_type->name); 259 | } else { 260 | printf("union %s ", t->name); 261 | } 262 | break; 263 | default: printf("unknown primitive type "); 264 | } 265 | 266 | for (i = 0; i < (t->primitive_type & 0xf); i++) printf("*"); 267 | printf("%s", t->name); 268 | 269 | switch (t->structural_type) { 270 | case STRUCTURAL_VARIABLE: break; 271 | case STRUCTURAL_FUNCTION: printf("()"); break; 272 | case STRUCTURAL_ARRAY: printf("[]"); break; 273 | default: printf(" unknown structural type"); 274 | } 275 | 276 | switch (t->storage_class) { 277 | case STORAGE_CLASS_GLOBAL: printf(": global"); break; 278 | case STORAGE_CLASS_LOCAL: printf(": local"); break; 279 | case STORAGE_CLASS_FUNCTION_PARAMETER: printf(": param"); break; 280 | case STORAGE_CLASS_EXTERN: printf(": extern"); break; 281 | case STORAGE_CLASS_STATIC: printf(": static"); break; 282 | case STORAGE_CLASS_STRUCT: printf(": struct"); break; 283 | case STORAGE_CLASS_UNION: printf(": union"); break; 284 | case STORAGE_CLASS_MEMBER: printf(": member"); break; 285 | case STORAGE_CLASS_ENUM_TYPE: printf(": enumtype"); break; 286 | case STORAGE_CLASS_ENUM_VALUE: printf(": enumval"); break; 287 | case STORAGE_CLASS_TYPEDEF: printf(": typedef"); break; 288 | default: printf(": unknown storage class"); 289 | } 290 | 291 | switch (t->structural_type) { 292 | case STRUCTURAL_VARIABLE: 293 | if (t->storage_class == STORAGE_CLASS_ENUM_VALUE) 294 | printf(", value %d\n", t->symbol_table_position); 295 | else 296 | printf(", size %d\n", t->size); 297 | break; 298 | case STRUCTURAL_FUNCTION: printf(", %d params\n", t->element_number); break; 299 | case STRUCTURAL_ARRAY: printf(", %d elems, size %d\n", t->element_number, t->size); break; 300 | } 301 | 302 | switch (t->primitive_type & (~0xf)) { 303 | case PRIMITIVE_STRUCT: 304 | case PRIMITIVE_UNION: dump_single_symbol_table(t->member, NULL, 4); 305 | } 306 | 307 | switch (t->structural_type) { 308 | case STRUCTURAL_FUNCTION: 309 | dump_single_symbol_table(t->member, NULL, 4); 310 | } 311 | } 312 | 313 | void dump_single_symbol_table( 314 | struct SymbolTable *head, 315 | char *name, 316 | int indent 317 | ) { 318 | struct SymbolTable *t; 319 | 320 | if (head && name) printf("%s\n--------\n", name); 321 | for (t = head; t; t = t->next) dump_single_symbol(t, indent); 322 | } 323 | 324 | void dump_symbol_table() { 325 | dump_single_symbol_table(global_head, "Global", 0); 326 | printf("\n"); 327 | dump_single_symbol_table(enum_head, "Enums", 0); 328 | printf("\n"); 329 | dump_single_symbol_table(typedef_head, "Typedefs", 0); 330 | } 331 | -------------------------------------------------------------------------------- /helper.h: -------------------------------------------------------------------------------- 1 | #ifndef __HELPER_H__ 2 | #define __HELPER_H__ 3 | 4 | #include "definations.h" 5 | 6 | void verify_token_and_fetch_next_token(int token, char *wanted_identifier); 7 | void verify_semicolon(); 8 | void verify_colon(); 9 | void verify_identifier(); 10 | void verify_if(); 11 | void verify_while(); 12 | void verify_for(); 13 | void verify_return(); 14 | void verify_left_paren(); 15 | void verify_right_paren(); 16 | void verify_left_brace(); 17 | void verify_right_brace(); 18 | void verify_left_bracket(); 19 | void verify_right_bracket(); 20 | void verify_comma(); 21 | 22 | void error(char *string); 23 | void error_with_message(char *string, char *message); 24 | void error_with_digital(char *string, int digital); 25 | void error_with_character(char *string, char character); 26 | 27 | void dump_ast(struct ASTNode *n, int label, int level); 28 | void dump_single_symbol_table( 29 | struct SymbolTable *head, 30 | char *name, 31 | int indent 32 | ); 33 | void dump_symbol_table(); 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /incdir.h: -------------------------------------------------------------------------------- 1 | #define INCDIR "/tmp/include" 2 | -------------------------------------------------------------------------------- /include/ctype.h: -------------------------------------------------------------------------------- 1 | #ifndef _CTYPE_H_ 2 | # define _CTYPE_H_ 3 | 4 | int isalnum(int c); 5 | int isalpha(int c); 6 | int iscntrl(int c); 7 | int isdigit(int c); 8 | int isgraph(int c); 9 | int islower(int c); 10 | int isprint(int c); 11 | int ispunct(int c); 12 | int isspace(int c); 13 | int isupper(int c); 14 | int isxdigit(int c); 15 | int isascii(int c); 16 | int isblank(int c); 17 | 18 | int toupper(int c); 19 | int tolower(int c); 20 | 21 | #endif // _CTYPE_H_ 22 | -------------------------------------------------------------------------------- /include/errno.h: -------------------------------------------------------------------------------- 1 | #ifndef _ERRNO_H_ 2 | # define _ERRNO_H_ 3 | 4 | int * __errno_location(void); 5 | 6 | #define errno (* __errno_location()) 7 | 8 | #endif // _ERRNO_H_ 9 | -------------------------------------------------------------------------------- /include/fcntl.h: -------------------------------------------------------------------------------- 1 | #ifndef _FCNTL_H_ 2 | # define _FCNTL_H_ 3 | 4 | #define O_RDONLY 00 5 | #define O_WRONLY 01 6 | #define O_RDWR 02 7 | 8 | int open(char *pathname, int flags); 9 | 10 | #endif // _FCNTL_H_ 11 | -------------------------------------------------------------------------------- /include/stddef.h: -------------------------------------------------------------------------------- 1 | #ifndef _STDDEF_H_ 2 | # define _STDDEF_H_ 3 | 4 | #ifndef NULL 5 | # define NULL (void *)0 6 | #endif 7 | 8 | typedef long size_t; 9 | 10 | #endif //_STDDEF_H_ 11 | 12 | -------------------------------------------------------------------------------- /include/stdio.h: -------------------------------------------------------------------------------- 1 | #ifndef _STDIO_H_ 2 | # define _STDIO_H_ 3 | 4 | #include 5 | 6 | #ifndef NULL 7 | # define NULL (void *)0 8 | #endif 9 | 10 | #ifndef EOF 11 | # define EOF (-1) 12 | #endif 13 | 14 | // This FILE definition will do for now 15 | typedef char * FILE; 16 | 17 | FILE *fopen(char *pathname, char *mode); 18 | size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); 19 | size_t fwrite(void *ptr, size_t size, size_t nmemb, FILE *stream); 20 | int fclose(FILE *stream); 21 | int printf(char *format); 22 | int fprintf(FILE *stream, char *format); 23 | int sprintf(char *str, char *format); 24 | int snprintf(char *str, size_t size, char *format); 25 | int fgetc(FILE *stream); 26 | int fputc(int c, FILE *stream); 27 | int fputs(char *s, FILE *stream); 28 | int putc(int c, FILE *stream); 29 | int putchar(int c); 30 | int puts(char *s); 31 | FILE *popen(char *command, char *type); 32 | int pclose(FILE *stream); 33 | 34 | extern FILE *stdin; 35 | extern FILE *stdout; 36 | extern FILE *stderr; 37 | 38 | #endif // _STDIO_H_ 39 | -------------------------------------------------------------------------------- /include/stdlib.h: -------------------------------------------------------------------------------- 1 | #ifndef _STDLIB_H_ 2 | # define _STDLIB_H_ 3 | 4 | void exit(int status); 5 | void _Exit(int status); 6 | 7 | void *malloc(int size); 8 | void free(void *ptr); 9 | void *calloc(int nmemb, int size); 10 | void *realloc(void *ptr, int size); 11 | int system(char *command); 12 | 13 | #endif // _STDLIB_H_ 14 | -------------------------------------------------------------------------------- /include/string.h: -------------------------------------------------------------------------------- 1 | #ifndef _STRING_H_ 2 | # define _STRING_H_ 3 | 4 | #include 5 | 6 | char *strdup(char *s); 7 | char *strchr(char *s, int c); 8 | char *strrchr(char *s, int c); 9 | int strcmp(char *s1, char *s2); 10 | int strncmp(char *s1, char *s2, size_t n); 11 | char *strerror(int errnum); 12 | 13 | #endif // _STRING_H_ 14 | -------------------------------------------------------------------------------- /include/unistd.h: -------------------------------------------------------------------------------- 1 | #ifndef _UNISTD_H_ 2 | # define _UNISTD_H_ 3 | 4 | void _exit(int status); 5 | int unlink(char *pathname); 6 | 7 | #endif // _UNISTD_H_ 8 | -------------------------------------------------------------------------------- /interpreter.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "definations.h" 5 | #include "data.h" 6 | #include "ast.h" 7 | #include "helper.h" 8 | 9 | /** 10 | * 由于 converse_token_2_ast 得到的树结构对于要遍历它进行运算来说是没有优先级的,所以这里 11 | * 需要对这个构建好的树进行解释,然后得到一个准确的运算结果 12 | * 简单来说,就是要让 13 | * * 14 | * / \ 15 | * 2 + 16 | * / \ 17 | * 3 * 18 | * / \ 19 | * 4 5 20 | * 变成 21 | * + 22 | * / \ 23 | * / \ 24 | * / \ 25 | * * * 26 | * / \ / \ 27 | * 2 3 4 5 28 | * 29 | * 然后再对树进行后序遍历,并将其做运算,就能得到对应的结果 30 | */ 31 | int interpret_ast(struct ASTNode *node) { 32 | int left_value, right_value; 33 | 34 | if (node->left) { 35 | left_value = interpret_ast(node->left); 36 | } 37 | if (node->right) { 38 | right_value = interpret_ast(node->right); 39 | } 40 | 41 | switch (node->operation) { 42 | case AST_PLUS: 43 | return (left_value + right_value); 44 | case AST_MINUS: 45 | return (left_value - right_value); 46 | case AST_MULTIPLY: 47 | return (left_value * right_value); 48 | case AST_DIVIDE: 49 | return (left_value / right_value); 50 | case AST_INTEGER_LITERAL: 51 | return (node->ast_node_integer_value); 52 | default: 53 | error_with_digital("Unknown AST operator", node->operation); 54 | } 55 | 56 | return NO_REGISTER; 57 | } 58 | -------------------------------------------------------------------------------- /interpreter.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __INTERPRETER_H__ 3 | #define __INTERPRETER_H__ 4 | 5 | int interpret_ast(struct ASTNode *node); 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define extern_ 8 | #include "data.h" 9 | #undef extern_ 10 | 11 | #include "definations.h" 12 | #include "scan.h" 13 | #include "parser.h" 14 | #include "interpreter.h" 15 | #include "generator.h" 16 | #include "statement.h" 17 | #include "helper.h" 18 | #include "declaration.h" 19 | #include "symbol_table.h" 20 | 21 | #define MAX_OBJECT_FILE_NUMBER 100 22 | 23 | static void init() { 24 | output_dump_ast = 0; 25 | output_keep_object_file = 0; 26 | output_keep_assembly_file = 0; 27 | output_binary_file = 1; 28 | output_verbose = 0; 29 | output_dump_symbol_table = 0; 30 | } 31 | 32 | static void usage_info(char *info) { 33 | fprintf(stderr, "Usage: %s [-vcSTM] [-o output file] file [file ...]\n", info); 34 | fprintf(stderr, " -c generate object files but don't link them\n"); 35 | fprintf(stderr, " -S generate assembly files but don't link them\n"); 36 | fprintf(stderr, " -T dump the AST trees for each input file\n"); 37 | fprintf(stderr, " -o output file, produce the output file executable file\n"); 38 | fprintf(stderr, " -v give verbose output of the compilation stages\n"); 39 | fprintf(stderr, " -M dump the symbol table for each input file\n"); 40 | exit(1); 41 | } 42 | 43 | // 改变一个带 '.' 的字符串的后缀,这个被更改的后缀即为给定的参数 suffix 44 | char *modify_string_suffix(char *string, char suffix) { 45 | char *p; 46 | char *new_string = strdup(string); 47 | if (!new_string) return (NULL); 48 | // 找出 '.' 的位置 49 | p = strrchr(new_string, '.'); 50 | if (!p) return (NULL); 51 | // 边界判断 52 | if (*(++p) == '\0') return (NULL); 53 | // 更改 suffix 54 | *(p++) = suffix; 55 | *p = '\0'; 56 | return (new_string); 57 | } 58 | 59 | void clear_all_static_symbol() { 60 | struct SymbolTable *current_symbol_table, *prev_symbol_table = NULL; 61 | 62 | // 遍历 global symbol table,寻找 static symbol 63 | for ( 64 | current_symbol_table = global_head; 65 | current_symbol_table; 66 | current_symbol_table = current_symbol_table->next 67 | ) { 68 | // 如果找到了 69 | if (current_symbol_table->storage_class == STORAGE_CLASS_STATIC) { 70 | // 正常情况: 跳过 static symbol 71 | if (prev_symbol_table) 72 | prev_symbol_table->next = current_symbol_table->next; 73 | else 74 | global_head->next = current_symbol_table->next; 75 | 76 | // 如果 static symbol 出现在结尾: 跳过 static symbol 77 | if (current_symbol_table == global_tail) { 78 | if (prev_symbol_table) global_tail = prev_symbol_table; 79 | else global_tail = global_head; 80 | } 81 | } 82 | } 83 | 84 | // 在指向下一个之前 prev 应该指向当前 node 85 | prev_symbol_table = current_symbol_table; 86 | } 87 | 88 | // 编译成汇编代码 89 | static char *do_compile(char *filename) { 90 | char cmd[TEXT_LENGTH]; 91 | 92 | global_output_filename = modify_string_suffix(filename, 's'); 93 | if (!global_output_filename) { 94 | fprintf(stderr, "Error: %s has no suffix, try .zc on the end\n", filename); 95 | exit(1); 96 | } 97 | 98 | // 先生成一个预处理器的命令行 99 | // INCLUDE_DIRECTORY 在 Makefile 里面找到 100 | snprintf(cmd, TEXT_LENGTH, "%s %s %s", CPP_CMD, INCDIR, filename); 101 | if (!(input_file = popen(cmd, "r"))) { 102 | fprintf(stderr, "Unable to open %s: %s\n", filename, strerror(errno)); 103 | exit(1); 104 | } 105 | global_input_filename = filename; 106 | 107 | // 用 output_file 来模拟一个被生成的汇编文件 108 | if (!(output_file = fopen(global_output_filename, "w"))) { 109 | fprintf(stderr, "Unable to open %s: %s\n", global_output_filename, strerror(errno)); 110 | exit(1); 111 | } 112 | 113 | line = 1; 114 | start_line = 1; 115 | putback_buffer = '\n'; 116 | clear_all_symbol_tables(); 117 | 118 | if (output_verbose) 119 | printf("compiling %s\n", filename); 120 | 121 | // 扫描文件中的字符串,并将其赋值给 token_from_file 这个全局变量 122 | scan(&token_from_file); 123 | look_ahead_token.token = 0; 124 | generate_preamble_code(); 125 | parse_global_declaration(); 126 | generate_postamble_code(); 127 | 128 | // 关闭文件 129 | fclose(input_file); 130 | fclose(output_file); 131 | 132 | if (output_dump_symbol_table) { 133 | printf("Symbols for %s\n", filename); 134 | dump_symbol_table(); 135 | fprintf(stdout, "\n\n"); 136 | } 137 | 138 | clear_all_static_symbol(); 139 | 140 | return (global_output_filename); 141 | } 142 | 143 | char *do_assemble(char *filename) { 144 | char cmd[TEXT_LENGTH]; 145 | int error; 146 | 147 | char *output_filename = modify_string_suffix(filename, 'o'); 148 | if (!output_filename) { 149 | fprintf(stderr, "Error: %s has no suffix, try .s on the end\n", filename); 150 | exit(1); 151 | } 152 | 153 | snprintf(cmd, TEXT_LENGTH, "%s %s %s", AS_CMD, output_filename, filename); 154 | if (output_verbose) printf("%s\n", cmd); 155 | error = system(cmd); 156 | if (error) { 157 | fprintf(stderr, "Assembly of %s failed\n", filename); 158 | exit(1); 159 | } 160 | return (output_filename); 161 | } 162 | 163 | // link 文件 164 | void do_link(char *output_filename, char **object_file_list) { 165 | int count, size = TEXT_LENGTH; 166 | char cmd[TEXT_LENGTH], *p; 167 | int error; 168 | 169 | p = cmd; 170 | count = snprintf(p, size, "%s %s ", LD_CMD, output_filename); 171 | p += count; 172 | size -= count; 173 | 174 | while (*object_file_list) { 175 | count = snprintf(p, size, "%s ", *object_file_list); 176 | p += count; 177 | size -= count; 178 | object_file_list++; 179 | } 180 | 181 | if (output_verbose) printf("%s\n", cmd); 182 | error = system(cmd); 183 | if (error) { 184 | fprintf(stderr, "Linking failed\n"); 185 | exit(1); 186 | } 187 | } 188 | 189 | void do_unlink(char *filename) { 190 | unlink(filename); 191 | } 192 | 193 | 194 | 195 | int main(int argc, char **argv) { 196 | char *output_filename = A_OUT; 197 | char *assembly_file, *object_file; 198 | char *object_file_list[MAX_OBJECT_FILE_NUMBER]; 199 | int i, j, object_file_count = 0; 200 | 201 | init(); 202 | 203 | // 扫描命令行输入 204 | for (i = 1; i < argc; i++) { 205 | if (*argv[i] != '-') break; 206 | for (j = 1; (*argv[i] == '-') && argv[i][j]; j++) { 207 | switch (argv[i][j]) { 208 | case 'T': output_dump_ast = 1; break; 209 | case 'o': output_filename = argv[++i]; break; 210 | case 'c': 211 | output_keep_object_file = 1; 212 | output_keep_assembly_file = 0; 213 | output_binary_file = 0; 214 | break; 215 | case 'S': 216 | output_keep_object_file = 0; 217 | output_keep_assembly_file = 1; 218 | output_binary_file = 0; 219 | break; 220 | case 'v': output_verbose = 1; break; 221 | case 'M': output_dump_symbol_table = 1; break; 222 | default: usage_info(argv[0]); 223 | } 224 | } 225 | } 226 | 227 | if (i >= argc) usage_info(argv[0]); 228 | 229 | // 轮流编译文件 230 | while (i < argc) { 231 | assembly_file = do_compile(argv[i]); 232 | 233 | if (output_binary_file || output_keep_object_file) { 234 | object_file = do_assemble(assembly_file); 235 | if (object_file_count == (MAX_OBJECT_FILE_NUMBER - 2)) { 236 | fprintf(stderr, "Too many object files for the compiler to handle\n"); 237 | exit(1); 238 | } 239 | object_file_list[object_file_count++] = object_file; 240 | object_file_list[object_file_count] = NULL; 241 | } 242 | 243 | if (!output_keep_assembly_file) do_unlink(assembly_file); 244 | i++; 245 | } 246 | 247 | if (output_binary_file) { 248 | do_link(output_filename, object_file_list); 249 | 250 | if (!output_keep_object_file) 251 | for(i = 0; object_file_list[i]; i++) 252 | do_unlink(object_file_list[i]); 253 | } 254 | 255 | return (0); 256 | } 257 | -------------------------------------------------------------------------------- /optimizer.c: -------------------------------------------------------------------------------- 1 | #include "data.h" 2 | #include "definations.h" 3 | #include "declaration.h" 4 | #include "ast.h" 5 | 6 | static struct ASTNode *fold_2_children(struct ASTNode *node) { 7 | int value, left_value, right_value; 8 | 9 | left_value = node->left->ast_node_integer_value; 10 | right_value = node->right->ast_node_integer_value; 11 | 12 | switch (node->operation) { 13 | case AST_PLUS: 14 | value = left_value + right_value; 15 | break; 16 | case AST_MINUS: 17 | value = left_value - right_value; 18 | break; 19 | case AST_MULTIPLY: 20 | value = left_value * right_value; 21 | break; 22 | case AST_DIVIDE: 23 | if (!right_value) return (node); 24 | value = left_value / right_value; 25 | break; 26 | default: 27 | return (node); 28 | } 29 | 30 | return (create_ast_leaf(AST_INTEGER_LITERAL, node->primitive_type, value, NULL, NULL)); 31 | } 32 | 33 | static struct ASTNode *fold_1_children(struct ASTNode *node) { 34 | int value = node->left->ast_node_integer_value; 35 | 36 | switch (node->operation) { 37 | // 如果是 x = 3000 + 1; 38 | // 这个 1 如果是 char 类型的,就需要 widen 至 int 类型 39 | case AST_WIDEN: break; 40 | case AST_INVERT: value = ~value; break; 41 | case AST_LOGIC_NOT: value = !value; break; 42 | default: return (node); 43 | } 44 | 45 | return (create_ast_leaf(AST_INTEGER_LITERAL, node->primitive_type, value, NULL, NULL)); 46 | } 47 | 48 | static struct ASTNode *fold(struct ASTNode *node) { 49 | if (!node) return (NULL); 50 | 51 | node->left = fold(node->left); 52 | node->right = fold(node->right); 53 | 54 | if (node->left && node->left->operation == AST_INTEGER_LITERAL) 55 | if (node->right && node->right->operation == AST_INTEGER_LITERAL) 56 | node = fold_2_children(node); 57 | else 58 | node = fold_1_children(node); 59 | 60 | return (node); 61 | } 62 | 63 | struct ASTNode *optimise(struct ASTNode *node) { 64 | return (fold(node)); 65 | } 66 | -------------------------------------------------------------------------------- /optimizer.h: -------------------------------------------------------------------------------- 1 | #ifndef __OPTIMIZER_H__ 2 | #define __OPTIMIZER_H__ 3 | 4 | struct ASTNode *optimise(struct ASTNode *node); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /parser.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __PARSER_H__ 3 | #define __PARSER_H__ 4 | 5 | struct ASTNode *parse_expression_list(int end_token); 6 | struct ASTNode *converse_token_2_ast(int previous_token_precedence); 7 | struct ASTNode *convert_function_call_2_ast(); 8 | struct ASTNode *convert_prefix_expression_2_ast(int previous_token_precedence); 9 | struct ASTNode *convert_postfix_expression_2_ast(int previous_token_precedence); 10 | struct ASTNode *convert_array_access_2_ast(struct ASTNode *left); 11 | struct ASTNode *convert_member_access_2_ast(int with_pointer, struct ASTNode *left); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /scan.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "data.h" 6 | #include "definations.h" 7 | #include "scan.h" 8 | #include "helper.h" 9 | 10 | char *token_strings[] = { 11 | "EOF", "=", "+=", "-=", "*=", "/=", "%=", "?", 12 | "&&", "||", "|", "^", "&", 13 | "==", "!=", ",", ">", "<=", ">=", "<<", ">>", 14 | "+", "-", "*", "/", "%", "++", "--", "~", "!", 15 | "void", "char", "int", "long", 16 | "if", "else", "while", "for", "return", 17 | "struct", "union", "enum", "typedef", 18 | "extern", "break", "continue", "switch", 19 | "case", "default", "sizeof", "static", 20 | "integer_literal", "string_literal", ";", "identifier", 21 | "{", "}", "(", ")", "[", "]", ",", ".", 22 | "->", ":" 23 | }; 24 | 25 | // 从文件中读取下一个字符 26 | static int next(void) { 27 | int c; 28 | int l; 29 | 30 | // 由于上一次读取到了不是数字的字符,所以这里相当于一个 buffer,直接返回上一次读取后的值即可 31 | if (putback_buffer) { 32 | c = putback_buffer; 33 | putback_buffer = 0; 34 | return (c); 35 | } 36 | 37 | // 返回了上一次读取后的值之后,再次从文件刚刚的位置的下一位读取 38 | c = fgetc(input_file); 39 | // 处理预编译处理过后的头文件,这些头文件会加载到 main.c 中 40 | // 这些头文件一般长这样 41 | // # 1 "z.c" 42 | // # 1 "" 43 | // # 1 "" 44 | // # 1 "z.c" 45 | // # 1 "include/stdio.h" 1 46 | // # 1 "include/stddef.h" 1 47 | // typedef long size_t; 48 | // # 5 "include/stdio.h" 2 49 | // typedef char * FILE; 50 | // FILE *fopen(char *pathname, char *mode); 51 | // ... 52 | // # 2 "z.c" 2 53 | // int main() {...} 54 | 55 | // 先从 '#' 开始 56 | while (start_line && c == '#') { 57 | start_line = 0; 58 | // 跳过 '#' 59 | scan(&token_from_file); 60 | // 如果不是 '1' 报错 61 | if (token_from_file.token != TOKEN_INTEGER_LITERAL) 62 | error_with_message("Expecting pre-processor line number, got", text_buffer); 63 | // 把 '1' 赋值给 l 64 | l = token_from_file.integer_value; 65 | 66 | // 跳过 '1',此时来到的是文件路径/文件名 "z.c" 67 | scan(&token_from_file); 68 | if (token_from_file.token != TOKEN_STRING_LITERAL) 69 | error_with_message("Expecting pre-processor file name, got", text_buffer); 70 | 71 | // 以 '<>' 包起来的不用检查 72 | if (text_buffer[0] != '<') { 73 | if (strcmp(text_buffer, global_input_filename)) 74 | global_input_filename = strdup(text_buffer); 75 | line = l; 76 | } 77 | 78 | // 跳过行尾继续下一个 79 | while ((c = fgetc(input_file) != '\n')); 80 | c = fgetc(input_file); 81 | start_line = 1; 82 | } 83 | 84 | start_line = 0; 85 | if ('\n' == c) { 86 | line ++; 87 | start_line = 1; 88 | } 89 | 90 | return (c); 91 | } 92 | 93 | // 把一个不需要的字符放回去 94 | static void put_back(int c) { 95 | putback_buffer = c; 96 | } 97 | 98 | // 白名单,遇到如下的字符就跳过 99 | static int skip(void) { 100 | int c = next(); 101 | 102 | while ( 103 | ' ' == c || 104 | '\t' == c || 105 | '\n' == c || 106 | '\r' == c || 107 | '\f' == c 108 | ) { 109 | // 遇到以上的字符就继续读取 110 | c = next(); 111 | } 112 | 113 | return (c); 114 | } 115 | 116 | static int get_the_position_of_the_charater(char *s, int c) { 117 | // s = "0123456789" 118 | // s 这里是字符串的首地址 119 | int i; 120 | for (i = 0; s[i] != '\0'; i++) 121 | if (s[i] == (char) c) 122 | return (i); 123 | return (-1); 124 | } 125 | 126 | // 从输入的 file 中扫描并返回一个 integer 字符 127 | static int scan_integer(int c) { 128 | // 默认 10 进制 129 | int k, value = 0, radix = 10; 130 | 131 | if (c == '0') { 132 | if ((c = next()) == 'x') { 133 | // 16 进制 134 | radix = 16; 135 | c = next(); 136 | } else 137 | // 8 进制 138 | radix = 8; 139 | } 140 | 141 | while (((k = get_the_position_of_the_charater("0123456789abcdef", tolower(c))) >= 0)) { 142 | if (k >= radix) 143 | error_with_character("invalid digit in integer literal", c); 144 | value = value * radix + k; 145 | // 如果是数字,继续扫描 146 | c = next(); 147 | } 148 | 149 | // 如果不是数字,则将读取到的字符放到 put buffer 中 150 | // 准备下一次读取 151 | // put buffer 在这里可以理解为一个读取完一个 interger 之后的状态 152 | put_back(c); 153 | return (value); 154 | } 155 | 156 | // 扫描标识符,并将其存入 buffer 中,最终返回是这个标识符的长度 157 | // 这个标识符是类似于 printf 之类的函数名称或者其他的变量 158 | static int scan_identifier(int c, char *buffer, int limit_length) { 159 | int length = 0; 160 | 161 | // 如果是 字母 | 数字 | _ 162 | while(isalpha(c) || isdigit(c) || '_' == c) { 163 | if (length >= limit_length - 1) { 164 | error("identifier too long on line"); 165 | } 166 | buffer[length ++] = (char)c; 167 | c = next(); 168 | } 169 | 170 | // 跳出循环时,最后一个通过 next 得到的 c 是无效的,所以这里需要 put_back 171 | put_back(c); 172 | 173 | // 在最后要加结尾符 174 | buffer[length] = '\0'; 175 | 176 | return (length); 177 | } 178 | 179 | // 解析类似于 \0x41 这样的字符 180 | static int hex_character() { 181 | int c, h, n = 0, flag = 0; 182 | 183 | while (isxdigit(c = next())) { 184 | // char 变成 int 185 | h = get_the_position_of_the_charater("0123456789abcdef", tolower(c)); 186 | n = n * 16 + h; 187 | flag = 1; 188 | } 189 | 190 | put_back(c); 191 | 192 | if (!flag) error("missing digits after '\\x'"); 193 | if (n > 255) error("value out of range after '\\x'"); 194 | 195 | return (n); 196 | } 197 | 198 | // 扫描单引号中的字符 199 | // 转义部分字符,这里暂时不考虑 8 进制或者其他类型的字符 200 | static int escape_character() { 201 | int c = next(), i, c2; 202 | // 处理类似于 \r\n 这种特殊字符 203 | // 符号 '\' 204 | if (c == '\\') { 205 | // 符号 'r'、'n' 等 206 | switch (c = next()) { 207 | case 'a': return ('\a'); 208 | case 'b': return ('\b'); 209 | case 'f': return ('\f'); 210 | case 'n': return ('\n'); 211 | case 'r': return ('\r'); 212 | case 't': return ('\t'); 213 | case 'v': return ('\v'); 214 | case '\\': return ('\\'); 215 | case '"': return ('"'); 216 | case '\'': return ('\''); 217 | case '0': 218 | case '1': 219 | case '2': 220 | case '3': 221 | case '4': 222 | case '5': 223 | case '6': 224 | case '7': 225 | for (i = c2 = 0; isdigit(c) && c < '8'; c = next()) { 226 | if (++i > 3) 227 | break; 228 | c2 = c2 * 8 + (c - '0'); 229 | } 230 | put_back(c); 231 | return (c2); 232 | case 'x': 233 | return (hex_character()); 234 | default: 235 | error_with_character("unknown escape sequence", c); 236 | } 237 | } 238 | return (c); 239 | } 240 | 241 | // 扫描 sting,并存入 text_buffer 中 242 | // 返回 string 的长度 243 | static int scan_string(char *buffer) { 244 | int i, c; 245 | for (i = 0; i < TEXT_LENGTH - 1; i++) { 246 | if ((c = escape_character()) == '"') { 247 | buffer[i] = 0; 248 | return (i); 249 | } 250 | buffer[i] = (char)c; 251 | } 252 | error("String literal too long"); 253 | return (0); 254 | } 255 | 256 | // 这里只做简单的判断,如果首字母是对应关键字的首字母,则直接返回关键字 257 | static int get_keyword(char *s) { 258 | switch (*s) { 259 | case 'c': 260 | if (!strcmp(s, "char")) return (TOKEN_CHAR); 261 | else if (!strcmp(s, "continue")) return (TOKEN_CONTINUE); 262 | else if (!strcmp(s, "case")) return (TOKEN_CASE); 263 | break; 264 | case 'l': 265 | if (!strcmp(s, "long")) return (TOKEN_LONG); 266 | case 'i': 267 | if (!strcmp(s, "if")) return (TOKEN_IF); 268 | else if (!strcmp(s, "int")) return (TOKEN_INT); 269 | break; 270 | case 'e': 271 | if (!strcmp(s, "else")) return (TOKEN_ELSE); 272 | else if (!strcmp(s, "enum")) return (TOKEN_ENUM); 273 | else if (!strcmp(s, "extern")) return (TOKEN_EXTERN); 274 | break; 275 | case 'w': 276 | if (!strcmp(s, "while")) return (TOKEN_WHILE); 277 | break; 278 | case 'f': 279 | if (!strcmp(s, "for")) return (TOKEN_FOR); 280 | break; 281 | case 'r': 282 | if (!strcmp(s, "return")) return (TOKEN_RETURN); 283 | case 'v': 284 | if (!strcmp(s, "void")) return (TOKEN_VOID); 285 | break; 286 | case 's': 287 | if (!strcmp(s, "struct")) return (TOKEN_STRUCT); 288 | else if (!strcmp(s, "switch")) return (TOKEN_SWITCH); 289 | else if (!strcmp(s, "sizeof")) return (TOKEN_SIZEOF); 290 | else if (!strcmp(s, "static")) return (TOKEN_STATIC); 291 | break; 292 | case 'u': 293 | if (!strcmp(s, "union")) return (TOKEN_UNION); 294 | break; 295 | case 't': 296 | if (!strcmp(s, "typedef")) return (TOKEN_TYPEDEF); 297 | break; 298 | case 'b': 299 | if (!strcmp(s, "break")) return (TOKEN_BREAK); 300 | break; 301 | case 'd': 302 | if (!strcmp(s, "default")) return (TOKEN_DEFAULT); 303 | break; 304 | } 305 | return (0); 306 | } 307 | 308 | // 扫描 tokens 309 | // 只有扫描到文件尾时返回 0,表示扫描结束 310 | // 其他情况均在扫描中 311 | int scan(struct Token *t) { 312 | int c, token_type; 313 | 314 | // 如果提前找到了 token,就直接返回这个 token 315 | if (look_ahead_token.token) { 316 | t->token = look_ahead_token.token; 317 | t->token_string = look_ahead_token.token_string; 318 | t->integer_value = look_ahead_token.integer_value; 319 | look_ahead_token.token = 0; 320 | return (1); 321 | } 322 | 323 | // 去掉不需要的字符 324 | c = skip(); 325 | 326 | switch (c) { 327 | case EOF: 328 | t->token = TOKEN_EOF; 329 | return (0); 330 | case '+': 331 | if ((c = next()) == '+') { 332 | t->token = TOKEN_INCREASE; 333 | } else if (c == '=') { 334 | t->token = TOKEN_ASSIGN_PLUS; 335 | } else { 336 | put_back(c); 337 | t->token = TOKEN_PLUS; 338 | } 339 | break; 340 | case '-': 341 | if ((c = next()) == '-') { 342 | t->token = TOKEN_DECREASE; 343 | } else if (c == '>') { 344 | t->token = TOKEN_ARROW; 345 | } else if (c == '=') { 346 | t->token = TOKEN_ASSIGN_MINUS; 347 | } else if (isdigit(c)) { 348 | // 有可能是个负数 349 | t->integer_value = -scan_integer(c); 350 | t->token = TOKEN_INTEGER_LITERAL; 351 | } else { 352 | put_back(c); 353 | t->token = TOKEN_MINUS; 354 | } 355 | break; 356 | case '*': 357 | if ((c = next()) == '=') { 358 | t->token = TOKEN_ASSIGN_MULTIPLY; 359 | } else { 360 | put_back(c); 361 | t->token = TOKEN_MULTIPLY; 362 | } 363 | break; 364 | case '/': 365 | if ((c = next()) == '=') { 366 | t->token = TOKEN_ASSGIN_DIVIDE; 367 | } else { 368 | put_back(c); 369 | t->token = TOKEN_DIVIDE; 370 | } 371 | break; 372 | case '%': 373 | if ((c = next()) == '=') { 374 | t->token = TOKEN_ASSGIN_MOD; 375 | } else { 376 | put_back(c); 377 | t->token = TOKEN_MOD; 378 | } 379 | break; 380 | case ';': 381 | t->token = TOKEN_SEMICOLON; 382 | break; 383 | case '(': 384 | t->token = TOKEN_LEFT_PAREN; 385 | break; 386 | case ')': 387 | t->token = TOKEN_RIGHT_PAREN; 388 | break; 389 | case '{': 390 | t->token = TOKEN_LEFT_BRACE; 391 | break; 392 | case '}': 393 | t->token = TOKEN_RIGHT_BRACE; 394 | break; 395 | case '[': 396 | t->token = TOKEN_LEFT_BRACKET; 397 | break; 398 | case ']': 399 | t->token = TOKEN_RIGHT_BRACKET; 400 | break; 401 | case ',': 402 | t->token = TOKEN_COMMA; 403 | break; 404 | case '~': 405 | t->token = TOKEN_INVERT; 406 | break; 407 | case '^': 408 | t->token = TOKEN_XOR; 409 | break; 410 | case '.': 411 | t->token = TOKEN_DOT; 412 | break; 413 | case ':': 414 | t->token = TOKEN_COLON; 415 | break; 416 | case '?': 417 | t->token = TOKEN_QUESTION; 418 | break; 419 | 420 | case '\'': 421 | // 如果是单引号,则扫描引号中字符的值以及尾单引号 422 | t->integer_value = escape_character(); 423 | t->token = TOKEN_INTEGER_LITERAL; 424 | if (next() != '\'') 425 | error("Expected '\\'' at end of char literal"); 426 | break; 427 | case '"': 428 | scan_string(text_buffer); 429 | t->token = TOKEN_STRING_LITERAL; 430 | break; 431 | 432 | case '&': 433 | if ((c = next()) == '&') { 434 | t->token = TOKEN_LOGIC_AND; 435 | } else { 436 | put_back(c); 437 | t->token = TOKEN_AMPERSAND; 438 | } 439 | break; 440 | case '|': 441 | if ((c = next()) == '|') { 442 | t->token = TOKEN_LOGIC_OR; 443 | } else { 444 | put_back(c); 445 | t->token = TOKEN_OR; 446 | } 447 | break; 448 | case '=': 449 | if ((c = next()) == '=') { 450 | t->token = TOKEN_COMPARE_EQUALS; 451 | } else { 452 | put_back(c); 453 | t->token = TOKEN_ASSIGN; 454 | } 455 | break; 456 | case '!': 457 | if ((c = next()) == '=') { 458 | t->token = TOKEN_COMPARE_NOT_EQUALS; 459 | } else { 460 | put_back(c); 461 | t->token = TOKEN_LOGIC_NOT; 462 | } 463 | break; 464 | case '<': 465 | if ((c = next()) == '=') { 466 | t->token = TOKEN_COMPARE_LESS_EQUALS; 467 | } else if (c == '<') { 468 | t->token = TOKEN_LEFT_SHIFT; 469 | } else { 470 | put_back(c); 471 | t->token = TOKEN_COMPARE_LESS_THAN; 472 | } 473 | break; 474 | case '>': 475 | if ((c = next()) == '=') { 476 | t->token = TOKEN_COMPARE_GREATER_EQUALS; 477 | } else if (c == '>') { 478 | t->token = TOKEN_RIGHT_SHIFT; 479 | }else { 480 | put_back(c); 481 | t->token = TOKEN_COMPARE_GREATER_THAN; 482 | } 483 | break; 484 | default: 485 | if (isdigit(c)) { 486 | t->token = TOKEN_INTEGER_LITERAL; 487 | // 如果遇到数字,则继续扫描 488 | t->integer_value = scan_integer(c); 489 | break; 490 | } else if (isalpha(c) || '_' == c) { 491 | // 如果遇到是一个字母开头的,则将其视为标识符扫描 492 | scan_identifier(c, text_buffer, TEXT_LENGTH); 493 | 494 | int token = get_keyword(text_buffer); 495 | if (token) { 496 | t->token = token; 497 | break; 498 | } 499 | // 如果都不是关键字,则只能说明是个标识符 500 | t->token = TOKEN_IDENTIFIER; 501 | break; 502 | } 503 | error_with_character("Unrecognised character", c); 504 | } 505 | 506 | t->token_string = token_strings[t->token]; 507 | // printf( 508 | // "scan '%s' '%s' -> (%s), line = %d\n", 509 | // global_input_filename, 510 | // t->token_string, 511 | // text_buffer, 512 | // line 513 | // ); 514 | return (1); 515 | } 516 | -------------------------------------------------------------------------------- /scan.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __SCAN_H__ 3 | #define __SCAN_H__ 4 | 5 | #include "definations.h" 6 | 7 | int scan(struct Token *t); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /statement.c: -------------------------------------------------------------------------------- 1 | #include "statement.h" 2 | #include "parser.h" 3 | #include "definations.h" 4 | #include "generator.h" 5 | #include "helper.h" 6 | #include "data.h" 7 | #include "symbol_table.h" 8 | #include "ast.h" 9 | #include "scan.h" 10 | #include "declaration.h" 11 | #include "types.h" 12 | 13 | static struct ASTNode *parse_return_statement(); 14 | static struct ASTNode *parse_break_statement() { 15 | // 解析类似 break; 这样的语句 16 | if (loop_level == 0 && switch_level == 0) 17 | error("no loop or switch to break out from"); 18 | scan(&token_from_file); 19 | verify_semicolon(); 20 | return (create_ast_leaf(AST_BREAK, PRIMITIVE_NONE, 0, NULL, NULL)); 21 | } 22 | static struct ASTNode *parse_continue_statement() { 23 | // 解析类似 continue; 这样的语句 24 | if (loop_level == 0) 25 | error("no loop to continue out from"); 26 | scan(&token_from_file); 27 | verify_semicolon(); 28 | return (create_ast_leaf(AST_CONTINUE, PRIMITIVE_NONE, 0, NULL, NULL)); 29 | } 30 | 31 | static struct ASTNode *parse_switch_statement() { 32 | struct ASTNode *left, *node, *c, *case_tree = NULL, *case_tail; 33 | int continue_loop = 1, case_count = 0, case_value, exist_default = 0, ast_operation; 34 | 35 | // 跳过 switch 以及 '(' 36 | scan(&token_from_file); 37 | verify_left_paren(); 38 | 39 | // 拿到 switch 里面的语句,并跳过 ')' 以及 '{' 40 | left = converse_token_2_ast(0); 41 | verify_right_paren(); 42 | verify_left_brace(); 43 | 44 | // 检查 switch 里面语句的结果是一个 int 类型 45 | if (!check_int_type(left->primitive_type)) 46 | error("Switch expression is not of integer type"); 47 | 48 | // 创建一个 AST_SWITCH 的 node 49 | node = create_ast_left_node(AST_SWITCH, 0, left, 0, NULL, NULL); 50 | 51 | // 开始解析 'case' 语句 52 | switch_level++; 53 | while (continue_loop) { 54 | switch(token_from_file.token) { 55 | // 如果是 switch(xxx) {} 这种情况,立刻退出 56 | case TOKEN_RIGHT_BRACE: 57 | if (case_count == 0) 58 | error("No cases in switch"); 59 | continue_loop = 0; 60 | break; 61 | case TOKEN_CASE: 62 | case TOKEN_DEFAULT: 63 | // 先检查 'default' 之后是否还有 'case' 或者 'default' 64 | if (exist_default) 65 | error("case or default after existing default"); 66 | 67 | if (token_from_file.token == TOKEN_DEFAULT) { 68 | ast_operation = AST_DEFAULT; 69 | exist_default = 1; 70 | scan(&token_from_file); 71 | } else { 72 | ast_operation = AST_CASE; 73 | scan(&token_from_file); 74 | 75 | // case a: 76 | left = converse_token_2_ast(0); 77 | 78 | // 检查 case a: 这个 a 是一个 int 类型的字面量 79 | if (left->operation != AST_INTEGER_LITERAL) 80 | error("Expecting integer literal for case value"); 81 | case_value = left->ast_node_integer_value; 82 | 83 | // 遍历所有的 case value 列表,检查是否有重复的 case value 84 | // 比如 case a: 后面又有一个 case a: 85 | for (c = case_tree; c; c = c->right) 86 | if (case_value == c->ast_node_integer_value) 87 | error("Duplicate case value"); 88 | } 89 | 90 | // 跳过 ':' 91 | verify_colon(); 92 | // 同时计算有多少个 case 93 | case_count++; 94 | 95 | // 解析 case a: 里面的复合语句 96 | // 也支持 case a: case b: xxx(); break; 这样的语句 97 | if (token_from_file.token == TOKEN_CASE) { 98 | left = NULL; 99 | } else { 100 | left = parse_compound_statement(1); 101 | } 102 | 103 | // 创建 case tree 104 | if (!case_tree) { 105 | case_tree = case_tail = create_ast_left_node(ast_operation, 0, left, case_value, NULL, NULL); 106 | } else { 107 | case_tail->right = create_ast_left_node(ast_operation, 0, left, case_value, NULL, NULL); 108 | case_tail = case_tail->right; 109 | } 110 | break; 111 | default: 112 | error_with_message("Unexpected token in switch", token_from_file.token_string); 113 | } 114 | } 115 | switch_level--; 116 | 117 | // 解析 case 完之后给初始 node 赋值 118 | node->ast_node_integer_value = case_count; 119 | node->right = case_tree; 120 | 121 | // 跳过 '}' 122 | verify_right_brace(); 123 | 124 | return (node); 125 | } 126 | 127 | static struct ASTNode *parse_single_statement() { 128 | struct SymbolTable *composite_type; 129 | struct ASTNode *statement; 130 | 131 | switch(token_from_file.token) { 132 | // ';' 就是一个空语句 133 | case TOKEN_SEMICOLON: 134 | verify_semicolon(); 135 | break; 136 | case TOKEN_LEFT_BRACE: 137 | verify_left_brace(); 138 | statement = parse_compound_statement(0); 139 | verify_right_brace(); 140 | return (statement); 141 | case TOKEN_IDENTIFIER: 142 | // 检查是否被 typedef 定义过 143 | if (!find_typedef_symbol(text_buffer)) { 144 | statement = converse_token_2_ast(0); 145 | verify_semicolon(); 146 | return (statement); 147 | } 148 | case TOKEN_CHAR: 149 | case TOKEN_INT: 150 | case TOKEN_LONG: 151 | case TOKEN_STRUCT: 152 | case TOKEN_UNION: 153 | case TOKEN_ENUM: 154 | case TOKEN_TYPEDEF: 155 | parse_declaration_list( 156 | &composite_type, 157 | STORAGE_CLASS_LOCAL, 158 | TOKEN_SEMICOLON, 159 | TOKEN_EOF, 160 | &statement); 161 | verify_semicolon(); 162 | return (statement); 163 | case TOKEN_IF: 164 | return (parse_if_statement()); 165 | case TOKEN_WHILE: 166 | return (parse_while_statement()); 167 | case TOKEN_FOR: 168 | return (parse_for_statement()); 169 | case TOKEN_RETURN: 170 | return (parse_return_statement()); 171 | case TOKEN_SWITCH: 172 | return (parse_switch_statement()); 173 | case TOKEN_BREAK: 174 | return (parse_break_statement()); 175 | case TOKEN_CONTINUE: 176 | return (parse_continue_statement()); 177 | default: 178 | statement = converse_token_2_ast(0); 179 | verify_semicolon(); 180 | return (statement); 181 | } 182 | 183 | return (NULL); 184 | } 185 | struct ASTNode *parse_if_statement() { 186 | struct ASTNode *condition_node, *true_node, *false_node = NULL; 187 | 188 | // 解析 statement 中是否有 if( 189 | verify_if(); 190 | verify_left_paren(); 191 | 192 | condition_node = converse_token_2_ast(0); 193 | 194 | // 确保条件语句中出现的是正确的符号 195 | if (condition_node->operation < AST_COMPARE_EQUALS || 196 | condition_node->operation > AST_COMPARE_GREATER_EQUALS) 197 | // 说明是一个条件语句或者是一个 int 数字之类的,将其 bool 化 198 | condition_node = create_ast_left_node( 199 | AST_TO_BE_BOOLEAN, 200 | condition_node->primitive_type, 201 | condition_node, 202 | 0, 203 | NULL, 204 | condition_node->composite_type); 205 | verify_right_paren(); 206 | 207 | // 为复合语句创建 ast 208 | true_node = parse_single_statement(); 209 | 210 | // 如果解析到下一步发现有 else,直接跳过,并同时为复合语句创建 ast 211 | if (token_from_file.token == TOKEN_ELSE) { 212 | scan(&token_from_file); 213 | false_node = parse_single_statement(); 214 | } 215 | 216 | return ( 217 | create_ast_node( 218 | AST_IF, 219 | PRIMITIVE_NONE, 220 | condition_node, 221 | true_node, 222 | false_node, 223 | 0, 224 | NULL, 225 | NULL) 226 | ); 227 | } 228 | 229 | struct ASTNode *parse_while_statement() { 230 | struct ASTNode *condition_node, *statement_node = NULL; 231 | 232 | verify_while(); 233 | verify_left_paren(); 234 | 235 | // 检测 while 中的 条件语句 236 | condition_node = converse_token_2_ast(0); 237 | // 确保条件语句中出现的是正确的符号 238 | if (condition_node->operation < AST_COMPARE_EQUALS || 239 | condition_node->operation > AST_COMPARE_GREATER_EQUALS) 240 | // 说明是一个条件语句或者是一个 int 数字之类的,将其 bool 化 241 | condition_node = create_ast_left_node( 242 | AST_TO_BE_BOOLEAN, 243 | condition_node->primitive_type, 244 | condition_node, 245 | 0, 246 | NULL, 247 | condition_node->composite_type); 248 | 249 | verify_right_paren(); 250 | 251 | // while 里面都是复合语句,所以直接解析即可 252 | 253 | loop_level++; 254 | statement_node = parse_single_statement(); 255 | loop_level--; 256 | return ( 257 | create_ast_node( 258 | AST_WHILE, 259 | PRIMITIVE_NONE, 260 | condition_node, 261 | NULL, 262 | statement_node, 263 | 0, 264 | NULL, 265 | NULL) 266 | ); 267 | } 268 | 269 | struct ASTNode *parse_for_statement() { 270 | struct ASTNode 271 | *condition_node, *statement_node, 272 | *pre_operation_statement_node, *post_operation_statement_node, 273 | *tree = NULL; 274 | 275 | // 解析类似 for (i=1 ; i < 10 ; i= i + 1) print('xxx'); 这样的语法 276 | 277 | // 解析 for( 278 | verify_for(); 279 | verify_left_paren(); 280 | 281 | // 解析 i=1; 282 | pre_operation_statement_node = parse_expression_list(TOKEN_SEMICOLON); 283 | verify_semicolon(); 284 | 285 | // 解析 i < 10; 286 | condition_node = converse_token_2_ast(0); 287 | // 确保条件语句中出现的是正确的符号 288 | if (condition_node->operation < AST_COMPARE_EQUALS || 289 | condition_node->operation > AST_COMPARE_GREATER_EQUALS) 290 | // 说明是一个条件语句或者是一个 int 数字之类的,将其 bool 化 291 | condition_node = create_ast_left_node( 292 | AST_TO_BE_BOOLEAN, 293 | condition_node->primitive_type, 294 | condition_node, 295 | 0, 296 | NULL, 297 | condition_node->composite_type); 298 | verify_semicolon(); 299 | 300 | // 解析 i = i+1) 301 | post_operation_statement_node = parse_expression_list(TOKEN_RIGHT_PAREN); 302 | verify_right_paren(); 303 | 304 | // 解析 for 语句块里面的 stmt 305 | loop_level++; 306 | statement_node = parse_single_statement(); 307 | loop_level--; 308 | 309 | // 递归构建 for ast 310 | // for 语句的 ast 结构如下 311 | // AST_GLUE 312 | // / \ 313 | // preop AST_WHILE 314 | // / \ 315 | // true_or_false_condition AST_GLUE 316 | // / \ 317 | // compound_stmt postop 318 | tree = create_ast_node(AST_GLUE, PRIMITIVE_NONE, statement_node, NULL, post_operation_statement_node, 0, NULL, NULL); 319 | tree = create_ast_node(AST_WHILE, PRIMITIVE_NONE, condition_node, NULL, tree, 0, NULL, NULL); 320 | return (create_ast_node(AST_GLUE, PRIMITIVE_NONE, pre_operation_statement_node, NULL, tree, 0, NULL, NULL)); 321 | } 322 | 323 | static struct ASTNode *parse_return_statement() { 324 | struct ASTNode *tree = NULL; 325 | int has_paren = 0; 326 | 327 | verify_return(); 328 | 329 | if (token_from_file.token == TOKEN_LEFT_PAREN) { 330 | has_paren = 1; 331 | 332 | if (current_function_symbol_id->primitive_type == PRIMITIVE_VOID) 333 | error("Can't return from a void function"); 334 | 335 | verify_left_paren(); 336 | // 解析 return 中间的语句 337 | tree = converse_token_2_ast(0); 338 | // 检查 return type 和 function type 是否兼容 339 | tree = modify_type(tree, current_function_symbol_id->primitive_type, 0, current_function_symbol_id->composite_type); 340 | 341 | if (!tree) // 不允许强制转换 342 | error("Incompatible types to return"); 343 | 344 | // 检查 ) 345 | verify_right_paren(); 346 | } 347 | 348 | // 生成 return_statement 的 node 349 | tree = create_ast_left_node(AST_RETURN, PRIMITIVE_NONE, tree, 0, NULL, NULL); 350 | 351 | if (!has_paren) { 352 | // 这里有两种情况 353 | // 看下一个 token 是不是 ; 354 | // 是就直接 verify semi 355 | // 目前仅支持 'return;' 以及 'return x;' 或者 'return 0;' 356 | // 这种情况 357 | if (token_from_file.token != TOKEN_SEMICOLON) { 358 | // 不是就 scan 359 | scan(&token_from_file); 360 | } 361 | } 362 | 363 | verify_semicolon(); 364 | return (tree); 365 | } 366 | 367 | /** 368 | * 语句(statement) 的 BNF 为 369 | * compound_statement: '{' '}' 370 | * | '{' statement '}' 371 | * | '{' statement statements '}' 372 | * ; 373 | * 374 | * statements: statement 375 | * | statement statements 376 | * ; 377 | * 378 | * statement: print_statement 379 | * | declaration_statement 380 | * | assignment_statement 381 | * | if_statement 382 | * ; 383 | * 384 | * print_statement: 'print' expression ';' 385 | * ; 386 | * 387 | * assignment_statement: identifier '=' expression ';' 388 | * ; 389 | * 390 | * if_statement: if_head 391 | * | if_head 'else' compound_statement 392 | * ; 393 | * 394 | * while_statement: 'while' '(' true_or_false_expression ')' compound_statement 395 | * 396 | * for_statement: 'for' '(' 397 | * expression_list ';' 398 | * true_or_false_expression ';' 399 | * expression_list ')' compound_statement 400 | * ; 401 | * 402 | * pre_operation_statement: statement 403 | * ; 404 | * post_operation_statement: statement 405 | * ; 406 | * 407 | * if_head: 'if' '(' true_or_false_expression ')' compound_statement 408 | * ; 409 | * 410 | * 411 | * global_declarations: global_declarations 412 | * | global_declaration global_declarations 413 | * ; 414 | * 415 | * global_declaration: function_declaration 416 | * | var_declaration 417 | * ; 418 | * 419 | * function_declaration: type identifier '(' ')' compound_statement 420 | * ; 421 | * 422 | * var_declaration: type identifier_list ';' 423 | * ; 424 | * 425 | * type: type_keyword operation_pointer 426 | * ; 427 | * 428 | * type_keyword: 'void' | 'char' | 'int' | 'long' 429 | * ; 430 | * 431 | * operation_pointer: | '*' opt_pointer 432 | * ; 433 | * 434 | * identifier_list: identifier 435 | * | identifier ',' identifier_list 436 | * ; 437 | * 438 | * function_call: identifier '(' expression ')' 439 | * ; 440 | * 441 | * return_statement: 'return' '(' expression ')' 442 | * ; 443 | * 444 | * identifier: TOKEN_IDENTIFIER 445 | * ; 446 | */ 447 | struct ASTNode *parse_compound_statement(int in_switch_statement) { 448 | struct ASTNode *left = NULL; 449 | struct ASTNode *tree; 450 | 451 | while (1) { 452 | // 可以允许 {} 里面的空语句 453 | if (token_from_file.token == TOKEN_RIGHT_BRACE) return (left); 454 | if (in_switch_statement && ( 455 | token_from_file.token == TOKEN_CASE || 456 | token_from_file.token == TOKEN_DEFAULT 457 | )) return (left); 458 | 459 | // 这里主要兼容对 for 语句的处理 460 | tree = parse_single_statement(); 461 | 462 | // 如果 tree 不为空,则更新对应的 left 463 | // 变成如下的形式 464 | // AST_GLUE 465 | // / \ 466 | // AST_GLUE stmt4 467 | // / \ 468 | // AST_GLUE stmt3 469 | // / \ 470 | // stmt1 stmt2 471 | if (tree) { 472 | if (left != NULL) { 473 | left = create_ast_node(AST_GLUE, PRIMITIVE_NONE, left, NULL, tree, 0, NULL, NULL); 474 | } else { 475 | left = tree; 476 | } 477 | } 478 | } 479 | 480 | return (NULL); 481 | } 482 | -------------------------------------------------------------------------------- /statement.h: -------------------------------------------------------------------------------- 1 | #ifndef __STATEMENT_H__ 2 | #define __STATEMENT_H__ 3 | 4 | #include "definations.h" 5 | 6 | struct ASTNode *parse_if_statement(); 7 | struct ASTNode *parse_while_statement(); 8 | struct ASTNode *parse_for_statement(); 9 | struct ASTNode *parse_compound_statement(int in_switch_statement); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /symbol_table.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "helper.h" 4 | #include "data.h" 5 | #include "generator.h" 6 | #include "symbol_table.h" 7 | #include "definations.h" 8 | #include "types.h" 9 | 10 | static struct SymbolTable *add_symbol_core( 11 | char *symbol_string, 12 | int primitive_type, 13 | int structural_type, 14 | int size, 15 | int storage_class, 16 | int position, 17 | struct SymbolTable** head, 18 | struct SymbolTable** tail, 19 | struct SymbolTable *composite_type 20 | ) { 21 | struct SymbolTable *t = new_symbol_table( 22 | symbol_string, 23 | primitive_type, 24 | structural_type, 25 | size, 26 | storage_class, 27 | position, 28 | composite_type 29 | ); 30 | // size: 变量里面所有元素的【大小】 31 | // element_number: 变量里面所有元素的【个数】 32 | if ((primitive_type == PRIMITIVE_STRUCT || 33 | primitive_type == PRIMITIVE_UNION) && 34 | composite_type) 35 | t->size = composite_type->size; 36 | append_to_symbol_table(head, tail, t); 37 | return (t); 38 | } 39 | 40 | static struct SymbolTable *find_symbol_in_list( 41 | char *symbol_string, 42 | struct SymbolTable *list, 43 | int storage_class 44 | ) { 45 | for (; list; list = list->next) { 46 | if (list->name && (!strcmp(symbol_string, list->name))) 47 | if (!storage_class || storage_class == list->storage_class) 48 | return (list); 49 | } 50 | return (NULL); 51 | } 52 | 53 | struct SymbolTable *find_global_symbol(char *symbol_string) { 54 | return (find_symbol_in_list(symbol_string, global_head, 0)); 55 | } 56 | 57 | struct SymbolTable *find_local_symbol(char *symbol_string) { 58 | struct SymbolTable *node; 59 | // 优先判断是否在函数体内,如果是则寻找 parameter 60 | if (current_function_symbol_id) { 61 | node = find_symbol_in_list(symbol_string, current_function_symbol_id->member, 0); 62 | if (node) return (node); 63 | } 64 | return (find_symbol_in_list(symbol_string, local_head, 0)); 65 | } 66 | 67 | struct SymbolTable *find_composite_symbol(char *symbol_string) { 68 | return (find_symbol_in_list(symbol_string, composite_head, 0)); 69 | } 70 | 71 | struct SymbolTable *find_temp_member_symbol(char *symbol_string) { 72 | return (find_symbol_in_list(symbol_string, temp_member_head, 0)); 73 | } 74 | 75 | struct SymbolTable *find_struct_symbol(char *symbol_string) { 76 | return (find_symbol_in_list(symbol_string, struct_head, 0)); 77 | } 78 | 79 | struct SymbolTable *find_union_symbol(char *symbol_string) { 80 | return (find_symbol_in_list(symbol_string, union_head, 0)); 81 | } 82 | 83 | struct SymbolTable *find_enum_type_symbol(char *symbol_string) { 84 | return (find_symbol_in_list(symbol_string, enum_head, STORAGE_CLASS_ENUM_TYPE)); 85 | } 86 | 87 | struct SymbolTable *find_enum_value_symbol(char *symbol_string) { 88 | return (find_symbol_in_list(symbol_string, enum_head, STORAGE_CLASS_ENUM_VALUE)); 89 | } 90 | 91 | struct SymbolTable *find_typedef_symbol(char *symbol_string) { 92 | return (find_symbol_in_list(symbol_string, typedef_head, 0)); 93 | } 94 | 95 | struct SymbolTable *find_symbol(char *symbol_string) { 96 | struct SymbolTable *node = find_local_symbol(symbol_string); 97 | if (node) return (node); 98 | return (find_global_symbol(symbol_string)); 99 | } 100 | 101 | void append_to_symbol_table( 102 | struct SymbolTable **head, 103 | struct SymbolTable **tail, 104 | struct SymbolTable *node 105 | ) { 106 | if (!head || !tail || !node) 107 | error("Either head, tail or node is NULL in append_to_symbol_table"); 108 | 109 | if (*tail) { 110 | (*tail)->next = node; 111 | *tail = node; 112 | } else 113 | *head = *tail = node; 114 | 115 | node->next = NULL; 116 | } 117 | 118 | /** 119 | * new 一个新的 symbol table 120 | */ 121 | struct SymbolTable *new_symbol_table( 122 | char *name, 123 | int primitive_type, 124 | int structural_type, 125 | int element_number, 126 | int storage_class, 127 | int position, 128 | struct SymbolTable *composite_type 129 | ) { 130 | struct SymbolTable *node = (struct SymbolTable *) malloc(sizeof(struct SymbolTable)); 131 | if (!node) 132 | error("Unable to malloc a symbol table node in update_symbol_table"); 133 | 134 | if (name == NULL || !name) 135 | node->name = NULL; 136 | else 137 | node->name = strdup(name); 138 | node->primitive_type = primitive_type; 139 | node->structural_type = structural_type; 140 | node->element_number = element_number; 141 | 142 | // 对于 指针 和 int 类型变量才去设置它们的 size 143 | // 对于 struct/union 类型变量,手动设置它们的 size 144 | if (check_pointer_type(primitive_type) || 145 | check_int_type(primitive_type)) 146 | node->size = element_number 147 | * get_primitive_type_size(primitive_type, composite_type); 148 | 149 | node->storage_class = storage_class; 150 | node->symbol_table_position = position; 151 | node->composite_type = composite_type; 152 | node->next = NULL; 153 | node->member = NULL; 154 | node->init_value_list = NULL; 155 | 156 | return (node); 157 | } 158 | struct SymbolTable *add_global_symbol( 159 | char *symbol_string, 160 | int primitive_type, 161 | int structural_type, 162 | int element_number, 163 | int storage_class, 164 | struct SymbolTable *composite_type, 165 | int position 166 | ) { 167 | return ( 168 | add_symbol_core( 169 | symbol_string, 170 | primitive_type, 171 | structural_type, 172 | element_number, 173 | storage_class, 174 | position, 175 | &global_head, 176 | &global_tail, 177 | composite_type 178 | ) 179 | ); 180 | } 181 | struct SymbolTable *add_local_symbol( 182 | char *symbol_string, 183 | int primitive_type, 184 | int structural_type, 185 | int size, 186 | struct SymbolTable *composite_type 187 | ) { 188 | return ( 189 | add_symbol_core( 190 | symbol_string, 191 | primitive_type, 192 | structural_type, 193 | size, 194 | STORAGE_CLASS_LOCAL, 195 | 0, 196 | &local_head, 197 | &local_tail, 198 | composite_type 199 | ) 200 | ); 201 | } 202 | 203 | struct SymbolTable *add_parameter_symbol( 204 | char *symbol_string, 205 | int primitive_type, 206 | int structural_type, 207 | struct SymbolTable *composite_type 208 | ) { 209 | return ( 210 | add_symbol_core( 211 | symbol_string, 212 | primitive_type, 213 | structural_type, 214 | 1, 215 | STORAGE_CLASS_FUNCTION_PARAMETER, 216 | 0, 217 | ¶meter_head, 218 | ¶meter_tail, 219 | composite_type 220 | ) 221 | ); 222 | } 223 | 224 | struct SymbolTable *add_temp_member_symbol( 225 | char *symbol_string, 226 | int primitive_type, 227 | int structural_type, 228 | int size, 229 | struct SymbolTable *composite_type 230 | ) { 231 | return ( 232 | add_symbol_core( 233 | symbol_string, 234 | primitive_type, 235 | structural_type, 236 | size, 237 | STORAGE_CLASS_MEMBER, 238 | 0, 239 | &temp_member_head, 240 | &temp_member_tail, 241 | composite_type 242 | ) 243 | ); 244 | } 245 | struct SymbolTable *add_struct_symbol(char *symbol_string) { 246 | return ( 247 | add_symbol_core( 248 | symbol_string, 249 | PRIMITIVE_STRUCT, 250 | 0, 251 | 0, 252 | STORAGE_CLASS_STRUCT, 253 | 0, 254 | &struct_head, 255 | &struct_tail, 256 | NULL 257 | ) 258 | ); 259 | } 260 | struct SymbolTable *add_union_symbol(char *symbol_string) { 261 | return ( 262 | add_symbol_core( 263 | symbol_string, 264 | PRIMITIVE_UNION, 265 | 0, 266 | 0, 267 | STORAGE_CLASS_UNION, 268 | 0, 269 | &union_head, 270 | &union_tail, 271 | NULL 272 | ) 273 | ); 274 | } 275 | 276 | struct SymbolTable *add_enum_symbol( 277 | char *symbol_string, 278 | int storage_class, 279 | int value 280 | ) { 281 | return ( 282 | add_symbol_core( 283 | symbol_string, 284 | PRIMITIVE_INT, 285 | 0, 286 | 0, 287 | storage_class, 288 | value, 289 | &enum_head, 290 | &enum_tail, 291 | NULL 292 | ) 293 | ); 294 | } 295 | 296 | struct SymbolTable *add_typedef_symbol( 297 | char *symbol_string, 298 | int primitive_type, 299 | int structural_type, 300 | int size, 301 | struct SymbolTable *composite_type 302 | ) { 303 | return ( 304 | add_symbol_core( 305 | symbol_string, 306 | primitive_type, 307 | structural_type, 308 | size, 309 | STORAGE_CLASS_TYPEDEF, 310 | 0, 311 | &typedef_head, 312 | &typedef_tail, 313 | composite_type 314 | ) 315 | ); 316 | } 317 | 318 | void clear_all_symbol_tables() { 319 | global_head = global_tail = NULL; 320 | local_head = local_tail = NULL; 321 | parameter_head = parameter_tail = NULL; 322 | composite_head = composite_tail = NULL; 323 | temp_member_head = temp_member_tail = NULL; 324 | struct_head = struct_tail = NULL; 325 | union_head = union_tail = NULL; 326 | enum_head = enum_tail = NULL; 327 | typedef_head = typedef_tail = NULL; 328 | } 329 | 330 | void clear_local_symbol_table() { 331 | local_head = local_tail = NULL; 332 | parameter_head = parameter_tail = NULL; 333 | current_function_symbol_id = NULL; 334 | } 335 | -------------------------------------------------------------------------------- /symbol_table.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYMBOL_TABLE_H__ 2 | #define __SYMBOL_TABLE_H__ 3 | 4 | struct SymbolTable *find_global_symbol(char *symbol_string); 5 | struct SymbolTable *find_local_symbol(char *symbol_string); 6 | struct SymbolTable *find_composite_symbol(char *symbol_string); 7 | struct SymbolTable *find_temp_member_symbol(char *symbol_string); 8 | struct SymbolTable *find_struct_symbol(char *symbol_string); 9 | struct SymbolTable *find_union_symbol(char *symbol_string); 10 | struct SymbolTable *find_enum_type_symbol(char *symbol_string); 11 | struct SymbolTable *find_enum_value_symbol(char *symbol_string); 12 | struct SymbolTable *find_typedef_symbol(char *symbol_string); 13 | struct SymbolTable *find_symbol(char *symbol_string); 14 | 15 | void append_to_symbol_table( 16 | struct SymbolTable **head, 17 | struct SymbolTable **tail, 18 | struct SymbolTable *node 19 | ); 20 | 21 | struct SymbolTable *new_symbol_table( 22 | char *name, 23 | int primitive_type, 24 | int structural_type, 25 | int element_number, 26 | int storage_class, 27 | int position, 28 | struct SymbolTable *composite_type 29 | ); 30 | struct SymbolTable *add_global_symbol( 31 | char *symbol_string, 32 | int primitive_type, 33 | int structural_type, 34 | int element_number, 35 | int storage_class, 36 | struct SymbolTable *composite_type, 37 | int position 38 | ); 39 | struct SymbolTable *add_local_symbol( 40 | char *symbol_string, 41 | int primitive_type, 42 | int structural_type, 43 | int size, 44 | struct SymbolTable *composite_type 45 | ); 46 | struct SymbolTable *add_parameter_symbol( 47 | char *symbol_string, 48 | int primitive_type, 49 | int structural_type, 50 | struct SymbolTable *composite_type 51 | ); 52 | struct SymbolTable *add_temp_member_symbol( 53 | char *symbol_string, 54 | int primitive_type, 55 | int structural_type, 56 | int size, 57 | struct SymbolTable *composite_type 58 | ); 59 | struct SymbolTable *add_struct_symbol(char *symbol_string); 60 | struct SymbolTable *add_union_symbol(char *symbol_string); 61 | struct SymbolTable *add_enum_symbol( 62 | char *symbol_string, 63 | int storage_class, 64 | int value 65 | ); 66 | struct SymbolTable *add_typedef_symbol( 67 | char *symbol_string, 68 | int primitive_type, 69 | int structural_type, 70 | int size, 71 | struct SymbolTable *composite_type 72 | ); 73 | void clear_all_symbol_tables(); 74 | void clear_local_symbol_table(); 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /test/assert/out.input001.zc: -------------------------------------------------------------------------------- 1 | 36 2 | 10 3 | 25 4 | -------------------------------------------------------------------------------- /test/assert/out.input002.zc: -------------------------------------------------------------------------------- 1 | 17 2 | -------------------------------------------------------------------------------- /test/assert/out.input003.zc: -------------------------------------------------------------------------------- 1 | 1 2 | 2 3 | 3 4 | 4 5 | 5 6 | -------------------------------------------------------------------------------- /test/assert/out.input004.zc: -------------------------------------------------------------------------------- 1 | 1 2 | 1 3 | 1 4 | 1 5 | 1 6 | 1 7 | 1 8 | 1 9 | 1 10 | -------------------------------------------------------------------------------- /test/assert/out.input005.zc: -------------------------------------------------------------------------------- 1 | 6 2 | -------------------------------------------------------------------------------- /test/assert/out.input006.zc: -------------------------------------------------------------------------------- 1 | 1 2 | 2 3 | 3 4 | 4 5 | 5 6 | 6 7 | 7 8 | 8 9 | 9 10 | 10 11 | -------------------------------------------------------------------------------- /test/assert/out.input007.zc: -------------------------------------------------------------------------------- 1 | 1 2 | 2 3 | 3 4 | 4 5 | 5 6 | 6 7 | 7 8 | 8 9 | 9 10 | 10 11 | -------------------------------------------------------------------------------- /test/assert/out.input008.zc: -------------------------------------------------------------------------------- 1 | 1 2 | 2 3 | 3 4 | 4 5 | 5 6 | 6 7 | 7 8 | 8 9 | 9 10 | 10 11 | -------------------------------------------------------------------------------- /test/assert/out.input009.zc: -------------------------------------------------------------------------------- 1 | 1 2 | 2 3 | 3 4 | 4 5 | 5 6 | 6 7 | 7 8 | 8 9 | 9 10 | 10 11 | -------------------------------------------------------------------------------- /test/assert/out.input010.zc: -------------------------------------------------------------------------------- 1 | 20 2 | 10 3 | 1 4 | 2 5 | 3 6 | 4 7 | 5 8 | 253 9 | 254 10 | 255 11 | 0 12 | 1 13 | -------------------------------------------------------------------------------- /test/assert/out.input011.zc: -------------------------------------------------------------------------------- 1 | 10 2 | 20 3 | 30 4 | 1 5 | 2 6 | 3 7 | 4 8 | 5 9 | 253 10 | 254 11 | 255 12 | 0 13 | 1 14 | 2 15 | 3 16 | 1 17 | 2 18 | 3 19 | 4 20 | 5 21 | -------------------------------------------------------------------------------- /test/assert/out.input012.zc: -------------------------------------------------------------------------------- 1 | 5 2 | -------------------------------------------------------------------------------- /test/assert/out.input013.zc: -------------------------------------------------------------------------------- 1 | 23 2 | 56 3 | -------------------------------------------------------------------------------- /test/assert/out.input014.zc: -------------------------------------------------------------------------------- 1 | 10 2 | 20 3 | 30 4 | -------------------------------------------------------------------------------- /test/assert/out.input015.zc: -------------------------------------------------------------------------------- 1 | 18 2 | 18 3 | 12 4 | 12 5 | -------------------------------------------------------------------------------- /test/assert/out.input016.zc: -------------------------------------------------------------------------------- 1 | 12 2 | 18 3 | -------------------------------------------------------------------------------- /test/assert/out.input017.zc: -------------------------------------------------------------------------------- 1 | 19 2 | 12 3 | -------------------------------------------------------------------------------- /test/assert/out.input018.zc: -------------------------------------------------------------------------------- 1 | 34 2 | 34 3 | -------------------------------------------------------------------------------- /test/assert/out.input019.zc: -------------------------------------------------------------------------------- 1 | 30 2 | -------------------------------------------------------------------------------- /test/assert/out.input020.zc: -------------------------------------------------------------------------------- 1 | 12 2 | -------------------------------------------------------------------------------- /test/assert/out.input021.zc: -------------------------------------------------------------------------------- 1 | 10 2 | Hello world 3 | -------------------------------------------------------------------------------- /test/assert/out.input022.zc: -------------------------------------------------------------------------------- 1 | 12 2 | 12 3 | 12 4 | 13 5 | 13 6 | 13 7 | 13 8 | 13 9 | 13 10 | 35 11 | 35 12 | 35 13 | -------------------------------------------------------------------------------- /test/assert/out.input023.zc: -------------------------------------------------------------------------------- 1 | -23 2 | 100 3 | -2 4 | 0 5 | 1 6 | 0 7 | 13 8 | 14 9 | Hello world 10 | -------------------------------------------------------------------------------- /test/assert/out.input024.zc: -------------------------------------------------------------------------------- 1 | 2 2 | 59 3 | 57 4 | 8 5 | 7 6 | -------------------------------------------------------------------------------- /test/assert/out.input025.zc: -------------------------------------------------------------------------------- 1 | 10 2 | 20 3 | 30 4 | 5 5 | 15 6 | 25 7 | -------------------------------------------------------------------------------- /test/assert/out.input026.zc: -------------------------------------------------------------------------------- 1 | 13 2 | 23 3 | 34 4 | 44 5 | 54 6 | 64 7 | 74 8 | 84 9 | 94 10 | 95 11 | 96 12 | -------------------------------------------------------------------------------- /test/assert/out.input027.zc: -------------------------------------------------------------------------------- 1 | 1 2 | 2 3 | 3 4 | 4 5 | 5 6 | 6 7 | 7 8 | 8 9 | 1 10 | 2 11 | 3 12 | 4 13 | 5 14 | 1 15 | 2 16 | 3 17 | 4 18 | 5 19 | 1 20 | 2 21 | 3 22 | 4 23 | 5 24 | -------------------------------------------------------------------------------- /test/assert/out.input028.zc: -------------------------------------------------------------------------------- 1 | 1 2 | 2 3 | 3 4 | 5 5 | 8 6 | 13 7 | 21 8 | 34 9 | 9 10 | -------------------------------------------------------------------------------- /test/assert/out.input029.zc: -------------------------------------------------------------------------------- 1 | 1 2 | 2 3 | 3 4 | 5 5 | 8 6 | 13 7 | 21 8 | 34 9 | 9 10 | -------------------------------------------------------------------------------- /test/assert/out.input030.zc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strugglebak/zcc/475906dc2b3faffd3ffa437e7e9cfd9fa76d115d/test/assert/out.input030.zc -------------------------------------------------------------------------------- /test/assert/out.input053.zc: -------------------------------------------------------------------------------- 1 | Hello world, 23 2 | -------------------------------------------------------------------------------- /test/assert/out.input054.zc: -------------------------------------------------------------------------------- 1 | Hello world, 0 2 | Hello world, 1 3 | Hello world, 2 4 | Hello world, 3 5 | Hello world, 4 6 | Hello world, 5 7 | Hello world, 6 8 | Hello world, 7 9 | Hello world, 8 10 | Hello world, 9 11 | Hello world, 10 12 | Hello world, 11 13 | Hello world, 12 14 | Hello world, 13 15 | Hello world, 14 16 | Hello world, 15 17 | Hello world, 16 18 | Hello world, 17 19 | Hello world, 18 20 | Hello world, 19 21 | -------------------------------------------------------------------------------- /test/assert/out.input055.zc: -------------------------------------------------------------------------------- 1 | Hello world 2 | Argument 0 is ./out 3 | -------------------------------------------------------------------------------- /test/assert/out.input058.zc: -------------------------------------------------------------------------------- 1 | 12 2 | 99 3 | 4005 4 | 4116 5 | 4116 6 | -------------------------------------------------------------------------------- /test/assert/out.input062.zc: -------------------------------------------------------------------------------- 1 | 65 2 | 66 3 | 66 4 | The next two depend on the endian of the platform 5 | 66 6 | 66 7 | 67 8 | 67 9 | -------------------------------------------------------------------------------- /test/assert/out.input063.zc: -------------------------------------------------------------------------------- 1 | 25 2 | -------------------------------------------------------------------------------- /test/assert/out.input067.zc: -------------------------------------------------------------------------------- 1 | 5 2 | 17 3 | -------------------------------------------------------------------------------- /test/assert/out.input070.zc: -------------------------------------------------------------------------------- 1 | 56 2 | -------------------------------------------------------------------------------- /test/assert/out.input071.zc: -------------------------------------------------------------------------------- 1 | 0 2 | 1 3 | 2 4 | 3 5 | 4 6 | 7 7 | 8 8 | 9 9 | 10 10 | 11 11 | 12 12 | 13 13 | 14 14 | Done 15 | -------------------------------------------------------------------------------- /test/assert/out.input074.zc: -------------------------------------------------------------------------------- 1 | 100 2 | 5 3 | 7 4 | 100 5 | 100 6 | -------------------------------------------------------------------------------- /test/assert/out.input080.zc: -------------------------------------------------------------------------------- 1 | 0 1 2 | 1 3 3 | 2 5 4 | 3 7 5 | 4 9 6 | 5 11 7 | -------------------------------------------------------------------------------- /test/assert/out.input081.zc: -------------------------------------------------------------------------------- 1 | 0 1 2 | 1 3 3 | 2 5 4 | 3 7 5 | 4 9 6 | -------------------------------------------------------------------------------- /test/assert/out.input082.zc: -------------------------------------------------------------------------------- 1 | 15 >= x > 5 2 | -------------------------------------------------------------------------------- /test/assert/out.input083.zc: -------------------------------------------------------------------------------- 1 | 5 < 6 <= 10 2 | 5 < 7 <= 10 3 | 5 < 8 <= 10 4 | 5 < 9 <= 10 5 | 5 < 10 <= 10 6 | 10 < 11 7 | -------------------------------------------------------------------------------- /test/assert/out.input084.zc: -------------------------------------------------------------------------------- 1 | 2 3 2 | f f 3 | -------------------------------------------------------------------------------- /test/assert/out.input088.zc: -------------------------------------------------------------------------------- 1 | 5 6 2 | -------------------------------------------------------------------------------- /test/assert/out.input089.zc: -------------------------------------------------------------------------------- 1 | 23 H Hello world 2 | -------------------------------------------------------------------------------- /test/assert/out.input090.zc: -------------------------------------------------------------------------------- 1 | 23 100 H Hello world 2 | -------------------------------------------------------------------------------- /test/assert/out.input091.zc: -------------------------------------------------------------------------------- 1 | 1 2 | 2 3 | 3 4 | 4 5 | 5 6 | 1 7 | 2 8 | 3 9 | 4 10 | 5 11 | 0 12 | 0 13 | 0 14 | 0 15 | 0 16 | -------------------------------------------------------------------------------- /test/assert/out.input099.zc: -------------------------------------------------------------------------------- 1 | EOF 2 | = 3 | || 4 | && 5 | | 6 | ^ 7 | & 8 | == 9 | != 10 | , 11 | > 12 | <= 13 | >= 14 | << 15 | >> 16 | + 17 | - 18 | * 19 | / 20 | ++ 21 | -- 22 | ~ 23 | ! 24 | void 25 | char 26 | int 27 | long 28 | if 29 | else 30 | while 31 | for 32 | return 33 | struct 34 | union 35 | enum 36 | typedef 37 | extern 38 | break 39 | continue 40 | switch 41 | case 42 | default 43 | intlit 44 | strlit 45 | ; 46 | identifier 47 | { 48 | } 49 | ( 50 | ) 51 | [ 52 | ] 53 | , 54 | . 55 | -> 56 | : 57 | -------------------------------------------------------------------------------- /test/assert/out.input100.zc: -------------------------------------------------------------------------------- 1 | Hello world 17 20 2 | -------------------------------------------------------------------------------- /test/assert/out.input101.zc: -------------------------------------------------------------------------------- 1 | 0xff 2 | 0x0 3 | -------------------------------------------------------------------------------- /test/assert/out.input106.zc: -------------------------------------------------------------------------------- 1 | 0x0 2 | -------------------------------------------------------------------------------- /test/assert/out.input107.zc: -------------------------------------------------------------------------------- 1 | fish 2 | cow 3 | NULL 4 | -------------------------------------------------------------------------------- /test/assert/out.input108.zc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strugglebak/zcc/475906dc2b3faffd3ffa437e7e9cfd9fa76d115d/test/assert/out.input108.zc -------------------------------------------------------------------------------- /test/assert/out.input109.zc: -------------------------------------------------------------------------------- 1 | 16 2 | -------------------------------------------------------------------------------- /test/assert/out.input110.zc: -------------------------------------------------------------------------------- 1 | 18 2 | 12 3 | 45 4 | 5 5 | -------------------------------------------------------------------------------- /test/assert/out.input111.zc: -------------------------------------------------------------------------------- 1 | 2029 2 | -------------------------------------------------------------------------------- /test/assert/out.input112.zc: -------------------------------------------------------------------------------- 1 | 16 2 | -------------------------------------------------------------------------------- /test/assert/out.input113.zc: -------------------------------------------------------------------------------- 1 | fred says hello 2 | -------------------------------------------------------------------------------- /test/assert/out.input114.zc: -------------------------------------------------------------------------------- 1 | J 2 | -------------------------------------------------------------------------------- /test/assert/out.input115.zc: -------------------------------------------------------------------------------- 1 | 1 2 | 4 3 | 8 4 | 8 5 | 13 6 | 64 7 | 48 8 | -------------------------------------------------------------------------------- /test/assert/out.input116.zc: -------------------------------------------------------------------------------- 1 | 0 2 | 1 3 | 2 4 | 3 5 | 4 6 | -------------------------------------------------------------------------------- /test/assert/out.input117.zc: -------------------------------------------------------------------------------- 1 | Hello 2 | -------------------------------------------------------------------------------- /test/assert/out.input119.zc: -------------------------------------------------------------------------------- 1 | 8 2 | 6 3 | -------------------------------------------------------------------------------- /test/assert/out.input120.zc: -------------------------------------------------------------------------------- 1 | 9 2 | 10 3 | 11 4 | 12 5 | 13 6 | 7 7 | 8 8 | 9 9 | 10 10 | 11 11 | -------------------------------------------------------------------------------- /test/assert/out.input121.zc: -------------------------------------------------------------------------------- 1 | 2 2 | 3 3 | 4 4 | 5 5 | 13 6 | 14 7 | 15 8 | 16 9 | 1000 10 | 1000 11 | -------------------------------------------------------------------------------- /test/assert/out.input122.zc: -------------------------------------------------------------------------------- 1 | x 0, y 0, x || y 0, x && y 0 2 | x 0, y 1, x || y 1, x && y 0 3 | x 1, y 0, x || y 1, x && y 0 4 | x 1, y 1, x || y 1, x && y 1 5 | -------------------------------------------------------------------------------- /test/assert/out.input123.zc: -------------------------------------------------------------------------------- 1 | 0 infant composite 2 | 1 infant composite 3 | 2 infant prime 4 | 3 infant prime 5 | 4 infant composite 6 | 5 infant prime 7 | 6 infant composite 8 | 7 infant prime 9 | 8 infant composite 10 | 9 infant composite 11 | 10 infant composite 12 | 11 infant prime 13 | 12 infant composite 14 | 13 teen prime 15 | 14 teen composite 16 | 15 teen composite 17 | 16 teen composite 18 | 17 teen prime 19 | 18 teen composite 20 | 19 teen prime 21 | -------------------------------------------------------------------------------- /test/assert/out.input125.zc: -------------------------------------------------------------------------------- 1 | 2008 2 | 2008 3 | -------------------------------------------------------------------------------- /test/assert/out.input127.zc: -------------------------------------------------------------------------------- 1 | 2008 2 | 2008 3 | -------------------------------------------------------------------------------- /test/assert/out.input128.zc: -------------------------------------------------------------------------------- 1 | 10 10 2 | 15 15 3 | 20 20 4 | -------------------------------------------------------------------------------- /test/assert/out.input130.zc: -------------------------------------------------------------------------------- 1 | Hello world 2 | -------------------------------------------------------------------------------- /test/assert/out.input131.zc: -------------------------------------------------------------------------------- 1 | Doing nothing... nothing done 2 | x is now 100 3 | -------------------------------------------------------------------------------- /test/assert/out.input132.zc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strugglebak/zcc/475906dc2b3faffd3ffa437e7e9cfd9fa76d115d/test/assert/out.input132.zc -------------------------------------------------------------------------------- /test/assert/out.input133.zc: -------------------------------------------------------------------------------- 1 | OK 2 | -------------------------------------------------------------------------------- /test/assert/out.input134.zc: -------------------------------------------------------------------------------- 1 | 1st match 2 | -------------------------------------------------------------------------------- /test/assert/out.input135.zc: -------------------------------------------------------------------------------- 1 | testing x 2 | -------------------------------------------------------------------------------- /test/assert/out.input136.zc: -------------------------------------------------------------------------------- 1 | -35 2 | -------------------------------------------------------------------------------- /test/assert/out.input137.zc: -------------------------------------------------------------------------------- 1 | x is 36 2 | -------------------------------------------------------------------------------- /test/assert/out.input138.zc: -------------------------------------------------------------------------------- 1 | 0 0 | 0 2 | 0 1 | 0 3 | 1 0 | 0 4 | 1 1 | 1 5 | 0 0 | 0 6 | 0 1 | 1 7 | 1 0 | 1 8 | 1 1 | 1 9 | aptr is NULL or doesn't point at 1 10 | aptr points at 1 11 | -------------------------------------------------------------------------------- /test/assert/out.input139.zc: -------------------------------------------------------------------------------- 1 | same apparently 2 | -------------------------------------------------------------------------------- /test/assert/out.input140.zc: -------------------------------------------------------------------------------- 1 | 0 2 | 1 3 | 4 4 | 9 5 | 16 6 | 5 H 7 | -------------------------------------------------------------------------------- /test/assert/out.input143.zc: -------------------------------------------------------------------------------- 1 | One of the three is NULL 2 | One of the three is NULL 3 | One of the three is NULL 4 | All three are non-NULL 5 | -------------------------------------------------------------------------------- /test/assert/out.input144.zc: -------------------------------------------------------------------------------- 1 | Unable to open fred: Success 2 | -------------------------------------------------------------------------------- /test/assert/out.input145.zc: -------------------------------------------------------------------------------- 1 | q 2 | w 3 | e 4 | r 5 | e 6 | 3 7 | 5 8 | 7 9 | 9 10 | 7 11 | -------------------------------------------------------------------------------- /test/assert/out.input146.zc: -------------------------------------------------------------------------------- 1 | q 2 | w 3 | e 4 | r 5 | e 6 | r 7 | e 8 | r 9 | e 10 | 11 | 3 12 | 5 13 | 7 14 | 9 15 | 7 16 | 9 17 | 7 18 | 9 19 | 7 20 | -------------------------------------------------------------------------------- /test/assert/out.input147.zc: -------------------------------------------------------------------------------- 1 | 6 2 | 9 3 | 6 4 | 9 5 | -------------------------------------------------------------------------------- /test/assert/out.input148.zc: -------------------------------------------------------------------------------- 1 | i is 1 2 | i is 2 3 | i is 3 4 | leftover owl 5 | -------------------------------------------------------------------------------- /test/assert/out.input149.zc: -------------------------------------------------------------------------------- 1 | 1 -4 2 | 2 -8 3 | 3 -12 4 | 4 -16 5 | 5 -21 6 | 6 -27 7 | 7 -34 8 | 8 -42 9 | 9 -51 10 | 10 -61 11 | 11 -72 12 | 12 -84 13 | -------------------------------------------------------------------------------- /test/assert/out.input150.zc: -------------------------------------------------------------------------------- 1 | 1 2 3 2 | 4 5 6 3 | 7 8 9 4 | 5 | 1 2 3 6 | 4 5 fish 7 | -------------------------------------------------------------------------------- /test/assert/out.input151.zc: -------------------------------------------------------------------------------- 1 | testing x 2 | bar = 3 3 | -------------------------------------------------------------------------------- /test/assert/out.input152.zc: -------------------------------------------------------------------------------- 1 | fib(10) = 55 2 | -------------------------------------------------------------------------------- /test/assert/out.input153.zc: -------------------------------------------------------------------------------- 1 | x = 888 2 | -------------------------------------------------------------------------------- /test/error/error.input031.zc: -------------------------------------------------------------------------------- 1 | Expecting a primary expression, got token:+ on line 5 of input031.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input032.zc: -------------------------------------------------------------------------------- 1 | Unknown variable or function:pizza on line 4 of input032.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input033.zc: -------------------------------------------------------------------------------- 1 | Incompatible types to return on line 4 of input033.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input035.zc: -------------------------------------------------------------------------------- 1 | Duplicate local/(function parameter) variable declaration:a on line 4 of input035.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input036.zc: -------------------------------------------------------------------------------- 1 | Type doesn't match prototype for parameter:2 on line 4 of input036.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input037.zc: -------------------------------------------------------------------------------- 1 | Expected:, on line 3 of input037.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input038.zc: -------------------------------------------------------------------------------- 1 | Type doesn't match prototype for parameter:2 on line 4 of input038.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input039.zc: -------------------------------------------------------------------------------- 1 | No statements in function with non-void type on line 4 of input039.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input040.zc: -------------------------------------------------------------------------------- 1 | No return for function with non-void type on line 4 of input040.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input041.zc: -------------------------------------------------------------------------------- 1 | Can't return from a void function on line 3 of input041.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input042.zc: -------------------------------------------------------------------------------- 1 | Unknown variable or function:fred on line 3 of input042.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input043.zc: -------------------------------------------------------------------------------- 1 | Unknown variable or function:b on line 3 of input043.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input044.zc: -------------------------------------------------------------------------------- 1 | Unknown variable or function:z on line 3 of input044.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input045.zc: -------------------------------------------------------------------------------- 1 | & operator must be followed by an identifier on line 3 of input045.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input046.zc: -------------------------------------------------------------------------------- 1 | * operator must be followed by an identifier or * on line 3 of input046.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input047.zc: -------------------------------------------------------------------------------- 1 | ++ operator must be followed by an identifier on line 3 of input047.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input048.zc: -------------------------------------------------------------------------------- 1 | -- operator must be followed by an identifier on line 3 of input048.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input049.zc: -------------------------------------------------------------------------------- 1 | Incompatible expression in assignment on line 6 of input049.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input050.zc: -------------------------------------------------------------------------------- 1 | Incompatible types in binary expression on line 6 of input050.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input051.zc: -------------------------------------------------------------------------------- 1 | Expected '\'' at end of char literal on line 4 of input051.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input052.zc: -------------------------------------------------------------------------------- 1 | Unrecognised character:$ on line 5 of input052.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input056.zc: -------------------------------------------------------------------------------- 1 | Unknown struct/union type:var1 on line 2 of input056.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input057.zc: -------------------------------------------------------------------------------- 1 | Previously defined struct/union:fred on line 2 of input057.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input059.zc: -------------------------------------------------------------------------------- 1 | Unknown variable or function:y on line 3 of input059.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input060.zc: -------------------------------------------------------------------------------- 1 | Expression is not a struct/union on line 3 of input060.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input061.zc: -------------------------------------------------------------------------------- 1 | Expression is not a pointer to a struct/union on line 3 of input061.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input064.zc: -------------------------------------------------------------------------------- 1 | Undeclared enum type:fred on line 1 of input064.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input065.zc: -------------------------------------------------------------------------------- 1 | Enum type redeclared:fred on line 2 of input065.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input066.zc: -------------------------------------------------------------------------------- 1 | Enum value redeclared:z on line 2 of input066.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input068.zc: -------------------------------------------------------------------------------- 1 | Redefinition of typedef:FOO on line 2 of input068.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input069.zc: -------------------------------------------------------------------------------- 1 | Unknown type:FLOO on line 2 of input069.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input072.zc: -------------------------------------------------------------------------------- 1 | no loop or switch to break out from on line 1 of input072.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input073.zc: -------------------------------------------------------------------------------- 1 | no loop to continue out from on line 1 of input073.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input075.zc: -------------------------------------------------------------------------------- 1 | Unexpected token in switch:if on line 4 of input075.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input076.zc: -------------------------------------------------------------------------------- 1 | No cases in switch on line 3 of input076.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input077.zc: -------------------------------------------------------------------------------- 1 | case or default after existing default on line 6 of input077.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input078.zc: -------------------------------------------------------------------------------- 1 | case or default after existing default on line 6 of input078.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input079.zc: -------------------------------------------------------------------------------- 1 | Duplicate case value on line 6 of input079.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input085.zc: -------------------------------------------------------------------------------- 1 | Bad type in parameter list on line 1 of input085.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input086.zc: -------------------------------------------------------------------------------- 1 | Function definition not at global level on line 3 of input086.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input087.zc: -------------------------------------------------------------------------------- 1 | Bad type in member list on line 4 of input087.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input092.zc: -------------------------------------------------------------------------------- 1 | Type mismatch: literal vs. variable on line 1 of input092.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input093.zc: -------------------------------------------------------------------------------- 1 | Unknown variable or function:fred on line 1 of input093.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input094.zc: -------------------------------------------------------------------------------- 1 | Type mismatch: literal vs. variable on line 1 of input094.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input095.zc: -------------------------------------------------------------------------------- 1 | Variable can not be initialised:x on line 1 of input095.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input096.zc: -------------------------------------------------------------------------------- 1 | Array size is illegal:0 on line 1 of input096.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input098.zc: -------------------------------------------------------------------------------- 1 | Too many values in initialisation list on line 1 of input098.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input102.zc: -------------------------------------------------------------------------------- 1 | Cannot cast to a struct, union or void type on line 3 of input102.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input103.zc: -------------------------------------------------------------------------------- 1 | Cannot cast to a struct, union or void type on line 3 of input103.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input104.zc: -------------------------------------------------------------------------------- 1 | Cannot cast to a struct, union or void type on line 2 of input104.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input105.zc: -------------------------------------------------------------------------------- 1 | Incompatible expression in assignment on line 4 of input105.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input118.zc: -------------------------------------------------------------------------------- 1 | Compiler doesn't support static or extern local declarations on line 2 of input118.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input124.zc: -------------------------------------------------------------------------------- 1 | Cannot ++ on rvalue on line 6 of input124.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input126.zc: -------------------------------------------------------------------------------- 1 | Unknown variable or function:ptr on line 7 of input126.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input129.zc: -------------------------------------------------------------------------------- 1 | Cannot ++ and/or -- more than once on line 6 of input129.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input141.zc: -------------------------------------------------------------------------------- 1 | Declaration of array parameters is not implemented on line 4 of input141.zc 2 | -------------------------------------------------------------------------------- /test/error/error.input142.zc: -------------------------------------------------------------------------------- 1 | Array must have non-zero elements:fred on line 1 of input142.zc 2 | -------------------------------------------------------------------------------- /test/input001.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | void main() 4 | { printf("%d\n", 12 * 3); 5 | printf("%d\n", 18 - 2 * 4); 6 | printf("%d\n", 1 + 2 + 9 - 5/2 + 3*5); 7 | } 8 | -------------------------------------------------------------------------------- /test/input002.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | void main() 4 | { 5 | int fred; 6 | int jim; 7 | fred= 5; 8 | jim= 12; 9 | printf("%d\n", fred + jim); 10 | } 11 | -------------------------------------------------------------------------------- /test/input003.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | void main() 4 | { 5 | int x; 6 | x= 1; printf("%d\n", x); 7 | x= x + 1; printf("%d\n", x); 8 | x= x + 1; printf("%d\n", x); 9 | x= x + 1; printf("%d\n", x); 10 | x= x + 1; printf("%d\n", x); 11 | } 12 | -------------------------------------------------------------------------------- /test/input004.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | void main() 4 | { 5 | int x; 6 | x= 7 < 9; printf("%d\n", x); 7 | x= 7 <= 9; printf("%d\n", x); 8 | x= 7 != 9; printf("%d\n", x); 9 | x= 7 == 7; printf("%d\n", x); 10 | x= 7 >= 7; printf("%d\n", x); 11 | x= 7 <= 7; printf("%d\n", x); 12 | x= 9 > 7; printf("%d\n", x); 13 | x= 9 >= 7; printf("%d\n", x); 14 | x= 9 != 7; printf("%d\n", x); 15 | } 16 | -------------------------------------------------------------------------------- /test/input005.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | void main() 4 | { 5 | int i; int j; 6 | i=6; j=12; 7 | if (i < j) { 8 | printf("%d\n", i); 9 | } else { 10 | printf("%d\n", j); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /test/input006.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | void main() 4 | { int i; 5 | i=1; 6 | while (i <= 10) { 7 | printf("%d\n", i); 8 | i= i + 1; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /test/input007.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | void main() 4 | { 5 | int i; 6 | for (i= 1; i <= 10; i= i + 1) { 7 | printf("%d\n", i); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /test/input008.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | void main() 4 | { 5 | int i; 6 | for (i= 1; i <= 10; i= i + 1) { 7 | printf("%d\n", i); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /test/input009.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | void main() 4 | { 5 | int i; 6 | for (i= 1; i <= 10; i= i + 1) { 7 | printf("%d\n", i); 8 | } 9 | } 10 | 11 | void fred() 12 | { 13 | int a; int b; 14 | a= 12; b= 3 * a; 15 | if (a >= b) { printf("%d\n", 2 * b - a); } 16 | } 17 | -------------------------------------------------------------------------------- /test/input010.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | void main() 4 | { 5 | int i; char j; 6 | 7 | j= 20; printf("%d\n", j); 8 | i= 10; printf("%d\n", i); 9 | 10 | for (i= 1; i <= 5; i= i + 1) { printf("%d\n", i); } 11 | for (j= 253; j != 2; j= j + 1) { printf("%d\n", j); } 12 | } 13 | -------------------------------------------------------------------------------- /test/input011.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | int main() 4 | { 5 | int i; char j; long k; 6 | 7 | i= 10; printf("%d\n", i); 8 | j= 20; printf("%d\n", j); 9 | k= 30; printf("%d\n", k); 10 | 11 | for (i= 1; i <= 5; i= i + 1) { printf("%d\n", i); } 12 | for (j= 253; j != 4; j= j + 1) { printf("%d\n", j); } 13 | for (k= 1; k <= 5; k= k + 1) { printf("%d\n", k); } 14 | return(i); 15 | printf("%d\n", 12345); 16 | return(3); 17 | } 18 | -------------------------------------------------------------------------------- /test/input012.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | int fred() { 4 | return(5); 5 | } 6 | 7 | void main() { 8 | int x; 9 | x= fred(2); 10 | printf("%d\n", x); 11 | } 12 | -------------------------------------------------------------------------------- /test/input013.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | int fred() { 4 | return(56); 5 | } 6 | 7 | void main() { 8 | int dummy; 9 | int result; 10 | dummy= printf("%d\n", 23); 11 | result= fred(10); 12 | dummy= printf("%d\n", result); 13 | } 14 | -------------------------------------------------------------------------------- /test/input014.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | int fred() { 4 | return(20); 5 | } 6 | 7 | int main() { 8 | int result; 9 | printf("%d\n", 10); 10 | result= fred(15); 11 | printf("%d\n", result); 12 | printf("%d\n", fred(15)+10); 13 | return(0); 14 | } 15 | -------------------------------------------------------------------------------- /test/input015.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | int main() { 4 | char a; 5 | char *b; 6 | char c; 7 | 8 | int d; 9 | int *e; 10 | int f; 11 | 12 | a= 18; printf("%d\n", a); 13 | b= &a; c= *b; printf("%d\n", c); 14 | 15 | d= 12; printf("%d\n", d); 16 | e= &d; f= *e; printf("%d\n", f); 17 | return(0); 18 | } 19 | -------------------------------------------------------------------------------- /test/input016.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | int c; 4 | int d; 5 | int *e; 6 | int f; 7 | 8 | int main() { 9 | c= 12; d=18; printf("%d\n", c); 10 | e= &c + 1; f= *e; printf("%d\n", f); 11 | return(0); 12 | } 13 | -------------------------------------------------------------------------------- /test/input017.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | int main() { 4 | char a; 5 | char *b; 6 | int d; 7 | int *e; 8 | 9 | b= &a; *b= 19; printf("%d\n", a); 10 | e= &d; *e= 12; printf("%d\n", d); 11 | return(0); 12 | } 13 | -------------------------------------------------------------------------------- /test/input018.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | int main() 4 | { 5 | int a; 6 | int b; 7 | a= b= 34; 8 | printf("%d\n", a); 9 | printf("%d\n", b); 10 | return(0); 11 | } 12 | -------------------------------------------------------------------------------- /test/input019.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | int a; 4 | int b; 5 | int c; 6 | int d; 7 | int e; 8 | int main() 9 | { 10 | a= 2; b= 4; c= 3; d= 2; 11 | e= (a+b) * (c+d); 12 | printf("%d\n", e); 13 | return(0); 14 | } 15 | -------------------------------------------------------------------------------- /test/input020.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | int a; 4 | int b[25]; 5 | 6 | int main() { 7 | b[3]= 12; 8 | a= b[3]; 9 | printf("%d\n", a); 10 | return(0); 11 | } 12 | -------------------------------------------------------------------------------- /test/input021.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | char c; 4 | char *str; 5 | 6 | int main() { 7 | c= '\n'; printf("%d\n", c); 8 | 9 | for (str= "Hello world\n"; *str != 0; str= str + 1) { 10 | printf("%c", *str); 11 | } 12 | return(0); 13 | } 14 | -------------------------------------------------------------------------------- /test/input022.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | char a; char b; char c; 4 | int d; int e; int f; 5 | long g; long h; long i; 6 | 7 | 8 | int main() { 9 | b= 5; c= 7; a= b + c++; printf("%d\n", a); 10 | e= 5; f= 7; d= e + f++; printf("%d\n", d); 11 | h= 5; i= 7; g= h + i++; printf("%d\n", g); 12 | a= b-- + c; printf("%d\n", a); 13 | d= e-- + f; printf("%d\n", d); 14 | g= h-- + i; printf("%d\n", g); 15 | a= ++b + c; printf("%d\n", a); 16 | d= ++e + f; printf("%d\n", d); 17 | g= ++h + i; printf("%d\n", g); 18 | a= b * --c; printf("%d\n", a); 19 | d= e * --f; printf("%d\n", d); 20 | g= h * --i; printf("%d\n", g); 21 | return(0); 22 | } 23 | -------------------------------------------------------------------------------- /test/input023.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | char *str; 4 | int x; 5 | 6 | int main() { 7 | x= -23; printf("%d\n", x); 8 | printf("%d\n", -10 * -10); 9 | 10 | x= 1; x= ~x; printf("%d\n", x); 11 | 12 | x= 2 > 5; printf("%d\n", x); 13 | x= !x; printf("%d\n", x); 14 | x= !x; printf("%d\n", x); 15 | 16 | x= 13; if (x) { printf("%d\n", 13); } 17 | x= 0; if (!x) { printf("%d\n", 14); } 18 | 19 | for (str= "Hello world\n"; *str; str++) { 20 | printf("%c", *str); 21 | } 22 | 23 | return(0); 24 | } 25 | -------------------------------------------------------------------------------- /test/input024.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | int a; 4 | int b; 5 | int c; 6 | int main() { 7 | a= 42; b= 19; 8 | printf("%d\n", a & b); 9 | printf("%d\n", a | b); 10 | printf("%d\n", a ^ b); 11 | printf("%d\n", 1 << 3); 12 | printf("%d\n", 63 >> 3); 13 | return(0); 14 | } 15 | -------------------------------------------------------------------------------- /test/input025.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | int a; 4 | int b; 5 | int c; 6 | 7 | int main() 8 | { 9 | char z; 10 | int y; 11 | int x; 12 | x= 10; y= 20; z= 30; 13 | printf("%d\n", x); printf("%d\n", y); printf("%d\n", z); 14 | a= 5; b= 15; c= 25; 15 | printf("%d\n", a); printf("%d\n", b); printf("%d\n", c); 16 | return(0); 17 | } 18 | -------------------------------------------------------------------------------- /test/input026.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | int main(int a, char b, long c, int d, int e, int f, int g, int h) { 4 | int i; int j; int k; 5 | 6 | a= 13; printf("%d\n", a); 7 | b= 23; printf("%d\n", b); 8 | c= 34; printf("%d\n", c); 9 | d= 44; printf("%d\n", d); 10 | e= 54; printf("%d\n", e); 11 | f= 64; printf("%d\n", f); 12 | g= 74; printf("%d\n", g); 13 | h= 84; printf("%d\n", h); 14 | i= 94; printf("%d\n", i); 15 | j= 95; printf("%d\n", j); 16 | k= 96; printf("%d\n", k); 17 | return(0); 18 | } 19 | -------------------------------------------------------------------------------- /test/input027.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | int param8(int a, int b, int c, int d, int e, int f, int g, int h) { 4 | printf("%d\n", a); printf("%d\n", b); printf("%d\n", c); printf("%d\n", d); 5 | printf("%d\n", e); printf("%d\n", f); printf("%d\n", g); printf("%d\n", h); 6 | return(0); 7 | } 8 | 9 | int param5(int a, int b, int c, int d, int e) { 10 | printf("%d\n", a); printf("%d\n", b); printf("%d\n", c); printf("%d\n", d); printf("%d\n", e); 11 | return(0); 12 | } 13 | 14 | int param2(int a, int b) { 15 | int c; int d; int e; 16 | c= 3; d= 4; e= 5; 17 | printf("%d\n", a); printf("%d\n", b); printf("%d\n", c); printf("%d\n", d); printf("%d\n", e); 18 | return(0); 19 | } 20 | 21 | int param0() { 22 | int a; int b; int c; int d; int e; 23 | a= 1; b= 2; c= 3; d= 4; e= 5; 24 | printf("%d\n", a); printf("%d\n", b); printf("%d\n", c); printf("%d\n", d); printf("%d\n", e); 25 | return(0); 26 | } 27 | 28 | int main() { 29 | param8(1,2,3,4,5,6,7,8); 30 | param5(1,2,3,4,5); 31 | param2(1,2); 32 | param0(); 33 | return(0); 34 | } 35 | -------------------------------------------------------------------------------- /test/input028.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | int param8(int a, int b, int c, int d, int e, int f, int g, int h) { 4 | printf("%d\n", a); printf("%d\n", b); printf("%d\n", c); printf("%d\n", d); 5 | printf("%d\n", e); printf("%d\n", f); printf("%d\n", g); printf("%d\n", h); 6 | return(0); 7 | } 8 | 9 | int fred(int a, int b, int c) { 10 | return(a+b+c); 11 | } 12 | 13 | int main() { 14 | int x; 15 | param8(1, 2, 3, 5, 8, 13, 21, 34); 16 | x= fred(2, 3, 4); printf("%d\n", x); 17 | return(0); 18 | } 19 | -------------------------------------------------------------------------------- /test/input029.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | int param8(int a, int b, int c, int d, int e, int f, int g, int h); 4 | int fred(int a, int b, int c); 5 | int main(); 6 | 7 | int param8(int a, int b, int c, int d, int e, int f, int g, int h) { 8 | printf("%d\n", a); printf("%d\n", b); printf("%d\n", c); printf("%d\n", d); 9 | printf("%d\n", e); printf("%d\n", f); printf("%d\n", g); printf("%d\n", h); 10 | return(0); 11 | } 12 | 13 | int fred(int a, int b, int c) { 14 | return(a+b+c); 15 | } 16 | 17 | int main() { 18 | int x; 19 | param8(1, 2, 3, 5, 8, 13, 21, 34); 20 | x= fred(2, 3, 4); printf("%d\n", x); 21 | return(0); 22 | } 23 | -------------------------------------------------------------------------------- /test/input030.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | int open(char *pathname, int flags); 4 | int read(int fd, char *buf, int count); 5 | int write(int fd, void *buf, int count); 6 | int close(int fd); 7 | 8 | char *buf; 9 | 10 | int main() { 11 | int zin; 12 | int cnt; 13 | 14 | buf= " "; 15 | zin = open("input030.c", 0); 16 | if (zin == -1) { 17 | return (1); 18 | } 19 | while ((cnt = read(zin, buf, 60)) > 0) { 20 | write(1, buf, cnt); 21 | } 22 | close(zin); 23 | return (0); 24 | } 25 | -------------------------------------------------------------------------------- /test/input031.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | int main() { 4 | int x; 5 | x= 2 + + 3 - * / ; 6 | } 7 | -------------------------------------------------------------------------------- /test/input032.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | int main() { 4 | pizza cow llama sausage; 5 | } 6 | -------------------------------------------------------------------------------- /test/input033.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | int main() { 4 | char *z; return(z); 5 | } 6 | -------------------------------------------------------------------------------- /test/input035.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | int fred(int a, int b) { 4 | int a; 5 | return(a); 6 | } 7 | -------------------------------------------------------------------------------- /test/input036.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | int fred(int a, char b, int c); 4 | int fred(int a, int b, char c); 5 | -------------------------------------------------------------------------------- /test/input037.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | int fred(int a, char b +, int z); 4 | -------------------------------------------------------------------------------- /test/input038.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | int fred(int a, char b, int c); 4 | int fred(int a, int b, char c, int g); 5 | -------------------------------------------------------------------------------- /test/input039.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | int main() { int a; } 4 | -------------------------------------------------------------------------------- /test/input040.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | int main() { int a; a= 5; } 4 | -------------------------------------------------------------------------------- /test/input041.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | void fred() { return(5); } 4 | -------------------------------------------------------------------------------- /test/input042.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | int main() { fred(5); } 4 | -------------------------------------------------------------------------------- /test/input043.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | int main() { int a; a= b[4]; } 4 | -------------------------------------------------------------------------------- /test/input044.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | int main() { int a; a= z; } 4 | -------------------------------------------------------------------------------- /test/input045.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | int main() { int a; a= &5; } 4 | -------------------------------------------------------------------------------- /test/input046.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | int main() { int a; a= *5; } 4 | -------------------------------------------------------------------------------- /test/input047.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | int main() { int a; a= ++5; } 4 | -------------------------------------------------------------------------------- /test/input048.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | int main() { int a; a= --5; } 4 | -------------------------------------------------------------------------------- /test/input049.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | int main() { 4 | int x; 5 | char y; 6 | y= x; 7 | } 8 | -------------------------------------------------------------------------------- /test/input050.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | int main() { 4 | char *a; 5 | char *b; 6 | a= a + b; 7 | } 8 | -------------------------------------------------------------------------------- /test/input051.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | int main() { 4 | char a; a= 'fred'; 5 | } 6 | -------------------------------------------------------------------------------- /test/input052.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | int main() { 4 | int a; 5 | a= $5.00; 6 | } 7 | -------------------------------------------------------------------------------- /test/input053.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | int main() 4 | { 5 | printf("Hello world, %d\n", 23); 6 | return(0); 7 | } 8 | -------------------------------------------------------------------------------- /test/input054.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | int main() 4 | { 5 | int i; 6 | for (i=0; i < 20; i++) { 7 | printf("Hello world, %d\n", i); 8 | } 9 | return(0); 10 | } 11 | -------------------------------------------------------------------------------- /test/input055.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | int main(int argc, char **argv) { 4 | int i; 5 | char *argument; 6 | printf("Hello world\n"); 7 | 8 | for (i=0; i < argc; i++) { 9 | argument= *argv; argv= argv + 1; 10 | printf("Argument %d is %s\n", i, argument); 11 | } 12 | return(0); 13 | } 14 | -------------------------------------------------------------------------------- /test/input056.zc: -------------------------------------------------------------------------------- 1 | struct foo { int x; }; 2 | struct mary var1; 3 | -------------------------------------------------------------------------------- /test/input057.zc: -------------------------------------------------------------------------------- 1 | struct fred { int x; } ; 2 | struct fred { char y; } ; 3 | -------------------------------------------------------------------------------- /test/input058.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | struct fred { 4 | int x; 5 | char y; 6 | long z; 7 | }; 8 | 9 | struct fred var2; 10 | struct fred *varptr; 11 | 12 | int main() { 13 | long result; 14 | 15 | var2.x= 12; printf("%d\n", var2.x); 16 | var2.y= 'c'; printf("%d\n", var2.y); 17 | var2.z= 4005; printf("%d\n", var2.z); 18 | 19 | result= var2.x + var2.y + var2.z; 20 | printf("%d\n", result); 21 | 22 | varptr= &var2; 23 | result= varptr->x + varptr->y + varptr->z; 24 | printf("%d\n", result); 25 | return(0); 26 | } 27 | -------------------------------------------------------------------------------- /test/input059.zc: -------------------------------------------------------------------------------- 1 | int main() { 2 | int x; 3 | x= y.foo; 4 | } 5 | -------------------------------------------------------------------------------- /test/input060.zc: -------------------------------------------------------------------------------- 1 | int main() { 2 | int x; 3 | x= x.foo; 4 | } 5 | -------------------------------------------------------------------------------- /test/input061.zc: -------------------------------------------------------------------------------- 1 | int main() { 2 | int x; 3 | x= x->foo; 4 | } 5 | -------------------------------------------------------------------------------- /test/input062.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | union fred { 4 | char w; 5 | int x; 6 | int y; 7 | long z; 8 | }; 9 | 10 | union fred var1; 11 | union fred *varptr; 12 | 13 | int main() { 14 | var1.x= 65; printf("%d\n", var1.x); 15 | var1.x= 66; printf("%d\n", var1.x); printf("%d\n", var1.y); 16 | printf("The next two depend on the endian of the platform\n"); 17 | printf("%d\n", var1.w); printf("%d\n", var1.z); 18 | 19 | varptr= &var1; varptr->x= 67; 20 | printf("%d\n", varptr->x); printf("%d\n", varptr->y); 21 | 22 | return(0); 23 | } 24 | -------------------------------------------------------------------------------- /test/input063.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | enum fred { apple=1, banana, carrot, pear=10, peach, mango, papaya }; 4 | enum jane { aple=1, bnana, crrot, par=10, pech, mago, paaya }; 5 | 6 | enum fred var1; 7 | enum jane var2; 8 | enum fred var3; 9 | 10 | int main() { 11 | var1= carrot + pear + mango; 12 | printf("%d\n", var1); 13 | return(0); 14 | } 15 | -------------------------------------------------------------------------------- /test/input064.zc: -------------------------------------------------------------------------------- 1 | enum fred var3; 2 | -------------------------------------------------------------------------------- /test/input065.zc: -------------------------------------------------------------------------------- 1 | enum fred { x, y, z }; 2 | enum fred { a, b }; 3 | -------------------------------------------------------------------------------- /test/input066.zc: -------------------------------------------------------------------------------- 1 | enum fred { x, y, z }; 2 | enum mary { a, b, z }; 3 | -------------------------------------------------------------------------------- /test/input067.zc: -------------------------------------------------------------------------------- 1 | int printf(char *fmt); 2 | 3 | typedef int FOO; 4 | FOO var1; 5 | 6 | struct bar { int x; int y} ; 7 | typedef struct bar BAR; 8 | BAR var2; 9 | 10 | int main() { 11 | var1= 5; printf("%d\n", var1); 12 | var2.x= 7; var2.y= 10; printf("%d\n", var2.x + var2.y); 13 | return(0); 14 | } 15 | -------------------------------------------------------------------------------- /test/input068.zc: -------------------------------------------------------------------------------- 1 | typedef int FOO; 2 | typedef char FOO; 3 | -------------------------------------------------------------------------------- /test/input069.zc: -------------------------------------------------------------------------------- 1 | typedef int FOO; 2 | FLOO y; 3 | -------------------------------------------------------------------------------- /test/input070.zc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | typedef int FOO; 4 | 5 | int main() { 6 | FOO x; 7 | x= 56; 8 | printf("%d\n", x); 9 | return(0); 10 | } 11 | -------------------------------------------------------------------------------- /test/input071.zc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | int x; 5 | x = 0; 6 | while (x < 100) { 7 | if (x == 5) { x = x + 2; continue; } 8 | printf("%d\n", x); 9 | if (x == 14) { break; } 10 | x = x + 1; 11 | } 12 | printf("Done\n"); 13 | return (0); 14 | } 15 | -------------------------------------------------------------------------------- /test/input072.zc: -------------------------------------------------------------------------------- 1 | int main() { break; } 2 | -------------------------------------------------------------------------------- /test/input073.zc: -------------------------------------------------------------------------------- 1 | int main() { continue; } 2 | -------------------------------------------------------------------------------- /test/input074.zc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | int x; 5 | int y; 6 | y= 0; 7 | 8 | for (x=0; x < 5; x++) { 9 | switch(x) { 10 | case 1: { y= 5; break; } 11 | case 2: { y= 7; break; } 12 | case 3: { y= 9; } 13 | default: { y= 100; } 14 | } 15 | printf("%d\n", y); 16 | } 17 | return(0); 18 | } 19 | -------------------------------------------------------------------------------- /test/input075.zc: -------------------------------------------------------------------------------- 1 | int main() { 2 | int x; 3 | switch(x) { 4 | if (x<5); 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /test/input076.zc: -------------------------------------------------------------------------------- 1 | int main() { 2 | int x; 3 | switch(x) { } 4 | } 5 | -------------------------------------------------------------------------------- /test/input077.zc: -------------------------------------------------------------------------------- 1 | int main() { 2 | int x; 3 | switch(x) { 4 | case 1: { x= 2; } 5 | default: { x= 3; } 6 | case 4: { x= 2; } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /test/input078.zc: -------------------------------------------------------------------------------- 1 | int main() { 2 | int x; 3 | switch(x) { 4 | case 1: { x= 2; } 5 | default: { x= 3; } 6 | default: { x= 2; } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /test/input079.zc: -------------------------------------------------------------------------------- 1 | int main() { 2 | int x; 3 | switch(x) { 4 | case 1: { x= 2; } 5 | case 2: { x= 2; } 6 | case 1: { x= 2; } 7 | default: { x= 2; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /test/input080.zc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int x; 4 | int y; 5 | 6 | int main() { 7 | 8 | for (x=0, y=1; x < 6; x++, y=y+2) { 9 | printf("%d %d\n", x, y); 10 | } 11 | 12 | return(0); 13 | } 14 | -------------------------------------------------------------------------------- /test/input081.zc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int x; 4 | int y; 5 | 6 | int main() { 7 | 8 | x= 0; y=1; 9 | 10 | for (;x<5;) { 11 | printf("%d %d\n", x, y); 12 | x=x+1; 13 | y=y+2; 14 | } 15 | 16 | return(0); 17 | } 18 | -------------------------------------------------------------------------------- /test/input082.zc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | int x; 5 | 6 | x= 10; 7 | // Dangling else test 8 | if (x > 5) 9 | if (x > 15) 10 | printf("x > 15\n"); 11 | else 12 | printf("15 >= x > 5\n"); 13 | else 14 | printf("5 >= x\n"); 15 | return(0); 16 | } 17 | -------------------------------------------------------------------------------- /test/input083.zc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | int x; 5 | 6 | // Dangling else test. 7 | // We should not print anything for x<= 5 8 | for (x=0; x < 12; x++) 9 | if (x > 5) 10 | if (x > 10) 11 | printf("10 < %2d\n", x); 12 | else 13 | printf(" 5 < %2d <= 10\n", x); 14 | return(0); 15 | } 16 | 17 | -------------------------------------------------------------------------------- /test/input084.zc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | int x, y; 5 | x=2; y=3; 6 | printf("%d %d\n", x, y); 7 | 8 | char a, *b; 9 | a= 'f'; b= &a; 10 | printf("%c %c\n", a, *b); 11 | 12 | return(0); 13 | } 14 | -------------------------------------------------------------------------------- /test/input085.zc: -------------------------------------------------------------------------------- 1 | int main(struct foo { int x; }; , int a) { 2 | return(0); 3 | } 4 | -------------------------------------------------------------------------------- /test/input086.zc: -------------------------------------------------------------------------------- 1 | int main() { 2 | int fred() { return(5); } 3 | int x; 4 | x=2; 5 | return(x); 6 | } 7 | -------------------------------------------------------------------------------- /test/input087.zc: -------------------------------------------------------------------------------- 1 | struct foo { 2 | int x; 3 | int y; 4 | struct blah { int g; }; 5 | }; 6 | -------------------------------------------------------------------------------- /test/input088.zc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct foo { 4 | int x; 5 | int y; 6 | } fred, mary; 7 | 8 | struct foo james; 9 | 10 | int main() { 11 | fred.x= 5; 12 | mary.y= 6; 13 | printf("%d %d\n", fred.x, mary.y); 14 | return(0); 15 | } 16 | -------------------------------------------------------------------------------- /test/input089.zc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int x= 23; 4 | char y= 'H'; 5 | char *z= "Hello world"; 6 | 7 | int main() { 8 | printf("%d %c %s\n", x, y, z); 9 | return(0); 10 | } 11 | -------------------------------------------------------------------------------- /test/input090.zc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int a = 23, b = 100; 4 | char y = 'H', *z = "Hello world"; 5 | 6 | int main() { 7 | printf("%d %d %c %s\n", a, b, y, z); 8 | return (0); 9 | } 10 | -------------------------------------------------------------------------------- /test/input091.zc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int fred[] = { 1, 2, 3, 4, 5 }; 4 | int jim[10] = { 1, 2, 3, 4, 5 }; 5 | 6 | int main() { 7 | int i; 8 | for (i=0; i < 5; i++) printf("%d\n", fred[i]); 9 | for (i=0; i < 10; i++) printf("%d\n", jim[i]); 10 | return(0); 11 | } 12 | -------------------------------------------------------------------------------- /test/input092.zc: -------------------------------------------------------------------------------- 1 | char x= 3000; 2 | -------------------------------------------------------------------------------- /test/input093.zc: -------------------------------------------------------------------------------- 1 | char x= fred; 2 | -------------------------------------------------------------------------------- /test/input094.zc: -------------------------------------------------------------------------------- 1 | char *s= 54; 2 | -------------------------------------------------------------------------------- /test/input095.zc: -------------------------------------------------------------------------------- 1 | int fred(int x=2) { return(x); } 2 | -------------------------------------------------------------------------------- /test/input096.zc: -------------------------------------------------------------------------------- 1 | int fred[0]; 2 | -------------------------------------------------------------------------------- /test/input098.zc: -------------------------------------------------------------------------------- 1 | int fred[3]= { 1, 2, 3, 4, 5 }; 2 | -------------------------------------------------------------------------------- /test/input099.zc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // List of token strings, for debugging purposes. 4 | // As yet, we can't store a NULL into the list 5 | char *Tstring[] = { 6 | "EOF", "=", "||", "&&", "|", "^", "&", 7 | "==", "!=", ",", ">", "<=", ">=", "<<", ">>", 8 | "+", "-", "*", "/", "++", "--", "~", "!", 9 | "void", "char", "int", "long", 10 | "if", "else", "while", "for", "return", 11 | "struct", "union", "enum", "typedef", 12 | "extern", "break", "continue", "switch", 13 | "case", "default", 14 | "intlit", "strlit", ";", "identifier", 15 | "{", "}", "(", ")", "[", "]", ",", ".", 16 | "->", ":", "" 17 | }; 18 | 19 | int main() { 20 | int i; 21 | char *str; 22 | 23 | i=0; 24 | while (1) { 25 | str= Tstring[i]; 26 | if (*str == 0) break; 27 | printf("%s\n", str); 28 | i++; 29 | } 30 | return(0); 31 | } 32 | -------------------------------------------------------------------------------- /test/input100.zc: -------------------------------------------------------------------------------- 1 | #include 2 | int main() { 3 | int x= 3, y=14; 4 | int z= 2 * x + y; 5 | char *str= "Hello world"; 6 | printf("%s %d %d\n", str, x+y, z); 7 | return(0); 8 | } 9 | -------------------------------------------------------------------------------- /test/input101.zc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | int x= 65535; 5 | char y; 6 | char *str; 7 | 8 | y= (char )x; printf("0x%x\n", y); 9 | str= (char *)0; printf("0x%lx\n", (long)str); 10 | return(0); 11 | } 12 | -------------------------------------------------------------------------------- /test/input102.zc: -------------------------------------------------------------------------------- 1 | int main() { 2 | struct foo { int p; }; 3 | int y= (struct foo) x; 4 | } 5 | -------------------------------------------------------------------------------- /test/input103.zc: -------------------------------------------------------------------------------- 1 | int main() { 2 | union foo { int p; }; 3 | int y= (union foo) x; 4 | } 5 | -------------------------------------------------------------------------------- /test/input104.zc: -------------------------------------------------------------------------------- 1 | int main() { 2 | int y= (void) x; 3 | } 4 | -------------------------------------------------------------------------------- /test/input105.zc: -------------------------------------------------------------------------------- 1 | int main() { 2 | int x; 3 | char *y; 4 | y= (char) x; 5 | } 6 | -------------------------------------------------------------------------------- /test/input106.zc: -------------------------------------------------------------------------------- 1 | #include 2 | char *y= (char *)0; 3 | 4 | int main() { 5 | printf("0x%lx\n", (long)y); 6 | return(0); 7 | } 8 | -------------------------------------------------------------------------------- /test/input107.zc: -------------------------------------------------------------------------------- 1 | #include 2 | char *y[] = { "fish", "cow", NULL }; 3 | char *z= NULL; 4 | 5 | int main() { 6 | int i; 7 | char *ptr; 8 | for (i=0; i < 3; i++) { 9 | ptr= y[i]; 10 | if (ptr != (char *)0) 11 | printf("%s\n", y[i]); 12 | else 13 | printf("NULL\n"); 14 | } 15 | return(0); 16 | } 17 | -------------------------------------------------------------------------------- /test/input108.zc: -------------------------------------------------------------------------------- 1 | int main() { 2 | char *str= (void *)0; 3 | return(0); 4 | } 5 | -------------------------------------------------------------------------------- /test/input109.zc: -------------------------------------------------------------------------------- 1 | #include 2 | int main() { 3 | int x= 17 - 1; 4 | printf("%d\n", x); 5 | return(0); 6 | } 7 | -------------------------------------------------------------------------------- /test/input110.zc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int x; 4 | int y; 5 | 6 | int main() { 7 | x= 3; y= 15; y += x; printf("%d\n", y); 8 | x= 3; y= 15; y -= x; printf("%d\n", y); 9 | x= 3; y= 15; y *= x; printf("%d\n", y); 10 | x= 3; y= 15; y /= x; printf("%d\n", y); 11 | return(0); 12 | } 13 | -------------------------------------------------------------------------------- /test/input111.zc: -------------------------------------------------------------------------------- 1 | #include 2 | int main() { 3 | int x= 2000 + 3 + 4 * 5 + 6; 4 | printf("%d\n", x); 5 | return(0); 6 | } 7 | -------------------------------------------------------------------------------- /test/input112.zc: -------------------------------------------------------------------------------- 1 | #include 2 | char* y = NULL; 3 | int x= 10 + 6; 4 | int fred [ 2 + 3 ]; 5 | 6 | int main() { 7 | fred[2]= x; 8 | printf("%d\n", fred[2]); 9 | return(0); 10 | } 11 | -------------------------------------------------------------------------------- /test/input113.zc: -------------------------------------------------------------------------------- 1 | #include 2 | void fred(void); 3 | 4 | void fred(void) { 5 | printf("fred says hello\n"); 6 | } 7 | 8 | int main(void) { 9 | fred(); return(0); 10 | } 11 | -------------------------------------------------------------------------------- /test/input114.zc: -------------------------------------------------------------------------------- 1 | #include 2 | int main() { 3 | int x= 0x4a; 4 | printf("%c\n", x); 5 | return(0); 6 | } 7 | -------------------------------------------------------------------------------- /test/input115.zc: -------------------------------------------------------------------------------- 1 | #include 2 | struct foo { int x; char y; long z; }; 3 | typedef struct foo blah; 4 | 5 | struct symtable { 6 | char *name; 7 | int type; 8 | struct symtable *ctype; 9 | int stype; 10 | int class; 11 | int size; 12 | int nelems; 13 | #define st_endlabel st_posn 14 | int st_posn; 15 | 16 | int *initlist; 17 | struct symtable *next; 18 | struct symtable *member; 19 | }; 20 | 21 | // Abstract Syntax Tree structure 22 | struct ASTnode { 23 | int op; 24 | int type; 25 | int rvalue; 26 | struct ASTnode *left; 27 | struct ASTnode *mid; 28 | struct ASTnode *right; 29 | struct symtable *sym; 30 | 31 | #define a_intvalue a_size 32 | int a_size; 33 | }; 34 | 35 | int main() { 36 | printf("%ld\n", sizeof(char)); 37 | printf("%ld\n", sizeof(int)); 38 | printf("%ld\n", sizeof(long)); 39 | printf("%ld\n", sizeof(char *)); 40 | printf("%ld\n", sizeof(blah)); 41 | printf("%ld\n", sizeof(struct symtable)); 42 | printf("%ld\n", sizeof(struct ASTnode)); 43 | return(0); 44 | } 45 | -------------------------------------------------------------------------------- /test/input116.zc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static int counter=0; 4 | static int fred(void) { return(counter++); } 5 | 6 | int main(void) { 7 | int i; 8 | for (i=0; i < 5; i++) 9 | printf("%d\n", fred()); 10 | return(0); 11 | } 12 | -------------------------------------------------------------------------------- /test/input117.zc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static char *fred(void) { 4 | return("Hello"); 5 | } 6 | 7 | int main(void) { 8 | printf("%s\n", fred()); 9 | return(0); 10 | } 11 | -------------------------------------------------------------------------------- /test/input118.zc: -------------------------------------------------------------------------------- 1 | int main(void) { 2 | static int x; 3 | } 4 | -------------------------------------------------------------------------------- /test/input119.zc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int x; 4 | int y= 3; 5 | 6 | int main() { 7 | x= y != 3 ? 6 : 8; printf("%d\n", x); 8 | x= (y == 3) ? 6 : 8; printf("%d\n", x); 9 | return(0); 10 | } 11 | -------------------------------------------------------------------------------- /test/input120.zc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int x; 4 | int y= 3; 5 | 6 | int main() { 7 | for (y= 0; y < 10; y++) { 8 | x= y > 4 ? y + 2 : y + 9; 9 | printf("%d\n", x); 10 | } 11 | return(0); 12 | } 13 | -------------------------------------------------------------------------------- /test/input121.zc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int x; 4 | int y= 3; 5 | 6 | int main() { 7 | for (y= 0; y < 10; y++) { 8 | x= (y < 4) ? y + 2 : 9 | (y > 7) ? 1000 : y + 9; 10 | printf("%d\n", x); 11 | } 12 | return(0); 13 | } 14 | -------------------------------------------------------------------------------- /test/input122.zc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int x, y, z1, z2; 4 | 5 | int main() { 6 | for (x= 0; x <= 1; x++) { 7 | for (y= 0; y <= 1; y++) { 8 | z1= x || y; z2= x && y; 9 | printf("x %d, y %d, x || y %d, x && y %d\n", x, y, z1, z2); 10 | } 11 | } 12 | 13 | //z= x || y; 14 | return(0); 15 | } 16 | -------------------------------------------------------------------------------- /test/input123.zc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | int x; 5 | for (x=0; x < 20; x++) 6 | switch(x) { 7 | case 2: 8 | case 3: 9 | case 5: 10 | case 7: 11 | case 11: printf("%2d infant prime\n", x); break; 12 | case 13: 13 | case 17: 14 | case 19: printf("%2d teen prime\n", x); break; 15 | case 0: 16 | case 1: 17 | case 4: 18 | case 6: 19 | case 8: 20 | case 9: 21 | case 10: 22 | case 12: printf("%2d infant composite\n", x); break; 23 | default: printf("%2d teen composite\n", x); break; 24 | } 25 | 26 | return(0); 27 | } 28 | -------------------------------------------------------------------------------- /test/input124.zc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int ary[5]; 4 | 5 | int main() { 6 | ary++; 7 | return(0); 8 | } 9 | -------------------------------------------------------------------------------- /test/input125.zc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int ary[5]; 4 | int *ptr; 5 | int x; 6 | 7 | int main() { 8 | ary[3]= 2008; 9 | ptr= ary; 10 | x= ary[3]; printf("%d\n", x); 11 | x= ptr[3]; printf("%d\n", x); 12 | return(0); 13 | } 14 | -------------------------------------------------------------------------------- /test/input126.zc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int ary[5]; 4 | 5 | int main() { 6 | ary[3]= 2008; 7 | ptr= &ary; 8 | return(0); 9 | } 10 | -------------------------------------------------------------------------------- /test/input127.zc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int ary[5]; 4 | 5 | void fred(int *ptr) { 6 | printf("%d\n", ptr[3]); 7 | } 8 | 9 | int main() { 10 | ary[3]= 2008; 11 | printf("%d\n", ary[3]); 12 | fred(ary); 13 | return(0); 14 | } 15 | -------------------------------------------------------------------------------- /test/input128.zc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct foo { 4 | int val; 5 | struct foo *next; 6 | }; 7 | 8 | struct foo head, mid, tail; 9 | 10 | int main() { 11 | struct foo *ptr; 12 | tail.val= 20; tail.next= NULL; 13 | mid.val= 15; mid.next= &tail; 14 | head.val= 10; head.next= ∣ 15 | 16 | ptr= &head; 17 | printf("%d %d\n", head.val, ptr->val); 18 | printf("%d %d\n", mid.val, ptr->next->val); 19 | printf("%d %d\n", tail.val, ptr->next->next->val); 20 | return(0); 21 | } 22 | -------------------------------------------------------------------------------- /test/input129.zc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int x= 6; 4 | 5 | int main() { 6 | printf("%d\n", x++ ++); 7 | return(0); 8 | } 9 | 10 | -------------------------------------------------------------------------------- /test/input130.zc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | char *x= "foo"; 4 | 5 | int main() { 6 | printf("Hello " "world" "\n"); 7 | return(0); 8 | } 9 | -------------------------------------------------------------------------------- /test/input131.zc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void donothing() { } 4 | 5 | int main() { 6 | int x=0; 7 | printf("Doing nothing... "); donothing(); 8 | printf("nothing done\n"); 9 | 10 | while (++x < 100) ; 11 | printf("x is now %d\n", x); 12 | 13 | return(0); 14 | } 15 | -------------------------------------------------------------------------------- /test/input132.zc: -------------------------------------------------------------------------------- 1 | extern int fred; 2 | int fred; 3 | 4 | int mary; 5 | extern int mary; 6 | 7 | int main() { return(0); } 8 | -------------------------------------------------------------------------------- /test/input133.zc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | extern int fred[]; 4 | int fred[23]; 5 | 6 | char mary[100]; 7 | extern char mary[]; 8 | 9 | void main() { printf("OK\n"); } 10 | -------------------------------------------------------------------------------- /test/input134.zc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | char y = 'a'; 4 | char *x; 5 | 6 | int main() { 7 | x= &y; if (x && y == 'a') printf("1st match\n"); 8 | x= NULL; if (x && y == 'a') printf("2nd match\n"); 9 | x= &y; y='b'; if (x && y == 'a') printf("3rd match\n"); 10 | return(0); 11 | } 12 | -------------------------------------------------------------------------------- /test/input135.zc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void fred() { 4 | int x= 5; 5 | printf("testing x\n"); 6 | if (x > 4) return; 7 | printf("x below 5\n"); 8 | } 9 | 10 | int main() { 11 | fred(); 12 | return(0); 13 | } 14 | -------------------------------------------------------------------------------- /test/input136.zc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int add(int x, int y) { 4 | return(x+y); 5 | } 6 | 7 | int main() { 8 | int result; 9 | result= 3 * add(2,3) - 5 * add(4,6); 10 | printf("%d\n", result); 11 | return(0); 12 | } 13 | -------------------------------------------------------------------------------- /test/input137.zc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int a=1, b=2, c=3, d=4, e=5, f=6, g=7, h=8; 4 | 5 | int main() { 6 | int x; 7 | x= ((((((a + b) + c) + d) + e) + f) + g) + h; 8 | x= a + (b + (c + (d + (e + (f + (g + h)))))); 9 | printf("x is %d\n", x); 10 | return(0); 11 | } 12 | -------------------------------------------------------------------------------- /test/input138.zc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int x, y, z; 4 | 5 | int a=1; 6 | int *aptr; 7 | 8 | int main() { 9 | 10 | for (x=0; x <= 1; x++) 11 | for (y=0; y <= 1; y++) { 12 | z= x && y; 13 | printf("%d %d | %d\n", x, y, z); 14 | } 15 | 16 | for (x=0; x <= 1; x++) 17 | for (y=0; y <= 1; y++) { 18 | z= x || y; 19 | printf("%d %d | %d\n", x, y, z); 20 | } 21 | 22 | aptr= NULL; 23 | if (aptr && *aptr == 1) 24 | printf("aptr points at 1\n"); 25 | else 26 | printf("aptr is NULL or doesn't point at 1\n"); 27 | 28 | aptr= &a; 29 | if (aptr && *aptr == 1) 30 | printf("aptr points at 1\n"); 31 | else 32 | printf("aptr is NULL or doesn't point at 1\n"); 33 | 34 | return(0); 35 | } 36 | -------------------------------------------------------------------------------- /test/input139.zc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int same(int x) { return(x); } 4 | 5 | int main() { 6 | int a= 3; 7 | 8 | if (same(a) && same(a) >= same(a)) 9 | printf("same apparently\n"); 10 | return(0); 11 | } 12 | -------------------------------------------------------------------------------- /test/input140.zc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | int i; 5 | int ary[5]; 6 | char z; 7 | 8 | // Write below the array 9 | z= 'H'; 10 | 11 | // Fill the array 12 | for (i=0; i < 5; i++) 13 | ary[i]= i * i; 14 | 15 | // Write above the array 16 | i=14; 17 | 18 | // Print out the array 19 | for (i=0; i < 5; i++) 20 | printf("%d\n", ary[i]); 21 | 22 | // See if either side is OK 23 | printf("%d %c\n", i, z); 24 | return(0); 25 | } 26 | -------------------------------------------------------------------------------- /test/input141.zc: -------------------------------------------------------------------------------- 1 | static int fred[5]; 2 | int jim; 3 | 4 | int foo(int mary[6]) { return(5); } 5 | -------------------------------------------------------------------------------- /test/input142.zc: -------------------------------------------------------------------------------- 1 | static int fred[]; 2 | int jim; 3 | -------------------------------------------------------------------------------- /test/input143.zc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | char foo; 4 | char *a, *b, *c; 5 | 6 | int main() { 7 | 8 | a= b= c= NULL; 9 | if (a==NULL || b==NULL || c==NULL) 10 | printf("One of the three is NULL\n"); 11 | a= &foo; 12 | if (a==NULL || b==NULL || c==NULL) 13 | printf("One of the three is NULL\n"); 14 | b= &foo; 15 | if (a==NULL || b==NULL || c==NULL) 16 | printf("One of the three is NULL\n"); 17 | c= &foo; 18 | if (a==NULL || b==NULL || c==NULL) 19 | printf("One of the three is NULL\n"); 20 | else 21 | printf("All three are non-NULL\n"); 22 | 23 | return(0); 24 | } 25 | -------------------------------------------------------------------------------- /test/input144.zc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | char *filename= "fred"; 5 | int main() { 6 | fprintf(stdout, "Unable to open %s: %s\n", filename, strerror(errno)); 7 | return(0); 8 | } 9 | -------------------------------------------------------------------------------- /test/input145.zc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | char *str= "qwertyuiop"; 4 | 5 | int list[]= {3, 5, 7, 9, 11, 13, 15}; 6 | 7 | int *lptr; 8 | 9 | int main() { 10 | printf("%c\n", *str); 11 | str= str + 1; printf("%c\n", *str); 12 | str += 1; printf("%c\n", *str); 13 | str += 1; printf("%c\n", *str); 14 | str -= 1; printf("%c\n", *str); 15 | 16 | lptr= list; 17 | printf("%d\n", *lptr); 18 | lptr= lptr + 1; printf("%d\n", *lptr); 19 | lptr += 1; printf("%d\n", *lptr); 20 | lptr += 1; printf("%d\n", *lptr); 21 | lptr -= 1; printf("%d\n", *lptr); 22 | return(0); 23 | } 24 | -------------------------------------------------------------------------------- /test/input146.zc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | char *str= "qwertyuiop"; 4 | 5 | int list[]= {3, 5, 7, 9, 11, 13, 15}; 6 | 7 | int *lptr; 8 | 9 | int main() { 10 | printf("%c\n", *str); 11 | str= str + 1; printf("%c\n", *str); 12 | str += 1; printf("%c\n", *str); 13 | str += 1; printf("%c\n", *str); 14 | str -= 1; printf("%c\n", *str); 15 | str++; printf("%c\n", *str); 16 | str--; printf("%c\n", *str); 17 | ++str; printf("%c\n", *str); 18 | --str; printf("%c\n\n", *str); 19 | 20 | lptr= list; 21 | printf("%d\n", *lptr); 22 | lptr= lptr + 1; printf("%d\n", *lptr); 23 | lptr += 1; printf("%d\n", *lptr); 24 | lptr += 1; printf("%d\n", *lptr); 25 | lptr -= 1; printf("%d\n", *lptr); 26 | lptr++ ; printf("%d\n", *lptr); 27 | lptr-- ; printf("%d\n", *lptr); 28 | ++lptr ; printf("%d\n", *lptr); 29 | --lptr ; printf("%d\n", *lptr); 30 | return(0); 31 | } 32 | -------------------------------------------------------------------------------- /test/input147.zc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int a; 4 | 5 | int main() { 6 | printf("%d\n", 24 % 9); 7 | printf("%d\n", 31 % 11); 8 | a= 24; a %= 9; printf("%d\n",a); 9 | a= 31; a %= 11; printf("%d\n",a); 10 | return(0); 11 | } 12 | -------------------------------------------------------------------------------- /test/input148.zc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | char *argv[]= { "unused", "-fish", "-cat", "owl" }; 4 | int argc= 4; 5 | 6 | int main() { 7 | int i; 8 | 9 | for (i = 1; i < argc; i++) { 10 | printf("i is %d\n", i); 11 | if (*argv[i] != '-') break; 12 | } 13 | 14 | while (i < argc) { 15 | printf("leftover %s\n", argv[i]); 16 | i++; 17 | } 18 | 19 | return (0); 20 | } 21 | -------------------------------------------------------------------------------- /test/input149.zc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static int localOffset=0; 4 | 5 | static int newlocaloffset(int size) { 6 | localOffset += (size > 4) ? size : 4; 7 | return (-localOffset); 8 | } 9 | 10 | int main() { 11 | int i, r; 12 | for (i=1; i <= 12; i++) { 13 | r= newlocaloffset(i); 14 | printf("%d %d\n", i, r); 15 | } 16 | return(0); 17 | } 18 | -------------------------------------------------------------------------------- /test/input150.zc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct Svalue { 5 | char *thing; 6 | int vreg; 7 | int intval; 8 | }; 9 | 10 | struct IR { 11 | int label; 12 | int op; 13 | struct Svalue dst; 14 | struct Svalue src1; 15 | struct Svalue src2; 16 | int jmplabel; 17 | }; 18 | 19 | struct foo { 20 | int a; 21 | int b; 22 | struct Svalue *c; 23 | int d; 24 | }; 25 | 26 | struct IR *fred; 27 | struct foo jane; 28 | 29 | int main() { 30 | fred= (struct IR *)malloc(sizeof(struct IR)); 31 | fred->label= 1; 32 | fred->op= 2; 33 | fred->dst.thing= NULL; 34 | fred->dst.vreg=3; 35 | fred->dst.intval=4; 36 | fred->src1.thing= NULL; 37 | fred->src1.vreg=5; 38 | fred->src1.intval=6; 39 | fred->src2.thing= NULL; 40 | fred->src2.vreg=7; 41 | fred->src2.intval=8; 42 | fred->jmplabel= 9; 43 | 44 | printf("%d %d %d\n", fred->label, fred->op, fred->dst.vreg); 45 | printf("%d %d %d\n", fred->dst.intval, fred->src1.vreg, fred->src1.intval); 46 | printf("%d %d %d\n\n", fred->src2.vreg, fred->src2.intval, fred->jmplabel); 47 | 48 | jane.c= (struct Svalue *)malloc(sizeof(struct Svalue)); 49 | jane.a= 1; jane.b= 2; jane.d= 4; 50 | jane.c->thing= "fish"; 51 | jane.c->vreg= 3; 52 | jane.c->intval= 5; 53 | 54 | printf("%d %d %d\n", jane.a, jane.b, jane.c->vreg); 55 | printf("%d %d %s\n", jane.d, jane.c->intval, jane.c->thing); 56 | 57 | return (0); 58 | } 59 | -------------------------------------------------------------------------------- /test/input151.zc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void fred() { 4 | int x= 5; 5 | printf("testing x\n"); 6 | if (x > 4) return; 7 | printf("x below 5\n"); 8 | } 9 | 10 | int bar(int a, int b) { 11 | // 表达式 12 | return (a + b); 13 | } 14 | 15 | int main() { 16 | fred(); 17 | printf("bar = %d\n", bar(1, 2)); 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /test/input152.zc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int fib(int n) { 4 | if (n <= 1) return (n); 5 | return (fib(n - 1) + fib(n - 2)); 6 | } 7 | 8 | int main() { 9 | printf("fib(10) = %d\n", fib(10)); 10 | return (0); 11 | } 12 | -------------------------------------------------------------------------------- /test/input153.zc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | int x = 2; 5 | switch(x) { 6 | case 0: 7 | x = 777; 8 | break; 9 | case 1: 10 | case 2: 11 | x = 888; 12 | break; 13 | default: 14 | x = 999; 15 | break; 16 | } 17 | 18 | printf("x = %d\n", x); 19 | return (0); 20 | } 21 | -------------------------------------------------------------------------------- /test/make_test: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # TEST="test" 4 | # ASSERT="assert" 5 | # ERROR="error" 6 | 7 | # (cd $TEST) 8 | 9 | if [ ! -f ../parser ]; 10 | then 11 | (cd ..; make clean && make) 12 | fi 13 | 14 | # if [ "$1" = "-s" ]; 15 | # then 16 | # # 不能为空串 17 | # if [ -z "$2" ]; 18 | # then 19 | # echo "Warning:" 20 | # echo "-s means make a single test" 21 | # echo "You should type like './make_test -s 01'" 22 | # exit 1 23 | # fi 24 | 25 | # if [ ! -f "input$2.zc" ]; 26 | # then 27 | # echo "Can't find file input$2.zc" 28 | # exit 1 29 | # fi 30 | 31 | # if [ ! -f "${ASSERT}/out.input$2.zc" -a ! -f "${ERROR}/error.input$2.zc" ]; 32 | # then 33 | # ../parser input$2.zc 2> "${ERROR}/error.input$2.zc" 34 | # if [ ! -s "${ERROR}/error.input$2.zc" ]; 35 | # then 36 | # cp input$2.zc input$2.c 37 | # cc -o out input$2.c 38 | # ./out > assert/out.input$2.zc 39 | # rm -f input$2.c "${ERROR}/error.input$2.zc" 40 | # fi 41 | # fi 42 | # rm -f out out.s 43 | 44 | # (cd ..) 45 | # exit 0 46 | # fi 47 | 48 | for i in input*zc 49 | do if [ ! -f "assert/out.$i" -a ! -f "error/error.$i" ] 50 | then 51 | echo "gen $i error..." 52 | ../parser -o out $i 2> "error/error.$i" 53 | echo "gen $i error Ok!" 54 | if [ ! -s "error/error.$i" ]; 55 | then 56 | echo "gen $i assert..." 57 | cp $i ${i%%.*}.c 58 | cc -o out ${i%%.*}.c 59 | ./out > assert/out.$i 60 | echo "gen $i assert Ok!" 61 | rm -f ${i%%.*}.c "error/error.$i" ${i%%.*}.s 62 | fi 63 | fi 64 | rm -f out out.s 65 | done 66 | -------------------------------------------------------------------------------- /test/run_test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PARSER=../parser 4 | PARSER_NAME=parser 5 | 6 | if [[ $1 = 0 || $1 = 2 || $1 = 2 ]]; then 7 | PARSER=../parser$1 8 | PARSER_NAME=parser$1 9 | fi 10 | 11 | echo "Use $PARSER" 12 | 13 | if [ ! -f $PARSER ]; 14 | then (cd ..; make clean && make $PARSER_NAME); 15 | fi 16 | 17 | for i in input* 18 | do if [ ! -f "assert/out.$i" -a ! -f "error/error.$i" ]; 19 | then 20 | echo "Can't run test on $i, no output file!" 21 | 22 | else if [ -f "assert/out.$i" ]; 23 | then 24 | echo -n "test $i..." 25 | $PARSER -o out $i 26 | ./out > assert/trial.$i 27 | cmp -s "assert/out.$i" "assert/trial.$i" 28 | if [ "$?" -eq "1" ]; 29 | then 30 | echo ": Failed" 31 | diff -c "assert/out.$i" "assert/trial.$i" 32 | echo 33 | else 34 | echo ": Ok" 35 | fi 36 | 37 | else if [ -f "error/error.$i" ]; 38 | then 39 | echo -n "gen $i error file..." 40 | $PARSER $i 2> "assert/trial.$i" 41 | cmp -s "error/error.$i" "assert/trial.$i" 42 | if [ "$?" -eq "1" ]; 43 | then 44 | echo ": Failed" 45 | diff -c "error/error.$i" "assert/trial.$i" 46 | echo 47 | else 48 | echo ": Ok" 49 | fi 50 | fi 51 | 52 | fi 53 | fi 54 | rm -rf out out.s "assert/trial.$i" *.s *.o 55 | done 56 | -------------------------------------------------------------------------------- /types.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "definations.h" 3 | #include "generator.h" 4 | #include "helper.h" 5 | #include "types.h" 6 | #include "ast.h" 7 | 8 | int check_int_type(int primitive_type) { 9 | return ((primitive_type & 0xf) == 0 && 10 | (primitive_type >= PRIMITIVE_CHAR && primitive_type <= PRIMITIVE_LONG)); 11 | } 12 | 13 | int check_pointer_type(int primitive_type) { 14 | return ((primitive_type & 0xf) != 0); 15 | } 16 | 17 | int get_primitive_type_size( 18 | int primitive_type, 19 | struct SymbolTable *composite_type 20 | ) { 21 | if (primitive_type == PRIMITIVE_STRUCT || primitive_type == PRIMITIVE_UNION) { 22 | return (composite_type->size); 23 | } 24 | return (generate_get_primitive_type_size(primitive_type)); 25 | } 26 | 27 | // 修改一个 ast node 的 type 类型,以便与给定的类型兼容 28 | // 对于指针来说,如果是一个二元运算(+ 或者 -),那么 ast 的 operation 就是非 0 29 | struct ASTNode *modify_type( 30 | struct ASTNode *tree, 31 | int right_primitive_type, 32 | int operation, 33 | struct SymbolTable *right_composite_type) { 34 | int left_primitive_size, right_primitive_size; 35 | int left_primitive_type = tree->primitive_type; 36 | 37 | // 比如这种情况 38 | // int *a, b; 39 | // if (a && b > 1) {...} 40 | // 如果是 && 或者 || 41 | // left 和 right 的 type 必须都是 int 类型 或者指针类型 42 | if (operation == AST_LOGIC_AND || operation == AST_LOGIC_OR) { 43 | if (!check_int_type(left_primitive_type) && 44 | !check_pointer_type(left_primitive_type)) 45 | return (NULL); 46 | if (!check_int_type(left_primitive_type) && 47 | !check_pointer_type(right_primitive_type)) 48 | return (NULL); 49 | return (tree); 50 | } 51 | 52 | // 特殊情况判断 53 | if (left_primitive_type == PRIMITIVE_STRUCT || 54 | left_primitive_type == PRIMITIVE_UNION) 55 | error("Does not support this type casting yet"); 56 | if (right_primitive_type == PRIMITIVE_STRUCT || 57 | right_primitive_type == PRIMITIVE_UNION) 58 | error("Does not support this type casting yet"); 59 | 60 | // 比较 char/int/long 61 | if (check_int_type(left_primitive_type) && check_int_type(right_primitive_type)) { 62 | if (left_primitive_type == right_primitive_type) return (tree); 63 | 64 | left_primitive_size = get_primitive_type_size(left_primitive_type, NULL); 65 | right_primitive_size = get_primitive_type_size(right_primitive_type, NULL); 66 | 67 | if (left_primitive_size > right_primitive_size) return (NULL); 68 | else if (left_primitive_size < right_primitive_size) 69 | return (create_ast_left_node(AST_WIDEN, right_primitive_type, tree, 0, NULL, NULL)); 70 | } 71 | 72 | // 比较 char/int/long 指针 73 | if (check_pointer_type(left_primitive_type) && 74 | check_pointer_type(right_primitive_type)) { 75 | 76 | // 如果是比较操作符 77 | if (operation >= AST_COMPARE_EQUALS && operation <= AST_COMPARE_GREATER_EQUALS) 78 | return (tree); 79 | 80 | if (!operation && ( 81 | left_primitive_type == right_primitive_type || 82 | left_primitive_type == pointer_to(PRIMITIVE_VOID) 83 | )) 84 | return (tree); 85 | } 86 | 87 | if (operation == AST_PLUS || 88 | operation == AST_MINUS || 89 | operation == AST_ASSIGN_PLUS || 90 | operation == AST_ASSIGN_MINUS) { 91 | if (check_int_type(left_primitive_type) && 92 | check_pointer_type(right_primitive_type)) { 93 | right_primitive_size = 94 | generate_get_primitive_type_size(value_at(right_primitive_type)); 95 | // size 比 char 大的 96 | // 强制转换 97 | if (right_primitive_size > 1) 98 | return ( 99 | create_ast_left_node( 100 | AST_SCALE, 101 | right_primitive_type, 102 | tree, 103 | right_primitive_size, 104 | NULL, 105 | right_composite_type) 106 | ); 107 | // 如果 size 就是 char,那么就返回这颗树 108 | return (tree); 109 | } 110 | } 111 | 112 | return (NULL); 113 | } 114 | 115 | 116 | int pointer_to(int primitive_type) { 117 | if ((primitive_type & 0xf) == 0xf) 118 | error_with_digital("Unrecognised in pointer_to: primitive type", primitive_type); 119 | return (primitive_type + 1); 120 | } 121 | 122 | int value_at(int primitive_type) { 123 | if ((primitive_type & 0xf) == 0x0) 124 | error_with_digital("Unrecognised in value_at: primitive type", primitive_type); 125 | return (primitive_type - 1); 126 | } 127 | -------------------------------------------------------------------------------- /types.h: -------------------------------------------------------------------------------- 1 | #ifndef __TYPES_H__ 2 | #define __TYPES_H__ 3 | 4 | int pointer_to(int primitive_type); 5 | int value_at(int primitive_type); 6 | int check_int_type(int primitive_type); 7 | int check_pointer_type(int primitive_type); 8 | int get_primitive_type_size( 9 | int primitive_type, 10 | struct SymbolTable *composite_type 11 | ); 12 | struct ASTNode *modify_type( 13 | struct ASTNode *tree, 14 | int right_primitive_type, 15 | int operation, 16 | struct SymbolTable *right_composite_type 17 | ); 18 | 19 | #endif 20 | --------------------------------------------------------------------------------