├── .gitignore ├── testCase ├── week1 │ ├── test_1.txt │ ├── test_2.txt │ ├── test_3.txt │ └── test_4.txt ├── week2 │ └── test_5.txt ├── week3 │ └── test_6.txt ├── week5 │ └── test_8.txt ├── week6 │ └── test_9.txt ├── week7 │ └── test_10.txt └── week4 │ ├── test_7(1).txt │ ├── test_7(2).txt │ └── test_7(3).txt ├── samples ├── array_ndim.x0 ├── test.x0 ├── gcd.x0 ├── array_recv.x0 ├── lcm.x0 ├── bool.x0 ├── char.x0 ├── operator.x0 ├── loop1.x0 ├── loop3.x0 ├── array.x0 ├── array_double.x0 ├── loop2.x0 ├── loop4.x0 ├── double.x0 └── isprime.x0 ├── Makefile ├── README.md ├── compiler.l ├── table.h ├── code.h └── compiler.y /.gitignore: -------------------------------------------------------------------------------- 1 | compiler 2 | compiler.tab.c 3 | compiler.tab.h 4 | lex.yy.c 5 | fin.txt 6 | core 7 | -------------------------------------------------------------------------------- /testCase/week1/test_1.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yiwangchunyu/X0Compiler/HEAD/testCase/week1/test_1.txt -------------------------------------------------------------------------------- /testCase/week1/test_2.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yiwangchunyu/X0Compiler/HEAD/testCase/week1/test_2.txt -------------------------------------------------------------------------------- /testCase/week1/test_3.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yiwangchunyu/X0Compiler/HEAD/testCase/week1/test_3.txt -------------------------------------------------------------------------------- /testCase/week1/test_4.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yiwangchunyu/X0Compiler/HEAD/testCase/week1/test_4.txt -------------------------------------------------------------------------------- /testCase/week2/test_5.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yiwangchunyu/X0Compiler/HEAD/testCase/week2/test_5.txt -------------------------------------------------------------------------------- /testCase/week3/test_6.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yiwangchunyu/X0Compiler/HEAD/testCase/week3/test_6.txt -------------------------------------------------------------------------------- /testCase/week5/test_8.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yiwangchunyu/X0Compiler/HEAD/testCase/week5/test_8.txt -------------------------------------------------------------------------------- /testCase/week6/test_9.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yiwangchunyu/X0Compiler/HEAD/testCase/week6/test_9.txt -------------------------------------------------------------------------------- /testCase/week7/test_10.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yiwangchunyu/X0Compiler/HEAD/testCase/week7/test_10.txt -------------------------------------------------------------------------------- /testCase/week4/test_7(1).txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yiwangchunyu/X0Compiler/HEAD/testCase/week4/test_7(1).txt -------------------------------------------------------------------------------- /testCase/week4/test_7(2).txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yiwangchunyu/X0Compiler/HEAD/testCase/week4/test_7(2).txt -------------------------------------------------------------------------------- /testCase/week4/test_7(3).txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yiwangchunyu/X0Compiler/HEAD/testCase/week4/test_7(3).txt -------------------------------------------------------------------------------- /samples/array_ndim.x0: -------------------------------------------------------------------------------- 1 | main 2 | { 3 | int a[2][3][4][5]; 4 | a[1][2][3][4]=2233; 5 | write a[1][2][3][4]; 6 | 7 | } -------------------------------------------------------------------------------- /samples/test.x0: -------------------------------------------------------------------------------- 1 | main 2 | { 3 | int a; 4 | int b; 5 | char rt; 6 | char sp; 7 | a=0; 8 | rt='\n'; 9 | sp=' '; 10 | write a; 11 | write rt; 12 | write a; 13 | } -------------------------------------------------------------------------------- /samples/gcd.x0: -------------------------------------------------------------------------------- 1 | main 2 | { 3 | int a; 4 | int b; 5 | int r; 6 | read a; 7 | read b; 8 | r=1; 9 | while(r!=0) 10 | { 11 | r=a%b; 12 | a=b; 13 | b=r; 14 | } 15 | write a; 16 | } 17 | -------------------------------------------------------------------------------- /samples/array_recv.x0: -------------------------------------------------------------------------------- 1 | main 2 | { 3 | const char sp=' '; 4 | const char rt='\n'; 5 | int i; 6 | int a[2][5]; 7 | i=2; 8 | a[0][0]=1; 9 | a[0][2]=3; 10 | i=a[0][a[0][i-2]+1]=i<=3; 11 | write i; 12 | } 13 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: prog clean 2 | 3 | prog: compiler.l compiler.y 4 | lex compiler.l 5 | bison -d compiler.y 6 | gcc -g -o compiler lex.yy.c compiler.tab.c -lm 7 | 8 | clean: 9 | rm lex.yy.c compiler.tab.c compiler.tab.h 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # x0Compiler 2 | ECNU编译原理课程大作业 x0编译器 lex yacc(bison)实现 3 | 4 | run on linux: 5 | 6 | make 7 | ./compiler -t -c src 8 | 9 | 10 | -t: show symbol table 11 | -c: show pcode 12 | src: your source code file 13 | -------------------------------------------------------------------------------- /samples/lcm.x0: -------------------------------------------------------------------------------- 1 | main 2 | { 3 | int a; 4 | int b; 5 | int aa; 6 | int bb; 7 | int r; 8 | read a; 9 | read b; 10 | r=1; 11 | aa=a; 12 | bb=b; 13 | while(r!=0) 14 | { 15 | r=aa%bb; 16 | aa=bb; 17 | bb=r; 18 | } 19 | write a*b/aa; 20 | } 21 | 22 | -------------------------------------------------------------------------------- /samples/bool.x0: -------------------------------------------------------------------------------- 1 | main 2 | { 3 | const char sp=' '; 4 | const char rt='\n'; 5 | const bool t=true; 6 | const bool f=false; 7 | int a; 8 | bool b; 9 | b=0; 10 | a=1; 11 | b = (f and t) or a; 12 | write b; 13 | write sp; 14 | b=not b; 15 | write b; 16 | } -------------------------------------------------------------------------------- /samples/char.x0: -------------------------------------------------------------------------------- 1 | main 2 | { 3 | const char sp=' '; 4 | const char rt='\n'; 5 | char c; 6 | int i; 7 | c='A'; 8 | for(i=1;i<=64;i++) 9 | { 10 | write c; 11 | c=c+1; 12 | write sp; 13 | if(i%26==0) 14 | { 15 | write rt; 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /samples/operator.x0: -------------------------------------------------------------------------------- 1 | main 2 | { 3 | const char sp=' '; 4 | int a; 5 | int b; 6 | a=4; 7 | b=7; 8 | write b%a; 9 | write sp; 10 | write a^b; 11 | write sp; 12 | write odd a; 13 | write sp; 14 | b=a++; 15 | write a; 16 | write sp; 17 | write b; 18 | } -------------------------------------------------------------------------------- /samples/loop1.x0: -------------------------------------------------------------------------------- 1 | main 2 | { 3 | const char sp=' '; 4 | const char rt='\n'; 5 | int i; 6 | int a[10]; 7 | 8 | /*测试for循环与break*/ 9 | for(i=0;i<10;i++) 10 | { 11 | a[i]=i; 12 | if(i==5) 13 | { 14 | break; 15 | } 16 | } 17 | /*打印输出*/ 18 | for(i=0;i<10;i++) 19 | { 20 | write a[i]; 21 | write sp; 22 | } 23 | write rt; 24 | 25 | } -------------------------------------------------------------------------------- /samples/loop3.x0: -------------------------------------------------------------------------------- 1 | main 2 | { 3 | const char sp=' '; 4 | const char rt='\n'; 5 | int i; 6 | int a[10]; 7 | 8 | /*测试repeat until循环与exit*/ 9 | for(i=0;i<10;i++) 10 | { 11 | a[i]=i; 12 | } 13 | /*打印输出*/ 14 | i=0; 15 | repeat 16 | { 17 | write a[i]; 18 | write sp; 19 | if(i==5) 20 | { 21 | exit; 22 | } 23 | i++; 24 | }until(i>=10); 25 | write rt; 26 | 27 | } -------------------------------------------------------------------------------- /samples/array.x0: -------------------------------------------------------------------------------- 1 | main 2 | { 3 | char sp; 4 | char rt; 5 | int i; 6 | int j; 7 | int a; 8 | int b[2][5]; 9 | sp=' '; 10 | rt='\n'; 11 | a=0; 12 | for(i=0;i<2;i=i+1) 13 | { 14 | for(j=0;j<5;j=j+1) 15 | { 16 | b[i][j]=a++; 17 | } 18 | } 19 | for(i=0;i<2;i=i+1) 20 | { 21 | for(j=0;j<5;j=j+1) 22 | { 23 | write b[i][j]; 24 | write sp; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /samples/array_double.x0: -------------------------------------------------------------------------------- 1 | main 2 | { 3 | char sp; 4 | char rt; 5 | int i; 6 | int j; 7 | int a; 8 | double b[2][5]; 9 | sp=' '; 10 | rt='\n'; 11 | a=0; 12 | for(i=0;i<2;i=i+1) 13 | { 14 | for(j=0;j<5;j=j+1) 15 | { 16 | b[i][j]=a++; 17 | } 18 | } 19 | for(i=0;i<2;i=i+1) 20 | { 21 | for(j=0;j<5;j=j+1) 22 | { 23 | write b[i][j]; 24 | write sp; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /samples/loop2.x0: -------------------------------------------------------------------------------- 1 | main 2 | { 3 | const char sp=' '; 4 | const char rt='\n'; 5 | int i; 6 | int a[10]; 7 | 8 | /*测试do while与continue*/ 9 | i=0; 10 | do{ 11 | if(odd i) 12 | { 13 | i++; 14 | continue; 15 | }else{ 16 | a[i]=i; 17 | i++; 18 | } 19 | }while(i<10); 20 | /*打印输出*/ 21 | for(i=0;i<10;i++) 22 | { 23 | write a[i]; 24 | write sp; 25 | } 26 | write rt; 27 | } -------------------------------------------------------------------------------- /samples/loop4.x0: -------------------------------------------------------------------------------- 1 | main 2 | { 3 | const char sp=' '; 4 | const char rt='\n'; 5 | int i; 6 | int j; 7 | int a[10][10]; 8 | int c; 9 | c=0; 10 | /*测试嵌套循环与break*/ 11 | for(i=0;i<10;i++) 12 | { 13 | if(i==5) 14 | { 15 | break; 16 | } 17 | for(j=0;j<10;j++) 18 | { 19 | a[i][j]=c++; 20 | if(j==6) 21 | { 22 | break; 23 | } 24 | } 25 | } 26 | /*打印输出*/ 27 | for(i=0;i<10;i++) 28 | { 29 | for(j=0;j<10;j++) 30 | { 31 | write a[i][j]; 32 | write sp; 33 | } 34 | write rt; 35 | } 36 | } -------------------------------------------------------------------------------- /samples/double.x0: -------------------------------------------------------------------------------- 1 | main 2 | { 3 | const char sp=' '; 4 | const char rt='\n'; 5 | int a; 6 | int b; 7 | double c; 8 | double d; 9 | a=1; 10 | b=3; 11 | c=2.5; 12 | d=6.3; 13 | write a; 14 | write sp; 15 | write b; 16 | write sp; 17 | write c; 18 | write sp; 19 | write d; 20 | write rt; 21 | 22 | /*整数与浮点数的互相运算*/ 23 | a=d/c; 24 | d=c/2; 25 | 26 | write a; 27 | write sp; 28 | write b; 29 | write sp; 30 | write c; 31 | write sp; 32 | write d; 33 | write rt; 34 | 35 | /*整数与浮点数的互相比较*/ 36 | if(a=100) 27 | break; 28 | } 29 | } 30 | } 31 | /*打印输出*/ 32 | 33 | for(i=0;i<100;i++) 34 | { 35 | if(a[i]==1) 36 | { 37 | write i; 38 | write sp; 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /compiler.l: -------------------------------------------------------------------------------- 1 | %{ 2 | 3 | #include "compiler.tab.h" 4 | #include "stdio.h" 5 | #include "string.h" 6 | #include "malloc.h" 7 | int line = 0; 8 | char msg[50]; 9 | int yywrap(); 10 | void yyerror(char*); 11 | %} 12 | 13 | 14 | whitespace ([ \t\n])+ 15 | ID [a-zA-Z_]([a-zA-Z_]|[0-9])* 16 | NUM ([0-9])+ 17 | 18 | %% 19 | [ \t] {;} 20 | \n {line++;} 21 | \r\n {line++;} 22 | "/*"([^\*]|(\*)*[^\*/])*(\*)*"*/" { 23 | char* c = yytext; 24 | while(*c!='\0'){ 25 | if(*c=='\n'){ 26 | line++; 27 | } 28 | c++; 29 | } 30 | } 31 | "+" {return PLUS;} 32 | "-" {return MINUS;} 33 | "*" {return TIMES;} 34 | "/" {return SLASH;} 35 | 36 | "%" {return MOD;} 37 | "^" {return XOR;} 38 | 39 | "++" {return SPLUS;} 40 | "--" {return SMINUS;} 41 | 42 | "==" {return EQL;} 43 | "!=" {return NEQ;} 44 | "<" {return LES;} 45 | "<=" {return LEQ;} 46 | ">" {return GTR;} 47 | ">=" {return GEQ;} 48 | "(" {return LPAREN;} 49 | ")" {return RPAREN;} 50 | "[" {return LBRACKETS;} 51 | "]" {return RBRACKETS;} 52 | "{" {return LBRACE;} 53 | "}" {return RBRACE;} 54 | "," {return COMMA;} 55 | ";" {return SEMICOLON;} 56 | ":" {return COLON;} 57 | "." {return PERIOD;} 58 | "=" {return BECOMES;} 59 | 60 | "odd"|"ODD" {return ODD;} 61 | "switch" {return SWITCH;} 62 | "case" {return CASE;} 63 | "default" {return DEFAULT;} 64 | "break" {return BREAK;} 65 | "continue" {return CONTINUE;} 66 | "main" {return MAIN;} 67 | "const" {return CONST;} 68 | "true" {yylval.number=1;return NUM;} 69 | "false" {yylval.number=0;return NUM;} 70 | "if" {return IF;} 71 | "else" {return ELSE;} 72 | "while" {return WHILE;} 73 | "for" {return FOR;} 74 | "do" {return DO;} 75 | "repeat" {return REPEAT;} 76 | "until" {return UNTIL;} 77 | "write" {return WRITE;} 78 | "read" {return READ;} 79 | "call" {return CALL;} 80 | "exit" {return EXIT;} 81 | "int" { 82 | yylval.type = (char *)malloc(strlen(yytext)+1); 83 | strcpy(yylval.type,yytext); 84 | return INT; 85 | } 86 | "double" { 87 | yylval.type = (char *)malloc(strlen(yytext)+1); 88 | strcpy(yylval.type,yytext); 89 | return DOUBLE; 90 | } 91 | 92 | "char" { 93 | yylval.type = (char *)malloc(strlen(yytext)+1); 94 | strcpy(yylval.type,yytext); 95 | return CHAR; 96 | } 97 | "bool" { 98 | yylval.type = (char *)malloc(strlen(yytext)+1); 99 | strcpy(yylval.type,yytext); 100 | return BOOL; 101 | } 102 | "and" {return AND;} 103 | "or" {return OR;} 104 | "not" {return NOT;} 105 | 106 | [0-9]+[.][0-9]+ { 107 | yylval.number_d=atof(yytext); 108 | return NUM_D; 109 | } 110 | 111 | '[^'\n]' { 112 | yylval.number=(int)(yytext[1]); 113 | return NUM; 114 | } 115 | 116 | "'\\n'" { 117 | yylval.number='\n'; 118 | return NUM; 119 | } 120 | 121 | "'\\t'" { 122 | yylval.number='\t'; 123 | return NUM; 124 | } 125 | 126 | {ID} { 127 | yylval.ident=(char *)malloc(strlen(yytext)+1); 128 | strcpy(yylval.ident,yytext); 129 | return ID; 130 | } 131 | 132 | {NUM} { 133 | yylval.number=atoi(yytext); 134 | return NUM; 135 | } 136 | 137 | . { 138 | sprintf(msg,"yyerror: unexpected character %s",yytext); 139 | yyerror(msg); 140 | } 141 | 142 | %% 143 | 144 | int yywrap(void) 145 | { 146 | return 1; 147 | } 148 | -------------------------------------------------------------------------------- /table.h: -------------------------------------------------------------------------------- 1 | #include "stdio.h" 2 | #include "string.h" 3 | 4 | #define TXMAX 100 5 | #define AL 20 6 | #define LEVMAX 3 7 | #define AMAX 65535 8 | #define STACKSIZE 100000 9 | 10 | int lev=0; 11 | int tx=0; 12 | int dx=0; 13 | int num; 14 | double num_d; 15 | int size; 16 | int array; 17 | struct list* array_size; 18 | int array_dim; 19 | char id[AL]; 20 | int error_count; 21 | extern int line; 22 | struct list{ 23 | int v; 24 | struct list *next; 25 | }; 26 | enum object{constant,variable,procedur}; 27 | enum type_e{int_t,char_t, double_tt, bool_t, none_t}; 28 | enum object kind; 29 | enum type_e type; 30 | 31 | void error(int); 32 | 33 | void syntax_error(char* s){ 34 | error_count++; 35 | printf("syntax error in line %d: %s\n", line+1, s); 36 | exit(1); 37 | } 38 | struct table1{ 39 | char name[AL]; 40 | enum object kind; 41 | enum type_e type; 42 | int val,adr,size,array,array_dim; 43 | double val_d; 44 | struct list* array_size; 45 | }; 46 | struct table1 table[TXMAX+1]; 47 | 48 | struct procReg1{ 49 | int dx0; 50 | int tx0; 51 | int cx0; 52 | }; 53 | struct procReg1 procReg; 54 | 55 | int array_len(struct list* head) 56 | { 57 | struct list* each = head; 58 | int len=1; 59 | if(head==NULL){ 60 | len=0; 61 | }else{ 62 | do{ 63 | len*=each->v; 64 | each = each->next; 65 | }while(each!=NULL); 66 | } 67 | return len; 68 | } 69 | int list_get_last(struct list* head) 70 | { 71 | if(head==NULL){ 72 | syntax_error("array is empty!"); 73 | return -1; 74 | } 75 | struct list* each = head; 76 | while(each->next!=NULL) 77 | each = each->next; 78 | return each->v; 79 | 80 | } 81 | int list_del_last(struct list* head) 82 | { 83 | if(head==NULL){ 84 | return 0; 85 | } 86 | struct list* each = head; 87 | struct list* befor=head; 88 | while(each->next!=NULL){ 89 | befor=each; 90 | each = each->next; 91 | } 92 | befor->next=NULL; 93 | free(each); 94 | each=NULL; 95 | return 0; 96 | 97 | } 98 | int list_get_product_after_id(struct list* head, int id) 99 | { 100 | int p=1,i=0; 101 | struct list* each = head; 102 | if(head==NULL){ 103 | return 0; 104 | } 105 | while(each!=NULL){ 106 | if(i++>id) 107 | p*=each->v; 108 | each = each->next; 109 | } 110 | return p; 111 | } 112 | int list_get_by_id(struct list* head, int id) 113 | { 114 | int i; 115 | struct list* each = head; 116 | for(i=0;inext; 123 | } 124 | if(each==NULL){ 125 | syntax_error("array index out of range!"); 126 | return -1; 127 | } 128 | return each->v; 129 | } 130 | char* list_prints(struct list* head, char *s){ 131 | struct list* each = head; 132 | strcpy(s,""); 133 | char stmp[50]=""; 134 | if(head==NULL){ 135 | sprintf(s,"%d",0); 136 | }else{ 137 | while(each!=NULL){ 138 | sprintf(stmp,"%d ",each->v); 139 | strcat(s,stmp); 140 | each = each->next; 141 | } 142 | } 143 | return s; 144 | } 145 | struct list* list_add(struct list* head, int v) 146 | { 147 | struct list* each = head; 148 | if(head==NULL){ 149 | head = (struct list*)malloc(sizeof(struct list)); 150 | head->v=v; 151 | head->next=NULL; 152 | }else{ 153 | while(each->next!=NULL) 154 | each = each->next; 155 | struct list* tmp = (struct list*)malloc(sizeof(struct list)); 156 | tmp->v=v; 157 | tmp->next=NULL; 158 | each->next=tmp; 159 | } 160 | return head; 161 | } 162 | 163 | void enter(enum object k){ 164 | tx=tx+1; 165 | strcpy(table[tx].name,id); 166 | table[tx].kind=k; 167 | switch(k) 168 | { 169 | case constant: 170 | if(type==double_tt){ 171 | table[tx].val=0; 172 | table[tx].val_d=num_d; 173 | }else{ 174 | if(num>AMAX){ 175 | error(31); 176 | num=0; 177 | } 178 | table[tx].val=num; 179 | table[tx].val_d=0; 180 | } 181 | table[tx].type=type; 182 | break; 183 | 184 | case variable: 185 | table[tx].adr=dx; 186 | table[tx].type=type; 187 | if(array){ 188 | table[tx].array=array; 189 | table[tx].array_dim=array_dim; 190 | table[tx].array_size=array_size; 191 | dx += array_len(table[tx].array_size); 192 | }else{ 193 | dx++; 194 | } 195 | break; 196 | case procedur: 197 | break; 198 | 199 | } 200 | } 201 | 202 | 203 | int position(char id[10]) 204 | { 205 | int i; 206 | //strcpy(table[0].name,id); 207 | i=tx; 208 | while(strcmp(table[i].name,id)!=0){ 209 | i--; 210 | if(i==0) 211 | break; 212 | } 213 | return i; 214 | } 215 | 216 | void printTable(int tofile) 217 | { 218 | int i; 219 | char kind[15]; 220 | char type[15]; 221 | int array_size0=0; 222 | printf("****************************************************************************************************************************************************\n"); 223 | printf("table:\n"); 224 | printf("%15s%15s%15s%15s%15s%15s%15s%15s%15s%15s\n", "name", "kind", "val", "val_d", "type", "adr", "size", "array", "array_dim", "array_size"); 225 | for(i=0;i<=tx;i++) 226 | { 227 | switch(table[i].kind) 228 | { 229 | case constant: 230 | strcpy(kind, "constant"); 231 | break; 232 | case variable: 233 | strcpy(kind, "variable"); 234 | break; 235 | case procedur: 236 | strcpy(kind, "procedur"); 237 | break; 238 | } 239 | switch(table[i].type) 240 | { 241 | case int_t: 242 | strcpy(type, "int"); 243 | break; 244 | case char_t: 245 | strcpy(type, "char"); 246 | break; 247 | case double_tt: 248 | strcpy(type, "double"); 249 | break; 250 | case bool_t: 251 | strcpy(type, "bool"); 252 | break; 253 | case none_t: 254 | strcpy(type, "none"); 255 | break; 256 | } 257 | char ss[50]; 258 | list_prints(table[i].array_size,ss); 259 | printf("%15s%15s%15d%15lf%15s%15d%15d%15d%15d%15s\n", table[i].name, kind, table[i].val, table[i].val_d, type, table[i].adr, table[i].size, table[i].array, table[i].array_dim, ss); 260 | } 261 | printf("****************************************************************************************************************************************************\n"); 262 | } -------------------------------------------------------------------------------- /code.h: -------------------------------------------------------------------------------- 1 | #include "table.h" 2 | #define CXMAX 1000 3 | #define LOOPMAX 50 4 | 5 | int cx,cx1,cx2; 6 | int err; 7 | 8 | enum fct{lit,opr,lod,sto,cal,ini,jmp,jpc,ext}; 9 | enum inloop{brk,ctn}; 10 | char *mnemonic[9]={"lit","opr","lod","sto","cal","ini","jmp","jpc", "ext"}; 11 | 12 | FILE *fa; 13 | FILE *fa1,*fa2; 14 | FILE *fin,*fout; 15 | char fname[AL]; 16 | 17 | enum listswitcher{false,true}; 18 | enum listswitcher listswitch; 19 | 20 | struct instruction{ 21 | enum fct f; 22 | int l; 23 | int a; 24 | int isd; 25 | double d; 26 | }; 27 | struct instruction code[CXMAX+1]; 28 | 29 | struct loop{ 30 | int cx; 31 | enum inloop type; 32 | int level; 33 | }; 34 | struct loop loopReg[LOOPMAX]; 35 | int loop_pos=0; 36 | int loop_level=0; 37 | 38 | int become_level=0; 39 | int pop_stack=0; 40 | int array_id=0; 41 | 42 | struct stack{ 43 | int vi; 44 | double vd; 45 | enum type_e type; 46 | }; 47 | 48 | void error(int n){ 49 | printf("***"); 50 | fputs("***",fa1); 51 | printf("error%d",n); 52 | fprintf(fa1,"error%d",n); 53 | } 54 | 55 | void code_error(char * s) 56 | { 57 | printf("%s\n", s); 58 | exit(1); 59 | } 60 | void _gen(enum fct x,int y,int z,int isd,double d) 61 | { 62 | if(cx>CXMAX) 63 | printf("program too long!"); 64 | code[cx].f=x; 65 | code[cx].l=y; 66 | code[cx].a=z; 67 | code[cx].isd=isd; 68 | code[cx].d=d; 69 | cx++; 70 | } 71 | 72 | void gen(enum fct x,int y,int z) 73 | { 74 | _gen(x,y,z,0,0.0); 75 | } 76 | 77 | void listcode( ) 78 | { 79 | int i; 80 | if(listswitch==true){ 81 | printf("****************************************************************************************************************************************************\n"); 82 | printf("pcode:\n"); 83 | printf("%15s %15s %15s %15s %15s %15s\n","id","f","l","a","isd","d"); 84 | for(i=0;i<=cx-1;i++){ 85 | printf("%15d %15s %15d %15d %15d %15lf\n",i,mnemonic[(int)code[i].f],code[i].l,code[i].a,code[i].isd,code[i].d); 86 | //fprintf(fa,"%2d %5s %3d %5d\n",i,mnemonic[(int)code[i].f],code[i].l,code[i].a); 87 | } 88 | printf("****************************************************************************************************************************************************\n"); 89 | } 90 | } 91 | 92 | 93 | int base(int l,int b,struct stack s[STACKSIZE]) 94 | { 95 | int b1; 96 | b1=b; 97 | while(l>0){ 98 | b1=s[b1].vi; 99 | l=l-1; 100 | } 101 | return b1; 102 | } 103 | 104 | void interpret() 105 | { 106 | int p=0; 107 | int b=0; 108 | int t=0; 109 | struct instruction i; 110 | /*int s[STACKSIZE];*/ 111 | struct stack s[STACKSIZE]; 112 | printf("********Start X0*********\n"); 113 | //fprintf(fa1,"********Start PL/0*********\n"); 114 | s[0].vi=0;s[0].vd=0.0;s[0].type=int_t; 115 | s[1].vi=0;s[1].vd=0.0;s[1].type=int_t; 116 | s[2].vi=0;s[2].vd=0.0;s[2].type=int_t; 117 | s[3].vi=0;s[3].vd=0.0;s[3].type=int_t; 118 | int ti=tx; 119 | while(ti>=0){ 120 | if(table[ti].kind==variable){ 121 | if(table[ti].array){ 122 | int len = array_len(table[tx].array_size); 123 | int tj; 124 | if(table[ti].type==double_tt){ 125 | for(tj=table[ti].adr;tj<(table[ti].adr+len);tj++){ 126 | s[tj].type=double_tt; 127 | } 128 | 129 | }else{ 130 | for(tj=table[ti].adr;tj<(table[ti].adr+len);tj++){ 131 | s[tj].type=int_t; 132 | } 133 | } 134 | 135 | }else{ 136 | if(table[ti].type==double_tt){ 137 | s[table[ti].adr].type=double_tt; 138 | }else{ 139 | s[table[ti].adr].type=int_t; 140 | } 141 | } 142 | } 143 | ti--; 144 | } 145 | do{ 146 | i=code[p]; 147 | p=p+1; 148 | switch(i.f){ 149 | case lit: 150 | t=t+1; 151 | if(i.isd){ 152 | s[t].type=double_tt; 153 | s[t].vd=i.d; 154 | }else{ 155 | s[t].type=int_t; 156 | s[t].vi=i.a; 157 | } 158 | break; 159 | case opr: 160 | switch(i.a){ 161 | case 0: 162 | p=0; 163 | break; 164 | case 1: 165 | if(i.isd){ 166 | s[t].type=double_tt; 167 | s[t].vd=-s[t].vd; 168 | }else{ 169 | s[t].type=int_t; 170 | s[t].vi=-s[t].vi; 171 | } 172 | break; 173 | case 2: 174 | t=t-1; 175 | if(s[t].type==double_tt&&s[t+1].type==double_tt){ 176 | s[t].type=double_tt; 177 | s[t].vd=s[t].vd+s[t+1].vd; 178 | }else if(s[t].type==double_tt&&s[t+1].type==int_t){ 179 | s[t].type=double_tt; 180 | s[t].vd=s[t].vd+s[t+1].vi; 181 | }else if(s[t].type==int_t&&s[t+1].type==double_tt){ 182 | s[t].type=double_tt; 183 | s[t].vd=s[t].vi+s[t+1].vd; 184 | }else if(s[t].type==int_t&&s[t+1].type==int_t){ 185 | s[t].type=int_t; 186 | s[t].vi=s[t].vi+s[t+1].vi; 187 | } 188 | break; 189 | case 3: 190 | t=t-1; 191 | if(s[t].type==double_tt&&s[t+1].type==double_tt){ 192 | s[t].type=double_tt; 193 | s[t].vd=s[t].vd-s[t+1].vd; 194 | }else if(s[t].type==double_tt&&s[t+1].type==int_t){ 195 | s[t].type=double_tt; 196 | s[t].vd=s[t].vd-s[t+1].vi; 197 | }else if(s[t].type==int_t&&s[t+1].type==double_tt){ 198 | s[t].type=double_tt; 199 | s[t].vd=s[t].vi-s[t+1].vd; 200 | }else if(s[t].type==int_t&&s[t+1].type==int_t){ 201 | s[t].type=int_t; 202 | s[t].vi=s[t].vi-s[t+1].vi; 203 | } 204 | break; 205 | case 4: 206 | t=t-1; 207 | if(s[t].type==double_tt&&s[t+1].type==double_tt){ 208 | s[t].type=double_tt; 209 | s[t].vd=s[t].vd*s[t+1].vd; 210 | }else if(s[t].type==double_tt&&s[t+1].type==int_t){ 211 | s[t].type=double_tt; 212 | s[t].vd=s[t].vd*s[t+1].vi; 213 | }else if(s[t].type==int_t&&s[t+1].type==double_tt){ 214 | s[t].type=double_tt; 215 | s[t].vd=s[t].vi*s[t+1].vd; 216 | }else if(s[t].type==int_t&&s[t+1].type==int_t){ 217 | s[t].type=int_t; 218 | s[t].vi=s[t].vi*s[t+1].vi; 219 | } 220 | break; 221 | case 5: 222 | t=t-1; 223 | if(s[t].type==double_tt&&s[t+1].type==double_tt){ 224 | s[t].type=double_tt; 225 | s[t].vd=s[t].vd/s[t+1].vd; 226 | }else if(s[t].type==double_tt&&s[t+1].type==int_t){ 227 | s[t].type=double_tt; 228 | s[t].vd=s[t].vd/s[t+1].vi; 229 | }else if(s[t].type==int_t&&s[t+1].type==double_tt){ 230 | s[t].type=double_tt; 231 | s[t].vd=s[t].vi/s[t+1].vd; 232 | }else if(s[t].type==int_t&&s[t+1].type==int_t){ 233 | s[t].type=int_t; 234 | s[t].vi=s[t].vi/s[t+1].vi; 235 | } 236 | break; 237 | case 6: 238 | if(s[t].type==double_tt){ 239 | code_error("top of the stack is a double so that we do not know if it is odd."); 240 | } 241 | if((s[t].vi)%2==0) 242 | s[t].vi=0; 243 | else 244 | s[t].vi=1; 245 | break; 246 | case 8: 247 | t=t-1; 248 | if(s[t].type==double_tt||s[t+1].type==double_tt){ 249 | code_error("tops of the stack are doubles so that we do not know if one is equals to another."); 250 | } 251 | if(s[t].vi==s[t+1].vi) 252 | s[t].vi=1; 253 | else 254 | s[t].vi=0; 255 | break; 256 | case 9: 257 | t=t-1; 258 | if(s[t].type==double_tt||s[t+1].type==double_tt){ 259 | code_error("tops of the stack are doubles so that we do not know if one is equals to another."); 260 | } 261 | if(s[t].vi!=s[t+1].vi) 262 | s[t].vi=1; 263 | else 264 | s[t].vi=0; 265 | break; 266 | case 10: 267 | t--; 268 | if(s[t].type==double_tt&&s[t+1].type==double_tt){ 269 | s[t].vi=s[t].vd=s[t+1].vd; 283 | }else if(s[t].type==double_tt&&s[t+1].type==int_t){ 284 | s[t].vi=s[t].vd>=s[t+1].vi; 285 | }else if(s[t].type==int_t&&s[t+1].type==double_tt){ 286 | s[t].vi=s[t].vi>=s[t+1].vd; 287 | }else if(s[t].type==int_t&&s[t+1].type==int_t){ 288 | s[t].vi=s[t].vi>=s[t+1].vi; 289 | } 290 | s[t].type=int_t; 291 | break; 292 | case 12: 293 | t=t-1; 294 | if(s[t].type==double_tt&&s[t+1].type==double_tt){ 295 | s[t].vi=s[t].vd>s[t+1].vd; 296 | }else if(s[t].type==double_tt&&s[t+1].type==int_t){ 297 | s[t].vi=s[t].vd>s[t+1].vi; 298 | }else if(s[t].type==int_t&&s[t+1].type==double_tt){ 299 | s[t].vi=s[t].vi>s[t+1].vd; 300 | }else if(s[t].type==int_t&&s[t+1].type==int_t){ 301 | s[t].vi=s[t].vi>s[t+1].vi; 302 | } 303 | s[t].type=int_t; 304 | break; 305 | case 13: 306 | t=t-1; 307 | if(s[t].type==double_tt&&s[t+1].type==double_tt){ 308 | s[t].vi=s[t].vd<=s[t+1].vd; 309 | }else if(s[t].type==double_tt&&s[t+1].type==int_t){ 310 | s[t].vi=s[t].vd<=s[t+1].vi; 311 | }else if(s[t].type==int_t&&s[t+1].type==double_tt){ 312 | s[t].vi=s[t].vi<=s[t+1].vd; 313 | }else if(s[t].type==int_t&&s[t+1].type==int_t){ 314 | s[t].vi=s[t].vi<=s[t+1].vi; 315 | } 316 | s[t].type=int_t; 317 | break; 318 | case 14: 319 | if(s[t].type==double_tt){ 320 | printf("%lf",s[t].vd); 321 | fprintf(fa2,"%lf",s[t].vd); 322 | }else{ 323 | printf("%d",s[t].vi); 324 | fprintf(fa2,"%d",s[t].vi); 325 | } 326 | t=t-1; 327 | break; 328 | case 15: 329 | printf("\n"); 330 | fprintf(fa2,"\n"); 331 | break; 332 | case 16: 333 | t=t+1; 334 | s[t].type=int_t; 335 | printf("?"); 336 | fprintf(fa2,"?"); 337 | if(i.isd){ 338 | scanf("%lf",&s[t].vd); 339 | fprintf(fa2,"%lf",s[t].vd); 340 | }else{ 341 | scanf("%d",&s[t].vi); 342 | fprintf(fa2,"%d",s[t].vi); 343 | } 344 | break; 345 | case 17: /*写字符*/ 346 | if(s[t].type==double_tt){ 347 | code_error("top of the stack is a double so that we cannot write a charater."); 348 | } 349 | printf("%c",s[t].vi); 350 | fprintf(fa2,"%c",s[t].vi); 351 | t=t-1; 352 | break; 353 | case 18: /*写栈顶值所在的数据单元int*/ 354 | if(s[t].type==double_tt){ 355 | code_error("top of the stack is a double so that we cannot write from a double address."); 356 | } 357 | if(s[s[t].vi].type==double_tt){ 358 | printf("%lf",s[s[t].vi].vd); 359 | fprintf(fa2,"%lf",s[s[t].vi].vd); 360 | }else{ 361 | printf("%d",s[s[t].vi].vi); 362 | fprintf(fa2,"%d",s[s[t].vi].vi); 363 | } 364 | t=t-1; 365 | break; 366 | case 19: /*写栈顶值所在的数据单元char*/ 367 | if(s[t].type==double_tt){ 368 | code_error("top of the stack is a double so that we cannot write a charater to an address."); 369 | } 370 | if(s[s[t].vi].type==double_tt){ 371 | code_error("adr of the stack is a double so that we cannot write a charater."); 372 | } 373 | printf("%c",s[s[t].vi].vi); 374 | fprintf(fa2,"%c",s[s[t].vi].vi); 375 | t=t-1; 376 | break; 377 | case 20: /*MOD*/ 378 | t=t-1; 379 | if(s[t].type==double_tt||s[t+1].type==double_tt){ 380 | code_error("tops of the stack are doubles so that one cannot mod another."); 381 | } 382 | s[t].vi=s[t].vi%s[t+1].vi; 383 | break; 384 | case 21: /*xor*/ 385 | t=t-1; 386 | if(s[t].type==double_tt||s[t+1].type==double_tt){ 387 | code_error("tops of the stack are doubles so that one cannot xor another."); 388 | } 389 | s[t].vi=s[t].vi^s[t+1].vi; 390 | break; 391 | case 22: /*and*/ 392 | t=t-1; 393 | if(s[t].type==double_tt||s[t+1].type==double_tt){ 394 | code_error("tops of the stack are doubles so that one cannot and another."); 395 | } 396 | s[t].vi=s[t].vi&&s[t+1].vi; 397 | break; 398 | case 23: /*or*/ 399 | t=t-1; 400 | if(s[t].type==double_tt||s[t+1].type==double_tt){ 401 | code_error("tops of the stack are doubles so that one cannot or another."); 402 | } 403 | s[t].vi=s[t].vi||s[t+1].vi; 404 | break; 405 | case 24: /*not*/ 406 | if(s[t].type==double_tt){ 407 | code_error("top of the stack is double so that one cannot do |not|."); 408 | } 409 | s[t].vi=!s[t].vi; 410 | break; 411 | case 25: /*写bool*/ 412 | if(s[t].type==double_tt){ 413 | code_error("tops of the stack are doubles so that one cannot be writen."); 414 | } 415 | printf("%s",s[t].vi==0?"false":"true"); 416 | fprintf(fa2,"%s",s[t].vi==0?"false":"true"); 417 | t=t-1; 418 | break; 419 | case 26: /*pop stack*/ 420 | t=t-1; 421 | break; 422 | } 423 | break; 424 | case lod: 425 | if(i.a==0)/*lod栈顶值所在的数据单元*/ 426 | { 427 | if(s[t].type==double_tt){ 428 | code_error("top of the stack is a double so that we cannot lod from a double address."); 429 | } 430 | if(s[t].vi>=table[array_id].adr+array_len(table[array_id].array_size)){ 431 | /*printf("%d %d %d\n", table[array_id].adr, array_len(table[array_id].array_size), s[t].vi);*/ 432 | code_error("\narray index out of range."); 433 | } 434 | if(s[base(i.l,b,s)+s[t].vi].type==double_tt){ 435 | s[t].type=double_tt; 436 | s[t].vd=s[base(i.l,b,s)+s[t].vi].vd; 437 | }else{ 438 | s[t].type=int_t; 439 | s[t].vi=s[base(i.l,b,s)+s[t].vi].vi; 440 | } 441 | } 442 | else 443 | { 444 | t=t+1; 445 | if(s[base(i.l,b,s)+i.a].type==double_tt){ 446 | s[t].type=double_tt; 447 | s[t].vd=s[base(i.l,b,s)+i.a].vd; 448 | }else{ 449 | s[t].type=int_t; 450 | s[t].vi=s[base(i.l,b,s)+i.a].vi; 451 | } 452 | } 453 | break; 454 | case sto: 455 | if(i.a==0)/*sto到次栈顶值所在的数据单元,数据源为栈顶*/ 456 | { 457 | if(s[t-1].type==double_tt){ 458 | code_error("top of the stack is a double so that we cannot lod from a double address."); 459 | } 460 | if(s[t-1].vi>=table[array_id].adr+array_len(table[array_id].array_size)){ 461 | /*printf("%d %d %d\n", table[array_id].adr, array_len(table[array_id].array_size), s[t-1].vi);*/ 462 | code_error("\narray index out of range."); 463 | } 464 | if(s[base(i.l,b,s)+s[t-1].vi].type==double_tt){ 465 | if(s[t].type==double_tt){ 466 | s[base(i.l,b,s)+s[t-1].vi].vd=s[t].vd; 467 | s[t-1].type=s[base(i.l,b,s)+s[t-1].vi].type; 468 | s[t-1].vd=s[t].vd; 469 | }else{ 470 | s[base(i.l,b,s)+s[t-1].vi].vd=s[t].vi; 471 | s[t-1].type=s[base(i.l,b,s)+s[t-1].vi].type; 472 | s[t-1].vd=s[t].vi; 473 | } 474 | }else{ 475 | if(s[t].type==double_tt){ 476 | s[base(i.l,b,s)+s[t-1].vi].vi=(int)s[t].vd; 477 | s[t-1].type=s[base(i.l,b,s)+s[t-1].vi].type; 478 | s[t-1].vi=(int)s[t].vd; 479 | }else{ 480 | s[base(i.l,b,s)+s[t-1].vi].vi=s[t].vi; 481 | s[t-1].type=s[base(i.l,b,s)+s[t-1].vi].type; 482 | s[t-1].vi=s[t].vi; 483 | } 484 | } 485 | t=t-1; 486 | } 487 | else 488 | { 489 | if(s[base(i.l,b,s)+i.a].type==double_tt){ 490 | if(s[t].type==double_tt){ 491 | s[base(i.l,b,s)+i.a].vd=s[t].vd; 492 | }else{ 493 | s[base(i.l,b,s)+i.a].vd=s[t].vi; 494 | } 495 | }else{ 496 | if(s[t].type==double_tt){ 497 | s[base(i.l,b,s)+i.a].vi=(int)s[t].vd; 498 | }else{ 499 | s[base(i.l,b,s)+i.a].vi=s[t].vi; 500 | } 501 | } 502 | t=t-1; 503 | } 504 | break; 505 | case cal: 506 | /* 507 | s[t+1]=base(i.l,b,s); 508 | s[t+2]=b; 509 | s[t+3]=p; 510 | b=t+1; 511 | p=i.a; 512 | */ 513 | break; 514 | case ini: 515 | t=t+i.a; 516 | break; 517 | case jmp: 518 | p=i.a; 519 | break; 520 | case jpc: 521 | if(s[t].type==double_tt){ 522 | code_error("top of the stack is a double so that we do not know if it is equals to zero."); 523 | } 524 | if(s[t].vi==0) 525 | p=i.a; 526 | t=t-1; 527 | break; 528 | case ext: /* exit */ 529 | p=0; 530 | break; 531 | } 532 | }while(p!=0); 533 | printf("\n********End X0***********\n"); 534 | fclose(fa2); 535 | } -------------------------------------------------------------------------------- /compiler.y: -------------------------------------------------------------------------------- 1 | %token ID 2 | %token NUM NUM_C 3 | %token NUM_D 4 | %token INT CHAR DOUBLE BOOL CONST 5 | %token PLUS MINUS TIMES SLASH EQL NEQ LES LEQ GTR GEQ MOD XOR ODD SPLUS SMINUS UMINUS AND OR NOT 6 | %token LPAREN RPAREN LBRACKETS RBRACKETS LBRACE RBRACE 7 | %token COMMA SEMICOLON PERIOD BECOMES COLON 8 | %token MAIN IF ELSE WHILE WRITE READ DO CALL SWITCH CASE DEFAULT BREAK CONTINUE FOR REPEAT UNTIL EXIT 9 | 10 | %type var 11 | %type get_code_addr 12 | %type else_stat 13 | %type array_size 14 | %type array_loc 15 | %type type 16 | %type statement 17 | %type loop_stat_list 18 | 19 | %right ODD 20 | %left OR 21 | %left AND 22 | %left XOR 23 | %left PLUS MINUS 24 | %left TIMES SLASH MOD 25 | %left SPLUS SMINUS UMINUS 26 | %right NOT 27 | %nonassoc ELSE 28 | 29 | 30 | %{ 31 | 32 | #include 33 | #include 34 | #include 35 | #include "string.h" 36 | #include "code.h" 37 | #include "malloc.h" 38 | void yyerror(char*); 39 | void syntax_error(char* s); 40 | int yylex(void); 41 | FILE *yout; 42 | FILE *yyin; 43 | struct list* array_ids; 44 | %} 45 | 46 | %union{ 47 | char *ident; 48 | int number; 49 | double number_d; 50 | void* ptr; 51 | char *type; 52 | struct databus* db; 53 | } 54 | 55 | %% 56 | program: 57 | MAIN LBRACE { 58 | dx=3; 59 | procReg.tx0=tx; 60 | table[tx].adr=cx; 61 | gen(jmp,0,1); 62 | } 63 | const_list {} 64 | declaration_list { 65 | code[table[procReg.tx0].adr].a=cx; 66 | strcpy(table[procReg.tx0].name,"main"); 67 | table[procReg.tx0].kind=procedur; 68 | table[procReg.tx0].type=none_t; 69 | table[procReg.tx0].adr=cx; 70 | table[procReg.tx0].size=dx; 71 | procReg.cx0=cx; 72 | gen(ini,0,dx); 73 | } 74 | statement_list { 75 | gen(opr,0,0); 76 | } 77 | RBRACE {} 78 | ; 79 | 80 | const_list: 81 | const_list const_dec {} 82 | | 83 | ; 84 | 85 | const_dec: 86 | CONST INT ID BECOMES NUM SEMICOLON { 87 | type=int_t; 88 | strcpy(id,$3); 89 | num=$5; 90 | enter(constant); 91 | } 92 | |CONST DOUBLE ID BECOMES NUM_D SEMICOLON { 93 | type=double_tt; 94 | strcpy(id,$3); 95 | num_d=$5; 96 | enter(constant); 97 | } 98 | |CONST CHAR ID BECOMES NUM SEMICOLON { 99 | type=char_t; 100 | strcpy(id,$3); 101 | num=$5; 102 | enter(constant); 103 | } 104 | |CONST BOOL ID BECOMES NUM SEMICOLON { 105 | type=bool_t; 106 | strcpy(id,$3); 107 | num=$5; 108 | enter(constant); 109 | } 110 | ; 111 | 112 | declaration_list: 113 | declaration_list declaration_stat { 114 | procReg.dx0=dx; 115 | } 116 | | {} 117 | ; 118 | 119 | declaration_stat: 120 | type ID array_size SEMICOLON { 121 | if(strcmp($1,"int")==0){ 122 | type=int_t; 123 | } else if(strcmp($1,"char")==0){ 124 | type=char_t; 125 | }else if(strcmp($1,"bool")==0){ 126 | type=bool_t; 127 | }else if(strcmp($1,"double")==0){ 128 | type=double_tt; 129 | } else{ 130 | type=none_t; 131 | } 132 | 133 | if(array==1){ 134 | strcpy(id,$2); 135 | enter(variable); 136 | }else 137 | { 138 | strcpy(id,$2); 139 | enter(variable); 140 | } 141 | type=none_t; 142 | } 143 | ; 144 | 145 | array_size: 146 | array_size LBRACKETS NUM RBRACKETS { 147 | array=1; 148 | array_dim++; 149 | array_size=list_add(array_size,$3); 150 | } 151 | | { 152 | array=0; 153 | array_dim=0; 154 | array_size=NULL; 155 | } 156 | ; 157 | type: 158 | INT {$$=$1;} 159 | |DOUBLE {$$=$1;} 160 | |CHAR {$$=$1;} 161 | |BOOL {$$=$1;} 162 | ; 163 | 164 | var: 165 | ID { 166 | int i = position ($1); 167 | if(i<=0){ 168 | char s[50]; 169 | sprintf(s,"variable %s undefined!", $1); 170 | syntax_error(s); 171 | } 172 | $$ = i; 173 | if(table[i].array){ 174 | array_ids = list_add(array_ids,i); 175 | array_id = i; 176 | } 177 | } 178 | /* 179 | | ID LBRACKETS expression RBRACKETS { 180 | $$ = position ($1); 181 | } 182 | */ 183 | ; 184 | 185 | statement_list: 186 | statement_list statement {} 187 | |statement {} 188 | ; 189 | 190 | statement: 191 | if_stat {} 192 | |while_stat {} 193 | |read_stat {} 194 | |write_stat {} 195 | |compound_stat {} 196 | |expression_stat {} 197 | /*|switch_case_stat {}*/ 198 | |for_stat {} 199 | |do_while_stat {} 200 | |repeat_until_stat {} 201 | |exit_stat {} 202 | |break_stat {} 203 | |continue_stat {} 204 | ; 205 | 206 | exit_stat: 207 | EXIT SEMICOLON {gen(ext,0,0);} 208 | ; 209 | 210 | break_stat: 211 | BREAK SEMICOLON { 212 | loop_pos++; 213 | if(loop_pos>=LOOPMAX){ 214 | syntax_error("too many breaks or continues."); 215 | } 216 | loopReg[loop_pos].cx=cx; 217 | loopReg[loop_pos].type=brk; 218 | loopReg[loop_pos].level=loop_level; 219 | gen(jmp,0,0); 220 | } 221 | ; 222 | 223 | continue_stat: 224 | CONTINUE SEMICOLON { 225 | loop_pos++; 226 | if(loop_pos>=LOOPMAX){ 227 | syntax_error("too many breaks or continues."); 228 | } 229 | loopReg[loop_pos].cx=cx; 230 | loopReg[loop_pos].type=ctn; 231 | loopReg[loop_pos].level=loop_level; 232 | gen(jmp,0,0); 233 | } 234 | ; 235 | 236 | for_stat: 237 | FOR LPAREN for_exp1 SEMICOLON get_code_addr for_exp2 SEMICOLON get_code_addr { 238 | if(loop_level==0){ 239 | loop_pos=-1; 240 | } 241 | loop_level++; 242 | gen(jpc,0,0); 243 | gen(jmp,0,0); 244 | } 245 | for_exp3 { 246 | gen(jmp,0,$5); 247 | } 248 | RPAREN get_code_addr loop_stat_list { 249 | gen(jmp,0,$8+2); 250 | code[$8].a=cx; 251 | code[$8+1].a=$13; 252 | int i; 253 | for(i=0;i<=loop_pos;i++) 254 | { 255 | if(loopReg[i].level==loop_level){ 256 | switch(loopReg[i].type){ 257 | case brk: 258 | code[loopReg[i].cx].a=cx; 259 | break; 260 | case ctn: 261 | code[loopReg[i].cx].a=$8+2; 262 | break; 263 | } 264 | } 265 | } 266 | loop_level--; 267 | 268 | } 269 | ; 270 | 271 | for_exp1: 272 | expression {} 273 | | {} 274 | ; 275 | 276 | for_exp2: 277 | simple_expr {} 278 | | {} 279 | ; 280 | 281 | for_exp3: 282 | expression {} 283 | | {} 284 | ; 285 | 286 | loop_stat_list: 287 | statement {} 288 | ; 289 | 290 | do_while_stat: 291 | DO get_code_addr { 292 | if(loop_level==0) 293 | { 294 | loop_pos=-1; 295 | } 296 | loop_level++; 297 | } 298 | do_while_stat_list WHILE get_code_addr LPAREN simple_expr RPAREN SEMICOLON get_code_addr { 299 | gen(jpc,0,$11+2); 300 | gen(jmp,0,$2); 301 | 302 | int i; 303 | for(i=0;i<=loop_pos;i++) 304 | { 305 | if(loopReg[i].level==loop_level){ 306 | switch(loopReg[i].type){ 307 | case brk: 308 | code[loopReg[i].cx].a=cx; 309 | break; 310 | case ctn: 311 | code[loopReg[i].cx].a=$6; 312 | break; 313 | } 314 | } 315 | } 316 | loop_level--; 317 | } 318 | ; 319 | 320 | do_while_stat_list: 321 | statement {} 322 | ; 323 | 324 | repeat_until_stat: 325 | REPEAT get_code_addr { 326 | if(loop_level==0) 327 | { 328 | loop_pos=-1; 329 | } 330 | loop_level++; 331 | } 332 | repeat_until_stat_list UNTIL get_code_addr LPAREN simple_expr RPAREN SEMICOLON { 333 | gen(jpc,0,$2); 334 | 335 | int i; 336 | for(i=0;i<=loop_pos;i++) 337 | { 338 | if(loopReg[i].level==loop_level){ 339 | switch(loopReg[i].type){ 340 | case brk: 341 | code[loopReg[i].cx].a=cx; 342 | break; 343 | case ctn: 344 | code[loopReg[i].cx].a=$6; 345 | break; 346 | } 347 | } 348 | } 349 | loop_level--; 350 | 351 | } 352 | ; 353 | 354 | repeat_until_stat_list: 355 | statement {} 356 | ; 357 | /*switch_case_stat: 358 | SWITCH LPAREN expression RPAREN LBRACE case_list default_stat RBRACE {} 359 | ; 360 | 361 | case_list: 362 | case_list CASE expression COLON statement_list {} 363 | ; 364 | 365 | default_stat: 366 | DEFAULT COLON statement_list {} 367 | ; 368 | */ 369 | if_stat: 370 | IF LPAREN expression RPAREN get_code_addr { 371 | gen(jpc, 0, 0); 372 | } 373 | statement else_stat { 374 | code[$5].a = $8; 375 | } 376 | ; 377 | 378 | else_stat: 379 | ELSE get_code_addr { 380 | gen(jmp,0,0); 381 | } 382 | statement { 383 | $$=$2+1; 384 | code[$2].a=cx; 385 | } 386 | | { 387 | $$ = cx; 388 | } 389 | ; 390 | 391 | while_stat: 392 | WHILE get_code_addr { 393 | if(loop_level==0) 394 | { 395 | loop_pos=-1; 396 | } 397 | loop_level++; 398 | } 399 | LPAREN expression RPAREN get_code_addr { 400 | gen(jpc, 0 , 0); 401 | } 402 | statement { 403 | gen(jmp, 0, $2); 404 | code[$7].a = cx; 405 | 406 | int i; 407 | for(i=0;i<=loop_pos;i++) 408 | { 409 | if(loopReg[i].level==loop_level){ 410 | switch(loopReg[i].type){ 411 | case brk: 412 | code[loopReg[i].cx].a=cx; 413 | break; 414 | case ctn: 415 | code[loopReg[i].cx].a=$2; 416 | break; 417 | } 418 | } 419 | } 420 | loop_level--; 421 | } 422 | ; 423 | 424 | write_stat: 425 | WRITE expression SEMICOLON { 426 | gen(opr,0,14); 427 | } 428 | |WRITE var SEMICOLON { 429 | if(table[$2].kind==constant){ 430 | if(table[$2].type==double_tt){ 431 | _gen(lit,0,0,1,table[$2].val_d); 432 | }else{ 433 | gen(lit,0,table[$2].val); 434 | } 435 | }else if(table[$2].kind==variable){ 436 | gen(lod,0,table[$2].adr); 437 | } 438 | if(table[$2].type==char_t) 439 | gen(opr,0,17); 440 | else if(table[$2].type==int_t) 441 | gen(opr,0,14); 442 | else if(table[$2].type==bool_t) 443 | gen(opr,0,25); 444 | else if(table[$2].type==double_tt) 445 | gen(opr,0,14); 446 | else 447 | error(0); 448 | } 449 | ; 450 | 451 | array_loc: 452 | array_loc LBRACKETS expression RBRACKETS { 453 | int id=list_get_last(array_ids); 454 | int dim_id=$1; 455 | $$=dim_id+1; 456 | if(dim_id+1>table[id].array_dim){ 457 | char s[50]; 458 | sprintf(s,"dimension of array %s is %d, gived %d.", table[id].name, table[id].array_dim, dim_id); 459 | syntax_error(s); 460 | } 461 | int p=list_get_product_after_id(table[id].array_size, dim_id); 462 | gen(lit,0,p); 463 | gen(opr,0,4); 464 | if(dim_id>=1){ 465 | gen(opr,0,2); 466 | } 467 | 468 | } 469 | | {$$=0;} 470 | ; 471 | 472 | read_stat: 473 | READ var array_loc SEMICOLON { 474 | if(table[$2].kind==constant){ 475 | syntax_error("constant cannot be read."); 476 | }else{ 477 | if($3>=1){ 478 | gen(lit,0,table[$2].adr); 479 | gen(opr,0,2); 480 | if(table[$2].type==double_tt){ 481 | _gen(opr,0,16,1,0.0); 482 | }else{ 483 | gen(opr,0,16); 484 | } 485 | gen(sto,0,0); 486 | }else{ 487 | if(table[$2].type==double_tt){ 488 | _gen(opr,0,16,1,0.0); 489 | }else{ 490 | gen(opr,0,16); 491 | } 492 | gen(sto,0,table[$2].adr); 493 | } 494 | } 495 | } 496 | ; 497 | 498 | compound_stat: 499 | LBRACE statement_list RBRACE {} 500 | ; 501 | 502 | expression_stat: 503 | expression SEMICOLON {} 504 | | SEMICOLON {} 505 | ; 506 | 507 | expression: 508 | var array_loc { 509 | if(table[$1].kind==constant){ 510 | syntax_error("constant cannot be writen."); 511 | }else{ 512 | if($2>=1){ 513 | gen(lit,0,table[$1].adr); 514 | gen(opr,0,2); 515 | } 516 | } 517 | } 518 | BECOMES expression { 519 | if($2>=1){ 520 | gen(sto,0,0); 521 | }else{ 522 | gen(sto,0,table[$1].adr); 523 | gen(lod,0,table[$1].adr); 524 | } 525 | } 526 | | simple_expr {} 527 | ; 528 | 529 | simple_expr: 530 | additive_expr {} 531 | | additive_expr GTR additive_expr { 532 | gen(opr,0,12); 533 | } 534 | | additive_expr LES additive_expr { 535 | gen(opr,0,10); 536 | } 537 | | additive_expr GEQ additive_expr { 538 | gen(opr,0,11); 539 | } 540 | | additive_expr LEQ additive_expr { 541 | gen(opr,0,13); 542 | } 543 | | additive_expr EQL additive_expr { 544 | gen(opr,0,8); 545 | } 546 | | additive_expr NEQ additive_expr { 547 | gen(opr,0,9); 548 | } 549 | | additive_expr AND additive_expr { 550 | gen(opr,0,22); 551 | } 552 | | additive_expr OR additive_expr { 553 | gen(opr,0,23); 554 | } 555 | |NOT additive_expr { 556 | gen(opr,0,24); 557 | } 558 | ; 559 | 560 | /* 561 | condition: 562 | additive_expr GTR additive_expr { 563 | gen(opr,0,12); 564 | } 565 | | additive_expr LES additive_expr { 566 | gen(opr,0,10); 567 | } 568 | | additive_expr GEQ additive_expr { 569 | gen(opr,0,11); 570 | } 571 | | additive_expr LEQ additive_expr { 572 | gen(opr,0,13); 573 | } 574 | | additive_expr EQL additive_expr { 575 | gen(opr,0,8); 576 | } 577 | | additive_expr NEQ additive_expr { 578 | gen(opr,0,9); 579 | } 580 | ; 581 | */ 582 | 583 | additive_expr: 584 | term {} 585 | |additive_expr PLUS term { 586 | gen(opr,0,2); 587 | } 588 | |additive_expr MINUS term { 589 | gen(opr,0,3); 590 | } 591 | ; 592 | 593 | term: 594 | factor { 595 | 596 | } 597 | |term TIMES factor { 598 | gen(opr,0,4); 599 | } 600 | |term SLASH factor { 601 | gen(opr,0,5); 602 | } 603 | |term MOD factor { 604 | gen(opr,0,20); 605 | } 606 | |term XOR factor { 607 | gen(opr,0,21); 608 | } 609 | |ODD factor { 610 | gen(opr,0,6); 611 | } 612 | ; 613 | 614 | factor: 615 | LPAREN expression RPAREN {} 616 | |var array_loc { 617 | switch(table[$1].kind){ 618 | case constant: 619 | if($2>=1){ 620 | syntax_error("constant have no index."); 621 | } 622 | if(table[$1].type==double_tt){ 623 | _gen(lit,0,0,1,table[$1].val_d); 624 | }else{ 625 | gen(lit,0,table[$1].val); 626 | } 627 | break; 628 | case variable: 629 | if($2>=1){ 630 | if(!table[$1].array){ 631 | char s[50]; 632 | sprintf(s,"variable %s is not an array.", table[$1].name); 633 | syntax_error(s); 634 | } 635 | gen(lit,0,table[$1].adr); 636 | gen(opr,0,2); 637 | gen(lod,0,0); 638 | list_del_last(array_ids); 639 | }else{ 640 | gen(lod,0,table[$1].adr); 641 | } 642 | break; 643 | case procedur: 644 | syntax_error("procedur is not supported yet."); 645 | break; 646 | } 647 | } 648 | |var SPLUS { 649 | if(table[$1].array==0){ 650 | gen(lod,0,table[$1].adr); 651 | gen(lod,0,table[$1].adr); 652 | gen(lit,0,1); 653 | gen(opr,0,2); 654 | gen(sto,0,table[$1].adr); 655 | }else{ 656 | char s[50]; 657 | sprintf(s,"%s is an array, not a simple variable.", table[$1].name); 658 | syntax_error(s); 659 | } 660 | } 661 | |var SMINUS { 662 | if(table[$1].array==0){ 663 | gen(lod,0,table[$1].adr); 664 | gen(lod,0,table[$1].adr); 665 | gen(lit,0,1); 666 | gen(opr,0,3); 667 | gen(sto,0,table[$1].adr); 668 | }else{ 669 | char s[50]; 670 | sprintf(s,"%s is an array, not a simple variable.", table[$1].name); 671 | syntax_error(s); 672 | } 673 | } 674 | |SPLUS var { 675 | if(table[$2].array==0){ 676 | gen(lod,0,table[$2].adr); 677 | gen(lit,0,1); 678 | gen(opr,0,2); 679 | gen(sto,0,table[$2].adr); 680 | gen(lod,0,table[$2].adr); 681 | }else{ 682 | char s[50]; 683 | sprintf(s,"%s is an array, not a simple variable.", table[$2].name); 684 | syntax_error(s); 685 | } 686 | } 687 | |SMINUS var { 688 | if(table[$2].array==0){ 689 | gen(lod,0,table[$2].adr); 690 | gen(lit,0,1); 691 | gen(opr,0,3); 692 | gen(sto,0,table[$2].adr); 693 | gen(lod,0,table[$2].adr); 694 | }else{ 695 | char s[50]; 696 | sprintf(s,"%s is an array, not a simple variable.", table[$2].name); 697 | syntax_error(s); 698 | } 699 | } 700 | |NUM { 701 | int num; 702 | num=$1; 703 | if(num>AMAX){ 704 | char s[100]; 705 | sprintf(s,"integer(%d) should not greater than %d, now 0 instead. ", $1, AMAX); 706 | syntax_error(s); 707 | num=0; 708 | } 709 | gen(lit,0,num); 710 | } 711 | |NUM_D { 712 | num_d=$1; 713 | _gen(lit,0,0,1,$1); 714 | } 715 | ; 716 | 717 | /* 718 | get_table_addr: 719 | { 720 | $$ = tx; 721 | } 722 | ; 723 | */ 724 | get_code_addr: 725 | { 726 | $$ = cx; 727 | } 728 | ; 729 | %% 730 | 731 | 732 | void yyerror(char *s){ 733 | err++; 734 | printf("%s in line %d\n",s,line); 735 | fprintf(fa1,"%s in line %d\n",s,line); 736 | } 737 | 738 | int main(int argc,char *argv[]) 739 | { 740 | int i; 741 | listswitch=false; 742 | int print_table=0; 743 | if (argc > 1) { 744 | for (i = 1; i < argc; i++) 745 | { 746 | if (strcmp(argv[i], "-c")==0) 747 | { 748 | listswitch=true; 749 | }else if (strcmp(argv[i], "-t")==0) 750 | { 751 | print_table=1; 752 | } 753 | else if ((strcmp(argv[i], "-f")==0) && (argc > i+1)) 754 | { 755 | yyin = fopen(argv[++i],"r"); 756 | } 757 | else if(argc>i){ 758 | yyin = fopen(argv[i],"r"); 759 | } 760 | else 761 | { 762 | 763 | } 764 | } 765 | } 766 | printf("x0 compiler\n"); 767 | if((fa1=fopen("fa1.txt","w"))==NULL){ 768 | printf("Cann't open file!\n"); 769 | exit(0); 770 | } 771 | if((fa=fopen("fa.txt","w"))==NULL){ 772 | printf("Cann't open fa.txt file!\n"); 773 | exit(0); 774 | } 775 | if((fa2=fopen("fa2.txt","w"))==NULL){ 776 | printf("Cann't open fa2.txt file!\n"); 777 | exit(0); 778 | } 779 | yyparse(); 780 | fclose(fa); 781 | fclose(fa1); 782 | if(err==0) 783 | { 784 | listcode(); 785 | interpret(); 786 | } 787 | 788 | else 789 | printf("%d errors in PL/0 program\n",err); 790 | if(print_table){ 791 | printTable(0); 792 | } 793 | return 0; 794 | } --------------------------------------------------------------------------------