├── Makefile ├── ProgramSlicing ├── README.md ├── ast_node.c ├── ast_node.h ├── astfile ├── bison_c.tab.c ├── bison_c.tab.h ├── bison_c.y ├── cfg.dot ├── cfg.png ├── cfg_node.c ├── cfg_node.h ├── flex_c.l ├── graph_to_dot.c ├── graph_to_dot.h ├── lex.yy.c ├── main.c ├── print_slicing_result.c ├── print_slicing_result.h ├── program_slicing.c ├── program_slicing.h ├── symbol.c ├── symbol.h ├── write_ast_to_file.c └── write_ast_to_file.h /Makefile: -------------------------------------------------------------------------------- 1 | #which complier 2 | CC = gcc 3 | 4 | #Options for development 5 | CFLAGS = -g 6 | 7 | ProgramSlicing: flex_c.l bison_c.y main.o ast_node.o cfg_node.o \ 8 | graph_to_dot.o write_ast_to_file.o program_slicing.o symbol.o print_slicing_result.o 9 | bison -d bison_c.y 10 | flex flex_c.l 11 | $(CC) -o $@ bison_c.tab.c lex.yy.c main.o ast_node.o cfg_node.o \ 12 | graph_to_dot.o write_ast_to_file.o program_slicing.o symbol.o print_slicing_result.o -lfl 13 | 14 | main.o: main.c bison_c.tab.h ast_node.h cfg_node.h symbol.h \ 15 | program_slicing.h graph_to_dot.h write_ast_to_file.h print_slicing_result.h 16 | 17 | ast_node.o: ast_node.c ast_node.h 18 | 19 | cfg_node.o: cfg_node.c cfg_node.h ast_node.h symbol.h 20 | 21 | graph_to_dot.o: graph_to_dot.c graph_to_dot.h cfg_node.h ast_node.h symbol.h program_slicing.h 22 | 23 | write_ast_to_file.o: write_ast_to_file.c write_ast_to_file.h ast_node.h 24 | 25 | program_slicing.o: program_slicing.c program_slicing.h cfg_node.h ast_node.h symbol.h 26 | 27 | symbol.o: symbol.c symbol.h 28 | 29 | print_slicing_result.o: print_slicing_result.c print_slicing_result.h program_slicing.h ast_node.h -------------------------------------------------------------------------------- /ProgramSlicing: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fengcc/ProgramSlicing/7159357011bf50cd4f188683fa60aeed1c63cab1/ProgramSlicing -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Static Program Slicing Tool Of Backward Slice 2 | 3 | This is a simple program slicing tool in C and also for C programs to see depending lines of code. 4 | 5 | ## Usage 6 | Clone the code: 7 | ```bash 8 | git clone https://github.com/feng01/ProgramSlicing.git 9 | ``` 10 | #### If you just want to run it: 11 | ```bash 12 | cd ProgramSlicing 13 | ./ProgramSlicing filepath/test.c #the second parameter is the code you want to analysis 14 | ``` 15 | Then input the slicing criterion : line number and variables.
16 | The slice result will saved in the file named test_slice.c which is located in the same directory as test.c. 17 | 18 | #### If you want to modify the code and recompile it: 19 | First, some software you need install: 20 | * flex 21 | * bison 22 | * graphviz
23 | 24 | On OpenSuse,you can use following command to install them: 25 | ```bash 26 | sudo zypper install flex bison graphviz 27 | ``` 28 | Then, run `make` to recompile the code you have modified. 29 | 30 | 31 | ## Bugs 32 | The program doesn't support all of the C syntax,and need to further improve.
33 | For example: 34 | * fuction call doesn's support. 35 | * Pointer does's support. 36 | * You should use `i=i+1` instead of `i++`. 37 | 38 | and so on. 39 | -------------------------------------------------------------------------------- /ast_node.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | #include "ast_node.h" 8 | 9 | /*创建一个表示节点值的共用体,若type值为0,则共用体使用的是value_string成员,若type值为1,则使用的是value_number成员*/ 10 | NodeValue *newNodeValue(int type, ...) 11 | { 12 | NodeValue *union_node = (NodeValue *)malloc(sizeof(NodeValue)); 13 | va_list ap; 14 | va_start(ap, type); 15 | 16 | if (type == 0) 17 | strcpy(union_node->value_string, va_arg(ap, char *)); 18 | else 19 | union_node->value_number = va_arg(ap, double); 20 | 21 | va_end(ap); 22 | 23 | return union_node; 24 | } 25 | 26 | /*创建一个抽象语法树的节点,并初始化其类型、值、以及行号*/ 27 | AstNode *newAstNode(enum AstNodeType type, NodeValue *val, int line_number) 28 | { 29 | AstNode *node = (AstNode *)malloc(sizeof(AstNode)); 30 | 31 | node->nodetype_ast = type; 32 | 33 | if (type == Number) 34 | node->value.value_number = val->value_number; 35 | else 36 | strcpy(node->value.value_string, val->value_string); 37 | 38 | free(val); /*因val所占的内存空间是在函数newNodeValue()中动态分配的,所以使用完后需要释放,防止内存泄漏*/ 39 | val = NULL; 40 | 41 | node->linenumber = line_number; 42 | 43 | /*初始化时将指向第一个孩子和下一个兄弟的指针赋空指针,实际指向在linkAstNode()函数中赋值*/ 44 | node->firstchild = node->nextsibling = NULL; 45 | 46 | return node; 47 | } 48 | 49 | /*将父节点和第一孩子相连,并将第一个孩子和它自己的兄弟相连,因不确定兄弟有多少,所以这里使用了变长参数*/ 50 | void linkAstNode(AstNode *parentNode, AstNode *first_child, ...) 51 | { 52 | AstNode *pre_temp, *temp; 53 | va_list ap; 54 | va_start(ap, first_child); 55 | 56 | parentNode->firstchild = first_child; 57 | 58 | pre_temp = first_child; 59 | while ((temp = va_arg(ap, AstNode *)) != NULL) 60 | { 61 | pre_temp->nextsibling = temp; 62 | 63 | pre_temp = temp; 64 | } 65 | 66 | va_end(ap); 67 | } 68 | 69 | /*按先序遍历的顺序给节点编号,根节点编号为1,递归调用结束后,node_counter的值即为节点总个数+1*/ 70 | void initialiseNodeId(AstNode *node) 71 | { 72 | if (node) 73 | { 74 | node->id = node_counter++; 75 | 76 | initialiseNodeId(node->firstchild); 77 | initialiseNodeId(node->nextsibling); 78 | } 79 | } 80 | 81 | /*后序遍历,释放节点空间*/ 82 | void freeAstNode(AstNode *node) 83 | { 84 | if(node) 85 | { 86 | freeAstNode(node->firstchild); 87 | freeAstNode(node->nextsibling); 88 | 89 | free(node); 90 | node = NULL; 91 | } 92 | } -------------------------------------------------------------------------------- /ast_node.h: -------------------------------------------------------------------------------- 1 | #ifndef NODE_H 2 | #define NODE_H 3 | 4 | #include 5 | 6 | enum AstNodeType 7 | { 8 | Identifier = 0, 9 | Number, 10 | String, 11 | Keyword, 12 | Operator, 13 | Statement, 14 | Expression, 15 | FunctionDefinition, 16 | Declaration 17 | }; 18 | 19 | typedef union 20 | { 21 | char value_string[40]; 22 | double value_number; 23 | }NodeValue; 24 | 25 | typedef struct AstNode 26 | { 27 | int id; 28 | enum AstNodeType nodetype_ast; 29 | NodeValue value; /*节点值*/ 30 | int linenumber; /*在源代码中的行号*/ 31 | int endlinenumber; /*记录整个语句的结束行号,仅在循环语句或选择语句中使用到*/ 32 | struct AstNode *firstchild, *nextsibling; /*指向第一个孩子和下一个兄弟*/ 33 | }AstNode; 34 | 35 | AstNode *ast_root; /*抽象语法树的根节点*/ 36 | extern int linesno; /*词法分析器的接口*/ 37 | int node_counter; /*抽象语法树的节点编号,用来初始化节点中的index,初始值为1*/ 38 | 39 | /*-----------------函数详细注释见函数定义处-------------------*/ 40 | /*创建表示节点值的共用体节点*/ 41 | NodeValue *newNodeValue(int type, ...); 42 | 43 | /*创建抽象语法树的节点*/ 44 | AstNode *newAstNode(enum AstNodeType type, NodeValue *val, int line_number); 45 | 46 | /*连接抽象语法树的节点*/ 47 | void linkAstNode(AstNode *parentNode, AstNode *first_child, ...); 48 | 49 | /*给节点编号,根节点编号为0*/ 50 | void initialiseNodeId(AstNode *node); 51 | 52 | /*释放抽象语法树节点所占空间*/ 53 | void freeAstNode(AstNode *node); 54 | 55 | #endif -------------------------------------------------------------------------------- /astfile: -------------------------------------------------------------------------------- 1 | TheTotalNumberOfNodes: 134 2 | 3 | @20 type : 0 value : i 4 | linenumber: 5 firstchild: -1 nextsibling: -1 5 | 6 | @19 type : 3 value : int 7 | linenumber: 5 firstchild: -1 nextsibling: 20 8 | 9 | @26 type : 1 value : 0.000000 10 | linenumber: 6 firstchild: -1 nextsibling: -1 11 | 12 | @25 type : 4 value : = 13 | linenumber: 6 firstchild: -1 nextsibling: 26 14 | 15 | @24 type : 0 value : sum 16 | linenumber: 6 firstchild: -1 nextsibling: 25 17 | 18 | @23 type : 6 value : init_declarator 19 | linenumber: 6 firstchild: 24 nextsibling: -1 20 | 21 | @22 type : 3 value : int 22 | linenumber: 6 firstchild: -1 nextsibling: 23 23 | 24 | @21 type : 8 value : declaration 25 | linenumber: 6 firstchild: 22 nextsibling: -1 26 | 27 | @18 type : 8 value : declaration 28 | linenumber: 5 firstchild: 19 nextsibling: 21 29 | 30 | @32 type : 1 value : 1.000000 31 | linenumber: 7 firstchild: -1 nextsibling: -1 32 | 33 | @31 type : 4 value : = 34 | linenumber: 7 firstchild: -1 nextsibling: 32 35 | 36 | @30 type : 0 value : product 37 | linenumber: 7 firstchild: -1 nextsibling: 31 38 | 39 | @29 type : 6 value : init_declarator 40 | linenumber: 7 firstchild: 30 nextsibling: -1 41 | 42 | @28 type : 3 value : int 43 | linenumber: 7 firstchild: -1 nextsibling: 29 44 | 45 | @27 type : 8 value : declaration 46 | linenumber: 7 firstchild: 28 nextsibling: -1 47 | 48 | @17 type : 7 value : block_item_list 49 | linenumber: 5 firstchild: 18 nextsibling: 27 50 | 51 | @39 type : 0 value : product 52 | linenumber: 9 firstchild: -1 nextsibling: -1 53 | 54 | @38 type : 4 value : + 55 | linenumber: 9 firstchild: -1 nextsibling: 39 56 | 57 | @37 type : 0 value : sum 58 | linenumber: 9 firstchild: -1 nextsibling: 38 59 | 60 | @40 type : 4 value : ; 61 | linenumber: 9 firstchild: -1 nextsibling: -1 62 | 63 | @36 type : 6 value : additive_expression 64 | linenumber: 9 firstchild: 37 nextsibling: 40 65 | 66 | @35 type : 4 value : = 67 | linenumber: 9 firstchild: -1 nextsibling: 36 68 | 69 | @34 type : 0 value : i 70 | linenumber: 9 firstchild: -1 nextsibling: 35 71 | 72 | @33 type : 5 value : assignment_statement 73 | linenumber: 9 firstchild: 34 nextsibling: -1 74 | 75 | @16 type : 7 value : block_item_list 76 | linenumber: 5 firstchild: 17 nextsibling: 33 77 | 78 | @47 type : 0 value : i 79 | linenumber: 10 firstchild: -1 nextsibling: -1 80 | 81 | @46 type : 4 value : + 82 | linenumber: 10 firstchild: -1 nextsibling: 47 83 | 84 | @45 type : 0 value : product 85 | linenumber: 10 firstchild: -1 nextsibling: 46 86 | 87 | @48 type : 4 value : ; 88 | linenumber: 10 firstchild: -1 nextsibling: -1 89 | 90 | @44 type : 6 value : additive_expression 91 | linenumber: 10 firstchild: 45 nextsibling: 48 92 | 93 | @43 type : 4 value : = 94 | linenumber: 10 firstchild: -1 nextsibling: 44 95 | 96 | @42 type : 0 value : product 97 | linenumber: 10 firstchild: -1 nextsibling: 43 98 | 99 | @41 type : 5 value : assignment_statement 100 | linenumber: 10 firstchild: 42 nextsibling: -1 101 | 102 | @15 type : 7 value : block_item_list 103 | linenumber: 5 firstchild: 16 nextsibling: 41 104 | 105 | @55 type : 0 value : i 106 | linenumber: 11 firstchild: -1 nextsibling: -1 107 | 108 | @54 type : 4 value : + 109 | linenumber: 11 firstchild: -1 nextsibling: 55 110 | 111 | @53 type : 0 value : sum 112 | linenumber: 11 firstchild: -1 nextsibling: 54 113 | 114 | @56 type : 4 value : ; 115 | linenumber: 11 firstchild: -1 nextsibling: -1 116 | 117 | @52 type : 6 value : additive_expression 118 | linenumber: 11 firstchild: 53 nextsibling: 56 119 | 120 | @51 type : 4 value : = 121 | linenumber: 11 firstchild: -1 nextsibling: 52 122 | 123 | @50 type : 0 value : sum 124 | linenumber: 11 firstchild: -1 nextsibling: 51 125 | 126 | @49 type : 5 value : assignment_statement 127 | linenumber: 11 firstchild: 50 nextsibling: -1 128 | 129 | @14 type : 7 value : block_item_list 130 | linenumber: 5 firstchild: 15 nextsibling: 49 131 | 132 | @63 type : 1 value : 1.000000 133 | linenumber: 13 firstchild: -1 nextsibling: -1 134 | 135 | @62 type : 4 value : > 136 | linenumber: 13 firstchild: -1 nextsibling: 63 137 | 138 | @61 type : 0 value : i 139 | linenumber: 13 firstchild: -1 nextsibling: 62 140 | 141 | @71 type : 4 value : ; 142 | linenumber: 15 firstchild: -1 nextsibling: -1 143 | 144 | @70 type : 1 value : 2.000000 145 | linenumber: 15 firstchild: -1 nextsibling: 71 146 | 147 | @69 type : 4 value : = 148 | linenumber: 15 firstchild: -1 nextsibling: 70 149 | 150 | @68 type : 0 value : product 151 | linenumber: 15 firstchild: -1 nextsibling: 69 152 | 153 | @72 type : 4 value : } 154 | linenumber: 16 firstchild: -1 nextsibling: -1 155 | 156 | @67 type : 5 value : assignment_statement 157 | linenumber: 15 firstchild: 68 nextsibling: 72 158 | 159 | @66 type : 4 value : { 160 | linenumber: 16 firstchild: -1 nextsibling: 67 161 | 162 | @65 type : 7 value : compound_statement 163 | linenumber: 14 firstchild: 66 nextsibling: -1 164 | 165 | @64 type : 4 value : ) 166 | linenumber: 13 firstchild: -1 nextsibling: 65 167 | 168 | @60 type : 6 value : relational_expression 169 | linenumber: 13 firstchild: 61 nextsibling: 64 170 | 171 | @59 type : 4 value : ( 172 | linenumber: 13 firstchild: -1 nextsibling: 60 173 | 174 | @58 type : 3 value : if 175 | linenumber: 13 firstchild: -1 nextsibling: 59 176 | 177 | @57 type : 5 value : selection_statement_no_else 178 | linenumber: 13 firstchild: 58 nextsibling: -1 179 | 180 | @13 type : 7 value : block_item_list 181 | linenumber: 5 firstchild: 14 nextsibling: 57 182 | 183 | @79 type : 1 value : 5.000000 184 | linenumber: 18 firstchild: -1 nextsibling: -1 185 | 186 | @78 type : 4 value : < 187 | linenumber: 18 firstchild: -1 nextsibling: 79 188 | 189 | @77 type : 0 value : i 190 | linenumber: 18 firstchild: -1 nextsibling: 78 191 | 192 | @91 type : 0 value : i 193 | linenumber: 20 firstchild: -1 nextsibling: -1 194 | 195 | @90 type : 4 value : + 196 | linenumber: 20 firstchild: -1 nextsibling: 91 197 | 198 | @89 type : 0 value : sum 199 | linenumber: 20 firstchild: -1 nextsibling: 90 200 | 201 | @92 type : 4 value : ; 202 | linenumber: 20 firstchild: -1 nextsibling: -1 203 | 204 | @88 type : 6 value : additive_expression 205 | linenumber: 20 firstchild: 89 nextsibling: 92 206 | 207 | @87 type : 4 value : = 208 | linenumber: 20 firstchild: -1 nextsibling: 88 209 | 210 | @86 type : 0 value : sum 211 | linenumber: 20 firstchild: -1 nextsibling: 87 212 | 213 | @99 type : 0 value : i 214 | linenumber: 21 firstchild: -1 nextsibling: -1 215 | 216 | @98 type : 4 value : * 217 | linenumber: 21 firstchild: -1 nextsibling: 99 218 | 219 | @97 type : 0 value : product 220 | linenumber: 21 firstchild: -1 nextsibling: 98 221 | 222 | @100 type : 4 value : ; 223 | linenumber: 21 firstchild: -1 nextsibling: -1 224 | 225 | @96 type : 6 value : multiplicative_expression 226 | linenumber: 21 firstchild: 97 nextsibling: 100 227 | 228 | @95 type : 4 value : = 229 | linenumber: 21 firstchild: -1 nextsibling: 96 230 | 231 | @94 type : 0 value : product 232 | linenumber: 21 firstchild: -1 nextsibling: 95 233 | 234 | @93 type : 5 value : assignment_statement 235 | linenumber: 21 firstchild: 94 nextsibling: -1 236 | 237 | @85 type : 5 value : assignment_statement 238 | linenumber: 20 firstchild: 86 nextsibling: 93 239 | 240 | @107 type : 1 value : 1.000000 241 | linenumber: 23 firstchild: -1 nextsibling: -1 242 | 243 | @106 type : 4 value : + 244 | linenumber: 23 firstchild: -1 nextsibling: 107 245 | 246 | @105 type : 0 value : i 247 | linenumber: 23 firstchild: -1 nextsibling: 106 248 | 249 | @108 type : 4 value : ; 250 | linenumber: 23 firstchild: -1 nextsibling: -1 251 | 252 | @104 type : 6 value : additive_expression 253 | linenumber: 23 firstchild: 105 nextsibling: 108 254 | 255 | @103 type : 4 value : = 256 | linenumber: 23 firstchild: -1 nextsibling: 104 257 | 258 | @102 type : 0 value : i 259 | linenumber: 23 firstchild: -1 nextsibling: 103 260 | 261 | @101 type : 5 value : assignment_statement 262 | linenumber: 23 firstchild: 102 nextsibling: -1 263 | 264 | @84 type : 7 value : block_item_list 265 | linenumber: 20 firstchild: 85 nextsibling: 101 266 | 267 | @109 type : 4 value : } 268 | linenumber: 24 firstchild: -1 nextsibling: -1 269 | 270 | @83 type : 7 value : block_item_list 271 | linenumber: 20 firstchild: 84 nextsibling: 109 272 | 273 | @82 type : 4 value : { 274 | linenumber: 24 firstchild: -1 nextsibling: 83 275 | 276 | @81 type : 7 value : compound_statement 277 | linenumber: 19 firstchild: 82 nextsibling: -1 278 | 279 | @80 type : 4 value : ) 280 | linenumber: 18 firstchild: -1 nextsibling: 81 281 | 282 | @76 type : 6 value : relational_expression 283 | linenumber: 18 firstchild: 77 nextsibling: 80 284 | 285 | @75 type : 4 value : ( 286 | linenumber: 18 firstchild: -1 nextsibling: 76 287 | 288 | @74 type : 3 value : while 289 | linenumber: 18 firstchild: -1 nextsibling: 75 290 | 291 | @73 type : 5 value : iteration_statement 292 | linenumber: 18 firstchild: 74 nextsibling: -1 293 | 294 | @12 type : 7 value : block_item_list 295 | linenumber: 5 firstchild: 13 nextsibling: 73 296 | 297 | @117 type : 0 value : sum 298 | linenumber: 26 firstchild: -1 nextsibling: -1 299 | 300 | @116 type : 4 value : , 301 | linenumber: 26 firstchild: -1 nextsibling: 117 302 | 303 | @115 type : 2 value : "%d\n" 304 | linenumber: 26 firstchild: -1 nextsibling: 116 305 | 306 | @118 type : 4 value : ) 307 | linenumber: 26 firstchild: -1 nextsibling: -1 308 | 309 | @114 type : 6 value : argument_expression_list 310 | linenumber: 26 firstchild: 115 nextsibling: 118 311 | 312 | @113 type : 4 value : ( 313 | linenumber: 26 firstchild: -1 nextsibling: 114 314 | 315 | @112 type : 0 value : printf 316 | linenumber: 26 firstchild: -1 nextsibling: 113 317 | 318 | @119 type : 4 value : ; 319 | linenumber: 26 firstchild: -1 nextsibling: -1 320 | 321 | @111 type : 6 value : postfix_expression 322 | linenumber: 26 firstchild: 112 nextsibling: 119 323 | 324 | @110 type : 5 value : expression_statement 325 | linenumber: 26 firstchild: 111 nextsibling: -1 326 | 327 | @11 type : 7 value : block_item_list 328 | linenumber: 5 firstchild: 12 nextsibling: 110 329 | 330 | @127 type : 0 value : product 331 | linenumber: 27 firstchild: -1 nextsibling: -1 332 | 333 | @126 type : 4 value : , 334 | linenumber: 27 firstchild: -1 nextsibling: 127 335 | 336 | @125 type : 2 value : "%d\n" 337 | linenumber: 27 firstchild: -1 nextsibling: 126 338 | 339 | @128 type : 4 value : ) 340 | linenumber: 27 firstchild: -1 nextsibling: -1 341 | 342 | @124 type : 6 value : argument_expression_list 343 | linenumber: 27 firstchild: 125 nextsibling: 128 344 | 345 | @123 type : 4 value : ( 346 | linenumber: 27 firstchild: -1 nextsibling: 124 347 | 348 | @122 type : 0 value : printf 349 | linenumber: 27 firstchild: -1 nextsibling: 123 350 | 351 | @129 type : 4 value : ; 352 | linenumber: 27 firstchild: -1 nextsibling: -1 353 | 354 | @121 type : 6 value : postfix_expression 355 | linenumber: 27 firstchild: 122 nextsibling: 129 356 | 357 | @120 type : 5 value : expression_statement 358 | linenumber: 27 firstchild: 121 nextsibling: -1 359 | 360 | @10 type : 7 value : block_item_list 361 | linenumber: 5 firstchild: 11 nextsibling: 120 362 | 363 | @133 type : 4 value : ; 364 | linenumber: 29 firstchild: -1 nextsibling: -1 365 | 366 | @132 type : 1 value : 0.000000 367 | linenumber: 29 firstchild: -1 nextsibling: 133 368 | 369 | @131 type : 3 value : return 370 | linenumber: 29 firstchild: -1 nextsibling: 132 371 | 372 | @130 type : 5 value : jump_statement 373 | linenumber: 29 firstchild: 131 nextsibling: -1 374 | 375 | @9 type : 7 value : block_item_list 376 | linenumber: 5 firstchild: 10 nextsibling: 130 377 | 378 | @134 type : 4 value : } 379 | linenumber: 30 firstchild: -1 nextsibling: -1 380 | 381 | @8 type : 7 value : block_item_list 382 | linenumber: 5 firstchild: 9 nextsibling: 134 383 | 384 | @7 type : 4 value : { 385 | linenumber: 30 firstchild: -1 nextsibling: 8 386 | 387 | @6 type : 7 value : compound_statement 388 | linenumber: 4 firstchild: 7 nextsibling: -1 389 | 390 | @5 type : 4 value : ) 391 | linenumber: 3 firstchild: -1 nextsibling: 6 392 | 393 | @4 type : 4 value : ( 394 | linenumber: 3 firstchild: -1 nextsibling: 5 395 | 396 | @3 type : 0 value : main 397 | linenumber: 3 firstchild: -1 nextsibling: 4 398 | 399 | @2 type : 3 value : int 400 | linenumber: 3 firstchild: -1 nextsibling: 3 401 | 402 | @1 type : 7 value : function_definition 403 | linenumber: 3 firstchild: 2 nextsibling: -1 404 | 405 | -------------------------------------------------------------------------------- /bison_c.tab.h: -------------------------------------------------------------------------------- 1 | /* A Bison parser, made by GNU Bison 2.7. */ 2 | 3 | /* Bison interface for Yacc-like parsers in C 4 | 5 | Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc. 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . */ 19 | 20 | /* As a special exception, you may create a larger work that contains 21 | part or all of the Bison parser skeleton and distribute that work 22 | under terms of your choice, so long as that work isn't itself a 23 | parser generator using the skeleton or a modified version thereof 24 | as a parser skeleton. Alternatively, if you modify or redistribute 25 | the parser skeleton itself, you may (at your option) remove this 26 | special exception, which will cause the skeleton and the resulting 27 | Bison output files to be licensed under the GNU General Public 28 | License without this special exception. 29 | 30 | This special exception was added by the Free Software Foundation in 31 | version 2.2 of Bison. */ 32 | 33 | #ifndef YY_YY_BISON_C_TAB_H_INCLUDED 34 | # define YY_YY_BISON_C_TAB_H_INCLUDED 35 | /* Enabling traces. */ 36 | #ifndef YYDEBUG 37 | # define YYDEBUG 0 38 | #endif 39 | #if YYDEBUG 40 | extern int yydebug; 41 | #endif 42 | 43 | /* Tokens. */ 44 | #ifndef YYTOKENTYPE 45 | # define YYTOKENTYPE 46 | /* Put the tokens into the symbol table, so that GDB and other debuggers 47 | know about them. */ 48 | enum yytokentype { 49 | AUTO = 258, 50 | DEFINE = 259, 51 | EXTERN = 260, 52 | REGISTER = 261, 53 | STATIC = 262, 54 | TYPEDEF = 263, 55 | CHAR = 264, 56 | DOUBLE = 265, 57 | FLOAT = 266, 58 | INT = 267, 59 | LONG = 268, 60 | SHORT = 269, 61 | SIGNED = 270, 62 | UNSIGNED = 271, 63 | VOID = 272, 64 | VOLATILE = 273, 65 | BREAK = 274, 66 | CASE = 275, 67 | CONTINUE = 276, 68 | DEFAULT = 277, 69 | DO = 278, 70 | ELSE = 279, 71 | FOR = 280, 72 | GOTO = 281, 73 | IF = 282, 74 | RETURN = 283, 75 | SWITCH = 284, 76 | WHILE = 285, 77 | ENUM = 286, 78 | STRUCT = 287, 79 | UNION = 288, 80 | SIZEOF = 289, 81 | NUMBER = 290, 82 | IDENTIFIER = 291, 83 | CHARACTER = 292, 84 | STRING_CONSTANT = 293, 85 | ADD_ASSIGN = 294, 86 | SUB_ASSIGN = 295, 87 | MUL_ASSIGN = 296, 88 | DIV_ASSIGN = 297, 89 | INC_OP = 298, 90 | DEC_OP = 299, 91 | AND_OP = 300, 92 | OR_OP = 301, 93 | LE_OP = 302, 94 | GE_OP = 303, 95 | EQ_OP = 304, 96 | NE_OP = 305, 97 | LOWER_THAN_ELSE = 306 98 | }; 99 | #endif 100 | 101 | 102 | #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED 103 | typedef union YYSTYPE 104 | { 105 | /* Line 2058 of yacc.c */ 106 | #line 9 "bison_c.y" 107 | 108 | struct AstNode *a; 109 | double d; 110 | char s[32]; 111 | 112 | 113 | /* Line 2058 of yacc.c */ 114 | #line 115 "bison_c.tab.h" 115 | } YYSTYPE; 116 | # define YYSTYPE_IS_TRIVIAL 1 117 | # define yystype YYSTYPE /* obsolescent; will be withdrawn */ 118 | # define YYSTYPE_IS_DECLARED 1 119 | #endif 120 | 121 | extern YYSTYPE yylval; 122 | 123 | #ifdef YYPARSE_PARAM 124 | #if defined __STDC__ || defined __cplusplus 125 | int yyparse (void *YYPARSE_PARAM); 126 | #else 127 | int yyparse (); 128 | #endif 129 | #else /* ! YYPARSE_PARAM */ 130 | #if defined __STDC__ || defined __cplusplus 131 | int yyparse (void); 132 | #else 133 | int yyparse (); 134 | #endif 135 | #endif /* ! YYPARSE_PARAM */ 136 | 137 | #endif /* !YY_YY_BISON_C_TAB_H_INCLUDED */ 138 | -------------------------------------------------------------------------------- /bison_c.y: -------------------------------------------------------------------------------- 1 | %{ 2 | #include 3 | #include 4 | #include "ast_node.h" 5 | 6 | void yyerror(char *s); 7 | %} 8 | 9 | %union { 10 | struct AstNode *a; 11 | double d; 12 | char s[32]; 13 | } 14 | 15 | %token AUTO DEFINE EXTERN REGISTER STATIC TYPEDEF 16 | %token CHAR DOUBLE FLOAT INT LONG SHORT SIGNED UNSIGNED VOID VOLATILE 17 | %token BREAK CASE CONTINUE DEFAULT DO ELSE FOR GOTO IF RETURN SWITCH WHILE 18 | %token ENUM STRUCT UNION SIZEOF 19 | 20 | %token NUMBER 21 | %token IDENTIFIER CHARACTER STRING_CONSTANT 22 | 23 | %token ADD_ASSIGN SUB_ASSIGN MUL_ASSIGN DIV_ASSIGN INC_OP DEC_OP AND_OP OR_OP LE_OP GE_OP EQ_OP NE_OP 24 | 25 | 26 | %type primary_expression postfix_expression argument_expression_list unary_expression unary_operator cast_expression 27 | %type type_name multiplicative_expression additive_expression relational_expression equality_expression and_expression 28 | %type exclusive_or_expression inclusive_or_expression logical_and_expression logical_or_expression expression 29 | %type declaration init_declarator_list init_declarator declarator initializer 30 | %type statement assignment_statement expression_statement selection_statement iteration_statement jump_statement 31 | %type translation_unit function_definition compound_statement block_item_list block_item 32 | 33 | %start translation_unit 34 | 35 | %nonassoc LOWER_THAN_ELSE /* 定义优先级,解决二义性 */ 36 | %nonassoc ELSE 37 | 38 | %% 39 | 40 | primary_expression 41 | : IDENTIFIER /*标识符*/ { $$ = newAstNode(Identifier, newNodeValue(0, $1), linesno); } 42 | | NUMBER /*数字*/ { $$ = newAstNode(Number, newNodeValue(1, $1), linesno); } 43 | | CHARACTER /*字符*/ { $$ = newAstNode(String, newNodeValue(0, $1), linesno); } 44 | | STRING_CONSTANT /*字符串常量*/ { $$ = newAstNode(String, newNodeValue(0, $1), linesno); } 45 | | '(' expression ')' { $$ = newAstNode(Expression, newNodeValue(0, "primary_expression"), linesno); 46 | AstNode *left_bracket = newAstNode(Operator, newNodeValue(0, "("), linesno); 47 | AstNode *right_bracket = newAstNode(Operator, newNodeValue(0, ")"), linesno); 48 | linkAstNode($$, left_bracket, $2, right_bracket, NULL); } 49 | ; 50 | 51 | postfix_expression /*数组,自定义函数 均未考虑*/ 52 | : primary_expression { $$ = $1; } 53 | | postfix_expression INC_OP { $$ = newAstNode(Expression, newNodeValue(0, "postfix_expression"), linesno); 54 | AstNode *inc_op = newAstNode(Operator, newNodeValue(0, "++"), linesno); 55 | linkAstNode($$, $1, inc_op, NULL); } 56 | | postfix_expression DEC_OP { $$ = newAstNode(Expression, newNodeValue(0, "postfix_expression"), linesno); 57 | AstNode *dec_op = newAstNode(Operator, newNodeValue(0, "--"), linesno); 58 | linkAstNode($$, $1, dec_op, NULL); } 59 | | postfix_expression '(' ')' /*无参库函数调用*/ 60 | { $$ = newAstNode(Expression, newNodeValue(0, "postfix_expression"), linesno); 61 | AstNode *left_bracket = newAstNode(Operator, newNodeValue(0, "("), linesno); 62 | AstNode *right_bracket = newAstNode(Operator, newNodeValue(0, ")"), linesno); 63 | linkAstNode($$, $1, left_bracket, right_bracket, NULL); } 64 | | postfix_expression '(' argument_expression_list ')' /*有参库函数调用*/ 65 | { $$ = newAstNode(Expression, newNodeValue(0, "postfix_expression"), linesno); 66 | AstNode *left_bracket = newAstNode(Operator, newNodeValue(0, "("), linesno); 67 | AstNode *right_bracket = newAstNode(Operator, newNodeValue(0, ")"), linesno); 68 | linkAstNode($$, $1, left_bracket, $3, right_bracket, NULL); } 69 | ; 70 | 71 | unary_expression 72 | : postfix_expression { $$ = $1; } 73 | | INC_OP unary_expression { $$ = newAstNode(Expression, newNodeValue(0, "unary_expression"), linesno); 74 | AstNode *inc_op = newAstNode(Operator, newNodeValue(0, "++"), linesno); 75 | linkAstNode($$, inc_op, $2, NULL); } 76 | | DEC_OP unary_expression { $$ = newAstNode(Expression, newNodeValue(0, "unary_expression"), linesno); 77 | AstNode *dec_op = newAstNode(Operator, newNodeValue(0, "--"), linesno); 78 | linkAstNode($$, dec_op, $2, NULL); } 79 | | unary_operator cast_expression { $$ = newAstNode(Expression, newNodeValue(0, "unary_expression"), linesno); 80 | linkAstNode($$, $1, $2, NULL); } 81 | ; 82 | 83 | unary_operator /*未考虑指针和取地址符*/ 84 | : '+' { $$ = newAstNode(Operator, newNodeValue(0, "+"), linesno); } 85 | | '-' { $$ = newAstNode(Operator, newNodeValue(0, "-"), linesno); } 86 | | '~' { $$ = newAstNode(Operator, newNodeValue(0, "~"), linesno); } 87 | | '!' { $$ = newAstNode(Operator, newNodeValue(0, "!"), linesno); } 88 | | '&' { $$ = newAstNode(Operator, newNodeValue(0, "&"), linesno); } 89 | ; 90 | 91 | cast_expression 92 | : unary_expression { $$ = $1; } 93 | | '(' type_name ')' cast_expression /*强制类型转换*/ 94 | { $$ = newAstNode(Expression, newNodeValue(0, "cast_expression"), linesno); 95 | AstNode *left_bracket = newAstNode(Operator, newNodeValue(0, "("), linesno); 96 | AstNode *right_bracket = newAstNode(Operator, newNodeValue(0, ")"), linesno); 97 | linkAstNode($$, left_bracket, $2, right_bracket, $4, NULL); } 98 | ; 99 | 100 | multiplicative_expression 101 | : cast_expression { $$ = $1; } 102 | | multiplicative_expression '*' cast_expression 103 | { $$ = newAstNode(Expression, newNodeValue(0, "multiplicative_expression"), linesno); 104 | AstNode *multiply = newAstNode(Operator, newNodeValue(0, "*"), linesno); 105 | linkAstNode($$, $1, multiply, $3, NULL); } 106 | | multiplicative_expression '/' cast_expression 107 | { $$ = newAstNode(Expression, newNodeValue(0, "multiplicative_expression"), linesno); 108 | AstNode *divide = newAstNode(Operator, newNodeValue(0, "/"), linesno); 109 | linkAstNode($$, $1, divide, $3, NULL); } 110 | | multiplicative_expression '%' cast_expression 111 | { $$ = newAstNode(Expression, newNodeValue(0, "multiplicative_expression"), linesno); 112 | AstNode *divide = newAstNode(Operator, newNodeValue(0, "%"), linesno); 113 | linkAstNode($$, $1, divide, $3, NULL); } 114 | ; 115 | 116 | additive_expression 117 | : multiplicative_expression { $$ = $1; } 118 | | additive_expression '+' multiplicative_expression 119 | { $$ = newAstNode(Expression, newNodeValue(0, "additive_expression"), linesno); 120 | AstNode *add = newAstNode(Operator, newNodeValue(0, "+"), linesno); 121 | linkAstNode($$, $1, add, $3, NULL); } 122 | | additive_expression '-' multiplicative_expression 123 | { $$ = newAstNode(Expression, newNodeValue(0, "additive_expression"), linesno); 124 | AstNode *sub = newAstNode(Operator, newNodeValue(0, "-"), linesno); 125 | linkAstNode($$, $1, sub, $3, NULL); } 126 | ; 127 | 128 | /*没有考虑移位运算*/ 129 | 130 | relational_expression 131 | : additive_expression { $$ = $1; } 132 | | relational_expression '<' additive_expression 133 | { $$ = newAstNode(Expression, newNodeValue(0, "relational_expression"), linesno); 134 | AstNode *less = newAstNode(Operator, newNodeValue(0, "<"), linesno); 135 | linkAstNode($$, $1, less, $3, NULL); } 136 | | relational_expression '>' additive_expression 137 | { $$ = newAstNode(Expression, newNodeValue(0, "relational_expression"), linesno); 138 | AstNode *greater = newAstNode(Operator, newNodeValue(0, ">"), linesno); 139 | linkAstNode($$, $1, greater, $3, NULL); } 140 | | relational_expression LE_OP additive_expression 141 | { $$ = newAstNode(Expression, newNodeValue(0, "relational_expression"), linesno); 142 | AstNode *le_op = newAstNode(Operator, newNodeValue(0, "<="), linesno); 143 | linkAstNode($$, $1, le_op, $3, NULL); } 144 | | relational_expression GE_OP additive_expression 145 | { $$ = newAstNode(Expression, newNodeValue(0, "relational_expression"), linesno); 146 | AstNode *ge_op = newAstNode(Operator, newNodeValue(0, ">="), linesno); 147 | linkAstNode($$, $1, ge_op, $3, NULL); } 148 | ; 149 | 150 | equality_expression 151 | : relational_expression { $$ = $1; } 152 | | equality_expression EQ_OP relational_expression 153 | { $$ = newAstNode(Expression, newNodeValue(0, "equality_expression"), linesno); 154 | AstNode *eq_op = newAstNode(Operator, newNodeValue(0, "=="), linesno); 155 | linkAstNode($$, $1, eq_op, $3, NULL); } 156 | | equality_expression NE_OP relational_expression 157 | { $$ = newAstNode(Expression, newNodeValue(0, "equality_expression"), linesno); 158 | AstNode *ne_op = newAstNode(Operator, newNodeValue(0, "!="), linesno); 159 | linkAstNode($$, $1, ne_op, $3, NULL); } 160 | ; 161 | 162 | and_expression 163 | : equality_expression { $$ = $1; } 164 | | and_expression '&' equality_expression 165 | { $$ = newAstNode(Expression, newNodeValue(0, "and_expression"), linesno); 166 | AstNode *and = newAstNode(Operator, newNodeValue(0, "&"), linesno); 167 | linkAstNode($$, $1, and, $3, NULL); } 168 | ; 169 | 170 | exclusive_or_expression 171 | : and_expression { $$ = $1; } 172 | | exclusive_or_expression '^' and_expression 173 | { $$ = newAstNode(Expression, newNodeValue(0, "exclusive_or_expression"), linesno); 174 | AstNode *e_or = newAstNode(Operator, newNodeValue(0, "^"), linesno); 175 | linkAstNode($$, $1, e_or, $3, NULL); } 176 | ; 177 | 178 | inclusive_or_expression 179 | : exclusive_or_expression { $$ = $1; } 180 | | inclusive_or_expression '|' exclusive_or_expression 181 | { $$ = newAstNode(Expression, newNodeValue(0, "inclusive_or_expression"), linesno); 182 | AstNode *i_or = newAstNode(Operator, newNodeValue(0, "|"), linesno); 183 | linkAstNode($$, $1, i_or, $3, NULL); } 184 | ; 185 | 186 | logical_and_expression 187 | : inclusive_or_expression { $$ = $1; } 188 | | logical_and_expression AND_OP inclusive_or_expression 189 | { $$ = newAstNode(Expression, newNodeValue(0, "logical_and_expression"), linesno); 190 | AstNode *l_and = newAstNode(Operator, newNodeValue(0, "&&"), linesno); 191 | linkAstNode($$, $1, l_and, $3, NULL); } 192 | ; 193 | 194 | logical_or_expression 195 | : logical_and_expression { $$ = $1; } 196 | | logical_or_expression OR_OP logical_and_expression 197 | { $$ = newAstNode(Expression, newNodeValue(0, "logical_or_expression"), linesno); 198 | AstNode *l_or = newAstNode(Operator, newNodeValue(0, "||"), linesno); 199 | linkAstNode($$, $1, l_or, $3, NULL); } 200 | ; 201 | 202 | expression 203 | : logical_or_expression { $$ = $1; } 204 | ; 205 | 206 | argument_expression_list 207 | : expression { $$ = $1; } 208 | | argument_expression_list ',' expression 209 | { $$ = newAstNode(Expression, newNodeValue(0, "argument_expression_list"), linesno); 210 | AstNode *comma = newAstNode(Operator, newNodeValue(0, ","), linesno); 211 | linkAstNode($$, $1, comma, $3, NULL); } 212 | ; 213 | 214 | 215 | 216 | declaration /* 暂时只考虑了简单的变量声明 */ 217 | : type_name init_declarator_list ';' 218 | { $$ = newAstNode(Declaration, newNodeValue(0, "declaration"), linesno); 219 | linkAstNode($$, $1, $2, NULL); } 220 | ; 221 | 222 | type_name /* 类型名 */ 223 | : CHAR { $$ = newAstNode(Keyword, newNodeValue(0, "char"), linesno); } 224 | | DOUBLE { $$ = newAstNode(Keyword, newNodeValue(0, "double"), linesno); } 225 | | FLOAT { $$ = newAstNode(Keyword, newNodeValue(0, "float"), linesno); } 226 | | INT { $$ = newAstNode(Keyword, newNodeValue(0, "int"), linesno); } 227 | | LONG { $$ = newAstNode(Keyword, newNodeValue(0, "long"), linesno); } 228 | | SHORT { $$ = newAstNode(Keyword, newNodeValue(0, "short"), linesno); } 229 | | SIGNED { $$ = newAstNode(Keyword, newNodeValue(0, "signed"), linesno); } 230 | | UNSIGNED { $$ = newAstNode(Keyword, newNodeValue(0, "unsigned"), linesno); } 231 | ; 232 | 233 | init_declarator_list /* 初始化列表 */ 234 | : init_declarator { $$ = $1; } 235 | | init_declarator_list ',' init_declarator 236 | { $$ = newAstNode(Expression, newNodeValue(0, "init_declarator_list"), linesno); 237 | AstNode *comma = newAstNode(Operator, newNodeValue(0, ","), linesno); 238 | linkAstNode($$, $1, comma, $3, NULL); } 239 | ; 240 | 241 | init_declarator 242 | : declarator { $$ = $1; } 243 | | declarator '=' initializer { $$ = newAstNode(Expression, newNodeValue(0, "init_declarator"), linesno); 244 | AstNode *assign = newAstNode(Operator, newNodeValue(0, "="), linesno); 245 | linkAstNode($$, $1, assign, $3, NULL); } 246 | ; 247 | 248 | declarator /* 暂时只考虑了简单的变量声明 */ 249 | : IDENTIFIER { $$ = newAstNode(Identifier, newNodeValue(0, $1), linesno); } 250 | ; 251 | 252 | initializer 253 | : NUMBER { $$ = newAstNode(Number, newNodeValue(1, $1), linesno); } 254 | | IDENTIFIER { $$ = newAstNode(Identifier, newNodeValue(0, $1), linesno); } 255 | | CHARACTER { $$ = newAstNode(String, newNodeValue(0, $1), linesno); } 256 | ; 257 | 258 | 259 | 260 | 261 | statement 262 | : assignment_statement /* 赋值语句 */ { $$ = $1; } 263 | | expression_statement /* 表达式语句 */ { $$ = $1; } 264 | | selection_statement /* 选择语句 */ { $$ = $1; } 265 | | iteration_statement /* 循环语句 */ { $$ = $1; } 266 | | jump_statement /* 跳转语句 */ { $$ = $1; } 267 | | compound_statement { $$ = $1; } 268 | ; 269 | 270 | assignment_statement 271 | : IDENTIFIER '=' expression ';' { $$ = newAstNode(Statement, newNodeValue(0, "assignment_statement"), linesno); 272 | AstNode *identifier = newAstNode(Identifier, newNodeValue(0, $1), linesno); 273 | AstNode *assign = newAstNode(Operator, newNodeValue(0, "="), linesno); 274 | AstNode *semicolon = newAstNode(Operator, newNodeValue(0, ";"), linesno); 275 | linkAstNode($$, identifier, assign, $3, semicolon, NULL); } 276 | ; 277 | 278 | expression_statement 279 | : expression ';' { $$ = newAstNode(Statement, newNodeValue(0, "expression_statement"), linesno); 280 | AstNode *semicolon = newAstNode(Operator, newNodeValue(0, ";"), linesno); 281 | linkAstNode($$, $1, semicolon, NULL); } 282 | ; 283 | 284 | selection_statement 285 | : IF '(' expression ')' compound_statement %prec LOWER_THAN_ELSE 286 | { $$ = newAstNode(Statement, newNodeValue(0, "selection_statement_no_else"), $3->linenumber); 287 | $$->endlinenumber = $5->firstchild->linenumber; 288 | AstNode *if_keyword = newAstNode(Keyword, newNodeValue(0, "if"), $3->linenumber); 289 | AstNode *left_bracket = newAstNode(Operator, newNodeValue(0, "("), $3->linenumber); 290 | AstNode *right_bracket = newAstNode(Operator, newNodeValue(0, ")"), $3->linenumber); 291 | linkAstNode($$, if_keyword, left_bracket, $3, right_bracket, $5, NULL); } 292 | | IF '(' expression ')' compound_statement ELSE compound_statement 293 | { $$ = newAstNode(Statement, newNodeValue(0, "selection_statement_with_else"), $3->linenumber); 294 | $$->endlinenumber = $7->firstchild->linenumber; 295 | AstNode *if_keyword = newAstNode(Keyword, newNodeValue(0, "if"), $3->linenumber); 296 | AstNode *else_keyword = newAstNode(Keyword, newNodeValue(0, "else"), $3->linenumber); 297 | AstNode *left_bracket = newAstNode(Operator, newNodeValue(0, "("), $3->linenumber); 298 | AstNode *right_bracket = newAstNode(Operator, newNodeValue(0, ")"), $3->linenumber); 299 | linkAstNode($$, if_keyword, left_bracket, $3, right_bracket, $5, else_keyword, $7, NULL); } 300 | ; 301 | 302 | iteration_statement 303 | : WHILE '(' expression ')' compound_statement 304 | { $$ = newAstNode(Statement, newNodeValue(0, "iteration_statement"), $3->linenumber); 305 | $$->endlinenumber = $5->firstchild->linenumber; 306 | AstNode *while_keyword = newAstNode(Keyword, newNodeValue(0, "while"), $3->linenumber); 307 | AstNode *left_bracket = newAstNode(Operator, newNodeValue(0, "("), $3->linenumber); 308 | AstNode *right_bracket = newAstNode(Operator, newNodeValue(0, ")"), $3->linenumber); 309 | linkAstNode($$, while_keyword, left_bracket, $3, right_bracket, $5, NULL); } 310 | ; 311 | 312 | jump_statement 313 | : RETURN ';' { $$ = newAstNode(Statement, newNodeValue(0, "jump_statement"), linesno); 314 | AstNode *return_keyword = newAstNode(Keyword, newNodeValue(0, "return"), linesno); 315 | AstNode *semicolon = newAstNode(Operator, newNodeValue(0, ";"), linesno); 316 | linkAstNode($$, return_keyword, semicolon, NULL); } 317 | | RETURN expression ';' { $$ = newAstNode(Statement, newNodeValue(0, "jump_statement"), linesno); 318 | AstNode *return_keyword = newAstNode(Keyword, newNodeValue(0, "return"), linesno); 319 | AstNode *semicolon = newAstNode(Operator, newNodeValue(0, ";"), linesno); 320 | linkAstNode($$, return_keyword, $2, semicolon, NULL); } 321 | ; 322 | 323 | 324 | 325 | translation_unit 326 | : function_definition /*仅仅用来考虑无参main函数的,其他函数情况暂时没有考虑*/ 327 | { ast_root = $1; } 328 | ; 329 | 330 | function_definition 331 | : type_name IDENTIFIER '(' ')' compound_statement 332 | { $$ = newAstNode(FunctionDefinition, newNodeValue(0, "function_definition"), $1->linenumber); 333 | AstNode *identifier = newAstNode(Identifier, newNodeValue(0, $2), $1->linenumber); 334 | AstNode *left_bracket = newAstNode(Operator, newNodeValue(0, "("), $1->linenumber); 335 | AstNode *right_bracket = newAstNode(Operator, newNodeValue(0, ")"), $1->linenumber); 336 | linkAstNode($$, $1, identifier, left_bracket, right_bracket, $5, NULL); } 337 | ; 338 | 339 | compound_statement 340 | : '{' '}' { $$ = newAstNode(FunctionDefinition, newNodeValue(0, "compound_statement"), linesno); 341 | AstNode *big_left_bracket = newAstNode(Operator, newNodeValue(0, "{"), linesno); 342 | AstNode *big_right_bracket = newAstNode(Operator, newNodeValue(0, "}"), linesno); 343 | linkAstNode($$, big_left_bracket, big_right_bracket, NULL); } 344 | | '{' block_item_list '}' { $$ = newAstNode(FunctionDefinition, newNodeValue(0, "compound_statement"), $2->linenumber-1); 345 | AstNode *big_left_bracket = newAstNode(Operator, newNodeValue(0, "{"), linesno); 346 | AstNode *big_right_bracket = newAstNode(Operator, newNodeValue(0, "}"), linesno); 347 | linkAstNode($$, big_left_bracket, $2, big_right_bracket, NULL); } 348 | ; 349 | 350 | block_item_list 351 | : block_item { $$ = $1; } 352 | | block_item_list block_item { $$ = newAstNode(FunctionDefinition, newNodeValue(0, "block_item_list"), $1->linenumber); 353 | linkAstNode($$, $1, $2, NULL); } 354 | ; 355 | 356 | block_item 357 | : declaration { $$ = $1; } 358 | | statement { $$ = $1; } 359 | ; 360 | 361 | %% 362 | 363 | void yyerror(char *s) 364 | { 365 | fflush(stdout); 366 | fprintf(stderr, "Error: lines %d: %s\n", linesno, s); 367 | } -------------------------------------------------------------------------------- /cfg.dot: -------------------------------------------------------------------------------- 1 | digraph CFG { 2 | Entry0 -> Assign_express_jump9 3 | Assign_express_jump9 -> Assign_express_jump10 4 | Assign_express_jump10 -> Assign_express_jump11 5 | Assign_express_jump11 -> Select13 6 | Select13 -> Assign_express_jump15 7 | Assign_express_jump15 -> Iteration18 8 | Iteration18 -> Assign_express_jump20 9 | Assign_express_jump20 -> Assign_express_jump21 10 | Assign_express_jump21 -> Assign_express_jump23 11 | Assign_express_jump23 -> Iteration18 12 | Iteration18 -> Assign_express_jump26 13 | Assign_express_jump26 -> Assign_express_jump27 14 | Assign_express_jump27 -> Assign_express_jump29 15 | Assign_express_jump29 -> Exit0 16 | Select13 -> Iteration18 17 | } 18 | -------------------------------------------------------------------------------- /cfg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fengcc/ProgramSlicing/7159357011bf50cd4f188683fa60aeed1c63cab1/cfg.png -------------------------------------------------------------------------------- /cfg_node.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "cfg_node.h" 6 | 7 | CfgNode *createCFG(AstNode *node_ast) 8 | { 9 | CfgNode *entrynode = newCfgNode(Entry); 10 | CfgNode *exitnode = newCfgNode(Exit); 11 | NodeParameterList *first, *last; 12 | NodeParameterList *p; /*用于节点释放空间时*/ 13 | CfgNodeList *pred; 14 | 15 | /*抽象语法树是从1开始编号的,这里把控制流图的入口和出口节点的id_of_ast的值都设为0,以示特殊*/ 16 | entrynode->node_of_ast = exitnode->node_of_ast = NULL; 17 | 18 | /*为入口节点创建一个后继节点,路径值为true*/ 19 | entrynode->successor = (CfgNodeList *)malloc(sizeof(CfgNodeList)); 20 | entrynode->successor->path_value = true; 21 | entrynode->successor->next = NULL; 22 | 23 | first = (NodeParameterList *)malloc(sizeof(NodeParameterList)); 24 | first->node_succ = entrynode->successor; 25 | first->node_cfg = entrynode; 26 | first->next = NULL; 27 | 28 | last = createNodeRecursively(first, node_ast); 29 | 30 | while (last) 31 | { 32 | last->node_succ->node_cfg = exitnode; /*将上一个节点的后继节点赋为当前节点*/ 33 | 34 | pred = (CfgNodeList *)malloc(sizeof(CfgNodeList)); 35 | pred->path_value = last->node_succ->path_value; 36 | pred->node_cfg = last->node_cfg; /*将此节点的前驱节点指向上一个节点*/ 37 | 38 | /*头插法插入前驱节点链表中*/ 39 | pred->next = exitnode->predecessor; 40 | exitnode->predecessor = pred; 41 | 42 | p = last; 43 | last = last->next; 44 | free(p); 45 | } 46 | 47 | return entrynode; 48 | } 49 | 50 | NodeParameterList *createNodeRecursively(NodeParameterList *succlist, AstNode *node_ast) 51 | { 52 | NodeParameterList *path_return; 53 | AstNode *p; 54 | 55 | if (!node_ast) /*node_ast为NULL*/ 56 | return succlist; 57 | 58 | if (node_ast->nodetype_ast == Statement) 59 | { 60 | /*赋值语句或表达式语句*/ 61 | if (strcmp(node_ast->value.value_string, "assignment_statement") == 0 62 | || strcmp(node_ast->value.value_string, "expression_statement") == 0 63 | || strcmp(node_ast->value.value_string, "jump_statement") == 0) 64 | path_return = assign_express_jump_case(succlist, node_ast); 65 | 66 | /*选择语句*/ 67 | if (strcmp(node_ast->value.value_string, "selection_statement_no_else") == 0) 68 | path_return = select_no_else_case(succlist, node_ast); 69 | if (strcmp(node_ast->value.value_string, "selection_statement_with_else") == 0) 70 | path_return = select_with_else_case(succlist, node_ast); 71 | 72 | /*循环语句*/ 73 | if (strcmp(node_ast->value.value_string, "iteration_statement") == 0) 74 | path_return = iteration_case(succlist, node_ast); 75 | 76 | } 77 | else 78 | { 79 | path_return = createNodeRecursively(succlist, node_ast->firstchild); 80 | 81 | if (node_ast->firstchild) /*有第一个孩子*/ 82 | { 83 | p = node_ast->firstchild->nextsibling; 84 | while (p) 85 | { 86 | path_return = createNodeRecursively(path_return, p); 87 | p = p->nextsibling; 88 | } 89 | } 90 | } 91 | 92 | return path_return; 93 | } 94 | 95 | NodeParameterList *assign_express_jump_case(NodeParameterList *succlist, AstNode *node_ast) 96 | { 97 | CfgNode *temp = newCfgNode(Assign_express_jump); 98 | NodeParameterList *path_return; 99 | NodeParameterList *p; /*用于节点释放空间时*/ 100 | CfgNodeList *pred; 101 | 102 | temp->node_of_ast = node_ast; 103 | 104 | if (strcmp(node_ast->value.value_string, "assignment_statement") == 0) 105 | { 106 | collectSymbol(node_ast->firstchild, &temp->def_s); 107 | collectSymbol(node_ast->firstchild->nextsibling->nextsibling, &temp->use_s); 108 | } 109 | 110 | /*创建后继节点*/ 111 | temp->successor = (CfgNodeList *)malloc(sizeof(CfgNodeList)); 112 | temp->successor->path_value = true; 113 | temp->successor->next = NULL; 114 | 115 | while (succlist) 116 | { 117 | succlist->node_succ->node_cfg = temp; /*将上一个节点的后继节点赋为当前节点*/ 118 | 119 | pred = (CfgNodeList *)malloc(sizeof(CfgNodeList)); 120 | pred->path_value = succlist->node_succ->path_value; 121 | pred->node_cfg = succlist->node_cfg; /*将此节点的前驱节点指向上一个节点*/ 122 | 123 | /*头插法插入前驱节点链表中*/ 124 | pred->next = temp->predecessor; 125 | temp->predecessor = pred; 126 | 127 | p = succlist; 128 | succlist = succlist->next; 129 | free(p); 130 | } 131 | 132 | path_return = (NodeParameterList *)malloc(sizeof(NodeParameterList)); 133 | path_return->node_succ = temp->successor; 134 | path_return->node_cfg = temp; 135 | path_return->next = NULL; 136 | 137 | return path_return; 138 | } 139 | 140 | NodeParameterList *select_no_else_case(NodeParameterList *succlist, AstNode *node_ast) 141 | { 142 | CfgNode *ifnode = newCfgNode(Select); 143 | NodeParameterList *to_true_path, *true_path_return, *false_path; 144 | NodeParameterList *p; /*用于节点释放空间时*/ 145 | CfgNodeList *pred; 146 | 147 | ifnode->node_of_ast = node_ast; 148 | /*选择语句有两个后继节点,一个路径值为true,另一个为false*/ 149 | ifnode->successor = (CfgNodeList *)malloc(sizeof(CfgNodeList)); 150 | ifnode->successor->path_value = true; 151 | ifnode->successor->next = (CfgNodeList *)malloc(sizeof(CfgNodeList)); 152 | ifnode->successor->next->path_value = false; 153 | ifnode->successor->next->next = NULL; 154 | 155 | while (succlist) 156 | { 157 | succlist->node_succ->node_cfg = ifnode; /*将上一个节点的后继节点赋为当前节点*/ 158 | 159 | pred = (CfgNodeList *)malloc(sizeof(CfgNodeList)); 160 | pred->path_value = succlist->node_succ->path_value; 161 | pred->node_cfg = succlist->node_cfg; /*将此节点的前驱节点指向上一个节点*/ 162 | 163 | /*头插法插入前驱节点链表中*/ 164 | pred->next = ifnode->predecessor; 165 | ifnode->predecessor = pred; 166 | 167 | p = succlist; 168 | succlist = succlist->next; 169 | free(p); 170 | } 171 | 172 | to_true_path = (NodeParameterList *)malloc(sizeof(NodeParameterList)); 173 | to_true_path->node_succ = ifnode->successor; 174 | to_true_path->node_cfg = ifnode; 175 | to_true_path->next = NULL; 176 | 177 | true_path_return = createNodeRecursively(to_true_path, 178 | /*第五个孩子*/ node_ast->firstchild->nextsibling->nextsibling->nextsibling->nextsibling); 179 | 180 | /*将if节点的false路径插入true路径的返回链表中,即得到整个if语句的返回链表*/ 181 | false_path = (NodeParameterList *)malloc(sizeof(NodeParameterList)); 182 | false_path->node_succ = ifnode->successor->next; 183 | false_path->node_cfg = ifnode; 184 | /*头插法*/ 185 | false_path->next = true_path_return; 186 | true_path_return = false_path; 187 | 188 | return true_path_return; 189 | } 190 | 191 | NodeParameterList *select_with_else_case(NodeParameterList *succlist, AstNode *node_ast) 192 | { 193 | CfgNode *ifnode = newCfgNode(Select); 194 | NodeParameterList *to_true_path, *to_false_path, *true_path_return, *false_path_return, *q; 195 | NodeParameterList *p; /*用于节点释放空间时*/ 196 | CfgNodeList *pred; 197 | 198 | ifnode->node_of_ast = node_ast; 199 | 200 | /*if节点有两个后继节点,一个路径值为true,另一个为false*/ 201 | ifnode->successor = (CfgNodeList *)malloc(sizeof(CfgNodeList)); 202 | ifnode->successor->path_value = true; 203 | ifnode->successor->next = (CfgNodeList *)malloc(sizeof(CfgNodeList)); 204 | ifnode->successor->next->path_value = false; 205 | ifnode->successor->next->next = NULL; 206 | 207 | while (succlist) 208 | { 209 | succlist->node_succ->node_cfg = ifnode; /*将上一个节点的后继节点赋为当前节点*/ 210 | 211 | pred = (CfgNodeList *)malloc(sizeof(CfgNodeList)); 212 | pred->path_value = succlist->node_succ->path_value; 213 | pred->node_cfg = succlist->node_cfg; /*将此节点的前驱节点指向上一个节点*/ 214 | 215 | /*头插法插入前驱节点链表中*/ 216 | pred->next = ifnode->predecessor; 217 | ifnode->predecessor = pred; 218 | 219 | p = succlist; 220 | succlist = succlist->next; 221 | free(p); 222 | } 223 | 224 | to_true_path = (NodeParameterList *)malloc(sizeof(NodeParameterList)); 225 | to_true_path->node_succ = ifnode->successor; 226 | to_true_path->node_cfg = ifnode; 227 | to_true_path->next = NULL; 228 | 229 | to_false_path = (NodeParameterList *)malloc(sizeof(NodeParameterList)); 230 | to_false_path->node_succ = ifnode->successor->next; 231 | to_false_path->node_cfg = ifnode; 232 | to_false_path->next = NULL; 233 | 234 | true_path_return = createNodeRecursively(to_true_path, 235 | /*第五个孩子*/ node_ast->firstchild->nextsibling->nextsibling->nextsibling->nextsibling); 236 | false_path_return= createNodeRecursively(to_false_path, 237 | /*第七个孩子*/ node_ast->firstchild->nextsibling->nextsibling->nextsibling->nextsibling->nextsibling->nextsibling); 238 | 239 | /*找到最后一个节点*/ 240 | for (q = true_path_return; q->next; q = q->next); 241 | /*将false_path_return连接在其后,即得到整个if语句的返回链表*/ 242 | q->next = false_path_return; 243 | 244 | return true_path_return; 245 | } 246 | 247 | NodeParameterList *iteration_case(NodeParameterList *succlist, AstNode *node_ast) 248 | { 249 | CfgNode *whilenode = newCfgNode(Iteration); 250 | NodeParameterList *to_true_path, *to_false_path, *true_path_return; 251 | NodeParameterList *p; /*用于节点释放空间时*/ 252 | CfgNodeList *pred; 253 | 254 | whilenode->node_of_ast = node_ast; 255 | 256 | /*while节点有两个后继节点,一个路径值为true,另一个为false*/ 257 | whilenode->successor = (CfgNodeList *)malloc(sizeof(CfgNodeList)); 258 | whilenode->successor->path_value = true; 259 | whilenode->successor->next = (CfgNodeList *)malloc(sizeof(CfgNodeList)); 260 | whilenode->successor->next->path_value = false; 261 | whilenode->successor->next->next = NULL; 262 | 263 | while (succlist) 264 | { 265 | succlist->node_succ->node_cfg = whilenode; /*将上一个节点的后继节点赋为当前节点*/ 266 | 267 | pred = (CfgNodeList *)malloc(sizeof(CfgNodeList)); 268 | pred->path_value = succlist->node_succ->path_value; 269 | pred->node_cfg = succlist->node_cfg; /*将此节点的前驱节点指向上一个节点*/ 270 | 271 | /*头插法插入前驱节点链表中*/ 272 | pred->next = whilenode->predecessor; 273 | whilenode->predecessor = pred; 274 | 275 | p = succlist; 276 | succlist = succlist->next; 277 | free(p); 278 | } 279 | 280 | to_true_path = (NodeParameterList *)malloc(sizeof(NodeParameterList)); 281 | to_true_path->node_succ = whilenode->successor; 282 | to_true_path->node_cfg = whilenode; 283 | to_true_path->next = NULL; 284 | 285 | to_false_path = (NodeParameterList *)malloc(sizeof(NodeParameterList)); 286 | to_false_path->node_succ = whilenode->successor->next; 287 | to_false_path->node_cfg = whilenode; 288 | to_false_path->next = NULL; 289 | 290 | true_path_return = createNodeRecursively(to_true_path, 291 | /*第五个孩子*/ node_ast->firstchild->nextsibling->nextsibling->nextsibling->nextsibling); 292 | 293 | /*循环结尾指向自己*/ 294 | while (true_path_return) 295 | { 296 | true_path_return->node_succ->node_cfg = whilenode; /*将上一个节点的后继节点赋为当前节点*/ 297 | 298 | pred = (CfgNodeList *)malloc(sizeof(CfgNodeList)); 299 | pred->path_value = true_path_return->node_succ->path_value; 300 | pred->node_cfg = true_path_return->node_cfg; /*将此节点的前驱节点指向上一个节点*/ 301 | 302 | /*头插法插入前驱节点链表中*/ 303 | pred->next = whilenode->predecessor; 304 | whilenode->predecessor = pred; 305 | 306 | p = true_path_return; 307 | true_path_return = true_path_return->next; 308 | free(p); 309 | } 310 | 311 | return to_false_path; 312 | } 313 | 314 | void collectSymbol(AstNode *node_ast, Symbol **symbol_list) 315 | { 316 | Symbol *p; 317 | AstNode *q; 318 | 319 | if (!node_ast) 320 | return; 321 | 322 | if (node_ast->nodetype_ast == Identifier) 323 | { 324 | p = (Symbol *)malloc(sizeof(Symbol)); 325 | strcpy(p->name, node_ast->value.value_string); 326 | 327 | /*头插法*/ 328 | p->next = *symbol_list; 329 | *symbol_list = p; 330 | } 331 | 332 | /*两个if只会执行其中一个,因为Identifier型的节点没有孩子*/ 333 | if (node_ast->firstchild) 334 | { 335 | collectSymbol(node_ast->firstchild, symbol_list); 336 | 337 | q = node_ast->firstchild->nextsibling; 338 | while (q) 339 | { 340 | collectSymbol(q, symbol_list); 341 | q = q->nextsibling; 342 | } 343 | } 344 | } 345 | 346 | CfgNode *newCfgNode(enum CfgNodeType type) 347 | { 348 | CfgNode *node = (CfgNode *)malloc(sizeof(CfgNode)); 349 | 350 | node->nodetype_cfg = type; 351 | 352 | node->node_of_ast = NULL; 353 | 354 | node->visited = false; 355 | 356 | node->def_s = node->use_s = NULL; 357 | 358 | node->predecessor = node->successor = NULL; 359 | 360 | return node; 361 | } 362 | 363 | void freeCfgNode(CfgNode *node) 364 | { 365 | CfgNodeList *p, *q; 366 | Symbol *m, *n; 367 | 368 | node->visited = true; 369 | 370 | p = node->successor; 371 | while (p) 372 | { 373 | if (!p->node_cfg->visited) 374 | freeCfgNode(p->node_cfg); 375 | 376 | q = p; 377 | p = p->next; 378 | free(q); /*释放后继节点列表所占空间*/ 379 | } 380 | 381 | /*释放前驱节点链表所占空间*/ 382 | p = node->predecessor; 383 | while (p) 384 | { 385 | q = p; 386 | p = p->next; 387 | free(q); 388 | } 389 | 390 | /*释放节点定义变量链表*/ 391 | m = node->def_s; 392 | while (m) 393 | { 394 | n = m; 395 | m = m->next; 396 | free(n); 397 | } 398 | 399 | /*释放节点使用变量链表*/ 400 | m = node->use_s; 401 | while (m) 402 | { 403 | n = m; 404 | m = m->next; 405 | free(n); 406 | } 407 | 408 | /*退出之前释放当前节点所占空间*/ 409 | free(node); 410 | } -------------------------------------------------------------------------------- /cfg_node.h: -------------------------------------------------------------------------------- 1 | #ifndef CFG_H 2 | #define CFG_H 3 | 4 | #include "ast_node.h" 5 | #include "symbol.h" 6 | 7 | #define true 1 8 | #define false 0 9 | 10 | enum CfgNodeType 11 | { 12 | Entry, 13 | Assign_express_jump, 14 | Select, 15 | Iteration, 16 | Exit 17 | }; 18 | 19 | /*用来保存后继节点指针的链表节点*/ 20 | struct _CfgNodeList 21 | { 22 | int path_value; /*路径值,true或false*/ 23 | struct _CfgNode *node_cfg; 24 | struct _CfgNodeList *next; 25 | }; 26 | 27 | /*在此是一条语句一个控制流图节点,而不是一个语句块一个节点*/ 28 | struct _CfgNode 29 | { 30 | enum CfgNodeType nodetype_cfg; 31 | 32 | AstNode *node_of_ast; /*对应的抽象语法树节点*/ 33 | int visited; /*节点是否访问过*/ 34 | 35 | Symbol *def_s, *use_s; /*节点定义和使用的变量链表*/ 36 | 37 | struct _CfgNodeList *predecessor; /*前驱节点指针链表*/ 38 | struct _CfgNodeList *successor; /*后继节点指针链表*/ 39 | }; 40 | 41 | typedef struct _CfgNodeList CfgNodeList; 42 | typedef struct _CfgNode CfgNode; 43 | 44 | /*用于建立控制流图时作为参数传递使用*/ 45 | typedef struct NodeParameterList 46 | { 47 | CfgNode *node_cfg; /*用于连接节点的前驱节点时使用*/ 48 | CfgNodeList *node_succ; /*用于连接节点的后继节点时使用*/ 49 | struct NodeParameterList *next; 50 | }NodeParameterList; 51 | 52 | /*根据抽象语法树,创建控制流图*/ 53 | CfgNode *createCFG(AstNode *node_ast); 54 | 55 | /*先序递归遍历抽象语法树,同时建立控制流图,由createCFG()函数调用*/ 56 | NodeParameterList *createNodeRecursively(NodeParameterList *succlist, AstNode *node_ast); 57 | 58 | /*---------------不同类型节点处理函数----------------*/ 59 | /*赋值语句节点或表达式语句节点或跳转语句节点处理函数*/ 60 | NodeParameterList *assign_express_jump_case(NodeParameterList *succlist, AstNode *node_ast); 61 | /*选择语句节点处理函数*/ 62 | NodeParameterList *select_no_else_case(NodeParameterList *succlist, AstNode *node_ast); 63 | NodeParameterList *select_with_else_case(NodeParameterList *succlist, AstNode *node_ast); 64 | /*循环语句处理函数*/ 65 | NodeParameterList *iteration_case(NodeParameterList *succlist, AstNode *node_ast); 66 | 67 | /*创建控制流图节点,由节点处理函数调用*/ 68 | CfgNode *newCfgNode(enum CfgNodeType type); 69 | 70 | /*将抽象语法树节点node_ast中的符号使用信息插入符号链表中*/ 71 | void collectSymbol(AstNode *node_ast, Symbol **symbol_list); 72 | 73 | void freeCfgNode(CfgNode *node); 74 | 75 | #endif -------------------------------------------------------------------------------- /flex_c.l: -------------------------------------------------------------------------------- 1 | %{ 2 | #include 3 | #include 4 | #include 5 | #include "bison_c.tab.h" 6 | #include "ast_node.h" 7 | 8 | FILE *yyin; 9 | int linesno = 1; 10 | 11 | void comment(); 12 | void ignoreHeadfile(); 13 | %} 14 | 15 | digit [0-9] 16 | number ("+"|"-")?{digit}+ 17 | letter [a-zA-Z_] 18 | identifier {letter}({letter}|{digit})* 19 | 20 | %% 21 | 22 | "/*" { comment(); } 23 | "//".* { /*ignore comment*/ } 24 | 25 | "auto" { return AUTO; } 26 | "break" { return BREAK; } 27 | "case" { return CASE; } 28 | "char" { return CHAR; } 29 | "define" { return DEFINE; } 30 | "continue" { return CONTINUE; } 31 | "default" { return DEFAULT; } 32 | "do" { return DO; } 33 | "double" { return DOUBLE; } 34 | "else" { return ELSE; } 35 | "enum" { return ENUM; } 36 | "extern" { return EXTERN; } 37 | "float" { return FLOAT; } 38 | "for" { return FOR; } 39 | "goto" { return GOTO; } 40 | "if" { return IF; } 41 | "int" { return INT; } 42 | "long" { return LONG; } 43 | "register" { return REGISTER; } 44 | "return" { return RETURN; } 45 | "short" { return SHORT; } 46 | "signed" { return SIGNED; } 47 | "sizeof" { return SIZEOF; } 48 | "static" { return STATIC; } 49 | "struct" { return STRUCT; } 50 | "switch" { return SWITCH; } 51 | "typedef" { return TYPEDEF; } 52 | "union" { return UNION; } 53 | "unsigned" { return UNSIGNED; } 54 | "void" { return VOID; } 55 | "volatile" { return VOLATILE; } 56 | "while" { return WHILE; } 57 | 58 | "+=" { return ADD_ASSIGN; } 59 | "-=" { return SUB_ASSIGN; } 60 | "*=" { return MUL_ASSIGN; } 61 | "/=" { return DIV_ASSIGN; } 62 | "++" { return INC_OP; } 63 | "--" { return DEC_OP; } 64 | "&&" { return AND_OP; } 65 | "||" { return OR_OP; } 66 | "<=" { return LE_OP; } 67 | ">=" { return GE_OP; } 68 | "==" { return EQ_OP; } 69 | "!=" { return NE_OP; } 70 | ";" { return ';'; } 71 | "{" { return '{'; } 72 | "}" { return '}'; } 73 | "," { return ','; } 74 | ":" { return ':'; } 75 | "=" { return '='; } 76 | "(" { return '('; } 77 | ")" { return ')'; } 78 | "[" { return '['; } 79 | "]" { return ']'; } 80 | "." { return '.'; } 81 | "&" { return '&'; } 82 | "!" { return '!'; } 83 | "~" { return '~'; } 84 | "-" { return '-'; } 85 | "+" { return '+'; } 86 | "*" { return '*'; } 87 | "/" { return '/'; } 88 | "%" { return '%'; } 89 | "<" { return '<'; } 90 | ">" { return '>'; } 91 | "^" { return '^'; } 92 | "|" { return '|'; } 93 | "?" { return '?'; } 94 | 95 | {number}("."{digit})? { yylval.d = atof(yytext); return NUMBER; } 96 | {identifier} { strcpy(yylval.s, yytext); return IDENTIFIER; } 97 | \"(.)+\" { strcpy(yylval.s, yytext); return STRING_CONSTANT; } 98 | \'.\' { yylval.s[0] = *yytext; yylval.s[1] = '\0'; return CHARACTER; } 99 | "#" { ignoreHeadfile(); linesno++; } 100 | \n { linesno++; } 101 | . { /*other characters*/ } 102 | 103 | %% 104 | void comment(void) 105 | { 106 | char c ,prev = NULL; 107 | 108 | while ((c = input()) != 0) 109 | { 110 | if ( c == '\n') 111 | linesno++; 112 | if (prev == '*' && c == '/') 113 | return; 114 | prev = c; 115 | } 116 | error("unterminated comment"); 117 | } 118 | 119 | void ignoreHeadfile() 120 | { 121 | while(input() != '\n'); 122 | 123 | return; 124 | } -------------------------------------------------------------------------------- /graph_to_dot.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "graph_to_dot.h" 5 | 6 | char *enum_to_string[] = { 7 | "Entry", 8 | "Assign_express_jump", 9 | "Select", 10 | "Iteration", 11 | "Exit" 12 | }; 13 | 14 | void graph_to_dot(CfgNode *root) 15 | { 16 | FILE *dotfile; 17 | RecordCfgNode *visited_node_list = NULL, *p; 18 | 19 | if ((dotfile = fopen("cfg.dot", "w")) == NULL) 20 | { 21 | printf("open file failed!\n"); 22 | return; 23 | } 24 | 25 | fprintf(dotfile, "digraph CFG {\n"); 26 | 27 | DFSTraverse(root, dotfile, &visited_node_list); 28 | 29 | fprintf(dotfile, "}\n"); 30 | 31 | fclose(dotfile); 32 | 33 | while (visited_node_list) 34 | { 35 | visited_node_list->node_cfg->visited = false; 36 | 37 | p = visited_node_list; 38 | visited_node_list = visited_node_list->next; 39 | free(p); 40 | } 41 | 42 | /*编译产生图片*/ 43 | system("dot -Tpng -o cfg.png cfg.dot"); 44 | } 45 | 46 | void DFSTraverse(CfgNode *node, FILE *dotfile, RecordCfgNode **visited_node) 47 | { 48 | CfgNodeList *p; 49 | RecordCfgNode *q; 50 | 51 | node->visited = true; 52 | 53 | q = (RecordCfgNode *)malloc(sizeof(RecordCfgNode)); 54 | q->node_cfg = node; 55 | q->next = *visited_node; 56 | *visited_node = q; 57 | 58 | for (p = node->successor; p ; p = p->next) 59 | { 60 | fprintf(dotfile, " %s%d -> %s%d\n", 61 | enum_to_string[node->nodetype_cfg], node->node_of_ast ? node->node_of_ast->linenumber : 0, 62 | enum_to_string[p->node_cfg->nodetype_cfg], 63 | p->node_cfg->node_of_ast ? p->node_cfg->node_of_ast->linenumber : 0 ); 64 | 65 | if ( !p->node_cfg->visited) 66 | DFSTraverse(p->node_cfg, dotfile, visited_node); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /graph_to_dot.h: -------------------------------------------------------------------------------- 1 | #ifndef GRAPH_TO_DOT_H 2 | #define GRAPH_TO_DOT_H 3 | 4 | #include 5 | 6 | #include "cfg_node.h" 7 | #include "program_slicing.h" 8 | 9 | void graph_to_dot(CfgNode *root); 10 | 11 | /*深度优先遍历控制流图,由graph_to_dot()函数调用*/ 12 | void DFSTraverse(CfgNode *node, FILE *dotfile, RecordCfgNode **visited_node); 13 | 14 | #endif -------------------------------------------------------------------------------- /lex.yy.c: -------------------------------------------------------------------------------- 1 | 2 | #line 3 "lex.yy.c" 3 | 4 | #define YY_INT_ALIGNED short int 5 | 6 | /* A lexical scanner generated by flex */ 7 | 8 | #define FLEX_SCANNER 9 | #define YY_FLEX_MAJOR_VERSION 2 10 | #define YY_FLEX_MINOR_VERSION 5 11 | #define YY_FLEX_SUBMINOR_VERSION 37 12 | #if YY_FLEX_SUBMINOR_VERSION > 0 13 | #define FLEX_BETA 14 | #endif 15 | 16 | /* First, we deal with platform-specific or compiler-specific issues. */ 17 | 18 | /* begin standard C headers. */ 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | /* end standard C headers. */ 25 | 26 | /* flex integer type definitions */ 27 | 28 | #ifndef FLEXINT_H 29 | #define FLEXINT_H 30 | 31 | /* C99 systems have . Non-C99 systems may or may not. */ 32 | 33 | #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L 34 | 35 | /* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, 36 | * if you want the limit (max/min) macros for int types. 37 | */ 38 | #ifndef __STDC_LIMIT_MACROS 39 | #define __STDC_LIMIT_MACROS 1 40 | #endif 41 | 42 | #include 43 | typedef int8_t flex_int8_t; 44 | typedef uint8_t flex_uint8_t; 45 | typedef int16_t flex_int16_t; 46 | typedef uint16_t flex_uint16_t; 47 | typedef int32_t flex_int32_t; 48 | typedef uint32_t flex_uint32_t; 49 | #else 50 | typedef signed char flex_int8_t; 51 | typedef short int flex_int16_t; 52 | typedef int flex_int32_t; 53 | typedef unsigned char flex_uint8_t; 54 | typedef unsigned short int flex_uint16_t; 55 | typedef unsigned int flex_uint32_t; 56 | 57 | /* Limits of integral types. */ 58 | #ifndef INT8_MIN 59 | #define INT8_MIN (-128) 60 | #endif 61 | #ifndef INT16_MIN 62 | #define INT16_MIN (-32767-1) 63 | #endif 64 | #ifndef INT32_MIN 65 | #define INT32_MIN (-2147483647-1) 66 | #endif 67 | #ifndef INT8_MAX 68 | #define INT8_MAX (127) 69 | #endif 70 | #ifndef INT16_MAX 71 | #define INT16_MAX (32767) 72 | #endif 73 | #ifndef INT32_MAX 74 | #define INT32_MAX (2147483647) 75 | #endif 76 | #ifndef UINT8_MAX 77 | #define UINT8_MAX (255U) 78 | #endif 79 | #ifndef UINT16_MAX 80 | #define UINT16_MAX (65535U) 81 | #endif 82 | #ifndef UINT32_MAX 83 | #define UINT32_MAX (4294967295U) 84 | #endif 85 | 86 | #endif /* ! C99 */ 87 | 88 | #endif /* ! FLEXINT_H */ 89 | 90 | #ifdef __cplusplus 91 | 92 | /* The "const" storage-class-modifier is valid. */ 93 | #define YY_USE_CONST 94 | 95 | #else /* ! __cplusplus */ 96 | 97 | /* C99 requires __STDC__ to be defined as 1. */ 98 | #if defined (__STDC__) 99 | 100 | #define YY_USE_CONST 101 | 102 | #endif /* defined (__STDC__) */ 103 | #endif /* ! __cplusplus */ 104 | 105 | #ifdef YY_USE_CONST 106 | #define yyconst const 107 | #else 108 | #define yyconst 109 | #endif 110 | 111 | /* Returned upon end-of-file. */ 112 | #define YY_NULL 0 113 | 114 | /* Promotes a possibly negative, possibly signed char to an unsigned 115 | * integer for use as an array index. If the signed char is negative, 116 | * we want to instead treat it as an 8-bit unsigned char, hence the 117 | * double cast. 118 | */ 119 | #define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) 120 | 121 | /* Enter a start condition. This macro really ought to take a parameter, 122 | * but we do it the disgusting crufty way forced on us by the ()-less 123 | * definition of BEGIN. 124 | */ 125 | #define BEGIN (yy_start) = 1 + 2 * 126 | 127 | /* Translate the current start state into a value that can be later handed 128 | * to BEGIN to return to the state. The YYSTATE alias is for lex 129 | * compatibility. 130 | */ 131 | #define YY_START (((yy_start) - 1) / 2) 132 | #define YYSTATE YY_START 133 | 134 | /* Action number for EOF rule of a given start state. */ 135 | #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) 136 | 137 | /* Special action meaning "start processing a new file". */ 138 | #define YY_NEW_FILE yyrestart(yyin ) 139 | 140 | #define YY_END_OF_BUFFER_CHAR 0 141 | 142 | /* Size of default input buffer. */ 143 | #ifndef YY_BUF_SIZE 144 | #define YY_BUF_SIZE 16384 145 | #endif 146 | 147 | /* The state buf must be large enough to hold one state per character in the main buffer. 148 | */ 149 | #define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) 150 | 151 | #ifndef YY_TYPEDEF_YY_BUFFER_STATE 152 | #define YY_TYPEDEF_YY_BUFFER_STATE 153 | typedef struct yy_buffer_state *YY_BUFFER_STATE; 154 | #endif 155 | 156 | #ifndef YY_TYPEDEF_YY_SIZE_T 157 | #define YY_TYPEDEF_YY_SIZE_T 158 | typedef size_t yy_size_t; 159 | #endif 160 | 161 | extern yy_size_t yyleng; 162 | 163 | extern FILE *yyin, *yyout; 164 | 165 | #define EOB_ACT_CONTINUE_SCAN 0 166 | #define EOB_ACT_END_OF_FILE 1 167 | #define EOB_ACT_LAST_MATCH 2 168 | 169 | #define YY_LESS_LINENO(n) 170 | 171 | /* Return all but the first "n" matched characters back to the input stream. */ 172 | #define yyless(n) \ 173 | do \ 174 | { \ 175 | /* Undo effects of setting up yytext. */ \ 176 | int yyless_macro_arg = (n); \ 177 | YY_LESS_LINENO(yyless_macro_arg);\ 178 | *yy_cp = (yy_hold_char); \ 179 | YY_RESTORE_YY_MORE_OFFSET \ 180 | (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ 181 | YY_DO_BEFORE_ACTION; /* set up yytext again */ \ 182 | } \ 183 | while ( 0 ) 184 | 185 | #define unput(c) yyunput( c, (yytext_ptr) ) 186 | 187 | #ifndef YY_STRUCT_YY_BUFFER_STATE 188 | #define YY_STRUCT_YY_BUFFER_STATE 189 | struct yy_buffer_state 190 | { 191 | FILE *yy_input_file; 192 | 193 | char *yy_ch_buf; /* input buffer */ 194 | char *yy_buf_pos; /* current position in input buffer */ 195 | 196 | /* Size of input buffer in bytes, not including room for EOB 197 | * characters. 198 | */ 199 | yy_size_t yy_buf_size; 200 | 201 | /* Number of characters read into yy_ch_buf, not including EOB 202 | * characters. 203 | */ 204 | yy_size_t yy_n_chars; 205 | 206 | /* Whether we "own" the buffer - i.e., we know we created it, 207 | * and can realloc() it to grow it, and should free() it to 208 | * delete it. 209 | */ 210 | int yy_is_our_buffer; 211 | 212 | /* Whether this is an "interactive" input source; if so, and 213 | * if we're using stdio for input, then we want to use getc() 214 | * instead of fread(), to make sure we stop fetching input after 215 | * each newline. 216 | */ 217 | int yy_is_interactive; 218 | 219 | /* Whether we're considered to be at the beginning of a line. 220 | * If so, '^' rules will be active on the next match, otherwise 221 | * not. 222 | */ 223 | int yy_at_bol; 224 | 225 | int yy_bs_lineno; /**< The line count. */ 226 | int yy_bs_column; /**< The column count. */ 227 | 228 | /* Whether to try to fill the input buffer when we reach the 229 | * end of it. 230 | */ 231 | int yy_fill_buffer; 232 | 233 | int yy_buffer_status; 234 | 235 | #define YY_BUFFER_NEW 0 236 | #define YY_BUFFER_NORMAL 1 237 | /* When an EOF's been seen but there's still some text to process 238 | * then we mark the buffer as YY_EOF_PENDING, to indicate that we 239 | * shouldn't try reading from the input source any more. We might 240 | * still have a bunch of tokens to match, though, because of 241 | * possible backing-up. 242 | * 243 | * When we actually see the EOF, we change the status to "new" 244 | * (via yyrestart()), so that the user can continue scanning by 245 | * just pointing yyin at a new input file. 246 | */ 247 | #define YY_BUFFER_EOF_PENDING 2 248 | 249 | }; 250 | #endif /* !YY_STRUCT_YY_BUFFER_STATE */ 251 | 252 | /* Stack of input buffers. */ 253 | static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ 254 | static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ 255 | static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ 256 | 257 | /* We provide macros for accessing buffer states in case in the 258 | * future we want to put the buffer states in a more general 259 | * "scanner state". 260 | * 261 | * Returns the top of the stack, or NULL. 262 | */ 263 | #define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ 264 | ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ 265 | : NULL) 266 | 267 | /* Same as previous macro, but useful when we know that the buffer stack is not 268 | * NULL or when we need an lvalue. For internal use only. 269 | */ 270 | #define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] 271 | 272 | /* yy_hold_char holds the character lost when yytext is formed. */ 273 | static char yy_hold_char; 274 | static yy_size_t yy_n_chars; /* number of characters read into yy_ch_buf */ 275 | yy_size_t yyleng; 276 | 277 | /* Points to current character in buffer. */ 278 | static char *yy_c_buf_p = (char *) 0; 279 | static int yy_init = 0; /* whether we need to initialize */ 280 | static int yy_start = 0; /* start state number */ 281 | 282 | /* Flag which is used to allow yywrap()'s to do buffer switches 283 | * instead of setting up a fresh yyin. A bit of a hack ... 284 | */ 285 | static int yy_did_buffer_switch_on_eof; 286 | 287 | void yyrestart (FILE *input_file ); 288 | void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ); 289 | YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ); 290 | void yy_delete_buffer (YY_BUFFER_STATE b ); 291 | void yy_flush_buffer (YY_BUFFER_STATE b ); 292 | void yypush_buffer_state (YY_BUFFER_STATE new_buffer ); 293 | void yypop_buffer_state (void ); 294 | 295 | static void yyensure_buffer_stack (void ); 296 | static void yy_load_buffer_state (void ); 297 | static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ); 298 | 299 | #define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER ) 300 | 301 | YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ); 302 | YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ); 303 | YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,yy_size_t len ); 304 | 305 | void *yyalloc (yy_size_t ); 306 | void *yyrealloc (void *,yy_size_t ); 307 | void yyfree (void * ); 308 | 309 | #define yy_new_buffer yy_create_buffer 310 | 311 | #define yy_set_interactive(is_interactive) \ 312 | { \ 313 | if ( ! YY_CURRENT_BUFFER ){ \ 314 | yyensure_buffer_stack (); \ 315 | YY_CURRENT_BUFFER_LVALUE = \ 316 | yy_create_buffer(yyin,YY_BUF_SIZE ); \ 317 | } \ 318 | YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ 319 | } 320 | 321 | #define yy_set_bol(at_bol) \ 322 | { \ 323 | if ( ! YY_CURRENT_BUFFER ){\ 324 | yyensure_buffer_stack (); \ 325 | YY_CURRENT_BUFFER_LVALUE = \ 326 | yy_create_buffer(yyin,YY_BUF_SIZE ); \ 327 | } \ 328 | YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ 329 | } 330 | 331 | #define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) 332 | 333 | /* Begin user sect3 */ 334 | 335 | typedef unsigned char YY_CHAR; 336 | 337 | FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; 338 | 339 | typedef int yy_state_type; 340 | 341 | extern int yylineno; 342 | 343 | int yylineno = 1; 344 | 345 | extern char *yytext; 346 | #define yytext_ptr yytext 347 | 348 | static yy_state_type yy_get_previous_state (void ); 349 | static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); 350 | static int yy_get_next_buffer (void ); 351 | static void yy_fatal_error (yyconst char msg[] ); 352 | 353 | /* Done after the current pattern has been matched and before the 354 | * corresponding action - sets up yytext. 355 | */ 356 | #define YY_DO_BEFORE_ACTION \ 357 | (yytext_ptr) = yy_bp; \ 358 | yyleng = (size_t) (yy_cp - yy_bp); \ 359 | (yy_hold_char) = *yy_cp; \ 360 | *yy_cp = '\0'; \ 361 | (yy_c_buf_p) = yy_cp; 362 | 363 | #define YY_NUM_RULES 78 364 | #define YY_END_OF_BUFFER 79 365 | /* This struct is not used in this scanner, 366 | but its presence is necessary. */ 367 | struct yy_trans_info 368 | { 369 | flex_int32_t yy_verify; 370 | flex_int32_t yy_nxt; 371 | }; 372 | static yyconst flex_int16_t yy_accept[201] = 373 | { 0, 374 | 0, 0, 79, 77, 76, 59, 77, 75, 65, 58, 375 | 77, 53, 54, 63, 62, 50, 61, 57, 64, 71, 376 | 51, 47, 66, 52, 67, 70, 72, 55, 56, 68, 377 | 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 378 | 72, 72, 72, 72, 72, 48, 69, 49, 60, 46, 379 | 0, 41, 0, 37, 39, 71, 35, 40, 36, 1, 380 | 2, 38, 0, 43, 45, 44, 72, 72, 72, 72, 381 | 72, 72, 72, 10, 72, 72, 72, 72, 72, 72, 382 | 18, 72, 72, 72, 72, 72, 72, 72, 72, 72, 383 | 72, 72, 42, 73, 74, 2, 71, 72, 72, 72, 384 | 385 | 72, 72, 72, 72, 72, 72, 72, 72, 16, 72, 386 | 19, 72, 72, 72, 72, 72, 72, 72, 72, 72, 387 | 72, 72, 72, 72, 72, 72, 3, 72, 5, 6, 388 | 72, 72, 72, 72, 12, 13, 72, 72, 17, 20, 389 | 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 390 | 72, 32, 72, 72, 4, 72, 72, 72, 72, 72, 391 | 15, 72, 72, 23, 72, 72, 72, 72, 72, 72, 392 | 30, 72, 72, 34, 72, 72, 7, 11, 14, 72, 393 | 22, 24, 25, 26, 27, 28, 72, 72, 72, 72, 394 | 9, 72, 29, 72, 72, 8, 21, 31, 33, 0 395 | 396 | } ; 397 | 398 | static yyconst flex_int32_t yy_ec[256] = 399 | { 0, 400 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 401 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 402 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 403 | 1, 1, 3, 4, 5, 1, 6, 7, 8, 9, 404 | 10, 11, 12, 13, 14, 15, 16, 17, 17, 17, 405 | 17, 17, 17, 17, 17, 17, 17, 18, 19, 20, 406 | 21, 22, 23, 1, 24, 24, 24, 24, 24, 24, 407 | 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 408 | 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 409 | 25, 1, 26, 27, 24, 1, 28, 29, 30, 31, 410 | 411 | 32, 33, 34, 35, 36, 24, 37, 38, 39, 40, 412 | 41, 42, 24, 43, 44, 45, 46, 47, 48, 49, 413 | 50, 51, 52, 53, 54, 55, 1, 1, 1, 1, 414 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 415 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 416 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 417 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 418 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 419 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 420 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 421 | 422 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 423 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 424 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 425 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 426 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 427 | 1, 1, 1, 1, 1 428 | } ; 429 | 430 | static yyconst flex_int32_t yy_meta[56] = 431 | { 0, 432 | 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 433 | 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 434 | 1, 1, 1, 3, 1, 1, 1, 3, 3, 3, 435 | 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 436 | 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 437 | 3, 1, 1, 1, 1 438 | } ; 439 | 440 | static yyconst flex_int16_t yy_base[205] = 441 | { 0, 442 | 0, 0, 214, 215, 215, 192, 0, 215, 215, 205, 443 | 0, 215, 215, 190, 44, 215, 43, 215, 47, 52, 444 | 215, 215, 189, 188, 187, 215, 0, 215, 215, 215, 445 | 161, 163, 31, 30, 35, 36, 164, 43, 163, 171, 446 | 43, 152, 161, 159, 164, 215, 145, 215, 215, 215, 447 | 193, 215, 188, 215, 215, 65, 215, 215, 215, 215, 448 | 0, 215, 178, 215, 215, 215, 0, 149, 161, 148, 449 | 163, 150, 156, 142, 143, 140, 140, 143, 140, 137, 450 | 0, 136, 140, 36, 138, 51, 58, 142, 135, 51, 451 | 54, 140, 215, 171, 215, 0, 215, 133, 145, 140, 452 | 453 | 128, 125, 61, 140, 136, 128, 134, 137, 0, 123, 454 | 0, 129, 126, 115, 117, 119, 126, 112, 110, 110, 455 | 122, 112, 116, 120, 122, 111, 0, 111, 0, 0, 456 | 111, 100, 105, 106, 0, 0, 100, 97, 0, 0, 457 | 97, 97, 94, 106, 96, 100, 105, 104, 102, 92, 458 | 97, 0, 85, 97, 0, 88, 89, 94, 93, 84, 459 | 0, 78, 82, 0, 90, 87, 89, 73, 82, 84, 460 | 0, 75, 78, 0, 67, 67, 0, 0, 0, 78, 461 | 0, 0, 0, 0, 0, 0, 74, 72, 62, 67, 462 | 0, 55, 0, 65, 62, 0, 0, 0, 0, 215, 463 | 464 | 102, 105, 90, 108 465 | } ; 466 | 467 | static yyconst flex_int16_t yy_def[205] = 468 | { 0, 469 | 200, 1, 200, 200, 200, 200, 201, 200, 200, 200, 470 | 202, 200, 200, 200, 200, 200, 200, 200, 200, 200, 471 | 200, 200, 200, 200, 200, 200, 203, 200, 200, 200, 472 | 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 473 | 203, 203, 203, 203, 203, 200, 200, 200, 200, 200, 474 | 201, 200, 200, 200, 200, 200, 200, 200, 200, 200, 475 | 204, 200, 200, 200, 200, 200, 203, 203, 203, 203, 476 | 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 477 | 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 478 | 203, 203, 200, 201, 200, 204, 200, 203, 203, 203, 479 | 480 | 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 481 | 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 482 | 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 483 | 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 484 | 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 485 | 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 486 | 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 487 | 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 488 | 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 489 | 203, 203, 203, 203, 203, 203, 203, 203, 203, 0, 490 | 491 | 200, 200, 200, 200 492 | } ; 493 | 494 | static yyconst flex_int16_t yy_nxt[271] = 495 | { 0, 496 | 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 497 | 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 498 | 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 499 | 34, 35, 36, 37, 27, 38, 27, 39, 27, 27, 500 | 27, 27, 40, 41, 42, 43, 44, 45, 27, 27, 501 | 27, 46, 47, 48, 49, 55, 58, 60, 70, 56, 502 | 56, 73, 61, 59, 57, 71, 63, 62, 56, 113, 503 | 74, 72, 75, 78, 76, 81, 79, 85, 86, 63, 504 | 114, 56, 82, 77, 116, 118, 122, 87, 132, 124, 505 | 88, 125, 67, 199, 123, 198, 133, 197, 196, 195, 506 | 507 | 119, 117, 51, 194, 51, 53, 193, 53, 96, 192, 508 | 96, 191, 190, 189, 188, 187, 186, 185, 184, 183, 509 | 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 510 | 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 511 | 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 512 | 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 513 | 142, 141, 140, 139, 138, 137, 136, 135, 134, 131, 514 | 130, 129, 128, 127, 94, 126, 121, 120, 115, 112, 515 | 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 516 | 101, 100, 99, 98, 97, 95, 94, 93, 92, 91, 517 | 518 | 90, 89, 84, 83, 80, 69, 68, 66, 65, 64, 519 | 54, 52, 50, 200, 3, 200, 200, 200, 200, 200, 520 | 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 521 | 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 522 | 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 523 | 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 524 | 200, 200, 200, 200, 200, 200, 200, 200, 200, 200 525 | } ; 526 | 527 | static yyconst flex_int16_t yy_chk[271] = 528 | { 0, 529 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 530 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 531 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 532 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 533 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 534 | 1, 1, 1, 1, 1, 15, 17, 19, 33, 17, 535 | 15, 34, 19, 17, 15, 33, 20, 19, 20, 84, 536 | 34, 33, 35, 36, 35, 38, 36, 41, 41, 56, 537 | 84, 56, 38, 35, 86, 87, 90, 41, 103, 91, 538 | 41, 91, 203, 195, 90, 194, 103, 192, 190, 189, 539 | 540 | 87, 86, 201, 188, 201, 202, 187, 202, 204, 180, 541 | 204, 176, 175, 173, 172, 170, 169, 168, 167, 166, 542 | 165, 163, 162, 160, 159, 158, 157, 156, 154, 153, 543 | 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 544 | 141, 138, 137, 134, 133, 132, 131, 128, 126, 125, 545 | 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 546 | 114, 113, 112, 110, 108, 107, 106, 105, 104, 102, 547 | 101, 100, 99, 98, 94, 92, 89, 88, 85, 83, 548 | 82, 80, 79, 78, 77, 76, 75, 74, 73, 72, 549 | 71, 70, 69, 68, 63, 53, 51, 47, 45, 44, 550 | 551 | 43, 42, 40, 39, 37, 32, 31, 25, 24, 23, 552 | 14, 10, 6, 3, 200, 200, 200, 200, 200, 200, 553 | 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 554 | 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 555 | 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 556 | 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 557 | 200, 200, 200, 200, 200, 200, 200, 200, 200, 200 558 | } ; 559 | 560 | static yy_state_type yy_last_accepting_state; 561 | static char *yy_last_accepting_cpos; 562 | 563 | extern int yy_flex_debug; 564 | int yy_flex_debug = 0; 565 | 566 | /* The intent behind this definition is that it'll catch 567 | * any uses of REJECT which flex missed. 568 | */ 569 | #define REJECT reject_used_but_not_detected 570 | #define yymore() yymore_used_but_not_detected 571 | #define YY_MORE_ADJ 0 572 | #define YY_RESTORE_YY_MORE_OFFSET 573 | char *yytext; 574 | #line 1 "flex_c.l" 575 | #line 2 "flex_c.l" 576 | #include 577 | #include 578 | #include 579 | #include "bison_c.tab.h" 580 | #include "ast_node.h" 581 | 582 | FILE *yyin; 583 | int linesno = 1; 584 | 585 | void comment(); 586 | void ignoreHeadfile(); 587 | #line 588 "lex.yy.c" 588 | 589 | #define INITIAL 0 590 | 591 | #ifndef YY_NO_UNISTD_H 592 | /* Special case for "unistd.h", since it is non-ANSI. We include it way 593 | * down here because we want the user's section 1 to have been scanned first. 594 | * The user has a chance to override it with an option. 595 | */ 596 | #include 597 | #endif 598 | 599 | #ifndef YY_EXTRA_TYPE 600 | #define YY_EXTRA_TYPE void * 601 | #endif 602 | 603 | static int yy_init_globals (void ); 604 | 605 | /* Accessor methods to globals. 606 | These are made visible to non-reentrant scanners for convenience. */ 607 | 608 | int yylex_destroy (void ); 609 | 610 | int yyget_debug (void ); 611 | 612 | void yyset_debug (int debug_flag ); 613 | 614 | YY_EXTRA_TYPE yyget_extra (void ); 615 | 616 | void yyset_extra (YY_EXTRA_TYPE user_defined ); 617 | 618 | FILE *yyget_in (void ); 619 | 620 | void yyset_in (FILE * in_str ); 621 | 622 | FILE *yyget_out (void ); 623 | 624 | void yyset_out (FILE * out_str ); 625 | 626 | yy_size_t yyget_leng (void ); 627 | 628 | char *yyget_text (void ); 629 | 630 | int yyget_lineno (void ); 631 | 632 | void yyset_lineno (int line_number ); 633 | 634 | /* Macros after this point can all be overridden by user definitions in 635 | * section 1. 636 | */ 637 | 638 | #ifndef YY_SKIP_YYWRAP 639 | #ifdef __cplusplus 640 | extern "C" int yywrap (void ); 641 | #else 642 | extern int yywrap (void ); 643 | #endif 644 | #endif 645 | 646 | static void yyunput (int c,char *buf_ptr ); 647 | 648 | #ifndef yytext_ptr 649 | static void yy_flex_strncpy (char *,yyconst char *,int ); 650 | #endif 651 | 652 | #ifdef YY_NEED_STRLEN 653 | static int yy_flex_strlen (yyconst char * ); 654 | #endif 655 | 656 | #ifndef YY_NO_INPUT 657 | 658 | #ifdef __cplusplus 659 | static int yyinput (void ); 660 | #else 661 | static int input (void ); 662 | #endif 663 | 664 | #endif 665 | 666 | /* Amount of stuff to slurp up with each read. */ 667 | #ifndef YY_READ_BUF_SIZE 668 | #define YY_READ_BUF_SIZE 8192 669 | #endif 670 | 671 | /* Copy whatever the last rule matched to the standard output. */ 672 | #ifndef ECHO 673 | /* This used to be an fputs(), but since the string might contain NUL's, 674 | * we now use fwrite(). 675 | */ 676 | #define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0) 677 | #endif 678 | 679 | /* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, 680 | * is returned in "result". 681 | */ 682 | #ifndef YY_INPUT 683 | #define YY_INPUT(buf,result,max_size) \ 684 | if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ 685 | { \ 686 | int c = '*'; \ 687 | size_t n; \ 688 | for ( n = 0; n < max_size && \ 689 | (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ 690 | buf[n] = (char) c; \ 691 | if ( c == '\n' ) \ 692 | buf[n++] = (char) c; \ 693 | if ( c == EOF && ferror( yyin ) ) \ 694 | YY_FATAL_ERROR( "input in flex scanner failed" ); \ 695 | result = n; \ 696 | } \ 697 | else \ 698 | { \ 699 | errno=0; \ 700 | while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ 701 | { \ 702 | if( errno != EINTR) \ 703 | { \ 704 | YY_FATAL_ERROR( "input in flex scanner failed" ); \ 705 | break; \ 706 | } \ 707 | errno=0; \ 708 | clearerr(yyin); \ 709 | } \ 710 | }\ 711 | \ 712 | 713 | #endif 714 | 715 | /* No semi-colon after return; correct usage is to write "yyterminate();" - 716 | * we don't want an extra ';' after the "return" because that will cause 717 | * some compilers to complain about unreachable statements. 718 | */ 719 | #ifndef yyterminate 720 | #define yyterminate() return YY_NULL 721 | #endif 722 | 723 | /* Number of entries by which start-condition stack grows. */ 724 | #ifndef YY_START_STACK_INCR 725 | #define YY_START_STACK_INCR 25 726 | #endif 727 | 728 | /* Report a fatal error. */ 729 | #ifndef YY_FATAL_ERROR 730 | #define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) 731 | #endif 732 | 733 | /* end tables serialization structures and prototypes */ 734 | 735 | /* Default declaration of generated scanner - a define so the user can 736 | * easily add parameters. 737 | */ 738 | #ifndef YY_DECL 739 | #define YY_DECL_IS_OURS 1 740 | 741 | extern int yylex (void); 742 | 743 | #define YY_DECL int yylex (void) 744 | #endif /* !YY_DECL */ 745 | 746 | /* Code executed at the beginning of each rule, after yytext and yyleng 747 | * have been set up. 748 | */ 749 | #ifndef YY_USER_ACTION 750 | #define YY_USER_ACTION 751 | #endif 752 | 753 | /* Code executed at the end of each rule. */ 754 | #ifndef YY_BREAK 755 | #define YY_BREAK break; 756 | #endif 757 | 758 | #define YY_RULE_SETUP \ 759 | YY_USER_ACTION 760 | 761 | /** The main scanner function which does all the work. 762 | */ 763 | YY_DECL 764 | { 765 | register yy_state_type yy_current_state; 766 | register char *yy_cp, *yy_bp; 767 | register int yy_act; 768 | 769 | #line 20 "flex_c.l" 770 | 771 | 772 | #line 773 "lex.yy.c" 773 | 774 | if ( !(yy_init) ) 775 | { 776 | (yy_init) = 1; 777 | 778 | #ifdef YY_USER_INIT 779 | YY_USER_INIT; 780 | #endif 781 | 782 | if ( ! (yy_start) ) 783 | (yy_start) = 1; /* first start state */ 784 | 785 | if ( ! yyin ) 786 | yyin = stdin; 787 | 788 | if ( ! yyout ) 789 | yyout = stdout; 790 | 791 | if ( ! YY_CURRENT_BUFFER ) { 792 | yyensure_buffer_stack (); 793 | YY_CURRENT_BUFFER_LVALUE = 794 | yy_create_buffer(yyin,YY_BUF_SIZE ); 795 | } 796 | 797 | yy_load_buffer_state( ); 798 | } 799 | 800 | while ( 1 ) /* loops until end-of-file is reached */ 801 | { 802 | yy_cp = (yy_c_buf_p); 803 | 804 | /* Support of yytext. */ 805 | *yy_cp = (yy_hold_char); 806 | 807 | /* yy_bp points to the position in yy_ch_buf of the start of 808 | * the current run. 809 | */ 810 | yy_bp = yy_cp; 811 | 812 | yy_current_state = (yy_start); 813 | yy_match: 814 | do 815 | { 816 | register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; 817 | if ( yy_accept[yy_current_state] ) 818 | { 819 | (yy_last_accepting_state) = yy_current_state; 820 | (yy_last_accepting_cpos) = yy_cp; 821 | } 822 | while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) 823 | { 824 | yy_current_state = (int) yy_def[yy_current_state]; 825 | if ( yy_current_state >= 201 ) 826 | yy_c = yy_meta[(unsigned int) yy_c]; 827 | } 828 | yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; 829 | ++yy_cp; 830 | } 831 | while ( yy_base[yy_current_state] != 215 ); 832 | 833 | yy_find_action: 834 | yy_act = yy_accept[yy_current_state]; 835 | if ( yy_act == 0 ) 836 | { /* have to back up */ 837 | yy_cp = (yy_last_accepting_cpos); 838 | yy_current_state = (yy_last_accepting_state); 839 | yy_act = yy_accept[yy_current_state]; 840 | } 841 | 842 | YY_DO_BEFORE_ACTION; 843 | 844 | do_action: /* This label is used only to access EOF actions. */ 845 | 846 | switch ( yy_act ) 847 | { /* beginning of action switch */ 848 | case 0: /* must back up */ 849 | /* undo the effects of YY_DO_BEFORE_ACTION */ 850 | *yy_cp = (yy_hold_char); 851 | yy_cp = (yy_last_accepting_cpos); 852 | yy_current_state = (yy_last_accepting_state); 853 | goto yy_find_action; 854 | 855 | case 1: 856 | YY_RULE_SETUP 857 | #line 22 "flex_c.l" 858 | { comment(); } 859 | YY_BREAK 860 | case 2: 861 | YY_RULE_SETUP 862 | #line 23 "flex_c.l" 863 | { /*ignore comment*/ } 864 | YY_BREAK 865 | case 3: 866 | YY_RULE_SETUP 867 | #line 25 "flex_c.l" 868 | { return AUTO; } 869 | YY_BREAK 870 | case 4: 871 | YY_RULE_SETUP 872 | #line 26 "flex_c.l" 873 | { return BREAK; } 874 | YY_BREAK 875 | case 5: 876 | YY_RULE_SETUP 877 | #line 27 "flex_c.l" 878 | { return CASE; } 879 | YY_BREAK 880 | case 6: 881 | YY_RULE_SETUP 882 | #line 28 "flex_c.l" 883 | { return CHAR; } 884 | YY_BREAK 885 | case 7: 886 | YY_RULE_SETUP 887 | #line 29 "flex_c.l" 888 | { return DEFINE; } 889 | YY_BREAK 890 | case 8: 891 | YY_RULE_SETUP 892 | #line 30 "flex_c.l" 893 | { return CONTINUE; } 894 | YY_BREAK 895 | case 9: 896 | YY_RULE_SETUP 897 | #line 31 "flex_c.l" 898 | { return DEFAULT; } 899 | YY_BREAK 900 | case 10: 901 | YY_RULE_SETUP 902 | #line 32 "flex_c.l" 903 | { return DO; } 904 | YY_BREAK 905 | case 11: 906 | YY_RULE_SETUP 907 | #line 33 "flex_c.l" 908 | { return DOUBLE; } 909 | YY_BREAK 910 | case 12: 911 | YY_RULE_SETUP 912 | #line 34 "flex_c.l" 913 | { return ELSE; } 914 | YY_BREAK 915 | case 13: 916 | YY_RULE_SETUP 917 | #line 35 "flex_c.l" 918 | { return ENUM; } 919 | YY_BREAK 920 | case 14: 921 | YY_RULE_SETUP 922 | #line 36 "flex_c.l" 923 | { return EXTERN; } 924 | YY_BREAK 925 | case 15: 926 | YY_RULE_SETUP 927 | #line 37 "flex_c.l" 928 | { return FLOAT; } 929 | YY_BREAK 930 | case 16: 931 | YY_RULE_SETUP 932 | #line 38 "flex_c.l" 933 | { return FOR; } 934 | YY_BREAK 935 | case 17: 936 | YY_RULE_SETUP 937 | #line 39 "flex_c.l" 938 | { return GOTO; } 939 | YY_BREAK 940 | case 18: 941 | YY_RULE_SETUP 942 | #line 40 "flex_c.l" 943 | { return IF; } 944 | YY_BREAK 945 | case 19: 946 | YY_RULE_SETUP 947 | #line 41 "flex_c.l" 948 | { return INT; } 949 | YY_BREAK 950 | case 20: 951 | YY_RULE_SETUP 952 | #line 42 "flex_c.l" 953 | { return LONG; } 954 | YY_BREAK 955 | case 21: 956 | YY_RULE_SETUP 957 | #line 43 "flex_c.l" 958 | { return REGISTER; } 959 | YY_BREAK 960 | case 22: 961 | YY_RULE_SETUP 962 | #line 44 "flex_c.l" 963 | { return RETURN; } 964 | YY_BREAK 965 | case 23: 966 | YY_RULE_SETUP 967 | #line 45 "flex_c.l" 968 | { return SHORT; } 969 | YY_BREAK 970 | case 24: 971 | YY_RULE_SETUP 972 | #line 46 "flex_c.l" 973 | { return SIGNED; } 974 | YY_BREAK 975 | case 25: 976 | YY_RULE_SETUP 977 | #line 47 "flex_c.l" 978 | { return SIZEOF; } 979 | YY_BREAK 980 | case 26: 981 | YY_RULE_SETUP 982 | #line 48 "flex_c.l" 983 | { return STATIC; } 984 | YY_BREAK 985 | case 27: 986 | YY_RULE_SETUP 987 | #line 49 "flex_c.l" 988 | { return STRUCT; } 989 | YY_BREAK 990 | case 28: 991 | YY_RULE_SETUP 992 | #line 50 "flex_c.l" 993 | { return SWITCH; } 994 | YY_BREAK 995 | case 29: 996 | YY_RULE_SETUP 997 | #line 51 "flex_c.l" 998 | { return TYPEDEF; } 999 | YY_BREAK 1000 | case 30: 1001 | YY_RULE_SETUP 1002 | #line 52 "flex_c.l" 1003 | { return UNION; } 1004 | YY_BREAK 1005 | case 31: 1006 | YY_RULE_SETUP 1007 | #line 53 "flex_c.l" 1008 | { return UNSIGNED; } 1009 | YY_BREAK 1010 | case 32: 1011 | YY_RULE_SETUP 1012 | #line 54 "flex_c.l" 1013 | { return VOID; } 1014 | YY_BREAK 1015 | case 33: 1016 | YY_RULE_SETUP 1017 | #line 55 "flex_c.l" 1018 | { return VOLATILE; } 1019 | YY_BREAK 1020 | case 34: 1021 | YY_RULE_SETUP 1022 | #line 56 "flex_c.l" 1023 | { return WHILE; } 1024 | YY_BREAK 1025 | case 35: 1026 | YY_RULE_SETUP 1027 | #line 58 "flex_c.l" 1028 | { return ADD_ASSIGN; } 1029 | YY_BREAK 1030 | case 36: 1031 | YY_RULE_SETUP 1032 | #line 59 "flex_c.l" 1033 | { return SUB_ASSIGN; } 1034 | YY_BREAK 1035 | case 37: 1036 | YY_RULE_SETUP 1037 | #line 60 "flex_c.l" 1038 | { return MUL_ASSIGN; } 1039 | YY_BREAK 1040 | case 38: 1041 | YY_RULE_SETUP 1042 | #line 61 "flex_c.l" 1043 | { return DIV_ASSIGN; } 1044 | YY_BREAK 1045 | case 39: 1046 | YY_RULE_SETUP 1047 | #line 62 "flex_c.l" 1048 | { return INC_OP; } 1049 | YY_BREAK 1050 | case 40: 1051 | YY_RULE_SETUP 1052 | #line 63 "flex_c.l" 1053 | { return DEC_OP; } 1054 | YY_BREAK 1055 | case 41: 1056 | YY_RULE_SETUP 1057 | #line 64 "flex_c.l" 1058 | { return AND_OP; } 1059 | YY_BREAK 1060 | case 42: 1061 | YY_RULE_SETUP 1062 | #line 65 "flex_c.l" 1063 | { return OR_OP; } 1064 | YY_BREAK 1065 | case 43: 1066 | YY_RULE_SETUP 1067 | #line 66 "flex_c.l" 1068 | { return LE_OP; } 1069 | YY_BREAK 1070 | case 44: 1071 | YY_RULE_SETUP 1072 | #line 67 "flex_c.l" 1073 | { return GE_OP; } 1074 | YY_BREAK 1075 | case 45: 1076 | YY_RULE_SETUP 1077 | #line 68 "flex_c.l" 1078 | { return EQ_OP; } 1079 | YY_BREAK 1080 | case 46: 1081 | YY_RULE_SETUP 1082 | #line 69 "flex_c.l" 1083 | { return NE_OP; } 1084 | YY_BREAK 1085 | case 47: 1086 | YY_RULE_SETUP 1087 | #line 70 "flex_c.l" 1088 | { return ';'; } 1089 | YY_BREAK 1090 | case 48: 1091 | YY_RULE_SETUP 1092 | #line 71 "flex_c.l" 1093 | { return '{'; } 1094 | YY_BREAK 1095 | case 49: 1096 | YY_RULE_SETUP 1097 | #line 72 "flex_c.l" 1098 | { return '}'; } 1099 | YY_BREAK 1100 | case 50: 1101 | YY_RULE_SETUP 1102 | #line 73 "flex_c.l" 1103 | { return ','; } 1104 | YY_BREAK 1105 | case 51: 1106 | YY_RULE_SETUP 1107 | #line 74 "flex_c.l" 1108 | { return ':'; } 1109 | YY_BREAK 1110 | case 52: 1111 | YY_RULE_SETUP 1112 | #line 75 "flex_c.l" 1113 | { return '='; } 1114 | YY_BREAK 1115 | case 53: 1116 | YY_RULE_SETUP 1117 | #line 76 "flex_c.l" 1118 | { return '('; } 1119 | YY_BREAK 1120 | case 54: 1121 | YY_RULE_SETUP 1122 | #line 77 "flex_c.l" 1123 | { return ')'; } 1124 | YY_BREAK 1125 | case 55: 1126 | YY_RULE_SETUP 1127 | #line 78 "flex_c.l" 1128 | { return '['; } 1129 | YY_BREAK 1130 | case 56: 1131 | YY_RULE_SETUP 1132 | #line 79 "flex_c.l" 1133 | { return ']'; } 1134 | YY_BREAK 1135 | case 57: 1136 | YY_RULE_SETUP 1137 | #line 80 "flex_c.l" 1138 | { return '.'; } 1139 | YY_BREAK 1140 | case 58: 1141 | YY_RULE_SETUP 1142 | #line 81 "flex_c.l" 1143 | { return '&'; } 1144 | YY_BREAK 1145 | case 59: 1146 | YY_RULE_SETUP 1147 | #line 82 "flex_c.l" 1148 | { return '!'; } 1149 | YY_BREAK 1150 | case 60: 1151 | YY_RULE_SETUP 1152 | #line 83 "flex_c.l" 1153 | { return '~'; } 1154 | YY_BREAK 1155 | case 61: 1156 | YY_RULE_SETUP 1157 | #line 84 "flex_c.l" 1158 | { return '-'; } 1159 | YY_BREAK 1160 | case 62: 1161 | YY_RULE_SETUP 1162 | #line 85 "flex_c.l" 1163 | { return '+'; } 1164 | YY_BREAK 1165 | case 63: 1166 | YY_RULE_SETUP 1167 | #line 86 "flex_c.l" 1168 | { return '*'; } 1169 | YY_BREAK 1170 | case 64: 1171 | YY_RULE_SETUP 1172 | #line 87 "flex_c.l" 1173 | { return '/'; } 1174 | YY_BREAK 1175 | case 65: 1176 | YY_RULE_SETUP 1177 | #line 88 "flex_c.l" 1178 | { return '%'; } 1179 | YY_BREAK 1180 | case 66: 1181 | YY_RULE_SETUP 1182 | #line 89 "flex_c.l" 1183 | { return '<'; } 1184 | YY_BREAK 1185 | case 67: 1186 | YY_RULE_SETUP 1187 | #line 90 "flex_c.l" 1188 | { return '>'; } 1189 | YY_BREAK 1190 | case 68: 1191 | YY_RULE_SETUP 1192 | #line 91 "flex_c.l" 1193 | { return '^'; } 1194 | YY_BREAK 1195 | case 69: 1196 | YY_RULE_SETUP 1197 | #line 92 "flex_c.l" 1198 | { return '|'; } 1199 | YY_BREAK 1200 | case 70: 1201 | YY_RULE_SETUP 1202 | #line 93 "flex_c.l" 1203 | { return '?'; } 1204 | YY_BREAK 1205 | case 71: 1206 | YY_RULE_SETUP 1207 | #line 95 "flex_c.l" 1208 | { yylval.d = atof(yytext); return NUMBER; } 1209 | YY_BREAK 1210 | case 72: 1211 | YY_RULE_SETUP 1212 | #line 96 "flex_c.l" 1213 | { strcpy(yylval.s, yytext); return IDENTIFIER; } 1214 | YY_BREAK 1215 | case 73: 1216 | YY_RULE_SETUP 1217 | #line 97 "flex_c.l" 1218 | { strcpy(yylval.s, yytext); return STRING_CONSTANT; } 1219 | YY_BREAK 1220 | case 74: 1221 | YY_RULE_SETUP 1222 | #line 98 "flex_c.l" 1223 | { yylval.s[0] = *yytext; yylval.s[1] = '\0'; return CHARACTER; } 1224 | YY_BREAK 1225 | case 75: 1226 | YY_RULE_SETUP 1227 | #line 99 "flex_c.l" 1228 | { ignoreHeadfile(); linesno++; } 1229 | YY_BREAK 1230 | case 76: 1231 | /* rule 76 can match eol */ 1232 | YY_RULE_SETUP 1233 | #line 100 "flex_c.l" 1234 | { linesno++; } 1235 | YY_BREAK 1236 | case 77: 1237 | YY_RULE_SETUP 1238 | #line 101 "flex_c.l" 1239 | { /*other characters*/ } 1240 | YY_BREAK 1241 | case 78: 1242 | YY_RULE_SETUP 1243 | #line 103 "flex_c.l" 1244 | ECHO; 1245 | YY_BREAK 1246 | #line 1247 "lex.yy.c" 1247 | case YY_STATE_EOF(INITIAL): 1248 | yyterminate(); 1249 | 1250 | case YY_END_OF_BUFFER: 1251 | { 1252 | /* Amount of text matched not including the EOB char. */ 1253 | int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; 1254 | 1255 | /* Undo the effects of YY_DO_BEFORE_ACTION. */ 1256 | *yy_cp = (yy_hold_char); 1257 | YY_RESTORE_YY_MORE_OFFSET 1258 | 1259 | if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) 1260 | { 1261 | /* We're scanning a new file or input source. It's 1262 | * possible that this happened because the user 1263 | * just pointed yyin at a new source and called 1264 | * yylex(). If so, then we have to assure 1265 | * consistency between YY_CURRENT_BUFFER and our 1266 | * globals. Here is the right place to do so, because 1267 | * this is the first action (other than possibly a 1268 | * back-up) that will match for the new input source. 1269 | */ 1270 | (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; 1271 | YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; 1272 | YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; 1273 | } 1274 | 1275 | /* Note that here we test for yy_c_buf_p "<=" to the position 1276 | * of the first EOB in the buffer, since yy_c_buf_p will 1277 | * already have been incremented past the NUL character 1278 | * (since all states make transitions on EOB to the 1279 | * end-of-buffer state). Contrast this with the test 1280 | * in input(). 1281 | */ 1282 | if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) 1283 | { /* This was really a NUL. */ 1284 | yy_state_type yy_next_state; 1285 | 1286 | (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; 1287 | 1288 | yy_current_state = yy_get_previous_state( ); 1289 | 1290 | /* Okay, we're now positioned to make the NUL 1291 | * transition. We couldn't have 1292 | * yy_get_previous_state() go ahead and do it 1293 | * for us because it doesn't know how to deal 1294 | * with the possibility of jamming (and we don't 1295 | * want to build jamming into it because then it 1296 | * will run more slowly). 1297 | */ 1298 | 1299 | yy_next_state = yy_try_NUL_trans( yy_current_state ); 1300 | 1301 | yy_bp = (yytext_ptr) + YY_MORE_ADJ; 1302 | 1303 | if ( yy_next_state ) 1304 | { 1305 | /* Consume the NUL. */ 1306 | yy_cp = ++(yy_c_buf_p); 1307 | yy_current_state = yy_next_state; 1308 | goto yy_match; 1309 | } 1310 | 1311 | else 1312 | { 1313 | yy_cp = (yy_c_buf_p); 1314 | goto yy_find_action; 1315 | } 1316 | } 1317 | 1318 | else switch ( yy_get_next_buffer( ) ) 1319 | { 1320 | case EOB_ACT_END_OF_FILE: 1321 | { 1322 | (yy_did_buffer_switch_on_eof) = 0; 1323 | 1324 | if ( yywrap( ) ) 1325 | { 1326 | /* Note: because we've taken care in 1327 | * yy_get_next_buffer() to have set up 1328 | * yytext, we can now set up 1329 | * yy_c_buf_p so that if some total 1330 | * hoser (like flex itself) wants to 1331 | * call the scanner after we return the 1332 | * YY_NULL, it'll still work - another 1333 | * YY_NULL will get returned. 1334 | */ 1335 | (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; 1336 | 1337 | yy_act = YY_STATE_EOF(YY_START); 1338 | goto do_action; 1339 | } 1340 | 1341 | else 1342 | { 1343 | if ( ! (yy_did_buffer_switch_on_eof) ) 1344 | YY_NEW_FILE; 1345 | } 1346 | break; 1347 | } 1348 | 1349 | case EOB_ACT_CONTINUE_SCAN: 1350 | (yy_c_buf_p) = 1351 | (yytext_ptr) + yy_amount_of_matched_text; 1352 | 1353 | yy_current_state = yy_get_previous_state( ); 1354 | 1355 | yy_cp = (yy_c_buf_p); 1356 | yy_bp = (yytext_ptr) + YY_MORE_ADJ; 1357 | goto yy_match; 1358 | 1359 | case EOB_ACT_LAST_MATCH: 1360 | (yy_c_buf_p) = 1361 | &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; 1362 | 1363 | yy_current_state = yy_get_previous_state( ); 1364 | 1365 | yy_cp = (yy_c_buf_p); 1366 | yy_bp = (yytext_ptr) + YY_MORE_ADJ; 1367 | goto yy_find_action; 1368 | } 1369 | break; 1370 | } 1371 | 1372 | default: 1373 | YY_FATAL_ERROR( 1374 | "fatal flex scanner internal error--no action found" ); 1375 | } /* end of action switch */ 1376 | } /* end of scanning one token */ 1377 | } /* end of yylex */ 1378 | 1379 | /* yy_get_next_buffer - try to read in a new buffer 1380 | * 1381 | * Returns a code representing an action: 1382 | * EOB_ACT_LAST_MATCH - 1383 | * EOB_ACT_CONTINUE_SCAN - continue scanning from current position 1384 | * EOB_ACT_END_OF_FILE - end of file 1385 | */ 1386 | static int yy_get_next_buffer (void) 1387 | { 1388 | register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; 1389 | register char *source = (yytext_ptr); 1390 | register int number_to_move, i; 1391 | int ret_val; 1392 | 1393 | if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) 1394 | YY_FATAL_ERROR( 1395 | "fatal flex scanner internal error--end of buffer missed" ); 1396 | 1397 | if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) 1398 | { /* Don't try to fill the buffer, so this is an EOF. */ 1399 | if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) 1400 | { 1401 | /* We matched a single character, the EOB, so 1402 | * treat this as a final EOF. 1403 | */ 1404 | return EOB_ACT_END_OF_FILE; 1405 | } 1406 | 1407 | else 1408 | { 1409 | /* We matched some text prior to the EOB, first 1410 | * process it. 1411 | */ 1412 | return EOB_ACT_LAST_MATCH; 1413 | } 1414 | } 1415 | 1416 | /* Try to read more data. */ 1417 | 1418 | /* First move last chars to start of buffer. */ 1419 | number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; 1420 | 1421 | for ( i = 0; i < number_to_move; ++i ) 1422 | *(dest++) = *(source++); 1423 | 1424 | if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) 1425 | /* don't do the read, it's not guaranteed to return an EOF, 1426 | * just force an EOF 1427 | */ 1428 | YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; 1429 | 1430 | else 1431 | { 1432 | yy_size_t num_to_read = 1433 | YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; 1434 | 1435 | while ( num_to_read <= 0 ) 1436 | { /* Not enough room in the buffer - grow it. */ 1437 | 1438 | /* just a shorter name for the current buffer */ 1439 | YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE; 1440 | 1441 | int yy_c_buf_p_offset = 1442 | (int) ((yy_c_buf_p) - b->yy_ch_buf); 1443 | 1444 | if ( b->yy_is_our_buffer ) 1445 | { 1446 | yy_size_t new_size = b->yy_buf_size * 2; 1447 | 1448 | if ( new_size <= 0 ) 1449 | b->yy_buf_size += b->yy_buf_size / 8; 1450 | else 1451 | b->yy_buf_size *= 2; 1452 | 1453 | b->yy_ch_buf = (char *) 1454 | /* Include room in for 2 EOB chars. */ 1455 | yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); 1456 | } 1457 | else 1458 | /* Can't grow it, we don't own it. */ 1459 | b->yy_ch_buf = 0; 1460 | 1461 | if ( ! b->yy_ch_buf ) 1462 | YY_FATAL_ERROR( 1463 | "fatal error - scanner input buffer overflow" ); 1464 | 1465 | (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; 1466 | 1467 | num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - 1468 | number_to_move - 1; 1469 | 1470 | } 1471 | 1472 | if ( num_to_read > YY_READ_BUF_SIZE ) 1473 | num_to_read = YY_READ_BUF_SIZE; 1474 | 1475 | /* Read in more data. */ 1476 | YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), 1477 | (yy_n_chars), num_to_read ); 1478 | 1479 | YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); 1480 | } 1481 | 1482 | if ( (yy_n_chars) == 0 ) 1483 | { 1484 | if ( number_to_move == YY_MORE_ADJ ) 1485 | { 1486 | ret_val = EOB_ACT_END_OF_FILE; 1487 | yyrestart(yyin ); 1488 | } 1489 | 1490 | else 1491 | { 1492 | ret_val = EOB_ACT_LAST_MATCH; 1493 | YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = 1494 | YY_BUFFER_EOF_PENDING; 1495 | } 1496 | } 1497 | 1498 | else 1499 | ret_val = EOB_ACT_CONTINUE_SCAN; 1500 | 1501 | if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { 1502 | /* Extend the array by 50%, plus the number we really need. */ 1503 | yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); 1504 | YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); 1505 | if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) 1506 | YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); 1507 | } 1508 | 1509 | (yy_n_chars) += number_to_move; 1510 | YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; 1511 | YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; 1512 | 1513 | (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; 1514 | 1515 | return ret_val; 1516 | } 1517 | 1518 | /* yy_get_previous_state - get the state just before the EOB char was reached */ 1519 | 1520 | static yy_state_type yy_get_previous_state (void) 1521 | { 1522 | register yy_state_type yy_current_state; 1523 | register char *yy_cp; 1524 | 1525 | yy_current_state = (yy_start); 1526 | 1527 | for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) 1528 | { 1529 | register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); 1530 | if ( yy_accept[yy_current_state] ) 1531 | { 1532 | (yy_last_accepting_state) = yy_current_state; 1533 | (yy_last_accepting_cpos) = yy_cp; 1534 | } 1535 | while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) 1536 | { 1537 | yy_current_state = (int) yy_def[yy_current_state]; 1538 | if ( yy_current_state >= 201 ) 1539 | yy_c = yy_meta[(unsigned int) yy_c]; 1540 | } 1541 | yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; 1542 | } 1543 | 1544 | return yy_current_state; 1545 | } 1546 | 1547 | /* yy_try_NUL_trans - try to make a transition on the NUL character 1548 | * 1549 | * synopsis 1550 | * next_state = yy_try_NUL_trans( current_state ); 1551 | */ 1552 | static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) 1553 | { 1554 | register int yy_is_jam; 1555 | register char *yy_cp = (yy_c_buf_p); 1556 | 1557 | register YY_CHAR yy_c = 1; 1558 | if ( yy_accept[yy_current_state] ) 1559 | { 1560 | (yy_last_accepting_state) = yy_current_state; 1561 | (yy_last_accepting_cpos) = yy_cp; 1562 | } 1563 | while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) 1564 | { 1565 | yy_current_state = (int) yy_def[yy_current_state]; 1566 | if ( yy_current_state >= 201 ) 1567 | yy_c = yy_meta[(unsigned int) yy_c]; 1568 | } 1569 | yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; 1570 | yy_is_jam = (yy_current_state == 200); 1571 | 1572 | return yy_is_jam ? 0 : yy_current_state; 1573 | } 1574 | 1575 | static void yyunput (int c, register char * yy_bp ) 1576 | { 1577 | register char *yy_cp; 1578 | 1579 | yy_cp = (yy_c_buf_p); 1580 | 1581 | /* undo effects of setting up yytext */ 1582 | *yy_cp = (yy_hold_char); 1583 | 1584 | if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) 1585 | { /* need to shift things up to make room */ 1586 | /* +2 for EOB chars. */ 1587 | register yy_size_t number_to_move = (yy_n_chars) + 2; 1588 | register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ 1589 | YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; 1590 | register char *source = 1591 | &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; 1592 | 1593 | while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) 1594 | *--dest = *--source; 1595 | 1596 | yy_cp += (int) (dest - source); 1597 | yy_bp += (int) (dest - source); 1598 | YY_CURRENT_BUFFER_LVALUE->yy_n_chars = 1599 | (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; 1600 | 1601 | if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) 1602 | YY_FATAL_ERROR( "flex scanner push-back overflow" ); 1603 | } 1604 | 1605 | *--yy_cp = (char) c; 1606 | 1607 | (yytext_ptr) = yy_bp; 1608 | (yy_hold_char) = *yy_cp; 1609 | (yy_c_buf_p) = yy_cp; 1610 | } 1611 | 1612 | #ifndef YY_NO_INPUT 1613 | #ifdef __cplusplus 1614 | static int yyinput (void) 1615 | #else 1616 | static int input (void) 1617 | #endif 1618 | 1619 | { 1620 | int c; 1621 | 1622 | *(yy_c_buf_p) = (yy_hold_char); 1623 | 1624 | if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) 1625 | { 1626 | /* yy_c_buf_p now points to the character we want to return. 1627 | * If this occurs *before* the EOB characters, then it's a 1628 | * valid NUL; if not, then we've hit the end of the buffer. 1629 | */ 1630 | if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) 1631 | /* This was really a NUL. */ 1632 | *(yy_c_buf_p) = '\0'; 1633 | 1634 | else 1635 | { /* need more input */ 1636 | yy_size_t offset = (yy_c_buf_p) - (yytext_ptr); 1637 | ++(yy_c_buf_p); 1638 | 1639 | switch ( yy_get_next_buffer( ) ) 1640 | { 1641 | case EOB_ACT_LAST_MATCH: 1642 | /* This happens because yy_g_n_b() 1643 | * sees that we've accumulated a 1644 | * token and flags that we need to 1645 | * try matching the token before 1646 | * proceeding. But for input(), 1647 | * there's no matching to consider. 1648 | * So convert the EOB_ACT_LAST_MATCH 1649 | * to EOB_ACT_END_OF_FILE. 1650 | */ 1651 | 1652 | /* Reset buffer status. */ 1653 | yyrestart(yyin ); 1654 | 1655 | /*FALLTHROUGH*/ 1656 | 1657 | case EOB_ACT_END_OF_FILE: 1658 | { 1659 | if ( yywrap( ) ) 1660 | return EOF; 1661 | 1662 | if ( ! (yy_did_buffer_switch_on_eof) ) 1663 | YY_NEW_FILE; 1664 | #ifdef __cplusplus 1665 | return yyinput(); 1666 | #else 1667 | return input(); 1668 | #endif 1669 | } 1670 | 1671 | case EOB_ACT_CONTINUE_SCAN: 1672 | (yy_c_buf_p) = (yytext_ptr) + offset; 1673 | break; 1674 | } 1675 | } 1676 | } 1677 | 1678 | c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ 1679 | *(yy_c_buf_p) = '\0'; /* preserve yytext */ 1680 | (yy_hold_char) = *++(yy_c_buf_p); 1681 | 1682 | return c; 1683 | } 1684 | #endif /* ifndef YY_NO_INPUT */ 1685 | 1686 | /** Immediately switch to a different input stream. 1687 | * @param input_file A readable stream. 1688 | * 1689 | * @note This function does not reset the start condition to @c INITIAL . 1690 | */ 1691 | void yyrestart (FILE * input_file ) 1692 | { 1693 | 1694 | if ( ! YY_CURRENT_BUFFER ){ 1695 | yyensure_buffer_stack (); 1696 | YY_CURRENT_BUFFER_LVALUE = 1697 | yy_create_buffer(yyin,YY_BUF_SIZE ); 1698 | } 1699 | 1700 | yy_init_buffer(YY_CURRENT_BUFFER,input_file ); 1701 | yy_load_buffer_state( ); 1702 | } 1703 | 1704 | /** Switch to a different input buffer. 1705 | * @param new_buffer The new input buffer. 1706 | * 1707 | */ 1708 | void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ) 1709 | { 1710 | 1711 | /* TODO. We should be able to replace this entire function body 1712 | * with 1713 | * yypop_buffer_state(); 1714 | * yypush_buffer_state(new_buffer); 1715 | */ 1716 | yyensure_buffer_stack (); 1717 | if ( YY_CURRENT_BUFFER == new_buffer ) 1718 | return; 1719 | 1720 | if ( YY_CURRENT_BUFFER ) 1721 | { 1722 | /* Flush out information for old buffer. */ 1723 | *(yy_c_buf_p) = (yy_hold_char); 1724 | YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); 1725 | YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); 1726 | } 1727 | 1728 | YY_CURRENT_BUFFER_LVALUE = new_buffer; 1729 | yy_load_buffer_state( ); 1730 | 1731 | /* We don't actually know whether we did this switch during 1732 | * EOF (yywrap()) processing, but the only time this flag 1733 | * is looked at is after yywrap() is called, so it's safe 1734 | * to go ahead and always set it. 1735 | */ 1736 | (yy_did_buffer_switch_on_eof) = 1; 1737 | } 1738 | 1739 | static void yy_load_buffer_state (void) 1740 | { 1741 | (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; 1742 | (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; 1743 | yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; 1744 | (yy_hold_char) = *(yy_c_buf_p); 1745 | } 1746 | 1747 | /** Allocate and initialize an input buffer state. 1748 | * @param file A readable stream. 1749 | * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. 1750 | * 1751 | * @return the allocated buffer state. 1752 | */ 1753 | YY_BUFFER_STATE yy_create_buffer (FILE * file, int size ) 1754 | { 1755 | YY_BUFFER_STATE b; 1756 | 1757 | b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); 1758 | if ( ! b ) 1759 | YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); 1760 | 1761 | b->yy_buf_size = size; 1762 | 1763 | /* yy_ch_buf has to be 2 characters longer than the size given because 1764 | * we need to put in 2 end-of-buffer characters. 1765 | */ 1766 | b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 ); 1767 | if ( ! b->yy_ch_buf ) 1768 | YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); 1769 | 1770 | b->yy_is_our_buffer = 1; 1771 | 1772 | yy_init_buffer(b,file ); 1773 | 1774 | return b; 1775 | } 1776 | 1777 | /** Destroy the buffer. 1778 | * @param b a buffer created with yy_create_buffer() 1779 | * 1780 | */ 1781 | void yy_delete_buffer (YY_BUFFER_STATE b ) 1782 | { 1783 | 1784 | if ( ! b ) 1785 | return; 1786 | 1787 | if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ 1788 | YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; 1789 | 1790 | if ( b->yy_is_our_buffer ) 1791 | yyfree((void *) b->yy_ch_buf ); 1792 | 1793 | yyfree((void *) b ); 1794 | } 1795 | 1796 | /* Initializes or reinitializes a buffer. 1797 | * This function is sometimes called more than once on the same buffer, 1798 | * such as during a yyrestart() or at EOF. 1799 | */ 1800 | static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file ) 1801 | 1802 | { 1803 | int oerrno = errno; 1804 | 1805 | yy_flush_buffer(b ); 1806 | 1807 | b->yy_input_file = file; 1808 | b->yy_fill_buffer = 1; 1809 | 1810 | /* If b is the current buffer, then yy_init_buffer was _probably_ 1811 | * called from yyrestart() or through yy_get_next_buffer. 1812 | * In that case, we don't want to reset the lineno or column. 1813 | */ 1814 | if (b != YY_CURRENT_BUFFER){ 1815 | b->yy_bs_lineno = 1; 1816 | b->yy_bs_column = 0; 1817 | } 1818 | 1819 | b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; 1820 | 1821 | errno = oerrno; 1822 | } 1823 | 1824 | /** Discard all buffered characters. On the next scan, YY_INPUT will be called. 1825 | * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. 1826 | * 1827 | */ 1828 | void yy_flush_buffer (YY_BUFFER_STATE b ) 1829 | { 1830 | if ( ! b ) 1831 | return; 1832 | 1833 | b->yy_n_chars = 0; 1834 | 1835 | /* We always need two end-of-buffer characters. The first causes 1836 | * a transition to the end-of-buffer state. The second causes 1837 | * a jam in that state. 1838 | */ 1839 | b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; 1840 | b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; 1841 | 1842 | b->yy_buf_pos = &b->yy_ch_buf[0]; 1843 | 1844 | b->yy_at_bol = 1; 1845 | b->yy_buffer_status = YY_BUFFER_NEW; 1846 | 1847 | if ( b == YY_CURRENT_BUFFER ) 1848 | yy_load_buffer_state( ); 1849 | } 1850 | 1851 | /** Pushes the new state onto the stack. The new state becomes 1852 | * the current state. This function will allocate the stack 1853 | * if necessary. 1854 | * @param new_buffer The new state. 1855 | * 1856 | */ 1857 | void yypush_buffer_state (YY_BUFFER_STATE new_buffer ) 1858 | { 1859 | if (new_buffer == NULL) 1860 | return; 1861 | 1862 | yyensure_buffer_stack(); 1863 | 1864 | /* This block is copied from yy_switch_to_buffer. */ 1865 | if ( YY_CURRENT_BUFFER ) 1866 | { 1867 | /* Flush out information for old buffer. */ 1868 | *(yy_c_buf_p) = (yy_hold_char); 1869 | YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); 1870 | YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); 1871 | } 1872 | 1873 | /* Only push if top exists. Otherwise, replace top. */ 1874 | if (YY_CURRENT_BUFFER) 1875 | (yy_buffer_stack_top)++; 1876 | YY_CURRENT_BUFFER_LVALUE = new_buffer; 1877 | 1878 | /* copied from yy_switch_to_buffer. */ 1879 | yy_load_buffer_state( ); 1880 | (yy_did_buffer_switch_on_eof) = 1; 1881 | } 1882 | 1883 | /** Removes and deletes the top of the stack, if present. 1884 | * The next element becomes the new top. 1885 | * 1886 | */ 1887 | void yypop_buffer_state (void) 1888 | { 1889 | if (!YY_CURRENT_BUFFER) 1890 | return; 1891 | 1892 | yy_delete_buffer(YY_CURRENT_BUFFER ); 1893 | YY_CURRENT_BUFFER_LVALUE = NULL; 1894 | if ((yy_buffer_stack_top) > 0) 1895 | --(yy_buffer_stack_top); 1896 | 1897 | if (YY_CURRENT_BUFFER) { 1898 | yy_load_buffer_state( ); 1899 | (yy_did_buffer_switch_on_eof) = 1; 1900 | } 1901 | } 1902 | 1903 | /* Allocates the stack if it does not exist. 1904 | * Guarantees space for at least one push. 1905 | */ 1906 | static void yyensure_buffer_stack (void) 1907 | { 1908 | yy_size_t num_to_alloc; 1909 | 1910 | if (!(yy_buffer_stack)) { 1911 | 1912 | /* First allocation is just for 2 elements, since we don't know if this 1913 | * scanner will even need a stack. We use 2 instead of 1 to avoid an 1914 | * immediate realloc on the next call. 1915 | */ 1916 | num_to_alloc = 1; 1917 | (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc 1918 | (num_to_alloc * sizeof(struct yy_buffer_state*) 1919 | ); 1920 | if ( ! (yy_buffer_stack) ) 1921 | YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); 1922 | 1923 | memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); 1924 | 1925 | (yy_buffer_stack_max) = num_to_alloc; 1926 | (yy_buffer_stack_top) = 0; 1927 | return; 1928 | } 1929 | 1930 | if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ 1931 | 1932 | /* Increase the buffer to prepare for a possible push. */ 1933 | int grow_size = 8 /* arbitrary grow size */; 1934 | 1935 | num_to_alloc = (yy_buffer_stack_max) + grow_size; 1936 | (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc 1937 | ((yy_buffer_stack), 1938 | num_to_alloc * sizeof(struct yy_buffer_state*) 1939 | ); 1940 | if ( ! (yy_buffer_stack) ) 1941 | YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); 1942 | 1943 | /* zero only the new slots.*/ 1944 | memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); 1945 | (yy_buffer_stack_max) = num_to_alloc; 1946 | } 1947 | } 1948 | 1949 | /** Setup the input buffer state to scan directly from a user-specified character buffer. 1950 | * @param base the character buffer 1951 | * @param size the size in bytes of the character buffer 1952 | * 1953 | * @return the newly allocated buffer state object. 1954 | */ 1955 | YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size ) 1956 | { 1957 | YY_BUFFER_STATE b; 1958 | 1959 | if ( size < 2 || 1960 | base[size-2] != YY_END_OF_BUFFER_CHAR || 1961 | base[size-1] != YY_END_OF_BUFFER_CHAR ) 1962 | /* They forgot to leave room for the EOB's. */ 1963 | return 0; 1964 | 1965 | b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); 1966 | if ( ! b ) 1967 | YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); 1968 | 1969 | b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ 1970 | b->yy_buf_pos = b->yy_ch_buf = base; 1971 | b->yy_is_our_buffer = 0; 1972 | b->yy_input_file = 0; 1973 | b->yy_n_chars = b->yy_buf_size; 1974 | b->yy_is_interactive = 0; 1975 | b->yy_at_bol = 1; 1976 | b->yy_fill_buffer = 0; 1977 | b->yy_buffer_status = YY_BUFFER_NEW; 1978 | 1979 | yy_switch_to_buffer(b ); 1980 | 1981 | return b; 1982 | } 1983 | 1984 | /** Setup the input buffer state to scan a string. The next call to yylex() will 1985 | * scan from a @e copy of @a str. 1986 | * @param yystr a NUL-terminated string to scan 1987 | * 1988 | * @return the newly allocated buffer state object. 1989 | * @note If you want to scan bytes that may contain NUL values, then use 1990 | * yy_scan_bytes() instead. 1991 | */ 1992 | YY_BUFFER_STATE yy_scan_string (yyconst char * yystr ) 1993 | { 1994 | 1995 | return yy_scan_bytes(yystr,strlen(yystr) ); 1996 | } 1997 | 1998 | /** Setup the input buffer state to scan the given bytes. The next call to yylex() will 1999 | * scan from a @e copy of @a bytes. 2000 | * @param yybytes the byte buffer to scan 2001 | * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. 2002 | * 2003 | * @return the newly allocated buffer state object. 2004 | */ 2005 | YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len ) 2006 | { 2007 | YY_BUFFER_STATE b; 2008 | char *buf; 2009 | yy_size_t n; 2010 | int i; 2011 | 2012 | /* Get memory for full buffer, including space for trailing EOB's. */ 2013 | n = _yybytes_len + 2; 2014 | buf = (char *) yyalloc(n ); 2015 | if ( ! buf ) 2016 | YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); 2017 | 2018 | for ( i = 0; i < _yybytes_len; ++i ) 2019 | buf[i] = yybytes[i]; 2020 | 2021 | buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; 2022 | 2023 | b = yy_scan_buffer(buf,n ); 2024 | if ( ! b ) 2025 | YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); 2026 | 2027 | /* It's okay to grow etc. this buffer, and we should throw it 2028 | * away when we're done. 2029 | */ 2030 | b->yy_is_our_buffer = 1; 2031 | 2032 | return b; 2033 | } 2034 | 2035 | #ifndef YY_EXIT_FAILURE 2036 | #define YY_EXIT_FAILURE 2 2037 | #endif 2038 | 2039 | static void yy_fatal_error (yyconst char* msg ) 2040 | { 2041 | (void) fprintf( stderr, "%s\n", msg ); 2042 | exit( YY_EXIT_FAILURE ); 2043 | } 2044 | 2045 | /* Redefine yyless() so it works in section 3 code. */ 2046 | 2047 | #undef yyless 2048 | #define yyless(n) \ 2049 | do \ 2050 | { \ 2051 | /* Undo effects of setting up yytext. */ \ 2052 | int yyless_macro_arg = (n); \ 2053 | YY_LESS_LINENO(yyless_macro_arg);\ 2054 | yytext[yyleng] = (yy_hold_char); \ 2055 | (yy_c_buf_p) = yytext + yyless_macro_arg; \ 2056 | (yy_hold_char) = *(yy_c_buf_p); \ 2057 | *(yy_c_buf_p) = '\0'; \ 2058 | yyleng = yyless_macro_arg; \ 2059 | } \ 2060 | while ( 0 ) 2061 | 2062 | /* Accessor methods (get/set functions) to struct members. */ 2063 | 2064 | /** Get the current line number. 2065 | * 2066 | */ 2067 | int yyget_lineno (void) 2068 | { 2069 | 2070 | return yylineno; 2071 | } 2072 | 2073 | /** Get the input stream. 2074 | * 2075 | */ 2076 | FILE *yyget_in (void) 2077 | { 2078 | return yyin; 2079 | } 2080 | 2081 | /** Get the output stream. 2082 | * 2083 | */ 2084 | FILE *yyget_out (void) 2085 | { 2086 | return yyout; 2087 | } 2088 | 2089 | /** Get the length of the current token. 2090 | * 2091 | */ 2092 | yy_size_t yyget_leng (void) 2093 | { 2094 | return yyleng; 2095 | } 2096 | 2097 | /** Get the current token. 2098 | * 2099 | */ 2100 | 2101 | char *yyget_text (void) 2102 | { 2103 | return yytext; 2104 | } 2105 | 2106 | /** Set the current line number. 2107 | * @param line_number 2108 | * 2109 | */ 2110 | void yyset_lineno (int line_number ) 2111 | { 2112 | 2113 | yylineno = line_number; 2114 | } 2115 | 2116 | /** Set the input stream. This does not discard the current 2117 | * input buffer. 2118 | * @param in_str A readable stream. 2119 | * 2120 | * @see yy_switch_to_buffer 2121 | */ 2122 | void yyset_in (FILE * in_str ) 2123 | { 2124 | yyin = in_str ; 2125 | } 2126 | 2127 | void yyset_out (FILE * out_str ) 2128 | { 2129 | yyout = out_str ; 2130 | } 2131 | 2132 | int yyget_debug (void) 2133 | { 2134 | return yy_flex_debug; 2135 | } 2136 | 2137 | void yyset_debug (int bdebug ) 2138 | { 2139 | yy_flex_debug = bdebug ; 2140 | } 2141 | 2142 | static int yy_init_globals (void) 2143 | { 2144 | /* Initialization is the same as for the non-reentrant scanner. 2145 | * This function is called from yylex_destroy(), so don't allocate here. 2146 | */ 2147 | 2148 | (yy_buffer_stack) = 0; 2149 | (yy_buffer_stack_top) = 0; 2150 | (yy_buffer_stack_max) = 0; 2151 | (yy_c_buf_p) = (char *) 0; 2152 | (yy_init) = 0; 2153 | (yy_start) = 0; 2154 | 2155 | /* Defined in main.c */ 2156 | #ifdef YY_STDINIT 2157 | yyin = stdin; 2158 | yyout = stdout; 2159 | #else 2160 | yyin = (FILE *) 0; 2161 | yyout = (FILE *) 0; 2162 | #endif 2163 | 2164 | /* For future reference: Set errno on error, since we are called by 2165 | * yylex_init() 2166 | */ 2167 | return 0; 2168 | } 2169 | 2170 | /* yylex_destroy is for both reentrant and non-reentrant scanners. */ 2171 | int yylex_destroy (void) 2172 | { 2173 | 2174 | /* Pop the buffer stack, destroying each element. */ 2175 | while(YY_CURRENT_BUFFER){ 2176 | yy_delete_buffer(YY_CURRENT_BUFFER ); 2177 | YY_CURRENT_BUFFER_LVALUE = NULL; 2178 | yypop_buffer_state(); 2179 | } 2180 | 2181 | /* Destroy the stack itself. */ 2182 | yyfree((yy_buffer_stack) ); 2183 | (yy_buffer_stack) = NULL; 2184 | 2185 | /* Reset the globals. This is important in a non-reentrant scanner so the next time 2186 | * yylex() is called, initialization will occur. */ 2187 | yy_init_globals( ); 2188 | 2189 | return 0; 2190 | } 2191 | 2192 | /* 2193 | * Internal utility routines. 2194 | */ 2195 | 2196 | #ifndef yytext_ptr 2197 | static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) 2198 | { 2199 | register int i; 2200 | for ( i = 0; i < n; ++i ) 2201 | s1[i] = s2[i]; 2202 | } 2203 | #endif 2204 | 2205 | #ifdef YY_NEED_STRLEN 2206 | static int yy_flex_strlen (yyconst char * s ) 2207 | { 2208 | register int n; 2209 | for ( n = 0; s[n]; ++n ) 2210 | ; 2211 | 2212 | return n; 2213 | } 2214 | #endif 2215 | 2216 | void *yyalloc (yy_size_t size ) 2217 | { 2218 | return (void *) malloc( size ); 2219 | } 2220 | 2221 | void *yyrealloc (void * ptr, yy_size_t size ) 2222 | { 2223 | /* The cast to (char *) in the following accommodates both 2224 | * implementations that use char* generic pointers, and those 2225 | * that use void* generic pointers. It works with the latter 2226 | * because both ANSI C and C++ allow castless assignment from 2227 | * any pointer type to void*, and deal with argument conversions 2228 | * as though doing an assignment. 2229 | */ 2230 | return (void *) realloc( (char *) ptr, size ); 2231 | } 2232 | 2233 | void yyfree (void * ptr ) 2234 | { 2235 | free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ 2236 | } 2237 | 2238 | #define YYTABLES_NAME "yytables" 2239 | 2240 | #line 103 "flex_c.l" 2241 | 2242 | 2243 | void comment(void) 2244 | { 2245 | char c ,prev = NULL; 2246 | 2247 | while ((c = input()) != 0) 2248 | { 2249 | if ( c == '\n') 2250 | linesno++; 2251 | if (prev == '*' && c == '/') 2252 | return; 2253 | prev = c; 2254 | } 2255 | error("unterminated comment"); 2256 | } 2257 | 2258 | void ignoreHeadfile() 2259 | { 2260 | while(input() != '\n'); 2261 | 2262 | return; 2263 | } 2264 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "bison_c.tab.h" 6 | #include "ast_node.h" 7 | #include "cfg_node.h" 8 | #include "program_slicing.h" 9 | #include "graph_to_dot.h" 10 | #include "write_ast_to_file.h" 11 | #include "print_slicing_result.h" 12 | 13 | int main(int argc, char **argv) 14 | { 15 | extern FILE *yyin; /*来自词法分析器*/ 16 | 17 | CfgNode *cfg_entry; 18 | RecordCfgNode *slicing_result = NULL, *q; 19 | int lineno; 20 | Symbol *var = NULL, *p; 21 | char name_temp[20]; 22 | 23 | if (argc != 2) 24 | { 25 | printf("Usage: ProgramSlicing \n"); 26 | return 1; 27 | } 28 | 29 | /*修改词法分析器的输入流*/ 30 | if ((yyin = fopen(argv[1], "r")) == NULL) 31 | { 32 | printf("Cannot open file!\n"); 33 | return 1; 34 | } 35 | 36 | /*yyparse()返回值为0或1 37 | 返回0表示执行成功,并已建立好抽象语法树; 38 | 返回1表示执行出错,会自动调用yyerror()函数输出错误信息.*/ 39 | if(yyparse()) 40 | { 41 | fclose(yyin); 42 | return 1; 43 | } 44 | 45 | fclose(yyin); 46 | 47 | /*仅作为测试,完成后删去*/ 48 | node_counter = 1; /*记得删除声明以及ast节点中的id以及valueIsNumber函数*/ 49 | initialiseNodeId(ast_root); 50 | writeAstToFile(ast_root); 51 | 52 | cfg_entry = createCFG(ast_root); 53 | 54 | /*仅作为测试,完成后删去,*/ 55 | graph_to_dot(cfg_entry); 56 | 57 | fflush(stdin); 58 | do 59 | { 60 | /*切片准则*/ 61 | printf("Please input the slicing criterion.\n"); 62 | printf("line number: "); 63 | scanf("%d", &lineno); 64 | 65 | printf("Set of variables: "); 66 | while (scanf("%s", name_temp) != EOF) 67 | { 68 | p = (Symbol *)malloc(sizeof(Symbol)); 69 | strcpy(p->name, name_temp); 70 | 71 | p->next = var; 72 | var = p; 73 | } 74 | }while (programSlicing(cfg_entry, lineno, var, &slicing_result)); 75 | 76 | printSlicingResult(argv[1], slicing_result, ast_root, cfg_entry); 77 | 78 | /*释放节点所占空间*/ 79 | freeAstNode(ast_root); 80 | freeCfgNode(cfg_entry); 81 | 82 | return 0; 83 | } -------------------------------------------------------------------------------- /print_slicing_result.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "print_slicing_result.h" 6 | 7 | void printSlicingResult(char *sourcefile, RecordCfgNode *slicing_result, 8 | AstNode *ast_root, CfgNode *entry) 9 | { 10 | int i; 11 | FILE *in, *out; 12 | char *destinationfile; /*存放切片结果的文件名*/ 13 | char line_contents[1024]; /*记录当前读取行的内容*/ 14 | int linecount ; /*记录当前需要读取行的行号*/ 15 | int file_path_length = strlen(sourcefile); 16 | CfgNode **cfg_array; 17 | RecordCfgNode *p; 18 | 19 | if ((in = fopen(sourcefile, "r")) == NULL) 20 | { 21 | printf("Cannot open source file!\n"); 22 | return; 23 | } 24 | 25 | destinationfile = (char *)malloc((file_path_length + 7) * sizeof(char)); 26 | strcpy(destinationfile, sourcefile); 27 | destinationfile[file_path_length - 2] = '\0'; 28 | strcat(destinationfile, "_slice.c"); 29 | 30 | if ((out = fopen(destinationfile, "w")) == NULL) 31 | { 32 | printf("Cannot open destination file!\n"); 33 | return; 34 | } 35 | 36 | /*为指针数组分配内存空间*/ 37 | cfg_array = (CfgNode **)malloc((linesno + 1) * sizeof(CfgNode *)); 38 | /*先将数组内容都置空*/ 39 | for (i = 0; i <= linesno; i++) 40 | cfg_array[i] = NULL; 41 | /*然后将控制流图节点指针存入以行号为下标的对应数组元素中*/ 42 | initialiseCfgArray(entry, cfg_array); 43 | 44 | linecount = 1; 45 | for (i = 1; i <= linesno; i++) 46 | { 47 | if (fgets(line_contents, 1024, in) == NULL) /*失败或到达文件结尾*/ 48 | break; 49 | 50 | if (i < linecount) /*还没到需要读取的那一行*/ 51 | continue; 52 | 53 | if (cfg_array[linecount] == NULL /*不再控制流图节点中*/ 54 | || isInSlicingResult(slicing_result, linecount)) /*或者在控制流图中且在切片结果链表中*/ 55 | { 56 | fputs(line_contents, out); /*写到文件里*/ 57 | linecount++; 58 | } 59 | else /*在控制流图中但不在切片结果链表中*/ 60 | { 61 | if (cfg_array[linecount]->nodetype_cfg == Iteration 62 | || cfg_array[linecount]->nodetype_cfg == Select) 63 | { 64 | /*找到紧接在此节点后的下一个切片结果节点*/ 65 | for (p = slicing_result; p; p = p->next) 66 | if (linecount < p->node_cfg->node_of_ast->linenumber) 67 | break; 68 | 69 | /*如果下一个切片结果节点在此节点对应的抽象语法树中,即控制依赖*/ 70 | if (p && isInAstNode(cfg_array[linecount]->node_of_ast->firstchild, 71 | p->node_cfg->node_of_ast->linenumber)) 72 | { 73 | fputs(line_contents, out); /*写到文件里*/ 74 | linecount++; 75 | } 76 | else /*否则,直接跳过此语句,将应读取行置为此语句结束行的下一行*/ 77 | linecount = cfg_array[linecount]->node_of_ast->endlinenumber + 1; 78 | 79 | } 80 | else if (strcmp(cfg_array[linecount]->node_of_ast->value.value_string, "jump_statement") == 0) 81 | { 82 | fputs(line_contents, out); 83 | linecount++; 84 | } 85 | else 86 | { 87 | linecount++; 88 | } 89 | } 90 | } 91 | 92 | while (slicing_result) 93 | { 94 | p = slicing_result; 95 | slicing_result = slicing_result->next; 96 | free(p); 97 | } 98 | 99 | printf("Program slicing finished, the result is stored in the %s\n", destinationfile); 100 | 101 | fclose(in); 102 | fclose(out); 103 | free(destinationfile); 104 | free(cfg_array); 105 | } 106 | 107 | void initialiseCfgArray(CfgNode *node_cfg, CfgNode **cfg_array) 108 | { 109 | CfgNodeList *p; 110 | 111 | if (node_cfg->nodetype_cfg != Entry 112 | && node_cfg->nodetype_cfg != Exit) 113 | { 114 | cfg_array[node_cfg->node_of_ast->linenumber] = node_cfg; 115 | node_cfg->visited = true; 116 | } 117 | 118 | for (p = node_cfg->successor; p; p = p->next) 119 | if (!p->node_cfg->visited) 120 | initialiseCfgArray(p->node_cfg, cfg_array); 121 | } 122 | 123 | /*在切片结果中返回1,否则返回0*/ 124 | int isInSlicingResult(RecordCfgNode *slicing_result, int linecount) 125 | { 126 | RecordCfgNode *p = NULL; 127 | 128 | p = slicing_result; 129 | while (p) 130 | { 131 | if (linecount == p->node_cfg->node_of_ast->linenumber) 132 | return 1; 133 | 134 | /*因为切片结果链表是按行号递增的顺序的,所以若行号小于当前行号,就不用往后找了*/ 135 | if (linecount < p->node_cfg->node_of_ast->linenumber) 136 | break; 137 | 138 | p = p->next; 139 | } 140 | 141 | return 0; 142 | } 143 | 144 | int isInAstNode(AstNode *node_ast, int linecount) 145 | { 146 | if (!node_ast) 147 | return 0; 148 | 149 | if (node_ast->linenumber == linecount) 150 | return 1; 151 | 152 | return isInAstNode(node_ast->firstchild, linecount) 153 | || isInAstNode(node_ast->nextsibling, linecount); 154 | } -------------------------------------------------------------------------------- /print_slicing_result.h: -------------------------------------------------------------------------------- 1 | #ifndef PRINT_SLICING_RESULT_H 2 | #define PRINT_SLICING_RESULT_H 3 | 4 | #include "ast_node.h" 5 | #include "program_slicing.h" 6 | 7 | extern int linesno; /*来自词法分析器*/ 8 | 9 | void printSlicingResult(char *sourcefile, RecordCfgNode *slicing_result, 10 | AstNode *ast_root, CfgNode *entry); 11 | 12 | void initialiseCfgArray(CfgNode *node_cfg, CfgNode **cfg_array); 13 | 14 | int isInSlicingResult(RecordCfgNode *slicing_result, int linecount); 15 | 16 | int isInAstNode(AstNode *node_ast, int linecount); 17 | 18 | #endif -------------------------------------------------------------------------------- /program_slicing.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "program_slicing.h" 6 | 7 | int programSlicing(CfgNode *entry, int lineno, Symbol *var, RecordCfgNode **slicing_list) 8 | { 9 | CfgNode *slice_start_node; 10 | RecordCfgNode *p; 11 | RecordCfgNode *visited_node_list = NULL; 12 | 13 | slice_start_node = searchNode(entry, lineno); 14 | if (!slice_start_node) 15 | { 16 | printf("line number error!\n"); 17 | return 1; 18 | } 19 | 20 | /*开始节点插入到切片结果链表中*/ 21 | insertSlicingResult(slicing_list, slice_start_node); 22 | 23 | /*深度优先遍历切片*/ 24 | DFSSlicing(slice_start_node, &var, &visited_node_list, slicing_list); 25 | 26 | /*访问过的节点标记复原*/ 27 | while (visited_node_list) 28 | { 29 | visited_node_list->node_cfg->visited = false; 30 | 31 | p = visited_node_list; 32 | visited_node_list = visited_node_list->next; 33 | free(p); 34 | } 35 | 36 | return 0; 37 | } 38 | 39 | CfgNode *searchNode(CfgNode *node_cfg, int lineno) 40 | { 41 | RecordCfgNode *visited_node_list = NULL, *p; 42 | CfgNode *search_result; 43 | 44 | search_result = DFSSearch(node_cfg, lineno, &visited_node_list); 45 | 46 | while (visited_node_list) 47 | { 48 | visited_node_list->node_cfg->visited = false; 49 | 50 | p = visited_node_list; 51 | visited_node_list = visited_node_list->next; 52 | free(p); 53 | } 54 | 55 | return search_result; 56 | } 57 | 58 | CfgNode *DFSSearch(CfgNode *node_cfg, int lineno, RecordCfgNode **visited_node) 59 | { 60 | RecordCfgNode *p; 61 | CfgNodeList *q; 62 | CfgNode *dfs_return; 63 | 64 | if (node_cfg->node_of_ast && node_cfg->node_of_ast->linenumber == lineno) 65 | return node_cfg; 66 | 67 | node_cfg->visited = true; 68 | 69 | /*头插法*/ 70 | p = (RecordCfgNode *)malloc(sizeof(RecordCfgNode)); 71 | p->node_cfg = node_cfg; 72 | p->next = *visited_node; 73 | *visited_node = p; 74 | 75 | for (q = node_cfg->successor; q; q = q->next) 76 | { 77 | if (!q->node_cfg->visited) 78 | { 79 | dfs_return = DFSSearch(q->node_cfg, lineno, visited_node); 80 | if (dfs_return) 81 | return dfs_return; 82 | } 83 | } 84 | 85 | /*没找到,返回NULL*/ 86 | return NULL; 87 | } 88 | 89 | void DFSSlicing(CfgNode *node_cfg, Symbol **relevant, 90 | RecordCfgNode **visited_node, RecordCfgNode **slicing_list) 91 | { 92 | RecordCfgNode *p, *p1; 93 | CfgNodeList *q; 94 | Symbol *r, *temp; /*释放relevant所占空间时使用*/ 95 | int flag; 96 | 97 | if (subtractSymbol(relevant, node_cfg->def_s)) /*如果修改过,即node_cfg定义了relevant中的变量*/ 98 | { 99 | insertSlicingResult(slicing_list, node_cfg); 100 | 101 | /*将node_cfg中使用的变量加入到relevant链表中*/ 102 | mergeSymbol(relevant, node_cfg->use_s); 103 | } 104 | 105 | if (node_cfg->nodetype_cfg != Iteration) 106 | { 107 | node_cfg->visited = true; 108 | 109 | /*插入到访问过的节点链表中*/ 110 | p = (RecordCfgNode *)malloc(sizeof(RecordCfgNode)); 111 | p->node_cfg = node_cfg; 112 | p->next = *visited_node; 113 | *visited_node = p; 114 | } 115 | 116 | if (!(*relevant)) /*relevant链表为空时结束,不在向上遍历*/ 117 | return; 118 | 119 | if (node_cfg->nodetype_cfg == Entry) 120 | { 121 | /*释放relevant所占空间*/ 122 | r = *relevant; 123 | while (r) 124 | { 125 | temp = r; 126 | r = r->next; 127 | free(temp); 128 | } 129 | return; /*结束*/ 130 | } 131 | 132 | for (q = node_cfg->predecessor; q; q = q->next) 133 | { 134 | /*是循环控制节点*/ 135 | if (q->node_cfg->nodetype_cfg == Iteration) 136 | { 137 | /*查找其是否在节点访问列表中,即是否是第一次访问*/ 138 | p = *visited_node; 139 | flag = 0; 140 | while (p) 141 | { 142 | /*找到*/ 143 | if (p->node_cfg->node_of_ast->linenumber == q->node_cfg->node_of_ast->linenumber) 144 | { 145 | p->visit_count++; 146 | flag = 1; 147 | break; 148 | } 149 | p = p->next; 150 | } 151 | 152 | if (!flag) /*如果没有找到*/ 153 | { 154 | p = (RecordCfgNode *)malloc(sizeof(RecordCfgNode)); 155 | p->node_cfg = q->node_cfg; 156 | p->node_cfg->visited = true; 157 | p->visit_count = 1; 158 | 159 | /*插入到已访问列表*/ 160 | p->next = *visited_node; 161 | *visited_node = p; 162 | } 163 | 164 | if (flag && p->visit_count == 2) /*如果找到且是第二次访问,此时p指向找到的节点*/ 165 | { 166 | while (*visited_node != p) 167 | { 168 | (*visited_node)->node_cfg->visited = false; 169 | 170 | p1 = *visited_node; 171 | *visited_node = (*visited_node)->next; 172 | free(p1); 173 | } 174 | } 175 | 176 | temp = copySymbolList(*relevant); 177 | DFSSlicing(q->node_cfg, &temp, visited_node, slicing_list); 178 | 179 | continue; 180 | } 181 | 182 | if (!q->node_cfg->visited) 183 | { 184 | temp = copySymbolList(*relevant); 185 | DFSSlicing(q->node_cfg, &temp, visited_node, slicing_list); 186 | } 187 | } 188 | 189 | /*退出函数前,释放relevant所占空间*/ 190 | r = *relevant; 191 | while (r) 192 | { 193 | temp = r; 194 | r = r->next; 195 | free(temp); 196 | } 197 | } 198 | 199 | Symbol *copySymbolList(Symbol *s) 200 | { 201 | Symbol *head = NULL, *p; 202 | 203 | while(s) 204 | { 205 | p = (Symbol *)malloc(sizeof(Symbol)); 206 | strcpy(p->name, s->name); 207 | p->next = head; 208 | head = p; 209 | 210 | s = s->next; 211 | } 212 | 213 | return head; 214 | } 215 | 216 | /*按行号递增的顺序插入切片结果链表中*/ 217 | void insertSlicingResult(RecordCfgNode **slicing_list, CfgNode *node_cfg) 218 | { 219 | RecordCfgNode *pre, *p, *t; 220 | 221 | /*小于第一个节点的行号,插入到第一个节点前即可*/ 222 | if ( !(*slicing_list) 223 | || node_cfg->node_of_ast->linenumber < (*slicing_list)->node_cfg->node_of_ast->linenumber) 224 | { 225 | t = (RecordCfgNode *)malloc(sizeof(RecordCfgNode)); 226 | t->node_cfg = node_cfg; 227 | t->next = *slicing_list; 228 | *slicing_list = t; 229 | 230 | return; 231 | } 232 | 233 | /*等于第一个节点行号,即切片结果链表里已有该节点,不用任何操作,直接退出函数*/ 234 | if (node_cfg->node_of_ast->linenumber == (*slicing_list)->node_cfg->node_of_ast->linenumber) 235 | return; 236 | 237 | /*即大于第一个节点行号的情况*/ 238 | pre = *slicing_list; 239 | p = pre->next; 240 | while (p) 241 | { 242 | /*插入到两者之间*/ 243 | if (node_cfg->node_of_ast->linenumber < p->node_cfg->node_of_ast->linenumber) 244 | { 245 | t = (RecordCfgNode *)malloc(sizeof(RecordCfgNode)); 246 | t->node_cfg = node_cfg; 247 | t->next = p; 248 | pre->next = t; 249 | 250 | return; 251 | } 252 | 253 | if (node_cfg->node_of_ast->linenumber == p->node_cfg->node_of_ast->linenumber) 254 | return; 255 | 256 | pre = p; 257 | p = p->next; 258 | } 259 | 260 | /*执行到此说明节点行号大于切片结果链表里所有节点的行号,把节点插入到链表结尾*/ 261 | t = (RecordCfgNode *)malloc(sizeof(RecordCfgNode)); 262 | t->node_cfg = node_cfg; 263 | t->next = NULL; 264 | pre->next = t; 265 | } -------------------------------------------------------------------------------- /program_slicing.h: -------------------------------------------------------------------------------- 1 | #ifndef PROGRAM_SLICING_H 2 | #define PROGRAM_SLICING_H 3 | 4 | #include "cfg_node.h" 5 | 6 | /*记录每次遍历时访问过的节点,以便在遍历结束时将visited标记置为访问前的值*/ 7 | typedef struct RecordCfgNode 8 | { 9 | int visit_count; /*专门为循环节点设置,其它节点不需要使用*/ 10 | CfgNode *node_cfg; 11 | struct RecordCfgNode *next; 12 | }RecordCfgNode; 13 | 14 | /*成功返回0, 失败返回1*/ 15 | int programSlicing(CfgNode *entry, int lineno, Symbol *var, RecordCfgNode **slicing_list); 16 | 17 | /*在控制流图中查找节点,返回相应节点的指针,由programSlicing()函数调用*/ 18 | CfgNode *searchNode(CfgNode *node_cfg, int lineno); 19 | 20 | /*深度优先遍历控制流图,由searchNode()函数调用*/ 21 | CfgNode *DFSSearch(CfgNode *node_cfg, int lineno, RecordCfgNode **visited_node); 22 | 23 | /*利用深度优先遍历进行切片,由programSlicing()函数调用*/ 24 | void DFSSlicing(CfgNode *node_cfg, Symbol **relevant, 25 | RecordCfgNode **visited_node, RecordCfgNode **slicing_list); 26 | 27 | /*复制符号链表*/ 28 | Symbol *copySymbolList(Symbol *s); 29 | 30 | void insertSlicingResult(RecordCfgNode **slicing_list, CfgNode *node_cfg); 31 | 32 | #endif -------------------------------------------------------------------------------- /symbol.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "symbol.h" 6 | 7 | int subtractSymbol(Symbol **s1, Symbol *s2) 8 | { 9 | Symbol *pre, *p; 10 | 11 | if (!s2) 12 | return 0; 13 | 14 | if (strcmp((*s1)->name, s2->name) == 0) 15 | { 16 | p = *s1; 17 | *s1 = (*s1)->next; 18 | free(p); 19 | 20 | return 1; 21 | } 22 | else 23 | { 24 | pre = *s1; 25 | p = (*s1)->next; 26 | while (p) 27 | { 28 | if (strcmp(p->name, s2->name) == 0) 29 | { 30 | pre->next = p->next; 31 | free(p); 32 | 33 | return 1; 34 | } 35 | pre = p; 36 | p = p->next; 37 | } 38 | } 39 | 40 | return 0; 41 | } 42 | 43 | void mergeSymbol(Symbol **s1, Symbol *s2) 44 | { 45 | Symbol *p; 46 | 47 | while (s2) 48 | { 49 | p = *s1; 50 | while (p) 51 | { 52 | if (strcmp(p->name, s2->name) == 0) 53 | break; 54 | 55 | p = p->next; 56 | } 57 | 58 | if (!p) /*在s1中没有找到*/ 59 | { 60 | p = (Symbol *)malloc(sizeof(Symbol)); 61 | strcpy(p->name, s2->name); 62 | 63 | p->next = *s1; 64 | *s1 = p; 65 | } 66 | 67 | s2 = s2->next; 68 | } 69 | } -------------------------------------------------------------------------------- /symbol.h: -------------------------------------------------------------------------------- 1 | #ifndef SYMBOL_H 2 | #define SYMBOL_H 3 | 4 | typedef struct Symbol 5 | { 6 | char name[20]; 7 | struct Symbol *next; 8 | }Symbol; 9 | 10 | /*集合s1减去集合s2,结果保存在集合s1中,返回1表示s1中元素减少了,否则返回0*/ 11 | int subtractSymbol(Symbol **s1, Symbol *s2); 12 | /*求两个集合的并集*/ 13 | void mergeSymbol(Symbol **s1, Symbol *s2); 14 | 15 | #endif -------------------------------------------------------------------------------- /write_ast_to_file.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "write_ast_to_file.h" 5 | 6 | /*遍历抽象语法树 7 | 按先序遍历顺序初始化节点中的索引值index,即给节点编号,根节点编号为1,便于识别; 8 | 按后序遍历顺序将节点信息写入文件,这种顺序便于以后建立语法树; 9 | 函数递归调用结束后,node_counter的值即为总节点数.*/ 10 | void writeNodeToFile(AstNode *root, FILE *file_stream) 11 | { 12 | if(root) 13 | { 14 | writeNodeToFile(root->firstchild, file_stream); /*写入孩子节点*/ 15 | writeNodeToFile(root->nextsibling, file_stream); /*写入兄弟节点*/ 16 | 17 | /*---------------写入节点信息------------------*/ 18 | /*写入节点索引*/ 19 | fprintf(file_stream, "@%-7d", root->id); 20 | /*写入节点类型*/ 21 | fprintf(file_stream, "type : %-8d", root->nodetype_ast); 22 | /*写入节点值,并换行*/ 23 | if (valueIsNumber(root->nodetype_ast)) 24 | fprintf(file_stream, "value : %-39.6lf\n", root->value.value_number); 25 | else 26 | fprintf(file_stream, "value : %-39s\n", root->value.value_string); 27 | 28 | /*写入行号,前面加入空格,保持对齐*/ 29 | fprintf(file_stream, " linenumber: %-8d", root->linenumber); 30 | 31 | /*写入第一个孩子的索引,若不存在则写入-1*/ 32 | fprintf(file_stream, "firstchild: %-8d", root->firstchild ? root->firstchild->id : -1); 33 | /*写入兄弟节点的索引,若不存在则写入-1;并换行*/ 34 | fprintf(file_stream, "nextsibling: %-7d\n\n", root->nextsibling ? root->nextsibling->id : -1); 35 | } 36 | } 37 | 38 | /*将抽象语法树写入文件中*/ 39 | void writeAstToFile(AstNode *root) 40 | { 41 | FILE *file_stream; 42 | 43 | file_stream = fopen("astfile", "w"); 44 | 45 | /*写入节点总数*/ 46 | fprintf(file_stream, "TheTotalNumberOfNodes: %-8d\n\n", node_counter-1); 47 | 48 | writeNodeToFile(root, file_stream); 49 | 50 | fclose(file_stream); 51 | } 52 | 53 | 54 | /*判断节点值是string型还是number型,string型返回0.number型返回1*/ 55 | int valueIsNumber(enum AstNodeType type) 56 | { 57 | switch(type) 58 | { 59 | case Number: 60 | return 1; 61 | case Identifier: 62 | case String: 63 | case Keyword: 64 | case Operator: 65 | case Statement: 66 | case Expression: 67 | case FunctionDefinition: 68 | case Declaration: 69 | return 0; 70 | } 71 | } -------------------------------------------------------------------------------- /write_ast_to_file.h: -------------------------------------------------------------------------------- 1 | #ifndef WRITE_AST_TO_FILE_H 2 | #define WRITE_AST_TO_FILE_H 3 | 4 | #include "ast_node.h" 5 | 6 | /*初始化抽象语法树节点索引, 由writeAstToFile调用*/ 7 | void writeNodeToFile(AstNode *root, FILE *file_stream); 8 | /*将抽象语法树写入到文件里*/ 9 | 10 | void writeAstToFile(AstNode *root); 11 | 12 | /*判断节点值是string型还是number型*/ 13 | int valueIsNumber(enum AstNodeType type); 14 | 15 | #endif --------------------------------------------------------------------------------