├── Project1 ├── Makefile ├── SyntaxTree.c ├── SyntaxTree.h ├── lexical.l ├── main.c ├── parse.h ├── pretest │ ├── 1.txt │ ├── 10.txt │ ├── 2.txt │ ├── 3.txt │ ├── 4.txt │ ├── 5.txt │ ├── 6.txt │ ├── 7.txt │ ├── 8.txt │ ├── 9.txt │ └── README.txt ├── report.md └── syntax.y ├── Project2 ├── HashTable.c ├── HashTable.h ├── Makefile ├── Semantic.c ├── Semantic.h ├── SyntaxTree.c ├── SyntaxTree.h ├── lexical.l ├── main.c ├── parse.h ├── pretest │ ├── .DS_Store │ ├── 1.txt │ ├── 10.txt │ ├── 11.txt │ ├── 12.txt │ ├── 13.txt │ ├── 14.txt │ ├── 15.txt │ ├── 16.txt │ ├── 17.txt │ ├── 18.txt │ ├── 19.txt │ ├── 2.txt │ ├── 20.txt │ ├── 21.txt │ ├── 22.txt │ ├── 23.txt │ ├── 24.txt │ ├── 3.txt │ ├── 4.txt │ ├── 5.txt │ ├── 6.txt │ ├── 7.txt │ ├── 8.txt │ ├── 9.txt │ └── README.txt ├── report.md └── syntax.y ├── Project3 ├── HashTable.c ├── HashTable.h ├── InterCode.c ├── InterCode.h ├── Makefile ├── Semantic.c ├── Semantic.h ├── SyntaxTree.c ├── SyntaxTree.h ├── irsim │ ├── irsim.py │ ├── resources_rc.py │ ├── resources_rc.pyc │ ├── ui_mainwindow.py │ └── ui_mainwindow.pyc ├── lexical.l ├── main.c ├── parse.h ├── report.md ├── syntax.y └── testcase │ ├── testcase1.txt │ ├── testcase2.txt │ ├── testcase3.txt │ └── testcase4.txt ├── Project4 ├── HashTable.c ├── HashTable.h ├── InterCode.c ├── InterCode.h ├── Makefile ├── Semantic.c ├── Semantic.h ├── SyntaxTree.c ├── SyntaxTree.h ├── lexical.l ├── main.c ├── mips.c ├── mips.h ├── parse.h ├── report.md ├── syntax.y └── testcase │ ├── testcase1.txt │ ├── testcase2.txt │ ├── testcase3.txt │ └── testcase4.txt └── README.md /Project1/Makefile: -------------------------------------------------------------------------------- 1 | parser: 2 | bison -d syntax.y 3 | flex lexical.l 4 | gcc -c lex.yy.c -o lex.o 5 | gcc main.c syntax.tab.c SyntaxTree.c lex.o -lfl -ly -o parser 6 | 7 | lexical: 8 | bison -d syntax.y 9 | flex lexical.l 10 | 11 | syntax: 12 | bison -d syntax.y 13 | 14 | clean: 15 | rm lex.yy.c lex.o syntax.tab.c syntax.tab.h parser 16 | -------------------------------------------------------------------------------- /Project1/SyntaxTree.c: -------------------------------------------------------------------------------- 1 | #include "SyntaxTree.h" 2 | #include 3 | 4 | Node* init(char identifier[], char value[], Type type, int line){ 5 | Node* root = malloc(sizeof(Node)); 6 | 7 | root->height = 0; 8 | strcpy(root->identifier, identifier); 9 | 10 | if(value != NULL) 11 | strcpy(root->value, value); 12 | else 13 | root->value[0]='\0'; 14 | 15 | root->type = type; 16 | root->line = line; 17 | 18 | return root; 19 | } 20 | 21 | 22 | void insert(Node *p, Node *child){ 23 | if(p == NULL || child == NULL) 24 | return; 25 | 26 | if(p->child == NULL){ 27 | p->child = child; 28 | return; 29 | } 30 | 31 | Node *temp = p->child; 32 | while(temp->sibling != NULL) 33 | temp = temp->sibling; 34 | temp->sibling = child; 35 | 36 | } 37 | 38 | void traverseTree(Node* p){ 39 | if(p == NULL) 40 | return; 41 | 42 | // Print Node 43 | 44 | for(int i=0; iheight; i++) 45 | printf(" "); 46 | switch(p->type){ 47 | case TYPE_NONTERMINAL: 48 | // non-terminals 49 | printf("%s (%d)\n",p->identifier,p->line); 50 | break; 51 | case TYPE_OCT: 52 | printf("%s: %d\n",p->identifier,(int)strtol(p->value,NULL,8)); 53 | break; 54 | case TYPE_HEX: 55 | printf("%s: %d\n",p->identifier,(int)strtol(p->value,NULL,16)); 56 | break; 57 | case TYPE_KEYWORD_BRACKET: 58 | case TYPE_KEYWORD_PUNCTUATION: 59 | case TYPE_KEYWORD_OPERATOR: 60 | // LP|RP|LB|RB|LC|RC|PUNCUTATION|OPERATOR 61 | printf("%s\n",p->identifier); 62 | break; 63 | default: 64 | // terminals 65 | printf("%s: %s\n",p->identifier,p->value); 66 | break; 67 | } 68 | 69 | if(p->child != NULL) 70 | p->child->height = p->height+1; 71 | if(p->sibling != NULL) 72 | p->sibling->height = p->height; 73 | traverseTree(p->child); 74 | traverseTree(p->sibling); 75 | 76 | } 77 | 78 | void cleanTree(Node *p){ 79 | if(p==NULL) 80 | return; 81 | 82 | cleanTree(p->child); 83 | cleanTree(p->sibling); 84 | free(p); 85 | } 86 | 87 | -------------------------------------------------------------------------------- /Project1/SyntaxTree.h: -------------------------------------------------------------------------------- 1 | #ifndef SYNTAXTREE_H 2 | #define SYNTAXTREE_H 3 | 4 | #include 5 | #include 6 | 7 | #define IDENTIFIER_LENGTH 32 8 | #define VALUE_LENGTH 32 9 | 10 | #define TYPE_KEYWORD 0 11 | #define TYPE_KEYWORD_RELOP 1 12 | #define TYPE_KEYWORD_BRACKET 2 13 | #define TYPE_KEYWORD_PUNCTUATION 3 14 | #define TYPE_KEYWORD_OPERATOR 4 15 | 16 | #define TYPE_NONTERMINAL 65536 17 | 18 | #define TYPE_ID 128 19 | 20 | #define TYPE_INT 256 21 | #define TYPE_OCT 257 22 | #define TYPE_HEX 258 23 | 24 | #define TYPE_FLOAT 512 25 | #define TYPE_SFLOAT 513 26 | 27 | #define TYPE_STRING 1024 28 | 29 | extern int yylineno; 30 | 31 | typedef int Type; 32 | 33 | typedef struct Node{ 34 | //TODO: Complete Node Structure 35 | 36 | char identifier[IDENTIFIER_LENGTH]; 37 | char value[VALUE_LENGTH]; 38 | Type type; 39 | int line; 40 | int height; 41 | 42 | // Children Brother Express 43 | struct Node *child; 44 | struct Node *sibling; 45 | 46 | }Node; 47 | 48 | extern Node* init(char identifier[], char value[], Type type, int line); 49 | extern void insert(Node *p, Node *child); 50 | extern void traverseTree(Node *p); 51 | extern void cleanTree(Node *p); 52 | #endif 53 | -------------------------------------------------------------------------------- /Project1/lexical.l: -------------------------------------------------------------------------------- 1 | %{ 2 | #include 3 | #include 4 | #include "SyntaxTree.h" 5 | #include "syntax.tab.h" 6 | 7 | extern int errorLexFlag; 8 | 9 | int yycolumn = 1; 10 | /* define YY_USER_ACTION */ 11 | #define YY_USER_ACTION \ 12 | yylloc.first_line = yylloc.last_line = yylineno; \ 13 | yylloc.first_column = yycolumn; \ 14 | yylloc.last_column = yycolumn + yyleng - 1; \ 15 | yycolumn += yyleng; 16 | 17 | %} 18 | 19 | %option yylineno 20 | 21 | DELIM [ \t] 22 | WS {DELIM}+ 23 | DIGIT [0-9] 24 | LETTER [A-Za-z] 25 | INT 0|([1-9]{DIGIT}*) 26 | OCT 0([0-7]+) 27 | OCT_ERROR 0[0-9A-WYZa-wyz][0-9A-Za-z]* 28 | HEX 0(x|X)[0-9a-fA-F]+ 29 | HEX_ERROR [0][Xx][0-9A-Za-z]* 30 | FLOAT {INT}(\.{DIGIT}+)? 31 | SFLOAT ((INT\.{DIGIT}*)|({DIGIT}*\.{DIGIT}+))[Ee][+-]?{DIGIT}+ 32 | SFLOAT_ERROR ((INT\.{DIGIT}*)|({DIGIT}*\.{DIGIT}+))[Ee][+-]?([0-9A-Za-z]*) 33 | RELOP >|<|>=|<=|==|!= 34 | ID ({LETTER}|_)({LETTER}|{DIGIT}|_)* 35 | LINE [\n] 36 | 37 | 38 | %% 39 | 40 | 41 | {WS} { /* tabs */ } 42 | 43 | "/*"([^\*]|(\*)*[^\*/])*(\*)*"*/" { /* C comments */ } 44 | 45 | "//" { 46 | /* C++ comment */ 47 | while(input() != '\n'); 48 | } 49 | 50 | ";" { 51 | yylval.type_node = init("SEMI",yytext,TYPE_KEYWORD_PUNCTUATION,yylineno); 52 | return SEMI; 53 | } 54 | 55 | "," { 56 | yylval.type_node = init("COMMA",yytext,TYPE_KEYWORD_PUNCTUATION,yylineno); 57 | return COMMA; 58 | } 59 | 60 | 61 | "=" { 62 | yylval.type_node = init("ASSIGNOP",yytext,TYPE_KEYWORD_OPERATOR,yylineno); 63 | return ASSIGNOP; 64 | } 65 | 66 | {RELOP} { 67 | yylval.type_node = init("RELOP",yytext,TYPE_KEYWORD_RELOP,yylineno); 68 | return RELOP; 69 | } 70 | 71 | "+" { 72 | yylval.type_node = init("PLUS",yytext,TYPE_KEYWORD_OPERATOR,yylineno); 73 | return PLUS; 74 | } 75 | 76 | "-" { 77 | yylval.type_node = init("MINUS",yytext,TYPE_KEYWORD_OPERATOR,yylineno); 78 | return MINUS; 79 | } 80 | 81 | "*" { 82 | yylval.type_node = init("STAR",yytext,TYPE_KEYWORD_OPERATOR,yylineno); 83 | return STAR; 84 | } 85 | 86 | "/" { 87 | yylval.type_node = init("DIV",yytext,TYPE_KEYWORD_OPERATOR,yylineno); 88 | return DIV; 89 | } 90 | 91 | "&&" { 92 | yylval.type_node = init("AND",yytext,TYPE_KEYWORD_OPERATOR,yylineno); 93 | return AND; 94 | } 95 | 96 | "||" { 97 | yylval.type_node = init("OR",yytext,TYPE_KEYWORD_OPERATOR,yylineno); 98 | return OR; 99 | } 100 | 101 | "!" { 102 | yylval.type_node = init("NOT",yytext,TYPE_KEYWORD_OPERATOR,yylineno); 103 | return NOT; 104 | } 105 | 106 | "." { 107 | yylval.type_node = init("DOT",yytext,TYPE_KEYWORD_PUNCTUATION,yylineno); 108 | return DOT; 109 | } 110 | 111 | "int"|"float" { 112 | yylval.type_node = init("TYPE",yytext,TYPE_KEYWORD,yylineno); 113 | return TYPE; 114 | } 115 | 116 | "(" { 117 | yylval.type_node = init("LP",yytext,TYPE_KEYWORD_BRACKET,yylineno); 118 | return LP; 119 | } 120 | 121 | ")" { 122 | yylval.type_node = init("RP",yytext,TYPE_KEYWORD_BRACKET,yylineno); 123 | return RP; 124 | } 125 | 126 | "[" { 127 | yylval.type_node = init("LB",yytext,TYPE_KEYWORD_BRACKET,yylineno); 128 | return LB; 129 | } 130 | 131 | "]" { 132 | yylval.type_node = init("RB",yytext,TYPE_KEYWORD_BRACKET,yylineno); 133 | return RB; 134 | } 135 | 136 | "{" { 137 | yylval.type_node = init("LC",yytext,TYPE_KEYWORD_BRACKET,yylineno); 138 | return LC; 139 | } 140 | 141 | "}" { 142 | yylval.type_node = init("RC",yytext,TYPE_KEYWORD_BRACKET,yylineno); 143 | return RC; 144 | } 145 | 146 | "struct" { 147 | yylval.type_node = init("STRUCT",yytext,TYPE_KEYWORD,yylineno); 148 | return STRUCT; 149 | } 150 | 151 | "return" { 152 | yylval.type_node = init("RETURN",yytext,TYPE_KEYWORD,yylineno); 153 | return RETURN; 154 | } 155 | 156 | "if" { 157 | yylval.type_node = init("IF",yytext,TYPE_KEYWORD,yylineno); 158 | return IF; 159 | } 160 | 161 | "else" { 162 | yylval.type_node = init("ELSE",yytext,TYPE_KEYWORD,yylineno); 163 | return ELSE; 164 | } 165 | 166 | "while" { 167 | yylval.type_node = init("WHILE",yytext,TYPE_KEYWORD,yylineno); 168 | return WHILE; 169 | } 170 | 171 | {OCT} { 172 | yylval.type_node = init("INT",yytext,TYPE_OCT,yylineno); 173 | return INT; 174 | } 175 | 176 | {OCT_ERROR} { 177 | printf("Error type A at line %d: Illegal octal number \'%s\'\n", yylineno, yytext); 178 | errorLexFlag = 1; 179 | } 180 | 181 | {HEX} { 182 | yylval.type_node = init("INT",yytext,TYPE_HEX,yylineno); 183 | return INT; 184 | } 185 | 186 | {HEX_ERROR} { 187 | printf("Error type A at line %d: Illegal hexadecimal number \'%s\'\n", yylineno, yytext); 188 | errorLexFlag = 1; 189 | } 190 | 191 | {SFLOAT} { 192 | yylval.type_node = init("FLOAT",yytext,TYPE_SFLOAT,yylineno); 193 | return FLOAT; 194 | } 195 | 196 | {SFLOAT_ERROR} { 197 | printf("Error type A at line %d: Illegal floating point number \'%s\'\n", yylineno, yytext); 198 | errorLexFlag = 1; 199 | } 200 | 201 | {INT} { 202 | yylval.type_node = init("INT",yytext,TYPE_INT,yylineno); 203 | return INT; 204 | } 205 | 206 | {FLOAT} { 207 | yylval.type_node = init("FLOAT",yytext,TYPE_FLOAT,yylineno); 208 | return FLOAT; 209 | } 210 | 211 | {LINE} { 212 | yycolumn = 1; 213 | } 214 | 215 | {ID} { 216 | yylval.type_node = init("ID",yytext,TYPE_ID,yylineno); 217 | return ID; 218 | } 219 | 220 | 221 | . { 222 | printf("Error type A at line %d: Mysterious character \'%s\'\n" 223 | , yylineno, yytext); 224 | errorLexFlag = 1; 225 | } 226 | 227 | 228 | %% 229 | 230 | /* 231 | int main(int argc, char** argv){ 232 | if (argc > 1) 233 | if (!(yyin = fopen(argv[1], "r"))){ 234 | perror(argv[1]); 235 | return 1; 236 | } 237 | } 238 | while (yylex() != 0) ; 239 | return 0; 240 | } 241 | */ 242 | -------------------------------------------------------------------------------- /Project1/main.c: -------------------------------------------------------------------------------- 1 | #include "SyntaxTree.h" 2 | #include "parse.h" 3 | 4 | Node *tree; 5 | int errorLexFlag; 6 | int errorSyntaxFlag; 7 | 8 | int main(int argc, char** argv){ 9 | if(argc <= 1) 10 | return 1; 11 | FILE *f = fopen(argv[1], "r"); 12 | if(!f){ 13 | perror(argv[1]); 14 | return 1; 15 | } 16 | 17 | 18 | tree = NULL; 19 | errorLexFlag = 0; 20 | errorSyntaxFlag = 0; 21 | yylineno = 1; 22 | yyrestart(f); 23 | yyparse(); 24 | 25 | if(errorLexFlag == 0 && errorSyntaxFlag==0) 26 | traverseTree(tree); 27 | 28 | cleanTree(tree); 29 | return 0; 30 | 31 | } 32 | -------------------------------------------------------------------------------- /Project1/parse.h: -------------------------------------------------------------------------------- 1 | #ifndef PRASE_H 2 | #define PRASE_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "SyntaxTree.h" 12 | 13 | /* 14 | * lex & parse 15 | */ 16 | extern int yylex(void); 17 | extern int yyparse(void); 18 | extern void yyrestart(FILE*); 19 | extern void yyerror(char*); 20 | extern int yylineno; 21 | 22 | /* 23 | * SyntaxTree 24 | */ 25 | extern Node* tree; 26 | 27 | /* 28 | * main 29 | */ 30 | extern int errorLexFlag; 31 | extern int errorSyntaxFlag; 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /Project1/pretest/1.txt: -------------------------------------------------------------------------------- 1 | int main() 2 | { 3 | int i=1; 4 | int j=~i; 5 | } -------------------------------------------------------------------------------- /Project1/pretest/10.txt: -------------------------------------------------------------------------------- 1 | int main() 2 | { 3 | /* 4 | comment 5 | /* 6 | nested comment*/ 7 | */ 8 | */ 9 | int i = 1; 10 | } -------------------------------------------------------------------------------- /Project1/pretest/2.txt: -------------------------------------------------------------------------------- 1 | int main() 2 | { 3 | float a[10][2]; 4 | int i; 5 | a[5,3] = 1.5; 6 | if (a[1][2] == 0) i = 1 else i = 0; 7 | } -------------------------------------------------------------------------------- /Project1/pretest/3.txt: -------------------------------------------------------------------------------- 1 | int inc() 2 | { 3 | int i; 4 | i = i + 1; 5 | } -------------------------------------------------------------------------------- /Project1/pretest/4.txt: -------------------------------------------------------------------------------- 1 | struct Complex 2 | { 3 | float real, image; 4 | }; 5 | int main() 6 | { 7 | struct Complex x; 8 | y.image = 3.5; 9 | } -------------------------------------------------------------------------------- /Project1/pretest/5.txt: -------------------------------------------------------------------------------- 1 | int main() 2 | { 3 | int i = 0123; 4 | int j = 0x3F; 5 | } -------------------------------------------------------------------------------- /Project1/pretest/6.txt: -------------------------------------------------------------------------------- 1 | int main() 2 | { 3 | int i = 09; 4 | int j = 0x3G; 5 | } -------------------------------------------------------------------------------- /Project1/pretest/7.txt: -------------------------------------------------------------------------------- 1 | int main() 2 | { 3 | float i = 1.05e-4; 4 | } -------------------------------------------------------------------------------- /Project1/pretest/8.txt: -------------------------------------------------------------------------------- 1 | int main() 2 | { 3 | float i = 1.05e; 4 | } -------------------------------------------------------------------------------- /Project1/pretest/9.txt: -------------------------------------------------------------------------------- 1 | int main() 2 | { 3 | // line comment 4 | /* 5 | block comment 6 | */ 7 | int i =1; 8 | } -------------------------------------------------------------------------------- /Project1/pretest/README.txt: -------------------------------------------------------------------------------- 1 | 本目录下的10个测试样例为实验指导书中给出的样例,占最终成绩的一部分。 2 | 注:final test case不会为难大家。 -------------------------------------------------------------------------------- /Project1/report.md: -------------------------------------------------------------------------------- 1 | # Project1 实验报告 2 | ###### 151220136-许卓尔,151220168-赵文昊 3 | 4 | ## 实现功能 5 | 1. **识别词法错误(错误类型A)**:即出现C--词法中未定义的字符以及任何不符合C--词法单元定义的字符; 6 | 7 | 8 | 2. **识别语法错误(错误类型B)** 9 | 10 | 3. **附加要求** 11 | 12 | a. 识别八进制数和十六进制数; 13 | 14 | b. 识别指数形式的浮点数; 15 | 16 | c. 识别“//”和“/*…*/”形式的注释; 17 | 18 | 19 | ## 实现方法 20 | 21 | #### 识别词法错误(错误类型A) 22 | 23 | - C语言词法:编写正则表达式进行识别,初始化节点作为其yyval,并返回token; 24 | - 非C语言词法:通过元字符"."匹配,设置errorLexFlag,并输出词法错误信息; 25 | 26 | #### 识别语法错误(错误类型B) 27 | 28 | - 正确语法:利用附录A中C语言文法进行文法定义,利用Bison中内容、位置信息,创建语法树节点,并将推导出的符号作为子节点插入; 29 | - 错误语法:利用Bison的错误恢复机制,在产生式的高层增加error符号和错误恢复同步符号,书写error产生式检查语法错误,具体信实现可见syntax.y; 30 | 31 | #### 附加要求 32 | 33 | ##### 识别八进制数和十六进制数 34 | 35 | - 对于正确的八进制、十六进制数,编写正则表达式,并作为INT类型初始化节点; 36 | - 对于非法的八进制、十六进制数,同样编写正则表达式OCT_ERROR、HEX_ERROR,action中设置errorLexFlag,并输出词法错误信息:"非法的八进制、十六进制数"; 37 | 38 | ##### 识别指数形式的浮点数 39 | 40 | - 对于正确的指数浮点数,编写正则表达式,并作为FLOAT类型初始化节点; 41 | - 对于非法的指数浮点数,同样编写正则表达式SFLOAT_ERROR,action中设置errorLexFlag,并输出词法错误信息:"非法的指数浮点数"; 42 | 43 | ##### 识别“//”和“/*…*/”形式的注释 44 | 45 | 在lexical.l中定义C type、C++ type的注释规则,添加响应的响应函数,即什么都不做; 46 | 47 | ## 编译介绍 48 | 49 | ##### Makefile文件 50 | 51 | make parser | make 52 | > 对词法分析器、语法分析器进行编译并生成相应的parser程序; 53 | 54 | make lexical 55 | > 单独编译词法分析器; 56 | 57 | make syntax 58 | > 单独编译语法分析器; 59 | 60 | make clean 61 | > 对生成文件进行清理; 62 | 63 | ./parser ./pretest/1.txt 64 | > 对当前路径下pretest文件夹中的1.txt文件进行词法分析、语法分析; 65 | -------------------------------------------------------------------------------- /Project1/syntax.y: -------------------------------------------------------------------------------- 1 | %{ 2 | #include 3 | #include 4 | #include "parse.h" 5 | #include "SyntaxTree.h" 6 | %} 7 | 8 | /* declared types */ 9 | %union { 10 | int type_int; 11 | float type_float; 12 | double type_double; 13 | Node* type_node; 14 | } 15 | 16 | /* declared tokens */ 17 | %token INT 18 | %token FLOAT 19 | %token ID 20 | %token SEMI 21 | %token COMMA 22 | %token ASSIGNOP 23 | %token RELOP 24 | %token PLUS 25 | %token MINUS 26 | %token STAR 27 | %token DIV 28 | %token AND 29 | %token OR 30 | %token NOT 31 | %token DOT 32 | %token TYPE 33 | %token LP 34 | %token RP 35 | %token LB 36 | %token RB 37 | %token LC 38 | %token RC 39 | %token STRUCT 40 | %token RETURN 41 | %token IF 42 | %token ELSE 43 | %token WHILE 44 | 45 | /* declared non-terminals */ 46 | %type Program ExtDefList ExtDef ExtDecList 47 | %type Specifier StructSpecifier OptTag Tag 48 | %type VarDec FunDec VarList ParamDec 49 | %type CompSt StmtList Stmt 50 | %type DefList Def DecList Dec 51 | %type Exp Args 52 | 53 | %right ASSIGNOP 54 | %left OR 55 | %left AND 56 | %left RELOP 57 | %left PLUS 58 | %left STAR DIV 59 | %right NOT 60 | %left LP RP LB RB DOT 61 | 62 | %nonassoc LOWER_THAN_ELSE 63 | %nonassoc ELSE 64 | 65 | 66 | %% 67 | 68 | /* High-level Definitions */ 69 | Program : ExtDefList { 70 | $$ = init("Program", NULL, TYPE_NONTERMINAL, @$.first_line); 71 | insert($$, $1); 72 | tree = $$; 73 | } 74 | ; 75 | ExtDefList : ExtDef ExtDefList{ 76 | $$ = init("ExtDefList", NULL, TYPE_NONTERMINAL, @$.first_line); 77 | insert($$,$1);insert($$,$2); 78 | } 79 | | /* empty */{ $$=NULL; } 80 | ; 81 | ExtDef : Specifier ExtDecList SEMI{ 82 | $$ = init("ExtDef", NULL, TYPE_NONTERMINAL, @$.first_line); 83 | insert($$,$1);insert($$,$2);insert($$,$3); 84 | } 85 | | Specifier SEMI{ 86 | $$ = init("ExtDef", NULL, TYPE_NONTERMINAL, @$.first_line); 87 | insert($$,$1);insert($$,$2); 88 | } 89 | | Specifier FunDec CompSt{ 90 | $$ = init("ExtDef", NULL, TYPE_NONTERMINAL, @$.first_line); 91 | insert($$,$1);insert($$,$2);insert($$,$3); 92 | } 93 | | error SEMI { errorSyntaxFlag=2; } 94 | ; 95 | ExtDecList : VarDec{ 96 | $$ = init("ExtDecList", NULL, TYPE_NONTERMINAL, @$.first_line); 97 | insert($$, $1); 98 | } 99 | | VarDec COMMA ExtDecList{ 100 | $$ = init("ExtDecList", NULL, TYPE_NONTERMINAL, @$.first_line); 101 | insert($$,$1);insert($$,$2);insert($$,$3); 102 | } 103 | ; 104 | 105 | /* Specifiers */ 106 | Specifier : TYPE{ 107 | $$ = init("Specifier", NULL, TYPE_NONTERMINAL, @$.first_line); 108 | insert($$,$1); 109 | } 110 | | StructSpecifier{ 111 | $$ = init("StructSpecifier", NULL, TYPE_NONTERMINAL, @$.first_line); 112 | insert($$,$1); 113 | } 114 | ; 115 | StructSpecifier : STRUCT OptTag LC DefList RC{ 116 | $$ = init("StructSpecifier", NULL, TYPE_NONTERMINAL, @$.first_line); 117 | insert($$,$1);insert($$,$2);insert($$,$3);insert($$,$4);insert($$,$5); 118 | } 119 | | STRUCT Tag{ 120 | $$ = init("StructSpecifier", NULL, TYPE_NONTERMINAL, @$.first_line); 121 | insert($$,$1);insert($$,$2); 122 | } 123 | ; 124 | OptTag : ID{ 125 | $$ = init("OptTag", NULL, TYPE_NONTERMINAL, @$.first_line); 126 | insert($$,$1); 127 | } 128 | | /* empty */{ $$=NULL; } 129 | ; 130 | Tag : ID{ 131 | $$ = init("Tag", NULL, TYPE_NONTERMINAL, @$.first_line); 132 | insert($$,$1); 133 | } 134 | ; 135 | 136 | /* Declarators */ 137 | VarDec : ID{ 138 | $$ = init("VarDec", NULL, TYPE_NONTERMINAL, @$.first_line); 139 | insert($$,$1); 140 | } 141 | | VarDec LB INT RB{ 142 | $$ = init("VarDec", NULL, TYPE_NONTERMINAL, @$.first_line); 143 | insert($$,$1);insert($$,$2);insert($$,$3);insert($$,$4); 144 | } 145 | ; 146 | FunDec : ID LP VarList RP{ 147 | $$ = init("FunDec", NULL, TYPE_NONTERMINAL, @$.first_line); 148 | insert($$,$1);insert($$,$2);insert($$,$3);insert($$,$4); 149 | } 150 | | ID LP RP{ 151 | $$ = init("FunDec", NULL, TYPE_NONTERMINAL, @$.first_line); 152 | insert($$,$1);insert($$,$2);insert($$,$3); 153 | } 154 | | error RP{ errorSyntaxFlag=2; } 155 | ; 156 | VarList : ParamDec COMMA VarList{ 157 | $$ = init("VarList", NULL, TYPE_NONTERMINAL, @$.first_line); 158 | insert($$,$1);insert($$,$2);insert($$,$3); 159 | } 160 | | ParamDec{ 161 | $$ = init("VarList", NULL, TYPE_NONTERMINAL, @$.first_line); 162 | insert($$,$1); 163 | } 164 | ; 165 | ParamDec : Specifier VarDec{ 166 | $$ = init("ParamDec", NULL, TYPE_NONTERMINAL, @$.first_line); 167 | insert($$,$1);insert($$,$2); 168 | } 169 | ; 170 | 171 | /* Statements */ 172 | CompSt : LC DefList StmtList RC{ 173 | $$ = init("CompSt", NULL, TYPE_NONTERMINAL, @$.first_line); 174 | insert($$,$1);insert($$,$2);insert($$,$3);insert($$,$4); 175 | } 176 | | LC error RC{ errorSyntaxFlag=2; } 177 | ; 178 | StmtList : Stmt StmtList{ 179 | $$ = init("StmtList", NULL, TYPE_NONTERMINAL, @$.first_line); 180 | insert($$,$1);insert($$,$2); 181 | } 182 | | /* empty */{ $$ = NULL; } 183 | ; 184 | Stmt : Exp SEMI{ 185 | $$ = init("Stmt", NULL, TYPE_NONTERMINAL, @$.first_line); 186 | insert($$,$1);insert($$,$2); 187 | } 188 | | CompSt{ 189 | $$ = init("Stmt", NULL, TYPE_NONTERMINAL, @$.first_line); 190 | insert($$,$1); 191 | } 192 | | RETURN Exp SEMI{ 193 | $$ = init("Stmt", NULL, TYPE_NONTERMINAL, @$.first_line); 194 | insert($$,$1);insert($$,$2);insert($$,$3); 195 | } 196 | | IF LP Exp RP Stmt %prec LOWER_THAN_ELSE{ 197 | $$ = init("Stmt", NULL, TYPE_NONTERMINAL, @$.first_line); 198 | insert($$,$1);insert($$,$2);insert($$,$3); 199 | insert($$,$4);insert($$,$5); 200 | } 201 | | IF LP Exp RP Stmt ELSE Stmt{ 202 | $$ = init("Stmt", NULL, TYPE_NONTERMINAL, @$.first_line); 203 | insert($$,$1);insert($$,$2);insert($$,$3); 204 | insert($$,$4);insert($$,$5);insert($$,$6);insert($$,$7); 205 | } 206 | | WHILE LP Exp RP Stmt{ 207 | $$ = init("Stmt", NULL, TYPE_NONTERMINAL, @$.first_line); 208 | insert($$,$1);insert($$,$2);insert($$,$3); 209 | insert($$,$4);insert($$,$5); 210 | } 211 | | error SEMI { errorSyntaxFlag=2; } 212 | ; 213 | 214 | /* Local Definitions */ 215 | DefList : Def DefList{ 216 | $$ = init("DefList", NULL, TYPE_NONTERMINAL, @$.first_line); 217 | insert($$,$1);insert($$,$2); 218 | } 219 | | /* empty */{ $$=NULL; } 220 | ; 221 | Def : Specifier DecList SEMI{ 222 | $$ = init("Def", NULL, TYPE_NONTERMINAL, @$.first_line); 223 | insert($$,$1);insert($$,$2);insert($$,$3); 224 | } 225 | | error SEMI{ errorSyntaxFlag=2; } 226 | ; 227 | DecList : Dec{ 228 | $$ = init("DecList", NULL, TYPE_NONTERMINAL, @$.first_line); 229 | insert($$,$1); 230 | } 231 | | Dec COMMA DecList{ 232 | $$ = init("DecList", NULL, TYPE_NONTERMINAL, @$.first_line); 233 | insert($$,$1);insert($$,$2);insert($$,$3); 234 | } 235 | ; 236 | Dec : VarDec{ 237 | $$ = init("Dec", NULL, TYPE_NONTERMINAL, @$.first_line); 238 | insert($$,$1); 239 | } 240 | | VarDec ASSIGNOP Exp{ 241 | $$ = init("Dec", NULL, TYPE_NONTERMINAL, @$.first_line); 242 | insert($$,$1);insert($$,$2);insert($$,$3); 243 | } 244 | 245 | /* Expressions */ 246 | Exp : Exp ASSIGNOP Exp{ 247 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 248 | insert($$,$1);insert($$,$2);insert($$,$3); 249 | } 250 | | Exp AND Exp{ 251 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 252 | insert($$,$1); 253 | } 254 | | Exp OR Exp{ 255 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 256 | insert($$,$1);insert($$,$2);insert($$,$3); 257 | } 258 | | Exp RELOP Exp{ 259 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 260 | insert($$,$1);insert($$,$2);insert($$,$3); 261 | } 262 | | Exp PLUS Exp{ 263 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 264 | insert($$,$1);insert($$,$2);insert($$,$3); 265 | } 266 | | Exp MINUS Exp{ 267 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 268 | insert($$,$1);insert($$,$2);insert($$,$3); 269 | } 270 | | Exp STAR Exp{ 271 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 272 | insert($$,$1);insert($$,$2);insert($$,$3); 273 | } 274 | | Exp DIV Exp{ 275 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 276 | insert($$,$1);insert($$,$2);insert($$,$3); 277 | } 278 | | LP Exp RP{ 279 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 280 | insert($$,$1);insert($$,$2);insert($$,$3); 281 | } 282 | | MINUS Exp{ 283 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 284 | insert($$,$1);insert($$,$2); 285 | } 286 | | NOT Exp{ 287 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 288 | insert($$,$1);insert($$,$2); 289 | } 290 | | ID LP Args RP{ 291 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 292 | insert($$,$1);insert($$,$2);insert($$,$3);insert($$,$4); 293 | } 294 | | ID LP RP{ 295 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 296 | insert($$,$1);insert($$,$2);insert($$,$3); 297 | } 298 | | Exp LB Exp RB{ 299 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 300 | insert($$,$1);insert($$,$2);insert($$,$3);insert($$,$4); 301 | } 302 | | Exp DOT ID{ 303 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 304 | insert($$,$1);insert($$,$2);insert($$,$3); 305 | } 306 | | ID{ 307 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 308 | insert($$,$1); 309 | } 310 | | INT{ 311 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 312 | insert($$,$1); 313 | } 314 | | FLOAT{ 315 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 316 | insert($$,$1); 317 | } 318 | | Exp LB error RB{ errorSyntaxFlag=2; } 319 | ; 320 | Args : Exp COMMA Args{ 321 | $$ = init("Args", NULL, TYPE_NONTERMINAL, @$.first_line); 322 | insert($$,$1);insert($$,$2);insert($$,$3); 323 | } 324 | | Exp{ 325 | $$ = init("Args", NULL, TYPE_NONTERMINAL, @$.first_line); 326 | insert($$,$1); 327 | } 328 | ; 329 | 330 | /* Comments */ 331 | 332 | %% 333 | 334 | 335 | void yyerror(char* msg){ 336 | if(errorLexFlag==0) 337 | fprintf(stderr, "Error type B at Line %d: %s\n",yylineno,msg); 338 | } 339 | -------------------------------------------------------------------------------- /Project2/HashTable.c: -------------------------------------------------------------------------------- 1 | #include "HashTable.h" 2 | 3 | Entry *hashTable[HASH_SIZE]; 4 | 5 | unsigned int hashPJW(char *name){ 6 | unsigned int val=0, i; 7 | for(; *name; ++name){ 8 | val = (val<<2)+*name; 9 | if(i= val& ~0x3fff) 10 | val = (val^(i>>12))&0x3fff; 11 | } 12 | return val; 13 | } 14 | 15 | void initTable(){ 16 | int i=0; 17 | for(;iname)%HASH_SIZE; 29 | 30 | Entry *curEntry = (Entry *)malloc(sizeof(Entry)); 31 | curEntry->next = hashTable[hashValue]; 32 | hashTable[hashValue] = curEntry; 33 | 34 | curEntry->type = value->type; 35 | curEntry->name = value->name; 36 | 37 | return 1; 38 | } 39 | 40 | int funcInsertTable(Function func){ 41 | if(hashTable==NULL || func==NULL) 42 | return 0; 43 | 44 | unsigned int hashValue = 0; 45 | hashValue = hashPJW(func->name)%HASH_SIZE; 46 | 47 | Entry *curEntry = (Entry *)malloc(sizeof(Entry)); 48 | curEntry->next = hashTable[hashValue]; 49 | hashTable[hashValue] = curEntry; 50 | 51 | curEntry->type = (Type)malloc(sizeof(struct Function_)); 52 | curEntry->type->kind = FUNCTION; 53 | curEntry->type->u.function = func; 54 | curEntry->name = func->name; 55 | 56 | FieldList param = func->param; 57 | int flag; 58 | 59 | while(param != NULL){ 60 | flag = varInsertCheck(param); 61 | if(flag == ERROR_REDEFINE){ 62 | printf("Error type 3 at Line %d: Redefine variable \"%s\"\n",func->line, param->name); 63 | } 64 | else{ 65 | varInsertTable(param); 66 | } 67 | param = param->tail; 68 | } 69 | 70 | return 1; 71 | } 72 | 73 | int structInsertTable(Structure structure){ 74 | if(hashTable==NULL || structure==NULL) 75 | return 0; 76 | 77 | unsigned int hashValue = 0; 78 | hashValue = hashPJW(structure->name)%HASH_SIZE; 79 | 80 | Entry *curEntry = (Entry *)malloc(sizeof(Entry)); 81 | curEntry->next = hashTable[hashValue]; 82 | hashTable[hashValue] = curEntry; 83 | 84 | curEntry->type = (Type)malloc(sizeof(struct Structure_)); 85 | curEntry->type->kind = STRUCTURE; 86 | curEntry->type->u.structure = structure; 87 | curEntry->name = structure->name; 88 | 89 | return 1; 90 | } 91 | 92 | int varInsertCheck(FieldList var){ 93 | if(var==NULL) 94 | return BINGO; 95 | 96 | unsigned int hashValue = hashPJW(var->name)%HASH_SIZE; 97 | Entry *tmp = hashTable[hashValue]; 98 | for(;tmp!=NULL;tmp=tmp->next){ 99 | if(tmp->type->kind!=FUNCTION&&strcmp(tmp->name, var->name)==0) 100 | return ERROR_REDEFINE; 101 | else 102 | continue; 103 | } 104 | } 105 | 106 | int funcInsertCheck(Function func){ 107 | 108 | if(hashTable==NULL || func==NULL) 109 | return BINGO; 110 | 111 | unsigned int hashValue = hashPJW(func->name)%HASH_SIZE; 112 | Entry *tmp = hashTable[hashValue]; 113 | for(;tmp!=NULL;tmp=tmp->next){ 114 | if(tmp->type->kind != FUNCTION) 115 | continue; 116 | Function tmpFunc = tmp->type->u.function; 117 | if(strcmp(tmpFunc->name,func->name)!=0) 118 | continue; 119 | if((valueEqual(tmpFunc->param,func->param)!=0) 120 | || (typeEqual(tmpFunc->retype,func->retype)!=0)) 121 | return ERROR_DECLARATION_CONFLICT; 122 | if(tmpFunc->isDefined!=0){ 123 | return ERROR_REDEFINE; 124 | } 125 | else{ 126 | tmpFunc->isDefined = func->isDefined; 127 | return FUNC_IS_DECLARED; 128 | } 129 | } 130 | return BINGO; 131 | } 132 | 133 | int structInsertCheck(Structure structure){ 134 | if(hashTable==NULL || structure==NULL) 135 | return BINGO; 136 | 137 | unsigned int hashValue = hashPJW(structure->name)%HASH_SIZE; 138 | Entry *tmp = hashTable[hashValue]; 139 | for(;tmp!=NULL;tmp=tmp->next){ 140 | if(tmp->type->kind!=FUNCTION&&strcmp(tmp->name,structure->name)==0) 141 | return ERROR_REDEFINE; 142 | else 143 | continue; 144 | } 145 | return BINGO; 146 | } 147 | 148 | Type getTable(char *name){ 149 | 150 | if(hashTable==NULL || name==NULL) 151 | return NULL; 152 | 153 | unsigned int hashValue = hashPJW(name)%HASH_SIZE; 154 | 155 | Entry *tmp = hashTable[hashValue]; 156 | for(;tmp!=NULL;tmp=tmp->next){ 157 | if(strcmp(tmp->name,name)==0) 158 | return tmp->type; 159 | } 160 | 161 | // Error: No such name 162 | return NULL; 163 | } 164 | 165 | void checkFuncDeclaration(){ 166 | int i=0; 167 | Entry *itor = NULL; 168 | for(;itype!=NULL&&itor->type->kind==FUNCTION&&itor->type->u.function->isDefined==0){ 173 | printf("Error type 18 at Line %d: Undefined function \"%s\".\n",itor->type->u.function->line,itor->type->u.function->name); 174 | } 175 | itor = itor->next; 176 | } 177 | } 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /Project2/HashTable.h: -------------------------------------------------------------------------------- 1 | #ifndef HASHTABLE_H 2 | #define HASHTABLE_H 3 | 4 | #include "SyntaxTree.h" 5 | #include "Semantic.h" 6 | #include 7 | 8 | #define HASH_SIZE 1024 9 | 10 | typedef struct Entry_{ 11 | char *name; 12 | Type type; 13 | struct Entry_ *next; 14 | }Entry; 15 | 16 | extern Entry *hashTable[HASH_SIZE]; 17 | 18 | void initTable(); 19 | Type getTable(char *name); 20 | 21 | int varInsertTable(FieldList value); 22 | int varInsertCheck(FieldList var); 23 | 24 | int funcInsertTable(Function func); 25 | int funcInsertCheck(Function func); 26 | 27 | int structInsertTable(Structure structure); 28 | int structInsertCheck(Structure structure); 29 | 30 | void checkFuncDeclaration(); 31 | #endif 32 | -------------------------------------------------------------------------------- /Project2/Makefile: -------------------------------------------------------------------------------- 1 | parser: 2 | bison -d syntax.y 3 | flex lexical.l 4 | gcc -c lex.yy.c -o lex.o 5 | gcc main.c syntax.tab.c SyntaxTree.c HashTable.c Semantic.c lex.o -lfl -ly -o parser 6 | 7 | lexical: 8 | bison -d syntax.y 9 | flex lexical.l 10 | 11 | syntax: 12 | bison -d syntax.y 13 | 14 | clean: 15 | rm lex.yy.c lex.o syntax.tab.c syntax.tab.h parser 16 | 17 | remake: 18 | make clean 19 | make 20 | 21 | test: 22 | ./parser ./pretest/1.txt 23 | ./parser ./pretest/2.txt 24 | ./parser ./pretest/3.txt 25 | ./parser ./pretest/4.txt 26 | ./parser ./pretest/5.txt 27 | ./parser ./pretest/6.txt 28 | ./parser ./pretest/7.txt 29 | ./parser ./pretest/8.txt 30 | ./parser ./pretest/9.txt 31 | ./parser ./pretest/10.txt 32 | ./parser ./pretest/11.txt 33 | ./parser ./pretest/12.txt 34 | ./parser ./pretest/13.txt 35 | ./parser ./pretest/14.txt 36 | ./parser ./pretest/15.txt 37 | ./parser ./pretest/16.txt 38 | ./parser ./pretest/17.txt 39 | ./parser ./pretest/18.txt 40 | ./parser ./pretest/19.txt 41 | ./parser ./pretest/20.txt 42 | ./parser ./pretest/21.txt 43 | ./parser ./pretest/22.txt 44 | ./parser ./pretest/23.txt 45 | -------------------------------------------------------------------------------- /Project2/Semantic.c: -------------------------------------------------------------------------------- 1 | #include "Semantic.h" 2 | #include "SyntaxTree.h" 3 | #include "HashTable.h" 4 | #include 5 | 6 | int typeEqual(Type lhs, Type rhs){ 7 | if(lhs==NULL && rhs==NULL) 8 | return 0; 9 | if(lhs==NULL || rhs==NULL) 10 | return 1; 11 | if(lhs->kind != rhs->kind) 12 | return 2; 13 | 14 | if(lhs->kind == BASIC){ 15 | if(lhs->u.basic == rhs->u.basic) 16 | return 0; 17 | else 18 | return 3; 19 | } 20 | else if(lhs->kind == ARRAY){ 21 | return typeEqual(lhs->u.array.elem, rhs->u.array.elem); 22 | } 23 | else if(lhs->kind == STRUCTURE){ 24 | return structEqual(lhs->u.structure, rhs->u.structure); 25 | } 26 | else if(lhs->kind == FUNCTION){ 27 | // It doesn't need to judge whether functions equal. 28 | exit(-2); 29 | } 30 | 31 | return 0; 32 | } 33 | 34 | int structEqual(Structure lhs, Structure rhs){ 35 | int flag = 0; 36 | FieldList lDomain = lhs->domain; 37 | FieldList rDomain = rhs->domain; 38 | while(lDomain!=NULL && rDomain!=NULL){ 39 | flag = typeEqual(lDomain->type, rDomain->type); 40 | if(flag != 0) 41 | return 4; 42 | lDomain = lDomain->tail; 43 | rDomain = rDomain->tail; 44 | } 45 | if(lDomain==NULL && rDomain==NULL) 46 | return 0; 47 | else 48 | return 4; 49 | } 50 | 51 | int valueEqual(FieldList lhs, FieldList rhs){ 52 | if(lhs==NULL && rhs==NULL) 53 | return 0; 54 | if(lhs==NULL || rhs==NULL) 55 | return 1; 56 | if(valueEqual(lhs->tail,rhs->tail)!=0) 57 | return 2; 58 | return typeEqual(lhs->type, rhs->type); 59 | } 60 | 61 | /* High-level Definitions */ 62 | void Program(Node* root){ 63 | //printf("%s\n",root->identifier); 64 | // ExtDefList 65 | 66 | ExtDefList(root->child); 67 | checkFuncDeclaration(); 68 | } 69 | 70 | void ExtDefList(Node* n){ 71 | if(n==NULL) 72 | return; 73 | //printf("%s\n",n->identifier); 74 | 75 | // ExtDefList -> NULL 76 | if(n->child == NULL) 77 | return; 78 | 79 | // ExtDef ExtDefList 80 | ExtDef(n->child); 81 | ExtDefList(n->child->sibling); 82 | } 83 | 84 | /* Global Variable */ 85 | void ExtDef(Node *n){ 86 | if(n==NULL) 87 | return; 88 | //printf("%s\n",n->identifier); 89 | 90 | Node* child = n->child; 91 | Type type; 92 | type = Specifier(child); 93 | child = child->sibling; 94 | 95 | // Specifier SEMI 96 | if(strcmp(child->identifier,"SEMI")==0) 97 | return; 98 | // Specifier ExtDecList SEMI 99 | else if(strcmp(child->identifier,"ExtDecList")==0) 100 | ExtDecList(child,type); 101 | // Specifier FunDec CompSt|SEMI 102 | else if(strcmp(child->identifier,"FunDec")==0){ 103 | Function func=FunDec(child,type); 104 | 105 | child = child->sibling; 106 | int i; 107 | // Specifier FunDec CompSt 108 | if(strcmp(child->identifier,"CompSt")==0){ 109 | if(func==NULL) 110 | return; 111 | func->isDefined = 1; 112 | int flag=funcInsertCheck(func); 113 | if(flag==ERROR_REDEFINE) 114 | printf("Error type 4 at Line %d: Redefined function \"%s\"\n",func->line,func->name); 115 | else if(flag==ERROR_DECLARATION_CONFLICT) 116 | printf("Error type 19 at Line %d: Inconsistent declaration of function \"%s\"\n",func->line,func->name); 117 | else if(flag!=FUNC_IS_DECLARED) 118 | funcInsertTable(func); 119 | CompSt(child,type); 120 | } 121 | // Specifier FunDec CompSt|SEMI 122 | else if(strcmp(child->identifier,"SEMI")==0){ 123 | if(func==NULL) 124 | return; 125 | func->isDefined = 0; 126 | int flag=funcInsertCheck(func); 127 | if(flag==ERROR_REDEFINE) 128 | printf("Error type 4 at Line %d: Redefined function \"%s\"\n",func->line,func->name); 129 | else if(flag==ERROR_DECLARATION_CONFLICT) 130 | printf("Error type 19 at Line %d: Inconsistent declaration of function \"%s\"\n",func->line,func->name); 131 | else if(flag!=FUNC_IS_DECLARED) 132 | funcInsertTable(func); 133 | } 134 | } 135 | else 136 | return; 137 | } 138 | 139 | void ExtDecList(Node *n, Type type){ 140 | if(n==NULL) 141 | return; 142 | //printf("%s\n",n->identifier); 143 | 144 | Node *child = n->child; 145 | if(child == NULL) 146 | return; 147 | VarDec(child, type, FROM_VARIABLE); 148 | 149 | // VarDec COMMA ExtDecList 150 | child = child->sibling; 151 | if(child == NULL) 152 | return; 153 | child = child->sibling; 154 | if(child == NULL) 155 | return; 156 | ExtDecList(child, type); 157 | } 158 | 159 | /* Specifiers */ 160 | Type Specifier(Node *n){ 161 | if(n==NULL) 162 | return NULL; 163 | //printf("%s\n",n->identifier); 164 | 165 | Node *child = n->child; 166 | if(child == NULL) 167 | exit(-1); 168 | 169 | Type type; 170 | 171 | // TYPE 172 | if(strcmp(child->identifier,"TYPE")==0){ 173 | type = (Type)malloc(sizeof(struct Type_)); 174 | type->kind = BASIC; 175 | if(strcmp(child->value,"int")==0){ 176 | type->u.basic = TYPE_INT; 177 | } 178 | else if(strcmp(child->value, "float")==0){ 179 | type->u.basic = TYPE_FLOAT; 180 | } 181 | else 182 | exit(-1); 183 | return type; 184 | } 185 | // StructSpecifier 186 | else if(strcmp(child->identifier, "StructSpecifier")==0){ 187 | return type = StructSpecifier(child); 188 | } 189 | else 190 | exit(-1); 191 | } 192 | 193 | Type StructSpecifier(Node *n){ 194 | if(n==NULL) 195 | return NULL; 196 | //printf("%s\n",n->identifier); 197 | 198 | Node *child = n->child; 199 | if(child == NULL) 200 | exit(-1); 201 | 202 | child = child->sibling; 203 | 204 | // STRUCT OptTag LC DefList RC 205 | if(strcmp(child->identifier, "OptTag")==0){ 206 | Type type = (Type)malloc(sizeof(struct Type_)); 207 | type->kind = STRUCTURE; 208 | Structure structure = (Structure)malloc(sizeof(struct Structure_)); 209 | type->u.structure = structure; 210 | 211 | // OptTag -> NULL 212 | if(child->child == NULL){ 213 | structure->name = NULL; 214 | } 215 | // OptTag -> ID 216 | else{ 217 | structure->name = child->child->value; 218 | } 219 | 220 | child = child->sibling->sibling; 221 | structure->domain = DefList(child,FROM_FIELD); 222 | if(structure->name!=NULL){ 223 | int flag = structInsertCheck(structure); 224 | if(flag == ERROR_REDEFINE){ 225 | printf("Error type 16 at Line %d: Duplicated name \"%s\".\n",n->child->line, structure->name); 226 | return NULL; 227 | } 228 | else{ 229 | structInsertTable(structure); 230 | } 231 | } 232 | return type; 233 | } 234 | // STRUCT Tag 235 | else if(strcmp(child->identifier, "Tag")==0){ 236 | Type result = getTable(child->child->value); 237 | if(result==NULL || result->kind!=STRUCTURE || 238 | strcmp(result->u.structure->name,child->child->value)!=0){ 239 | printf("Error type 17 at Line %d: Undefined structure \"%s\".\n",n->child->line, child->child->value); 240 | } 241 | return result; 242 | } 243 | } 244 | 245 | /* Declarators */ 246 | FieldList VarDec(Node *n, Type type, int from){ 247 | if(n==NULL) 248 | return NULL; 249 | //printf("%s\n",n->identifier); 250 | 251 | Node *child = n->child; 252 | FieldList varDec=NULL; 253 | if(child == NULL) 254 | return NULL; 255 | 256 | // ID 257 | if(strcmp(child->identifier, "ID")==0){ 258 | varDec = (FieldList)malloc(sizeof(struct FieldList_)); 259 | varDec->name = child->value; 260 | varDec->type = type; 261 | varDec->tail = NULL; 262 | if(from==FROM_PARAM) 263 | return varDec; 264 | int flag = varInsertCheck(varDec); 265 | if(flag==ERROR_REDEFINE){ 266 | if(from==FROM_VARIABLE){ 267 | printf("Error type 3 at Line %d: Redefined variable \"%s\".\n",child->line, varDec->name); 268 | } 269 | else{ 270 | printf("Error type 15 at Line %d: Redefined field \"%s\".\n",child->line, varDec->name); 271 | } 272 | return NULL; 273 | } 274 | else 275 | varInsertTable(varDec); 276 | return varDec; 277 | } 278 | // VarDec LB INT RB 279 | else if(strcmp(child->identifier, "VarDec")==0){ 280 | 281 | Type varDec = (Type)malloc(sizeof(struct Type_)); 282 | varDec->kind = ARRAY; 283 | varDec->u.array.size = (int)strtol(child->sibling->sibling->value,NULL,10); 284 | varDec->u.array.elem = type; 285 | 286 | return VarDec(child, varDec, from); 287 | } 288 | } 289 | 290 | Function FunDec(Node *n, Type type){ 291 | if(n==NULL) 292 | return NULL; 293 | //printf("%s\n",n->identifier); 294 | 295 | Node *child = n->child; 296 | Function func = (Function)malloc(sizeof(struct Function_)); 297 | func->name = child->value; 298 | func->isDefined = 0; 299 | func->param = NULL; 300 | func->retype = type; 301 | func->line = child->line; 302 | 303 | child = child->sibling->sibling; 304 | // ID LP VarList RP 305 | if(strcmp(child->identifier,"VarList")==0){ 306 | func->param = VarList(child); 307 | } 308 | return func; 309 | } 310 | 311 | FieldList VarList(Node *n){ 312 | if(n==NULL) 313 | return NULL; 314 | //printf("%s\n",n->identifier); 315 | 316 | Node *child = n->child; 317 | // ParamDec 318 | FieldList varList = ParamDec(child); 319 | child = child->sibling; 320 | 321 | // ParamDec COMMA VarList ? 322 | if(child != NULL){ 323 | child = child->sibling; 324 | varList->tail = VarList(child); 325 | } 326 | 327 | return varList; 328 | } 329 | 330 | FieldList ParamDec(Node *n){ 331 | if(n==NULL) 332 | return NULL; 333 | //printf("%s\n",n->identifier); 334 | 335 | Node *child = n->child; 336 | // Specifier VarDec 337 | Type type = Specifier(child); 338 | child = child->sibling; 339 | FieldList paramDec = VarDec(child, type, FROM_PARAM); 340 | return paramDec; 341 | } 342 | 343 | /* Statements */ 344 | void CompSt(Node *n, Type retype){ 345 | if(n==NULL) 346 | return; 347 | //printf("%s\n",n->identifier); 348 | 349 | Node *child = n->child; 350 | // LC DefList StmtList RC 351 | child = child->sibling; 352 | DefList(child, FROM_VARIABLE); 353 | child = child->sibling; 354 | StmtList(child, retype); 355 | } 356 | 357 | void StmtList(Node *n, Type retype){ 358 | if(n==NULL) 359 | return; 360 | //printf("%s\n",n->identifier); 361 | 362 | Node *child = n->child; 363 | // StmtList -> NULL 364 | if(child == NULL) 365 | return; 366 | 367 | // Stmt StmtList 368 | Stmt(child, retype); 369 | StmtList(child->sibling, retype); 370 | } 371 | 372 | void Stmt(Node *n, Type retype){ 373 | if(n==NULL) 374 | return; 375 | //printf("%s\n",n->identifier); 376 | 377 | Node *child = n->child; 378 | // Exp SEMI 379 | if(strcmp(child->identifier, "Exp")==0){ 380 | Exp(child); 381 | } 382 | // CompSt 383 | else if(strcmp(child->identifier, "CompSt")==0){ 384 | CompSt(child, retype); 385 | } 386 | // RETURN Exp SEMI 387 | else if(strcmp(child->identifier, "RETURN")==0){ 388 | Type expType=Exp(child->sibling); 389 | if(expType==NULL||retype==NULL) return; 390 | if(typeEqual(retype,expType)!=0){ 391 | printf("Error type 8 at Line %d: Type mismatched for return.\n",child->line); 392 | } 393 | } 394 | // IF LP Exp Stmt (ELSE Stmt)? 395 | else if(strcmp(child->identifier, "IF")==0){ 396 | child = child->sibling->sibling; 397 | Type expType=Exp(child); 398 | child = child->sibling->sibling; 399 | Stmt(child, retype); 400 | child = child->sibling; 401 | if(child == NULL) 402 | return; 403 | child = child->sibling; 404 | Stmt(child, retype); 405 | } 406 | // WHILE LP Exp RP Stmt 407 | else if(strcmp(child->identifier, "WHILE")==0){ 408 | child = child->sibling->sibling; 409 | Exp(child); 410 | child = child->sibling->sibling; 411 | Stmt(child, retype); 412 | } 413 | } 414 | 415 | /* Local Definitions */ 416 | FieldList DefList(Node *n, int from){ 417 | if(n==NULL) 418 | return NULL; 419 | //printf("%s\n",n->identifier); 420 | 421 | Node *child = n->child; 422 | FieldList defList = NULL; 423 | 424 | // DefList -> NULL 425 | if(child==NULL) 426 | return defList; 427 | // Def DefList 428 | defList = Def(child, from); 429 | 430 | if(defList == NULL){ 431 | defList = DefList(child->sibling, from); 432 | return defList; 433 | } 434 | 435 | FieldList tmp = defList; 436 | while(tmp->tail != NULL) 437 | tmp = tmp->tail; 438 | tmp->tail = DefList(child->sibling, from); 439 | return defList; 440 | } 441 | 442 | FieldList Def(Node *n, int from){ 443 | if(n==NULL) 444 | return NULL; 445 | //printf("%s\n",n->identifier); 446 | 447 | Node *child = n->child; 448 | // Specifier DecList SEMI 449 | FieldList def = NULL; 450 | Type type = Specifier(child); 451 | child = child->sibling; 452 | def = DecList(child, type, from); 453 | return def; 454 | } 455 | 456 | FieldList DecList(Node *n, Type type, int from){ 457 | if(n==NULL) 458 | return NULL; 459 | //printf("%s\n",n->identifier); 460 | 461 | Node *child = n->child; 462 | FieldList decList = NULL; 463 | 464 | decList = Dec(child, type, from); 465 | child = child->sibling; 466 | 467 | // Dec 468 | if(child == NULL) 469 | return decList; 470 | // Dec COMMA DecList 471 | child = child->sibling; 472 | if(decList==NULL){ 473 | decList = DecList(child, type, from); 474 | } 475 | else{ 476 | FieldList tmpDec = decList; 477 | while(tmpDec->tail != NULL) 478 | tmpDec = tmpDec->tail; 479 | tmpDec->tail = DecList(child, type, from); 480 | } 481 | return decList; 482 | } 483 | 484 | FieldList Dec(Node *n, Type type, int from){ 485 | if(n==NULL) 486 | return NULL; 487 | //printf("%s\n",n->identifier); 488 | 489 | Node *child = n->child; 490 | FieldList dec = VarDec(child, type, from); 491 | 492 | child = child->sibling; 493 | // VarDec 494 | if(child == NULL) 495 | return dec; 496 | // VarDec ASSIGNOP Exp 497 | if(from == FROM_FIELD){ 498 | printf("Error type 15 at Line %d: be initialized field \"%s\"\n",child->line, dec->name); 499 | return NULL; 500 | } 501 | child = child->sibling; 502 | Type expType = Exp(child); 503 | if(typeEqual(type, expType)!=0){ 504 | printf("Error type 5 at Line %d: The type mismatched\n",child->line); 505 | return NULL; 506 | } 507 | return dec; 508 | } 509 | 510 | /* Expressions */ 511 | Type Exp(Node *n){ 512 | if(n==NULL) 513 | return NULL; 514 | //printf("%s\n",n->identifier); 515 | 516 | Node *child = n->child; 517 | //printf("%s\n",child->identifier); 518 | if(strcmp(child->identifier,"LP")==0){ 519 | //Exp->LP Exp RP 520 | child = child->sibling; 521 | return Exp(child); 522 | } 523 | else if(strcmp(child->identifier,"MINUS")==0){ 524 | //Exp->MINUS Exp 525 | child = child->sibling; 526 | Type type = NULL; 527 | type = Exp(child); 528 | if(type==NULL) 529 | return NULL; 530 | if(type->kind!=BASIC){ 531 | printf("Error type 7 at Line %d: Operands type mismatched\n", child->line); 532 | return NULL; 533 | } 534 | Type rtn = (Type)malloc(sizeof(struct Type_)); 535 | memcpy(rtn, type, sizeof(struct Type_)); 536 | rtn->assign = RIGHT; 537 | return rtn; 538 | } 539 | else if(strcmp(child->identifier,"NOT")==0){ 540 | //Exp->NOT Exp 541 | child = child->sibling; 542 | Type type = NULL; 543 | type = Exp(child); 544 | if(type==NULL) 545 | return NULL; 546 | if(type->kind!=BASIC || type->u.basic!=TYPE_INT){ 547 | printf("Error type 7 at Line %d: Operands type mismatched\n", child->line); 548 | return NULL; 549 | } 550 | Type rtn = (Type)malloc(sizeof(struct Type_)); 551 | memcpy(rtn, type, sizeof(struct Type_)); 552 | rtn->assign = RIGHT; 553 | return rtn; 554 | } 555 | else if(strcmp(child->identifier,"ID")==0){ 556 | if(child->sibling==NULL){ 557 | //Exp->ID 558 | Type value = getTable(child->value); //判断是否定义过 559 | if(value==NULL||value->kind==FUNCTION){ 560 | printf("Error type 1 at Line %d: Undefined variable \"%s\".\n", child->line, child->value); 561 | return NULL; 562 | } 563 | Type rtn = (Type)malloc(sizeof(struct Type_)); 564 | memcpy(rtn, value, sizeof(struct Type_)); 565 | rtn->assign = BOTH; 566 | return rtn; 567 | } 568 | else{ 569 | //Exp->ID LP RP | ID LP Args RP 570 | Type func = getTable(child->value); //判断是否定义过 571 | if(func==NULL){ 572 | printf("Error type 2 at Line %d: Undefined function \"%s\".\n", child->line, child->value); 573 | return NULL; 574 | } 575 | if(func->kind!=FUNCTION){ 576 | printf("Error type 11 at Line %d: \"%s\" is not a function.\n", child->line, child->value); 577 | return NULL; 578 | } 579 | if(func->u.function->isDefined==0){ 580 | printf("Error type 2 at Line %d: Undefined function \"%s\".\n", child->line, child->value); 581 | return NULL; 582 | } 583 | FieldList param = func->u.function->param; 584 | child = child->sibling->sibling; 585 | if(strcmp(child->identifier,"RP")==0){ 586 | if(param!=NULL){ 587 | printf("Error type 9 at Line %d: Function \"%s\" is not applicable for arguments.\n", child->line, func->u.function->name); 588 | return NULL; 589 | } 590 | } 591 | else{ 592 | if(Args(child,param)!=0){ //比较两个类型是否匹配 593 | printf("Error type 9 at Line %d: Function \"%s\" is not applicable for arguments.\n", child->line, func->u.function->name); 594 | return NULL; 595 | } 596 | } 597 | Type rtn = (Type)malloc(sizeof(struct Type_)); 598 | memcpy(rtn, func->u.function->retype, sizeof(struct Type_)); 599 | rtn->assign = RIGHT; 600 | return rtn; 601 | } 602 | } 603 | else if(strcmp(child->identifier,"INT")==0){ 604 | //Exp->INT 605 | Type type = (Type)malloc(sizeof(struct Type_)); 606 | type->kind = BASIC; 607 | type->u.basic = TYPE_INT; 608 | type->assign = RIGHT; 609 | return type; 610 | } 611 | else if(strcmp(child->identifier,"FLOAT")==0){ 612 | //Exp->FLOAT 613 | Type type = (Type)malloc(sizeof(struct Type_)); 614 | type->kind = BASIC; 615 | type->u.basic = TYPE_FLOAT; 616 | type->assign = RIGHT; 617 | return type; 618 | } 619 | else if(strcmp(child->identifier,"Exp")==0){ 620 | //Exp->Exp ... 621 | if(strcmp(child->sibling->identifier,"ASSIGNOP")==0 ){ 622 | //Exp->Exp ASSIGNOP Exp 623 | 624 | //判断表达式左边是否为左值 625 | Type lhs = Exp(child); 626 | Type rhs = Exp(child->sibling->sibling); 627 | if(lhs==NULL || rhs==NULL) 628 | return NULL; 629 | if(lhs->assign==RIGHT){ 630 | printf("Error type 6 at Line %d: The left-hand side of an assignment must be a variable.\n", child->line); 631 | return NULL; 632 | } 633 | //判断赋值号两边表达式是否类型匹配 634 | if(typeEqual(lhs, rhs)==0){ 635 | return lhs; 636 | } 637 | else{ 638 | printf("Error type 5 at Line %d: Type mismatched for assignment.\n", child->line); 639 | return NULL; 640 | } 641 | } 642 | else if(strcmp(child->sibling->identifier,"AND")==0 || 643 | strcmp(child->sibling->identifier,"OR")==0 || 644 | strcmp(child->sibling->identifier,"RELOP")==0 || 645 | strcmp(child->sibling->identifier,"PLUS")==0 || 646 | strcmp(child->sibling->identifier,"MINUS")==0 || 647 | strcmp(child->sibling->identifier,"STAR")==0 || 648 | strcmp(child->sibling->identifier,"DIV")==0){ 649 | //Exp->Exp AND|OR|RELOP|PLUS|MINUS|STAR|DIV Exp 650 | Type lhs = Exp(child); 651 | Type rhs = Exp(child->sibling->sibling); 652 | 653 | if(lhs==NULL||rhs==NULL) 654 | return NULL; 655 | if(lhs->kind==BASIC && rhs->kind==BASIC && 656 | lhs->u.basic==rhs->u.basic){ 657 | Type rtn = (Type)malloc(sizeof(struct Type_)); 658 | memcpy(rtn, lhs, sizeof(struct Type_)); 659 | rtn->assign = RIGHT; 660 | return rtn; 661 | } 662 | else{ 663 | printf("Error type 7 at Line %d: Type mismatched for operands.\n", child->line); 664 | return NULL; 665 | } 666 | } 667 | else if(strcmp(child->sibling->identifier,"LB")==0){ 668 | //Exp->Exp LB Exp RB 669 | Type array=Exp(child); 670 | 671 | if(array==NULL) 672 | return NULL; 673 | if(array->kind!=ARRAY){ 674 | printf("Error type 10 at Line %d: \"%s\" is not an array.\n", child->line, child->child->value); 675 | return NULL; 676 | } 677 | child = child->sibling->sibling; 678 | Type arrayNumber = Exp(child); 679 | if(arrayNumber==NULL) 680 | return NULL; 681 | if(arrayNumber->kind!=BASIC || arrayNumber->u.basic!=TYPE_INT){ 682 | printf("Error type 12 at Line %d: \"%s\" is not an integer.\n", child->line , child->child->value); 683 | return NULL; 684 | } 685 | Type rtn = (Type)malloc(sizeof(struct Type_)); 686 | memcpy(rtn, array->u.array.elem, sizeof(struct Type_)); 687 | rtn->assign = BOTH; 688 | return rtn; 689 | } 690 | else if(strcmp(child->sibling->identifier,"DOT")==0){ 691 | //Exp->Exp DOT ID 692 | Type structure = Exp(child); 693 | if(structure==NULL) 694 | return NULL; 695 | if(structure->kind!=STRUCTURE){ 696 | printf("Error type 13 at Line %d: Illegal use of \".\".\n", child->line); 697 | return NULL; 698 | } 699 | FieldList structDomain = structure->u.structure->domain; 700 | child = child->sibling->sibling; 701 | while(structDomain!=NULL){ 702 | if(strcmp(structDomain->name, child->value) ==0){ 703 | Type rtn = (Type)malloc(sizeof(struct Type_)); 704 | memcpy(rtn, structDomain->type, sizeof(struct Type_)); 705 | rtn->assign = BOTH; 706 | return rtn; 707 | } 708 | structDomain = structDomain->tail; //可能有错,找下一个 709 | } 710 | printf("Error type 14 at Line %d: Non-existent field \"%s\".\n", child->line, child->value); 711 | return NULL; 712 | } 713 | 714 | return NULL; 715 | } 716 | 717 | return NULL; 718 | } 719 | 720 | int Args(Node *n, FieldList param){ 721 | if(n==NULL) 722 | return 1; 723 | //printf("%s\n",n->identifier); 724 | 725 | Node *child = n->child; 726 | if(param==NULL) 727 | return 1; 728 | 729 | Type tmpParam = Exp(child); 730 | if(typeEqual(param->type, tmpParam)==0){ 731 | if(child->sibling==NULL) 732 | return 0; 733 | else 734 | return Args(child->sibling->sibling, param->tail); 735 | } 736 | else 737 | return 2; 738 | } 739 | -------------------------------------------------------------------------------- /Project2/Semantic.h: -------------------------------------------------------------------------------- 1 | #ifndef SEMANTIC_H 2 | #define SEMANTIC_H 3 | 4 | #include "SyntaxTree.h" 5 | 6 | #define BINGO 0 7 | #define ERROR_REDEFINE 1 8 | #define ERROR_DECLARATION_CONFLICT 2 9 | #define ERROR_DOMAIN_REDEFINE 3 10 | 11 | #define FUNC_IS_DECLARED 4 12 | 13 | #define FROM_VARIABLE 1 14 | #define FROM_FIELD 2 15 | #define FROM_PARAM 3 16 | 17 | typedef struct Type_* Type; 18 | typedef struct Structure_* Structure; 19 | typedef struct FieldList_* FieldList; 20 | typedef struct Function_* Function; 21 | 22 | struct Type_{ 23 | enum { BASIC,ARRAY,STRUCTURE,FUNCTION } kind; 24 | union{ 25 | // basic type 26 | int basic; 27 | 28 | // array information 29 | struct { Type elem; int size;} array; 30 | 31 | // structure information 32 | Structure structure; 33 | 34 | // function information 35 | Function function; 36 | } u; 37 | enum { LEFT,RIGHT,BOTH } assign; 38 | }; 39 | 40 | struct Structure_{ 41 | char *name; 42 | FieldList domain; 43 | }; 44 | 45 | struct FieldList_{ 46 | // Field name 47 | char *name; 48 | // Field type 49 | Type type; 50 | // next field 51 | FieldList tail; 52 | }; 53 | 54 | struct Function_{ 55 | char *name; 56 | int isDefined; 57 | int line; 58 | Type retype; 59 | FieldList param; 60 | }; 61 | 62 | int typeEqual(Type lhs, Type rhs); 63 | int structEqual(Structure lhs, Structure rhs); 64 | int valueEqual(FieldList lhs, FieldList rhs); 65 | 66 | void Program(Node* root); 67 | void ExtDefList(Node *n); 68 | void ExtDef(Node *n); 69 | void ExtDecList(Node *n, Type type); 70 | 71 | Type Specifier(Node *n); 72 | Type StructSpecifier(Node *n); 73 | 74 | FieldList VarDec(Node *n, Type type, int from); 75 | Function FunDec(Node *n, Type type); 76 | FieldList VarList(Node *n); 77 | FieldList ParamDec(Node *n); 78 | 79 | void CompSt(Node *n, Type retype); 80 | void StmtList(Node *n, Type retype); 81 | void Stmt(Node *n, Type retype); 82 | 83 | FieldList DefList(Node *n, int from); 84 | FieldList Def(Node *n, int from); 85 | FieldList DecList(Node *n, Type type, int from); 86 | FieldList Dec(Node *n, Type type, int from); 87 | 88 | Type Exp(Node *n); 89 | int Args(Node *n, FieldList param); 90 | 91 | #endif 92 | -------------------------------------------------------------------------------- /Project2/SyntaxTree.c: -------------------------------------------------------------------------------- 1 | #include "SyntaxTree.h" 2 | #include 3 | 4 | Node* init(char identifier[], char value[], _Type type, int line){ 5 | Node* root = malloc(sizeof(Node)); 6 | 7 | root->height = 0; 8 | strcpy(root->identifier, identifier); 9 | 10 | if(value != NULL) 11 | strcpy(root->value, value); 12 | else 13 | root->value[0]='\0'; 14 | 15 | root->type = type; 16 | root->line = line; 17 | 18 | return root; 19 | } 20 | 21 | 22 | void insert(Node *p, Node *child){ 23 | if(p == NULL || child == NULL) 24 | return; 25 | 26 | if(p->child == NULL){ 27 | p->child = child; 28 | return; 29 | } 30 | 31 | Node *temp = p->child; 32 | while(temp->sibling != NULL) 33 | temp = temp->sibling; 34 | temp->sibling = child; 35 | 36 | } 37 | 38 | void traverseTree(Node* p){ 39 | if(p == NULL) 40 | return; 41 | 42 | // Print Node 43 | 44 | for(int i=0; iheight; i++) 45 | printf(" "); 46 | switch(p->type){ 47 | case TYPE_NONTERMINAL: 48 | // non-terminals 49 | printf("%s (%d)\n",p->identifier,p->line); 50 | break; 51 | case TYPE_OCT: 52 | printf("%s: %d\n",p->identifier,(int)strtol(p->value,NULL,8)); 53 | break; 54 | case TYPE_HEX: 55 | printf("%s: %d\n",p->identifier,(int)strtol(p->value,NULL,16)); 56 | break; 57 | case TYPE_KEYWORD_BRACKET: 58 | case TYPE_KEYWORD_PUNCTUATION: 59 | case TYPE_KEYWORD_OPERATOR: 60 | // LP|RP|LB|RB|LC|RC|PUNCUTATION|OPERATOR 61 | printf("%s\n",p->identifier); 62 | break; 63 | default: 64 | // terminals 65 | printf("%s: %s\n",p->identifier,p->value); 66 | break; 67 | } 68 | 69 | if(p->child != NULL) 70 | p->child->height = p->height+1; 71 | if(p->sibling != NULL) 72 | p->sibling->height = p->height; 73 | traverseTree(p->child); 74 | traverseTree(p->sibling); 75 | 76 | } 77 | 78 | void cleanTree(Node *p){ 79 | if(p==NULL) 80 | return; 81 | 82 | cleanTree(p->child); 83 | cleanTree(p->sibling); 84 | free(p); 85 | } 86 | 87 | -------------------------------------------------------------------------------- /Project2/SyntaxTree.h: -------------------------------------------------------------------------------- 1 | #ifndef SYNTAXTREE_H 2 | #define SYNTAXTREE_H 3 | 4 | #include 5 | #include 6 | 7 | #define IDENTIFIER_LENGTH 32 8 | #define VALUE_LENGTH 32 9 | 10 | #define TYPE_KEYWORD 0 11 | #define TYPE_KEYWORD_RELOP 1 12 | #define TYPE_KEYWORD_BRACKET 2 13 | #define TYPE_KEYWORD_PUNCTUATION 3 14 | #define TYPE_KEYWORD_OPERATOR 4 15 | 16 | #define TYPE_NONTERMINAL 65536 17 | 18 | #define TYPE_ID 128 19 | 20 | #define TYPE_INT 256 21 | #define TYPE_OCT 257 22 | #define TYPE_HEX 258 23 | 24 | #define TYPE_FLOAT 512 25 | #define TYPE_SFLOAT 513 26 | 27 | #define TYPE_STRING 1024 28 | 29 | extern int yylineno; 30 | 31 | typedef int _Type; 32 | 33 | typedef struct Node{ 34 | //TODO: Complete Node Structure 35 | 36 | char identifier[IDENTIFIER_LENGTH]; 37 | char value[VALUE_LENGTH]; 38 | _Type type; 39 | int line; 40 | int height; 41 | 42 | // Children Brother Express 43 | struct Node *child; 44 | struct Node *sibling; 45 | 46 | }Node; 47 | 48 | extern Node* init(char identifier[], char value[], _Type type, int line); 49 | extern void insert(Node *p, Node *child); 50 | extern void traverseTree(Node *p); 51 | extern void cleanTree(Node *p); 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /Project2/lexical.l: -------------------------------------------------------------------------------- 1 | %{ 2 | #include 3 | #include 4 | #include "SyntaxTree.h" 5 | #include "syntax.tab.h" 6 | 7 | extern int errorLexFlag; 8 | 9 | int yycolumn = 1; 10 | /* define YY_USER_ACTION */ 11 | #define YY_USER_ACTION yylloc.first_line = yylloc.last_line = yylineno; \ 12 | yylloc.first_column = yycolumn; \ 13 | yylloc.last_column = yycolumn + yyleng - 1; \ 14 | yycolumn += yyleng; 15 | 16 | %} 17 | 18 | %option yylineno 19 | 20 | DELIM [ \t] 21 | WS {DELIM}+ 22 | DIGIT [0-9] 23 | LETTER [A-Za-z] 24 | INT 0|([1-9]{DIGIT}*) 25 | OCT 0([0-7]+) 26 | OCT_ERROR 0[0-9A-WYZa-wyz][0-9A-Za-z]* 27 | HEX 0(x|X)[0-9a-fA-F]+ 28 | HEX_ERROR [0][Xx][0-9A-Za-z]* 29 | FLOAT {INT}(\.{DIGIT}+)? 30 | SFLOAT ((INT\.{DIGIT}*)|({DIGIT}*\.{DIGIT}+))[Ee][+-]?{DIGIT}+ 31 | SFLOAT_ERROR ((INT\.{DIGIT}*)|({DIGIT}*\.{DIGIT}+))[Ee][+-]?([0-9A-Za-z]*) 32 | RELOP >|<|>=|<=|==|!= 33 | ID ({LETTER}|_)({LETTER}|{DIGIT}|_)* 34 | 35 | 36 | %% 37 | 38 | 39 | {WS} { /* tabs */ } 40 | 41 | 42 | "/*"([^\*]|(\*)*[^\*/])*(\*)*"*/" { /* C comments */ } 43 | 44 | "//" { 45 | /* C++ comment */ 46 | while(input() != '\n'); 47 | } 48 | 49 | ";" { 50 | yylval.type_node = init("SEMI",yytext,TYPE_KEYWORD_PUNCTUATION,yylineno); 51 | return SEMI; 52 | } 53 | 54 | "," { 55 | yylval.type_node = init("COMMA",yytext,TYPE_KEYWORD_PUNCTUATION,yylineno); 56 | return COMMA; 57 | } 58 | 59 | 60 | "=" { 61 | yylval.type_node = init("ASSIGNOP",yytext,TYPE_KEYWORD_OPERATOR,yylineno); 62 | return ASSIGNOP; 63 | } 64 | 65 | {RELOP} { 66 | yylval.type_node = init("RELOP",yytext,TYPE_KEYWORD_RELOP,yylineno); 67 | return RELOP; 68 | } 69 | 70 | "+" { 71 | yylval.type_node = init("PLUS",yytext,TYPE_KEYWORD_OPERATOR,yylineno); 72 | return PLUS; 73 | } 74 | 75 | "-" { 76 | yylval.type_node = init("MINUS",yytext,TYPE_KEYWORD_OPERATOR,yylineno); 77 | return MINUS; 78 | } 79 | 80 | "*" { 81 | yylval.type_node = init("STAR",yytext,TYPE_KEYWORD_OPERATOR,yylineno); 82 | return STAR; 83 | } 84 | 85 | "/" { 86 | yylval.type_node = init("DIV",yytext,TYPE_KEYWORD_OPERATOR,yylineno); 87 | return DIV; 88 | } 89 | 90 | "&&" { 91 | yylval.type_node = init("AND",yytext,TYPE_KEYWORD_OPERATOR,yylineno); 92 | return AND; 93 | } 94 | 95 | "||" { 96 | yylval.type_node = init("OR",yytext,TYPE_KEYWORD_OPERATOR,yylineno); 97 | return OR; 98 | } 99 | 100 | "!" { 101 | yylval.type_node = init("NOT",yytext,TYPE_KEYWORD_OPERATOR,yylineno); 102 | return NOT; 103 | } 104 | 105 | "." { 106 | yylval.type_node = init("DOT",yytext,TYPE_KEYWORD_PUNCTUATION,yylineno); 107 | return DOT; 108 | } 109 | 110 | "int"|"float" { 111 | yylval.type_node = init("TYPE",yytext,TYPE_KEYWORD,yylineno); 112 | return TYPE; 113 | } 114 | 115 | "(" { 116 | yylval.type_node = init("LP",yytext,TYPE_KEYWORD_BRACKET,yylineno); 117 | return LP; 118 | } 119 | 120 | ")" { 121 | yylval.type_node = init("RP",yytext,TYPE_KEYWORD_BRACKET,yylineno); 122 | return RP; 123 | } 124 | 125 | "[" { 126 | yylval.type_node = init("LB",yytext,TYPE_KEYWORD_BRACKET,yylineno); 127 | return LB; 128 | } 129 | 130 | "]" { 131 | yylval.type_node = init("RB",yytext,TYPE_KEYWORD_BRACKET,yylineno); 132 | return RB; 133 | } 134 | 135 | "{" { 136 | yylval.type_node = init("LC",yytext,TYPE_KEYWORD_BRACKET,yylineno); 137 | return LC; 138 | } 139 | 140 | "}" { 141 | yylval.type_node = init("RC",yytext,TYPE_KEYWORD_BRACKET,yylineno); 142 | return RC; 143 | } 144 | 145 | "struct" { 146 | yylval.type_node = init("STRUCT",yytext,TYPE_KEYWORD,yylineno); 147 | return STRUCT; 148 | } 149 | 150 | "return" { 151 | yylval.type_node = init("RETURN",yytext,TYPE_KEYWORD,yylineno); 152 | return RETURN; 153 | } 154 | 155 | "if" { 156 | yylval.type_node = init("IF",yytext,TYPE_KEYWORD,yylineno); 157 | return IF; 158 | } 159 | 160 | "else" { 161 | yylval.type_node = init("ELSE",yytext,TYPE_KEYWORD,yylineno); 162 | return ELSE; 163 | } 164 | 165 | "while" { 166 | yylval.type_node = init("WHILE",yytext,TYPE_KEYWORD,yylineno); 167 | return WHILE; 168 | } 169 | 170 | {OCT} { 171 | yylval.type_node = init("INT",yytext,TYPE_OCT,yylineno); 172 | return INT; 173 | } 174 | 175 | {OCT_ERROR} { 176 | printf("Error type A at line %d: Illegal octal number \'%s\'\n", yylineno, yytext); 177 | errorLexFlag = 1; 178 | } 179 | 180 | {HEX} { 181 | yylval.type_node = init("INT",yytext,TYPE_HEX,yylineno); 182 | return INT; 183 | } 184 | 185 | {HEX_ERROR} { 186 | printf("Error type A at line %d: Illegal hexadecimal number \'%s\'\n", yylineno, yytext); 187 | errorLexFlag = 1; 188 | } 189 | 190 | {SFLOAT} { 191 | yylval.type_node = init("FLOAT",yytext,TYPE_SFLOAT,yylineno); 192 | return FLOAT; 193 | } 194 | 195 | {SFLOAT_ERROR} { 196 | printf("Error type A at line %d: Illegal floating point number \'%s\'\n", yylineno, yytext); 197 | errorLexFlag = 1; 198 | } 199 | 200 | {INT} { 201 | yylval.type_node = init("INT",yytext,TYPE_INT,yylineno); 202 | return INT; 203 | } 204 | 205 | {FLOAT} { 206 | yylval.type_node = init("FLOAT",yytext,TYPE_FLOAT,yylineno); 207 | return FLOAT; 208 | } 209 | 210 | \n { yycolumn = 1; } 211 | 212 | {ID} { 213 | yylval.type_node = init("ID",yytext,TYPE_ID,yylineno); 214 | return ID; 215 | } 216 | 217 | 218 | . { 219 | printf("Error type A at line %d: Mysterious character \'%s\'\n" 220 | , yylineno, yytext); 221 | errorLexFlag = 1; 222 | } 223 | 224 | 225 | %% 226 | 227 | /* 228 | int main(int argc, char** argv){ 229 | if (argc > 1) 230 | if (!(yyin = fopen(argv[1], "r"))){ 231 | perror(argv[1]); 232 | return 1; 233 | } 234 | } 235 | while (yylex() != 0) ; 236 | return 0; 237 | } 238 | */ 239 | -------------------------------------------------------------------------------- /Project2/main.c: -------------------------------------------------------------------------------- 1 | #include "SyntaxTree.h" 2 | #include "parse.h" 3 | #include "HashTable.h" 4 | #include "Semantic.h" 5 | 6 | Node *tree; 7 | int errorLexFlag; 8 | int errorSyntaxFlag; 9 | 10 | int main(int argc, char** argv){ 11 | if(argc <= 1) 12 | return 1; 13 | FILE *f = fopen(argv[1], "r"); 14 | if(!f){ 15 | perror(argv[1]); 16 | return 1; 17 | } 18 | 19 | 20 | tree = NULL; 21 | errorLexFlag = 0; 22 | errorSyntaxFlag = 0; 23 | yylineno = 1; 24 | yyrestart(f); 25 | yyparse(); 26 | 27 | if(errorLexFlag == 0 && errorSyntaxFlag==0){ 28 | initTable(); 29 | // traverseTree(tree); 30 | Program(tree); 31 | } 32 | 33 | cleanTree(tree); 34 | return 0; 35 | 36 | } 37 | -------------------------------------------------------------------------------- /Project2/parse.h: -------------------------------------------------------------------------------- 1 | #ifndef PRASE_H 2 | #define PRASE_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "SyntaxTree.h" 12 | 13 | /* 14 | * lex & parse 15 | */ 16 | extern int yylex(void); 17 | extern int yyparse(void); 18 | extern void yyrestart(FILE*); 19 | extern void yyerror(char*); 20 | extern int yylineno; 21 | 22 | /* 23 | * SyntaxTree 24 | */ 25 | extern Node* tree; 26 | 27 | /* 28 | * main 29 | */ 30 | extern int errorLexFlag; 31 | extern int errorSyntaxFlag; 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /Project2/pretest/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Unkrible/Compilers/50a13f45ae865d0dfaf8f91d4f44913433ad7dfa/Project2/pretest/.DS_Store -------------------------------------------------------------------------------- /Project2/pretest/1.txt: -------------------------------------------------------------------------------- 1 | int main() 2 | { 3 | int i = 0; 4 | j = i + 1; 5 | } -------------------------------------------------------------------------------- /Project2/pretest/10.txt: -------------------------------------------------------------------------------- 1 | int main() 2 | { 3 | int i; 4 | i[0]; 5 | } -------------------------------------------------------------------------------- /Project2/pretest/11.txt: -------------------------------------------------------------------------------- 1 | int main() 2 | { 3 | int i; 4 | i(10); 5 | } -------------------------------------------------------------------------------- /Project2/pretest/12.txt: -------------------------------------------------------------------------------- 1 | int main() 2 | { 3 | int i[10]; 4 | i[1.5] = 10; 5 | } -------------------------------------------------------------------------------- /Project2/pretest/13.txt: -------------------------------------------------------------------------------- 1 | struct Position 2 | { 3 | float x, y; 4 | }; 5 | int main() 6 | { 7 | int i; 8 | i.x; 9 | } -------------------------------------------------------------------------------- /Project2/pretest/14.txt: -------------------------------------------------------------------------------- 1 | struct Position 2 | { 3 | float x, y; 4 | }; 5 | int main() 6 | { 7 | struct Position p; 8 | if (p.n == 3.7) 9 | return 0; 10 | } -------------------------------------------------------------------------------- /Project2/pretest/15.txt: -------------------------------------------------------------------------------- 1 | struct Position 2 | { 3 | float x, y; 4 | int x; 5 | }; 6 | int main() 7 | { 8 | 9 | } -------------------------------------------------------------------------------- /Project2/pretest/16.txt: -------------------------------------------------------------------------------- 1 | struct Position 2 | { 3 | float x; 4 | }; 5 | 6 | struct Position 7 | { 8 | int y; 9 | }; 10 | 11 | int main() 12 | { 13 | 14 | } -------------------------------------------------------------------------------- /Project2/pretest/17.txt: -------------------------------------------------------------------------------- 1 | int main() 2 | { 3 | struct Position pos; 4 | } -------------------------------------------------------------------------------- /Project2/pretest/18.txt: -------------------------------------------------------------------------------- 1 | int func(int a); 2 | int func(int a) 3 | { 4 | return 1; 5 | } 6 | 7 | int main() 8 | { 9 | 10 | } -------------------------------------------------------------------------------- /Project2/pretest/19.txt: -------------------------------------------------------------------------------- 1 | struct Position 2 | { 3 | float x,y; 4 | }; 5 | int func(int a); 6 | int func(struct Position p); 7 | int main() 8 | { 9 | 10 | } -------------------------------------------------------------------------------- /Project2/pretest/2.txt: -------------------------------------------------------------------------------- 1 | int main() 2 | { 3 | int i = 0; 4 | inc(i); 5 | } -------------------------------------------------------------------------------- /Project2/pretest/20.txt: -------------------------------------------------------------------------------- 1 | int func() 2 | { 3 | int i = 10; 4 | return i; 5 | } 6 | 7 | int main() 8 | { 9 | int i; 10 | i = func(); 11 | } -------------------------------------------------------------------------------- /Project2/pretest/21.txt: -------------------------------------------------------------------------------- 1 | int func() 2 | { 3 | int i = 10; 4 | return i; 5 | } 6 | int main() 7 | { 8 | int i; 9 | int i, j; 10 | i = func(); 11 | } -------------------------------------------------------------------------------- /Project2/pretest/22.txt: -------------------------------------------------------------------------------- 1 | struct Temp1 2 | { 3 | int i; 4 | float j; 5 | }; 6 | struct Temp2 7 | { 8 | int x; 9 | float y; 10 | }; 11 | 12 | int main() 13 | { 14 | struct Temp1 t1; 15 | struct Temp2 t2; 16 | t1 = t2; 17 | } -------------------------------------------------------------------------------- /Project2/pretest/23.txt: -------------------------------------------------------------------------------- 1 | struct Temp1 2 | { 3 | int i; 4 | float j; 5 | }; 6 | struct Temp2 7 | { 8 | int x; 9 | }; 10 | 11 | int main() 12 | { 13 | struct Temp1 t1; 14 | struct Temp2 t2; 15 | t1 = t2; 16 | } -------------------------------------------------------------------------------- /Project2/pretest/24.txt: -------------------------------------------------------------------------------- 1 | int main() 2 | { 3 | int a[10][10], b[10][10]; 4 | int i, j, N = 10; 5 | while(i < N) 6 | { 7 | while(j < N) 8 | { 9 | a[i-1][j] = b[i][j] + i * j; 10 | a[i][j-1] = a[i][j][0]; 11 | j = j + 1; 12 | } 13 | i = i + 1; 14 | } 15 | return 0; 16 | } -------------------------------------------------------------------------------- /Project2/pretest/3.txt: -------------------------------------------------------------------------------- 1 | int main() 2 | { 3 | int i, j; 4 | int i; 5 | } -------------------------------------------------------------------------------- /Project2/pretest/4.txt: -------------------------------------------------------------------------------- 1 | int func(int i) 2 | { 3 | return i; 4 | } 5 | int func() 6 | { 7 | return 0; 8 | } 9 | int main() 10 | { 11 | 12 | } -------------------------------------------------------------------------------- /Project2/pretest/5.txt: -------------------------------------------------------------------------------- 1 | int main() 2 | { 3 | int i; 4 | i = 3.7; 5 | } -------------------------------------------------------------------------------- /Project2/pretest/6.txt: -------------------------------------------------------------------------------- 1 | int main() 2 | { 3 | int i; 4 | 10 = i; 5 | } -------------------------------------------------------------------------------- /Project2/pretest/7.txt: -------------------------------------------------------------------------------- 1 | int main() 2 | { 3 | float j; 4 | 10 + j; 5 | } -------------------------------------------------------------------------------- /Project2/pretest/8.txt: -------------------------------------------------------------------------------- 1 | int main() 2 | { 3 | float j = 1.7; 4 | return j; 5 | } -------------------------------------------------------------------------------- /Project2/pretest/9.txt: -------------------------------------------------------------------------------- 1 | int func(int i) 2 | { 3 | return i; 4 | } 5 | int main() 6 | { 7 | func(1, 2); 8 | } -------------------------------------------------------------------------------- /Project2/pretest/README.txt: -------------------------------------------------------------------------------- 1 | 本目录下的23个测试样例为实验指导书中给出的样例,占最终成绩的一部分。 -------------------------------------------------------------------------------- /Project2/report.md: -------------------------------------------------------------------------------- 1 | # Project2 实验报告 2 | ###### 151220136 许卓尔 3 | 4 | ## 实现功能 5 | 6 | 1. **进行语义分析且检查错误类型** 7 | > 部分由队友赵文昊完成 8 | 9 | 2. **附加要求** 10 | 11 | - 要求2.1 12 | 13 | - 要求2.3(由队友赵文昊完成) 14 | 15 | 16 | 17 | ## 实现方法 18 | 19 | #### 进行语义分析且检查错误类型 20 | 21 | - 属性文法 22 | 23 | 由于Bison采用了自底向上的LALR(1)分析技术,对于SDT无法实现继承属性的计算,因此需要通过Bison建立语法树,并在语法树的基础上自顶向下进行SDT; 24 | 25 | 通过上下文无关文法,对语法分析树进行遍历,并在遍历过程中进行语义分析; 26 | 27 | - 类型表示 28 | 29 | 参考了实验指导书中取自老虎书的代码风格,对类型的数据结构进行设计; 30 | 31 | 有所改变的是,自己设计了 Structure、 Function 的数据结构,具体可见/code/Semantic.h; 32 | 33 | 在此基础上,由于Exp属性文法中需要进行左值、右值判断,在 strcut Type_ 的基础上加入枚举类型成员变量 34 | ``` 35 | struct Type_{ 36 | ... 37 | enum{LEFT,RIGHT,BOTH} assign; 38 | }; 39 | ``` 40 | 41 | 42 | 43 | - 符号表 44 | 45 | 符号表采用散列表的实现方案,设计如下数据结构; 46 | 47 | 采用P.J.Weinberger提出的哈希函数; 48 | 49 | 对于冲突,采用开散列的处理方式; 50 | > 由于基本要求中,对于大部分类型判断采用名等价的方案,于是加入 name 属性方便判断; 51 | 52 | ``` 53 | typedef struct Entry_{ 54 | char *name; 55 | Type type; 56 | struct Entry_ *next; 57 | }Entry; 58 | extern Entry *hashTable[HASH_SIZE]; 59 | ``` 60 | 61 | 62 | - 错误检查 63 | 64 | 在语法制导翻译的过程中进行错误检查; 65 | 66 | - Error Type 1~2、17: 调用的时候于符号表查找,若为NULL报错; 67 | - Error Type 3~4、16: 插入符号表时进行查重; 68 | - Error Type 5~14: 在Exp中,对于Type lhs、Type rhs进行类型判断,不满足条件则报错; 69 | - Error Type 15: 结构体域名插入符号表时查重;对于赋值,判断其文法上一层的来源是否为StructSpecifier; 70 | 71 | #### 要求2.1 72 | 73 | ##### 进行函数声明 74 | 75 | - 添加文法 ExtDef -> Specifier FunDec SEMI; 76 | - 对于 struct Function_ 添加变量 isDefined 判断其为声明或定义; 77 | - 函数插入符号表时,进行判断,具体实现可见 /code/HashTable.c/funcInsertCheck(); 78 | - Error Type 18: 在文法 Program 完成后,对符号表进行查找,若仍有函数 isDefined==0 ,则报错; 79 | - Error Type 19: 在funcInsertCheck()时,进行返回类型、参数类型判断,若不一致则标错; 80 | ``` 81 | struct Function_{ 82 | ... 83 | int isDefined; // 判断为声明或实现; 84 | }; 85 | ``` 86 | 87 | 88 | 89 | ## 编译介绍 90 | 91 | ##### Makefile文件 92 | 93 | make parser | make 94 | > 对词法分析器、语法分析器进行编译并生成相应的parser程序; 95 | 96 | make clean 97 | > 对生成文件进行清理; 98 | 99 | ./parser ./pretest/FileName.txt 100 | > 对当前路径下pretest文件夹中的FileName.txt文件进行语义分析并检查是否有错; 101 | -------------------------------------------------------------------------------- /Project2/syntax.y: -------------------------------------------------------------------------------- 1 | %{ 2 | #include 3 | #include 4 | #include "parse.h" 5 | #include "SyntaxTree.h" 6 | %} 7 | 8 | /* declared types */ 9 | %union { 10 | int type_int; 11 | float type_float; 12 | double type_double; 13 | Node* type_node; 14 | } 15 | 16 | /* declared tokens */ 17 | %token INT 18 | %token FLOAT 19 | %token ID 20 | %token SEMI 21 | %token COMMA 22 | %token ASSIGNOP 23 | %token RELOP 24 | %token PLUS 25 | %token MINUS 26 | %token STAR 27 | %token DIV 28 | %token AND 29 | %token OR 30 | %token NOT 31 | %token DOT 32 | %token TYPE 33 | %token LP 34 | %token RP 35 | %token LB 36 | %token RB 37 | %token LC 38 | %token RC 39 | %token STRUCT 40 | %token RETURN 41 | %token IF 42 | %token ELSE 43 | %token WHILE 44 | 45 | /* declared non-terminals */ 46 | %type Program ExtDefList ExtDef ExtDecList 47 | %type Specifier StructSpecifier OptTag Tag 48 | %type VarDec FunDec VarList ParamDec 49 | %type CompSt StmtList Stmt 50 | %type DefList Def DecList Dec 51 | %type Exp Args 52 | 53 | %right ASSIGNOP 54 | %left OR 55 | %left AND 56 | %left RELOP 57 | %left PLUS 58 | %left STAR DIV 59 | %right NOT 60 | %left LP RP LB RB DOT 61 | 62 | %nonassoc LOWER_THAN_ELSE 63 | %nonassoc ELSE 64 | 65 | 66 | %% 67 | 68 | /* High-level Definitions */ 69 | Program : ExtDefList { 70 | $$ = init("Program", NULL, TYPE_NONTERMINAL, @$.first_line); 71 | insert($$, $1); 72 | tree = $$; 73 | } 74 | ; 75 | ExtDefList : ExtDef ExtDefList{ 76 | $$ = init("ExtDefList", NULL, TYPE_NONTERMINAL, @$.first_line); 77 | insert($$,$1);insert($$,$2); 78 | } 79 | | /* empty */{ $$ = init("ExtDefList", NULL, TYPE_NONTERMINAL, @$.first_line); } 80 | ; 81 | ExtDef : Specifier ExtDecList SEMI{ 82 | $$ = init("ExtDef", NULL, TYPE_NONTERMINAL, @$.first_line); 83 | insert($$,$1);insert($$,$2);insert($$,$3); 84 | } 85 | | Specifier SEMI{ 86 | $$ = init("ExtDef", NULL, TYPE_NONTERMINAL, @$.first_line); 87 | insert($$,$1);insert($$,$2); 88 | } 89 | | Specifier FunDec SEMI{ 90 | $$ = init("ExtDef", NULL, TYPE_NONTERMINAL, @$.first_line); 91 | insert($$,$1);insert($$,$2);insert($$,$3); 92 | } 93 | | Specifier FunDec CompSt{ 94 | $$ = init("ExtDef", NULL, TYPE_NONTERMINAL, @$.first_line); 95 | insert($$,$1);insert($$,$2);insert($$,$3); 96 | } 97 | | error SEMI { errorSyntaxFlag=2; } 98 | ; 99 | ExtDecList : VarDec{ 100 | $$ = init("ExtDecList", NULL, TYPE_NONTERMINAL, @$.first_line); 101 | insert($$, $1); 102 | } 103 | | VarDec COMMA ExtDecList{ 104 | $$ = init("ExtDecList", NULL, TYPE_NONTERMINAL, @$.first_line); 105 | insert($$,$1);insert($$,$2);insert($$,$3); 106 | } 107 | ; 108 | 109 | /* Specifiers */ 110 | Specifier : TYPE{ 111 | $$ = init("Specifier", NULL, TYPE_NONTERMINAL, @$.first_line); 112 | insert($$,$1); 113 | } 114 | | StructSpecifier{ 115 | $$ = init("Specifier", NULL, TYPE_NONTERMINAL, @$.first_line); 116 | insert($$,$1); 117 | } 118 | ; 119 | StructSpecifier : STRUCT OptTag LC DefList RC{ 120 | $$ = init("StructSpecifier", NULL, TYPE_NONTERMINAL, @$.first_line); 121 | insert($$,$1);insert($$,$2);insert($$,$3);insert($$,$4);insert($$,$5); 122 | } 123 | | STRUCT Tag{ 124 | $$ = init("StructSpecifier", NULL, TYPE_NONTERMINAL, @$.first_line); 125 | insert($$,$1);insert($$,$2); 126 | } 127 | ; 128 | OptTag : ID{ 129 | $$ = init("OptTag", NULL, TYPE_NONTERMINAL, @$.first_line); 130 | insert($$,$1); 131 | } 132 | | /* empty */{$$ = init("OptTag", NULL, TYPE_NONTERMINAL, @$.first_line);} 133 | ; 134 | Tag : ID{ 135 | $$ = init("Tag", NULL, TYPE_NONTERMINAL, @$.first_line); 136 | insert($$,$1); 137 | } 138 | ; 139 | 140 | /* Declarators */ 141 | VarDec : ID{ 142 | $$ = init("VarDec", NULL, TYPE_NONTERMINAL, @$.first_line); 143 | insert($$,$1); 144 | } 145 | | VarDec LB INT RB{ 146 | $$ = init("VarDec", NULL, TYPE_NONTERMINAL, @$.first_line); 147 | insert($$,$1);insert($$,$2);insert($$,$3);insert($$,$4); 148 | } 149 | ; 150 | FunDec : ID LP VarList RP{ 151 | $$ = init("FunDec", NULL, TYPE_NONTERMINAL, @$.first_line); 152 | insert($$,$1);insert($$,$2);insert($$,$3);insert($$,$4); 153 | } 154 | | ID LP RP{ 155 | $$ = init("FunDec", NULL, TYPE_NONTERMINAL, @$.first_line); 156 | insert($$,$1);insert($$,$2);insert($$,$3); 157 | } 158 | | error RP{ errorSyntaxFlag=2; } 159 | ; 160 | VarList : ParamDec COMMA VarList{ 161 | $$ = init("VarList", NULL, TYPE_NONTERMINAL, @$.first_line); 162 | insert($$,$1);insert($$,$2);insert($$,$3); 163 | } 164 | | ParamDec{ 165 | $$ = init("VarList", NULL, TYPE_NONTERMINAL, @$.first_line); 166 | insert($$,$1); 167 | } 168 | ; 169 | ParamDec : Specifier VarDec{ 170 | $$ = init("ParamDec", NULL, TYPE_NONTERMINAL, @$.first_line); 171 | insert($$,$1);insert($$,$2); 172 | } 173 | ; 174 | 175 | /* Statements */ 176 | CompSt : LC DefList StmtList RC{ 177 | $$ = init("CompSt", NULL, TYPE_NONTERMINAL, @$.first_line); 178 | insert($$,$1);insert($$,$2);insert($$,$3);insert($$,$4); 179 | } 180 | | error RC{ errorSyntaxFlag=2; } 181 | ; 182 | StmtList : Stmt StmtList{ 183 | $$ = init("StmtList", NULL, TYPE_NONTERMINAL, @$.first_line); 184 | insert($$,$1);insert($$,$2); 185 | } 186 | | /* empty */{ 187 | $$ = init("StmtList", NULL, TYPE_NONTERMINAL, @$.first_line); 188 | } 189 | ; 190 | Stmt : Exp SEMI{ 191 | $$ = init("Stmt", NULL, TYPE_NONTERMINAL, @$.first_line); 192 | insert($$,$1);insert($$,$2); 193 | } 194 | | CompSt{ 195 | $$ = init("Stmt", NULL, TYPE_NONTERMINAL, @$.first_line); 196 | insert($$,$1); 197 | } 198 | | RETURN Exp SEMI{ 199 | $$ = init("Stmt", NULL, TYPE_NONTERMINAL, @$.first_line); 200 | insert($$,$1);insert($$,$2);insert($$,$3); 201 | } 202 | | IF LP Exp RP Stmt %prec LOWER_THAN_ELSE{ 203 | $$ = init("Stmt", NULL, TYPE_NONTERMINAL, @$.first_line); 204 | insert($$,$1);insert($$,$2);insert($$,$3); 205 | insert($$,$4);insert($$,$5); 206 | } 207 | | IF LP Exp RP Stmt ELSE Stmt{ 208 | $$ = init("Stmt", NULL, TYPE_NONTERMINAL, @$.first_line); 209 | insert($$,$1);insert($$,$2);insert($$,$3); 210 | insert($$,$4);insert($$,$5);insert($$,$6);insert($$,$7); 211 | } 212 | | WHILE LP Exp RP Stmt{ 213 | $$ = init("Stmt", NULL, TYPE_NONTERMINAL, @$.first_line); 214 | insert($$,$1);insert($$,$2);insert($$,$3); 215 | insert($$,$4);insert($$,$5); 216 | } 217 | | error SEMI { errorSyntaxFlag=2; } 218 | ; 219 | 220 | /* Local Definitions */ 221 | DefList : Def DefList{ 222 | $$ = init("DefList", NULL, TYPE_NONTERMINAL, @$.first_line); 223 | insert($$,$1);insert($$,$2); 224 | } 225 | | /* empty */{ 226 | $$ = init("DefList", NULL, TYPE_NONTERMINAL, @$.first_line); 227 | } 228 | ; 229 | Def : Specifier DecList SEMI{ 230 | $$ = init("Def", NULL, TYPE_NONTERMINAL, @$.first_line); 231 | insert($$,$1);insert($$,$2);insert($$,$3); 232 | } 233 | | error SEMI{ errorSyntaxFlag=2; } 234 | ; 235 | DecList : Dec{ 236 | $$ = init("DecList", NULL, TYPE_NONTERMINAL, @$.first_line); 237 | insert($$,$1); 238 | } 239 | | Dec COMMA DecList{ 240 | $$ = init("DecList", NULL, TYPE_NONTERMINAL, @$.first_line); 241 | insert($$,$1);insert($$,$2);insert($$,$3); 242 | } 243 | ; 244 | Dec : VarDec{ 245 | $$ = init("Dec", NULL, TYPE_NONTERMINAL, @$.first_line); 246 | insert($$,$1); 247 | } 248 | | VarDec ASSIGNOP Exp{ 249 | $$ = init("Dec", NULL, TYPE_NONTERMINAL, @$.first_line); 250 | insert($$,$1);insert($$,$2);insert($$,$3); 251 | } 252 | 253 | /* Expressions */ 254 | Exp : Exp ASSIGNOP Exp{ 255 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 256 | insert($$,$1);insert($$,$2);insert($$,$3); 257 | } 258 | | Exp AND Exp{ 259 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 260 | insert($$,$1); 261 | } 262 | | Exp OR Exp{ 263 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 264 | insert($$,$1);insert($$,$2);insert($$,$3); 265 | } 266 | | Exp RELOP Exp{ 267 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 268 | insert($$,$1);insert($$,$2);insert($$,$3); 269 | } 270 | | Exp PLUS Exp{ 271 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 272 | insert($$,$1);insert($$,$2);insert($$,$3); 273 | } 274 | | Exp MINUS Exp{ 275 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 276 | insert($$,$1);insert($$,$2);insert($$,$3); 277 | } 278 | | Exp STAR Exp{ 279 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 280 | insert($$,$1);insert($$,$2);insert($$,$3); 281 | } 282 | | Exp DIV Exp{ 283 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 284 | insert($$,$1);insert($$,$2);insert($$,$3); 285 | } 286 | | LP Exp RP{ 287 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 288 | insert($$,$1);insert($$,$2);insert($$,$3); 289 | } 290 | | MINUS Exp{ 291 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 292 | insert($$,$1);insert($$,$2); 293 | } 294 | | NOT Exp{ 295 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 296 | insert($$,$1);insert($$,$2); 297 | } 298 | | ID LP Args RP{ 299 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 300 | insert($$,$1);insert($$,$2);insert($$,$3);insert($$,$4); 301 | } 302 | | ID LP RP{ 303 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 304 | insert($$,$1);insert($$,$2);insert($$,$3); 305 | } 306 | | Exp LB Exp RB{ 307 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 308 | insert($$,$1);insert($$,$2);insert($$,$3);insert($$,$4); 309 | } 310 | | Exp DOT ID{ 311 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 312 | insert($$,$1);insert($$,$2);insert($$,$3); 313 | } 314 | | ID{ 315 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 316 | insert($$,$1); 317 | } 318 | | INT{ 319 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 320 | insert($$,$1); 321 | } 322 | | FLOAT{ 323 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 324 | insert($$,$1); 325 | } 326 | ; 327 | Args : Exp COMMA Args{ 328 | $$ = init("Args", NULL, TYPE_NONTERMINAL, @$.first_line); 329 | insert($$,$1);insert($$,$2);insert($$,$3); 330 | } 331 | | Exp{ 332 | $$ = init("Args", NULL, TYPE_NONTERMINAL, @$.first_line); 333 | insert($$,$1); 334 | } 335 | ; 336 | 337 | /* Comments */ 338 | 339 | %% 340 | 341 | 342 | void yyerror(char* msg){ 343 | if(errorLexFlag==0) 344 | fprintf(stderr, "Error type B at Line %d: %s\n",yylineno,msg); 345 | } 346 | -------------------------------------------------------------------------------- /Project3/HashTable.c: -------------------------------------------------------------------------------- 1 | #include "HashTable.h" 2 | 3 | Entry *hashTable[HASH_SIZE]; 4 | 5 | unsigned int hashPJW(char *name){ 6 | unsigned int val=0, i; 7 | for(; *name; ++name){ 8 | val = (val<<2)+*name; 9 | if(i= val& ~0x3fff) 10 | val = (val^(i>>12))&0x3fff; 11 | } 12 | return val; 13 | 14 | } 15 | 16 | void initTable(){ 17 | int i=0; 18 | for(;iname=malloc(16); 23 | memset(read->name, 0, sizeof(read->name)); 24 | strcpy(read->name,"read"); 25 | read->isDefined=1; 26 | read->line=0; 27 | read->retype=malloc(sizeof(struct Type_)); 28 | read->retype->kind=BASIC; 29 | read->retype->u.basic=TYPE_INT; 30 | read->param=NULL; 31 | funcInsertTable(read); 32 | Function write=malloc(sizeof(struct Function_)); 33 | write->name=malloc(16); 34 | memset(write->name, 0, sizeof(write->name)); 35 | strcpy(write->name,"write"); 36 | write->isDefined=1; 37 | write->line=0; 38 | write->retype=malloc(sizeof(struct Type_)); 39 | write->retype->kind=BASIC; 40 | write->retype->u.basic=TYPE_INT; 41 | write->param=malloc(sizeof(struct FieldList_)); 42 | write->param->name = malloc(16); 43 | strcpy(write->param->name,"write_param"); 44 | write->param->type=malloc(sizeof(struct Type_)); 45 | write->param->type->kind = BASIC; 46 | write->param->type->u.basic = TYPE_INT; 47 | write->param->tail=NULL; 48 | funcInsertTable(write); 49 | } 50 | 51 | int varInsertTable(FieldList value){ 52 | 53 | if(hashTable==NULL || value==NULL) 54 | return 0; 55 | 56 | unsigned int hashValue = 0; 57 | hashValue = hashPJW(value->name)%HASH_SIZE; 58 | 59 | Entry *curEntry = (Entry *)malloc(sizeof(Entry)); 60 | curEntry->next = hashTable[hashValue]; 61 | hashTable[hashValue] = curEntry; 62 | 63 | curEntry->type = value->type; 64 | curEntry->name = value->name; 65 | 66 | return 1; 67 | } 68 | 69 | int funcInsertTable(Function func){ 70 | if(hashTable==NULL || func==NULL) 71 | return 0; 72 | 73 | unsigned int hashValue = 0; 74 | hashValue = hashPJW(func->name)%HASH_SIZE; 75 | 76 | Entry *curEntry = (Entry *)malloc(sizeof(Entry)); 77 | curEntry->next = hashTable[hashValue]; 78 | hashTable[hashValue] = curEntry; 79 | 80 | curEntry->type = (Type)malloc(sizeof(struct Function_)); 81 | curEntry->type->kind = FUNCTION; 82 | curEntry->type->u.function = func; 83 | curEntry->name = func->name; 84 | 85 | FieldList param = func->param; 86 | int flag; 87 | 88 | while(param != NULL){ 89 | flag = varInsertCheck(param); 90 | if(flag == ERROR_REDEFINE){ 91 | printf("Error type 3 at Line %d: Redefine variable \"%s\"\n",func->line, param->name); 92 | } 93 | else{ 94 | varInsertTable(param); 95 | } 96 | param = param->tail; 97 | } 98 | 99 | return 1; 100 | } 101 | 102 | int structInsertTable(Structure structure){ 103 | if(hashTable==NULL || structure==NULL) 104 | return 0; 105 | 106 | unsigned int hashValue = 0; 107 | hashValue = hashPJW(structure->name)%HASH_SIZE; 108 | 109 | Entry *curEntry = (Entry *)malloc(sizeof(Entry)); 110 | curEntry->next = hashTable[hashValue]; 111 | hashTable[hashValue] = curEntry; 112 | 113 | curEntry->type = (Type)malloc(sizeof(struct Structure_)); 114 | curEntry->type->kind = STRUCTURE; 115 | curEntry->type->u.structure = structure; 116 | curEntry->name = structure->name; 117 | 118 | return 1; 119 | } 120 | 121 | int varInsertCheck(FieldList var){ 122 | if(var==NULL) 123 | return BINGO; 124 | 125 | unsigned int hashValue = hashPJW(var->name)%HASH_SIZE; 126 | Entry *tmp = hashTable[hashValue]; 127 | for(;tmp!=NULL;tmp=tmp->next){ 128 | if(tmp->type->kind!=FUNCTION&&strcmp(tmp->name, var->name)==0) 129 | return ERROR_REDEFINE; 130 | else 131 | continue; 132 | } 133 | } 134 | 135 | int funcInsertCheck(Function func){ 136 | 137 | if(hashTable==NULL || func==NULL) 138 | return BINGO; 139 | 140 | unsigned int hashValue = hashPJW(func->name)%HASH_SIZE; 141 | Entry *tmp = hashTable[hashValue]; 142 | for(;tmp!=NULL;tmp=tmp->next){ 143 | if(tmp->type->kind != FUNCTION) 144 | continue; 145 | Function tmpFunc = tmp->type->u.function; 146 | if(strcmp(tmpFunc->name,func->name)!=0) 147 | continue; 148 | if((valueEqual(tmpFunc->param,func->param)!=0) 149 | || (typeEqual(tmpFunc->retype,func->retype)!=0)) 150 | return ERROR_DECLARATION_CONFLICT; 151 | if(tmpFunc->isDefined!=0){ 152 | return ERROR_REDEFINE; 153 | } 154 | else{ 155 | tmpFunc->isDefined = func->isDefined; 156 | return FUNC_IS_DECLARED; 157 | } 158 | } 159 | return BINGO; 160 | } 161 | 162 | int structInsertCheck(Structure structure){ 163 | if(hashTable==NULL || structure==NULL) 164 | return BINGO; 165 | 166 | unsigned int hashValue = hashPJW(structure->name)%HASH_SIZE; 167 | Entry *tmp = hashTable[hashValue]; 168 | for(;tmp!=NULL;tmp=tmp->next){ 169 | if(tmp->type->kind!=FUNCTION&&strcmp(tmp->name,structure->name)==0) 170 | return ERROR_REDEFINE; 171 | else 172 | continue; 173 | } 174 | return BINGO; 175 | } 176 | 177 | Type getTable(char *name){ 178 | 179 | if(hashTable==NULL || name==NULL) 180 | return NULL; 181 | 182 | unsigned int hashValue = hashPJW(name)%HASH_SIZE; 183 | 184 | Entry *tmp = hashTable[hashValue]; 185 | for(;tmp!=NULL;tmp=tmp->next){ 186 | if(strcmp(tmp->name,name)==0) 187 | return tmp->type; 188 | } 189 | 190 | // Error: No such name 191 | return NULL; 192 | } 193 | 194 | void checkFuncDeclaration(){ 195 | int i=0; 196 | Entry *itor = NULL; 197 | for(;itype!=NULL&&itor->type->kind==FUNCTION&&itor->type->u.function->isDefined==0){ 202 | printf("Error type 18 at Line %d: Undefined function \"%s\".\n",itor->type->u.function->line,itor->type->u.function->name); 203 | } 204 | itor = itor->next; 205 | } 206 | } 207 | } 208 | } 209 | -------------------------------------------------------------------------------- /Project3/HashTable.h: -------------------------------------------------------------------------------- 1 | #ifndef HASHTABLE_H 2 | #define HASHTABLE_H 3 | 4 | #include "SyntaxTree.h" 5 | #include "Semantic.h" 6 | #include 7 | 8 | #define HASH_SIZE 1024 9 | 10 | typedef struct Entry_{ 11 | char *name; 12 | Type type; 13 | struct Entry_ *next; 14 | } Entry; 15 | 16 | extern Entry *hashTable[HASH_SIZE]; 17 | 18 | void initTable(); 19 | Type getTable(char *name); 20 | 21 | int varInsertTable(FieldList value); 22 | int varInsertCheck(FieldList var); 23 | 24 | int funcInsertTable(Function func); 25 | int funcInsertCheck(Function func); 26 | 27 | int structInsertTable(Structure structure); 28 | int structInsertCheck(Structure structure); 29 | 30 | void checkFuncDeclaration(); 31 | #endif 32 | -------------------------------------------------------------------------------- /Project3/InterCode.c: -------------------------------------------------------------------------------- 1 | #include"stdlib.h" 2 | #include"stdio.h" 3 | #include"string.h" 4 | #include"InterCode.h" 5 | 6 | InterCode code_head=NULL; 7 | InterCode code_tail=NULL; 8 | 9 | int temVarNo = 1; 10 | int labelNo = 1; 11 | int varNo = 1; 12 | char *zeroStr; 13 | char *oneStr; 14 | char *neStr; 15 | 16 | void insertCode(InterCode p){ 17 | if(p==NULL) 18 | exit(-1); 19 | //assert(p!=NULL); 20 | p->pre=NULL; 21 | p->next=NULL; 22 | if(code_head==NULL){ 23 | code_head = p; 24 | code_tail = p; 25 | } 26 | else{ 27 | p->pre = code_tail; 28 | code_tail->next = p; 29 | code_tail = p; 30 | } 31 | } 32 | 33 | void deleteCode(InterCode p){ 34 | if(p==NULL) 35 | exit(-1); 36 | //assert(p!=NULL); 37 | if(p==code_head){ 38 | code_head = p->next; 39 | } 40 | else{ 41 | p->pre->next = p->next; 42 | } 43 | 44 | if(p==code_tail){ 45 | code_tail = p->pre; 46 | } 47 | else{ 48 | p->next->pre = p->pre; 49 | } 50 | } 51 | 52 | void printOp(Operand p, FILE* fp){ 53 | if(p==NULL) 54 | exit(-1); 55 | //assert(p!=NULL); 56 | char str[50]; 57 | memset(str, 0, sizeof(str)); 58 | switch(p->kind){ 59 | case TEMPVAR: 60 | sprintf(str, "t%d ", p->u.var_no); 61 | fputs(str, fp); 62 | break; 63 | case VARIABLE: 64 | if(p->u.value==NULL) 65 | exit(-1); 66 | sprintf(str, "%s ", p->u.value); 67 | fputs(str, fp); 68 | break; 69 | case CONSTANT: 70 | sprintf(str, "#%s ", p->u.value); 71 | fputs(str, fp); 72 | break; 73 | case VADDRESS: 74 | fputs("*", fp); 75 | assert(p->u.addr!=NULL); 76 | fputs(p->u.addr->u.value, fp); 77 | break; 78 | case LABEL: 79 | sprintf(str, "label%d ", p->u.var_no); 80 | fputs(str, fp); 81 | break; 82 | case FUNCTION_: 83 | sprintf(str, "%s ", p->u.value); 84 | fputs(str, fp); 85 | break; 86 | case TADDRESS: 87 | fputs("*t",fp); 88 | sprintf(str,"%d",p->u.addr->u.var_no); 89 | fputs(str,fp); 90 | break; 91 | default: 92 | assert(0); 93 | } 94 | } 95 | 96 | void printCode(char* fileName){ 97 | FILE* fp = fopen(fileName, "w"); 98 | if(fp==NULL){ 99 | printf("ERROR: Can not open file \"%s\".",fileName); 100 | return; 101 | } 102 | InterCode p; 103 | for(p=code_head;p!=NULL;p=p->next){ 104 | switch(p->kind){ 105 | case ASSIGN_N: 106 | printOp(p->u.assign.left, fp); 107 | fputs(":= ", fp); 108 | printOp(p->u.assign.right, fp); 109 | break; 110 | case ADD_N: 111 | printOp(p->u.binop.result, fp); 112 | fputs(":= ", fp); 113 | printOp(p->u.binop.op1, fp); 114 | fputs("+ ", fp); 115 | printOp(p->u.binop.op2, fp); 116 | break; 117 | case SUB_N: 118 | printOp(p->u.binop.result, fp); 119 | fputs(":= ", fp); 120 | printOp(p->u.binop.op1, fp); 121 | fputs("- ", fp); 122 | printOp(p->u.binop.op2, fp); 123 | break; 124 | case MUL_N: 125 | printOp(p->u.binop.result, fp); 126 | fputs(":= ", fp); 127 | printOp(p->u.binop.op1, fp); 128 | fputs("* ", fp); 129 | printOp(p->u.binop.op2, fp); 130 | break; 131 | case DIV_N: 132 | printOp(p->u.binop.result, fp); 133 | fputs(":= ", fp); 134 | printOp(p->u.binop.op1, fp); 135 | fputs("/ ", fp); 136 | printOp(p->u.binop.op2, fp); 137 | break; 138 | case RETURN_N: 139 | fputs("RETURN ", fp); 140 | printOp(p->u.sinop.op, fp); 141 | break; 142 | case LABEL_N: 143 | fputs("LABEL ", fp); 144 | printOp(p->u.sinop.op, fp); 145 | fputs(": ", fp); 146 | break; 147 | case GOTO_N: 148 | fputs("GOTO ", fp); 149 | printOp(p->u.sinop.op, fp); 150 | break; 151 | case IFGOTO_N: 152 | fputs("IF ", fp); 153 | printOp(p->u.triop.x, fp); 154 | fputs(p->u.triop.op, fp); 155 | fputs(" ", fp); 156 | printOp(p->u.triop.y, fp); 157 | fputs("GOTO ", fp); 158 | printOp(p->u.triop.label, fp); 159 | break; 160 | case READ_N: 161 | fputs("READ ", fp); 162 | printOp(p->u.sinop.op, fp); 163 | break; 164 | case WRITE_N: 165 | fputs("WRITE ", fp); 166 | printOp(p->u.sinop.op, fp); 167 | break; 168 | case CALL_N: 169 | printOp(p->u.assign.left, fp); 170 | fputs(":= CALL ", fp); 171 | printOp(p->u.assign.right, fp); 172 | break; 173 | case ARG_N: 174 | fputs("ARG ", fp); 175 | printOp(p->u.sinop.op, fp); 176 | break; 177 | case FUNCTION_N: 178 | fputs("FUNCTION ", fp); 179 | printOp(p->u.sinop.op, fp); 180 | fputs(": ", fp); 181 | break; 182 | case PARAM_N: 183 | fputs("PARAM ", fp); 184 | printOp(p->u.sinop.op, fp); 185 | break; 186 | case DEC_N: 187 | fputs("DEC ", fp); 188 | printOp(p->u.dec.op, fp); 189 | char sizeStr[16]; 190 | sprintf(sizeStr, "%d", p->u.dec.size); 191 | fputs(sizeStr, fp); 192 | break; 193 | case ADDRESS_N: 194 | printOp(p->u.assign.left, fp); 195 | fputs(":= &", fp); 196 | printOp(p->u.assign.right, fp); 197 | break; 198 | default: 199 | assert(0); 200 | } 201 | fputs("\n", fp); 202 | } 203 | fclose(fp); 204 | } 205 | 206 | void optimizeGoto() 207 | { 208 | InterCode c; 209 | for(c=code_head;c!=NULL;c=c->next) 210 | { 211 | if(c->kind==IFGOTO_N) 212 | { 213 | InterCode c1=c; 214 | InterCode c2=c->next; 215 | if(c2==NULL) 216 | continue; 217 | InterCode c3=c2->next; 218 | if(c3==NULL) 219 | continue; 220 | if(c2->kind==GOTO_N&&c3->kind==LABEL_N&&c1->u.triop.label==c3->u.sinop.op) 221 | { 222 | c1->u.triop.label=c2->u.sinop.op; 223 | deleteCode(c2); 224 | if(strcmp(c1->u.triop.op,"==")==0) 225 | { 226 | char* newop = malloc(4); 227 | memset(newop, 0, 4); 228 | strcpy(newop,"!="); 229 | c1->u.triop.op=newop; 230 | } 231 | else if(strcmp(c1->u.triop.op,"!=")==0) 232 | { 233 | char* newop = malloc(4); 234 | memset(newop, 0, 4); 235 | strcpy(newop,"=="); 236 | c1->u.triop.op=newop; 237 | } 238 | else if(strcmp(c1->u.triop.op,">=")==0) 239 | { 240 | char* newop = malloc(4); 241 | memset(newop, 0, 4); 242 | strcpy(newop,"<"); 243 | c1->u.triop.op=newop; 244 | } 245 | else if(strcmp(c1->u.triop.op,"<")==0) 246 | { 247 | char* newop = malloc(4); 248 | memset(newop, 0, 4); 249 | strcpy(newop,">="); 250 | c1->u.triop.op=newop; 251 | } 252 | else if(strcmp(c1->u.triop.op,">")==0) 253 | { 254 | char* newop = malloc(4); 255 | memset(newop, 0, 4); 256 | strcpy(newop,"<="); 257 | c1->u.triop.op=newop; 258 | } 259 | else if(strcmp(c1->u.triop.op,"<=")==0) 260 | { 261 | char* newop = malloc(4); 262 | memset(newop, 0, 4); 263 | strcpy(newop,">"); 264 | c1->u.triop.op=newop; 265 | } 266 | } 267 | } 268 | else if(c->kind==GOTO_N) 269 | { 270 | InterCode c1=c; 271 | InterCode c2=c->next; 272 | if(c2==NULL) 273 | continue; 274 | if(c2->kind==LABEL_N&&c1->u.sinop.op==c2->u.sinop.op) 275 | deleteCode(c1); 276 | } 277 | } 278 | } 279 | 280 | void deleteLabel() 281 | { 282 | Label_No head=malloc(sizeof(struct Label_No_)); 283 | head->no=-1; 284 | head->next=NULL; 285 | Label_No tail=head; 286 | InterCode c=code_head; 287 | 288 | while(c!=NULL) 289 | { 290 | if(c->kind==GOTO_N) 291 | { 292 | Label_No temp=malloc(sizeof(struct Label_No_)); 293 | temp->no=c->u.sinop.op->u.var_no; 294 | temp->next=NULL; 295 | tail->next=temp; 296 | tail=temp; 297 | } 298 | else if(c->kind==IFGOTO_N) 299 | { 300 | Label_No temp=malloc(sizeof(struct Label_No_)); 301 | temp->no=c->u.triop.label->u.var_no; 302 | temp->next=NULL; 303 | tail->next=temp; 304 | tail=temp; 305 | } 306 | c=c->next; 307 | } 308 | 309 | c=code_head; 310 | while(c!=NULL) 311 | { 312 | if(c->kind==LABEL_N) 313 | { 314 | int no=c->u.sinop.op->u.var_no; 315 | Label_No ln=head; 316 | while(ln!=NULL) 317 | { 318 | if(ln->no==no)break; 319 | ln=ln->next; 320 | } 321 | InterCode c1=c; 322 | c=c->next; 323 | if(ln==NULL) 324 | deleteCode(c1); 325 | } 326 | else 327 | c=c->next; 328 | } 329 | 330 | tail=NULL; 331 | while(head!=NULL) 332 | { 333 | Label_No ln=head; 334 | head=head->next; 335 | free(ln); 336 | } 337 | } 338 | 339 | void figureCon() 340 | { 341 | InterCode p; 342 | for(p=code_head;p!=NULL;) 343 | { 344 | if(p->kind==ADD_N||p->kind==SUB_N||p->kind==MUL_N||p->kind==DIV_N) 345 | { 346 | Operand op1 = p->u.binop.op1; 347 | Operand op2 = p->u.binop.op2; 348 | Operand result = p->u.binop.result; 349 | 350 | if(result->kind==TEMPVAR&&op1->kind==CONSTANT&&op2->kind==CONSTANT) 351 | { 352 | int o1=atoi(op1->u.value); 353 | int o2=atoi(op2->u.value); 354 | int r=0; 355 | switch(p->kind){ 356 | case ADD_N:r=o1+o2;break; 357 | case SUB_N:r=o1-o2;break; 358 | case MUL_N:r=o1*o2;break; 359 | case DIV_N:r=o1/o2;break; 360 | default:break; 361 | } 362 | result->kind=CONSTANT; 363 | result->u.value = malloc(32); 364 | sprintf(result->u.value,"%d",r); 365 | InterCode tmp = p; 366 | p = p->next; 367 | deleteCode(tmp); 368 | continue; 369 | } 370 | } 371 | p = p->next; 372 | } 373 | } 374 | -------------------------------------------------------------------------------- /Project3/InterCode.h: -------------------------------------------------------------------------------- 1 | #ifndef _INTERCODE_H 2 | #define _INTERCODE_H 3 | 4 | #include 5 | 6 | typedef struct Operand_* Operand; 7 | typedef struct InterCode_* InterCode; 8 | typedef struct Label_No_* Label_No; 9 | 10 | 11 | typedef struct Operand_{ 12 | enum{TEMPVAR,VARIABLE,CONSTANT,VADDRESS,LABEL,FUNCTION_,TADDRESS }kind; 13 | 14 | union{ 15 | int var_no; 16 | char* value; 17 | Operand addr; 18 | }u; 19 | Operand next; 20 | } Operand_; 21 | 22 | typedef struct InterCode_{ 23 | enum{ASSIGN_N,ADD_N,SUB_N,MUL_N,DIV_N,RETURN_N,LABEL_N,GOTO_N,IFGOTO_N,READ_N,WRITE_N,CALL_N,ARG_N,FUNCTION_N,PARAM_N,DEC_N,ADDRESS_N}kind; 24 | 25 | union{ 26 | struct{ Operand op; }sinop; 27 | 28 | struct{ Operand left,right; }assign; 29 | 30 | struct{ Operand op1,op2,result; }binop; 31 | 32 | struct{ Operand x; Operand y; Operand label; char *op; }triop; 33 | 34 | struct{ Operand op; int size; }dec; 35 | }u; 36 | 37 | InterCode pre; 38 | InterCode next; 39 | } InterCode_; 40 | 41 | typedef struct Label_No_ 42 | { 43 | int no; 44 | Label_No next; 45 | } Label_No_; 46 | 47 | void insertCode(InterCode c); 48 | void deleteCode(InterCode c); 49 | void printCode(char *fileName); 50 | void printOp(Operand p,FILE *fp); 51 | 52 | extern InterCode code_head,code_tail; 53 | extern char* zeroStr; 54 | extern char* oneStr; 55 | extern char* neStr; 56 | extern int temVarNo; 57 | extern int labelNo; 58 | extern int varNo; 59 | 60 | void optimizeGoto(); 61 | void deleteLabel(); 62 | void figureCon(); 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /Project3/Makefile: -------------------------------------------------------------------------------- 1 | parser: 2 | bison -d syntax.y 3 | flex lexical.l 4 | gcc -c lex.yy.c -o lex.o 5 | gcc main.c syntax.tab.c SyntaxTree.c HashTable.c Semantic.c InterCode.c lex.o -lfl -ly -o parser 6 | 7 | lexical: 8 | bison -d syntax.y 9 | flex lexical.l 10 | 11 | syntax: 12 | bison -d syntax.y 13 | 14 | clean: 15 | rm lex.yy.c lex.o syntax.tab.c syntax.tab.h parser 16 | 17 | remake: 18 | make clean 19 | make 20 | 21 | test: 22 | ./parser ./testcase/testcase1.txt out1.ir 23 | ./parser ./testcase/testcase2.txt out2.ir 24 | -------------------------------------------------------------------------------- /Project3/Semantic.h: -------------------------------------------------------------------------------- 1 | #ifndef SEMANTIC_H 2 | #define SEMANTIC_H 3 | 4 | #include "SyntaxTree.h" 5 | #include "InterCode.h" 6 | 7 | #define BINGO 0 8 | #define ERROR_REDEFINE 1 9 | #define ERROR_DECLARATION_CONFLICT 2 10 | #define ERROR_DOMAIN_REDEFINE 3 11 | 12 | #define FUNC_IS_DECLARED 4 13 | 14 | #define FROM_VARIABLE 1 15 | #define FROM_FIELD 2 16 | #define FROM_PARAM 3 17 | 18 | typedef struct Type_* Type; 19 | typedef struct Structure_* Structure; 20 | typedef struct FieldList_* FieldList; 21 | typedef struct Function_* Function; 22 | 23 | struct Type_{ 24 | enum { BASIC,ARRAY,STRUCTURE,FUNCTION } kind; 25 | union{ 26 | // basic type 27 | int basic; 28 | 29 | // array information 30 | struct { Type elem; int size;} array; 31 | 32 | // structure information 33 | Structure structure; 34 | 35 | // function information 36 | Function function; 37 | } u; 38 | enum { LEFT,RIGHT,BOTH } assign; 39 | }; 40 | 41 | struct Structure_{ 42 | char *name; 43 | FieldList domain; 44 | }; 45 | 46 | struct FieldList_{ 47 | // Field name 48 | char *name; 49 | // Field type 50 | Type type; 51 | // next field 52 | FieldList tail; 53 | }; 54 | 55 | struct Function_{ 56 | char *name; 57 | int isDefined; 58 | int line; 59 | Type retype; 60 | FieldList param; 61 | }; 62 | 63 | int typeEqual(Type lhs, Type rhs); 64 | int typeSize(Type type); 65 | int structEqual(Structure lhs, Structure rhs); 66 | int valueEqual(FieldList lhs, FieldList rhs); 67 | 68 | void Program(Node* root); 69 | void ExtDefList(Node *n); 70 | void ExtDef(Node *n); 71 | void ExtDecList(Node *n, Type type); 72 | 73 | Type Specifier(Node *n); 74 | Type StructSpecifier(Node *n); 75 | 76 | FieldList VarDec(Node *n, Type type, int from); 77 | Function FunDec(Node *n, Type type); 78 | FieldList VarList(Node *n); 79 | FieldList ParamDec(Node *n); 80 | 81 | void CompSt(Node *n, Type retype); 82 | void StmtList(Node *n, Type retype); 83 | void Stmt(Node *n, Type retype); 84 | 85 | FieldList DefList(Node *n, int from); 86 | FieldList Def(Node *n, int from); 87 | FieldList DecList(Node *n, Type type, int from); 88 | FieldList Dec(Node *n, Type type, int from); 89 | 90 | Type Exp(Node *n, Operand place); 91 | Type Exp_Cond(Node *n,Operand label_true,Operand label_false); 92 | int Args(Node *n, FieldList param, Operand arg); 93 | 94 | #endif 95 | -------------------------------------------------------------------------------- /Project3/SyntaxTree.c: -------------------------------------------------------------------------------- 1 | #include "SyntaxTree.h" 2 | #include 3 | 4 | Node* init(char identifier[], char value[], _Type type, int line){ 5 | Node* root = malloc(sizeof(Node)); 6 | 7 | root->height = 0; 8 | strcpy(root->identifier, identifier); 9 | 10 | if(value != NULL) 11 | strcpy(root->value, value); 12 | else 13 | root->value[0]='\0'; 14 | 15 | root->type = type; 16 | root->line = line; 17 | 18 | return root; 19 | } 20 | 21 | 22 | void insert(Node *p, Node *child){ 23 | if(p == NULL || child == NULL) 24 | return; 25 | 26 | if(p->child == NULL){ 27 | p->child = child; 28 | return; 29 | } 30 | 31 | Node *temp = p->child; 32 | while(temp->sibling != NULL) 33 | temp = temp->sibling; 34 | temp->sibling = child; 35 | 36 | } 37 | 38 | void traverseTree(Node* p){ 39 | if(p == NULL) 40 | return; 41 | 42 | // Print Node 43 | 44 | for(int i=0; iheight; i++) 45 | printf(" "); 46 | switch(p->type){ 47 | case TYPE_NONTERMINAL: 48 | // non-terminals 49 | printf("%s (%d)\n",p->identifier,p->line); 50 | break; 51 | case TYPE_OCT: 52 | printf("%s: %d\n",p->identifier,(int)strtol(p->value,NULL,8)); 53 | break; 54 | case TYPE_HEX: 55 | printf("%s: %d\n",p->identifier,(int)strtol(p->value,NULL,16)); 56 | break; 57 | case TYPE_KEYWORD_BRACKET: 58 | case TYPE_KEYWORD_PUNCTUATION: 59 | case TYPE_KEYWORD_OPERATOR: 60 | // LP|RP|LB|RB|LC|RC|PUNCUTATION|OPERATOR 61 | printf("%s\n",p->identifier); 62 | break; 63 | default: 64 | // terminals 65 | printf("%s: %s\n",p->identifier,p->value); 66 | break; 67 | } 68 | 69 | if(p->child != NULL) 70 | p->child->height = p->height+1; 71 | if(p->sibling != NULL) 72 | p->sibling->height = p->height; 73 | traverseTree(p->child); 74 | traverseTree(p->sibling); 75 | 76 | } 77 | 78 | void cleanTree(Node *p){ 79 | if(p==NULL) 80 | return; 81 | 82 | cleanTree(p->child); 83 | cleanTree(p->sibling); 84 | free(p); 85 | } 86 | 87 | -------------------------------------------------------------------------------- /Project3/SyntaxTree.h: -------------------------------------------------------------------------------- 1 | #ifndef SYNTAXTREE_H 2 | #define SYNTAXTREE_H 3 | 4 | #include 5 | #include 6 | 7 | #define IDENTIFIER_LENGTH 32 8 | #define VALUE_LENGTH 32 9 | 10 | #define TYPE_KEYWORD 0 11 | #define TYPE_KEYWORD_RELOP 1 12 | #define TYPE_KEYWORD_BRACKET 2 13 | #define TYPE_KEYWORD_PUNCTUATION 3 14 | #define TYPE_KEYWORD_OPERATOR 4 15 | 16 | #define TYPE_NONTERMINAL 65536 17 | 18 | #define TYPE_ID 128 19 | 20 | #define TYPE_INT 256 21 | #define TYPE_OCT 257 22 | #define TYPE_HEX 258 23 | 24 | #define TYPE_FLOAT 512 25 | #define TYPE_SFLOAT 513 26 | 27 | #define TYPE_STRING 1024 28 | 29 | extern int yylineno; 30 | 31 | typedef int _Type; 32 | 33 | typedef struct Node{ 34 | //TODO: Complete Node Structure 35 | 36 | char identifier[IDENTIFIER_LENGTH]; 37 | char value[VALUE_LENGTH]; 38 | _Type type; 39 | int line; 40 | int height; 41 | 42 | // Children Brother Express 43 | struct Node *child; 44 | struct Node *sibling; 45 | 46 | }Node; 47 | 48 | extern Node* init(char identifier[], char value[], _Type type, int line); 49 | extern void insert(Node *p, Node *child); 50 | extern void traverseTree(Node *p); 51 | extern void cleanTree(Node *p); 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /Project3/irsim/irsim.py: -------------------------------------------------------------------------------- 1 | import sys, os, platform 2 | from PyQt4.QtCore import * 3 | from PyQt4.QtGui import * 4 | import ui_mainwindow, resources_rc 5 | 6 | __version__ = "1.0.2" 7 | 8 | class IRSyntaxError(Exception): pass 9 | class DuplicatedLabelError(Exception): pass 10 | class UndefinedLabelError(Exception): pass 11 | class DuplicatedVariableError(Exception): pass 12 | class CurrentFunctionNoneError(Exception): pass 13 | 14 | class IRSim(QMainWindow, ui_mainwindow.Ui_MainWindow): 15 | def __init__(self, parent=None): 16 | super(IRSim, self).__init__(parent) 17 | 18 | # Some brushes 19 | self.cyanBrush = QBrush(Qt.cyan) 20 | self.yellowBrush = QBrush(Qt.yellow) 21 | self.noBrush = QBrush() 22 | 23 | # Read the UI design from Qt Designer file 24 | self.setupUi(self) 25 | self.rowLabel = QLabel() 26 | self.rowLabel.setFrameStyle(QFrame.StyledPanel|QFrame.Sunken) 27 | self.statusBar().addPermanentWidget(self.rowLabel) 28 | 29 | # Initialize some values 30 | self.initialize() 31 | 32 | # Connect the signals with desired slots 33 | self.connect(self.actionQuit, SIGNAL('triggered()'), self.close) 34 | self.connect(self.action_Open, SIGNAL('triggered()'), self.fileOpen) 35 | self.connect(self.actionRun, SIGNAL('triggered()'), self.run) 36 | self.connect(self.actionStop, SIGNAL('triggered()'), self.stop) 37 | self.connect(self.actionStep, SIGNAL('triggered()'), self.step) 38 | self.connect(self.actionAbout, SIGNAL('triggered()'), self.helpAbout) 39 | self.connect(self.codeList, SIGNAL('currentRowChanged(int)'), self.updateRowLabel) 40 | 41 | # Open an existing IR file 42 | def fileOpen(self): 43 | if not self.okToContinue(): 44 | return 45 | dir = '.' if self.filename is None else os.path.dirname(self.filename) 46 | fname = unicode(QFileDialog.getOpenFileName(self, 47 | "IR Simulator - Open IR file", dir, 48 | "IR files (*.ir)")) 49 | if fname: 50 | self.initialize() 51 | self.loadFile(fname) 52 | 53 | # Initialize the VM settings 54 | def initialize(self): 55 | self.filename = None 56 | self.ip = -1 57 | self.entranceIP = -1 58 | self.pauseRunning = False 59 | self.offset = 0 60 | self.instrCnt = 0 61 | self.codes = list() 62 | self.mem = None 63 | self.functionDict = dict() 64 | self.currentFunction = None 65 | self.symTable = dict() 66 | self.labelTable = dict() 67 | self.callStack = list() 68 | self.argumentStack = list() 69 | self.codeList.clear() 70 | self.watchTable.setRowCount(0) 71 | self.watchTable.clearContents() 72 | self.console.clear() 73 | self.updateStatus(None) 74 | 75 | # Load the contents of the file 76 | def loadFile(self, fname): 77 | fp = open(fname, 'r') 78 | lineno = 0 79 | for line in fp: 80 | if line.isspace(): continue 81 | if self.sanity_check(line, lineno): 82 | self.codeList.addItem(line.strip().replace('\t', ' ')) 83 | else: 84 | break 85 | lineno += 1 86 | else: 87 | self.filename = fname 88 | self.lineno = lineno 89 | fp.close() 90 | if self.entranceIP == -1: 91 | QMessageBox.critical(self, 'Error', 'Cannot find program entrance. Please make sure the \'main\' function does exist.') 92 | if (self.filename is None) or (not self.labelCheck()) or (self.offset > 0x100000) or (self.entranceIP == -1): 93 | self.updateStatus('Loading failed.') 94 | self.initialize() 95 | return 96 | 97 | self.mem = [0] * 262144 98 | self.displayWatchTable() 99 | self.updateStatus('File loaded successfully.') 100 | 101 | # Run the codes 102 | def run(self): 103 | self.stop() 104 | self.ip = self.entranceIP 105 | while True: 106 | if self.ip < 0 or self.ip >= len(self.codes): 107 | error_code = 3 108 | break 109 | code = self.codes[self.ip] 110 | error_code = self.execute_code(code) # error_code : [0=nextIR; 1=finish; 2=memAccessError; 3=IPError] 111 | if error_code > 0: 112 | break 113 | self.ip += 1 114 | if error_code == 1: 115 | QMessageBox.information(self, 'Finish', 'Program has exited gracefully.\nTotal instructions = %d' % self.instrCnt) 116 | self.updateStatus('Simulation OK. Instruction count = %d' % self.instrCnt) 117 | elif error_code == 2: 118 | QMessageBox.critical(self, 'Error', 'An error occurred at line %d: Illegal memory access. \nIf this message keeps popping out, please reload the source file' % (self.ip+1)) 119 | self.updateStatus('Simulation failed: Memory access out of bound.') 120 | elif error_code == 3: 121 | QMessageBox.warning(self, 'Warning', 'Program Counter goes out of bound. The running program will be terminated instantly.') 122 | self.updateStatus('Simulation failed: PC error.') 123 | self.watchTable.setRowCount(0) 124 | self.displayWatchTable() 125 | self.ip = -1 126 | 127 | # Stop the running 128 | def stop(self): 129 | if self.ip != -1: 130 | self.codeList.item(self.ip).setBackground(self.noBrush) 131 | self.ip = -1 132 | self.instrCnt = 0 133 | self.pauseRunning = False 134 | self.watchTable.setRowCount(0) 135 | self.mem = [0] * 262144 136 | self.callStack = list() 137 | self.argumentStack = list() 138 | self.displayWatchTable() 139 | self.codeList.setCurrentRow(-1) 140 | self.console.clear() 141 | 142 | # Step by step 143 | def step(self): 144 | if self.ip == -1: 145 | self.stop() 146 | self.pauseRunning = True 147 | self.ip = self.entranceIP - 1 148 | else: 149 | self.codeList.item(self.ip).setBackground(self.noBrush) 150 | self.ip += 1 151 | if self.ip < 0 or self.ip >= len(self.codes): 152 | QMessageBox.warning(self, 'Warning', 'Program Counter goes out of bound. The running program will be terminated instantly.') 153 | self.updateStatus('Simulation failed: PC error.') 154 | self.ip = -1 155 | self.pauseRunning = False 156 | return 157 | code = self.codes[self.ip] 158 | error_code = self.execute_code(code) 159 | if error_code == 1: 160 | QMessageBox.information(self, 'Finish', 'Program has exited gracefully.\nTotal instructions = %d' % self.instrCnt) 161 | self.updateStatus('Simulation OK. Instruction count = %d' % self.instrCnt) 162 | self.ip = -1 163 | self.pauseRunning = False 164 | elif error_code == 2: 165 | QMessageBox.critical(self, 'Error', 'An error occurred at line %d: Illegal memory access' % (self.ip+1)) 166 | self.updateStatus('Simulation failed: Memory access out of bound') 167 | self.ip = -1 168 | self.pauseRunning = False 169 | else: 170 | self.codeList.item(self.ip).setBackground(self.cyanBrush) 171 | self.codeList.setCurrentRow(self.ip) 172 | self.watchTable.setRowCount(0) 173 | self.displayWatchTable() 174 | 175 | # Display the ABOUT dialog 176 | def helpAbout(self): 177 | QMessageBox.about(self, "About IR Simulator", 178 | """IR Simulator v {0} 179 |

