├── .vscode └── settings.json ├── Makefile ├── README.md ├── build └── ir ├── doc ├── SC_requirement.md └── syntax.md ├── example ├── lex1.c ├── lex2.c └── lex3.c ├── include ├── dyn.h ├── dynstack.h ├── error.h ├── json.h ├── lex.h ├── symbol.h ├── syntax.h └── token.h └── src ├── dyn.c ├── dynstack.c ├── error.c ├── ir.c ├── json.c ├── lex.c ├── lexcolor.c ├── symbol.c ├── syntax.c ├── syntaxindent.c └── token.c /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "iosfwd": "cpp", 4 | "algorithm": "cpp", 5 | "cctype": "cpp", 6 | "clocale": "cpp", 7 | "cmath": "cpp", 8 | "cstdarg": "cpp", 9 | "cstddef": "cpp", 10 | "cstdio": "cpp", 11 | "cstdlib": "cpp", 12 | "cstring": "cpp", 13 | "ctime": "cpp", 14 | "cwchar": "cpp", 15 | "cwctype": "cpp", 16 | "array": "cpp", 17 | "atomic": "cpp", 18 | "strstream": "cpp", 19 | "*.tcc": "cpp", 20 | "bitset": "cpp", 21 | "chrono": "cpp", 22 | "complex": "cpp", 23 | "cstdint": "cpp", 24 | "deque": "cpp", 25 | "list": "cpp", 26 | "unordered_map": "cpp", 27 | "vector": "cpp", 28 | "exception": "cpp", 29 | "functional": "cpp", 30 | "optional": "cpp", 31 | "ratio": "cpp", 32 | "string_view": "cpp", 33 | "system_error": "cpp", 34 | "tuple": "cpp", 35 | "type_traits": "cpp", 36 | "fstream": "cpp", 37 | "initializer_list": "cpp", 38 | "iomanip": "cpp", 39 | "iostream": "cpp", 40 | "istream": "cpp", 41 | "limits": "cpp", 42 | "memory": "cpp", 43 | "new": "cpp", 44 | "ostream": "cpp", 45 | "numeric": "cpp", 46 | "sstream": "cpp", 47 | "stdexcept": "cpp", 48 | "streambuf": "cpp", 49 | "thread": "cpp", 50 | "cfenv": "cpp", 51 | "cinttypes": "cpp", 52 | "utility": "cpp", 53 | "typeindex": "cpp", 54 | "typeinfo": "cpp", 55 | "token.h": "c", 56 | "error.h": "c", 57 | "errno.h": "c" 58 | } 59 | } -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | CFLAGS=-I include/ 3 | LD=ld 4 | LDFLAGS=-I include/ 5 | BIN=lex syntax 6 | 7 | .PHONY: clean 8 | 9 | TARGET: lex syntax 10 | mkdir build 11 | mv $^ build/ 12 | 13 | lex : src/lexcolor.c src/lex.c src/token.c src/dyn.c src/error.c 14 | $(CC) $(CFLAGS) -o $@ $^ 15 | 16 | syntax : src/syntaxindent.c src/syntax.c src/lex.c src/token.c src/error.c src/dyn.c 17 | $(CC) $(CFLAGS) -o $@ $^ -D __SYNTAX_INDENT 18 | 19 | clean: 20 | rm -rf build/ 21 | 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 自己动手写编译器、链接器的前5章实现 2 | 3 | 在项目文件夹下使用make工具即可编译完成 4 | 5 | `lex`是分词功能,对C语言中的关键字、常量、符号、变量名等涂色区分。 6 | `syntax`不仅实现了对不同词的涂色区分,还有根据语法的缩进功能。 7 | 8 | 目前支持的功能: 9 | ## 源码字符集 10 | - 大小写字母和下划线 11 | - 数字 12 | - 标点以及特殊字符:+ - * / % = ! < > . & ( ) [ ] { } ; , \ " ' 13 | - 空白符 14 | - 空字符 15 | 16 | ## SC语言词法定义 17 | ### 关键字 18 | 参照C89要求,有如下关键字,其语义与C89的相似或一致 19 | - char 20 | - short 21 | - int 22 | - void 23 | - struct 24 | - if 25 | - else 26 | - for 27 | - continue 28 | - break 29 | - return 30 | - sizeof 31 | 32 | ### 标识符 33 | 参照C89要求,标识符的语法定义与C89一致,语义也一致: 34 | id -> letter_ | (letter_ | digit)* 35 | letter_ -> [a-zA-Z_] 36 | digit -> [0-9] 37 | 38 | ### 整数常量 39 | 目前仅考虑整数类型,因此,参照C89要求做如下定义: 40 | int_num -> digit+ 41 | digit -> [0-9] 42 | 43 | ### 字符常量 44 | 参照C89要求,字符常量定义与C89一致,语义也一致: 45 | constchar -> ' char ' 46 | char -> ([a-zA-Z0-9] | schar) 47 | schar -> \n | \b | \r | \t | , | . | & | | | + ... 48 | 49 | ### 字符串常量 50 | 参照C89要求,字符串常量定义与C89一致,语义也一致: 51 | str -> " constchar* " 52 | 53 | ### 运算以及分隔符 54 | 参照C89要求,运算符号的定义与C89一致,语义也一致: 55 | 支持如下运算符号: 56 | - \+ 57 | - \- 58 | - \* 59 | - / 60 | - % 61 | - == 62 | - != 63 | - < 64 | - \> 65 | - <= 66 | - \>= 67 | - & 68 | - | 69 | - -> 70 | - . 71 | - ( 72 | - ) 73 | - [ 74 | - ] 75 | - { 76 | - } 77 | - , 78 | 79 | 分隔符为; 80 | 81 | ### 注释 82 | 仅支持/* */的注释符号 -------------------------------------------------------------------------------- /build/ir: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dingfen/syntax_indent/ce206a07cd28d2d5841276a364a795d9006fcf14/build/ir -------------------------------------------------------------------------------- /doc/SC_requirement.md: -------------------------------------------------------------------------------- 1 | [TOC] 2 | 3 | # 具体需求 4 | 5 | 以C89为蓝本,开发一种Simple C语言的编译器。 6 | 有以下简化原则: 7 | - 支持单字节、双字节、四字节的基本数据类型 8 | - 支持数组、结构体 9 | - 支持字符串 10 | - 支持函数、局部变量、全局变量 11 | - 支持条件语句、循环语句 12 | - 支持基本的算术运算、关系运算 13 | 14 | ## 源码字符集 15 | - 大小写字母和下划线 16 | - 数字 17 | - 标点以及特殊字符:+ - * / % = ! < > . & ( ) [ ] { } ; , \ " ' 18 | - 空白符 19 | - 空字符 20 | 21 | ## SC语言词法定义 22 | ### 关键字 23 | 参照C89要求,有如下关键字,其语义与C89的相似或一致 24 | - char 25 | - short 26 | - int 27 | - void 28 | - struct 29 | - if 30 | - else 31 | - for 32 | - continue 33 | - break 34 | - return 35 | - sizeof 36 | 37 | ### 标识符 38 | 参照C89要求,标识符的语法定义与C89一致,语义也一致: 39 | id -> letter_ | (letter_ | digit)* 40 | letter_ -> [a-zA-Z_] 41 | digit -> [0-9] 42 | 43 | ### 整数常量 44 | 目前仅考虑整数类型,因此,参照C89要求做如下定义: 45 | int_num -> digit+ 46 | digit -> [0-9] 47 | 48 | ### 字符常量 49 | 参照C89要求,字符常量定义与C89一致,语义也一致: 50 | constchar -> ' char ' 51 | char -> ([a-zA-Z0-9] | schar) 52 | schar -> \n | \b | \r | \t | , | . | & | | | + ... 53 | 54 | ### 字符串常量 55 | 参照C89要求,字符串常量定义与C89一致,语义也一致: 56 | str -> " constchar* " 57 | 58 | ### 运算以及分隔符 59 | 参照C89要求,运算符号的定义与C89一致,语义也一致: 60 | 支持如下运算符号: 61 | - \+ 62 | - \- 63 | - \* 64 | - / 65 | - % 66 | - == 67 | - != 68 | - < 69 | - \> 70 | - <= 71 | - \>= 72 | - & 73 | - | 74 | - -> 75 | - . 76 | - ( 77 | - ) 78 | - [ 79 | - ] 80 | - { 81 | - } 82 | - , 83 | 84 | 分隔符为; 85 | 86 | ### 注释 87 | 仅支持/* */的注释符号 88 | 89 | ### 未来可能会支持的C语言语法 90 | 91 | - 运算符 自加 自减操作 92 | - 运算符 逻辑或、逻辑与、逻辑取反操作 93 | - 运算符 按位取反操作 94 | - 运算符 移位操作 95 | - 各类复合赋值运算操作符 96 | 97 | ## SC语法定义 98 | ### 外部定义 99 | 由于还需要实现链接器,因此将每个SC源文件看作是一个翻译单元,由一系列的外部声明组成,它们出现在任何函数之外,具有全局作用域。 100 | #### 外部定义 101 | TranslateUnit -> (ExternDeclaration)* EOF 102 | 103 | ExternDeclaration -> func_def | declaration 104 | 105 | #### 函数定义 106 | func_def -> type decl_id func_body 107 | 108 | func_body -> multi_statement 109 | 110 | #### 声明 111 | 声明规定一组标识符的解释和属性,与C89类似,在声明变量时,必须先明确类型,可以使用逗号声明多个标识符,可选地赋予初始值 112 | 113 | declaration -> type (sdecls)+ ; 114 | 115 | sdecls -> sdecl ( , sdecl)* 116 | 117 | sdecl -> decl_id | decl_id = init_val 118 | 119 | #### 类型 120 | SC的类型除了没有浮点等类型外,与C89保持一致,结构体的声明情况值得注意。 121 | 122 | type -> void | char | short | int | structid 123 | 124 | structid -> struct id { structdecls } | struct id 125 | 126 | structdecls -> (structdecl)+ 127 | 128 | structdecl -> type struct_decl_id ; 129 | 130 | struct_decl_id -> decl_id ( , decl_id)* 131 | 132 | #### 声明符 133 | decl_id -> (pointer)* (direct_decl_id) 134 | 135 | pointer -> * 136 | 137 | direct_decl_id -> id direct_decl_id_suffix 138 | 139 | direct_decl_id_suffix -> ( [ ] | [ int_num ] | ( ) | ( args_list ) )* 140 | 141 | 142 | #### 初始值 143 | init_val -> assign_expr 144 | 145 | ### 语句 146 | 参照C89标准,结合之前已经地定义的原则等,做出如下定义: 147 | 148 | statement -> multi_statement | if_statement | for_statement |break_statement 149 | | for_statement | continue_statement | return_statement | expr_statement 150 | 151 | #### 复合语句 152 | 相当于C89中用大括号括起来的语句 153 | 154 | multi_statement -> { (declaration | statement)* } 155 | 156 | #### 表达式语句 157 | expr_statement -> expr ; 158 | 159 | #### 选择语句 160 | if_statement -> if ( expr ) statement (else statement)? 161 | 162 | #### 循环语句 163 | for_statement -> for ( expr_statement expr_statement expr ) 164 | 165 | #### 跳转语句 166 | continue_statement -> continue ; 167 | 168 | return_statement -> return expr ; 169 | 170 | break_statement -> break ; 171 | 172 | ### 表达式 173 | expr -> assign_expr ( , assign_expr)* 174 | 175 | #### 赋值表达式 176 | assign_expr -> equal_expr | unary_expr = assign_expr 177 | 178 | #### 相等类表达式 179 | equal_expr -> rel_expr (== rel_expr | != rel_expr)* 180 | 181 | #### 关系表达式 182 | rel_expr -> add_expr ( < add_expr | > add_expr | <= add_expr | >= add_expr )* 183 | 184 | #### 加减表达式 185 | add_expr -> mul_expr ( + mul_expr | - mul_expr )* 186 | 187 | #### 乘除表达式 188 | mul_expr -> unary_expr ( * unary_expr | / unary_expr | % unary_expr )* 189 | 190 | #### 一元表达式 191 | unary_expr -> suffix_expr | & unary_expr | | unary_expr | + unary_expr | - 192 | unary_expr | sizeof_expr 193 | 194 | sizeof_expr -> sizeof (type) 195 | 196 | #### 后缀表达式 197 | suffix_expr -> primary_expr ( [ expr ] | ( ) | ( ars ) | . id | -> id )* 198 | 199 | ars -> assign_expr ( , assign_expr )* 200 | 201 | #### 初等表达式 202 | primary_expr -> id | int_num | strs | constchar | ( expr ) 203 | 204 | -------------------------------------------------------------------------------- /doc/syntax.md: -------------------------------------------------------------------------------- 1 | # SC语法分析与中间代码生成 2 | 3 | 4 | -------------------------------------------------------------------------------- /example/lex1.c: -------------------------------------------------------------------------------- 1 | int main() 2 | { 3 | int a = 2; 4 | int b = 3; 5 | int c; 6 | char *d = "asbsdq"; 7 | c = a + b * 2; 8 | return 0; 9 | } -------------------------------------------------------------------------------- /example/lex2.c: -------------------------------------------------------------------------------- 1 | void foo(int arg1, char arg2) 2 | { 3 | printf("hello world\n"); 4 | printf("%d %c\n", arg1, arg2); 5 | } 6 | 7 | int main() 8 | { 9 | int a = 2; 10 | int b = 3; 11 | int c; 12 | char *d = "asbsdq"; 13 | c = a + b * 2; 14 | if (c >= 3) 15 | foo(c, d[2]); 16 | else { 17 | foo(14, d[1]); 18 | } 19 | for(a = 0; a < 10; a=a+1) { 20 | b = b + a; 21 | printf("%d\n", b); 22 | } 23 | return 0; 24 | } -------------------------------------------------------------------------------- /example/lex3.c: -------------------------------------------------------------------------------- 1 | void foo(int arg1, char arg2) 2 | { 3 | printf("hello world\n"); 4 | printf("%d %c\n", arg1, arg2); 5 | } 6 | 7 | int main() 8 | { 9 | char *d = "awesbsdq"; 10 | int i; 11 | for(i = 0; i < strlen(d); i=i+1) { 12 | if (d[i] > 's') { 13 | d[i] = d[i]+1; /* for d[i]++ */ 14 | } else { 15 | d[i] = 0; 16 | } 17 | } 18 | return 0; 19 | } -------------------------------------------------------------------------------- /include/dyn.h: -------------------------------------------------------------------------------- 1 | // C语言中没有提供动态存储下的字符串和数组的便捷操作 2 | // 需要自己实现 3 | 4 | #ifndef __MY_SCC_DYN_ 5 | #define __MY_SCC_DYN_ 6 | 7 | #include 8 | 9 | #include "error.h" 10 | 11 | typedef struct DynString 12 | { 13 | int count; // 字符串长度 14 | int capacity; // 分配到的缓冲区容量 15 | char *data; // 指向字符串的指针 16 | } DynString; 17 | 18 | typedef struct DynArray 19 | { 20 | int count; // 数组元素个数 21 | int capacity; // 缓冲区容量 22 | void **data; // 指向数据指针数组 23 | } DynArray; 24 | 25 | /** 26 | * 初始化动态字符串存储容量 27 | * pstr 动态字符串存储结构 28 | * initsize 初始化分配的大小 29 | */ 30 | void dynstring_init(DynString *pstr, int initsize); 31 | 32 | /** 33 | * 释放动态字符串使用的空间 34 | * pstr 动态字符串存储结构 35 | */ 36 | void dynstring_free(DynString *pstr); 37 | 38 | /** 39 | * 重置动态字符串,先释放,再分配 40 | * pstr 动态字符串存储结构 41 | */ 42 | void dynstring_reset(DynString *pstr); 43 | 44 | /** 45 | * pstr 动态字符串存储结构 46 | * new_size 字符串新长度 47 | */ 48 | void dynstring_realloc(DynString *pstr, int new_size); 49 | 50 | /** 51 | * 追加字符到动态字符串中 52 | * pstr 动态字符串存储结构 53 | * ch 追加啊的字符 54 | */ 55 | void dynstring_append(DynString *pstr, char ch); 56 | 57 | /** 58 | * 初始化动态数组存储容量 59 | * parr 动态数组存储结构 60 | * initsize 动态数组初始化分配空间 61 | */ 62 | void dynarray_init(DynArray *parr, int initsize); 63 | 64 | /** 65 | * 释放动态数组使用的内存空间 66 | * parr 动态数组存储结构 67 | */ 68 | void dynarray_free(DynArray *parr); 69 | 70 | /** 71 | * 动态数组元素查找 72 | * parr 动态数组存储结构 73 | * key 要查找的元素 74 | */ 75 | int dynarray_search(DynArray *parr, int key); 76 | 77 | /** 78 | * 重新分配动态数组容量 79 | * parr 动态数组存储结构 80 | * new_size 动态数组新的大小 81 | */ 82 | void dynarray_realloc(DynArray *parr, int new_size); 83 | 84 | /** 85 | * 追加动态数组元素 86 | * parr 动态数组存储结构 87 | * data 追加的元素 88 | */ 89 | void dynarray_add(DynArray *parr, void *data); 90 | 91 | 92 | 93 | #endif // __MY_SCC_DYN_ -------------------------------------------------------------------------------- /include/dynstack.h: -------------------------------------------------------------------------------- 1 | #ifndef __MY_SCC_STACK_ 2 | #define __MY_SCC_STACK_ 3 | 4 | #include 5 | #include 6 | #include "error.h" 7 | 8 | typedef struct Stack { 9 | void **base; // 栈低指针 10 | void **top; // 栈顶指针 11 | int stacksize; // 栈最大容量值 12 | } Stack; 13 | 14 | /** 15 | * 功能:初始化栈容量 16 | * pstack 指向栈的指针 17 | * initsize 栈大小 18 | */ 19 | void stack_init(Stack * pstack, int initsize); 20 | 21 | /** 22 | * 功能:在栈顶插入元素 23 | * pstack 指向栈的指针 24 | * element 要插入栈顶的元素 25 | * size 栈元素的实际大小 26 | * 返回值 栈顶元素指针 27 | */ 28 | void *stack_push(Stack *pstack, void *element, int size); 29 | 30 | /** 31 | * 功能:弹出栈顶元素 32 | * pstack 栈指针 33 | */ 34 | void stack_pop(Stack *pstack); 35 | 36 | /** 37 | * 功能:获取栈顶元素 38 | * pstack 栈指针 39 | * 返回值 栈顶元素 40 | */ 41 | void * stack_get_top(Stack *pstack); 42 | 43 | /** 44 | * 功能:判断栈是否为空 45 | * pstack 栈指针 46 | * 返回值 1 为空 0 不为空 47 | */ 48 | int stack_is_empty(Stack *pstack); 49 | 50 | /** 51 | * 功能:销毁栈 52 | * pstack 栈指针 53 | */ 54 | void stack_destroy(Stack *pstack); 55 | 56 | #endif // __MY_SCC_STACK_ -------------------------------------------------------------------------------- /include/error.h: -------------------------------------------------------------------------------- 1 | // 错误处理程序 2 | #ifndef __MY_SCC_ERROR_ 3 | #define __MY_SCC_ERROR_ 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | // 错误级别 11 | enum ErrorLevel 12 | { 13 | LEVEL_WARNING, 14 | LEVEL_ERROR 15 | }; 16 | 17 | // 工作阶段 18 | enum WorkStage 19 | { 20 | STAGE_COMPILE, 21 | STAGE_LINK 22 | }; 23 | 24 | /** 25 | * 异常处理 26 | * stage 编译阶段错误还是链接阶段错误 27 | * level 错误级别 28 | * fmt 参数输出格式 29 | * ap 可变参数列表 30 | */ 31 | void handle_exception(int stage, int level, char *fmt, va_list ap); 32 | 33 | /** 34 | * 编译警告处理 35 | * fmt 参数输出格式 36 | * ap 可变参数列表 37 | */ 38 | void warning(char *fmt, ...); 39 | 40 | /** 41 | * 编译错误处理 42 | * fmt 参数输出格式 43 | * ap 可变参数列表 44 | */ 45 | void error(char *fmt, ...); 46 | 47 | /** 48 | * 提示错误,缺少某个语法成分 49 | * msg 需要的语法成分 50 | */ 51 | void expect(char *msg); 52 | 53 | /** 54 | * 跳过单词c,取下一个单词 55 | * 如果不是单词c,提示错误 56 | * c 要跳过的单词 57 | */ 58 | void skip(int c); 59 | 60 | 61 | #endif // __MY_SCC_ERROR_ -------------------------------------------------------------------------------- /include/json.h: -------------------------------------------------------------------------------- 1 | #ifndef _MYSCC_JSON 2 | #define _MYSCC_JSON 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | typedef union Value 9 | { 10 | int data; 11 | const char * str; 12 | char ch; 13 | struct JSONobj *obj; 14 | } Value; 15 | 16 | typedef enum State { 17 | V_INT, 18 | V_STR, 19 | V_CHAR, 20 | V_JSON 21 | } State; 22 | 23 | typedef struct JSONobj { 24 | const char* key; 25 | Value value; 26 | State state; 27 | struct JSONobj *next; 28 | } JSONobj; 29 | 30 | void initJSON(JSONobj *pj); 31 | 32 | void destroyJSON(JSONobj *pj); 33 | 34 | void addJSON(JSONobj *pj, const char* key, Value val, State s); 35 | 36 | // void add(JSONobj *pj, const char *key, Value val, State s); 37 | 38 | void printJSON(JSONobj *obj); 39 | 40 | 41 | #endif // _MYSCC_JSON -------------------------------------------------------------------------------- /include/lex.h: -------------------------------------------------------------------------------- 1 | #ifndef __MY_SCC_LEX_ 2 | #define __MY_SCC_LEX_ 3 | 4 | #include 5 | #include 6 | 7 | #include "error.h" 8 | #include "token.h" 9 | #include "dyn.h" 10 | 11 | #define BLUE 34 12 | #define YELLOW 33 13 | #define RED 31 14 | 15 | /** 16 | * 词法分析程序初始化 17 | */ 18 | void init(); 19 | 20 | 21 | /** 22 | * 清理工作 23 | */ 24 | void cleanup(); 25 | 26 | /** 27 | * 获得取到的源码字符 28 | */ 29 | void getch(); 30 | 31 | /** 32 | * 注释处理 33 | */ 34 | void parse_comment(); 35 | 36 | /** 37 | * 空白字符处理 38 | */ 39 | void skip_white_space(); 40 | 41 | /** 42 | * 预处理,忽略空白字符及注释 43 | */ 44 | void preprocess(); 45 | 46 | /** 47 | * 判断c是否为字母或下划线 48 | */ 49 | int is_nodigit(char c); 50 | 51 | /** 52 | * 判断c是否为数字 53 | */ 54 | int is_digit(char c); 55 | 56 | /** 57 | * 解析标识符 58 | */ 59 | void parse_identifier(); 60 | 61 | /** 62 | * 解析整形常量 63 | */ 64 | void parse_num(); 65 | 66 | /** 67 | * 解析字符常量和字符串常量 68 | * sep 单引号为 字符常量 双引号为字符串常量 69 | */ 70 | void parse_string(char sep); 71 | 72 | /** 73 | * 取单词主程序 74 | */ 75 | void get_token(); 76 | 77 | 78 | 79 | #endif // __MY_SCC_LEX_ -------------------------------------------------------------------------------- /include/symbol.h: -------------------------------------------------------------------------------- 1 | #ifndef __MY_SCC_SYMBOL_ 2 | #define __MY_SCC_SYMBOL_ 3 | 4 | #include 5 | #include "dynstack.h" 6 | #include "token.h" 7 | 8 | enum TypeCode { // 数据类型编码 9 | T_INT = 0, 10 | T_CHAR = 1, 11 | T_SHORT= 2, 12 | T_VOID = 3, 13 | T_PTR = 4, 14 | T_FUNC = 5, 15 | T_STRUCT=6, 16 | 17 | T_BTYPE = 0x000f, 18 | T_ARRAY = 0x0010 19 | }; 20 | 21 | enum StorageClass { // 存储类型 22 | SC_GLOBAL = 0x00f0, // 包括常量 全局变量 函数定义 23 | SC_LOCAL = 0x00f1, // 栈中变量 24 | SC_LLOCAL = 0x00f2, // 寄存器溢出 存放在栈中的变量 25 | SC_CMP = 0x00f3, // 使用标志寄存器 26 | SC_VALMASK= 0x00ff, // 存储类型掩码 27 | SC_LVAL = 0x0100, // 左值 28 | SC_SYM = 0x0200, // 符号 29 | 30 | SC_ANOM = 0x10000000, // 匿名符号 31 | SC_STRUCT = 0x20000000, // 结构体符号 32 | SC_MEMBER = 0x40000000, // 结构体成员变量 33 | SC_PARAMS = 0x80000000 // 函数参数 34 | }; 35 | 36 | 37 | typedef struct Type // 数据类型结构 38 | { 39 | int t; // 数据类型 40 | struct Symbol *ref; // 引用符号 41 | } Type; 42 | 43 | 44 | typedef struct Symbol // 符号表项定义 45 | { 46 | int v; // 在tktable 单词表中的编码 47 | int r; // 关联的寄存器 48 | int c; // 符号关联值 49 | Type type; // 符号数据类型 50 | struct Symbol *next; // 下一个符号 51 | struct Symbol *prev; // 前一个符号 52 | } Symbol; 53 | 54 | /** 55 | * 功能:将符号放入到符号栈中 56 | * v 符号编号 57 | * type 符号数据类型 58 | * c 符号关联值 59 | */ 60 | Symbol *sym_direct_push(Stack *ss, int v, Type *type, int c); 61 | 62 | /** 63 | * 功能:将符号放在符号栈中,动态判断放入全局符号栈还是局部符号栈 64 | * v 符号编号 65 | * type 符号数据类型 66 | * r 符号存储类型 67 | * c 符号关联值 68 | */ 69 | Symbol *sym_push(int v, Type *type, int r, int c); 70 | 71 | /** 72 | * 功能:函数符号放入到全局符号表 73 | * v 符号编号 74 | * type 符号数据类型 75 | */ 76 | Symbol * func_sym_push(int v, Type *type); 77 | 78 | /** 79 | * 功能:变量符号放入到全局符号表 80 | * type 符号数据类型 81 | * r 存储类型 82 | * v 单词编号 83 | * addr 地址 84 | */ 85 | Symbol *var_sym_put(Type *type, int r, int v, int addr); 86 | 87 | /** 88 | * 功能:将节名称放入全局符号表 89 | * sec 节名称 90 | * c 符号关联值 91 | */ 92 | Symbol * sec_sym_put(char *sec, int c); 93 | 94 | /** 95 | * 功能:弹出栈中符号直到找到符号'b' 96 | * ptop:符号栈栈顶 97 | * b: 符号指针 98 | */ 99 | void sym_pop(Stack *ptop, Symbol *b); 100 | 101 | 102 | /** 103 | * 功能:查找结构定义 104 | * v 符号编号 105 | */ 106 | Symbol *struct_search(int v); 107 | 108 | /** 109 | * 功能:查找结构定义 110 | * v 符号编号 111 | */ 112 | Symbol *sym_search(int v); 113 | 114 | #endif // __MY_SCC_SYMBOL_ -------------------------------------------------------------------------------- /include/syntax.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | #define SC_GLOBAL 1 5 | #define SC_LOCAL 0 6 | #define SC_MEMBER 0 7 | 8 | 9 | /* 全局变量 */ 10 | int syntax_state; // 语法状态 11 | int syntax_level; // 缩进级别 12 | 13 | /* 语法状态枚举 */ 14 | enum SynTaxState 15 | { 16 | SNTX_NUL, // 空状态 17 | SNTX_SP, // 空格 18 | SNTX_LF_HT, // 换行并缩进 声明 定义 语句结束都置为该状态 19 | SNTX_DELAY // 延迟到取出下一个单词后确定输出格式 20 | }; 21 | 22 | /** 23 | * 功能:翻译单元,语法分析顶层 24 | * ::= {} 25 | */ 26 | void translation_unit(); 27 | 28 | /** 29 | * 功能: 解析外部声明 30 | * l: 存储类型 指明局部还是全局 31 | * ExternDeclaration 32 | * --> ( 33 | * | 34 | * | [] 35 | * {[]}) 36 | */ 37 | void external_declaration(int l); 38 | 39 | /** 40 | * 功能:解析类型区分符 41 | * 返回值:是否发现合法的类型区分符 42 | * 43 | * --> |||| 44 | */ 45 | int type_specifier(); 46 | 47 | /** 48 | * 功能:结构体类型区分符 49 | * 50 | * --> 51 | * | 52 | */ 53 | void struct_specifier(); 54 | 55 | /** 56 | * 功能:结构体中声明的变量的全体 57 | * 58 | * --> {} 59 | */ 60 | void struct_declaration_list(); 61 | 62 | /** 63 | * 功能:结构体中声明的变量 64 | * 65 | * --> 66 | * 67 | * --> {} 68 | */ 69 | void struct_declaration(); 70 | 71 | /** 72 | * 功能:声明符的解析 73 | * 74 | * --> {} 75 | */ 76 | void declarator(); 77 | 78 | /** 79 | * 功能:直接声明符解析 80 | * 81 | * --> 82 | */ 83 | void direct_declarator(); 84 | 85 | /** 86 | * 功能:直接声明符后缀 87 | * 88 | * --> {} 89 | * | 90 | * | 91 | * | 92 | */ 93 | void direct_declarator_postfix(); 94 | 95 | /** 96 | * 功能:解析形参类型表 97 | * 98 | * --> {} 99 | * --> 100 | */ 101 | void parameter_type_list(); 102 | 103 | /** 104 | * 功能:函数体解析 105 | * --> 106 | */ 107 | void funcbody(); 108 | 109 | /** 110 | * 功能:解析初值符 111 | * --> 112 | */ 113 | void initializer(); 114 | 115 | /** 116 | * 功能:语句解析 117 | * --> 118 | * | | | 119 | * | | | 120 | */ 121 | void statement(); 122 | 123 | /** 124 | * 功能:解析复合语句 125 | * --> 126 | * { | } 127 | */ 128 | void compound_statement(); 129 | 130 | /** 131 | * 功能:判断是否为类型区分符 132 | * v:单词编号 133 | */ 134 | int is_type_specifier(int v); 135 | 136 | /** 137 | * 功能:表达式语句解析 138 | * --> | 139 | */ 140 | void expression_statement(); 141 | 142 | /** 143 | * 功能:选择语句解析 144 | * --> 145 | * [] 146 | */ 147 | void if_statement(); 148 | 149 | /** 150 | * 功能:循环语句解析 151 | * --> 152 | * 153 | * 154 | */ 155 | void for_statement(); 156 | 157 | /** 158 | * 功能:continue语句解析 159 | */ 160 | void continue_statement(); 161 | 162 | /** 163 | * 功能:break语句解析 164 | */ 165 | void break_statement(); 166 | 167 | /** 168 | * 功能:return语句解析 169 | * --> 170 | * | 171 | */ 172 | void return_statement(); 173 | 174 | /** 175 | * 功能:解析表达式 176 | * -->{} 177 | */ 178 | void expression(); 179 | 180 | /** 181 | * 功能:解析赋值表达式 182 | * 183 | * --> | 184 | */ 185 | void assignment_expression(); 186 | 187 | /** 188 | * 功能:解析相等类表达式 189 | * --> 190 | * {}| 191 | */ 192 | void equality_expression(); 193 | 194 | /** 195 | * 功能:关系表达式 196 | * --> { 197 | * 198 | * | 199 | * | 200 | * | } 201 | */ 202 | void relational_expression(); 203 | 204 | /** 205 | * 功能:加减类表达式 206 | * --> 207 | * {|} 208 | */ 209 | void additive_expression(); 210 | 211 | /** 212 | * 功能:乘法除法表达式 213 | * --> 214 | * {||} 215 | */ 216 | void multiplicative_expression(); 217 | 218 | /** 219 | * 功能:一元表达式解析 220 | * --> 221 | * | | 222 | * | 223 | */ 224 | void unary_expression(); 225 | 226 | /** 227 | * 功能:解析sizeof表达式 228 | * --> 229 | */ 230 | void sizeof_expression(); 231 | 232 | /** 233 | * 功能:后缀表达式 234 | * --> 235 | * {| 236 | * ||} 237 | */ 238 | void postfix_expression(); 239 | 240 | /** 241 | * 功能:解析初值表达式 242 | * --> |||| 243 | * 244 | */ 245 | void primary_expression(); 246 | 247 | /** 248 | * 功能:解析实参表达式 249 | * --> 250 | * { } 251 | */ 252 | void argument_expression_list(); 253 | 254 | /** 255 | * 功能:语法缩进 256 | */ 257 | void syntax_indent(); 258 | 259 | /** 260 | * 取单词主程序 261 | */ 262 | void get_token(); 263 | 264 | 265 | void syntax_indent(); 266 | -------------------------------------------------------------------------------- /include/token.h: -------------------------------------------------------------------------------- 1 | // 词法分析 2 | // 定义 关键字和词法记号的类型标识 3 | // 使用enum结构 4 | #ifndef __MY_SCC_TOKEN_ 5 | #define __MY_SCC_TOKEN_ 6 | 7 | #include "dyn.h" 8 | 9 | enum Token 10 | { 11 | TK_PLUS, // + 12 | TK_MINUS, // - 13 | TK_STAR, // * 14 | TK_DIVIDE, // / 15 | TK_MOD, // % 16 | TK_EQ, // == 17 | TK_NEQ, // != 18 | TK_LT, // < 19 | TK_LEQ, // <= 20 | TK_GT, // > 21 | TK_GEQ, // >= 22 | TK_ASSIGN, // = 23 | TK_POINTO, // -> 24 | TK_DOT, // . 25 | TK_AND, // & 26 | TK_OR, // | 27 | TK_OPENPA, // ( 28 | TK_CLOSPA, // ) 29 | TK_OPENBR, // [ 30 | TK_CLOSBR, // ] 31 | TK_BEGIN, // { 32 | TK_END, // } 33 | TK_SEMICOLON, // ; 34 | TK_COMMA, // , 35 | TK_EOF, // EOF 36 | 37 | /* 常量 */ 38 | TK_CINT, // 整型常量 39 | TK_CCHAR, // 字符常量 40 | TK_CSTR, // 字符串常量 41 | 42 | /* 关键字 */ 43 | KW_CHAR, // char 44 | KW_SHORT, // short 45 | KW_INT, // int 46 | KW_VOID, // void 47 | KW_STRUCT, // struct 48 | KW_IF, // if 49 | KW_ELSE, // else 50 | KW_FOR, // for 51 | KW_CONTINUE, // continue 52 | KW_BREAK, // break 53 | KW_RETURN, // return 54 | KW_SIZEOF, // sizeof 55 | 56 | /* 标识符 */ 57 | TK_IDENT 58 | }; 59 | 60 | 61 | // 数据结构 62 | // 考虑到C89标准 规定最多32个字符 63 | // 常量字符串长度可以很长,故使用动态存储 64 | // 单词表查找频繁,可以借助哈系表 65 | 66 | /* 单词存储结构定义 */ 67 | typedef struct TKWord 68 | { 69 | int tkcode; // 词法符号编码 70 | struct TKWord *next; // 指向哈系冲突的同义词 71 | char *spelling; // 词的字符串 72 | struct Symbol *sym_struct; // 指向单词表示的结构定义 73 | struct Symbol *sym_id; // 指向单词表示的标识符 74 | } TKWord; 75 | 76 | /* 全局变量 */ 77 | #define MAXKEY 1024 78 | TKWord *tk_hashtable[MAXKEY]; // 词哈系表 79 | DynArray tktable; // 单词表 80 | 81 | 82 | void init_lex(); 83 | TKWord *tkword_insert(char *); 84 | char * get_tkstr(int v); 85 | 86 | 87 | #endif // __MY_SCC_TOKEN_ -------------------------------------------------------------------------------- /src/dyn.c: -------------------------------------------------------------------------------- 1 | #include "dyn.h" 2 | 3 | 4 | /* 全局变量 */ 5 | DynString tkstr; // 单词字符串 6 | DynString sourcestr; // 单词源码字符串 7 | int tkvalue; // 单词的词法值 8 | 9 | /** 10 | * 初始化动态字符串存储容量 11 | * pstr 动态字符串存储结构 12 | * initsize 初始化分配的大小 13 | */ 14 | void dynstring_init(DynString *pstr, int initsize) 15 | { 16 | if (pstr) 17 | { 18 | pstr->data = (char*)malloc(sizeof(char)*initsize); 19 | pstr->count = 0; 20 | pstr->capacity = initsize; 21 | } 22 | } 23 | 24 | /** 25 | * 释放动态字符串使用的空间 26 | * pstr 动态字符串存储结构 27 | */ 28 | void dynstring_free(DynString *pstr) 29 | { 30 | if (pstr->data) 31 | free(pstr->data); 32 | pstr->capacity = 0; 33 | pstr->count = 0; 34 | } 35 | 36 | /** 37 | * 重置动态字符串,先释放,再分配 38 | * pstr 动态字符串存储结构 39 | */ 40 | void dynstring_reset(DynString *pstr) 41 | { 42 | dynstring_free(pstr); 43 | dynstring_init(pstr, 16); 44 | } 45 | 46 | /** 47 | * pstr 动态字符串存储结构 48 | * new_size 字符串新长度 49 | */ 50 | void dynstring_realloc(DynString *pstr, int new_size) 51 | { 52 | int capacity; 53 | char *data; 54 | capacity = pstr->capacity; 55 | while(capacity < new_size) 56 | { 57 | capacity = capacity * 2; 58 | } 59 | data = (char *)realloc(pstr->data, capacity); 60 | if (!data) 61 | { 62 | error("memory alloc failed."); 63 | } 64 | pstr->capacity = capacity; 65 | pstr->data = data; 66 | } 67 | 68 | /** 69 | * 追加字符到动态字符串中 70 | * pstr 动态字符串存储结构 71 | * ch 追加啊的字符 72 | */ 73 | void dynstring_append(DynString *pstr, char ch) 74 | { 75 | int count; 76 | count = pstr->count+1; 77 | if (count > pstr->capacity) 78 | dynstring_realloc(pstr, count); 79 | pstr->data[count-1] = ch; 80 | pstr->count = count; 81 | } 82 | 83 | /** 84 | * 初始化动态数组存储容量 85 | * parr 动态数组存储结构 86 | * initsize 动态数组初始化分配空间 87 | */ 88 | void dynarray_init(DynArray *parr, int initsize) 89 | { 90 | if (parr) 91 | { 92 | parr->data = (void**)malloc(sizeof(char)*initsize); 93 | parr->capacity = initsize; 94 | parr->count = 0; 95 | } 96 | } 97 | 98 | /** 99 | * 释放动态数组使用的内存空间 100 | * parr 动态数组存储结构 101 | */ 102 | void dynarray_free(DynArray *parr) 103 | { 104 | void **p; 105 | for(p=parr->data;parr->count;++p, --parr->count) 106 | { 107 | if (*p) 108 | free(*p); 109 | } 110 | free(parr->data); 111 | parr->data = NULL; 112 | } 113 | 114 | /** 115 | * 动态数组元素查找 116 | * parr 动态数组存储结构 117 | * key 要查找的元素 118 | */ 119 | int dynarray_search(DynArray *parr, int key) 120 | { 121 | int i; 122 | int **p; 123 | p = (int**)parr->data; 124 | for(i = 0; i < parr->count; i++, p++) 125 | if (key == **p) 126 | return i; 127 | return -1; 128 | } 129 | 130 | /** 131 | * 重新分配动态数组容量 132 | * parr 动态数组存储结构 133 | * new_size 动态数组新的大小 134 | */ 135 | void dynarray_realloc(DynArray *parr, int new_size) 136 | { 137 | int capacity; 138 | void **data; 139 | capacity = parr->capacity; 140 | while (capacity < new_size) 141 | { 142 | capacity = capacity * 2; 143 | } 144 | if (!data) 145 | { 146 | error("memory alloc failed."); 147 | } 148 | data = (void**)realloc(parr->data, capacity); 149 | parr->capacity = capacity; 150 | parr->data = data; 151 | } 152 | 153 | /** 154 | * 追加动态数组元素 155 | * parr 动态数组存储结构 156 | * data 追加的元素 157 | */ 158 | void dynarray_add(DynArray *parr, void *data) 159 | { 160 | int count; 161 | count = parr->count+1; 162 | if (count * sizeof(void*) > parr->capacity) 163 | dynarray_realloc(parr, count * sizeof(void*)); 164 | parr->data[count-1] = data; 165 | parr->count = count; 166 | } -------------------------------------------------------------------------------- /src/dynstack.c: -------------------------------------------------------------------------------- 1 | #include "dynstack.h" 2 | 3 | /** 4 | * 功能:初始化栈容量 5 | * pstack 指向栈的指针 6 | * initsize 栈大小 7 | */ 8 | void stack_init(Stack * pstack, int initsize) 9 | { 10 | pstack->base = (void **)malloc(sizeof(void*)*initsize); 11 | if (!pstack->base) 12 | { 13 | error("memory alloc failed.\n"); 14 | } 15 | else 16 | { 17 | pstack->top = pstack->base; 18 | pstack->stacksize = initsize; 19 | } 20 | } 21 | 22 | /** 23 | * 功能:在栈顶插入元素 24 | * pstack 指向栈的指针 25 | * element 要插入栈顶的元素 26 | * size 栈元素的实际大小 27 | * 返回值 栈顶元素指针 28 | */ 29 | void * stack_push(Stack *pstack, void *element, int size) 30 | { 31 | int newsize; 32 | if (pstack->top >= pstack->base + pstack->stacksize) 33 | { 34 | newsize = pstack->stacksize * 2; 35 | pstack->base = (void **)realloc(pstack->base, sizeof(void*)*newsize); 36 | if (!pstack->base) return NULL; 37 | pstack->top = pstack->base + pstack->stacksize; 38 | pstack->stacksize = newsize; 39 | } 40 | *pstack->top = malloc(size); 41 | memcpy(*pstack->top, element, size); 42 | pstack->top++; 43 | return *(pstack->top-1); 44 | } 45 | 46 | /** 47 | * 功能:弹出栈顶元素 48 | * pstack 栈指针 49 | */ 50 | void stack_pop(Stack *pstack) 51 | { 52 | if (pstack->top > pstack->base) 53 | { 54 | free(*(--pstack->top)); 55 | } 56 | } 57 | 58 | /** 59 | * 功能:获取栈顶元素 60 | * pstack 栈指针 61 | * 返回值 栈顶元素 62 | */ 63 | void * stack_get_top(Stack *pstack) 64 | { 65 | if (pstack->top > pstack->base) 66 | { 67 | return *(--pstack->top); 68 | } 69 | } 70 | 71 | /** 72 | * 功能:判断栈是否为空 73 | * pstack 栈指针 74 | * 返回值 1 为空 0 不为空 75 | */ 76 | int stack_is_empty(Stack *pstack) 77 | { 78 | if (pstack->top == pstack->base) 79 | return 1; 80 | else return 0; 81 | } 82 | 83 | /** 84 | * 功能:销毁栈 85 | * pstack 栈指针 86 | */ 87 | void stack_destroy(Stack *pstack) 88 | { 89 | for(void **ele = pstack->base; ele < pstack->top; ele++) 90 | { 91 | free(*ele); 92 | } 93 | if (pstack->base) 94 | free(pstack->base); 95 | pstack->base = NULL; 96 | pstack->top = NULL; 97 | pstack->stacksize = 0; 98 | } -------------------------------------------------------------------------------- /src/error.c: -------------------------------------------------------------------------------- 1 | #include "error.h" 2 | 3 | 4 | extern int token; 5 | extern char * filename; 6 | extern int line_num; 7 | extern int column_num; 8 | extern void get_token(); 9 | extern char * get_tkstr(int c); 10 | 11 | 12 | /** 13 | * 异常处理 14 | * stage 编译阶段错误还是链接阶段错误 15 | * level 错误级别 16 | * fmt 参数输出格式 17 | * ap 可变参数列表 18 | */ 19 | void handle_exception(int stage, int level, char *fmt, va_list ap) 20 | { 21 | char buf[1024]; 22 | vsprintf(buf, fmt, ap); 23 | if (stage == STAGE_COMPILE) 24 | { 25 | if (level == LEVEL_WARNING) 26 | printf("%s(第%d行 第%d列):编译警告:%s!\n", filename, line_num, column_num, buf); 27 | else 28 | { 29 | printf("%s(第%d行 第%d列):编译错误:%s!\n", filename, line_num, column_num, buf); 30 | exit(-1); 31 | } 32 | } 33 | else 34 | { 35 | printf("链接错误:%s!\n", buf); 36 | exit(-1); 37 | } 38 | } 39 | 40 | /** 41 | * 编译警告处理 42 | * fmt 参数输出格式 43 | * ap 可变参数列表 44 | */ 45 | void warning(char *fmt, ...) 46 | { 47 | va_list ap; 48 | 49 | va_start(ap, fmt); 50 | handle_exception(STAGE_COMPILE, LEVEL_WARNING, fmt, ap); 51 | va_end(ap); 52 | } 53 | 54 | /** 55 | * 编译错误处理 56 | * fmt 参数输出格式 57 | * ap 可变参数列表 58 | */ 59 | void error(char *fmt, ...) 60 | { 61 | va_list ap; 62 | va_start(ap, fmt); 63 | handle_exception(STAGE_COMPILE, LEVEL_ERROR, fmt, ap); 64 | va_end(ap); 65 | } 66 | 67 | /** 68 | * 提示错误,缺少某个语法成分 69 | * msg 需要的语法成分 70 | */ 71 | void expect(char *msg) 72 | { 73 | error("缺少 %s", msg); 74 | } 75 | 76 | /** 77 | * 跳过单词c,取下一个单词 78 | * 如果不是单词c,提示错误 79 | * c 要跳过的单词 80 | */ 81 | void skip(int c) 82 | { 83 | if (token != c) 84 | error("lack of %s", get_tkstr(c)); 85 | get_token(); 86 | } -------------------------------------------------------------------------------- /src/ir.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "syntax.h" 4 | #include "lex.h" 5 | #include "json.h" 6 | #include "symbol.h" 7 | #include "token.h" 8 | #include "dynstack.h" 9 | 10 | FILE *fin; 11 | int token; 12 | int line_num; 13 | int column_num; 14 | Symbol *sym_sec_rdata; 15 | 16 | void init() { 17 | line_num = 1; 18 | column_num = 0; 19 | init_lex(); 20 | 21 | stack_init(&local_sym_stack, 16); 22 | stack_init(&global_sym_stack, 16); 23 | sym_sec_rdata = sec_sym_put(".rdata", 0); 24 | 25 | int_type.t = T_INT; 26 | char_pointer_type.t = T_CHAR; 27 | mk_pointer(&char_pointer_type); 28 | default_func_type.t = T_FUNC; 29 | default_func_type.ref = sym_push(SC_ANOM, &int_type, 0, 0); 30 | } 31 | 32 | void cleanup() 33 | { 34 | int i; 35 | sym_pop(&global_sym_stack, NULL); 36 | stack_destroy(&local_sym_stack); 37 | stack_destroy(&global_sym_stack); 38 | 39 | printf("\ntktable.count = %d\n", tktable.count); 40 | for(i = TK_IDENT; i < tktable.count; i++) 41 | free(tktable.data[i]); 42 | free(tktable.data); 43 | } 44 | 45 | int main(int argc, char const *argv[]) 46 | { 47 | fin = fopen(argv[1], "rb"); 48 | 49 | if (!fin) { 50 | printf("cannot open SC source file\n"); 51 | return 0; 52 | } 53 | 54 | init(); 55 | getch(); 56 | get_token(); 57 | JSONobj *obj = translation_unit(); 58 | printJSON(obj); 59 | destroyJSON(obj); 60 | cleanup(); 61 | fclose(fin); 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /src/json.c: -------------------------------------------------------------------------------- 1 | #include "json.h" 2 | 3 | void initJSON(JSONobj *pj) 4 | { 5 | pj->key = "Head Of List"; 6 | if (pj->next) 7 | pj->next = NULL; 8 | } 9 | 10 | void addJSON(JSONobj *pj, const char* key, Value val, State s) 11 | { 12 | JSONobj *p; 13 | if (!pj) 14 | return ; 15 | 16 | while(pj->next) 17 | pj = pj->next; 18 | p = pj->next = (JSONobj *)malloc(sizeof(JSONobj)); 19 | p->key = key; 20 | p->state = s; 21 | if (s == V_JSON) { 22 | p->value.obj = (JSONobj *)malloc(sizeof(JSONobj)); 23 | memcpy(p->value.obj, val.obj, sizeof(JSONobj)); 24 | } 25 | else 26 | p->value = val; 27 | p->next = NULL; 28 | } 29 | 30 | void printJSON(JSONobj *obj) 31 | { 32 | obj = obj->next; 33 | while (obj) 34 | { 35 | printf("\"%s\" : ", obj->key); 36 | switch (obj->state) 37 | { 38 | case V_CHAR: 39 | printf("\'%c\'\n", obj->value.ch); 40 | break; 41 | case V_INT: 42 | printf("%d\n", obj->value.data); 43 | break; 44 | case V_STR: 45 | printf("\"%s\"\n", obj->value.str); 46 | break; 47 | case V_JSON: 48 | printf(" {\n"); 49 | printJSON(obj->value.obj); 50 | printf("}\n"); 51 | break; 52 | } 53 | obj = obj->next; 54 | } 55 | } 56 | 57 | void destroyJSON(JSONobj *pj) 58 | { 59 | JSONobj *p, *q; 60 | p = pj->next; 61 | while (p) 62 | { 63 | q = p->next; 64 | if (p->state == V_JSON) { 65 | destroyJSON(p->value.obj); 66 | free(p->value.obj); 67 | } 68 | free(p); 69 | p = q; 70 | } 71 | return ; 72 | } 73 | -------------------------------------------------------------------------------- /src/lex.c: -------------------------------------------------------------------------------- 1 | #include "lex.h" 2 | #include "token.h" 3 | #include "syntax.h" 4 | 5 | /* 全局变量 */ 6 | extern FILE* fin; 7 | int ch; 8 | extern int token; 9 | extern int line_num; 10 | extern int column_num; 11 | char * filename; 12 | extern DynString tkstr; // 单词字符串 13 | extern DynString sourcestr; // 单词源码字符串 14 | extern int tkvalue; // 单词的词法值 15 | 16 | /** 17 | * 词法分析程序初始化 18 | */ 19 | void init() 20 | { 21 | line_num = 1; 22 | column_num = 0; 23 | init_lex(); 24 | } 25 | 26 | /** 27 | * 清理工作 28 | */ 29 | void cleanup() 30 | { 31 | int i; 32 | printf("\ntktable.count=%d\n", tktable.count); 33 | for(i = TK_IDENT; i < tktable.count; i++) 34 | { 35 | free(tktable.data[i]); 36 | } 37 | free(tktable.data); 38 | } 39 | 40 | /** 41 | * 获得取到的源码字符 42 | */ 43 | void getch() 44 | { 45 | ch = getc(fin); 46 | column_num ++; 47 | // printf("Now the ch is %c\n", ch); 48 | } 49 | 50 | /** 51 | * 注释处理 52 | */ 53 | void parse_comment() 54 | { 55 | getch(); 56 | do 57 | { 58 | do 59 | { 60 | if (ch == '\n' || ch == '*' || ch == EOF) 61 | break; 62 | else 63 | getch(); 64 | } while (1); 65 | if (ch == '\n') 66 | { 67 | line_num ++; 68 | column_num = 0; 69 | getch(); 70 | } 71 | else if (ch == '*') 72 | { 73 | getch(); 74 | if (ch == '/') 75 | { 76 | getch(); 77 | return; 78 | } 79 | } 80 | else 81 | { 82 | error("No End_Of_File found at the end of file.\n"); 83 | return; 84 | } 85 | }while(1); 86 | } 87 | 88 | /** 89 | * 空白字符处理 90 | */ 91 | void skip_white_space() 92 | { 93 | while(ch == ' ' || ch == '\t' || ch == '\r' ||ch == '\n') 94 | { 95 | if (ch == '\n') 96 | { 97 | // getch(); 98 | line_num++; 99 | column_num = 0; 100 | } 101 | // printf("%c", ch); 102 | getch(); 103 | } 104 | } 105 | 106 | /** 107 | * 预处理,忽略空白字符及注释 108 | */ 109 | void preprocess() 110 | { 111 | while (1) 112 | { 113 | if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n') 114 | skip_white_space(); 115 | else if (ch == '/') 116 | { 117 | // 看是否是注释 118 | getch(); 119 | if (ch == '*') 120 | { 121 | parse_comment(); 122 | } 123 | else 124 | { 125 | ungetc(ch, fin); 126 | column_num--; 127 | ch = '/'; 128 | break; 129 | } 130 | } 131 | else 132 | break; 133 | } 134 | 135 | } 136 | 137 | /** 138 | * 判断c是否为字母或下划线 139 | */ 140 | int is_nodigit(char c) 141 | { 142 | return (c >= 'a' && c <= 'z') || 143 | (c >= 'A' && c <= 'Z') || 144 | c == '_'; 145 | } 146 | 147 | /** 148 | * 判断c是否为数字 149 | */ 150 | int is_digit(char c) 151 | { 152 | return c>='0' && c<='9'; 153 | } 154 | 155 | /** 156 | * 解析标识符 157 | */ 158 | void parse_identifier() 159 | { 160 | dynstring_reset(&tkstr); 161 | dynstring_append(&tkstr, ch); 162 | getch(); 163 | 164 | while (is_nodigit(ch) || is_digit(ch)) 165 | { 166 | dynstring_append(&tkstr, ch); 167 | getch(); 168 | } 169 | dynstring_append(&tkstr, '\0'); 170 | } 171 | 172 | /** 173 | * 解析整形常量 174 | */ 175 | void parse_num() 176 | { 177 | dynstring_reset(&tkstr); 178 | dynstring_reset(&sourcestr); 179 | do 180 | { 181 | dynstring_append(&tkstr, ch); 182 | dynstring_append(&sourcestr, ch); 183 | getch(); 184 | } while (is_digit(ch)); 185 | if (ch =='.') 186 | { 187 | do 188 | { 189 | dynstring_append(&tkstr, ch); 190 | dynstring_append(&sourcestr, ch); 191 | } while (is_digit(ch)); 192 | } 193 | dynstring_append(&tkstr, '\0'); 194 | dynstring_append(&sourcestr, '\0'); 195 | tkvalue = atoi(tkstr.data); 196 | } 197 | 198 | /** 199 | * 解析字符常量和字符串常量 200 | * sep 单引号为 字符常量 双引号为字符串常量 201 | */ 202 | void parse_string(char sep) 203 | { 204 | char c; 205 | dynstring_reset(&tkstr); 206 | dynstring_reset(&sourcestr); 207 | dynstring_append(&sourcestr, sep); 208 | getch(); 209 | for(;;) 210 | { 211 | if (ch == sep) 212 | break; 213 | else if (ch == '\\') 214 | { 215 | dynstring_append(&sourcestr, ch); 216 | getch(); 217 | // 解析转义字符 218 | switch (ch) 219 | { 220 | case '0': 221 | c = '\0'; 222 | break; 223 | case 'b': 224 | c = '\b'; 225 | break; 226 | case 'n': 227 | c = '\n'; 228 | break; 229 | case '\'': 230 | c = '\''; 231 | break; 232 | case '\"': 233 | c = '\"'; 234 | break; 235 | default: 236 | c = ch; 237 | warning("illegal escape character: \'\\%c\'", c); 238 | break; 239 | } 240 | dynstring_append(&tkstr, c); 241 | dynstring_append(&sourcestr, ch); 242 | getch(); 243 | } 244 | else 245 | { 246 | dynstring_append(&tkstr, ch); 247 | dynstring_append(&sourcestr, ch); 248 | getch(); 249 | } 250 | } 251 | dynstring_append(&tkstr, '\0'); 252 | dynstring_append(&sourcestr, sep); 253 | dynstring_append(&sourcestr, '\0'); 254 | getch(); 255 | } 256 | 257 | /** 258 | * 词法着色 259 | */ 260 | 261 | // void color_print(char *fmt, ...) 262 | // { 263 | // va_list ap; 264 | // char buf[1024]; 265 | // va_start(ap, fmt); 266 | // vsprintf(buf, fmt, ap); 267 | // printf("%s", buf); 268 | // va_end(ap); 269 | // } 270 | 271 | // void color_token() 272 | // { 273 | // char *p = get_tkstr(token); 274 | // char fmt[128] = ""; 275 | // if (token >= TK_IDENT) {// 标识符 为白色 276 | // sprintf(fmt, "%%s"); 277 | // } 278 | // else if (token >= KW_CHAR) {// 关键字 蓝色 34 279 | // sprintf(fmt, "\033[%dm%%s\033[0m", BLUE); 280 | // } 281 | // else if (token >= TK_CINT) {// 常量 黄色 33 282 | // sprintf(fmt, "\033[%dm%%s\033[0m", YELLOW); 283 | // } 284 | // else {// 运算符等 红色 31 285 | // sprintf(fmt, "\033[%dm%%s\033[0m", RED); 286 | // } 287 | // color_print(fmt, p); 288 | // } 289 | 290 | /** 291 | * 取单词主程序 292 | */ 293 | void get_token() 294 | { 295 | preprocess(); 296 | if (is_nodigit(ch)) 297 | { 298 | TKWord *tp; 299 | parse_identifier(); 300 | tp = tkword_insert(tkstr.data); 301 | token = tp->tkcode; 302 | } 303 | else if (is_digit(ch)) 304 | { 305 | parse_num(); 306 | token = TK_CINT; 307 | } 308 | else 309 | { 310 | switch (ch) 311 | { 312 | case '+': 313 | getch(); 314 | token = TK_PLUS; 315 | break; 316 | case '-': 317 | getch(); 318 | if (ch == '>') 319 | { 320 | token = TK_POINTO; 321 | getch(); 322 | } 323 | else 324 | token = TK_MINUS; 325 | break; 326 | case '/': 327 | token = TK_DIVIDE; 328 | getch(); 329 | break; 330 | case '%': 331 | token = TK_MOD; 332 | getch(); 333 | break; 334 | case '=': 335 | getch(); 336 | if (ch == '=') 337 | { 338 | token = TK_EQ; 339 | getch(); 340 | } 341 | else 342 | token = TK_ASSIGN; 343 | break; 344 | case '!': 345 | getch(); 346 | if (ch == '=') 347 | { 348 | token = TK_NEQ; 349 | getch(); 350 | } 351 | else 352 | error("illegal operator"); 353 | break; 354 | case '<': 355 | getch(); 356 | if (ch == '=') 357 | { 358 | token = TK_LEQ; 359 | getch(); 360 | } 361 | else 362 | token = TK_LT; 363 | break; 364 | case '>': 365 | getch(); 366 | if (ch == '=') 367 | { 368 | token = TK_GEQ; 369 | getch(); 370 | } 371 | else 372 | token = TK_GT; 373 | break; 374 | case '.': 375 | getch(); 376 | token = TK_DOT; 377 | break; 378 | case '&': 379 | token = TK_AND; 380 | getch(); 381 | break; 382 | case '|': 383 | token = TK_OR; 384 | getch(); 385 | break; 386 | case ';': 387 | token = TK_SEMICOLON; 388 | getch(); 389 | break; 390 | case '(': 391 | token = TK_OPENPA; 392 | getch(); 393 | break; 394 | case '[': 395 | token = TK_OPENBR; 396 | getch(); 397 | break; 398 | case '{': 399 | token = TK_BEGIN; 400 | getch(); 401 | break; 402 | case ')': 403 | token = TK_CLOSPA; 404 | getch(); 405 | break; 406 | case ']': 407 | token = TK_CLOSBR; 408 | getch(); 409 | break; 410 | case '}': 411 | token = TK_END; 412 | getch(); 413 | break; 414 | case ',': 415 | token = TK_COMMA; 416 | getch(); 417 | break; 418 | case '*': 419 | token = TK_STAR; 420 | getch(); 421 | break; 422 | case '\'': 423 | parse_string(ch); 424 | token = TK_CCHAR; 425 | tkvalue = *(char *)tkstr.data; 426 | break; 427 | case '\"': 428 | parse_string(ch); 429 | token = TK_CSTR; 430 | break; 431 | case EOF: 432 | token = TK_EOF; 433 | break; 434 | default: 435 | error("illegal word! Lexical cannot recognise %c", ch); 436 | getch(); 437 | break; 438 | } 439 | } 440 | #ifdef __SYNTAX_INDENT 441 | syntax_indent(); 442 | #endif 443 | } 444 | 445 | /** 446 | * 词法分析主函数入口 447 | * argv 为传入的文件名 448 | */ 449 | // int main(int argc, char const *argv[]) 450 | // { 451 | // fin = fopen(argv[1], "rb"); 452 | // if (!fin) 453 | // { 454 | // printf("Can not open the SC file %s !\n", argv[1]); 455 | // return 0; 456 | // } 457 | // init(); 458 | 459 | // getch(); 460 | // do 461 | // { 462 | // get_token(); 463 | // color_token(); 464 | // } while (token != TK_EOF); 465 | // printf("\n 代码行数:%d行, 代码列数:%d列\n", line_num, column_num); 466 | 467 | // cleanup(); 468 | // fclose(fin); 469 | 470 | // return 0; 471 | // } 472 | -------------------------------------------------------------------------------- /src/lexcolor.c: -------------------------------------------------------------------------------- 1 | #include "lex.h" 2 | #include "token.h" 3 | 4 | /* 全局变量 */ 5 | FILE* fin; 6 | int token; 7 | int line_num; 8 | int column_num; 9 | 10 | /** 11 | * 词法着色 12 | */ 13 | void color_print(char *fmt, ...) 14 | { 15 | va_list ap; 16 | char buf[1024]; 17 | va_start(ap, fmt); 18 | vsprintf(buf, fmt, ap); 19 | printf("%s", buf); 20 | va_end(ap); 21 | } 22 | 23 | void color_token() 24 | { 25 | char *p = get_tkstr(token); 26 | char fmt[128] = ""; 27 | if (token >= TK_IDENT) {// 标识符 为白色 28 | sprintf(fmt, "%%s"); 29 | } 30 | else if (token >= KW_CHAR) {// 关键字 蓝色 34 31 | sprintf(fmt, "\033[%dm%%s\033[0m", BLUE); 32 | } 33 | else if (token >= TK_CINT) {// 常量 黄色 33 34 | sprintf(fmt, "\033[%dm%%s\033[0m", YELLOW); 35 | } 36 | else {// 运算符等 红色 31 37 | sprintf(fmt, "\033[%dm%%s\033[0m", RED); 38 | } 39 | color_print(fmt, p); 40 | } 41 | 42 | 43 | /** 44 | * 词法分析主函数入口 45 | * argv 为传入的文件名 46 | */ 47 | int main(int argc, char const *argv[]) 48 | { 49 | fin = fopen(argv[1], "rb"); 50 | if (!fin) 51 | { 52 | printf("Can not open the SC file %s !\n", argv[1]); 53 | return 0; 54 | } 55 | init(); 56 | 57 | getch(); 58 | do 59 | { 60 | get_token(); 61 | color_token(); 62 | } while (token != TK_EOF); 63 | printf("\n 代码行数:%d行, 代码列数:%d列\n", line_num, column_num); 64 | 65 | cleanup(); 66 | fclose(fin); 67 | 68 | return 0; 69 | } 70 | -------------------------------------------------------------------------------- /src/symbol.c: -------------------------------------------------------------------------------- 1 | #include "symbol.h" 2 | #include "syntax.h" 3 | 4 | extern int token; 5 | 6 | /** 7 | * 功能:将符号放入到符号栈中 8 | * v 符号编号 9 | * type 符号数据类型 10 | * c 符号关联值 11 | */ 12 | Symbol *sym_direct_push(Stack *ss, int v, Type *type, int c) 13 | { 14 | Symbol s, *p; 15 | s.v = v; 16 | s.type.t = type->t; 17 | s.c = c; 18 | s.next = NULL; 19 | p = (Symbol *)stack_push(ss, &s, sizeof(Symbol)); 20 | return p; 21 | } 22 | 23 | /** 24 | * 功能:将符号放在符号栈中,动态判断放入全局符号栈还是局部符号栈 25 | * v 符号编号 26 | * type 符号数据类型 27 | * r 符号存储类型 28 | * c 符号关联值 29 | */ 30 | Symbol *sym_push(int v, Type *type, int r, int c) 31 | { 32 | Symbol *ps, **pps; 33 | TKWord *ts; 34 | Stack *ss; 35 | 36 | if (stack_is_empty(&local_sym_stack) == 0) 37 | { 38 | ss = &local_sym_stack; 39 | } 40 | else 41 | { 42 | ss = &global_sym_stack; 43 | } 44 | ps = sym_direct_push(ss, v, type, c); 45 | ps->r = r; 46 | 47 | // 不记录结构体成员及匿名符号 48 | if((v & SC_STRUCT) || v sym_struct; 54 | else pps = &ts->sym_id; 55 | 56 | ps->prev = *pps; 57 | *pps = ps; 58 | } 59 | return ps; 60 | } 61 | 62 | /** 63 | * 功能:函数符号放入到全局符号表 64 | * v 符号编号 65 | * type 符号数据类型 66 | */ 67 | Symbol * func_sym_push(int v, Type *type) 68 | { 69 | Symbol *s, **ps; 70 | s = sym_direct_push(&global_sym_stack, v, type, 0); 71 | 72 | ps = &((TKWord *)tktable.data[v])->sym_id; 73 | 74 | while(*ps != NULL) 75 | ps = &(*ps)->prev; 76 | s->prev = NULL; 77 | *ps = s; 78 | return s; 79 | } 80 | 81 | /** 82 | * 功能:变量符号放入到全局符号表 83 | * type 符号数据类型 84 | * r 存储类型 85 | * v 单词编号 86 | * addr 地址 87 | */ 88 | Symbol *var_sym_put(Type *type, int r, int v, int addr) 89 | { 90 | Symbol *sym = NULL; 91 | if ((r & SC_VALMASK) == SC_LOCAL) // 局部变量 92 | { 93 | sym = sym_push(v, type, r, addr); 94 | } 95 | else if (v && (r & SC_VALMASK) == SC_GLOBAL) // 全局变量 96 | { 97 | sym = sym_search(v); 98 | if (sym) 99 | error("%s multi-defined.\n", ((TKWord*)tktable.data[v])->spelling); 100 | else 101 | { 102 | sym = sym_push(v, type, r | SC_SYM, 0); 103 | } 104 | } 105 | return sym; 106 | } 107 | 108 | /** 109 | * 功能:将节名称放入全局符号表 110 | * sec 节名称 111 | * c 符号关联值 112 | */ 113 | Symbol * sec_sym_put(char *sec, int c) 114 | { 115 | TKWord *tp; 116 | Symbol *s; 117 | Type type; 118 | type.t = T_INT; 119 | tp = tkword_insert(sec); 120 | token = tp->tkcode; 121 | s = sym_push(token, &type, SC_GLOBAL, c); 122 | return s; 123 | } 124 | 125 | /** 126 | * 功能:弹出栈中符号直到找到符号'b' 127 | * ptop:符号栈栈顶 128 | * b: 符号指针 129 | */ 130 | void sym_pop(Stack *ptop, Symbol *b) 131 | { 132 | Symbol *s, **ps; 133 | TKWord *ts; 134 | int v; 135 | 136 | s = (Symbol *)stack_get_top(ptop); 137 | while(s != b) 138 | { 139 | v = s->v; 140 | // 更新单词表中的sym_struct sym_id 141 | if ((v & SC_STRUCT) || v < SC_ANOM) 142 | { 143 | ts = (TKWord *)tktable.data[(v & ~SC_STRUCT)]; 144 | if (v & SC_STRUCT) 145 | ps = &ts->sym_struct; 146 | else ps = &ts->sym_id; 147 | *ps = s->prev; 148 | } 149 | stack_pop(ptop); 150 | s = (Symbol *)stack_get_top(ptop); 151 | } 152 | } 153 | 154 | /** 155 | * 功能:查找结构定义 156 | * v 符号编号 157 | */ 158 | Symbol *struct_search(int v) 159 | { 160 | if(v >= tktable.count) 161 | return NULL; 162 | else return ((TKWord *)tktable.data[v])->sym_struct; 163 | } 164 | 165 | /** 166 | * 功能:查找结构定义 167 | * v 符号编号 168 | */ 169 | Symbol *sym_search(int v) 170 | { 171 | if(v >= tktable.count) 172 | return NULL; 173 | else return ((TKWord *)tktable.data[v])->sym_id; 174 | } -------------------------------------------------------------------------------- /src/syntax.c: -------------------------------------------------------------------------------- 1 | #include "token.h" 2 | #include "syntax.h" 3 | 4 | 5 | /* 全局变量 */ 6 | extern int token; 7 | extern int tkvalue; 8 | extern int ch; 9 | extern DynString tkstr; 10 | 11 | /** 12 | * 功能:翻译单元,语法分析顶层 13 | * ::= {} 14 | */ 15 | void translation_unit() 16 | { 17 | while(token != TK_EOF) 18 | { 19 | external_declaration(SC_GLOBAL); 20 | } 21 | } 22 | 23 | 24 | /** 25 | * 功能: 解析外部声明 26 | * l: 存储类型 指明局部还是全局 27 | * ExternDeclaration 28 | * --> ( 29 | * | 30 | * | [] 31 | * {[]}) 32 | */ 33 | void external_declaration(int l) 34 | { 35 | if(!type_specifier()) 36 | { 37 | expect(""); 38 | } 39 | if (token == TK_SEMICOLON) 40 | { 41 | get_token(); 42 | return ; 43 | } 44 | while (1) 45 | { 46 | declarator(); 47 | if (token == TK_BEGIN) 48 | { 49 | if (l == SC_LOCAL) 50 | { 51 | error("nested func declarator unsupported.\n"); 52 | } 53 | funcbody(); 54 | break; 55 | } 56 | else 57 | { 58 | if (token == TK_ASSIGN) 59 | { 60 | get_token(); 61 | initializer(); 62 | } 63 | if (token == TK_COMMA) 64 | { 65 | get_token(); 66 | } 67 | else 68 | { 69 | syntax_state = SNTX_LF_HT; 70 | skip(TK_SEMICOLON); 71 | break; 72 | } 73 | } 74 | } 75 | } 76 | 77 | /** 78 | * 功能:解析类型区分符 79 | * 返回值:是否发现合法的类型区分符 80 | * 81 | * --> |||| 82 | */ 83 | int type_specifier() 84 | { 85 | int type_found = 0; 86 | switch (token) 87 | { 88 | case KW_CHAR: 89 | type_found = 1; 90 | syntax_state = SNTX_SP; 91 | get_token(); 92 | break; 93 | case KW_SHORT: 94 | type_found = 1; 95 | syntax_state = SNTX_SP; 96 | get_token(); 97 | break; 98 | case KW_VOID: 99 | type_found = 1; 100 | syntax_state = SNTX_SP; 101 | get_token(); 102 | break; 103 | case KW_INT: 104 | type_found = 1; 105 | syntax_state = SNTX_SP; 106 | get_token(); 107 | break; 108 | case KW_STRUCT: 109 | syntax_state = SNTX_SP; 110 | type_found = 1; 111 | struct_specifier(); 112 | break; 113 | 114 | default: 115 | break; 116 | } 117 | return type_found; 118 | } 119 | 120 | /** 121 | * 功能:结构体类型区分符 122 | * 123 | * --> 124 | * | 125 | */ 126 | void struct_specifier() 127 | { 128 | int v; 129 | 130 | get_token(); // struct 131 | v = token; 132 | syntax_state = SNTX_DELAY; 133 | get_token; // identifier 134 | 135 | if (token == TK_BEGIN) 136 | syntax_state = SNTX_LF_HT; // for define 137 | else if (token == TK_CLOSPA) // for sizeof(struct id) 138 | syntax_state = SNTX_NUL; 139 | else syntax_state = SNTX_SP; // for declarator 140 | 141 | syntax_indent(); 142 | 143 | if (v < TK_IDENT) 144 | expect("struct identifier name"); 145 | if (token == TK_BEGIN) 146 | struct_declaration_list(); 147 | } 148 | 149 | /** 150 | * 功能:结构体中声明的变量的全体 151 | * 152 | * --> {} 153 | */ 154 | void struct_declaration_list() 155 | { 156 | int maxalign, offset; 157 | 158 | syntax_state = SNTX_LF_HT; 159 | syntax_level++; 160 | 161 | get_token(); 162 | while (token != TK_END) 163 | { 164 | struct_declaration(&maxalign, &offset); 165 | } 166 | skip(TK_END); 167 | 168 | syntax_state = SNTX_LF_HT; 169 | } 170 | 171 | /** 172 | * 功能:结构体中声明的变量 173 | * 174 | * --> 175 | * 176 | * --> {} 177 | */ 178 | void struct_declaration() 179 | { 180 | type_specifier(); 181 | while (1) 182 | { 183 | declarator(); 184 | 185 | if (token == TK_SEMICOLON) 186 | break; 187 | skip(TK_COMMA); 188 | } 189 | syntax_state = SNTX_LF_HT; 190 | skip(TK_SEMICOLON); 191 | } 192 | 193 | /** 194 | * 功能:声明符的解析 195 | * 196 | * --> {} 197 | */ 198 | void declarator() 199 | { 200 | while(token == TK_STAR) 201 | { 202 | get_token(); 203 | } 204 | direct_declarator(); 205 | } 206 | 207 | 208 | /** 209 | * 功能:直接声明符解析 210 | * 211 | * --> 212 | */ 213 | void direct_declarator() 214 | { 215 | if (token >= TK_IDENT) 216 | { 217 | get_token(); 218 | } 219 | else 220 | { 221 | expect("Identifier\n"); 222 | } 223 | direct_declarator_postfix(); 224 | } 225 | 226 | 227 | /** 228 | * 功能:直接声明符后缀 229 | * 230 | * --> {} 231 | * | 232 | * | 233 | * | 234 | */ 235 | void direct_declarator_postfix() 236 | { 237 | int n; 238 | if (token == TK_OPENPA) 239 | { 240 | parameter_type_list(); 241 | } 242 | else if (token == TK_OPENBR) 243 | { 244 | get_token(); 245 | if (token == TK_CINT) 246 | { 247 | get_token(); 248 | n = tkvalue; 249 | } 250 | skip(TK_CLOSBR); 251 | direct_declarator_postfix(); 252 | } 253 | } 254 | 255 | /** 256 | * 功能:解析形参类型表 257 | * 258 | * --> {} 259 | * --> 260 | */ 261 | void parameter_type_list() 262 | { 263 | get_token(); 264 | while(token != TK_CLOSPA) 265 | { 266 | if (!type_specifier()) 267 | { 268 | error("invalid type specifier"); 269 | } 270 | declarator(); 271 | if (token == TK_CLOSPA) 272 | break; 273 | skip(TK_COMMA); 274 | } 275 | syntax_state = SNTX_DELAY; 276 | skip(TK_CLOSPA); 277 | if (token == TK_BEGIN) 278 | syntax_state = SNTX_LF_HT; // function define 279 | else syntax_state = SNTX_NUL; // function declaration 280 | 281 | syntax_indent(); 282 | } 283 | 284 | 285 | /** 286 | * 功能:函数体解析 287 | * --> 288 | */ 289 | void funcbody() 290 | { 291 | compound_statement(); 292 | } 293 | 294 | /** 295 | * 功能:解析初值符 296 | * --> 297 | */ 298 | void initializer() 299 | { 300 | assignment_expression(); 301 | } 302 | 303 | /** 304 | * 功能:语句解析 305 | * --> 306 | * | | | 307 | * | | | 308 | */ 309 | void statement() 310 | { 311 | switch (token) 312 | { 313 | case TK_BEGIN: 314 | compound_statement(); 315 | break; 316 | case KW_IF: 317 | if_statement(); 318 | break; 319 | case KW_RETURN: 320 | return_statement(); 321 | break; 322 | case KW_BREAK: 323 | break_statement(); 324 | break; 325 | case KW_CONTINUE: 326 | continue_statement(); 327 | break; 328 | case KW_FOR: 329 | for_statement(); 330 | break; 331 | 332 | default: 333 | expression_statement(); 334 | break; 335 | } 336 | } 337 | 338 | /** 339 | * 功能:解析复合语句 340 | * --> 341 | * { | } 342 | */ 343 | void compound_statement() 344 | { 345 | syntax_state = SNTX_LF_HT; 346 | syntax_level++; 347 | 348 | get_token(); 349 | 350 | while (token != TK_END) 351 | { 352 | if (is_type_specifier(token)) 353 | external_declaration(SC_LOCAL); 354 | else statement(); 355 | } 356 | syntax_state = SNTX_LF_HT; 357 | get_token(); 358 | } 359 | 360 | 361 | /** 362 | * 功能:判断是否为类型区分符 363 | * v:单词编号 364 | */ 365 | int is_type_specifier(int v) 366 | { 367 | switch (v) 368 | { 369 | case KW_SHORT: 370 | case KW_INT: 371 | case KW_VOID: 372 | case KW_STRUCT: 373 | case KW_CHAR: 374 | return 1; 375 | 376 | default: 377 | break; 378 | } 379 | return 0; 380 | } 381 | 382 | /** 383 | * 功能:表达式语句解析 384 | * --> | 385 | */ 386 | void expression_statement() 387 | { 388 | if (token != TK_SEMICOLON) 389 | expression(); 390 | 391 | syntax_state = SNTX_LF_HT; 392 | skip(TK_SEMICOLON); 393 | } 394 | 395 | /** 396 | * 功能:选择语句解析 397 | * --> 398 | * [] 399 | */ 400 | void if_statement() 401 | { 402 | syntax_state = SNTX_SP; 403 | get_token(); 404 | skip(TK_OPENPA); 405 | expression(); 406 | syntax_state = SNTX_LF_HT; 407 | skip(TK_CLOSPA); 408 | statement(); 409 | if (token == KW_ELSE) 410 | { 411 | syntax_state = SNTX_LF_HT; 412 | get_token(); 413 | statement(); 414 | } 415 | } 416 | 417 | 418 | /** 419 | * 功能:循环语句解析 420 | * --> 421 | * 422 | * 423 | */ 424 | void for_statement() 425 | { 426 | get_token(); 427 | skip(TK_OPENPA); 428 | if (token != TK_SEMICOLON) 429 | expression(); 430 | skip(TK_SEMICOLON); 431 | if (token != TK_SEMICOLON) 432 | expression(); 433 | skip(TK_SEMICOLON); 434 | if(token != TK_CLOSPA) 435 | expression(); 436 | 437 | syntax_state = SNTX_LF_HT; 438 | skip(TK_CLOSPA); 439 | statement(); 440 | } 441 | 442 | /** 443 | * 功能:continue语句解析 444 | */ 445 | void continue_statement() 446 | { 447 | get_token(); 448 | syntax_state = SNTX_LF_HT; 449 | skip(TK_SEMICOLON); 450 | } 451 | 452 | /** 453 | * 功能:break语句解析 454 | */ 455 | void break_statement() 456 | { 457 | get_token(); 458 | syntax_state = SNTX_LF_HT; 459 | skip(TK_SEMICOLON); 460 | } 461 | 462 | /** 463 | * 功能:return语句解析 464 | * --> 465 | * | 466 | */ 467 | void return_statement() 468 | { 469 | syntax_state = SNTX_DELAY; 470 | get_token(); 471 | if (token==TK_SEMICOLON) 472 | syntax_state = SNTX_NUL; 473 | else 474 | syntax_state = SNTX_SP; 475 | syntax_indent(); 476 | 477 | if (token != TK_SEMICOLON) 478 | expression(); 479 | syntax_state = SNTX_LF_HT; 480 | skip(TK_SEMICOLON); 481 | } 482 | 483 | /** 484 | * 功能:解析表达式 485 | * -->{} 486 | */ 487 | void expression() 488 | { 489 | while (1) 490 | { 491 | assignment_expression(); 492 | if (token != TK_COMMA) 493 | break; 494 | get_token(); 495 | } 496 | } 497 | 498 | /** 499 | * 功能:解析赋值表达式 500 | * 501 | * --> | 502 | */ 503 | void assignment_expression() 504 | { 505 | equality_expression(); 506 | if(token == TK_ASSIGN) 507 | { 508 | get_token(); 509 | assignment_expression(); 510 | } 511 | } 512 | 513 | /** 514 | * 功能:解析相等类表达式 515 | * --> 516 | * {}| 517 | */ 518 | void equality_expression() 519 | { 520 | relational_expression(); 521 | while (token == TK_EQ || token == TK_NEQ) 522 | { 523 | get_token(); 524 | relational_expression(); 525 | } 526 | } 527 | 528 | /** 529 | * 功能:关系表达式 530 | * --> { 531 | * 532 | * | 533 | * | 534 | * | } 535 | */ 536 | void relational_expression() 537 | { 538 | additive_expression(); 539 | while ((token == TK_LT || token == TK_LEQ) || 540 | (token == TK_GT || token == TK_GEQ)) 541 | { 542 | get_token(); 543 | additive_expression(); 544 | } 545 | } 546 | 547 | /** 548 | * 功能:加减类表达式 549 | * --> 550 | * {|} 551 | */ 552 | void additive_expression() 553 | { 554 | multiplicative_expression(); 555 | while (token==TK_PLUS || token==TK_MINUS) 556 | { 557 | get_token(); 558 | multiplicative_expression(); 559 | } 560 | } 561 | 562 | /** 563 | * 功能:乘法除法表达式 564 | * --> 565 | * {||} 566 | */ 567 | void multiplicative_expression() 568 | { 569 | unary_expression(); 570 | while (token == TK_STAR || token ==TK_DIVIDE || token == TK_MOD) 571 | { 572 | get_token(); 573 | unary_expression(); 574 | } 575 | } 576 | 577 | /** 578 | * 功能:一元表达式解析 579 | * --> 580 | * | | 581 | * | 582 | */ 583 | void unary_expression() 584 | { 585 | switch (token) 586 | { 587 | case TK_AND: 588 | get_token(); 589 | unary_expression(); 590 | break; 591 | case TK_OR: 592 | get_token(); 593 | unary_expression(); 594 | break; 595 | case TK_STAR: 596 | get_token(); 597 | unary_expression(); 598 | break; 599 | case TK_PLUS: 600 | get_token(); 601 | unary_expression(); 602 | break; 603 | case TK_MINUS: 604 | get_token(); 605 | unary_expression(); 606 | break; 607 | case KW_SIZEOF: 608 | sizeof_expression(); 609 | break; 610 | default: 611 | postfix_expression(); 612 | break; 613 | } 614 | } 615 | 616 | 617 | /** 618 | * 功能:解析sizeof表达式 619 | * --> 620 | */ 621 | void sizeof_expression() 622 | { 623 | get_token(); 624 | skip(TK_OPENPA); 625 | type_specifier(); 626 | skip(TK_CLOSPA); 627 | } 628 | 629 | /** 630 | * 功能:后缀表达式 631 | * --> 632 | * {| 633 | * ||} 634 | */ 635 | void postfix_expression() 636 | { 637 | primary_expression(); 638 | while (1) 639 | { 640 | if (token == TK_DOT || token == TK_POINTO) 641 | { 642 | get_token(); 643 | token |= SC_MEMBER; 644 | get_token(); 645 | } else if (token == TK_OPENBR) 646 | { 647 | get_token(); 648 | expression(); 649 | skip(TK_CLOSBR); 650 | } else if (token == TK_OPENPA) 651 | { 652 | argument_expression_list(); 653 | } else break; 654 | } 655 | } 656 | 657 | /** 658 | * 功能:解析初值表达式 659 | * --> |||| 660 | * 661 | */ 662 | void primary_expression() 663 | { 664 | int t; 665 | switch (token) 666 | { 667 | case TK_CINT: 668 | case TK_CCHAR: 669 | case TK_CSTR: 670 | get_token(); 671 | break; 672 | case TK_OPENPA: 673 | get_token(); 674 | expression(); 675 | skip(TK_CLOSPA); 676 | break; 677 | default: 678 | t = token; 679 | get_token(); 680 | if (t < TK_CINT) { 681 | expect("Identifier or constant value."); 682 | } 683 | break; 684 | } 685 | } 686 | 687 | /** 688 | * 功能:解析实参表达式 689 | * --> 690 | * { } 691 | */ 692 | void argument_expression_list() 693 | { 694 | get_token(); 695 | if (token != TK_CLOSPA) 696 | { 697 | for(;;) 698 | { 699 | assignment_expression(); 700 | if (token == TK_CLOSPA) 701 | break; 702 | skip(TK_COMMA); 703 | } 704 | } 705 | skip(TK_CLOSPA); 706 | } 707 | -------------------------------------------------------------------------------- /src/syntaxindent.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "syntax.h" 4 | #include "lex.h" 5 | #include "token.h" 6 | 7 | 8 | FILE *fin; 9 | int token; 10 | int line_num; 11 | int column_num; 12 | 13 | /** 14 | * 词法着色 15 | */ 16 | void color_print(char *fmt, ...) 17 | { 18 | va_list ap; 19 | char buf[1024]; 20 | va_start(ap, fmt); 21 | vsprintf(buf, fmt, ap); 22 | printf("%s", buf); 23 | va_end(ap); 24 | } 25 | 26 | void color_token() 27 | { 28 | char *p = get_tkstr(token); 29 | char fmt[128] = ""; 30 | if (token >= TK_IDENT) {// 标识符 为白色 31 | sprintf(fmt, "%%s"); 32 | } 33 | else if (token >= KW_CHAR) {// 关键字 蓝色 34 34 | sprintf(fmt, "\033[%dm%%s\033[0m", BLUE); 35 | } 36 | else if (token >= TK_CINT) {// 常量 黄色 33 37 | sprintf(fmt, "\033[%dm%%s\033[0m", YELLOW); 38 | } 39 | else {// 运算符等 红色 31 40 | sprintf(fmt, "\033[%dm%%s\033[0m", RED); 41 | } 42 | color_print(fmt, p); 43 | } 44 | 45 | /** 46 | * 功能:缩进n个tab 47 | * n:缩进个数 48 | */ 49 | void print_tab(int n) 50 | { 51 | for(int i = 0; i < n; i++) 52 | printf("\t"); 53 | } 54 | 55 | /** 56 | * 功能:语法缩进 57 | */ 58 | void syntax_indent() 59 | { 60 | switch (syntax_state) 61 | { 62 | case SNTX_NUL: 63 | color_token(); 64 | break; 65 | case SNTX_SP: 66 | printf(" "); 67 | color_token(); 68 | break; 69 | case SNTX_LF_HT:{ 70 | if (token == TK_END) 71 | syntax_level--; 72 | printf("\n"); 73 | print_tab(syntax_level); 74 | color_token(); 75 | break; 76 | } 77 | case SNTX_DELAY: 78 | break; 79 | } 80 | syntax_state = SNTX_NUL; 81 | } 82 | 83 | /** 84 | * 功能:语法缩进主函数 85 | */ 86 | int main(int argc, char const *argv[]) 87 | { 88 | fin = fopen(argv[1], "rb"); 89 | if (!fin) { 90 | printf("Cannot open SC source file.\n"); 91 | return 1; 92 | } 93 | 94 | init(); 95 | getch(); 96 | get_token(); 97 | translation_unit(); 98 | cleanup(); 99 | fclose(fin); 100 | printf("\n%s syntax analysis passed!\n", argv[1]); 101 | return 0; 102 | } 103 | -------------------------------------------------------------------------------- /src/token.c: -------------------------------------------------------------------------------- 1 | #include "token.h" 2 | #include 3 | 4 | #include "dyn.h" 5 | #include "error.h" 6 | 7 | extern int token; 8 | extern DynString sourcestr; 9 | 10 | /** 11 | * elf - 哈系表 12 | * key 传入的字符串 13 | */ 14 | int elf_hash(char *key) 15 | { 16 | int h = 0; 17 | int g; 18 | while (*key) 19 | { 20 | h = (h << 4) + *key++; 21 | g = h & 0xf0000000; 22 | if (g) 23 | h ^= g >> 24; 24 | h &= ~g; 25 | } 26 | return h % MAXKEY; 27 | } 28 | 29 | /** 30 | * 分配堆内存并将数据初始化 31 | * size 分配大小 32 | */ 33 | void* mallocz(int size) 34 | { 35 | void *ptr; 36 | ptr = malloc(size); 37 | if (!ptr && size) 38 | error("memory alloc failed.\n"); 39 | memset(ptr, 0, size); 40 | return ptr; 41 | } 42 | 43 | /** 44 | * 单词表操作,直接放入单词表 45 | * 用于运算符、关键字、常量 46 | */ 47 | TKWord * tkword_direct_insert(TKWord * tp) 48 | { 49 | int keyno; 50 | dynarray_add(&tktable, tp); 51 | keyno = elf_hash(tp->spelling); 52 | tp->next = tk_hashtable[keyno]; 53 | tk_hashtable[keyno] = tp; 54 | return tp; 55 | } 56 | 57 | /** 58 | * 查找单词 59 | * p 要查找的单词 60 | * keyno 要查找的单词哈系值 61 | */ 62 | TKWord * tkword_find(char *p, int keyno) 63 | { 64 | TKWord *tp = NULL; 65 | TKWord *tp1; 66 | for (tp1 = tk_hashtable[keyno];tp1;tp1=tp1->next) 67 | { 68 | if (!strcmp(p, tp1->spelling)) 69 | { 70 | token = tp1->tkcode; 71 | tp = tp1; 72 | } 73 | } 74 | return tp; 75 | } 76 | 77 | /** 78 | * 标识符插入单词表,先查找,查找不到再插入 79 | */ 80 | TKWord * tkword_insert(char *p) 81 | { 82 | TKWord *tp; 83 | int keyno; 84 | char *s; 85 | char *end; 86 | int length; 87 | 88 | keyno = elf_hash(p); 89 | tp = tkword_find(p, keyno); 90 | if (tp == NULL) 91 | { 92 | length = strlen(p); 93 | tp = (TKWord *)mallocz(sizeof(TKWord)+length+1); 94 | 95 | tp->next = tk_hashtable[keyno]; 96 | tk_hashtable[keyno] = tp; 97 | dynarray_add(&tktable, tp); 98 | tp->tkcode = tktable.count - 1; 99 | s = (char *)tp + sizeof(TKWord); 100 | tp->spelling = (char *)s; 101 | for(end = p + length; p < end;) 102 | { 103 | *s++ = *p++; 104 | } 105 | *s = (char)'\0'; 106 | } 107 | return tp; 108 | } 109 | 110 | /** 111 | * 词法分析初始化 112 | */ 113 | void init_lex() 114 | { 115 | TKWord *tp; 116 | static TKWord keywords[] = { 117 | {TK_PLUS, NULL, "+", NULL, NULL}, 118 | {TK_MINUS, NULL, "-", NULL, NULL}, 119 | {TK_STAR, NULL, "*", NULL, NULL}, 120 | {TK_DIVIDE, NULL, "/", NULL, NULL}, 121 | {TK_MOD, NULL, "%", NULL, NULL}, 122 | {TK_EQ, NULL, "==", NULL, NULL}, 123 | {TK_NEQ, NULL, "!=", NULL, NULL}, 124 | {TK_LT, NULL, "<", NULL, NULL}, 125 | {TK_LEQ, NULL, "<=", NULL, NULL}, 126 | {TK_GT, NULL, ">", NULL, NULL}, 127 | {TK_GEQ, NULL, ">=", NULL, NULL}, 128 | {TK_ASSIGN, NULL, "=", NULL, NULL}, 129 | {TK_POINTO, NULL, "->", NULL, NULL}, 130 | {TK_DOT, NULL, ".", NULL, NULL}, 131 | {TK_AND, NULL, "&", NULL, NULL}, 132 | {TK_OR, NULL, "|", NULL, NULL}, 133 | {TK_OPENPA, NULL, "(", NULL, NULL}, 134 | {TK_CLOSPA, NULL, ")", NULL, NULL}, 135 | {TK_OPENBR, NULL, "[", NULL, NULL}, 136 | {TK_CLOSBR, NULL, "]", NULL, NULL}, 137 | {TK_BEGIN, NULL, "{", NULL, NULL}, 138 | {TK_END, NULL, "}", NULL, NULL}, 139 | {TK_SEMICOLON, NULL, ";", NULL, NULL}, 140 | {TK_COMMA, NULL, ",", NULL, NULL}, 141 | {TK_EOF, NULL, "End_Of_File", NULL, NULL}, 142 | {TK_CINT, NULL, "CINT", NULL, NULL}, 143 | {TK_CCHAR, NULL, "CCHAR", NULL, NULL}, 144 | {TK_CSTR, NULL, "CSTR", NULL, NULL}, 145 | 146 | {KW_CHAR, NULL, "char", NULL, NULL}, 147 | {KW_SHORT, NULL, "short", NULL, NULL}, 148 | {KW_INT, NULL, "int", NULL, NULL}, 149 | {KW_VOID, NULL, "void", NULL, NULL}, 150 | {KW_STRUCT, NULL, "struct", NULL, NULL}, 151 | {KW_IF, NULL, "if", NULL, NULL}, 152 | {KW_ELSE, NULL, "else", NULL, NULL}, 153 | {KW_FOR, NULL, "for", NULL, NULL}, 154 | {KW_CONTINUE,NULL, "continue", NULL, NULL}, 155 | {KW_BREAK, NULL, "break", NULL, NULL}, 156 | {KW_RETURN, NULL, "return", NULL, NULL}, 157 | {KW_SIZEOF, NULL, "sizeof", NULL, NULL}, 158 | {0, NULL, NULL, NULL, NULL} 159 | }; 160 | 161 | dynarray_init(&tktable, 16); 162 | for(tp=&keywords[0];tp->spelling!=NULL;tp++) 163 | tkword_direct_insert(tp); 164 | } 165 | 166 | /** 167 | * 取得单词v所代表的源码字符串 168 | * v 单词编号 169 | */ 170 | char * get_tkstr(int v) 171 | { 172 | if (v > tktable.count) 173 | return NULL; 174 | else if (v >= TK_CINT && v <= TK_CSTR) 175 | return sourcestr.data; 176 | else 177 | return ((TKWord*)tktable.data[v])->spelling; 178 | } --------------------------------------------------------------------------------