Copyright © 2012 Grieve. 180 | All rights reserved. 181 |

This application can be used to simulate the IR 182 | designed for the Compiler course here at NJU. 183 |

Python {1} - Qt {2} - PyQt {3} on {4}""".format( 184 | __version__, platform.python_version(), 185 | QT_VERSION_STR, PYQT_VERSION_STR, 186 | platform.system())) 187 | 188 | # When current file is running, warn the user when he want to open a new file 189 | def okToContinue(self): 190 | if self.ip != -1: 191 | reply = QMessageBox.question(self, 192 | 'IR Simulator - Warning', 193 | 'You are running a file currently. Stop the running and proceed?', 194 | QMessageBox.Yes|QMessageBox.No) 195 | if reply == QMessageBox.No: 196 | return False 197 | self.ip = -1; 198 | return True 199 | 200 | # Update status bar, window title and enable actions 201 | def updateStatus(self, message): 202 | if message: self.statusBar().showMessage(message, 5000) 203 | if self.filename is None: 204 | self.setWindowTitle('IR Simulator') 205 | self.actionRun.setEnabled(False) 206 | self.actionStop.setEnabled(False) 207 | self.actionStep.setEnabled(False) 208 | else: 209 | self.setWindowTitle('IR Simulator - {0}'.format(os.path.basename(self.filename))) 210 | self.actionRun.setEnabled(True) 211 | self.actionStop.setEnabled(True) 212 | self.actionStep.setEnabled(True) 213 | 214 | # Update selected line in codeList 215 | def updateRowLabel(self): 216 | row = self.codeList.currentRow() 217 | if row >= 0: 218 | self.rowLabel.setText('Line %d' % (row+1)) 219 | else: 220 | self.rowLabel.setText('') 221 | 222 | # Check the syntax of the line and update symbol&label table 223 | def sanity_check(self, code, lineno): 224 | strs = code.split() 225 | relops = [ '>', '<', '>=', '<=', '==', '!=' ] 226 | arithops = [ '+', '-', '*', '/' ] 227 | try: 228 | if strs[0] == 'LABEL' or strs[0] == 'FUNCTION': 229 | if len(strs) != 3 or strs[2] != ':': 230 | raise IRSyntaxError 231 | if strs[1] in self.labelTable: 232 | raise DuplicatedLabelError 233 | self.labelTable[strs[1]] = lineno 234 | if strs[1] == 'main': 235 | if strs[0] == 'LABEL': raise IRSyntaxError 236 | self.entranceIP = lineno 237 | if strs[0] == 'FUNCTION': 238 | self.currentFunction = strs[1] 239 | self.functionDict[strs[1]] = list() 240 | self.codes.append(('LABEL', strs[1])) 241 | else: 242 | if self.currentFunction == None: 243 | raise CurrentFunctionNoneError 244 | if strs[0] == 'GOTO': 245 | if len(strs) != 2: 246 | raise IRSyntaxError 247 | self.codes.append(('GOTO', strs[1])) 248 | elif strs[0] == 'RETURN' or strs[0] == 'READ' or strs[0] == 'WRITE' or strs[0] == 'ARG' or strs[0] == 'PARAM': 249 | if len(strs) != 2: 250 | raise IRSyntaxError 251 | if (strs[0] == 'READ' or strs[0] == 'PARAM') and (not strs[1][0].isalpha()): 252 | raise IRSyntaxError 253 | self.tableInsert(strs[1]) 254 | self.codes.append((strs[0], strs[1])) 255 | elif strs[0] == 'DEC': 256 | if len(strs) != 3 or (int(strs[2]) % 4 != 0): 257 | raise IRSyntaxError 258 | if strs[1] in self.symTable: 259 | raise DuplicatedVariableError 260 | self.tableInsert(strs[1], int(strs[2]), True) 261 | self.codes.append('DEC') 262 | elif strs[0] == 'IF': 263 | if len(strs) != 6 or strs[4] != 'GOTO' or strs[2] not in relops: 264 | raise IRSyntaxError 265 | self.tableInsert(strs[1]) 266 | self.tableInsert(strs[3]) 267 | self.codes.append(('IF', strs[1], strs[2], strs[3], strs[5])) 268 | else: 269 | if strs[1] != ':=' or len(strs) < 3: 270 | raise IRSyntaxError 271 | if strs[0][0] == '&' or strs[0][0] == '#': 272 | raise IRSyntaxError 273 | self.tableInsert(strs[0]) 274 | if strs[2] == 'CALL': 275 | if len(strs) != 4: 276 | raise IRSyntaxError 277 | self.codes.append(('CALL', strs[0], strs[3])) 278 | elif len(strs) == 3: 279 | self.tableInsert(strs[2]) 280 | self.codes.append(('MOV', strs[0], strs[2])) 281 | elif len(strs) == 5 and strs[3] in arithops: 282 | self.tableInsert(strs[2]) 283 | self.tableInsert(strs[4]) 284 | self.codes.append(('ARITH', strs[0], strs[2], strs[3], strs[4])) 285 | else: 286 | raise IRSyntaxError 287 | except (IRSyntaxError, ValueError): 288 | QMessageBox.critical(self, 'Error', 'Syntax error at line %d:\n\n%s' % (lineno+1, code)) 289 | return False 290 | except DuplicatedLabelError: 291 | QMessageBox.critical(self, 'Error', 'Duplicated label %s at line %d:\n\n%s' % (strs[1], lineno+1, code)) 292 | return False 293 | except DuplicatedVariableError: 294 | QMessageBox.critical(self, 'Error', 'Duplicated variable %s at line %d:\n\n%s' % (strs[1], lineno+1, code)) 295 | return False 296 | except CurrentFunctionNoneError: 297 | QMessageBox.critical(self, 'Error', 'Line %d does not belong to any function:\n\n%s' % (lineno+1, code)) 298 | return False 299 | return True 300 | 301 | # Check if there is undefined label 302 | def labelCheck(self): 303 | try: 304 | for i in range(self.lineno): 305 | code = unicode(self.codeList.item(i).text()) 306 | strs = code.split() 307 | if strs[0] == 'GOTO': 308 | if strs[1] not in self.labelTable: 309 | raise UndefinedLabelError 310 | elif strs[0] == 'IF': 311 | if strs[5] not in self.labelTable: 312 | raise UndefinedLabelError 313 | elif len(strs) > 2 and strs[2] == 'CALL': 314 | if strs[3] not in self.labelTable: 315 | raise UndefinedLabelError 316 | except UndefinedLabelError: 317 | QMessageBox.critical(self, 'Error', 'Undefined label at line %d:\n\n%s' % (i+1, code)) 318 | return False 319 | return True 320 | 321 | # Insert variables into symTable 322 | def tableInsert(self, var, size=4, array=False): 323 | if var.isdigit(): 324 | raise IRSyntaxError 325 | if var[0] == '&' or var[0] == '*': var = var[1:] 326 | elif var[0] == '#': 327 | test = int(var[1:]) 328 | return 329 | if var in self.symTable:return 330 | self.functionDict[self.currentFunction].append(var) 331 | if self.currentFunction == 'main': 332 | self.symTable[var] = self.offset, size, array 333 | self.offset += size 334 | else: 335 | self.symTable[var] = -1, size, array 336 | 337 | # Get Value from a variable 338 | def getValue(self, var): 339 | if var[0] == '#': 340 | return int(var[1:]) 341 | elif var[0] == '&': 342 | return self.symTable[var[1:]][0] 343 | elif var[0] == '*': 344 | return self.mem[self.mem[self.symTable[var[1:]][0] / 4] / 4] 345 | else: 346 | return self.mem[self.symTable[var][0]/ 4] 347 | 348 | # Populate watchTable from symTable 349 | def displayWatchTable(self): 350 | for row, key in enumerate(self.symTable.keys()): 351 | self.watchTable.insertRow(row) 352 | item = QTableWidgetItem(key) 353 | item.setTextAlignment(Qt.AlignRight|Qt.AlignVCenter) 354 | self.watchTable.setItem(row, 0, item) 355 | if self.symTable[key][0] >= 0: 356 | item = QTableWidgetItem(str(self.symTable[key][0])) 357 | else: 358 | item = QTableWidgetItem('N/A') 359 | item.setTextAlignment(Qt.AlignRight|Qt.AlignVCenter) 360 | self.watchTable.setItem(row, 1, item) 361 | if self.symTable[key][0] < 0: 362 | item = QTableWidgetItem('N/A') 363 | elif self.symTable[key][1] > 4: 364 | strs = str(self.mem[(self.symTable[key][0]/4) : (self.symTable[key][0]/4+self.symTable[key][1]/4)]) 365 | item = QTableWidgetItem(strs) 366 | else : 367 | item = QTableWidgetItem(str(self.mem[self.symTable[key][0] / 4])) 368 | 369 | item.setTextAlignment(Qt.AlignRight|Qt.AlignVCenter) 370 | self.watchTable.setItem(row, 2, item) 371 | self.watchTable.sortItems(0) 372 | 373 | # Executed a single line 374 | def execute_code(self, code): 375 | #print 'Excecuting code: ' , code 376 | self.instrCnt += 1 377 | try: 378 | if code[0] == 'READ': 379 | result, ok = QInputDialog.getInteger(self, 'IR Simulator - Read', 'Please enter an integral value for %s' % code[1], 0) 380 | if ok: 381 | self.mem[self.symTable[code[1]][0] / 4] = result 382 | elif code[0] == 'WRITE': 383 | self.console.append(str(self.getValue(code[1]))) 384 | elif code[0] == 'GOTO': 385 | self.ip = self.labelTable[code[1]] 386 | elif code[0] == 'IF': 387 | value1 = self.getValue(code[1]) 388 | value2 = self.getValue(code[3]) 389 | if eval(str(value1) + code[2] + str(value2)): 390 | self.ip = self.labelTable[code[4]] 391 | elif code[0] == 'MOV': 392 | value = self.getValue(code[2]) 393 | if code[1][0] == '*': 394 | self.mem[self.mem[self.symTable[code[1][1:]][0] / 4] / 4] = value 395 | else: 396 | self.mem[self.symTable[code[1]][0] / 4] = value 397 | elif code[0] == 'ARITH': 398 | value1 = self.getValue(code[2]) 399 | value2 = self.getValue(code[4]) 400 | self.mem[self.symTable[code[1]][0] / 4] = eval(str(value1) + code[3] + str(value2)) 401 | elif code[0] == 'RETURN': 402 | if len(self.callStack) == 0: 403 | return 1 404 | else: 405 | returnValue = self.getValue(code[1]) 406 | stackItem = self.callStack.pop() 407 | self.ip = stackItem[0] 408 | for key in stackItem[2].keys(): 409 | self.symTable[key] = stackItem[2][key] 410 | self.offset = stackItem[3] 411 | self.mem[self.symTable[stackItem[1]][0] / 4] = returnValue 412 | elif code[0] == 'CALL': 413 | oldAddrs = dict() 414 | oldOffset = self.offset 415 | for key in self.functionDict[code[2]]: 416 | oldAddrs[key] = self.symTable[key] 417 | self.symTable[key] = self.getNewAddr(self.symTable[key][1]), self.symTable[key][1], self.symTable[key][2] 418 | self.callStack.append((self.ip, code[1], oldAddrs, oldOffset)) 419 | self.ip = self.labelTable[code[2]] 420 | elif code[0] == 'ARG': 421 | self.argumentStack.append(self.getValue(code[1])) 422 | elif code[0] == 'PARAM': 423 | self.mem[self.symTable[code[1]][0] / 4] = self.argumentStack.pop() 424 | # Not finished yet 425 | except IndexError: 426 | return 2 427 | return 0 428 | 429 | def getNewAddr(self, size): 430 | ret = self.offset 431 | self.offset = self.offset + size 432 | return ret 433 | 434 | app = QApplication(sys.argv) 435 | app.setOrganizationName('Nanjing University') 436 | app.setApplicationName('IR Simulator') 437 | app.setWindowIcon(QIcon(':/icon.png')) 438 | app.setStyle('Plastique') 439 | form = IRSim() 440 | form.show() 441 | app.exec_() 442 | 443 | -------------------------------------------------------------------------------- /Project3/irsim/resources_rc.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Unkrible/Compilers/50a13f45ae865d0dfaf8f91d4f44913433ad7dfa/Project3/irsim/resources_rc.pyc -------------------------------------------------------------------------------- /Project3/irsim/ui_mainwindow.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'MainWindow.ui' 4 | # 5 | # Created: Fri Feb 24 09:42:37 2012 6 | # by: PyQt4 UI code generator 4.9.1 7 | # 8 | # WARNING! All changes made in this file will be lost! 9 | 10 | from PyQt4 import QtCore, QtGui 11 | 12 | try: 13 | _fromUtf8 = QtCore.QString.fromUtf8 14 | except AttributeError: 15 | _fromUtf8 = lambda s: s 16 | 17 | class Ui_MainWindow(object): 18 | def setupUi(self, MainWindow): 19 | MainWindow.setObjectName(_fromUtf8("MainWindow")) 20 | MainWindow.resize(800, 600) 21 | sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) 22 | sizePolicy.setHorizontalStretch(0) 23 | sizePolicy.setVerticalStretch(0) 24 | sizePolicy.setHeightForWidth(MainWindow.sizePolicy().hasHeightForWidth()) 25 | MainWindow.setSizePolicy(sizePolicy) 26 | MainWindow.setMinimumSize(QtCore.QSize(800, 600)) 27 | MainWindow.setMaximumSize(QtCore.QSize(800, 600)) 28 | icon = QtGui.QIcon() 29 | icon.addPixmap(QtGui.QPixmap(_fromUtf8(":/icon.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) 30 | MainWindow.setWindowIcon(icon) 31 | self.centralwidget = QtGui.QWidget(MainWindow) 32 | self.centralwidget.setObjectName(_fromUtf8("centralwidget")) 33 | self.layoutWidget = QtGui.QWidget(self.centralwidget) 34 | self.layoutWidget.setGeometry(QtCore.QRect(20, 10, 761, 490)) 35 | self.layoutWidget.setObjectName(_fromUtf8("layoutWidget")) 36 | self.horizontalLayout = QtGui.QHBoxLayout(self.layoutWidget) 37 | self.horizontalLayout.setMargin(0) 38 | self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout")) 39 | self.verticalLayout = QtGui.QVBoxLayout() 40 | self.verticalLayout.setObjectName(_fromUtf8("verticalLayout")) 41 | self.label = QtGui.QLabel(self.layoutWidget) 42 | font = QtGui.QFont() 43 | font.setFamily(_fromUtf8("Verdana")) 44 | font.setBold(True) 45 | font.setWeight(75) 46 | self.label.setFont(font) 47 | self.label.setObjectName(_fromUtf8("label")) 48 | self.verticalLayout.addWidget(self.label) 49 | self.codeList = QtGui.QListWidget(self.layoutWidget) 50 | self.codeList.setEnabled(True) 51 | font = QtGui.QFont() 52 | font.setFamily(_fromUtf8("Arial")) 53 | self.codeList.setFont(font) 54 | self.codeList.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers) 55 | self.codeList.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) 56 | self.codeList.setObjectName(_fromUtf8("codeList")) 57 | self.verticalLayout.addWidget(self.codeList) 58 | self.horizontalLayout.addLayout(self.verticalLayout) 59 | spacerItem = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Minimum) 60 | self.horizontalLayout.addItem(spacerItem) 61 | self.verticalLayout_2 = QtGui.QVBoxLayout() 62 | self.verticalLayout_2.setObjectName(_fromUtf8("verticalLayout_2")) 63 | self.label_2 = QtGui.QLabel(self.layoutWidget) 64 | font = QtGui.QFont() 65 | font.setFamily(_fromUtf8("Verdana")) 66 | font.setBold(True) 67 | font.setWeight(75) 68 | self.label_2.setFont(font) 69 | self.label_2.setObjectName(_fromUtf8("label_2")) 70 | self.verticalLayout_2.addWidget(self.label_2) 71 | self.watchTable = QtGui.QTableWidget(self.layoutWidget) 72 | font = QtGui.QFont() 73 | font.setFamily(_fromUtf8("Arial")) 74 | self.watchTable.setFont(font) 75 | self.watchTable.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers) 76 | self.watchTable.setSelectionMode(QtGui.QAbstractItemView.SingleSelection) 77 | self.watchTable.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) 78 | self.watchTable.setHorizontalScrollMode(QtGui.QAbstractItemView.ScrollPerPixel) 79 | self.watchTable.setObjectName(_fromUtf8("watchTable")) 80 | self.watchTable.setColumnCount(3) 81 | self.watchTable.setRowCount(0) 82 | item = QtGui.QTableWidgetItem() 83 | self.watchTable.setHorizontalHeaderItem(0, item) 84 | item = QtGui.QTableWidgetItem() 85 | self.watchTable.setHorizontalHeaderItem(1, item) 86 | item = QtGui.QTableWidgetItem() 87 | self.watchTable.setHorizontalHeaderItem(2, item) 88 | self.verticalLayout_2.addWidget(self.watchTable) 89 | spacerItem1 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred) 90 | self.verticalLayout_2.addItem(spacerItem1) 91 | self.label_3 = QtGui.QLabel(self.layoutWidget) 92 | font = QtGui.QFont() 93 | font.setFamily(_fromUtf8("Verdana")) 94 | font.setBold(True) 95 | font.setWeight(75) 96 | self.label_3.setFont(font) 97 | self.label_3.setObjectName(_fromUtf8("label_3")) 98 | self.verticalLayout_2.addWidget(self.label_3) 99 | self.console = QtGui.QTextEdit(self.layoutWidget) 100 | font = QtGui.QFont() 101 | font.setFamily(_fromUtf8("Serif")) 102 | self.console.setFont(font) 103 | self.console.setReadOnly(True) 104 | self.console.setObjectName(_fromUtf8("console")) 105 | self.verticalLayout_2.addWidget(self.console) 106 | self.horizontalLayout.addLayout(self.verticalLayout_2) 107 | MainWindow.setCentralWidget(self.centralwidget) 108 | self.menubar = QtGui.QMenuBar(MainWindow) 109 | self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 25)) 110 | self.menubar.setObjectName(_fromUtf8("menubar")) 111 | self.menuFile = QtGui.QMenu(self.menubar) 112 | self.menuFile.setObjectName(_fromUtf8("menuFile")) 113 | self.menuRun = QtGui.QMenu(self.menubar) 114 | self.menuRun.setObjectName(_fromUtf8("menuRun")) 115 | self.menuAbout = QtGui.QMenu(self.menubar) 116 | self.menuAbout.setObjectName(_fromUtf8("menuAbout")) 117 | MainWindow.setMenuBar(self.menubar) 118 | self.statusbar = QtGui.QStatusBar(MainWindow) 119 | self.statusbar.setObjectName(_fromUtf8("statusbar")) 120 | MainWindow.setStatusBar(self.statusbar) 121 | self.toolBar = QtGui.QToolBar(MainWindow) 122 | self.toolBar.setObjectName(_fromUtf8("toolBar")) 123 | MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar) 124 | self.action_Open = QtGui.QAction(MainWindow) 125 | icon1 = QtGui.QIcon() 126 | icon1.addPixmap(QtGui.QPixmap(_fromUtf8(":/filenew.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) 127 | self.action_Open.setIcon(icon1) 128 | self.action_Open.setObjectName(_fromUtf8("action_Open")) 129 | self.actionQuit = QtGui.QAction(MainWindow) 130 | icon2 = QtGui.QIcon() 131 | icon2.addPixmap(QtGui.QPixmap(_fromUtf8(":/filequit.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) 132 | self.actionQuit.setIcon(icon2) 133 | self.actionQuit.setObjectName(_fromUtf8("actionQuit")) 134 | self.actionRun = QtGui.QAction(MainWindow) 135 | self.actionRun.setEnabled(True) 136 | icon3 = QtGui.QIcon() 137 | icon3.addPixmap(QtGui.QPixmap(_fromUtf8(":/run.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) 138 | self.actionRun.setIcon(icon3) 139 | self.actionRun.setObjectName(_fromUtf8("actionRun")) 140 | self.actionStop = QtGui.QAction(MainWindow) 141 | self.actionStop.setEnabled(True) 142 | icon4 = QtGui.QIcon() 143 | icon4.addPixmap(QtGui.QPixmap(_fromUtf8(":/stop.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) 144 | self.actionStop.setIcon(icon4) 145 | self.actionStop.setObjectName(_fromUtf8("actionStop")) 146 | self.actionStep = QtGui.QAction(MainWindow) 147 | self.actionStep.setEnabled(True) 148 | icon5 = QtGui.QIcon() 149 | icon5.addPixmap(QtGui.QPixmap(_fromUtf8(":/step.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) 150 | self.actionStep.setIcon(icon5) 151 | self.actionStep.setObjectName(_fromUtf8("actionStep")) 152 | self.actionAbout = QtGui.QAction(MainWindow) 153 | self.actionAbout.setIcon(icon) 154 | self.actionAbout.setObjectName(_fromUtf8("actionAbout")) 155 | self.menuFile.addAction(self.action_Open) 156 | self.menuFile.addSeparator() 157 | self.menuFile.addAction(self.actionQuit) 158 | self.menuRun.addAction(self.actionRun) 159 | self.menuRun.addAction(self.actionStop) 160 | self.menuRun.addAction(self.actionStep) 161 | self.menuAbout.addAction(self.actionAbout) 162 | self.menubar.addAction(self.menuFile.menuAction()) 163 | self.menubar.addAction(self.menuRun.menuAction()) 164 | self.menubar.addAction(self.menuAbout.menuAction()) 165 | self.toolBar.addAction(self.action_Open) 166 | self.toolBar.addSeparator() 167 | self.toolBar.addAction(self.actionRun) 168 | self.toolBar.addAction(self.actionStep) 169 | self.toolBar.addAction(self.actionStop) 170 | self.toolBar.addSeparator() 171 | self.toolBar.addAction(self.actionQuit) 172 | 173 | self.retranslateUi(MainWindow) 174 | QtCore.QMetaObject.connectSlotsByName(MainWindow) 175 | MainWindow.setTabOrder(self.codeList, self.watchTable) 176 | MainWindow.setTabOrder(self.watchTable, self.console) 177 | 178 | def retranslateUi(self, MainWindow): 179 | MainWindow.setWindowTitle(QtGui.QApplication.translate("MainWindow", "IR Simulator", None, QtGui.QApplication.UnicodeUTF8)) 180 | self.label.setText(QtGui.QApplication.translate("MainWindow", "Code", None, QtGui.QApplication.UnicodeUTF8)) 181 | self.label_2.setText(QtGui.QApplication.translate("MainWindow", "Watch", None, QtGui.QApplication.UnicodeUTF8)) 182 | item = self.watchTable.horizontalHeaderItem(0) 183 | item.setText(QtGui.QApplication.translate("MainWindow", "Variable", None, QtGui.QApplication.UnicodeUTF8)) 184 | item = self.watchTable.horizontalHeaderItem(1) 185 | item.setText(QtGui.QApplication.translate("MainWindow", "Address", None, QtGui.QApplication.UnicodeUTF8)) 186 | item = self.watchTable.horizontalHeaderItem(2) 187 | item.setText(QtGui.QApplication.translate("MainWindow", "Value", None, QtGui.QApplication.UnicodeUTF8)) 188 | self.label_3.setText(QtGui.QApplication.translate("MainWindow", "Console", None, QtGui.QApplication.UnicodeUTF8)) 189 | self.menuFile.setTitle(QtGui.QApplication.translate("MainWindow", "File", None, QtGui.QApplication.UnicodeUTF8)) 190 | self.menuRun.setTitle(QtGui.QApplication.translate("MainWindow", "Run", None, QtGui.QApplication.UnicodeUTF8)) 191 | self.menuAbout.setTitle(QtGui.QApplication.translate("MainWindow", "About", None, QtGui.QApplication.UnicodeUTF8)) 192 | self.toolBar.setWindowTitle(QtGui.QApplication.translate("MainWindow", "toolBar", None, QtGui.QApplication.UnicodeUTF8)) 193 | self.action_Open.setText(QtGui.QApplication.translate("MainWindow", "&Open...", None, QtGui.QApplication.UnicodeUTF8)) 194 | self.action_Open.setStatusTip(QtGui.QApplication.translate("MainWindow", "Open an existing IR file", None, QtGui.QApplication.UnicodeUTF8)) 195 | self.action_Open.setWhatsThis(QtGui.QApplication.translate("MainWindow", "Open", None, QtGui.QApplication.UnicodeUTF8)) 196 | self.action_Open.setShortcut(QtGui.QApplication.translate("MainWindow", "Ctrl+O", None, QtGui.QApplication.UnicodeUTF8)) 197 | self.actionQuit.setText(QtGui.QApplication.translate("MainWindow", "&Quit", None, QtGui.QApplication.UnicodeUTF8)) 198 | self.actionQuit.setStatusTip(QtGui.QApplication.translate("MainWindow", "Quit the application", None, QtGui.QApplication.UnicodeUTF8)) 199 | self.actionQuit.setShortcut(QtGui.QApplication.translate("MainWindow", "Esc", None, QtGui.QApplication.UnicodeUTF8)) 200 | self.actionRun.setText(QtGui.QApplication.translate("MainWindow", "&Run", None, QtGui.QApplication.UnicodeUTF8)) 201 | self.actionRun.setStatusTip(QtGui.QApplication.translate("MainWindow", "Run the code", None, QtGui.QApplication.UnicodeUTF8)) 202 | self.actionRun.setShortcut(QtGui.QApplication.translate("MainWindow", "F5", None, QtGui.QApplication.UnicodeUTF8)) 203 | self.actionStop.setText(QtGui.QApplication.translate("MainWindow", "St&op", None, QtGui.QApplication.UnicodeUTF8)) 204 | self.actionStop.setStatusTip(QtGui.QApplication.translate("MainWindow", "Stop the current running process", None, QtGui.QApplication.UnicodeUTF8)) 205 | self.actionStop.setShortcut(QtGui.QApplication.translate("MainWindow", "F4", None, QtGui.QApplication.UnicodeUTF8)) 206 | self.actionStep.setText(QtGui.QApplication.translate("MainWindow", "St&ep...", None, QtGui.QApplication.UnicodeUTF8)) 207 | self.actionStep.setStatusTip(QtGui.QApplication.translate("MainWindow", "Run the code step by step", None, QtGui.QApplication.UnicodeUTF8)) 208 | self.actionStep.setShortcut(QtGui.QApplication.translate("MainWindow", "F8", None, QtGui.QApplication.UnicodeUTF8)) 209 | self.actionAbout.setText(QtGui.QApplication.translate("MainWindow", "&About...", None, QtGui.QApplication.UnicodeUTF8)) 210 | self.actionAbout.setStatusTip(QtGui.QApplication.translate("MainWindow", "About this application", None, QtGui.QApplication.UnicodeUTF8)) 211 | 212 | import resources_rc 213 | -------------------------------------------------------------------------------- /Project3/irsim/ui_mainwindow.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Unkrible/Compilers/50a13f45ae865d0dfaf8f91d4f44913433ad7dfa/Project3/irsim/ui_mainwindow.pyc -------------------------------------------------------------------------------- /Project3/lexical.l: -------------------------------------------------------------------------------- 1 | %{ 2 | #include 3 | #include 4 | #include "SyntaxTree.h" 5 | #include "syntax.tab.h" 6 | 7 | extern int errorLexFlag; 8 | 9 | int yycolumn = 1; 10 | /* define YY_USER_ACTION */ 11 | #define YY_USER_ACTION yylloc.first_line = yylloc.last_line = yylineno; \ 12 | yylloc.first_column = yycolumn; \ 13 | yylloc.last_column = yycolumn + yyleng - 1; \ 14 | yycolumn += yyleng; 15 | 16 | %} 17 | 18 | %option yylineno 19 | 20 | DELIM [ \t] 21 | WS {DELIM}+ 22 | DIGIT [0-9] 23 | LETTER [A-Za-z] 24 | INT 0|([1-9]{DIGIT}*) 25 | OCT 0([0-7]+) 26 | OCT_ERROR 0[0-9A-WYZa-wyz][0-9A-Za-z]* 27 | HEX 0(x|X)[0-9a-fA-F]+ 28 | HEX_ERROR [0][Xx][0-9A-Za-z]* 29 | FLOAT {INT}(\.{DIGIT}+)? 30 | SFLOAT ((INT\.{DIGIT}*)|({DIGIT}*\.{DIGIT}+))[Ee][+-]?{DIGIT}+ 31 | SFLOAT_ERROR ((INT\.{DIGIT}*)|({DIGIT}*\.{DIGIT}+))[Ee][+-]?([0-9A-Za-z]*) 32 | RELOP >|<|>=|<=|==|!= 33 | ID ({LETTER}|_)({LETTER}|{DIGIT}|_)* 34 | 35 | 36 | %% 37 | 38 | 39 | {WS} { /* tabs */ } 40 | 41 | 42 | "/*"([^\*]|(\*)*[^\*/])*(\*)*"*/" { /* C comments */ } 43 | 44 | "//" { 45 | /* C++ comment */ 46 | while(input() != '\n'); 47 | } 48 | 49 | ";" { 50 | yylval.type_node = init("SEMI",yytext,TYPE_KEYWORD_PUNCTUATION,yylineno); 51 | return SEMI; 52 | } 53 | 54 | "," { 55 | yylval.type_node = init("COMMA",yytext,TYPE_KEYWORD_PUNCTUATION,yylineno); 56 | return COMMA; 57 | } 58 | 59 | 60 | "=" { 61 | yylval.type_node = init("ASSIGNOP",yytext,TYPE_KEYWORD_OPERATOR,yylineno); 62 | return ASSIGNOP; 63 | } 64 | 65 | {RELOP} { 66 | yylval.type_node = init("RELOP",yytext,TYPE_KEYWORD_RELOP,yylineno); 67 | return RELOP; 68 | } 69 | 70 | "+" { 71 | yylval.type_node = init("PLUS",yytext,TYPE_KEYWORD_OPERATOR,yylineno); 72 | return PLUS; 73 | } 74 | 75 | "-" { 76 | yylval.type_node = init("MINUS",yytext,TYPE_KEYWORD_OPERATOR,yylineno); 77 | return MINUS; 78 | } 79 | 80 | "*" { 81 | yylval.type_node = init("STAR",yytext,TYPE_KEYWORD_OPERATOR,yylineno); 82 | return STAR; 83 | } 84 | 85 | "/" { 86 | yylval.type_node = init("DIV",yytext,TYPE_KEYWORD_OPERATOR,yylineno); 87 | return DIV; 88 | } 89 | 90 | "&&" { 91 | yylval.type_node = init("AND",yytext,TYPE_KEYWORD_OPERATOR,yylineno); 92 | return AND; 93 | } 94 | 95 | "||" { 96 | yylval.type_node = init("OR",yytext,TYPE_KEYWORD_OPERATOR,yylineno); 97 | return OR; 98 | } 99 | 100 | "!" { 101 | yylval.type_node = init("NOT",yytext,TYPE_KEYWORD_OPERATOR,yylineno); 102 | return NOT; 103 | } 104 | 105 | "." { 106 | yylval.type_node = init("DOT",yytext,TYPE_KEYWORD_PUNCTUATION,yylineno); 107 | return DOT; 108 | } 109 | 110 | "int"|"float" { 111 | yylval.type_node = init("TYPE",yytext,TYPE_KEYWORD,yylineno); 112 | return TYPE; 113 | } 114 | 115 | "(" { 116 | yylval.type_node = init("LP",yytext,TYPE_KEYWORD_BRACKET,yylineno); 117 | return LP; 118 | } 119 | 120 | ")" { 121 | yylval.type_node = init("RP",yytext,TYPE_KEYWORD_BRACKET,yylineno); 122 | return RP; 123 | } 124 | 125 | "[" { 126 | yylval.type_node = init("LB",yytext,TYPE_KEYWORD_BRACKET,yylineno); 127 | return LB; 128 | } 129 | 130 | "]" { 131 | yylval.type_node = init("RB",yytext,TYPE_KEYWORD_BRACKET,yylineno); 132 | return RB; 133 | } 134 | 135 | "{" { 136 | yylval.type_node = init("LC",yytext,TYPE_KEYWORD_BRACKET,yylineno); 137 | return LC; 138 | } 139 | 140 | "}" { 141 | yylval.type_node = init("RC",yytext,TYPE_KEYWORD_BRACKET,yylineno); 142 | return RC; 143 | } 144 | 145 | "struct" { 146 | yylval.type_node = init("STRUCT",yytext,TYPE_KEYWORD,yylineno); 147 | return STRUCT; 148 | } 149 | 150 | "return" { 151 | yylval.type_node = init("RETURN",yytext,TYPE_KEYWORD,yylineno); 152 | return RETURN; 153 | } 154 | 155 | "if" { 156 | yylval.type_node = init("IF",yytext,TYPE_KEYWORD,yylineno); 157 | return IF; 158 | } 159 | 160 | "else" { 161 | yylval.type_node = init("ELSE",yytext,TYPE_KEYWORD,yylineno); 162 | return ELSE; 163 | } 164 | 165 | "while" { 166 | yylval.type_node = init("WHILE",yytext,TYPE_KEYWORD,yylineno); 167 | return WHILE; 168 | } 169 | 170 | {OCT} { 171 | yylval.type_node = init("INT",yytext,TYPE_OCT,yylineno); 172 | return INT; 173 | } 174 | 175 | {OCT_ERROR} { 176 | printf("Error type A at line %d: Illegal octal number \'%s\'\n", yylineno, yytext); 177 | errorLexFlag = 1; 178 | } 179 | 180 | {HEX} { 181 | yylval.type_node = init("INT",yytext,TYPE_HEX,yylineno); 182 | return INT; 183 | } 184 | 185 | {HEX_ERROR} { 186 | printf("Error type A at line %d: Illegal hexadecimal number \'%s\'\n", yylineno, yytext); 187 | errorLexFlag = 1; 188 | } 189 | 190 | {SFLOAT} { 191 | yylval.type_node = init("FLOAT",yytext,TYPE_SFLOAT,yylineno); 192 | return FLOAT; 193 | } 194 | 195 | {SFLOAT_ERROR} { 196 | printf("Error type A at line %d: Illegal floating point number \'%s\'\n", yylineno, yytext); 197 | errorLexFlag = 1; 198 | } 199 | 200 | {INT} { 201 | yylval.type_node = init("INT",yytext,TYPE_INT,yylineno); 202 | return INT; 203 | } 204 | 205 | {FLOAT} { 206 | yylval.type_node = init("FLOAT",yytext,TYPE_FLOAT,yylineno); 207 | return FLOAT; 208 | } 209 | 210 | \n { yycolumn = 1; } 211 | 212 | {ID} { 213 | yylval.type_node = init("ID",yytext,TYPE_ID,yylineno); 214 | return ID; 215 | } 216 | 217 | 218 | . { 219 | printf("Error type A at line %d: Mysterious character \'%s\'\n" 220 | , yylineno, yytext); 221 | errorLexFlag = 1; 222 | } 223 | 224 | 225 | %% 226 | 227 | /* 228 | int main(int argc, char** argv){ 229 | if (argc > 1) 230 | if (!(yyin = fopen(argv[1], "r"))){ 231 | perror(argv[1]); 232 | return 1; 233 | } 234 | } 235 | while (yylex() != 0) ; 236 | return 0; 237 | } 238 | */ 239 | -------------------------------------------------------------------------------- /Project3/main.c: -------------------------------------------------------------------------------- 1 | #include "SyntaxTree.h" 2 | #include "parse.h" 3 | #include "HashTable.h" 4 | #include "Semantic.h" 5 | #include "InterCode.h" 6 | #include "string.h" 7 | 8 | Node *tree; 9 | int errorLexFlag; 10 | int errorSyntaxFlag; 11 | 12 | int main(int argc, char** argv){ 13 | if(argc <= 1) 14 | return 1; 15 | FILE *f = fopen(argv[1], "r"); 16 | if(!f){ 17 | perror(argv[1]); 18 | return 1; 19 | } 20 | 21 | zeroStr = malloc(sizeof(char[2])); 22 | memset(zeroStr, 0, sizeof(zeroStr)); 23 | strcpy(zeroStr, "0"); 24 | oneStr = malloc(sizeof(char[2])); 25 | memset(oneStr, 0, sizeof(oneStr)); 26 | strcpy(oneStr, "1"); 27 | neStr = malloc(sizeof(char[3])); 28 | memset(neStr, 0, sizeof(neStr)); 29 | strcpy(neStr, "!="); 30 | 31 | tree = NULL; 32 | errorLexFlag = 0; 33 | errorSyntaxFlag = 0; 34 | yylineno = 1; 35 | yyrestart(f); 36 | yyparse(); 37 | 38 | if(errorLexFlag == 0 && errorSyntaxFlag==0){ 39 | initTable(); 40 | // traverseTree(tree); 41 | Program(tree); 42 | optimizeGoto(); 43 | deleteLabel(); 44 | figureCon(); 45 | printCode(argv[2]); 46 | } 47 | 48 | cleanTree(tree); 49 | return 0; 50 | 51 | } 52 | -------------------------------------------------------------------------------- /Project3/parse.h: -------------------------------------------------------------------------------- 1 | #ifndef PRASE_H 2 | #define PRASE_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "SyntaxTree.h" 12 | 13 | /* 14 | * lex & parse 15 | */ 16 | extern int yylex(void); 17 | extern int yyparse(void); 18 | extern void yyrestart(FILE*); 19 | extern void yyerror(char*); 20 | extern int yylineno; 21 | 22 | /* 23 | * SyntaxTree 24 | */ 25 | extern Node* tree; 26 | 27 | /* 28 | * main 29 | */ 30 | extern int errorLexFlag; 31 | extern int errorSyntaxFlag; 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /Project3/report.md: -------------------------------------------------------------------------------- 1 | # Project2 实验报告 2 | ###### 151220136 许卓尔 3 | ###### 151220168 赵文昊 4 | 5 | ## 实现功能 6 | 7 | 1. **源代码翻译为中间代码** 8 | 2. **优化中间代码的生成** 9 | 3. **以线性结构输出中间代码** 10 | 11 | 12 | ## 实现方法 13 | 14 | #### 源代码翻译为中间代码 15 | 16 | - 中间代码数据结构 17 | 18 | 中间代码使用双向链表存储在内存中,待全部生成完毕后进行优化; 19 | 20 | 链表以增加实现的复杂性为代价换得了极大的灵活性,可以进行高效的插入、删除以及调换位置操作,并且几乎不存在代码最大行数的限制; 21 | 22 | 23 | - 中间代码翻译 24 | 25 | 在实验二语义分析部分添加中间代码生成的内容,使编译器一边进行语义检查一遍生成中间代码,并插入双向链表中; 26 | 27 | 根据相应文法,进行翻译,生成相应中间代码,由于语义检查的过程中伴随符号表插入等操作,可以直接get到变量信息,更为快捷; 28 | 29 | 30 | ``` 31 | typedef struct Operand_{ 32 | enum{TEMPVAR,VARIABLE,CONSTANT... }kind; 33 | union{ 34 | int var_no; 35 | char* value; 36 | ... 37 | }u; 38 | Operand next; 39 | } Operand_; 40 | 41 | typedef struct InterCode_{ 42 | enum{ASSIGN_N,ADD_N,SUB_N,MUL_N,DIV_N,...}kind; 43 | union{ 44 | struct{ Operand op; }sinop; 45 | struct{ Operand left,right; }assign; 46 | struct{ Operand op1,op2,result; }binop; 47 | ... 48 | }u; 49 | InterCode pre; // 实现双向链表 50 | InterCode next; 51 | } InterCode_; 52 | ``` 53 | 54 | 55 | #### 优化中间代码的生成 56 | 57 | - 消除冗余的跳转 58 | 59 | - 删除未被指向的label 60 | 61 | 对中间代码双向链表进行遍历; 62 | 63 | 对于Label类型的代码,判断是否会跳转到此Label; 64 | 65 | 若无,则为未被指向的label,删除; 66 | 67 | - 直接计算常数 68 | 69 | 对中间代码双向链表进行遍历; 70 | 71 | 对于计算类型的操作,判断左手端、右手端是否为常量; 72 | 73 | 若均为常量,则将该代码替换为lhs、rhs计算结果的常量; 74 | 75 | 76 | #### 以线性结构输出中间代码 77 | 78 | - 输出中间代码 79 | 80 | 对优化后的双向链表进行遍历; 81 | 82 | 根据实验要求中的规则,输出中间代码到指定文件流中; 83 | 84 | 85 | ## 编译介绍 86 | 87 | ##### Makefile文件 88 | 89 | make parser | make 90 | > 对词法分析器、语法分析器进行编译并生成相应的parser程序; 91 | 92 | make clean 93 | > 对生成文件进行清理; 94 | 95 | ./parser ./testcase/TestFile.txt OutFileName.ir 96 | > 对当前路径下pretest文件夹中的TestFile.txt文件进行中间代码翻译与优化,并以线性结构输出到自定义的OutFileName.ir文件中; 97 | -------------------------------------------------------------------------------- /Project3/syntax.y: -------------------------------------------------------------------------------- 1 | %{ 2 | #include 3 | #include 4 | #include "parse.h" 5 | #include "SyntaxTree.h" 6 | %} 7 | 8 | /* declared types */ 9 | %union { 10 | int type_int; 11 | float type_float; 12 | double type_double; 13 | Node* type_node; 14 | } 15 | 16 | /* declared tokens */ 17 | %token INT 18 | %token FLOAT 19 | %token ID 20 | %token SEMI 21 | %token COMMA 22 | %token ASSIGNOP 23 | %token RELOP 24 | %token PLUS 25 | %token MINUS 26 | %token STAR 27 | %token DIV 28 | %token AND 29 | %token OR 30 | %token NOT 31 | %token DOT 32 | %token TYPE 33 | %token LP 34 | %token RP 35 | %token LB 36 | %token RB 37 | %token LC 38 | %token RC 39 | %token STRUCT 40 | %token RETURN 41 | %token IF 42 | %token ELSE 43 | %token WHILE 44 | 45 | /* declared non-terminals */ 46 | %type Program ExtDefList ExtDef ExtDecList 47 | %type Specifier StructSpecifier OptTag Tag 48 | %type VarDec FunDec VarList ParamDec 49 | %type CompSt StmtList Stmt 50 | %type DefList Def DecList Dec 51 | %type Exp Args 52 | 53 | %right ASSIGNOP 54 | %left OR 55 | %left AND 56 | %left RELOP 57 | %left PLUS 58 | %left STAR DIV 59 | %right NOT 60 | %left LP RP LB RB DOT 61 | 62 | %nonassoc LOWER_THAN_ELSE 63 | %nonassoc ELSE 64 | 65 | 66 | %% 67 | 68 | /* High-level Definitions */ 69 | Program : ExtDefList { 70 | $$ = init("Program", NULL, TYPE_NONTERMINAL, @$.first_line); 71 | insert($$, $1); 72 | tree = $$; 73 | } 74 | ; 75 | ExtDefList : ExtDef ExtDefList{ 76 | $$ = init("ExtDefList", NULL, TYPE_NONTERMINAL, @$.first_line); 77 | insert($$,$1);insert($$,$2); 78 | } 79 | | /* empty */{ $$ = init("ExtDefList", NULL, TYPE_NONTERMINAL, @$.first_line); } 80 | ; 81 | ExtDef : Specifier ExtDecList SEMI{ 82 | $$ = init("ExtDef", NULL, TYPE_NONTERMINAL, @$.first_line); 83 | insert($$,$1);insert($$,$2);insert($$,$3); 84 | } 85 | | Specifier SEMI{ 86 | $$ = init("ExtDef", NULL, TYPE_NONTERMINAL, @$.first_line); 87 | insert($$,$1);insert($$,$2); 88 | } 89 | | Specifier FunDec SEMI{ 90 | $$ = init("ExtDef", NULL, TYPE_NONTERMINAL, @$.first_line); 91 | insert($$,$1);insert($$,$2);insert($$,$3); 92 | } 93 | | Specifier FunDec CompSt{ 94 | $$ = init("ExtDef", NULL, TYPE_NONTERMINAL, @$.first_line); 95 | insert($$,$1);insert($$,$2);insert($$,$3); 96 | } 97 | | error SEMI { errorSyntaxFlag=2; } 98 | ; 99 | ExtDecList : VarDec{ 100 | $$ = init("ExtDecList", NULL, TYPE_NONTERMINAL, @$.first_line); 101 | insert($$, $1); 102 | } 103 | | VarDec COMMA ExtDecList{ 104 | $$ = init("ExtDecList", NULL, TYPE_NONTERMINAL, @$.first_line); 105 | insert($$,$1);insert($$,$2);insert($$,$3); 106 | } 107 | ; 108 | 109 | /* Specifiers */ 110 | Specifier : TYPE{ 111 | $$ = init("Specifier", NULL, TYPE_NONTERMINAL, @$.first_line); 112 | insert($$,$1); 113 | } 114 | | StructSpecifier{ 115 | $$ = init("Specifier", NULL, TYPE_NONTERMINAL, @$.first_line); 116 | insert($$,$1); 117 | } 118 | ; 119 | StructSpecifier : STRUCT OptTag LC DefList RC{ 120 | $$ = init("StructSpecifier", NULL, TYPE_NONTERMINAL, @$.first_line); 121 | insert($$,$1);insert($$,$2);insert($$,$3);insert($$,$4);insert($$,$5); 122 | } 123 | | STRUCT Tag{ 124 | $$ = init("StructSpecifier", NULL, TYPE_NONTERMINAL, @$.first_line); 125 | insert($$,$1);insert($$,$2); 126 | } 127 | ; 128 | OptTag : ID{ 129 | $$ = init("OptTag", NULL, TYPE_NONTERMINAL, @$.first_line); 130 | insert($$,$1); 131 | } 132 | | /* empty */{$$ = init("OptTag", NULL, TYPE_NONTERMINAL, @$.first_line);} 133 | ; 134 | Tag : ID{ 135 | $$ = init("Tag", NULL, TYPE_NONTERMINAL, @$.first_line); 136 | insert($$,$1); 137 | } 138 | ; 139 | 140 | /* Declarators */ 141 | VarDec : ID{ 142 | $$ = init("VarDec", NULL, TYPE_NONTERMINAL, @$.first_line); 143 | insert($$,$1); 144 | } 145 | | VarDec LB INT RB{ 146 | $$ = init("VarDec", NULL, TYPE_NONTERMINAL, @$.first_line); 147 | insert($$,$1);insert($$,$2);insert($$,$3);insert($$,$4); 148 | } 149 | ; 150 | FunDec : ID LP VarList RP{ 151 | $$ = init("FunDec", NULL, TYPE_NONTERMINAL, @$.first_line); 152 | insert($$,$1);insert($$,$2);insert($$,$3);insert($$,$4); 153 | } 154 | | ID LP RP{ 155 | $$ = init("FunDec", NULL, TYPE_NONTERMINAL, @$.first_line); 156 | insert($$,$1);insert($$,$2);insert($$,$3); 157 | } 158 | | error RP{ errorSyntaxFlag=2; } 159 | ; 160 | VarList : ParamDec COMMA VarList{ 161 | $$ = init("VarList", NULL, TYPE_NONTERMINAL, @$.first_line); 162 | insert($$,$1);insert($$,$2);insert($$,$3); 163 | } 164 | | ParamDec{ 165 | $$ = init("VarList", NULL, TYPE_NONTERMINAL, @$.first_line); 166 | insert($$,$1); 167 | } 168 | ; 169 | ParamDec : Specifier VarDec{ 170 | $$ = init("ParamDec", NULL, TYPE_NONTERMINAL, @$.first_line); 171 | insert($$,$1);insert($$,$2); 172 | } 173 | ; 174 | 175 | /* Statements */ 176 | CompSt : LC DefList StmtList RC{ 177 | $$ = init("CompSt", NULL, TYPE_NONTERMINAL, @$.first_line); 178 | insert($$,$1);insert($$,$2);insert($$,$3);insert($$,$4); 179 | } 180 | | error RC{ errorSyntaxFlag=2; } 181 | ; 182 | StmtList : Stmt StmtList{ 183 | $$ = init("StmtList", NULL, TYPE_NONTERMINAL, @$.first_line); 184 | insert($$,$1);insert($$,$2); 185 | } 186 | | /* empty */{ 187 | $$ = init("StmtList", NULL, TYPE_NONTERMINAL, @$.first_line); 188 | } 189 | ; 190 | Stmt : Exp SEMI{ 191 | $$ = init("Stmt", NULL, TYPE_NONTERMINAL, @$.first_line); 192 | insert($$,$1);insert($$,$2); 193 | } 194 | | CompSt{ 195 | $$ = init("Stmt", NULL, TYPE_NONTERMINAL, @$.first_line); 196 | insert($$,$1); 197 | } 198 | | RETURN Exp SEMI{ 199 | $$ = init("Stmt", NULL, TYPE_NONTERMINAL, @$.first_line); 200 | insert($$,$1);insert($$,$2);insert($$,$3); 201 | } 202 | | IF LP Exp RP Stmt %prec LOWER_THAN_ELSE{ 203 | $$ = init("Stmt", NULL, TYPE_NONTERMINAL, @$.first_line); 204 | insert($$,$1);insert($$,$2);insert($$,$3); 205 | insert($$,$4);insert($$,$5); 206 | } 207 | | IF LP Exp RP Stmt ELSE Stmt{ 208 | $$ = init("Stmt", NULL, TYPE_NONTERMINAL, @$.first_line); 209 | insert($$,$1);insert($$,$2);insert($$,$3); 210 | insert($$,$4);insert($$,$5);insert($$,$6);insert($$,$7); 211 | } 212 | | WHILE LP Exp RP Stmt{ 213 | $$ = init("Stmt", NULL, TYPE_NONTERMINAL, @$.first_line); 214 | insert($$,$1);insert($$,$2);insert($$,$3); 215 | insert($$,$4);insert($$,$5); 216 | } 217 | | error SEMI { errorSyntaxFlag=2; } 218 | ; 219 | 220 | /* Local Definitions */ 221 | DefList : Def DefList{ 222 | $$ = init("DefList", NULL, TYPE_NONTERMINAL, @$.first_line); 223 | insert($$,$1);insert($$,$2); 224 | } 225 | | /* empty */{ 226 | $$ = init("DefList", NULL, TYPE_NONTERMINAL, @$.first_line); 227 | } 228 | ; 229 | Def : Specifier DecList SEMI{ 230 | $$ = init("Def", NULL, TYPE_NONTERMINAL, @$.first_line); 231 | insert($$,$1);insert($$,$2);insert($$,$3); 232 | } 233 | | error SEMI{ errorSyntaxFlag=2; } 234 | ; 235 | DecList : Dec{ 236 | $$ = init("DecList", NULL, TYPE_NONTERMINAL, @$.first_line); 237 | insert($$,$1); 238 | } 239 | | Dec COMMA DecList{ 240 | $$ = init("DecList", NULL, TYPE_NONTERMINAL, @$.first_line); 241 | insert($$,$1);insert($$,$2);insert($$,$3); 242 | } 243 | ; 244 | Dec : VarDec{ 245 | $$ = init("Dec", NULL, TYPE_NONTERMINAL, @$.first_line); 246 | insert($$,$1); 247 | } 248 | | VarDec ASSIGNOP Exp{ 249 | $$ = init("Dec", NULL, TYPE_NONTERMINAL, @$.first_line); 250 | insert($$,$1);insert($$,$2);insert($$,$3); 251 | } 252 | 253 | /* Expressions */ 254 | Exp : Exp ASSIGNOP Exp{ 255 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 256 | insert($$,$1);insert($$,$2);insert($$,$3); 257 | } 258 | | Exp AND Exp{ 259 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 260 | insert($$,$1); 261 | } 262 | | Exp OR Exp{ 263 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 264 | insert($$,$1);insert($$,$2);insert($$,$3); 265 | } 266 | | Exp RELOP Exp{ 267 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 268 | insert($$,$1);insert($$,$2);insert($$,$3); 269 | } 270 | | Exp PLUS Exp{ 271 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 272 | insert($$,$1);insert($$,$2);insert($$,$3); 273 | } 274 | | Exp MINUS Exp{ 275 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 276 | insert($$,$1);insert($$,$2);insert($$,$3); 277 | } 278 | | Exp STAR Exp{ 279 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 280 | insert($$,$1);insert($$,$2);insert($$,$3); 281 | } 282 | | Exp DIV Exp{ 283 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 284 | insert($$,$1);insert($$,$2);insert($$,$3); 285 | } 286 | | LP Exp RP{ 287 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 288 | insert($$,$1);insert($$,$2);insert($$,$3); 289 | } 290 | | MINUS Exp{ 291 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 292 | insert($$,$1);insert($$,$2); 293 | } 294 | | NOT Exp{ 295 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 296 | insert($$,$1);insert($$,$2); 297 | } 298 | | ID LP Args RP{ 299 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 300 | insert($$,$1);insert($$,$2);insert($$,$3);insert($$,$4); 301 | } 302 | | ID LP RP{ 303 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 304 | insert($$,$1);insert($$,$2);insert($$,$3); 305 | } 306 | | Exp LB Exp RB{ 307 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 308 | insert($$,$1);insert($$,$2);insert($$,$3);insert($$,$4); 309 | } 310 | | Exp DOT ID{ 311 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 312 | insert($$,$1);insert($$,$2);insert($$,$3); 313 | } 314 | | ID{ 315 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 316 | insert($$,$1); 317 | } 318 | | INT{ 319 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 320 | insert($$,$1); 321 | } 322 | | FLOAT{ 323 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 324 | insert($$,$1); 325 | } 326 | ; 327 | Args : Exp COMMA Args{ 328 | $$ = init("Args", NULL, TYPE_NONTERMINAL, @$.first_line); 329 | insert($$,$1);insert($$,$2);insert($$,$3); 330 | } 331 | | Exp{ 332 | $$ = init("Args", NULL, TYPE_NONTERMINAL, @$.first_line); 333 | insert($$,$1); 334 | } 335 | ; 336 | 337 | /* Comments */ 338 | 339 | %% 340 | 341 | 342 | void yyerror(char* msg){ 343 | if(errorLexFlag==0) 344 | fprintf(stderr, "Error type B at Line %d: %s\n",yylineno,msg); 345 | } 346 | -------------------------------------------------------------------------------- /Project3/testcase/testcase1.txt: -------------------------------------------------------------------------------- 1 | int main() 2 | { 3 | int n; 4 | n = read(); 5 | if( n > 0) 6 | write(1); 7 | else if( n < 0) 8 | write(-1); 9 | else 10 | write(0); 11 | return 0; 12 | } -------------------------------------------------------------------------------- /Project3/testcase/testcase2.txt: -------------------------------------------------------------------------------- 1 | int fact(int n) 2 | { 3 | if( n == 1) 4 | return n; 5 | else 6 | return (n*fact(n-1)); 7 | } 8 | int main() 9 | { 10 | int m,result; 11 | m = read(); 12 | if( m>1) 13 | result = fact(m); 14 | else 15 | result = 1; 16 | write(result); 17 | return 0; 18 | } -------------------------------------------------------------------------------- /Project3/testcase/testcase3.txt: -------------------------------------------------------------------------------- 1 | struct Operands 2 | { 3 | int o1; 4 | int o2; 5 | }; 6 | 7 | int add(struct Operands temp) 8 | { 9 | return(temp.o1+temp.o2); 10 | } 11 | int main() 12 | { 13 | int n; 14 | struct Operands op; 15 | op.o1 = 1; 16 | op.o2 = 2; 17 | n = add(op); 18 | write(n); 19 | return 0; 20 | } -------------------------------------------------------------------------------- /Project3/testcase/testcase4.txt: -------------------------------------------------------------------------------- 1 | int add(int temp[2]) 2 | { 3 | return (temp[0] +temp[1]); 4 | } 5 | 6 | int main() 7 | { 8 | int op[2]; 9 | int r[1][2]; 10 | int i = 0,j = 0; 11 | while(i<2) 12 | { 13 | while(j<2){ 14 | op[j]=i+j; 15 | j=j+1; 16 | } 17 | r[0][1] = add(op); 18 | write(r[0][i]); 19 | i = i+1; 20 | j = 0; 21 | } 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /Project4/HashTable.c: -------------------------------------------------------------------------------- 1 | #include "HashTable.h" 2 | 3 | Entry *hashTable[HASH_SIZE]; 4 | 5 | unsigned int hashPJW(char *name){ 6 | unsigned int val=0, i; 7 | for(; *name; ++name){ 8 | val = (val<<2)+*name; 9 | if(i= val& ~0x3fff) 10 | val = (val^(i>>12))&0x3fff; 11 | } 12 | return val; 13 | 14 | } 15 | 16 | void initTable(){ 17 | int i=0; 18 | for(;iname=malloc(16); 23 | memset(read->name, 0, sizeof(read->name)); 24 | strcpy(read->name,"read"); 25 | read->isDefined=1; 26 | read->line=0; 27 | read->retype=malloc(sizeof(struct Type_)); 28 | read->retype->kind=BASIC; 29 | read->retype->u.basic=TYPE_INT; 30 | read->param=NULL; 31 | funcInsertTable(read); 32 | Function write=malloc(sizeof(struct Function_)); 33 | write->name=malloc(16); 34 | memset(write->name, 0, sizeof(write->name)); 35 | strcpy(write->name,"write"); 36 | write->isDefined=1; 37 | write->line=0; 38 | write->retype=malloc(sizeof(struct Type_)); 39 | write->retype->kind=BASIC; 40 | write->retype->u.basic=TYPE_INT; 41 | write->param=malloc(sizeof(struct FieldList_)); 42 | write->param->name = malloc(16); 43 | strcpy(write->param->name,"write_param"); 44 | write->param->type=malloc(sizeof(struct Type_)); 45 | write->param->type->kind = BASIC; 46 | write->param->type->u.basic = TYPE_INT; 47 | write->param->tail=NULL; 48 | funcInsertTable(write); 49 | } 50 | 51 | int varInsertTable(FieldList value){ 52 | 53 | if(hashTable==NULL || value==NULL) 54 | return 0; 55 | 56 | unsigned int hashValue = 0; 57 | hashValue = hashPJW(value->name)%HASH_SIZE; 58 | 59 | Entry *curEntry = (Entry *)malloc(sizeof(Entry)); 60 | curEntry->next = hashTable[hashValue]; 61 | hashTable[hashValue] = curEntry; 62 | 63 | curEntry->type = value->type; 64 | curEntry->name = value->name; 65 | 66 | return 1; 67 | } 68 | 69 | int funcInsertTable(Function func){ 70 | if(hashTable==NULL || func==NULL) 71 | return 0; 72 | 73 | unsigned int hashValue = 0; 74 | hashValue = hashPJW(func->name)%HASH_SIZE; 75 | 76 | Entry *curEntry = (Entry *)malloc(sizeof(Entry)); 77 | curEntry->next = hashTable[hashValue]; 78 | hashTable[hashValue] = curEntry; 79 | 80 | curEntry->type = (Type)malloc(sizeof(struct Function_)); 81 | curEntry->type->kind = FUNCTION; 82 | curEntry->type->u.function = func; 83 | curEntry->name = func->name; 84 | 85 | FieldList param = func->param; 86 | int flag; 87 | 88 | while(param != NULL){ 89 | flag = varInsertCheck(param); 90 | if(flag == ERROR_REDEFINE){ 91 | printf("Error type 3 at Line %d: Redefine variable \"%s\"\n",func->line, param->name); 92 | } 93 | else{ 94 | varInsertTable(param); 95 | } 96 | param = param->tail; 97 | } 98 | 99 | return 1; 100 | } 101 | 102 | int structInsertTable(Structure structure){ 103 | if(hashTable==NULL || structure==NULL) 104 | return 0; 105 | 106 | unsigned int hashValue = 0; 107 | hashValue = hashPJW(structure->name)%HASH_SIZE; 108 | 109 | Entry *curEntry = (Entry *)malloc(sizeof(Entry)); 110 | curEntry->next = hashTable[hashValue]; 111 | hashTable[hashValue] = curEntry; 112 | 113 | curEntry->type = (Type)malloc(sizeof(struct Structure_)); 114 | curEntry->type->kind = STRUCTURE; 115 | curEntry->type->u.structure = structure; 116 | curEntry->name = structure->name; 117 | 118 | return 1; 119 | } 120 | 121 | int varInsertCheck(FieldList var){ 122 | if(var==NULL) 123 | return BINGO; 124 | 125 | unsigned int hashValue = hashPJW(var->name)%HASH_SIZE; 126 | Entry *tmp = hashTable[hashValue]; 127 | for(;tmp!=NULL;tmp=tmp->next){ 128 | if(tmp->type->kind!=FUNCTION&&strcmp(tmp->name, var->name)==0) 129 | return ERROR_REDEFINE; 130 | else 131 | continue; 132 | } 133 | } 134 | 135 | int funcInsertCheck(Function func){ 136 | 137 | if(hashTable==NULL || func==NULL) 138 | return BINGO; 139 | 140 | unsigned int hashValue = hashPJW(func->name)%HASH_SIZE; 141 | Entry *tmp = hashTable[hashValue]; 142 | for(;tmp!=NULL;tmp=tmp->next){ 143 | if(tmp->type->kind != FUNCTION) 144 | continue; 145 | Function tmpFunc = tmp->type->u.function; 146 | if(strcmp(tmpFunc->name,func->name)!=0) 147 | continue; 148 | if((valueEqual(tmpFunc->param,func->param)!=0) 149 | || (typeEqual(tmpFunc->retype,func->retype)!=0)) 150 | return ERROR_DECLARATION_CONFLICT; 151 | if(tmpFunc->isDefined!=0){ 152 | return ERROR_REDEFINE; 153 | } 154 | else{ 155 | tmpFunc->isDefined = func->isDefined; 156 | return FUNC_IS_DECLARED; 157 | } 158 | } 159 | return BINGO; 160 | } 161 | 162 | int structInsertCheck(Structure structure){ 163 | if(hashTable==NULL || structure==NULL) 164 | return BINGO; 165 | 166 | unsigned int hashValue = hashPJW(structure->name)%HASH_SIZE; 167 | Entry *tmp = hashTable[hashValue]; 168 | for(;tmp!=NULL;tmp=tmp->next){ 169 | if(tmp->type->kind!=FUNCTION&&strcmp(tmp->name,structure->name)==0) 170 | return ERROR_REDEFINE; 171 | else 172 | continue; 173 | } 174 | return BINGO; 175 | } 176 | 177 | Type getTable(char *name){ 178 | 179 | if(hashTable==NULL || name==NULL) 180 | return NULL; 181 | 182 | unsigned int hashValue = hashPJW(name)%HASH_SIZE; 183 | 184 | Entry *tmp = hashTable[hashValue]; 185 | for(;tmp!=NULL;tmp=tmp->next){ 186 | if(strcmp(tmp->name,name)==0) 187 | return tmp->type; 188 | } 189 | 190 | // Error: No such name 191 | return NULL; 192 | } 193 | 194 | void checkFuncDeclaration(){ 195 | int i=0; 196 | Entry *itor = NULL; 197 | for(;itype!=NULL&&itor->type->kind==FUNCTION&&itor->type->u.function->isDefined==0){ 202 | printf("Error type 18 at Line %d: Undefined function \"%s\".\n",itor->type->u.function->line,itor->type->u.function->name); 203 | } 204 | itor = itor->next; 205 | } 206 | } 207 | } 208 | } 209 | -------------------------------------------------------------------------------- /Project4/HashTable.h: -------------------------------------------------------------------------------- 1 | #ifndef HASHTABLE_H 2 | #define HASHTABLE_H 3 | 4 | #include "SyntaxTree.h" 5 | #include "Semantic.h" 6 | #include 7 | 8 | #define HASH_SIZE 1024 9 | 10 | typedef struct Entry_{ 11 | char *name; 12 | Type type; 13 | struct Entry_ *next; 14 | } Entry; 15 | 16 | extern Entry *hashTable[HASH_SIZE]; 17 | 18 | void initTable(); 19 | Type getTable(char *name); 20 | 21 | int varInsertTable(FieldList value); 22 | int varInsertCheck(FieldList var); 23 | 24 | int funcInsertTable(Function func); 25 | int funcInsertCheck(Function func); 26 | 27 | int structInsertTable(Structure structure); 28 | int structInsertCheck(Structure structure); 29 | 30 | void checkFuncDeclaration(); 31 | #endif 32 | -------------------------------------------------------------------------------- /Project4/InterCode.c: -------------------------------------------------------------------------------- 1 | #include"stdlib.h" 2 | #include"stdio.h" 3 | #include"string.h" 4 | #include"InterCode.h" 5 | 6 | InterCode code_head=NULL; 7 | InterCode code_tail=NULL; 8 | 9 | int temVarNo = 1; 10 | int labelNo = 1; 11 | int varNo = 1; 12 | char *zeroStr; 13 | char *oneStr; 14 | char *neStr; 15 | 16 | void insertCode(InterCode p){ 17 | if(p==NULL) 18 | exit(-1); 19 | //assert(p!=NULL); 20 | p->pre=NULL; 21 | p->next=NULL; 22 | if(code_head==NULL){ 23 | code_head = p; 24 | code_tail = p; 25 | } 26 | else{ 27 | p->pre = code_tail; 28 | code_tail->next = p; 29 | code_tail = p; 30 | } 31 | } 32 | 33 | void deleteCode(InterCode p){ 34 | if(p==NULL) 35 | exit(-1); 36 | //assert(p!=NULL); 37 | if(p==code_head){ 38 | code_head = p->next; 39 | } 40 | else{ 41 | p->pre->next = p->next; 42 | } 43 | 44 | if(p==code_tail){ 45 | code_tail = p->pre; 46 | } 47 | else{ 48 | p->next->pre = p->pre; 49 | } 50 | } 51 | 52 | void printOp(Operand p, FILE* fp){ 53 | if(p==NULL) 54 | exit(-1); 55 | //assert(p!=NULL); 56 | char str[50]; 57 | memset(str, 0, sizeof(str)); 58 | switch(p->kind){ 59 | case TEMPVAR: 60 | sprintf(str, "t%d ", p->u.var_no); 61 | fputs(str, fp); 62 | break; 63 | case VARIABLE: 64 | if(p->u.value==NULL) 65 | exit(-1); 66 | sprintf(str, "%s ", p->u.value); 67 | fputs(str, fp); 68 | break; 69 | case CONSTANT: 70 | sprintf(str, "#%s ", p->u.value); 71 | fputs(str, fp); 72 | break; 73 | case VADDRESS: 74 | fputs("*", fp); 75 | assert(p->u.addr!=NULL); 76 | fputs(p->u.addr->u.value, fp); 77 | break; 78 | case LABEL: 79 | sprintf(str, "label%d ", p->u.var_no); 80 | fputs(str, fp); 81 | break; 82 | case FUNCTION_: 83 | sprintf(str, "%s ", p->u.value); 84 | fputs(str, fp); 85 | break; 86 | case TADDRESS: 87 | fputs("*t",fp); 88 | sprintf(str,"%d",p->u.addr->u.var_no); 89 | fputs(str,fp); 90 | break; 91 | default: 92 | assert(0); 93 | } 94 | } 95 | 96 | void printCode(char* fileName){ 97 | FILE* fp = fopen(fileName, "w"); 98 | if(fp==NULL){ 99 | printf("ERROR: Can not open file \"%s\".",fileName); 100 | return; 101 | } 102 | InterCode p; 103 | for(p=code_head;p!=NULL;p=p->next){ 104 | switch(p->kind){ 105 | case ASSIGN_N: 106 | printOp(p->u.assign.left, fp); 107 | fputs(":= ", fp); 108 | printOp(p->u.assign.right, fp); 109 | break; 110 | case ADD_N: 111 | printOp(p->u.binop.result, fp); 112 | fputs(":= ", fp); 113 | printOp(p->u.binop.op1, fp); 114 | fputs("+ ", fp); 115 | printOp(p->u.binop.op2, fp); 116 | break; 117 | case SUB_N: 118 | printOp(p->u.binop.result, fp); 119 | fputs(":= ", fp); 120 | printOp(p->u.binop.op1, fp); 121 | fputs("- ", fp); 122 | printOp(p->u.binop.op2, fp); 123 | break; 124 | case MUL_N: 125 | printOp(p->u.binop.result, fp); 126 | fputs(":= ", fp); 127 | printOp(p->u.binop.op1, fp); 128 | fputs("* ", fp); 129 | printOp(p->u.binop.op2, fp); 130 | break; 131 | case DIV_N: 132 | printOp(p->u.binop.result, fp); 133 | fputs(":= ", fp); 134 | printOp(p->u.binop.op1, fp); 135 | fputs("/ ", fp); 136 | printOp(p->u.binop.op2, fp); 137 | break; 138 | case RETURN_N: 139 | fputs("RETURN ", fp); 140 | printOp(p->u.sinop.op, fp); 141 | break; 142 | case LABEL_N: 143 | fputs("LABEL ", fp); 144 | printOp(p->u.sinop.op, fp); 145 | fputs(": ", fp); 146 | break; 147 | case GOTO_N: 148 | fputs("GOTO ", fp); 149 | printOp(p->u.sinop.op, fp); 150 | break; 151 | case IFGOTO_N: 152 | fputs("IF ", fp); 153 | printOp(p->u.triop.x, fp); 154 | fputs(p->u.triop.op, fp); 155 | fputs(" ", fp); 156 | printOp(p->u.triop.y, fp); 157 | fputs("GOTO ", fp); 158 | printOp(p->u.triop.label, fp); 159 | break; 160 | case READ_N: 161 | fputs("READ ", fp); 162 | printOp(p->u.sinop.op, fp); 163 | break; 164 | case WRITE_N: 165 | fputs("WRITE ", fp); 166 | printOp(p->u.sinop.op, fp); 167 | break; 168 | case CALL_N: 169 | printOp(p->u.assign.left, fp); 170 | fputs(":= CALL ", fp); 171 | printOp(p->u.assign.right, fp); 172 | break; 173 | case ARG_N: 174 | fputs("ARG ", fp); 175 | printOp(p->u.sinop.op, fp); 176 | break; 177 | case FUNCTION_N: 178 | fputs("FUNCTION ", fp); 179 | printOp(p->u.sinop.op, fp); 180 | fputs(": ", fp); 181 | break; 182 | case PARAM_N: 183 | fputs("PARAM ", fp); 184 | printOp(p->u.sinop.op, fp); 185 | break; 186 | case DEC_N: 187 | fputs("DEC ", fp); 188 | printOp(p->u.dec.op, fp); 189 | char sizeStr[16]; 190 | sprintf(sizeStr, "%d", p->u.dec.size); 191 | fputs(sizeStr, fp); 192 | break; 193 | case ADDRESS_N: 194 | printOp(p->u.assign.left, fp); 195 | fputs(":= &", fp); 196 | printOp(p->u.assign.right, fp); 197 | break; 198 | default: 199 | assert(0); 200 | } 201 | fputs("\n", fp); 202 | } 203 | fclose(fp); 204 | } 205 | 206 | void optimizeGoto() 207 | { 208 | InterCode c; 209 | for(c=code_head;c!=NULL;c=c->next) 210 | { 211 | if(c->kind==IFGOTO_N) 212 | { 213 | InterCode c1=c; 214 | InterCode c2=c->next; 215 | if(c2==NULL) 216 | continue; 217 | InterCode c3=c2->next; 218 | if(c3==NULL) 219 | continue; 220 | if(c2->kind==GOTO_N&&c3->kind==LABEL_N&&c1->u.triop.label==c3->u.sinop.op) 221 | { 222 | c1->u.triop.label=c2->u.sinop.op; 223 | deleteCode(c2); 224 | if(strcmp(c1->u.triop.op,"==")==0) 225 | { 226 | char* newop = malloc(4); 227 | memset(newop, 0, 4); 228 | strcpy(newop,"!="); 229 | c1->u.triop.op=newop; 230 | } 231 | else if(strcmp(c1->u.triop.op,"!=")==0) 232 | { 233 | char* newop = malloc(4); 234 | memset(newop, 0, 4); 235 | strcpy(newop,"=="); 236 | c1->u.triop.op=newop; 237 | } 238 | else if(strcmp(c1->u.triop.op,">=")==0) 239 | { 240 | char* newop = malloc(4); 241 | memset(newop, 0, 4); 242 | strcpy(newop,"<"); 243 | c1->u.triop.op=newop; 244 | } 245 | else if(strcmp(c1->u.triop.op,"<")==0) 246 | { 247 | char* newop = malloc(4); 248 | memset(newop, 0, 4); 249 | strcpy(newop,">="); 250 | c1->u.triop.op=newop; 251 | } 252 | else if(strcmp(c1->u.triop.op,">")==0) 253 | { 254 | char* newop = malloc(4); 255 | memset(newop, 0, 4); 256 | strcpy(newop,"<="); 257 | c1->u.triop.op=newop; 258 | } 259 | else if(strcmp(c1->u.triop.op,"<=")==0) 260 | { 261 | char* newop = malloc(4); 262 | memset(newop, 0, 4); 263 | strcpy(newop,">"); 264 | c1->u.triop.op=newop; 265 | } 266 | } 267 | } 268 | else if(c->kind==GOTO_N) 269 | { 270 | InterCode c1=c; 271 | InterCode c2=c->next; 272 | if(c2==NULL) 273 | continue; 274 | if(c2->kind==LABEL_N&&c1->u.sinop.op==c2->u.sinop.op) 275 | deleteCode(c1); 276 | } 277 | } 278 | } 279 | 280 | void deleteLabel() 281 | { 282 | Label_No head=malloc(sizeof(struct Label_No_)); 283 | head->no=-1; 284 | head->next=NULL; 285 | Label_No tail=head; 286 | InterCode c=code_head; 287 | 288 | while(c!=NULL) 289 | { 290 | if(c->kind==GOTO_N) 291 | { 292 | Label_No temp=malloc(sizeof(struct Label_No_)); 293 | temp->no=c->u.sinop.op->u.var_no; 294 | temp->next=NULL; 295 | tail->next=temp; 296 | tail=temp; 297 | } 298 | else if(c->kind==IFGOTO_N) 299 | { 300 | Label_No temp=malloc(sizeof(struct Label_No_)); 301 | temp->no=c->u.triop.label->u.var_no; 302 | temp->next=NULL; 303 | tail->next=temp; 304 | tail=temp; 305 | } 306 | c=c->next; 307 | } 308 | 309 | c=code_head; 310 | while(c!=NULL) 311 | { 312 | if(c->kind==LABEL_N) 313 | { 314 | int no=c->u.sinop.op->u.var_no; 315 | Label_No ln=head; 316 | while(ln!=NULL) 317 | { 318 | if(ln->no==no)break; 319 | ln=ln->next; 320 | } 321 | InterCode c1=c; 322 | c=c->next; 323 | if(ln==NULL) 324 | deleteCode(c1); 325 | } 326 | else 327 | c=c->next; 328 | } 329 | 330 | tail=NULL; 331 | while(head!=NULL) 332 | { 333 | Label_No ln=head; 334 | head=head->next; 335 | free(ln); 336 | } 337 | } 338 | 339 | void figureCon() 340 | { 341 | InterCode p; 342 | for(p=code_head;p!=NULL;) 343 | { 344 | if(p->kind==ADD_N||p->kind==SUB_N||p->kind==MUL_N||p->kind==DIV_N) 345 | { 346 | Operand op1 = p->u.binop.op1; 347 | Operand op2 = p->u.binop.op2; 348 | Operand result = p->u.binop.result; 349 | 350 | if(result->kind==TEMPVAR&&op1->kind==CONSTANT&&op2->kind==CONSTANT) 351 | { 352 | int o1=atoi(op1->u.value); 353 | int o2=atoi(op2->u.value); 354 | int r=0; 355 | switch(p->kind){ 356 | case ADD_N:r=o1+o2;break; 357 | case SUB_N:r=o1-o2;break; 358 | case MUL_N:r=o1*o2;break; 359 | case DIV_N:r=o1/o2;break; 360 | default:break; 361 | } 362 | result->kind=CONSTANT; 363 | result->u.value = malloc(32); 364 | sprintf(result->u.value,"%d",r); 365 | InterCode tmp = p; 366 | p = p->next; 367 | deleteCode(tmp); 368 | continue; 369 | } 370 | } 371 | p = p->next; 372 | } 373 | } 374 | -------------------------------------------------------------------------------- /Project4/InterCode.h: -------------------------------------------------------------------------------- 1 | #ifndef _INTERCODE_H 2 | #define _INTERCODE_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | typedef struct Operand_* Operand; 9 | typedef struct InterCode_* InterCode; 10 | typedef struct Label_No_* Label_No; 11 | 12 | 13 | typedef struct Operand_{ 14 | enum{TEMPVAR,VARIABLE,CONSTANT,VADDRESS,LABEL,FUNCTION_,TADDRESS }kind; 15 | 16 | union{ 17 | int var_no; 18 | char* value; 19 | Operand addr; 20 | }u; 21 | Operand next; 22 | } Operand_; 23 | 24 | typedef struct InterCode_{ 25 | enum{ASSIGN_N,ADD_N,SUB_N,MUL_N,DIV_N,RETURN_N,LABEL_N,GOTO_N,IFGOTO_N,READ_N,WRITE_N,CALL_N,ARG_N,FUNCTION_N,PARAM_N,DEC_N,ADDRESS_N}kind; 26 | 27 | union{ 28 | struct{ Operand op; }sinop; 29 | 30 | struct{ Operand left,right; }assign; 31 | 32 | struct{ Operand op1,op2,result; }binop; 33 | 34 | struct{ Operand x; Operand y; Operand label; char *op; }triop; 35 | 36 | struct{ Operand op; int size; }dec; 37 | }u; 38 | 39 | InterCode pre; 40 | InterCode next; 41 | } InterCode_; 42 | 43 | typedef struct Label_No_ 44 | { 45 | int no; 46 | Label_No next; 47 | } Label_No_; 48 | 49 | void insertCode(InterCode c); 50 | void deleteCode(InterCode c); 51 | void printCode(char *fileName); 52 | void printOp(Operand p,FILE *fp); 53 | 54 | extern InterCode code_head,code_tail; 55 | extern char* zeroStr; 56 | extern char* oneStr; 57 | extern char* neStr; 58 | extern int temVarNo; 59 | extern int labelNo; 60 | extern int varNo; 61 | 62 | void optimizeGoto(); 63 | void deleteLabel(); 64 | void figureCon(); 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /Project4/Makefile: -------------------------------------------------------------------------------- 1 | parser: 2 | bison -d syntax.y 3 | flex lexical.l 4 | gcc -c lex.yy.c -o lex.o 5 | gcc main.c syntax.tab.c SyntaxTree.c HashTable.c Semantic.c InterCode.c mips.c lex.o -lfl -ly -o parser 6 | 7 | lexical: 8 | bison -d syntax.y 9 | flex lexical.l 10 | 11 | syntax: 12 | bison -d syntax.y 13 | 14 | clean: 15 | rm lex.yy.c lex.o syntax.tab.c syntax.tab.h parser out1.s out2.s 16 | 17 | remake: 18 | make clean 19 | make 20 | 21 | test1: 22 | ./parser ./testcase/testcase1.txt out1.s 23 | 24 | test2: 25 | ./parser ./testcase/testcase2.txt out2.s 26 | 27 | test: 28 | ./parser ./testcase/testcase1.txt out1.s 29 | ./parser ./testcase/testcase2.txt out2.s 30 | -------------------------------------------------------------------------------- /Project4/Semantic.h: -------------------------------------------------------------------------------- 1 | #ifndef SEMANTIC_H 2 | #define SEMANTIC_H 3 | 4 | #include "SyntaxTree.h" 5 | #include "InterCode.h" 6 | 7 | #define BINGO 0 8 | #define ERROR_REDEFINE 1 9 | #define ERROR_DECLARATION_CONFLICT 2 10 | #define ERROR_DOMAIN_REDEFINE 3 11 | 12 | #define FUNC_IS_DECLARED 4 13 | 14 | #define FROM_VARIABLE 1 15 | #define FROM_FIELD 2 16 | #define FROM_PARAM 3 17 | 18 | typedef struct Type_* Type; 19 | typedef struct Structure_* Structure; 20 | typedef struct FieldList_* FieldList; 21 | typedef struct Function_* Function; 22 | 23 | struct Type_{ 24 | enum { BASIC,ARRAY,STRUCTURE,FUNCTION } kind; 25 | union{ 26 | // basic type 27 | int basic; 28 | 29 | // array information 30 | struct { Type elem; int size;} array; 31 | 32 | // structure information 33 | Structure structure; 34 | 35 | // function information 36 | Function function; 37 | } u; 38 | enum { LEFT,RIGHT,BOTH } assign; 39 | }; 40 | 41 | struct Structure_{ 42 | char *name; 43 | FieldList domain; 44 | }; 45 | 46 | struct FieldList_{ 47 | // Field name 48 | char *name; 49 | // Field type 50 | Type type; 51 | // next field 52 | FieldList tail; 53 | }; 54 | 55 | struct Function_{ 56 | char *name; 57 | int isDefined; 58 | int line; 59 | Type retype; 60 | FieldList param; 61 | }; 62 | 63 | int typeEqual(Type lhs, Type rhs); 64 | int typeSize(Type type); 65 | int structEqual(Structure lhs, Structure rhs); 66 | int valueEqual(FieldList lhs, FieldList rhs); 67 | 68 | void Program(Node* root); 69 | void ExtDefList(Node *n); 70 | void ExtDef(Node *n); 71 | void ExtDecList(Node *n, Type type); 72 | 73 | Type Specifier(Node *n); 74 | Type StructSpecifier(Node *n); 75 | 76 | FieldList VarDec(Node *n, Type type, int from); 77 | Function FunDec(Node *n, Type type); 78 | FieldList VarList(Node *n); 79 | FieldList ParamDec(Node *n); 80 | 81 | void CompSt(Node *n, Type retype); 82 | void StmtList(Node *n, Type retype); 83 | void Stmt(Node *n, Type retype); 84 | 85 | FieldList DefList(Node *n, int from); 86 | FieldList Def(Node *n, int from); 87 | FieldList DecList(Node *n, Type type, int from); 88 | FieldList Dec(Node *n, Type type, int from); 89 | 90 | Type Exp(Node *n, Operand place); 91 | Type Exp_Cond(Node *n,Operand label_true,Operand label_false); 92 | int Args(Node *n, FieldList param, Operand arg); 93 | 94 | #endif 95 | -------------------------------------------------------------------------------- /Project4/SyntaxTree.c: -------------------------------------------------------------------------------- 1 | #include "SyntaxTree.h" 2 | #include 3 | 4 | Node* init(char identifier[], char value[], _Type type, int line){ 5 | Node* root = malloc(sizeof(Node)); 6 | 7 | root->height = 0; 8 | strcpy(root->identifier, identifier); 9 | 10 | if(value != NULL) 11 | strcpy(root->value, value); 12 | else 13 | root->value[0]='\0'; 14 | 15 | root->type = type; 16 | root->line = line; 17 | 18 | return root; 19 | } 20 | 21 | 22 | void insert(Node *p, Node *child){ 23 | if(p == NULL || child == NULL) 24 | return; 25 | 26 | if(p->child == NULL){ 27 | p->child = child; 28 | return; 29 | } 30 | 31 | Node *temp = p->child; 32 | while(temp->sibling != NULL) 33 | temp = temp->sibling; 34 | temp->sibling = child; 35 | 36 | } 37 | 38 | void traverseTree(Node* p){ 39 | if(p == NULL) 40 | return; 41 | 42 | // Print Node 43 | 44 | for(int i=0; iheight; i++) 45 | printf(" "); 46 | switch(p->type){ 47 | case TYPE_NONTERMINAL: 48 | // non-terminals 49 | printf("%s (%d)\n",p->identifier,p->line); 50 | break; 51 | case TYPE_OCT: 52 | printf("%s: %d\n",p->identifier,(int)strtol(p->value,NULL,8)); 53 | break; 54 | case TYPE_HEX: 55 | printf("%s: %d\n",p->identifier,(int)strtol(p->value,NULL,16)); 56 | break; 57 | case TYPE_KEYWORD_BRACKET: 58 | case TYPE_KEYWORD_PUNCTUATION: 59 | case TYPE_KEYWORD_OPERATOR: 60 | // LP|RP|LB|RB|LC|RC|PUNCUTATION|OPERATOR 61 | printf("%s\n",p->identifier); 62 | break; 63 | default: 64 | // terminals 65 | printf("%s: %s\n",p->identifier,p->value); 66 | break; 67 | } 68 | 69 | if(p->child != NULL) 70 | p->child->height = p->height+1; 71 | if(p->sibling != NULL) 72 | p->sibling->height = p->height; 73 | traverseTree(p->child); 74 | traverseTree(p->sibling); 75 | 76 | } 77 | 78 | void cleanTree(Node *p){ 79 | if(p==NULL) 80 | return; 81 | 82 | cleanTree(p->child); 83 | cleanTree(p->sibling); 84 | free(p); 85 | } 86 | 87 | -------------------------------------------------------------------------------- /Project4/SyntaxTree.h: -------------------------------------------------------------------------------- 1 | #ifndef SYNTAXTREE_H 2 | #define SYNTAXTREE_H 3 | 4 | #include 5 | #include 6 | 7 | #define IDENTIFIER_LENGTH 32 8 | #define VALUE_LENGTH 32 9 | 10 | #define TYPE_KEYWORD 0 11 | #define TYPE_KEYWORD_RELOP 1 12 | #define TYPE_KEYWORD_BRACKET 2 13 | #define TYPE_KEYWORD_PUNCTUATION 3 14 | #define TYPE_KEYWORD_OPERATOR 4 15 | 16 | #define TYPE_NONTERMINAL 65536 17 | 18 | #define TYPE_ID 128 19 | 20 | #define TYPE_INT 256 21 | #define TYPE_OCT 257 22 | #define TYPE_HEX 258 23 | 24 | #define TYPE_FLOAT 512 25 | #define TYPE_SFLOAT 513 26 | 27 | #define TYPE_STRING 1024 28 | 29 | extern int yylineno; 30 | 31 | typedef int _Type; 32 | 33 | typedef struct Node{ 34 | //TODO: Complete Node Structure 35 | 36 | char identifier[IDENTIFIER_LENGTH]; 37 | char value[VALUE_LENGTH]; 38 | _Type type; 39 | int line; 40 | int height; 41 | 42 | // Children Brother Express 43 | struct Node *child; 44 | struct Node *sibling; 45 | 46 | }Node; 47 | 48 | extern Node* init(char identifier[], char value[], _Type type, int line); 49 | extern void insert(Node *p, Node *child); 50 | extern void traverseTree(Node *p); 51 | extern void cleanTree(Node *p); 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /Project4/lexical.l: -------------------------------------------------------------------------------- 1 | %{ 2 | #include 3 | #include 4 | #include "SyntaxTree.h" 5 | #include "syntax.tab.h" 6 | 7 | extern int errorLexFlag; 8 | 9 | int yycolumn = 1; 10 | /* define YY_USER_ACTION */ 11 | #define YY_USER_ACTION yylloc.first_line = yylloc.last_line = yylineno; \ 12 | yylloc.first_column = yycolumn; \ 13 | yylloc.last_column = yycolumn + yyleng - 1; \ 14 | yycolumn += yyleng; 15 | 16 | %} 17 | 18 | %option yylineno 19 | 20 | DELIM [ \t] 21 | WS {DELIM}+ 22 | DIGIT [0-9] 23 | LETTER [A-Za-z] 24 | INT 0|([1-9]{DIGIT}*) 25 | OCT 0([0-7]+) 26 | OCT_ERROR 0[0-9A-WYZa-wyz][0-9A-Za-z]* 27 | HEX 0(x|X)[0-9a-fA-F]+ 28 | HEX_ERROR [0][Xx][0-9A-Za-z]* 29 | FLOAT {INT}(\.{DIGIT}+)? 30 | SFLOAT ((INT\.{DIGIT}*)|({DIGIT}*\.{DIGIT}+))[Ee][+-]?{DIGIT}+ 31 | SFLOAT_ERROR ((INT\.{DIGIT}*)|({DIGIT}*\.{DIGIT}+))[Ee][+-]?([0-9A-Za-z]*) 32 | RELOP >|<|>=|<=|==|!= 33 | ID ({LETTER}|_)({LETTER}|{DIGIT}|_)* 34 | 35 | 36 | %% 37 | 38 | 39 | {WS} { /* tabs */ } 40 | 41 | 42 | "/*"([^\*]|(\*)*[^\*/])*(\*)*"*/" { /* C comments */ } 43 | 44 | "//" { 45 | /* C++ comment */ 46 | while(input() != '\n'); 47 | } 48 | 49 | ";" { 50 | yylval.type_node = init("SEMI",yytext,TYPE_KEYWORD_PUNCTUATION,yylineno); 51 | return SEMI; 52 | } 53 | 54 | "," { 55 | yylval.type_node = init("COMMA",yytext,TYPE_KEYWORD_PUNCTUATION,yylineno); 56 | return COMMA; 57 | } 58 | 59 | 60 | "=" { 61 | yylval.type_node = init("ASSIGNOP",yytext,TYPE_KEYWORD_OPERATOR,yylineno); 62 | return ASSIGNOP; 63 | } 64 | 65 | {RELOP} { 66 | yylval.type_node = init("RELOP",yytext,TYPE_KEYWORD_RELOP,yylineno); 67 | return RELOP; 68 | } 69 | 70 | "+" { 71 | yylval.type_node = init("PLUS",yytext,TYPE_KEYWORD_OPERATOR,yylineno); 72 | return PLUS; 73 | } 74 | 75 | "-" { 76 | yylval.type_node = init("MINUS",yytext,TYPE_KEYWORD_OPERATOR,yylineno); 77 | return MINUS; 78 | } 79 | 80 | "*" { 81 | yylval.type_node = init("STAR",yytext,TYPE_KEYWORD_OPERATOR,yylineno); 82 | return STAR; 83 | } 84 | 85 | "/" { 86 | yylval.type_node = init("DIV",yytext,TYPE_KEYWORD_OPERATOR,yylineno); 87 | return DIV; 88 | } 89 | 90 | "&&" { 91 | yylval.type_node = init("AND",yytext,TYPE_KEYWORD_OPERATOR,yylineno); 92 | return AND; 93 | } 94 | 95 | "||" { 96 | yylval.type_node = init("OR",yytext,TYPE_KEYWORD_OPERATOR,yylineno); 97 | return OR; 98 | } 99 | 100 | "!" { 101 | yylval.type_node = init("NOT",yytext,TYPE_KEYWORD_OPERATOR,yylineno); 102 | return NOT; 103 | } 104 | 105 | "." { 106 | yylval.type_node = init("DOT",yytext,TYPE_KEYWORD_PUNCTUATION,yylineno); 107 | return DOT; 108 | } 109 | 110 | "int"|"float" { 111 | yylval.type_node = init("TYPE",yytext,TYPE_KEYWORD,yylineno); 112 | return TYPE; 113 | } 114 | 115 | "(" { 116 | yylval.type_node = init("LP",yytext,TYPE_KEYWORD_BRACKET,yylineno); 117 | return LP; 118 | } 119 | 120 | ")" { 121 | yylval.type_node = init("RP",yytext,TYPE_KEYWORD_BRACKET,yylineno); 122 | return RP; 123 | } 124 | 125 | "[" { 126 | yylval.type_node = init("LB",yytext,TYPE_KEYWORD_BRACKET,yylineno); 127 | return LB; 128 | } 129 | 130 | "]" { 131 | yylval.type_node = init("RB",yytext,TYPE_KEYWORD_BRACKET,yylineno); 132 | return RB; 133 | } 134 | 135 | "{" { 136 | yylval.type_node = init("LC",yytext,TYPE_KEYWORD_BRACKET,yylineno); 137 | return LC; 138 | } 139 | 140 | "}" { 141 | yylval.type_node = init("RC",yytext,TYPE_KEYWORD_BRACKET,yylineno); 142 | return RC; 143 | } 144 | 145 | "struct" { 146 | yylval.type_node = init("STRUCT",yytext,TYPE_KEYWORD,yylineno); 147 | return STRUCT; 148 | } 149 | 150 | "return" { 151 | yylval.type_node = init("RETURN",yytext,TYPE_KEYWORD,yylineno); 152 | return RETURN; 153 | } 154 | 155 | "if" { 156 | yylval.type_node = init("IF",yytext,TYPE_KEYWORD,yylineno); 157 | return IF; 158 | } 159 | 160 | "else" { 161 | yylval.type_node = init("ELSE",yytext,TYPE_KEYWORD,yylineno); 162 | return ELSE; 163 | } 164 | 165 | "while" { 166 | yylval.type_node = init("WHILE",yytext,TYPE_KEYWORD,yylineno); 167 | return WHILE; 168 | } 169 | 170 | {OCT} { 171 | yylval.type_node = init("INT",yytext,TYPE_OCT,yylineno); 172 | return INT; 173 | } 174 | 175 | {OCT_ERROR} { 176 | printf("Error type A at line %d: Illegal octal number \'%s\'\n", yylineno, yytext); 177 | errorLexFlag = 1; 178 | } 179 | 180 | {HEX} { 181 | yylval.type_node = init("INT",yytext,TYPE_HEX,yylineno); 182 | return INT; 183 | } 184 | 185 | {HEX_ERROR} { 186 | printf("Error type A at line %d: Illegal hexadecimal number \'%s\'\n", yylineno, yytext); 187 | errorLexFlag = 1; 188 | } 189 | 190 | {SFLOAT} { 191 | yylval.type_node = init("FLOAT",yytext,TYPE_SFLOAT,yylineno); 192 | return FLOAT; 193 | } 194 | 195 | {SFLOAT_ERROR} { 196 | printf("Error type A at line %d: Illegal floating point number \'%s\'\n", yylineno, yytext); 197 | errorLexFlag = 1; 198 | } 199 | 200 | {INT} { 201 | yylval.type_node = init("INT",yytext,TYPE_INT,yylineno); 202 | return INT; 203 | } 204 | 205 | {FLOAT} { 206 | yylval.type_node = init("FLOAT",yytext,TYPE_FLOAT,yylineno); 207 | return FLOAT; 208 | } 209 | 210 | \n { yycolumn = 1; } 211 | 212 | {ID} { 213 | yylval.type_node = init("ID",yytext,TYPE_ID,yylineno); 214 | return ID; 215 | } 216 | 217 | 218 | . { 219 | printf("Error type A at line %d: Mysterious character \'%s\'\n" 220 | , yylineno, yytext); 221 | errorLexFlag = 1; 222 | } 223 | 224 | 225 | %% 226 | 227 | /* 228 | int main(int argc, char** argv){ 229 | if (argc > 1) 230 | if (!(yyin = fopen(argv[1], "r"))){ 231 | perror(argv[1]); 232 | return 1; 233 | } 234 | } 235 | while (yylex() != 0) ; 236 | return 0; 237 | } 238 | */ 239 | -------------------------------------------------------------------------------- /Project4/main.c: -------------------------------------------------------------------------------- 1 | #include "SyntaxTree.h" 2 | #include "parse.h" 3 | #include "HashTable.h" 4 | #include "Semantic.h" 5 | #include "InterCode.h" 6 | #include "mips.h" 7 | #include "string.h" 8 | 9 | Node *tree; 10 | int errorLexFlag; 11 | int errorSyntaxFlag; 12 | 13 | int main(int argc, char** argv){ 14 | if(argc <= 1) 15 | return 1; 16 | FILE *f = fopen(argv[1], "r"); 17 | if(!f){ 18 | perror(argv[1]); 19 | return 1; 20 | } 21 | 22 | zeroStr = malloc(sizeof(char[2])); 23 | memset(zeroStr, 0, sizeof(zeroStr)); 24 | strcpy(zeroStr, "0"); 25 | oneStr = malloc(sizeof(char[2])); 26 | memset(oneStr, 0, sizeof(oneStr)); 27 | strcpy(oneStr, "1"); 28 | neStr = malloc(sizeof(char[3])); 29 | memset(neStr, 0, sizeof(neStr)); 30 | strcpy(neStr, "!="); 31 | 32 | tree = NULL; 33 | errorLexFlag = 0; 34 | errorSyntaxFlag = 0; 35 | yylineno = 1; 36 | yyrestart(f); 37 | yyparse(); 38 | 39 | if(errorLexFlag == 0 && errorSyntaxFlag==0){ 40 | initTable(); 41 | // traverseTree(tree); 42 | Program(tree); 43 | optimizeGoto(); 44 | deleteLabel(); 45 | figureCon(); 46 | // printCode(argv[2]); 47 | printMips(argv[2]); 48 | } 49 | 50 | cleanTree(tree); 51 | return 0; 52 | 53 | } 54 | -------------------------------------------------------------------------------- /Project4/mips.c: -------------------------------------------------------------------------------- 1 | #include "mips.h" 2 | 3 | void printMips(char *fileName){ 4 | fp = fopen(fileName, "w"); 5 | if(fp==NULL){ 6 | printf("ERROR: Can not open file \"%s\".", fileName); 7 | return; 8 | } 9 | initRegs(); 10 | fputs(".data\n", fp); 11 | fputs("_prompt: .asciiz \"Enter an integer:\"\n", fp); 12 | fputs("_ret: .asciiz \"\\n\"\n", fp); 13 | fputs(".globl main\n", fp); 14 | fputs(".text\n",fp); 15 | // FUNCTION read 16 | fputs("\nread:\n", fp); 17 | fputs("\tli $v0, 4\n", fp); 18 | fputs("\tla $a0, _prompt\n",fp); 19 | fputs("\tsyscall\n", fp); 20 | fputs("\tli $v0, 5\n", fp); 21 | fputs("\tsyscall\n", fp); 22 | fputs("\tjr $ra\n", fp); 23 | // FUNCTION write 24 | fputs("\nwrite:\n",fp); 25 | fputs("\tli $v0, 1\n", fp); 26 | fputs("\tsyscall\n", fp); 27 | fputs("\tli $v0, 4\n", fp); 28 | fputs("\tla $a0, _ret\n", fp); 29 | fputs("\tsyscall\n", fp); 30 | fputs("\tmove $v0, $0\n", fp); 31 | fputs("\tjr $ra\n\n", fp); 32 | 33 | InterCode itor = code_head; 34 | while(itor != NULL){ 35 | printMipsCode(itor); 36 | itor = itor->next; 37 | } 38 | } 39 | 40 | void printMipsCode(InterCode interCode){ 41 | switch (interCode->kind) { 42 | case LABEL_N: 43 | mipsLabel(interCode); 44 | break; 45 | case ASSIGN_N: 46 | mipsAssign(interCode); 47 | break; 48 | case ADD_N: case SUB_N: case MUL_N: case DIV_N: 49 | mipsOperation(interCode); 50 | break; 51 | case READ_N: 52 | mipsRead(interCode); 53 | break; 54 | case WRITE_N: 55 | mipsWrite(interCode); 56 | break; 57 | case CALL_N: 58 | mipsCall(interCode); 59 | break; 60 | case RETURN_N: 61 | mipsReturn(interCode); 62 | break; 63 | case GOTO_N: 64 | mipsGOTO(interCode); 65 | break; 66 | case IFGOTO_N: 67 | mipsIFGOTO(interCode); 68 | break; 69 | case FUNCTION_N: 70 | mipsFunction(interCode); 71 | break; 72 | case ARG_N: 73 | mipsArg(interCode); 74 | break; 75 | case PARAM_N: 76 | mipsParam(interCode); 77 | break; 78 | case DEC_N: 79 | mipsDec(interCode); 80 | break; 81 | case ADDRESS_N: 82 | mipsAddress(interCode); 83 | break; 84 | default: 85 | printf("Error: Unknown Kind to MIPS\n"); 86 | exit(-1); 87 | } 88 | } 89 | 90 | void mipsLabel(InterCode interCode){ 91 | char str[STR_LENGTH]; 92 | memset(str, 0, sizeof(str)); 93 | // x: 94 | sprintf(str, "label%d:\n",interCode->u.sinop.op->u.var_no); 95 | fputs(str, fp); 96 | } 97 | 98 | void mipsAssign(InterCode interCode){ 99 | char str[STR_LENGTH]; 100 | memset(str, 0, sizeof(str)); 101 | Operand leftOp = interCode->u.assign.left; 102 | Operand rightOp = interCode->u.assign.right; 103 | int x, y; 104 | if(leftOp->kind==TEMPVAR || leftOp->kind==VARIABLE){ 105 | // x:= #k 106 | if(rightOp->kind == CONSTANT){ 107 | // li reg(x), k 108 | x = getReg(leftOp); 109 | sprintf(str, "\tli %s, %s\n", printReg(x), rightOp->u.value); 110 | fputs(str, fp); 111 | } 112 | // x:= y 113 | else if(rightOp->kind==TEMPVAR || rightOp->kind==VARIABLE){ 114 | x = getReg(leftOp); 115 | y = getReg(rightOp); 116 | sprintf(str, "\tmove %s, %s\n", printReg(x), printReg(y)); 117 | fputs(str, fp); 118 | } 119 | // x:= *y 120 | else if(rightOp->kind==TADDRESS || rightOp->kind==VADDRESS){ 121 | x = getReg(leftOp); 122 | y = getReg(rightOp); 123 | sprintf(str, "\tlw %s, 0(%s)\n", printReg(x), printReg(y)); 124 | fputs(str, fp); 125 | } 126 | 127 | } else if(leftOp->kind==TADDRESS || leftOp->kind==VADDRESS){ 128 | // *x = y 129 | if(rightOp->kind == CONSTANT){ 130 | x = getReg(leftOp); 131 | sprintf(str, "\tli $s3, %s\n\tsw $s3, 0(%s)\n", rightOp->u.value, printReg(x)); 132 | fputs(str, fp); 133 | } else if(rightOp->kind==VARIABLE || rightOp->kind==TEMPVAR){ 134 | x = getReg(leftOp); 135 | y = getReg(rightOp); 136 | sprintf(str, "\tsw %s, 0(%s)\n", printReg(y), printReg(x)); 137 | fputs(str, fp); 138 | } 139 | } 140 | swReg(x); 141 | } 142 | 143 | void mipsOperation(InterCode interCode){ 144 | char str[STR_LENGTH]; 145 | memset(str, 0, sizeof(str)); 146 | // + - * / 147 | Operand result = interCode->u.binop.result; 148 | Operand leftOp = interCode->u.binop.op1; 149 | Operand rightOp = interCode->u.binop.op2; 150 | int x, y, z; 151 | if((leftOp->kind==TEMPVAR||leftOp->kind==VARIABLE)&&(rightOp->kind==TEMPVAR||rightOp->kind==VARIABLE)){ 152 | x = getReg(result); 153 | y = getReg(leftOp); 154 | z = getReg(rightOp); 155 | switch (interCode->kind) { 156 | case ADD_N: 157 | sprintf(str, "\tadd %s, %s, %s\n", printReg(x), printReg(y), printReg(z)); 158 | break; 159 | case SUB_N: 160 | sprintf(str, "\tsub %s, %s, %s\n", printReg(x), printReg(y), printReg(z)); 161 | break; 162 | case MUL_N: 163 | sprintf(str, "\tmul %s, %s, %s\n", printReg(x), printReg(y), printReg(z)); 164 | break; 165 | case DIV_N: 166 | sprintf(str, "\tdiv %s, %s\n\tmflo %s\n", printReg(y), printReg(z), printReg(x)); 167 | break; 168 | } 169 | fputs(str, fp); 170 | } 171 | else if((leftOp->kind==CONSTANT)&&(rightOp->kind==TEMPVAR||rightOp->kind==VARIABLE)){ 172 | x = getReg(result); 173 | y = getReg(rightOp); 174 | switch (interCode->kind) { 175 | case ADD_N: 176 | sprintf(str, "\taddi %s, %s, %s\n", printReg(x), printReg(y), leftOp->u.value); 177 | break; 178 | case SUB_N: 179 | sprintf(str, "\taddi %s, %s, -%s\n", printReg(x), printReg(y), leftOp->u.value); 180 | break; 181 | default: 182 | exit(-1); 183 | } 184 | fputs(str, fp); 185 | } 186 | else if((rightOp->kind==CONSTANT)&&(leftOp->kind==TEMPVAR||leftOp->kind==VARIABLE)){ 187 | x = getReg(result); 188 | y = getReg(leftOp); 189 | switch (interCode->kind) { 190 | case ADD_N: 191 | sprintf(str, "\taddi %s, %s, %s\n", printReg(x), printReg(y), rightOp->u.value); 192 | break; 193 | case SUB_N: 194 | sprintf(str, "\taddi %s, %s, -%s\n", printReg(x), printReg(y), rightOp->u.value); 195 | break; 196 | case MUL_N: case DIV_N: 197 | default: 198 | exit(-1); 199 | } 200 | fputs(str, fp); 201 | } 202 | swReg(x); 203 | } 204 | 205 | void mipsRead(InterCode interCode){ 206 | fputs("\tsubu $sp, $sp, 4\n", fp); 207 | fputs("\tsw $ra, 0($sp)\n", fp); 208 | 209 | int x = getReg(interCode->u.sinop.op); 210 | char str[STR_LENGTH]; 211 | memset(str, 0, sizeof(str)); 212 | sprintf(str, "\tjal read\n\tmove %s, $v0\n", printReg(x)); 213 | fputs(str, fp); 214 | swReg(x); 215 | 216 | fputs("\tlw $ra, 0($sp)\n", fp); 217 | fputs("\taddi $sp, $sp, 4\n", fp); 218 | } 219 | 220 | void mipsWrite(InterCode interCode){ 221 | fputs("\tsubu $sp, $sp, 4\n", fp); 222 | fputs("\tsw $ra, 0($sp)\n", fp); 223 | 224 | char str[STR_LENGTH]; 225 | memset(str, 0, sizeof(str)); 226 | int r = getReg(interCode->u.sinop.op); 227 | if(interCode->u.sinop.op->kind == TEMPVAR || interCode->u.sinop.op->kind == VARIABLE) 228 | sprintf(str, "\tmove $a0, %s\n\tjal write\n", printReg(r)); 229 | else if(interCode->u.sinop.op->kind == TADDRESS || interCode->u.sinop.op->kind == VADDRESS){ 230 | sprintf(str, "\tlw $a0, 0(%s)\n\tjal write\n", printReg(r)); 231 | } 232 | fputs(str, fp); 233 | swReg(r); 234 | 235 | fputs("\tlw $ra, 0($sp)\n", fp); 236 | fputs("\taddi $sp, $sp, 4\n", fp); 237 | } 238 | 239 | void mipsCall(InterCode interCode){ 240 | fputs("\tsubu $sp, $sp, 4\n", fp); 241 | fputs("\tsw $ra, 0($sp)\n", fp); 242 | 243 | Operand op = interCode->u.assign.left; 244 | Operand func = interCode->u.assign.right; 245 | int x = getReg(op); 246 | // jal f 247 | // move reg(x), $v0 248 | char str[STR_LENGTH]; 249 | memset(str, 0, sizeof(str)); 250 | sprintf(str, "\tjal %s\n\tmove %s, $v0\n", func->u.value, printReg(x)); 251 | fputs(str, fp); 252 | swReg(x); 253 | fputs("\tlw $ra, 0($sp)\n", fp); 254 | fputs("\taddi $sp, $sp, 4\n", fp); 255 | curArg = 0; 256 | } 257 | 258 | void mipsReturn(InterCode interCode){ 259 | char str[STR_LENGTH]; 260 | memset(str, 0, sizeof(str)); 261 | Operand op = interCode->u.sinop.op; 262 | if(op->kind!=CONSTANT){ 263 | int x = getReg(op); 264 | // move $v0, reg(x) 265 | // jr $ra 266 | sprintf(str, "\tmove $v0, %s\n\taddi $sp, $sp, %d\n\tlw $fp, 0($sp)\n\taddi $sp, $sp, 4\n\tjr $ra\n", printReg(x), stackSize); 267 | } else { 268 | sprintf(str, "\tmove $v0, $%s\n\taddi $sp, $sp, %d\n\tlw $fp, 0($sp)\n\taddi $sp, $sp, 4\n\tjr $ra\n", op->u.value, stackSize); 269 | } 270 | fputs(str, fp); 271 | } 272 | 273 | void mipsGOTO(InterCode interCode){ 274 | char str[STR_LENGTH]; 275 | memset(str, 0, sizeof(str)); 276 | // j x 277 | sprintf(str, "\tj label%d\n",interCode->u.sinop.op->u.var_no); 278 | fputs(str, fp); 279 | } 280 | 281 | void mipsIFGOTO(InterCode interCode){ 282 | char str[STR_LENGTH]; 283 | memset(str, 0, sizeof(str)); 284 | Operand leftOp = interCode->u.triop.x; 285 | Operand rightOp = interCode->u.triop.y; 286 | Operand label = interCode->u.triop.label; 287 | char *op = interCode->u.triop.op; 288 | 289 | if(leftOp->kind != CONSTANT && rightOp->kind != CONSTANT){ 290 | int x = getReg(leftOp); 291 | int y = getReg(rightOp); 292 | // bxx reg(x), reg(y), z 293 | if(strcmp(op, "==")==0){ 294 | sprintf(str, "\tbeq %s, %s, label%d\n",printReg(x), printReg(y), label->u.var_no); 295 | } else if(strcmp(op, "!=")==0){ 296 | sprintf(str, "\tbne %s, %s, label%d\n",printReg(x), printReg(y), label->u.var_no); 297 | } else if(strcmp(op, ">")==0){ 298 | sprintf(str, "\tbgt %s, %s, label%d\n",printReg(x), printReg(y), label->u.var_no); 299 | } else if(strcmp(op, "<")==0){ 300 | sprintf(str, "\tblt %s, %s, label%d\n",printReg(x), printReg(y), label->u.var_no); 301 | } else if(strcmp(op, ">=")==0){ 302 | sprintf(str, "\tbge %s, %s, label%d\n",printReg(x), printReg(y), label->u.var_no); 303 | } else if(strcmp(op, "<=")==0){ 304 | sprintf(str, "\tble %s, %s, label%d\n",printReg(x), printReg(y), label->u.var_no); 305 | } 306 | } else if(leftOp->kind == CONSTANT && rightOp->kind != CONSTANT){ 307 | int y = getReg(rightOp); 308 | // bxx reg(x), reg(y), z 309 | if(strcmp(op, "==")==0){ 310 | sprintf(str, "\tbeq %s, %s, label%d\n", printReg(y), leftOp->u.value, label->u.var_no); 311 | } else if(strcmp(op, "!=")==0){ 312 | sprintf(str, "\tbne %s, %s, label%d\n", printReg(y), leftOp->u.value, label->u.var_no); 313 | } else if(strcmp(op, ">")==0){ 314 | sprintf(str, "\tblt %s, %s, label%d\n", printReg(y), leftOp->u.value, label->u.var_no); 315 | } else if(strcmp(op, "<")==0){ 316 | sprintf(str, "\tbgt %s, %s, label%d\n", printReg(y), leftOp->u.value, label->u.var_no); 317 | } else if(strcmp(op, ">=")==0){ 318 | sprintf(str, "\tble %s, %s, label%d\n", printReg(y), leftOp->u.value, label->u.var_no); 319 | } else if(strcmp(op, "<=")==0){ 320 | sprintf(str, "\tbge %s, %s, label%d\n", printReg(y), leftOp->u.value, label->u.var_no); 321 | } 322 | } else if(rightOp->kind == CONSTANT && leftOp->kind != CONSTANT){ 323 | int x = getReg(leftOp); 324 | // bxx reg(x), reg(y), z 325 | if(strcmp(op, "==")==0){ 326 | sprintf(str, "\tbeq %s, %s, label%d\n",printReg(x), rightOp->u.value, label->u.var_no); 327 | } else if(strcmp(op, "!=")==0){ 328 | sprintf(str, "\tbne %s, %s, label%d\n",printReg(x), rightOp->u.value, label->u.var_no); 329 | } else if(strcmp(op, ">")==0){ 330 | sprintf(str, "\tbgt %s, %s, label%d\n",printReg(x), rightOp->u.value, label->u.var_no); 331 | } else if(strcmp(op, "<")==0){ 332 | sprintf(str, "\tblt %s, %s, label%d\n",printReg(x), rightOp->u.value, label->u.var_no); 333 | } else if(strcmp(op, ">=")==0){ 334 | sprintf(str, "\tbge %s, %s, label%d\n",printReg(x), rightOp->u.value, label->u.var_no); 335 | } else if(strcmp(op, "<=")==0){ 336 | sprintf(str, "\tble %s, %s, label%d\n",printReg(x), rightOp->u.value, label->u.var_no); 337 | } 338 | } 339 | fputs(str, fp); 340 | } 341 | 342 | void mipsFunction(InterCode interCode){ 343 | 344 | char str[STR_LENGTH]; 345 | memset(str, 0, sizeof(str)); 346 | // function: 347 | sprintf(str, "%s:\n\tsubu $sp, $sp, 4\n\tsw $fp, 0($sp)\n\tmove $fp, $sp\n\tsubu $sp, $sp, %d\n",interCode->u.sinop.op->u.value,stackSize); 348 | fputs(str, fp); 349 | spOffset = 0; 350 | curParam = 0; 351 | } 352 | 353 | void mipsArg(InterCode interCode){ 354 | char str[STR_LENGTH]; 355 | memset(str, 0, sizeof(str)); 356 | Operand op = interCode->u.sinop.op; 357 | Var_t *arg=NULL; 358 | if(op->kind == TEMPVAR){ 359 | char argName[20]; 360 | memset(argName, 0, 20); 361 | sprintf(argName, "t%d", op->u.var_no); 362 | arg = findVar(argName); 363 | } else if(op->kind ==VARIABLE){ 364 | arg = findVar(op->u.value); 365 | } 366 | if(arg == NULL) 367 | exit(-1); 368 | if(curArg<4){ 369 | sprintf(str, "\tlw $a%d, %d($fp)\n", curArg, arg->offset); 370 | } else{ 371 | sprintf(str, "\tlw $s0, %d($fp)\n\tsubu $sp, $sp, 4\n\tlw $s0, 0($sp)\n", arg->offset); 372 | } 373 | fputs(str, fp); 374 | ++curArg; 375 | if(interCode->next==NULL || interCode->next->kind!=ARG_N){ 376 | curArg = 0; 377 | } 378 | } 379 | 380 | void mipsParam(InterCode interCode){ 381 | char str[STR_LENGTH]; 382 | memset(str, 0, sizeof(str)); 383 | 384 | Var_t* param = malloc(sizeof(Var_t)); 385 | param->name = interCode->u.sinop.op->u.value; 386 | spOffset -= 4; 387 | param->offset = spOffset; 388 | addVar(param); 389 | if(curParam<4){ 390 | sprintf(str, "\tsw $a%d, %d($fp)\n", curParam, param->offset); 391 | } else { 392 | sprintf(str, "\tlw $a0, %d($fp)\n\tsw $a0, %d($fp)\n", (curParam-2)*4, param->offset); 393 | } 394 | fputs(str, fp); 395 | ++curParam; 396 | } 397 | 398 | void mipsDec(InterCode interCode){ 399 | Var_t *arrayHead = malloc(sizeof(Var_t)); 400 | spOffset -= 4; 401 | arrayHead->offset = spOffset; 402 | spOffset -= interCode->u.dec.size; 403 | if(interCode->u.dec.op->kind == VARIABLE){ 404 | arrayHead->name = interCode->u.dec.op->u.value; 405 | } else if(interCode->u.dec.op->kind == TEMPVAR){ 406 | char *arrayName = malloc(32); 407 | memset(arrayName, 0, sizeof(arrayName)); 408 | sprintf(arrayName, "t%d", interCode->u.dec.op->u.var_no); 409 | arrayHead->name = arrayName; 410 | } 411 | addVar(arrayHead); 412 | 413 | char str[STR_LENGTH]; 414 | memset(str, 0, sizeof(str)); 415 | sprintf(str, "\taddi $s1, $fp, %d\n\tsw $s1, %d($fp)\n", spOffset, arrayHead->offset); 416 | fputs(str, fp); 417 | } 418 | 419 | void mipsAddress(InterCode interCode){ 420 | Operand leftOp = interCode->u.assign.left; 421 | Operand rightOp = interCode->u.assign.right; 422 | Var_t *arrayHead=NULL; 423 | if(rightOp->kind == TEMPVAR){ 424 | char *arrayName = malloc(32); 425 | memset(arrayName, 0, sizeof(arrayName)); 426 | sprintf(arrayName, "t%d", rightOp->u.var_no); 427 | arrayHead = findVar(arrayName); 428 | } else if(rightOp->kind == VARIABLE){ 429 | arrayHead = findVar(rightOp->u.value); 430 | } 431 | if(arrayHead == NULL){ 432 | exit(-1); 433 | } 434 | int x = getReg(leftOp); 435 | char str[STR_LENGTH]; 436 | memset(str, 0, sizeof(str)); 437 | sprintf(str, "\tlw %s, %d($fp)\n", printReg(x), arrayHead->offset); 438 | fputs(str, fp); 439 | swReg(x); 440 | } 441 | 442 | // Register 443 | void initRegs(){ 444 | int i=0; 445 | for(i=0; ikind == TEMPVAR){ 454 | name = malloc(40); 455 | memset(name, 0, sizeof(name)); 456 | sprintf(name, "t%d", op->u.var_no); 457 | } 458 | else if(op->kind == TADDRESS){ 459 | name = malloc(40); 460 | memset(name, 0, sizeof(name)); 461 | sprintf(name, "t%d", op->u.addr->u.var_no); 462 | } 463 | else if(op->kind == VADDRESS){ 464 | name = op->u.addr->u.value; 465 | } 466 | else if(op->kind == VARIABLE){ 467 | name = op->u.value; 468 | } 469 | Var_t* var = findVar(name); 470 | int i = curReg + REG_T_START; 471 | curReg = (++curReg)%(REG_T_END - REG_T_START); 472 | if(var == NULL){ 473 | var = malloc(sizeof(Var_t)); 474 | var->name = name; 475 | spOffset -= 4; 476 | var->offset = spOffset; 477 | addVar(var); 478 | var->reg = i; 479 | regs[i].var = var; 480 | } else{ 481 | var->reg = i; 482 | regs[i].var = var; 483 | lwReg(i, var); 484 | } 485 | return i; 486 | } 487 | 488 | char* printReg(int index){ 489 | return regs[index].name; 490 | } 491 | 492 | void swReg(int index){ 493 | char str[50]; 494 | memset(str, 0, sizeof(str)); 495 | Var_t *var = regs[index].var; 496 | sprintf(str, "\tsw %s, %d($fp)\n", printReg(index), var->offset); 497 | fputs(str, fp); 498 | } 499 | 500 | void lwReg(int index, Var_t *var){ 501 | char str[50]; 502 | memset(str, 0, sizeof(str)); 503 | regs[index].var = var; 504 | sprintf(str, "\tlw %s, %d($fp)\n", printReg(index), var->offset); 505 | fputs(str, fp); 506 | } 507 | 508 | // Variable 509 | void delVars(){ 510 | Var_t *ptr = varList; 511 | while(ptr != NULL){ 512 | varList = varList->next; 513 | free(ptr); 514 | ptr = varList; 515 | } 516 | } 517 | 518 | void addVar(Var_t *var){ 519 | if(var==NULL) 520 | exit(-1); 521 | var->next = NULL; 522 | if(varList==NULL){ 523 | varList = var; 524 | } else{ 525 | Var_t *ptr = varList; 526 | while(ptr->next!=NULL) 527 | ptr = ptr->next; 528 | ptr->next = var; 529 | } 530 | } 531 | 532 | Var_t* findVar(char *name){ 533 | Var_t *ptr = varList; 534 | while(ptr != NULL){ 535 | if(strcmp(ptr->name, name)==0){ 536 | break; 537 | } else{ 538 | ptr = ptr->next; 539 | } 540 | } 541 | return ptr; 542 | } 543 | 544 | Register_ regs[REG_NUM]; 545 | Var_t *varList = NULL; 546 | FILE *fp = NULL; 547 | int curReg = 0; 548 | int spOffset = 0; 549 | int curParam = 0; 550 | int curArg = 0; 551 | const int stackSize = 100; 552 | 553 | char* regName[] = { 554 | "$zero", 555 | "$at", 556 | "$v0","$v1", 557 | "$a0","$a1","$a2","$a3", 558 | "$t0","$t1","$t2","$t3","$t4","$t5","$t6","$t7", 559 | "$s0","$s1","$s2","$s3","$s4","$s5","$s6","$s7", 560 | "$t8","$t9", 561 | "$k0","$k1", 562 | "$gp", 563 | "$sp", 564 | "$fp", 565 | "$ra" 566 | }; 567 | -------------------------------------------------------------------------------- /Project4/mips.h: -------------------------------------------------------------------------------- 1 | #ifndef MIPS_H 2 | #define MIPS_H 3 | 4 | #define REG_NUM 32 5 | #define REG_T_START 8 6 | #define REG_T_END 16 7 | #define STR_LENGTH 200 8 | 9 | #include "InterCode.h" 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | typedef struct Var_t { 16 | char *name; 17 | int reg; 18 | int offset; 19 | struct Var_t *next; 20 | } Var_t; 21 | 22 | typedef struct Register_ { 23 | char *name; 24 | Var_t *var; 25 | } Register_; 26 | 27 | void printMips(char *fileName); 28 | void printMipsCode(InterCode interCode); 29 | 30 | void mipsLabel(InterCode interCode); 31 | void mipsAssign(InterCode interCode); 32 | void mipsOperation(InterCode interCodep); 33 | void mipsRead(InterCode interCode); 34 | void mipsWrite(InterCode interCode); 35 | void mipsCall(InterCode interCode); 36 | void mipsReturn(InterCode interCode); 37 | void mipsGOTO(InterCode interCode); 38 | void mipsIFGOTO(InterCode interCode); 39 | void mipsFunction(InterCode interCode); 40 | void mipsArg(InterCode interCode); 41 | void mipsParam(InterCode interCode); 42 | void mipsDec(InterCode interCode); 43 | void mipsAddress(InterCode interCode); 44 | 45 | void initRegs(); 46 | int getReg(Operand op); 47 | char* printReg(int index); 48 | void swReg(int index); 49 | void lwReg(int index, Var_t *var); 50 | 51 | void delVars(); 52 | void addVar(Var_t *var); 53 | Var_t* findVar(char *name); 54 | 55 | extern Register_ regs[]; 56 | extern char* regName[]; 57 | extern FILE* fp; 58 | extern Var_t *varList; 59 | extern int curReg; 60 | extern int spOffset; 61 | extern int curParam; 62 | extern int curArg; 63 | extern const int stackSize; 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /Project4/parse.h: -------------------------------------------------------------------------------- 1 | #ifndef PRASE_H 2 | #define PRASE_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "SyntaxTree.h" 12 | 13 | /* 14 | * lex & parse 15 | */ 16 | extern int yylex(void); 17 | extern int yyparse(void); 18 | extern void yyrestart(FILE*); 19 | extern void yyerror(char*); 20 | extern int yylineno; 21 | 22 | /* 23 | * SyntaxTree 24 | */ 25 | extern Node* tree; 26 | 27 | /* 28 | * main 29 | */ 30 | extern int errorLexFlag; 31 | extern int errorSyntaxFlag; 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /Project4/report.md: -------------------------------------------------------------------------------- 1 | # Project4 实验报告 2 | ###### 151220136 许卓尔 3 | ###### 151220168 赵文昊 4 | 5 | ## 实现功能 6 | 7 | 1. **指令选择**(151220136) 8 | 2. **寄存器选择**(151220136) 9 | 3. **栈管理**(151220168) 10 | 11 | 12 | ## 实现方法 13 | 14 | #### 指令选择 15 | 16 | - 指令选择 17 | 18 | 通过遍历IR线性表,根据IR->kind,参照指导攻略中的IR-MIPS指令表进行翻译,输出到out.s中; 19 | 20 | 21 | 22 | #### 寄存器选择 23 | 24 | - 寄存器数据结构 25 | 26 | 定义了全局变量为寄存器的名字,在初始化过程中进行赋值,这样可以通过下标访问寄存器; 27 | 28 | 寄存器中存储了当前寄存器中变量的指针; 29 | 30 | - 选择算法 31 | 32 | 由于时间原因,直接在t0~t7中进行了队列式寄存器分配——先来先分配; 33 | 34 | 通过void swReg(int)函数,在使用完寄存器后马上把相应的变量存入内存; 35 | 36 | - 变量管理 37 | 38 | 由于变量不重名、采用名等价的形式,因此将所有的变量记录在Var_t的链表中; 39 | 40 | 对于新的变量,即认为是当前函数的临时变量,存储到函数的栈空间中; 41 | 42 | ``` 43 | typedef struct Var_t { 44 | char *name; 45 | int reg; 46 | int offset; 47 | struct Var_t *next; 48 | } Var_t; 49 | 50 | typedef struct Register_ { 51 | char *name; 52 | Var_t *var; 53 | } Register_; 54 | 55 | Register_ regs[]; 56 | char* regName[]; 57 | Var_t *varList; 58 | ``` 59 | 60 | #### 栈管理 61 | 62 | - 参数传入 63 | 64 | 前4个参数,存入a0~a3寄存器中; 65 | 66 | 对于其他参数,按序存入栈中,在函数中,利用fp拿出实参存入栈中作为临时变量; 67 | 68 | - 活动记录 69 | 70 | 只需在调用前将$fp、$ra压栈,在RETURN后将$ra、$fp弹出即可 71 | 72 | 73 | 74 | > 因为没有写寄存器分配,于是都作为栈中临时变量处理了,在Var_t中加入了offset确定相对于fp的偏移; 75 | 76 | 77 | ## 编译介绍 78 | 79 | ##### Makefile文件 80 | 81 | make parser | make 82 | > 对词法分析器、语法分析器进行编译并生成相应的parser程序; 83 | 84 | make clean 85 | > 对生成文件进行清理; 86 | 87 | ./parser ./testcase/TestFile.txt OutFileName.s 88 | > 对当前路径下pretest文件夹中的TestFile.txt文件进行编译,生成MIPS32汇编代码到OutFileName.s文件中; 89 | -------------------------------------------------------------------------------- /Project4/syntax.y: -------------------------------------------------------------------------------- 1 | %{ 2 | #include 3 | #include 4 | #include "parse.h" 5 | #include "SyntaxTree.h" 6 | %} 7 | 8 | /* declared types */ 9 | %union { 10 | int type_int; 11 | float type_float; 12 | double type_double; 13 | Node* type_node; 14 | } 15 | 16 | /* declared tokens */ 17 | %token INT 18 | %token FLOAT 19 | %token ID 20 | %token SEMI 21 | %token COMMA 22 | %token ASSIGNOP 23 | %token RELOP 24 | %token PLUS 25 | %token MINUS 26 | %token STAR 27 | %token DIV 28 | %token AND 29 | %token OR 30 | %token NOT 31 | %token DOT 32 | %token TYPE 33 | %token LP 34 | %token RP 35 | %token LB 36 | %token RB 37 | %token LC 38 | %token RC 39 | %token STRUCT 40 | %token RETURN 41 | %token IF 42 | %token ELSE 43 | %token WHILE 44 | 45 | /* declared non-terminals */ 46 | %type Program ExtDefList ExtDef ExtDecList 47 | %type Specifier StructSpecifier OptTag Tag 48 | %type VarDec FunDec VarList ParamDec 49 | %type CompSt StmtList Stmt 50 | %type DefList Def DecList Dec 51 | %type Exp Args 52 | 53 | %right ASSIGNOP 54 | %left OR 55 | %left AND 56 | %left RELOP 57 | %left PLUS 58 | %left STAR DIV 59 | %right NOT 60 | %left LP RP LB RB DOT 61 | 62 | %nonassoc LOWER_THAN_ELSE 63 | %nonassoc ELSE 64 | 65 | 66 | %% 67 | 68 | /* High-level Definitions */ 69 | Program : ExtDefList { 70 | $$ = init("Program", NULL, TYPE_NONTERMINAL, @$.first_line); 71 | insert($$, $1); 72 | tree = $$; 73 | } 74 | ; 75 | ExtDefList : ExtDef ExtDefList{ 76 | $$ = init("ExtDefList", NULL, TYPE_NONTERMINAL, @$.first_line); 77 | insert($$,$1);insert($$,$2); 78 | } 79 | | /* empty */{ $$ = init("ExtDefList", NULL, TYPE_NONTERMINAL, @$.first_line); } 80 | ; 81 | ExtDef : Specifier ExtDecList SEMI{ 82 | $$ = init("ExtDef", NULL, TYPE_NONTERMINAL, @$.first_line); 83 | insert($$,$1);insert($$,$2);insert($$,$3); 84 | } 85 | | Specifier SEMI{ 86 | $$ = init("ExtDef", NULL, TYPE_NONTERMINAL, @$.first_line); 87 | insert($$,$1);insert($$,$2); 88 | } 89 | | Specifier FunDec SEMI{ 90 | $$ = init("ExtDef", NULL, TYPE_NONTERMINAL, @$.first_line); 91 | insert($$,$1);insert($$,$2);insert($$,$3); 92 | } 93 | | Specifier FunDec CompSt{ 94 | $$ = init("ExtDef", NULL, TYPE_NONTERMINAL, @$.first_line); 95 | insert($$,$1);insert($$,$2);insert($$,$3); 96 | } 97 | | error SEMI { errorSyntaxFlag=2; } 98 | ; 99 | ExtDecList : VarDec{ 100 | $$ = init("ExtDecList", NULL, TYPE_NONTERMINAL, @$.first_line); 101 | insert($$, $1); 102 | } 103 | | VarDec COMMA ExtDecList{ 104 | $$ = init("ExtDecList", NULL, TYPE_NONTERMINAL, @$.first_line); 105 | insert($$,$1);insert($$,$2);insert($$,$3); 106 | } 107 | ; 108 | 109 | /* Specifiers */ 110 | Specifier : TYPE{ 111 | $$ = init("Specifier", NULL, TYPE_NONTERMINAL, @$.first_line); 112 | insert($$,$1); 113 | } 114 | | StructSpecifier{ 115 | $$ = init("Specifier", NULL, TYPE_NONTERMINAL, @$.first_line); 116 | insert($$,$1); 117 | } 118 | ; 119 | StructSpecifier : STRUCT OptTag LC DefList RC{ 120 | $$ = init("StructSpecifier", NULL, TYPE_NONTERMINAL, @$.first_line); 121 | insert($$,$1);insert($$,$2);insert($$,$3);insert($$,$4);insert($$,$5); 122 | } 123 | | STRUCT Tag{ 124 | $$ = init("StructSpecifier", NULL, TYPE_NONTERMINAL, @$.first_line); 125 | insert($$,$1);insert($$,$2); 126 | } 127 | ; 128 | OptTag : ID{ 129 | $$ = init("OptTag", NULL, TYPE_NONTERMINAL, @$.first_line); 130 | insert($$,$1); 131 | } 132 | | /* empty */{$$ = init("OptTag", NULL, TYPE_NONTERMINAL, @$.first_line);} 133 | ; 134 | Tag : ID{ 135 | $$ = init("Tag", NULL, TYPE_NONTERMINAL, @$.first_line); 136 | insert($$,$1); 137 | } 138 | ; 139 | 140 | /* Declarators */ 141 | VarDec : ID{ 142 | $$ = init("VarDec", NULL, TYPE_NONTERMINAL, @$.first_line); 143 | insert($$,$1); 144 | } 145 | | VarDec LB INT RB{ 146 | $$ = init("VarDec", NULL, TYPE_NONTERMINAL, @$.first_line); 147 | insert($$,$1);insert($$,$2);insert($$,$3);insert($$,$4); 148 | } 149 | ; 150 | FunDec : ID LP VarList RP{ 151 | $$ = init("FunDec", NULL, TYPE_NONTERMINAL, @$.first_line); 152 | insert($$,$1);insert($$,$2);insert($$,$3);insert($$,$4); 153 | } 154 | | ID LP RP{ 155 | $$ = init("FunDec", NULL, TYPE_NONTERMINAL, @$.first_line); 156 | insert($$,$1);insert($$,$2);insert($$,$3); 157 | } 158 | | error RP{ errorSyntaxFlag=2; } 159 | ; 160 | VarList : ParamDec COMMA VarList{ 161 | $$ = init("VarList", NULL, TYPE_NONTERMINAL, @$.first_line); 162 | insert($$,$1);insert($$,$2);insert($$,$3); 163 | } 164 | | ParamDec{ 165 | $$ = init("VarList", NULL, TYPE_NONTERMINAL, @$.first_line); 166 | insert($$,$1); 167 | } 168 | ; 169 | ParamDec : Specifier VarDec{ 170 | $$ = init("ParamDec", NULL, TYPE_NONTERMINAL, @$.first_line); 171 | insert($$,$1);insert($$,$2); 172 | } 173 | ; 174 | 175 | /* Statements */ 176 | CompSt : LC DefList StmtList RC{ 177 | $$ = init("CompSt", NULL, TYPE_NONTERMINAL, @$.first_line); 178 | insert($$,$1);insert($$,$2);insert($$,$3);insert($$,$4); 179 | } 180 | | error RC{ errorSyntaxFlag=2; } 181 | ; 182 | StmtList : Stmt StmtList{ 183 | $$ = init("StmtList", NULL, TYPE_NONTERMINAL, @$.first_line); 184 | insert($$,$1);insert($$,$2); 185 | } 186 | | /* empty */{ 187 | $$ = init("StmtList", NULL, TYPE_NONTERMINAL, @$.first_line); 188 | } 189 | ; 190 | Stmt : Exp SEMI{ 191 | $$ = init("Stmt", NULL, TYPE_NONTERMINAL, @$.first_line); 192 | insert($$,$1);insert($$,$2); 193 | } 194 | | CompSt{ 195 | $$ = init("Stmt", NULL, TYPE_NONTERMINAL, @$.first_line); 196 | insert($$,$1); 197 | } 198 | | RETURN Exp SEMI{ 199 | $$ = init("Stmt", NULL, TYPE_NONTERMINAL, @$.first_line); 200 | insert($$,$1);insert($$,$2);insert($$,$3); 201 | } 202 | | IF LP Exp RP Stmt %prec LOWER_THAN_ELSE{ 203 | $$ = init("Stmt", NULL, TYPE_NONTERMINAL, @$.first_line); 204 | insert($$,$1);insert($$,$2);insert($$,$3); 205 | insert($$,$4);insert($$,$5); 206 | } 207 | | IF LP Exp RP Stmt ELSE Stmt{ 208 | $$ = init("Stmt", NULL, TYPE_NONTERMINAL, @$.first_line); 209 | insert($$,$1);insert($$,$2);insert($$,$3); 210 | insert($$,$4);insert($$,$5);insert($$,$6);insert($$,$7); 211 | } 212 | | WHILE LP Exp RP Stmt{ 213 | $$ = init("Stmt", NULL, TYPE_NONTERMINAL, @$.first_line); 214 | insert($$,$1);insert($$,$2);insert($$,$3); 215 | insert($$,$4);insert($$,$5); 216 | } 217 | | error SEMI { errorSyntaxFlag=2; } 218 | ; 219 | 220 | /* Local Definitions */ 221 | DefList : Def DefList{ 222 | $$ = init("DefList", NULL, TYPE_NONTERMINAL, @$.first_line); 223 | insert($$,$1);insert($$,$2); 224 | } 225 | | /* empty */{ 226 | $$ = init("DefList", NULL, TYPE_NONTERMINAL, @$.first_line); 227 | } 228 | ; 229 | Def : Specifier DecList SEMI{ 230 | $$ = init("Def", NULL, TYPE_NONTERMINAL, @$.first_line); 231 | insert($$,$1);insert($$,$2);insert($$,$3); 232 | } 233 | | error SEMI{ errorSyntaxFlag=2; } 234 | ; 235 | DecList : Dec{ 236 | $$ = init("DecList", NULL, TYPE_NONTERMINAL, @$.first_line); 237 | insert($$,$1); 238 | } 239 | | Dec COMMA DecList{ 240 | $$ = init("DecList", NULL, TYPE_NONTERMINAL, @$.first_line); 241 | insert($$,$1);insert($$,$2);insert($$,$3); 242 | } 243 | ; 244 | Dec : VarDec{ 245 | $$ = init("Dec", NULL, TYPE_NONTERMINAL, @$.first_line); 246 | insert($$,$1); 247 | } 248 | | VarDec ASSIGNOP Exp{ 249 | $$ = init("Dec", NULL, TYPE_NONTERMINAL, @$.first_line); 250 | insert($$,$1);insert($$,$2);insert($$,$3); 251 | } 252 | 253 | /* Expressions */ 254 | Exp : Exp ASSIGNOP Exp{ 255 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 256 | insert($$,$1);insert($$,$2);insert($$,$3); 257 | } 258 | | Exp AND Exp{ 259 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 260 | insert($$,$1); 261 | } 262 | | Exp OR Exp{ 263 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 264 | insert($$,$1);insert($$,$2);insert($$,$3); 265 | } 266 | | Exp RELOP Exp{ 267 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 268 | insert($$,$1);insert($$,$2);insert($$,$3); 269 | } 270 | | Exp PLUS Exp{ 271 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 272 | insert($$,$1);insert($$,$2);insert($$,$3); 273 | } 274 | | Exp MINUS Exp{ 275 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 276 | insert($$,$1);insert($$,$2);insert($$,$3); 277 | } 278 | | Exp STAR Exp{ 279 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 280 | insert($$,$1);insert($$,$2);insert($$,$3); 281 | } 282 | | Exp DIV Exp{ 283 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 284 | insert($$,$1);insert($$,$2);insert($$,$3); 285 | } 286 | | LP Exp RP{ 287 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 288 | insert($$,$1);insert($$,$2);insert($$,$3); 289 | } 290 | | MINUS Exp{ 291 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 292 | insert($$,$1);insert($$,$2); 293 | } 294 | | NOT Exp{ 295 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 296 | insert($$,$1);insert($$,$2); 297 | } 298 | | ID LP Args RP{ 299 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 300 | insert($$,$1);insert($$,$2);insert($$,$3);insert($$,$4); 301 | } 302 | | ID LP RP{ 303 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 304 | insert($$,$1);insert($$,$2);insert($$,$3); 305 | } 306 | | Exp LB Exp RB{ 307 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 308 | insert($$,$1);insert($$,$2);insert($$,$3);insert($$,$4); 309 | } 310 | | Exp DOT ID{ 311 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 312 | insert($$,$1);insert($$,$2);insert($$,$3); 313 | } 314 | | ID{ 315 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 316 | insert($$,$1); 317 | } 318 | | INT{ 319 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 320 | insert($$,$1); 321 | } 322 | | FLOAT{ 323 | $$ = init("Exp", NULL, TYPE_NONTERMINAL, @$.first_line); 324 | insert($$,$1); 325 | } 326 | ; 327 | Args : Exp COMMA Args{ 328 | $$ = init("Args", NULL, TYPE_NONTERMINAL, @$.first_line); 329 | insert($$,$1);insert($$,$2);insert($$,$3); 330 | } 331 | | Exp{ 332 | $$ = init("Args", NULL, TYPE_NONTERMINAL, @$.first_line); 333 | insert($$,$1); 334 | } 335 | ; 336 | 337 | /* Comments */ 338 | 339 | %% 340 | 341 | 342 | void yyerror(char* msg){ 343 | if(errorLexFlag==0) 344 | fprintf(stderr, "Error type B at Line %d: %s\n",yylineno,msg); 345 | } 346 | -------------------------------------------------------------------------------- /Project4/testcase/testcase1.txt: -------------------------------------------------------------------------------- 1 | int main() 2 | { 3 | int a = 0, b = 1, i = 0, n; 4 | n = read(); 5 | while (i < n) 6 | { 7 | int c = a + b; 8 | write(b); 9 | a = b; 10 | b = c; 11 | i = i + 1; 12 | } 13 | return 0; 14 | } -------------------------------------------------------------------------------- /Project4/testcase/testcase2.txt: -------------------------------------------------------------------------------- 1 | int fact(int n) 2 | { 3 | if (n == 1) 4 | return n; 5 | else 6 | return (n * fact(n - 1)); 7 | } 8 | 9 | int main() 10 | { 11 | int m, result; 12 | m = read(); 13 | if (m > 1) 14 | result = fact(m); 15 | else 16 | result = 1; 17 | write(result); 18 | return 0; 19 | } -------------------------------------------------------------------------------- /Project4/testcase/testcase3.txt: -------------------------------------------------------------------------------- 1 | int main() 2 | { 3 | int a[2]; 4 | a[1] = 13; 5 | write(a[1]); 6 | return 0; 7 | } 8 | -------------------------------------------------------------------------------- /Project4/testcase/testcase4.txt: -------------------------------------------------------------------------------- 1 | int test(int a, int b, int c, int d, int e){ 2 | e = c + d; 3 | return e; 4 | } 5 | 6 | int main(){ 7 | int f=0, g=1, h=2, i=3, k=4, m; 8 | m = test(f, g, h, i, k); 9 | write(m); 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Compilers 2 | 3 | ### Project 1 4 | 5 | #### 词法分析 6 | - 使用GNU Flex工具实现词法分析器的功能; 7 | > 即撰写一些正则表达式,较为简单; 8 | 9 | #### 语法分析 10 | - 使用GNU Bison工具实现语法分析器的功能; 11 | - 按要求输出语法树; 12 | > 即在action增加自己写的"SyntaxTree.h"的建造,辅以错误恢复,难度一般; 13 | 14 | ### Project 2 15 | 16 | #### 语义分析 17 | - 自顶向下进行SDT,实现属性文法; 18 | - 撰写类型表示、符号表的数据结构; 19 | - 对上下文无关文法进行一定的补充满足附加条件; 20 | > 主要工作为设计数据结构,在SDT中对对应文法增加acion,代码量较大,难度一般; 21 | 22 | 23 | 24 | > 版权所有:正在上编译原理课,注意查重,仅供参考; 25 | --------------------------------------------------------------------------------