├── .gitignore ├── Makefile ├── README.md ├── expression.txt ├── function.txt ├── input.txt ├── lex.lex ├── llist.cpp ├── llist.h ├── parser.y └── statement.txt /.gitignore: -------------------------------------------------------------------------------- 1 | main 2 | output.txt 3 | *.c 4 | *.o 5 | .DS_Store 6 | parser.output 7 | parser.out 8 | parser.tab.* 9 | a.out 10 | grammer 11 | input.txt.back 12 | llist.h.gch 13 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all : lex parse compiler run 2 | debug : lex parser-debug compiler run 3 | 4 | parse : 5 | bison -d parser.y 6 | 7 | parser-debug : 8 | bison --verbose -d parser.y 9 | 10 | compiler: 11 | clang++ -std=c++14 lex.yy.c llist.cpp llist.h parser.tab.h parser.tab.c 12 | 13 | lex : lex.lex 14 | flex lex.lex 15 | 16 | run : 17 | ./a.out 18 | 19 | clean : 20 | rm -rf a.out lex.o lex.c output.txt parser.tab.h parser.tab.c lex.yy.c parser.output 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Hits](https://hits.seeyoufarm.com/api/count/incr/badge.svg?url=https%3A%2F%2Fgithub.com%2Fmahi97%2FPersian-Compiler&count_bg=%2379C83D&title_bg=%23555555&icon=&icon_color=%23E7E7E7&title=hits&edge_flat=false)](https://hits.seeyoufarm.com) 2 | 3 | # Persian-Compiler 4 | ~ Just Another Persian Compiler 5 | 6 | for build `output.txt` file just run : 7 | > `make` 8 | 9 | for clean files : 10 | >`make clean` 11 | -------------------------------------------------------------------------------- /expression.txt: -------------------------------------------------------------------------------- 1 | برنامه عبارت 2 | // این برنامه برای آزمایش پیاده‌سازی بخش عبارت‌ها طراحی شده است 3 | // و هیچ ارزش دیگر ندارد :) 4 | 5 | صحیح اصلی () { 6 | 7 | صحیح گنده؛ 8 | 9 | صحیح آرایه[2]; 10 | آرایه[0] = 2; 11 | آرایه[1] = 100; 12 | 13 | گنده = ۱ + ۱ + ۱ + ۱ + ۱ + ۱ + ۱ + ۱ + ۱ + ۱ + ۱ + ۱ + ۱ + ۱ + ۱ + ۱ + ۱ + ۱ + ۱ + ۱ + ۱ + ۱ + ۱ + ۱ + ۱ + درست + آرایه[1] + آرایه[1 - 1]؛ // ۲۵ :| 14 | 15 | 16 | 17 | 18 | } -------------------------------------------------------------------------------- /function.txt: -------------------------------------------------------------------------------- 1 | برنامه عبارت 2 | // این برنامه برای آزمایش پیاده‌سازی بخش توابع و ساختارها طراحی شده است 3 | // و هیچ ارزش دیگر ندارد :) 4 | 5 | ساختار فاکتوریل { 6 | ثابت صحیح شماره = ۵؛ 7 | صحیح مقدار؛ 8 | } 9 | 10 | صحیح محسابه_فاکتوریل (صحیح عدد) { 11 | اگر عدد < ۰ آنگاه برگردان -۱؛ 12 | وگرنه اگر عدد == ۱ آنگاه برگردان ۱؛ 13 | وگرنه { 14 | صحیح قبلی = محاسبه_فاکتوریل (عدد - ۱)؛ 15 | برگردان قبلی * عدد؛ 16 | } 17 | } 18 | 19 | ساختار توان { 20 | ثابت اعشاری پایه = ۲.۰؛ 21 | ثابت صحیح توان = ۵؛ 22 | اعشاری مقدار؛ 23 | } 24 | 25 | اعشاری محاسبه_توان (اعشاری پایه، صحیح توان) { 26 | صحیح شمارنده ۰؛ 27 | صحیح نتیجه = ۱؛ 28 | وقتی (شمارنده < توان) { 29 | نتیجه *= پایه؛ 30 | شمارنده++؛ 31 | } 32 | } 33 | 34 | صحیح اصلی () { 35 | فاکتوریل.مقدار = محاسبه_فاکتوریل(فاکتوریل.شماره)؛ 36 | // فاکتوریل.مقدار باید برابر نتیجه شود! 37 | توان.مقدار = محاسبه_توان(توان.پایه، توان.توان)؛ 38 | // توان.مقدار باید برابر نتیجه شود! 39 | } -------------------------------------------------------------------------------- /input.txt: -------------------------------------------------------------------------------- 1 | برنامه من 2 | ساختار ماهی 3 | { 4 | ثابت صحیح آ=۲۳، سلام=۲؛ 5 | اعشاری ب=۰.۰۳۲۳۰۲؛ 6 | حرف ث='آ'؛ 7 | منطقی ت=درست؛ 8 | } 9 | 10 | اعشاری ماهیساما=-21، ماهیگو=-23.۲۳، ماهیسان=۲۳.۰۰۰۳؛ 11 | صحیح نتیجه=-۲۳۳؛ 12 | منطقی الکی = غلط؛ 13 | حرف بیمقدار='\0'؛ 14 | 15 | صحیح محاسبهـفاکتوریل (صحیح شماره) { 16 | صحیح شمارنده = ۲۲؛ 17 | صحیح ن2تیجه = ۴۳؛ 18 | } 19 | 20 | صحیح اصلی (صحیح تعدادـآرگومان; حرف آرگومانها[])‌{ 21 | صحیح من[3]; 22 | صحیح ماهی = ۰؛ 23 | صحیح شسیب = ۰؛ 24 | شسیب += ۲؛ 25 | شسیب *= ۲؛ 26 | شسیب -= ۲؛ 27 | شسیب /= ۲؛ 28 | ;;;; 29 | برگردان ۳۲ ؛ 30 | بشکن؛ 31 | اگر آ == ۰ آنگاه { 32 | 33 | } وگرنه { 34 | اگر ماهی == ۲ آنگاه { 35 | وقتی ( ماهی == ۲ ) { 36 | ماهی++؛ 37 | } 38 | } 39 | ؛؛؛ 40 | ;;; 41 | کلید (ماهی) 42 | حالت ۳: بشکن؛؛ 43 | پیشفرض : بشکن؛; 44 | تمام 45 | 46 | تابع (ماهی ، 1, ۳+۴); 47 | 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /lex.lex: -------------------------------------------------------------------------------- 1 | %option noyywrap 2 | 3 | %{ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "parser.tab.h" 11 | 12 | char* lexID; 13 | int lexNum; 14 | double lexReal; 15 | char* lexChar; 16 | bool lexBool; 17 | 18 | double toReal(char* real_num) { 19 | int i = 0; 20 | int count = 0,count2 = 0; 21 | int res[50]; 22 | bool intPart = true; 23 | 24 | int n1 = real_num[i]; 25 | int n2 = real_num[i+1]; 26 | 27 | while((n1 == 37 && n2 == -80) || real_num[i] == '0') { 28 | i++; 29 | n1 = real_num[i]; 30 | n2 = real_num[i+1]; 31 | } 32 | 33 | while(real_num[i] != '\0') { 34 | if (real_num[i] == '.') { 35 | intPart = false; 36 | i++; 37 | continue; 38 | } 39 | if (intPart) { 40 | int num = real_num[i]; 41 | if (num >= 0 && num <= 255) { 42 | res[count] = real_num[i] - '0'; 43 | count++; 44 | } else { 45 | if (num != -37) { 46 | res[count] = num + 80; 47 | count++; 48 | } 49 | } 50 | } else { 51 | int num = real_num[i]; 52 | if (num >= 0 && num <= 255) { 53 | res[count+count2] = real_num[i] - '0'; 54 | count2++; 55 | } else { 56 | if (num != -37) { 57 | res[count+count2] = num + 80; 58 | count2++; 59 | } 60 | } 61 | } 62 | i++; 63 | 64 | } 65 | double r = 0; 66 | for (int j = 0; j < count; j++) { 67 | r += res[j] * pow(10,count-j-1); 68 | } 69 | for (int j = 0; j < count2; j++) { 70 | r += res[count + j] * pow(0.1,j+1); 71 | } 72 | return r; 73 | } 74 | 75 | int toNum(char* int_num) { 76 | int i = 0; 77 | int count = 0; 78 | int res[50]; 79 | 80 | int n1 = int_num[i]; 81 | int n2 = int_num[i+1]; 82 | 83 | while((n1 == 37 && n2 == -80) || int_num[i] == '0') { 84 | i++; 85 | n1 = int_num[i]; 86 | n2 = int_num[i+1]; 87 | } 88 | 89 | while(int_num[i] != '\0') { 90 | int num = int_num[i]; 91 | if (num >= 0 && num <= 255) { 92 | res[count] = int_num[i] - '0'; 93 | count++; 94 | } else { 95 | if (num != -37) { 96 | res[count] = num + 80; 97 | count++; 98 | } 99 | } 100 | i++; 101 | } 102 | int r = 0; 103 | for (int j = 0; j < count; j++) { 104 | r += res[j]*pow(10,count-j-1); 105 | } 106 | return r; 107 | } 108 | 109 | char* toChar(char* harf) { 110 | char* result; 111 | if (strcmp(harf, "\'\\n\'") == 0) { 112 | return harf; 113 | } else if ( strcmp(harf, "\'\\0\'") == 0 || strcmp(harf, "\'\\۰\'") == 0 ) { 114 | return "\'\\0\'"; 115 | } else { 116 | int idxToDel = 1; 117 | if (harf[0] == '\'') 118 | memmove(&harf[idxToDel], &harf[idxToDel + 1], strlen(harf) - idxToDel); 119 | result = harf; 120 | } 121 | int type = -1; 122 | int cnt = 0; 123 | char* result2 = new char[100]; 124 | for (int i = 0; i < strlen(result); i++) { 125 | int r = result[i]; 126 | if (r > 0 && r < 256) { 127 | result2[cnt++] = r; 128 | continue; 129 | } 130 | else if (r == -37) { 131 | type = 0; 132 | continue; 133 | } else if (r == -38) { 134 | type = 1; 135 | continue; 136 | } else if (r == -39) { 137 | type = 2; 138 | continue; 139 | } else if (r == -40) { 140 | type = 3; 141 | continue; 142 | } 143 | else { 144 | switch(type) { 145 | case 0: 146 | if (r >= -80) r += 80; // handle numbers 147 | else r += 193; 148 | break; 149 | case 1: 150 | r += 193; 151 | break; 152 | case 2: 153 | if (r == -66) r += 161; // handle pe :D 154 | else r += 193; 155 | break; 156 | case 3: 157 | r += 191; 158 | break; 159 | } 160 | } 161 | result2[cnt++] = r; 162 | } 163 | result2[cnt] = '\0'; 164 | return result2; 165 | } 166 | 167 | 168 | 169 | %} 170 | 171 | ZERO (0|۰) 172 | DIGIT (۰|۱|۲|۳|۴|۵|۶|۷|۸|۹|[0-9]) 173 | NONZERO_DIGIT (۱|۲|۳|۴|۵|۶|۷|۸|۹|[1-9]) 174 | UNDER (ـ) 175 | harf (ض|ص|ث|ق|ف|غ|ع|ه|خ|ح|ج|چ|گ|ک|م|ن|ت|ا|ل|ب|ی|س|ش|ظ|ط|ز|ر|ذ|د|پ|و|ژ|آ|{UNDER}) 176 | BOOLEAN_CONSTANT_TRUE (درست) 177 | BOOLEAN_CONSTANT_FALSE (غلط) 178 | 179 | PROGRAM_KW (برنامه) 180 | STRUCT_KW (ساختار) 181 | CONST_KW (ثابت) 182 | 183 | INT_KW (صحیح) 184 | REAL_KW (اعشاری) 185 | CHAR_KW (حرف) 186 | BOOL_KW (منطقی) 187 | 188 | IF_KW (اگر) 189 | THEN_KW (آنگاه) 190 | ELSE_KW (وگرنه) 191 | SWITCH_KW (کلید) 192 | DEFAULT_KW (پیشفرض) 193 | CASE_KW (حالت) 194 | END_KW (تمام) 195 | WHEN_KW (وقتی) 196 | RETURN_KW (برگردان) 197 | BREAK_KW (بشکن) 198 | OR_KW (یا) 199 | AND_KW (و) 200 | XOR_KW (یاوگرنه) 201 | ALSO_KW (وهمچنین) 202 | NOT_KW (خلاف) 203 | 204 | GT_KW (>) 205 | LT_KW (<) 206 | LE_KW (<=) 207 | EQ_KW (==) 208 | GE_KW (>=) 209 | 210 | PLUS_KW (\+) 211 | MINUS_KW (-) 212 | MULT_KW (\*) 213 | DIV_KW (\/) 214 | MOD_KW (%) 215 | 216 | AMALGAR_YEGANI_NEG (-) 217 | AMALGAR_YEGANI_STR (\*) 218 | QUEST_MARK (\?|؟) 219 | 220 | INC_KW (\+\+) 221 | DEC_KW (--) 222 | 223 | ASSIGN_OP (=) 224 | ASSIGN_PLUS (\+=) 225 | ASSIGN_MINUS (-=) 226 | ASSIGN_MULT (\*=) 227 | ASSIGN_DIV (\/=) 228 | 229 | 230 | JAYEKHALI (\ |\t)* 231 | NOGHTE_VIRGUL (;|؛) 232 | COMMA (,|،) 233 | PARANTES_BAZ [\(] 234 | PARANTES_BASTE [\)] 235 | AQULAD_BAZ [\{] 236 | AQULAD_BASTE [\}] 237 | DOT_PUNC (\.) 238 | DDOT_PUNC (\:) 239 | BRUCKET_BAZ (\[) 240 | BRUCKET_BASTE (\]) 241 | COMMENT (\/\/.*)|(\/\*(.|\n)*\*\/) 242 | 243 | IDENTIFIER {harf}({harf}|{DIGIT})* 244 | 245 | HARFE_SABET \'{harf}\' 246 | HARFE_SABET_KHAS (\'\\{harf}\'|\'\\0\'|\'\\n\'|\'\\۰\') 247 | 248 | INT_NUM [-]?{ZERO}|({NONZERO_DIGIT}{DIGIT}*) 249 | REAL_NUM [-]?({DIGIT}*\.{DIGIT}+|{DIGIT}+) 250 | CHAR_CONSTANT {HARFE_SABET}|{HARFE_SABET_KHAS} 251 | 252 | %% 253 | 254 | {COMMENT} {} 255 | 256 | {PROGRAM_KW} {return PROGRAM_KW;} 257 | {STRUCT_KW} {return STRUCT_KW;} 258 | {CONST_KW} {return CONST_KW;} 259 | {INT_KW} {return INT_KW;} 260 | {REAL_KW} {return REAL_KW;} 261 | {CHAR_KW} {return CHAR_KW;} 262 | {BOOL_KW} {return BOOL_KW;} 263 | {IF_KW} {return IF_KW;} 264 | {THEN_KW} {return THEN_KW;} 265 | {ELSE_KW} {return ELSE_KW;} 266 | {SWITCH_KW} {return SWITCH_KW;} 267 | {CASE_KW} {return CASE_KW;} 268 | {END_KW} {return END_KW;} 269 | {DEFAULT_KW} {return DEFAULT_KW;} 270 | {WHEN_KW} {return WHEN_KW;} 271 | {RETURN_KW} {return RETURN_KW;} 272 | {BREAK_KW} {return BREAK_KW;} 273 | {OR_KW} {return OR_KW;} 274 | {AND_KW} {return AND_KW;} 275 | {XOR_KW} {return XOR_KW;} 276 | {ALSO_KW} {return ALSO_KW;} 277 | {NOT_KW} {return NOT_KW;} 278 | 279 | 280 | {BOOLEAN_CONSTANT_TRUE} {return BOOL_CONSTANT_TRUE;} 281 | {BOOLEAN_CONSTANT_FALSE} {return BOOL_CONSTANT_FALSE;} 282 | {CHAR_CONSTANT} {lexChar = toChar(yytext); return CHAR_CONSTANT;} 283 | {INT_NUM} {lexNum = toNum(yytext); return INT_NUM;} 284 | {REAL_NUM} {lexReal = toReal(yytext); return REAL_NUM;} 285 | 286 | {IDENTIFIER} {lexID = new char[strlen(yytext)]; 287 | strcpy(lexID,toChar(yytext)); 288 | return IDENTIFIER; 289 | } 290 | 291 | {GT_KW} {return GT_KW;} 292 | {LT_KW} {return LT_KW;} 293 | {LE_KW} {return LE_KW;} 294 | {EQ_KW} {return EQ_KW;} 295 | {GE_KW} {return GE_KW;} 296 | 297 | {PLUS_KW} {return PLUS_KW;} 298 | {MINUS_KW} {return MINUS_KW;} 299 | {MULT_KW} {return MULT_KW;} 300 | {DIV_KW} {return DIV_KW;} 301 | {MOD_KW} {return MOD_KW;} 302 | 303 | {QUEST_MARK} {return QUEST_MARK;} 304 | 305 | {INC_KW} {return INC_KW;} 306 | {DEC_KW} {return DEC_KW;} 307 | 308 | {ASSIGN_OP} {return '=';} 309 | {ASSIGN_PLUS} {return ASSIGN_PLUS;} 310 | {ASSIGN_MINUS} {return ASSIGN_MINUS;} 311 | {ASSIGN_MULT} {return ASSIGN_MULT;} 312 | {ASSIGN_DIV} {return ASSIGN_DIV;} 313 | 314 | {DOT_PUNC} {return '.';} 315 | {DDOT_PUNC} {return ':';} 316 | {NOGHTE_VIRGUL} {return ';';} 317 | {COMMA} {return ',';} 318 | 319 | {AQULAD_BAZ} {return '{';} 320 | {AQULAD_BASTE} {return '}';} 321 | {BRUCKET_BAZ} {return '[';} 322 | {BRUCKET_BASTE} {return ']';} 323 | {PARANTES_BASTE} {return ')';} 324 | {PARANTES_BAZ} {return '(';} 325 | 326 | [\n] {++yylineno;} 327 | 328 | . {} 329 | -------------------------------------------------------------------------------- /llist.cpp: -------------------------------------------------------------------------------- 1 | #include "llist.h" 2 | 3 | #include 4 | #include 5 | 6 | struct node* create_node(int data) 7 | { 8 | struct node *result = (struct node *) malloc(sizeof(struct node)); 9 | result->data = data; 10 | result->next = nullptr; 11 | return result; 12 | } 13 | 14 | int size_of(struct llist* _list) { 15 | if (_list->head == nullptr) return 0; 16 | int size = 0; 17 | struct node* temp = _list->head; 18 | while(temp) { 19 | temp = temp->next; 20 | size++; 21 | } 22 | return size; 23 | } 24 | 25 | //Recursive 26 | int size_of(struct node* first) { 27 | if(first == nullptr) return 0; 28 | else return (size_of(first->next) + 1); 29 | } 30 | 31 | void add_end(struct node * first, int data) 32 | { 33 | struct node *current; 34 | for(current = first; current->next != NULL; current = current->next); 35 | struct node *new_node = create_node(data); 36 | current->next = new_node; 37 | } 38 | 39 | void add_end(struct llist * _list, int data) 40 | { 41 | struct node *new_node = create_node(data); 42 | _list->tail->next = new_node; 43 | _list->tail = new_node; 44 | } 45 | 46 | void print_list(struct node *first) 47 | { 48 | struct node *current; 49 | for(current=first; current!=NULL; current=current->next) 50 | { 51 | printf("Node %d\n", current->data); 52 | } 53 | } 54 | 55 | void print_list(struct llist *_list) 56 | { 57 | struct node *current; 58 | for(current=_list->head; current!=NULL; current=current->next) 59 | { 60 | printf("Node %d\n", current->data); 61 | } 62 | } 63 | 64 | struct node* merge_lists(struct node *first_x,struct node *first_y) 65 | { 66 | if(first_x == NULL) return first_y; 67 | if(first_y == NULL) return first_x; 68 | struct node* result; 69 | if(first_x->data >= first_y->data) 70 | result = first_y; 71 | else 72 | result = first_x; 73 | struct node * temp = NULL; 74 | while(first_x!=NULL && first_y!=NULL) 75 | { 76 | /*cout<data<<" "<data; 77 | if(temp==NULL) 78 | cout<<" "<<"NULL"<data<next&&first_x->next->datadata; first_x=first_x->next); 83 | for(; first_y->next&&first_y->next->datadata; first_y=first_y->next); 84 | if(first_x->data>=first_y->data) 85 | { 86 | temp = first_y; 87 | first_y = first_y->next; 88 | temp->next=first_x; 89 | } 90 | else 91 | { 92 | temp = first_x; 93 | first_x = first_x->next; 94 | temp->next = first_y; 95 | } 96 | } 97 | 98 | return result; 99 | } 100 | 101 | 102 | struct llist* merge_lists(struct llist *_list1,struct llist *_list2) 103 | { 104 | if(_list1->head == nullptr) return _list2; 105 | if(_list2->head == nullptr) return _list1; 106 | struct llist* result = new llist; 107 | result->head = _list1->head; 108 | result->tail = _list1->tail; 109 | if (result->tail == nullptr) result->tail = new node; 110 | result->tail->next = _list2->head; 111 | result->tail = _list2->tail; 112 | return result; 113 | } 114 | -------------------------------------------------------------------------------- /llist.h: -------------------------------------------------------------------------------- 1 | #ifndef _LLIST_H 2 | #define _LLIST_H 3 | 4 | struct node { 5 | int data; 6 | struct node* next; 7 | }; 8 | 9 | struct llist{ 10 | struct node* head; 11 | struct node* tail; 12 | }; 13 | 14 | struct node* create_node(int data); 15 | 16 | int size_of(struct llist* first); 17 | 18 | void add_end(struct llist* _list, int data); 19 | 20 | void print_list(struct llist *_list); 21 | 22 | 23 | struct llist* merge_lists(struct llist *_list1, struct llist *_list2); 24 | 25 | 26 | #endif // _LLIST_H -------------------------------------------------------------------------------- /parser.y: -------------------------------------------------------------------------------- 1 | %{ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "llist.h" 14 | #include 15 | using namespace std; 16 | 17 | 18 | // stuff from flex that bison needs to know about: 19 | // extern "C" int yylex(); 20 | // extern "C" int yyparse(); 21 | extern FILE *yyin; 22 | extern int yylineno; 23 | extern char* yytext; 24 | extern char* lexID; 25 | extern int lexNum; 26 | extern double lexReal; 27 | extern char* lexChar; 28 | extern bool lexBool; 29 | extern int yylex(void); 30 | 31 | // char symbolTable[1000][50]; 32 | int wrong=0; 33 | int nextquad = 0; 34 | int num = 0; // temporary variable numbers 35 | 36 | void yyerror(const char *s); 37 | 38 | FILE *fout; 39 | 40 | enum { 41 | TYPE_UNKNOWN = -1, 42 | TYPE_INT = 0, 43 | TYPE_REAL = 1, 44 | TYPE_CHAR = 2, 45 | TYPE_BOOL = 3 46 | }; 47 | 48 | void split(const string &s, char delim, vector &elems) { 49 | stringstream ss; 50 | ss.str(s); 51 | string item; 52 | while (getline(ss, item, delim)) { 53 | elems.push_back(item); 54 | } 55 | if (elems.empty()) elems.push_back(s); 56 | } 57 | 58 | vector split(const string &s, char delim) { 59 | vector elems; 60 | split(s, delim, elems); 61 | return elems; 62 | } 63 | 64 | /*** Symbol Table ***/ 65 | struct symbolTableEntry { 66 | string id; 67 | int type; 68 | bool is_array = false; 69 | vector *forward = NULL; 70 | vector *backward = NULL; 71 | int uid = 0; 72 | }; 73 | 74 | int cursor = 0; 75 | vector symbolTable; 76 | 77 | int symbolTableInsert(string _id, int _type, bool _isArray) { 78 | symbolTableEntry* ste = new symbolTableEntry; 79 | if (_id[0] == '#') _id = _id.substr(1); 80 | printf("%s %d\n", _id.c_str(), _id.size()); 81 | ste->id = _id; 82 | ste->type = _type; 83 | ste->is_array = _isArray; 84 | ste->uid = cursor; 85 | symbolTable.push_back(ste); 86 | return cursor++; 87 | } 88 | 89 | symbolTableEntry* symbolTableLookup(const string& _id) { 90 | for (auto& ste : symbolTable) { 91 | if (ste->id == _id) { 92 | return ste; 93 | } 94 | } 95 | return nullptr; 96 | } 97 | 98 | string printSymbolTable() { 99 | std::string s; 100 | for(auto& ste : symbolTable) { 101 | std::string arr = (ste->is_array) ? "*" : ""; 102 | switch(ste->type) { 103 | case TYPE_INT: 104 | s += "\tint " + arr + ste->id + ";\n"; 105 | break; 106 | case TYPE_BOOL: 107 | s += "\tchar " + arr + ste->id + ";\n"; 108 | break; 109 | case TYPE_REAL: 110 | s += "\tdouble " + arr + ste->id + ";\n"; 111 | break; 112 | case TYPE_CHAR: 113 | s += "\tchar " + arr + ste->id + ";\n"; 114 | break; 115 | } 116 | } 117 | return s; 118 | } 119 | 120 | char* newTemp(int _type, bool _isArray) { 121 | string* name = new string{"temp"}; 122 | *name += std::to_string(num++); 123 | symbolTableInsert(*name, _type, _isArray); 124 | return const_cast(name->c_str()); 125 | } 126 | 127 | llist* makelist(int _data) { 128 | node* n = create_node(_data); 129 | llist* l = new llist; 130 | l->head = n; 131 | l->tail = nullptr; 132 | return l; 133 | } 134 | 135 | // END_OF_SYMBOL_TABLE 136 | 137 | /*** Quadruples ***/ 138 | 139 | // // Quadruple 140 | /* ______________________________________________________________________________ 141 | * | | 142 | * | Quadruples | 143 | * |______________________________________________________________________________| 144 | * | Statement | Operation | Arg0 | Arg1 | Result | 145 | * |____________________________________|___________|___________|_______|_________| 146 | * | goto L | goto | | | L | 147 | * | if BOOLEAN then goto L | check | BOOLEAN | | L | 148 | * | E = E1 < E2 | < | E1 | E2 | E | 149 | * | E = E1 <= E2 | <= | E1 | E2 | E | 150 | * | E = E1 > E2 | > | E1 | E2 | E | 151 | * | E = E1 >= E2 | >= | E1 | E2 | E | 152 | * | E = E1 == E2 | == | E1 | E2 | E | 153 | * | E = E1 + E2 | + | E1 | E2 | E | 154 | * | E = E1 - E2 | - | E1 | E2 | E | 155 | * | E = E1 * E2 | * | E1 | E2 | E | 156 | * | E = E1 / E2 | / | E1 | E2 | E | 157 | * | E = E1 % E2 | % | E1 | E2 | E | 158 | * | E = -E1 | usub | E1 | | E | 159 | * | E = *E1 | asterisk | E1 | | E | 160 | * | E = ?E1 | quest | E1 | | E | 161 | * | E = E1 | = | E1 | | E | 162 | * | E = (TYPE) E1 | cast | E1 | TYPE | E | 163 | * | TYPE E | init | | TYPE | E | 164 | * | printf("E = E.val") | iprint | | | int | 165 | * | printf("E = E.val") | rprint | | | real | 166 | * | printf("E = E.val") | cprint | | | char | 167 | * | printf("E = E.val") | bprint | | | boolean | 168 | * | printf("E[PLACE] = E[INDEX].val") | aiprint | PLACE | INDEX | int | 169 | * | printf("E[PLACE] = E[INDEX].val") | arprint | PLACE | INDEX | real | 170 | * | printf("E[PLACE] = E[INDEX].val") | acprint | PLACE | INDEX | char | 171 | * | printf("E[PLACE] = E[INDEX].val") | abprint | PLACE | INDEX | boolean | 172 | * | E[INDEX] = E1 | []= | E1 | INDEX | E | 173 | * | E = E1[INDEX] | =[] | E1 | INDEX | E | 174 | * |____________________________________|___________|___________|_______|_________| 175 | */ 176 | 177 | struct Quadruple 178 | { 179 | Quadruple(string _op, string _arg1, string _arg2, string _res) : 180 | operation(_op), 181 | arg1(_arg1), 182 | arg2(_arg2), 183 | result(_res) 184 | { 185 | 186 | } 187 | string operation; 188 | string arg1; 189 | string arg2; 190 | string result; 191 | }; 192 | 193 | vector quadruples; 194 | 195 | void emit(string _op, string _arg1, string _arg2, string _result) { 196 | nextquad++; 197 | quadruples.push_back(new Quadruple(_op, _arg1, _arg2, _result)); 198 | } 199 | 200 | void backpatch(struct llist* _head, int _label) { 201 | struct node* current; 202 | for (current = _head->head; current != nullptr; current = current->next) { 203 | quadruples[current->data]->result = std::to_string(_label); 204 | } 205 | } 206 | 207 | void fillQuad(int i, int j, string _data) { 208 | switch(j) { 209 | case 0: 210 | quadruples[i]->operation = _data; 211 | break; 212 | case 1: 213 | quadruples[i]->arg1 = _data; 214 | break; 215 | case 2: 216 | quadruples[i]->arg2 = _data; 217 | break; 218 | case 3: 219 | quadruples[i]->result = _data; 220 | break; 221 | default: 222 | printf("Wrong index%d\n", j); 223 | } 224 | } 225 | 226 | string printQuadruple() 227 | { 228 | std::string s; 229 | for(int i = 0;i < quadruples.size();i++) 230 | { 231 | s += "L" + std::to_string(i) + ": "; 232 | if (quadruples[i] -> operation == "+") { 233 | s += quadruples[i] -> result + " = " + quadruples[i] -> arg1 + " + " + quadruples[i] -> arg2 + ";\n"; 234 | } else if(quadruples[i] -> operation == "-") { 235 | s += quadruples[i] -> result + " = " + quadruples[i] -> arg1 + " - " + quadruples[i] -> arg2 + ";\n"; 236 | } else if(quadruples[i] -> operation == "*") { 237 | s += quadruples[i] -> result + " = " + quadruples[i] -> arg1 + " * " + quadruples[i] -> arg2 + ";\n"; 238 | } else if(quadruples[i] -> operation == "/") { 239 | s += quadruples[i] -> result + " = " + quadruples[i] -> arg1 + " / " + quadruples[i] -> arg2 + ";\n"; 240 | } else if(quadruples[i] -> operation == "%") { 241 | s += quadruples[i] -> result + " = " + quadruples[i] -> arg1 + " % " + quadruples[i] -> arg2 + ";\n"; 242 | } else if(quadruples[i] -> operation == "ifgoto") { 243 | s += std::string("if") + " ( " + quadruples[i] -> arg1 +" ) " + "goto " + "L" + quadruples[i] -> result + ";\n"; 244 | } else if(quadruples[i] -> operation == "goto") { 245 | s += std::string("goto ") + "L" + quadruples[i] -> result + ";\n"; 246 | } else if(quadruples[i] -> operation == "=") { 247 | s += quadruples[i] -> result + " = " + quadruples[i] -> arg1 + ";\n"; 248 | } else if(quadruples[i] -> operation == "<") { 249 | s += quadruples[i] -> result + " = (" + quadruples[i] -> arg1 + "<" + quadruples[i] -> arg2 + ") ;\n"; 250 | } else if(quadruples[i] -> operation == "<=") { 251 | s += quadruples[i] -> result + " = (" + quadruples[i] -> arg1 + "<=" + quadruples[i] -> arg2 + ") ;\n"; 252 | } else if(quadruples[i] -> operation == "==") { 253 | s += quadruples[i] -> result + " = (" + quadruples[i] -> arg1 + "==" + quadruples[i] -> arg2 + ") ;\n"; 254 | } else if(quadruples[i] -> operation == ">") { 255 | s += quadruples[i] -> result + " = (" + quadruples[i] -> arg1 + ">" + quadruples[i] -> arg2 + ") ;\n"; 256 | } else if(quadruples[i] -> operation == ">=") { 257 | s += quadruples[i] -> result + " = (" + quadruples[i] -> arg1 + ">=" + quadruples[i] -> arg2 + ") ;\n"; 258 | } else if(quadruples[i] -> operation == "usub") { 259 | s += quadruples[i] -> result + " = " + "-1 * " + quadruples[i] -> arg1 + ";\n"; 260 | } else if(quadruples[i] -> operation == "asterisk") { 261 | s += quadruples[i] -> result + " = " + "sizeof(" + quadruples[i] -> arg1 + ")/sizeof(" + quadruples[i] -> arg1 + "[0]) ;\n"; 262 | } else if(quadruples[i] -> operation == "quest") { 263 | s += quadruples[i] -> result + " = " + "ud(0, " + quadruples[i] -> arg1 + ") ;\n"; 264 | } else if(quadruples[i] -> operation == "[]=") { 265 | s += quadruples[i] -> result + "["+ quadruples[i] -> arg2 + "]" + " = " + quadruples[i] -> arg1 + ";\n"; 266 | } else if(quadruples[i] -> operation == "=[]") { 267 | s += quadruples[i] -> result + " = " + quadruples[i] -> arg1 + "["+ quadruples[i] -> arg2 + "]" + ";\n"; 268 | } else { 269 | s+= quadruples[i]->operation + ";\n"; 270 | } 271 | } 272 | return s; 273 | } 274 | 275 | // END_OF_QUADRUPLES 276 | 277 | void generateInterCode() { 278 | FILE* interCode; 279 | interCode = fopen("generatedCode.c", "w"); 280 | if (fout == NULL) { 281 | printf("Error opening file!\n"); 282 | return; 283 | } 284 | fprintf(interCode, "#include \n"); 285 | fprintf(interCode, "#include \n"); 286 | fprintf(interCode, "#include \n\n"); 287 | fprintf(interCode, "int ud(int rL, int rH) {\n\tdouble mR = rand()/(1.0 + RAND_MAX);\n\tint r = rH - rL + 1;\n\tint mRS = (mR * r) + rL;\n\treturn mRS;\n}\n\n"); 288 | fprintf(interCode, "int main() {\n"); 289 | fprintf(interCode, "/* SYMBOL TABLE */\n"); 290 | fprintf(interCode, "%s\n", printSymbolTable().c_str()); 291 | fprintf(interCode, "/* Quadruples */\n"); 292 | fprintf(interCode, "%s\n", printQuadruple().c_str()); 293 | std::string nextLabel = std::string("L") + std::to_string(quadruples.size()) + ": ;"; 294 | fprintf(interCode, "%s\n", nextLabel.c_str()); 295 | fprintf(interCode, "return 0;\n}\n"); 296 | fclose(interCode); 297 | 298 | } 299 | 300 | %} 301 | 302 | %union { 303 | struct { 304 | 305 | int type; 306 | char* place; 307 | char* code; 308 | struct llist* truelist; 309 | struct llist* falselist; 310 | struct llist* nextlist; 311 | int quad; 312 | } E; 313 | } 314 | 315 | // define the "terminal symbol" token types I'm going to use (in CAPS 316 | // by convention), and associate each with a field of the union: 317 | %token PROGRAM_KW STRUCT_KW CONST_KW INT_KW REAL_KW CHAR_KW BOOL_KW IF_KW THEN_KW ELSE_KW SWITCH_KW DEFAULT_KW WHEN_KW RETURN_KW BREAK_KW OR_KW AND_KW XOR_KW ALSO_KW NOT_KW GT_KW LT_KW LE_KW EQ_KW GE_KW PLUS_KW MINUS_KW MULT_KW DIV_KW MOD_KW QUEST_MARK ASSIGN_PLUS ASSIGN_MINUS ASSIGN_MULT ASSIGN_DIV INC_KW DEC_KW CASE_KW END_KW 318 | %token INT_NUM 319 | %token REAL_NUM 320 | %token BOOL_CONSTANT_TRUE 321 | %token BOOL_CONSTANT_FALSE 322 | %token IDENTIFIER 323 | %token CHAR_CONSTANT 324 | 325 | %type idetifier_type 326 | %type int_type 327 | %type real_type 328 | %type bool_type 329 | %type char_type 330 | %type program declist dec structdec localdec limitedvardec limitedvartype type vardec varsdecs primiryvardec varIDdec funcdec arg args argstype argsID argID sentence compSent sentences exprSent selectSent caseelement defaultelement repeatSent returnSent argsVector constant argVector call breakSent unvar expr simpleexp variable relativeexp relativeop arthlogicexpr unaryexpr unaryop opera 331 | %type M 332 | 333 | %right THEN_KW 334 | %right ELSE_KW 335 | %left XOR_KW OR_KW 336 | %right '=' 337 | %left AND_KW ALSO_KW 338 | %left EQ_KW LT_KW GT_KW LE_KW GE_KW 339 | %left PLUS_KW MINUS_KW 340 | %left MULT_KW DIV_KW MOD_KW 341 | %right NOT_KW 342 | 343 | %% 344 | 345 | 346 | program : PROGRAM_KW idetifier_type declist 347 | { 348 | printf("Mahi\n"); 349 | generateInterCode(); 350 | fprintf(fout, "Rule 1 \t\t program -> PROGRAM_KW idetifier_type declist \n") ; 351 | }; 352 | 353 | declist : declist dec 354 | { 355 | fprintf(fout, "Rule 2.1 \t\t declist -> declist dec \n") ; 356 | }; 357 | | dec 358 | { 359 | fprintf(fout, "Rule 2.2 \t\t declist -> dec \n") ; 360 | }; 361 | 362 | dec : structdec 363 | { 364 | fprintf(fout, "%d: Rule 3.1 \t\t dec -> structdec \n", yylineno) ; 365 | }; 366 | | vardec 367 | { 368 | fprintf(fout, "%d: Rule 3.2 \t\t dec -> vardec \n", yylineno) ; 369 | }; 370 | | funcdec 371 | { 372 | fprintf(fout, "%d: Rule 3.3 \t\t dec -> funcdec \n", yylineno) ; 373 | }; 374 | 375 | structdec : STRUCT_KW idetifier_type '{' localdec '}' 376 | { 377 | fprintf(fout, "%d: Rule 4 \t\t structdec -> STRUCT_KW idetifier_type { localdec } \n", yylineno); 378 | }; 379 | 380 | localdec : localdec limitedvardec 381 | { 382 | fprintf(fout, "%d: Rule 5.1 \t\t localdec -> localdec limitedvardec \n", yylineno); 383 | }; 384 | | /* empty */ 385 | { 386 | fprintf(fout, "%d: Rule 5.2 \t\t localdec -> e \n", yylineno); 387 | }; 388 | 389 | limitedvardec : limitedvartype varsdecs ';' 390 | { 391 | fprintf(fout, "%d: Rule 6 \t\t limitedvardec -> limitedvartype varsdecs ; \n", yylineno); 392 | vector tokens = split($2.code, ','); 393 | for(auto& token : tokens) { 394 | symbolTableInsert(token, $1.type, (token[0] == '#')); 395 | } 396 | }; 397 | 398 | limitedvartype : CONST_KW type 399 | { 400 | $$.type = $2.type; 401 | fprintf(fout, "%d: Rule 7.1 \t\t limitedvartype -> CONST_KW type \n", yylineno); 402 | }; 403 | | type 404 | { 405 | $$.type = $1.type; 406 | fprintf(fout, "%d: Rule 7.2 \t\t limitedvartype -> type \n", yylineno); 407 | }; 408 | 409 | type : INT_KW 410 | { 411 | $$.type = TYPE_INT; 412 | fprintf(fout, "%d: Rule 8.1 \t\t type -> INT_KW \n", yylineno); 413 | }; 414 | | REAL_KW 415 | { 416 | $$.type = TYPE_REAL; 417 | fprintf(fout, "%d: Rule 8.2 \t\t type : REAL_KW \n", yylineno); 418 | }; 419 | | CHAR_KW 420 | { 421 | $$.type = TYPE_CHAR; 422 | fprintf(fout, "%d: Rule 8.3 \t\t type : CHAR_KW \n", yylineno); 423 | }; 424 | | BOOL_KW 425 | { 426 | $$.type = TYPE_BOOL; 427 | fprintf(fout, "%d: Rule 8.4 \t\t type : BOOL_KW \n", yylineno); 428 | }; 429 | 430 | vardec : type varsdecs ';' 431 | { 432 | vector tokens = split($2.code, ','); 433 | for(auto& token : tokens) { 434 | symbolTableInsert(token, $1.type, (token[0] == '#')); 435 | } 436 | fprintf(fout, "%d: Rule 9 \t\t vardec -> type varsdecs ;\n", yylineno); 437 | }; 438 | 439 | varsdecs : primiryvardec 440 | { 441 | fprintf(fout, "%d: Rule 10.1 \t\t varsdecs -> primiryvardec \n", yylineno); 442 | $$.code = new char[100]; 443 | strcpy($$.code,$1.place); 444 | 445 | }; 446 | | varsdecs ',' primiryvardec 447 | { 448 | fprintf(fout, "%d: Rule 10.2 \t\t varsdecs -> varsdecs , primiryvardec \n", yylineno); 449 | char *tt = new char[100]; 450 | strcpy(tt, $1.code); 451 | $$.code = strcat(strcat(tt, ","), $3.place); 452 | }; 453 | 454 | primiryvardec : varIDdec 455 | { 456 | fprintf(fout, "%d: Rule 11.1 \t\t primiryvardec -> varIDdec \n", yylineno); 457 | $$.place = $1.place; 458 | 459 | }; 460 | | varIDdec '=' simpleexp 461 | { 462 | fprintf(fout, "%d: Rule 11.2 \t\t primiryvardec -> varIDdec = simpleexp \n", yylineno); 463 | $$.place = $1.place; 464 | emit("=", $3.place, "", $1.place); 465 | }; 466 | 467 | varIDdec : idetifier_type 468 | { 469 | $$.place = $1.place; 470 | fprintf(fout, "%d: Rule 12.1 \t\t varIDdec -> idetifier_type \n", yylineno); 471 | }; 472 | | idetifier_type '[' int_type ']' 473 | { 474 | fprintf(fout, "%d: Rule 12.2 \t\t varIDdec -> idetifier_type [ int_type ] \n", yylineno); 475 | $$.place = new char[100]; 476 | strcpy($$.place,"#"); 477 | strcat($$.place,$1.place); 478 | printf("%s\n", $$.place); 479 | }; 480 | 481 | funcdec : type idetifier_type '(' arg ')' sentence 482 | { 483 | fprintf(fout, "%d: Rule 13.1 \t\t funcdec -> type idetifier_type ( arg ) sentence \n", yylineno); 484 | }; 485 | | idetifier_type '(' arg ')' sentence 486 | { 487 | fprintf(fout, "%d: Rule 13.2 \t\t funcdec -> idetifier_type ( arg ) sentence \n", yylineno); 488 | }; 489 | 490 | arg : args 491 | { 492 | fprintf(fout, "%d: Rule 14.1 \t\t arg -> args \n", yylineno); 493 | }; 494 | | /* empty */ 495 | { 496 | fprintf(fout, "%d: Rule 14.2 \t\t arg : e \n", yylineno); 497 | }; 498 | 499 | args : args ';' argstype 500 | { 501 | fprintf(fout, "%d: Rule 15.1 \t\t args -> args ; argstype \n", yylineno); 502 | }; 503 | | argstype 504 | { 505 | fprintf(fout, "%d: Rule 15.2 \t\t args -> argstype \n", yylineno); 506 | }; 507 | 508 | argstype : type argsID 509 | { 510 | fprintf(fout, "%d: Rule 16 \t\t argstype -> type argsID \n", yylineno); 511 | }; 512 | 513 | argsID : argsID ',' argID 514 | { 515 | fprintf(fout, "Rule 17.1 \t\t argsID -> argsID , argID \n"); 516 | }; 517 | | argID 518 | { 519 | fprintf(fout, "Rule 17.2 \t\t argsID -> argID \n"); 520 | }; 521 | 522 | argID : idetifier_type 523 | { 524 | fprintf(fout, "Rule 18.1 \t\t argID -> idetifier_type \n"); 525 | }; 526 | | idetifier_type '[' ']' 527 | { 528 | fprintf(fout, "Rule 18.2 \t\t argID : idetifier_type [ ] \n"); 529 | }; 530 | 531 | sentence : compSent 532 | { 533 | fprintf(fout, "Rule 19.1 \t\t sentence -> compSent \n"); 534 | }; 535 | | exprSent 536 | { 537 | fprintf(fout, "Rule 19.2 \t\t sentence -> exprSent \n"); 538 | }; 539 | | selectSent 540 | { 541 | fprintf(fout, "Rule 19.3 \t\t sentence -> selectSent \n"); 542 | }; 543 | | repeatSent 544 | { 545 | fprintf(fout, "Rule 19.4 \t\t sentence -> repeatSent \n"); 546 | }; 547 | | returnSent 548 | { 549 | fprintf(fout, "Rule 19.5 \t\t sentence -> returnSent \n"); 550 | }; 551 | | breakSent 552 | { 553 | fprintf(fout, "Rule 19.6 \t\t sentence -> breakSent \n"); 554 | }; 555 | 556 | compSent : '{' localdec sentences '}' 557 | { 558 | fprintf(fout, "Rule 20 \t\t compSent -> { localdec sentences } \n"); 559 | }; 560 | 561 | sentences : sentences sentence 562 | { 563 | fprintf(fout, "Rule 21.1 \t\t sentences -> sentences sentence \n"); 564 | }; 565 | | /* empty */ 566 | { 567 | fprintf(fout, "Rule 21.2 \t\t sentences -> e \n"); 568 | }; 569 | 570 | exprSent : expr ';' 571 | { 572 | fprintf(fout, "Rule 22.1 \t\t exprSent -> expr ; \n"); 573 | }; 574 | | ';' 575 | { 576 | fprintf(fout, "Rule 22.2 \t\t exprSent -> ; \n"); 577 | }; 578 | 579 | selectSent : IF_KW simpleexp THEN_KW sentence 580 | { 581 | fprintf(fout, "Rule 23.1 \t\t selectSent -> IF_KW simpleexp THEN_KW sentence \n"); 582 | 583 | }; 584 | | IF_KW simpleexp THEN_KW sentence ELSE_KW sentence 585 | { 586 | fprintf(fout, "Rule 23.2 \t\t selectSent -> IF_KW simpleexp THEN_KW sentence ELSE_KW sentence \n"); 587 | }; 588 | | SWITCH_KW '(' simpleexp ')' caseelement defaultelement END_KW 589 | { 590 | fprintf(fout, "Rule 23.3 \t\t selectSent -> SWITCH_KW '(' simpleexp ')' caseelement defaultelement END_KW \n"); 591 | }; 592 | 593 | caseelement : CASE_KW int_type ':' sentence ';' 594 | { 595 | fprintf(fout, "Rule 24.1 \t\t caseelement -> CASE_KW int_type : sentence ; \n"); 596 | }; 597 | | caseelement CASE_KW int_type ':' sentence ';' 598 | { 599 | fprintf(fout, "Rule 24.2 \t\t caseelement -> caseelement CASE_KW int_type : sentence ; \n"); 600 | }; 601 | 602 | defaultelement : DEFAULT_KW ':' sentence ';' 603 | { 604 | fprintf(fout, "Rule 25.1 \t\t defaultelement -> DEFAULT_KW : sentence ; \n"); 605 | }; 606 | | /* empty */ 607 | { 608 | fprintf(fout, "Rule 25.2 \t\t defaultelement -> e \n"); 609 | }; 610 | 611 | repeatSent : WHEN_KW '(' simpleexp ')' sentence 612 | { 613 | fprintf(fout, "Rule 26 \t\t repeatSent -> WHEN_KW '(' simpleexp ')' sentence \n"); 614 | }; 615 | 616 | returnSent : RETURN_KW expr ';' 617 | { 618 | fprintf(fout, "Rule 27 \t\t returnSent -> RETURN_KW ; \n"); 619 | }; 620 | 621 | breakSent : BREAK_KW ';' 622 | { 623 | fprintf(fout, "Rule 28 \t\t breakSent -> BREAK_KW ; \n"); 624 | }; 625 | 626 | expr : variable '=' expr 627 | { 628 | fprintf(fout, "Rule 29.1 \t\t expr -> variable = expr \n"); 629 | if($3.type == TYPE_BOOL) { 630 | backpatch($3.truelist,nextquad); 631 | backpatch($3.falselist,nextquad + 2); 632 | emit("=", "1", "", $1.place); 633 | emit("goto", "", "", std::to_string(nextquad + 3)); 634 | emit("=", "0", "",$1.place); 635 | } else { 636 | if (symbolTableLookup($1.place) != nullptr && symbolTableLookup($1.place)->is_array) { 637 | $$.type = $1.type; 638 | emit("[]=", $1.place, $3.place, $$.place); 639 | 640 | } else if (symbolTableLookup($3.place) != nullptr && symbolTableLookup($3.place)->is_array) { 641 | $$.type = $1.type; 642 | emit("=[]", $1.place, $3.place, $$.place); 643 | 644 | } else { 645 | $$.type = $1.type; 646 | emit("=", $3.place, "", $1.place); 647 | 648 | } 649 | } 650 | }; 651 | | variable ASSIGN_PLUS expr 652 | { 653 | $$.place = newTemp($1.type, false); 654 | $$.type = $1.type; 655 | emit("+", $1.place, $3.place, $$.place); 656 | emit("+", $1.place, $3.place, $1.place); 657 | fprintf(fout, "Rule 29.2 \t\t expr -> variable += expr \n"); 658 | }; 659 | | variable ASSIGN_MINUS expr 660 | { 661 | $$.place = newTemp($1.type, false); 662 | $$.type = $1.type; 663 | emit("-", $1.place, $3.place, $$.place); 664 | emit("-", $1.place, $3.place, $1.place); 665 | fprintf(fout, "Rule 29.3 \t\t expr -> variable -= expr \n"); 666 | }; 667 | | variable ASSIGN_MULT expr 668 | { 669 | $$.place = newTemp($1.type, false); 670 | $$.type = $1.type; 671 | emit("*", $1.place, $3.place, $$.place); 672 | emit("*", $1.place, $3.place, $1.place); 673 | fprintf(fout, "Rule 29.4 \t\t expr -> variable *= expr \n"); 674 | }; 675 | | variable ASSIGN_DIV expr 676 | { 677 | $$.place = newTemp($1.type, false); 678 | $$.type = $1.type; 679 | emit("/", $1.place, $3.place, $$.place); 680 | emit("/", $1.place, $3.place, $1.place); 681 | fprintf(fout, "Rule 29.5 \t\t expr -> variable /= expr \n"); 682 | }; 683 | | variable INC_KW 684 | { 685 | $$.place = newTemp($1.type, false); 686 | fprintf(fout, "Rule 29.6 \t\t expr -> variable ++ \n"); 687 | $$.type = $1.type; 688 | emit("+", $1.place, "1", $$.place); 689 | emit("+", $1.place, "1", $1.place); 690 | }; 691 | | variable DEC_KW 692 | { 693 | fprintf(fout, "Rule 29.7 \t\t expr -> variable -- \n"); 694 | $$.place = newTemp($1.type, false); 695 | $$.type = $1.type; 696 | emit("-", $1.place, "1", $$.place); 697 | emit("-", $1.place, "1", $1.place); 698 | }; 699 | | simpleexp 700 | { 701 | fprintf(fout, "Rule 29.8 \t\t expr -> simpleexp \n"); 702 | $$.type = $1.type; 703 | $$.place = $1.place; 704 | $$.truelist = $1.truelist; 705 | $$.falselist = $1.falselist; 706 | }; 707 | 708 | 709 | simpleexp : simpleexp OR_KW M simpleexp 710 | { 711 | fprintf(fout, "Rule 30.1 \t\t simpleexp -> simpleexp OR simpleexp \n"); 712 | $$.place = newTemp(TYPE_BOOL, false); 713 | backpatch($1.falselist,$3.quad); 714 | $$.truelist = merge_lists($1.truelist,$4.truelist); 715 | $$.falselist = $4.falselist; 716 | $$.type = TYPE_BOOL; 717 | }; 718 | | simpleexp AND_KW M simpleexp 719 | { 720 | fprintf(fout, "Rule 30.2 \t\t simpleexp -> simpleexp AND simpleexp \n"); 721 | $$.place = newTemp(TYPE_BOOL, false); 722 | backpatch($1.truelist,$3.quad); 723 | $$.truelist = $4.truelist; 724 | $$.falselist = merge_lists($1.falselist,$4.falselist); 725 | $$.type = TYPE_BOOL; 726 | }; 727 | | simpleexp XOR_KW simpleexp 728 | { 729 | fprintf(fout, "Rule 30.3 \t\t simpleexp -> simpleexp XOR simpleexp \n"); 730 | }; 731 | | simpleexp ALSO_KW simpleexp 732 | { 733 | fprintf(fout, "Rule 30.4 \t\t simpleexp -> simpleexp ALSO simpleexp \n"); 734 | }; 735 | | NOT_KW simpleexp 736 | { 737 | fprintf(fout, "Rule 30.5 \t\t simpleexp -> NOT simpleexp \n"); 738 | $$.place = newTemp(TYPE_BOOL, false); 739 | $$.type = TYPE_BOOL; 740 | $$.truelist = $2.falselist; 741 | $$.falselist = $2.truelist; 742 | }; 743 | | relativeexp 744 | { 745 | fprintf(fout, "Rule 30.6 \t\t simpleexp -> relativeexp \n"); 746 | $$.type = $1.type; 747 | $$.place = $1.place; 748 | $$.truelist = $1.truelist; 749 | $$.falselist = $1.falselist; 750 | }; 751 | 752 | relativeexp : arthlogicexpr 753 | { 754 | fprintf(fout, "Rule 31.1 \t\t relativeexp -> arthlogicexpr \n"); 755 | $$.type = $1.type; 756 | $$.place = $1.place; 757 | $$.truelist = $1.truelist; 758 | $$.falselist = $1.falselist; 759 | }; 760 | | arthlogicexpr relativeop arthlogicexpr 761 | { 762 | fprintf(fout, "Rule 31.2 \t\t relativeexp -> arthlogicexpr relativeop arthlogicexpr \n"); 763 | $$.place = newTemp(TYPE_BOOL, false); 764 | $$.type = TYPE_BOOL; 765 | $$.truelist = makelist(nextquad + 1); 766 | $$.falselist = makelist(nextquad + 2); 767 | emit($2.place, $1.place, $3.place, $$.place); 768 | printf("%d,,, %s\n", nextquad + 2, std::to_string(nextquad + 2).c_str()); 769 | emit("ifgoto", $$.place,"", std::to_string(nextquad + 2)); 770 | emit("goto", "", "", std::to_string(nextquad + 1)); 771 | }; 772 | 773 | relativeop : LT_KW 774 | { 775 | fprintf(fout, "Rule 32.1 \t\t relativeop -> < \n"); 776 | $$.place = new char[3]; 777 | strcpy($$.place,"<"); 778 | }; 779 | | LE_KW 780 | { 781 | fprintf(fout, "Rule 32.2 \t\t relativeop -> <= \n"); 782 | $$.place = new char[3]; 783 | strcpy($$.place,"<="); 784 | }; 785 | | EQ_KW 786 | { 787 | fprintf(fout, "Rule 32.3 \t\t relativeop -> == \n"); 788 | $$.place = new char[3]; 789 | strcpy($$.place,"=="); 790 | }; 791 | | GE_KW 792 | { 793 | fprintf(fout, "Rule 32.4 \t\t relativeop -> >= \n"); 794 | $$.place = new char[3]; 795 | strcpy($$.place,">="); 796 | }; 797 | | GT_KW 798 | { 799 | fprintf(fout, "Rule 32.5 \t\t relativeop -> > \n"); 800 | $$.place = new char[3]; 801 | strcpy($$.place,">"); 802 | }; 803 | 804 | arthlogicexpr : unaryexpr 805 | { 806 | fprintf(fout, "Rule 33.1 \t\t arthlogicexpr -> unaryexpr \n"); 807 | $$.type = $1.type; 808 | $$.place = $1.place; 809 | $$.truelist = $1.truelist; 810 | $$.falselist = $1.falselist; 811 | }; 812 | | arthlogicexpr PLUS_KW arthlogicexpr 813 | { 814 | fprintf(fout, "Rule 33.2 \t\t arthlogicexpr -> arthlogicexpr PLUS_KW arthlogicexpr \n"); 815 | $$.place = newTemp($1.type, false); 816 | $$.truelist = makelist(nextquad + 1); 817 | $$.falselist = makelist(nextquad + 2); 818 | emit("+", $1.place, $3.place, $$.place); 819 | emit("ifgoto", $$.place, "", std::to_string(nextquad + 2)); 820 | emit("goto", "", "", std::to_string(nextquad + 1)); 821 | }; 822 | | arthlogicexpr MINUS_KW arthlogicexpr 823 | { 824 | fprintf(fout, "Rule 33.3 \t\t arthlogicexpr -> arthlogicexpr MINUS_KW arthlogicexpr \n"); 825 | $$.place = newTemp($1.type, false); 826 | $$.truelist = makelist(nextquad + 1); 827 | $$.falselist = makelist(nextquad + 2); 828 | emit("-", $1.place, $3.place, $$.place); 829 | emit("ifgoto", $$.place, "", std::to_string(nextquad + 2)); 830 | emit("goto", "", "", std::to_string(nextquad + 1)); 831 | }; 832 | | arthlogicexpr MULT_KW arthlogicexpr 833 | { 834 | fprintf(fout, "Rule 33.4 \t\t arthlogicexpr -> arthlogicexpr MULT_KW arthlogicexpr \n"); 835 | $$.place = newTemp($1.type, false); 836 | $$.truelist = makelist(nextquad + 1); 837 | $$.falselist = makelist(nextquad + 2); 838 | emit("*", $1.place, $3.place, $$.place); 839 | emit("ifgoto", $$.place, "", std::to_string(nextquad + 2)); 840 | emit("goto", "", "", std::to_string(nextquad + 1)); 841 | }; 842 | | arthlogicexpr DIV_KW arthlogicexpr 843 | { 844 | fprintf(fout, "Rule 33.5 \t\t arthlogicexpr -> arthlogicexpr DIV_KW arthlogicexpr \n"); 845 | $$.place = newTemp($1.type, false); 846 | $$.truelist = makelist(nextquad + 1); 847 | $$.falselist = makelist(nextquad + 2); 848 | emit("-", $1.place, $3.place, $$.place); 849 | emit("ifgoto", $$.place, "", std::to_string(nextquad + 2)); 850 | emit("goto", "", "", std::to_string(nextquad + 1)); 851 | }; 852 | | arthlogicexpr MOD_KW arthlogicexpr 853 | { 854 | fprintf(fout, "Rule 33.6 \t\t arthlogicexpr -> arthlogicexpr MOD_KW arthlogicexpr \n"); 855 | $$.place = newTemp($1.type, false); 856 | $$.truelist = makelist(nextquad + 1); 857 | $$.falselist = makelist(nextquad + 2); 858 | emit("%", $1.place, $3.place, $$.place); 859 | emit("ifgoto", $$.place, "", std::to_string(nextquad + 2)); 860 | emit("goto", "", "", std::to_string(nextquad + 1)); 861 | }; 862 | 863 | unaryexpr : unaryop unaryexpr 864 | { 865 | if ($1.type == TYPE_UNKNOWN) { 866 | $$.place = newTemp($2.type, false); 867 | $$.type = $2.type; 868 | $$.truelist = $2.truelist; 869 | $$.falselist = $2.falselist; 870 | emit($1.place, $2.place, "", $$.place); 871 | } 872 | else { 873 | $$.place = newTemp($1.type, false); 874 | $$.type = $1.type; 875 | $$.truelist = makelist(nextquad + 1); 876 | $$.falselist = makelist(nextquad + 2); 877 | emit($1.place, $2.place, "", $$.place); 878 | emit("ifgoto", $$.place, "", std::to_string(nextquad + 2)); 879 | emit("goto", "", "", std::to_string(nextquad + 1)); 880 | 881 | } 882 | fprintf(fout, "Rule 34.1 \t\t unaryexpr -> unaryop unaryexpr \n"); 883 | }; 884 | | opera 885 | { 886 | $$.type = $1.type; 887 | $$.place = $1.place; 888 | $$.truelist = $1.truelist; 889 | $$.falselist = $1.falselist; 890 | fprintf(fout, "Rule 34.2 \t\t unaryexpr -> opera \n"); 891 | }; 892 | 893 | unaryop : MINUS_KW 894 | { 895 | fprintf(fout, "Rule 35.1 \t\t unaryop -> - \n"); 896 | $$.place = new char[10]; 897 | $$.type = TYPE_UNKNOWN; 898 | strcpy($$.place,"usub"); 899 | }; 900 | | MULT_KW 901 | { 902 | fprintf(fout, "Rule 35.2 \t\t unaryop -> * \n"); 903 | $$.place = new char[10]; 904 | $$.type = TYPE_INT; 905 | strcpy($$.place,"asterisk"); 906 | }; 907 | | QUEST_MARK 908 | { 909 | fprintf(fout, "Rule 35.3 \t\t unaryop -> ? \n"); 910 | $$.place = new char[10]; 911 | $$.type = TYPE_INT; 912 | strcpy($$.place,"quest"); 913 | }; 914 | 915 | opera : variable 916 | { 917 | fprintf(fout, "Rule 36.1 \t\t opera -> variable \n"); 918 | $$.place = $1.place; 919 | }; 920 | | unvar 921 | { 922 | fprintf(fout, "Rule 36.2 \t\t opera -> unvar \n"); 923 | $$.type = $1.type; 924 | $$.place = $1.place; 925 | $$.truelist = $1.truelist; 926 | $$.falselist = $1.falselist; 927 | }; 928 | 929 | variable : idetifier_type 930 | { 931 | fprintf(fout, "Rule 37.1 \t\t variable -> idetifier_type \n"); 932 | symbolTableEntry* temp = symbolTableLookup($1.place); 933 | if (temp == nullptr) { 934 | printf("%d : Error! %s is not declared.\n", yylineno, $1.place); 935 | } else { 936 | $$.place = $1.place; 937 | $$.type = temp->type; 938 | $$.truelist = makelist(nextquad + 1); 939 | $$.falselist = makelist(nextquad + 2); 940 | emit("ifgoto", $$.place, "", std::to_string(nextquad + 2)); 941 | emit("goto", "", "", std::to_string(nextquad + 1)); 942 | } 943 | }; 944 | | variable '[' expr ']' 945 | { 946 | fprintf(fout, "Rule 37.2 \t\t variable -> variable [ expr ] \n"); 947 | symbolTableEntry* tmp = symbolTableLookup($1.place); 948 | if (tmp == nullptr || !tmp->is_array) { 949 | printf("%d : Error! %s is not declared.\n", yylineno, $1.place); 950 | } else { 951 | $$.place = newTemp($1.type, false); 952 | $$.type = tmp->type; 953 | $$.truelist = makelist(nextquad + 1); 954 | $$.falselist = makelist(nextquad + 2); 955 | emit("ifgoto", $$.place, "", std::to_string(nextquad + 2)); 956 | emit("goto", "", "", std::to_string(nextquad + 1)); 957 | } 958 | }; 959 | | variable '.' idetifier_type 960 | { 961 | fprintf(fout, "Rule 37.3 \t\t variable : variable . idetifier_type \n"); 962 | }; 963 | 964 | unvar : '(' expr ')' 965 | { 966 | fprintf(fout, "Rule 38.1 \t\t unvar -> ( expr ) \n"); 967 | $$.type = $2.type; 968 | $$.place = $2.place; 969 | $$.truelist = $2.truelist; 970 | $$.falselist = $2.falselist; 971 | }; 972 | | call 973 | { 974 | fprintf(fout, "Rule 38.2 \t\t unvar -> call \n"); 975 | }; 976 | | constant 977 | { 978 | fprintf(fout, "Rule 38.3 \t\t unvar : constant \n"); 979 | $$.type = $1.type; 980 | $$.place = $1.place; 981 | $$.truelist = $1.truelist; 982 | $$.falselist = $1.falselist; 983 | }; 984 | 985 | call : idetifier_type '(' argVector ')' 986 | { 987 | fprintf(fout, "Rule 39 \t\t call -> idetifier_type '(' argVector ')' \n"); 988 | }; 989 | 990 | argVector : argsVector 991 | { 992 | fprintf(fout, "Rule 40.1 \t\t argVector -> argsVector \n"); 993 | }; 994 | | /* empty */ 995 | { 996 | fprintf(fout, "Rule 40.2 \t\t argVector -> e \n"); 997 | }; 998 | 999 | argsVector : argsVector ',' expr 1000 | { 1001 | fprintf(fout, "Rule 41.1 \t\t argsVector -> argsVector , expr \n"); 1002 | }; 1003 | | expr 1004 | { 1005 | fprintf(fout, "Rule 41.2 \t\t argsVector -> expr \n"); 1006 | $$.place = $1.place; 1007 | $$.type = $1.type; 1008 | 1009 | }; 1010 | 1011 | constant : int_type 1012 | { 1013 | fprintf(fout, "Rule 42.1 \t\t constant : int_type \n"); 1014 | $$.type = $1.type; 1015 | $$.place = $1.place; 1016 | $$.truelist = $1.truelist; 1017 | $$.falselist = $1.falselist; 1018 | }; 1019 | | real_type 1020 | { 1021 | fprintf(fout, "Rule 42.2 \t\t constant : real_type \n"); 1022 | $$.type = $1.type; 1023 | $$.place = $1.place; 1024 | $$.truelist = $1.truelist; 1025 | $$.falselist = $1.falselist; 1026 | }; 1027 | | char_type 1028 | { 1029 | fprintf(fout, "Rule 42.3 \t\t constant : char_type \n"); 1030 | $$.type = $1.type; 1031 | $$.place = $1.place; 1032 | $$.truelist = $1.truelist; 1033 | $$.falselist = $1.falselist; 1034 | }; 1035 | | bool_type 1036 | { 1037 | fprintf(fout, "Rule 42.4 \t\t constant : bool_type \n"); 1038 | $$.type = $1.type; 1039 | $$.place = $1.place; 1040 | $$.truelist = $1.truelist; 1041 | $$.falselist = $1.falselist; 1042 | }; 1043 | 1044 | int_type : INT_NUM { 1045 | fprintf(fout, "Rule 42.5 \t\t int_type : INT_NUM \n"); 1046 | 1047 | $$.type = TYPE_INT; 1048 | $$.place = newTemp(TYPE_INT,false); 1049 | $$.truelist = makelist(nextquad + 1); 1050 | $$.falselist = makelist(nextquad + 2); 1051 | emit("=", std::to_string(lexNum), "", $$.place); 1052 | emit("ifgoto", $$.place, "", std::to_string(nextquad + 2)); 1053 | emit("goto", "", "", std::to_string(nextquad + 1)); 1054 | }; 1055 | 1056 | real_type : REAL_NUM { 1057 | fprintf(fout, "Rule 43 \t\t real_type : REAL_NUM \n"); 1058 | 1059 | $$.type = TYPE_REAL; 1060 | $$.place = newTemp(TYPE_REAL,false); 1061 | $$.truelist = makelist(nextquad + 1); 1062 | $$.falselist = makelist(nextquad + 2); 1063 | emit("=", std::to_string(lexReal), "", $$.place); 1064 | emit("ifgoto", $$.place, "", std::to_string(nextquad + 2)); 1065 | emit("goto", "", "", std::to_string(nextquad + 1)); 1066 | }; 1067 | 1068 | char_type : CHAR_CONSTANT { 1069 | 1070 | fprintf(fout, "Rule 44 \t\t char_type : CHAR_CONSTANT \n"); 1071 | $$.type = TYPE_CHAR; 1072 | $$.place = newTemp(TYPE_CHAR,false); 1073 | $$.truelist = makelist(nextquad + 1); 1074 | $$.falselist = makelist(nextquad + 2); 1075 | emit("=", std::string(lexChar), "", $$.place); 1076 | emit("ifgoto", $$.place, "", std::to_string(nextquad + 2)); 1077 | emit("goto", "", "", std::to_string(nextquad + 1)); 1078 | }; 1079 | 1080 | bool_type : BOOL_CONSTANT_FALSE { 1081 | 1082 | fprintf(fout, "Rule 45 \t\t bool_type : BOOL_CONSTANT_FALSE \n"); 1083 | $$.type = TYPE_BOOL; 1084 | $$.place = newTemp(TYPE_BOOL,false); 1085 | $$.truelist = makelist(nextquad + 1); 1086 | $$.falselist = makelist(nextquad + 2); 1087 | emit("=", "0", "", $$.place); 1088 | emit("ifgoto", $$.place, "", std::to_string(nextquad + 2)); 1089 | emit("goto", "", "", std::to_string(nextquad + 1)); 1090 | 1091 | }; 1092 | | BOOL_CONSTANT_TRUE { 1093 | 1094 | fprintf(fout, "Rule 46 \t\t bool_type : BOOL_CONSTANT_TRUE \n"); 1095 | $$.type = TYPE_BOOL; 1096 | $$.place = newTemp(TYPE_BOOL,false); 1097 | $$.truelist = makelist(nextquad + 1); 1098 | $$.falselist = makelist(nextquad + 2); 1099 | emit("=", "1", "", $$.place); 1100 | emit("ifgoto", $$.place, "", std::to_string(nextquad + 2)); 1101 | emit("goto", "", "", std::to_string(nextquad + 1)); 1102 | } 1103 | 1104 | 1105 | idetifier_type : IDENTIFIER { 1106 | fprintf(fout, "Rule 47 \t\t idetifier_type : IDENTIFIER \n"); 1107 | $$.place = lexID; 1108 | $$.type = TYPE_UNKNOWN; 1109 | }; 1110 | 1111 | M : /* empty */ 1112 | { 1113 | fprintf(fout, "Rule 48 \t\t M : empty \n"); 1114 | $$.quad = nextquad; 1115 | }; 1116 | 1117 | %% 1118 | 1119 | void handle(int signal) { 1120 | fclose(fout); 1121 | exit(1); 1122 | } 1123 | 1124 | int main() { 1125 | 1126 | signal(11, handle); 1127 | signal(SIGINT, handle); 1128 | signal(SIGABRT, handle); 1129 | // open a file handle to a particular file: 1130 | yyin = fopen("expression.txt", "r"); 1131 | 1132 | fout = fopen("output.txt", "w"); 1133 | fprintf(fout, "\n \t \t \t PARSER \n"); 1134 | fprintf(fout, "Rule No. --> Rule Description \n"); 1135 | 1136 | if (fout == NULL) 1137 | { 1138 | printf("Error opening file!\n"); 1139 | //exit(1); 1140 | } 1141 | // make sure it is valIDENTIFIER: 1142 | else if (!yyin) { 1143 | printf("Error opening file!\n"); 1144 | //exit(1); 1145 | } 1146 | // set flex to read from it instead of defaulting to STDIN: 1147 | 1148 | // parse through the input until there is no more: 1149 | else 1150 | yyparse(); 1151 | fclose(fout); 1152 | printf("Finished\n"); 1153 | } 1154 | 1155 | void yyerror(const char *s) { 1156 | fprintf(fout, "**Error: Line %d near token '%s' --> Message: %s **\n", yylineno,yytext ,s); 1157 | printf("**Error: Line %d near token '%s' --> Message: %s **\n", yylineno,yytext, s); 1158 | // might as well halt now: 1159 | //exit(-1); 1160 | } 1161 | -------------------------------------------------------------------------------- /statement.txt: -------------------------------------------------------------------------------- 1 | برنامه جمله 2 | // این برنامه برای آزمایش پیاده‌سازی بخش جمله‌ها طراحی شده است 3 | // و هیچ ارزش دیگر ندارد :) 4 | 5 | صحیح اصلی () { 6 | صحیح کنترلگر = ۱۰؛ 7 | صحیح مقدار = ۱؛ 8 | 9 | // این تکه کد باید مقدار فاکتوریل کنترلگر را در متغیر مقدار ذخیره کند :) 10 | وقتی (درست) { 11 | اگر کنترلگر < ۰ آنگاه بشکن؛ 12 | وگرنه اگر کنترلگر == ۱ آنگاه {} 13 | وگرنه اگر کنترلگر > ۰ آنگاه { 14 | مقدار *= کنترلگر؛ 15 | } 16 | کنترلگر--؛ 17 | } 18 | 19 | // ماشین حساب :) 20 | { 21 | // ۱: جمع 22 | // ۲: تفریق 23 | // ۳: توان 24 | 25 | صحیح عملگر = ۱؛ 26 | اعشاری اول = ۲.۵؛ 27 | صحیح دوم = ۴؛ 28 | {} 29 | 30 | کلید (عملگر) 31 | حالت ۱: 32 | { 33 | اول += دوم؛ 34 | بشکن؛ 35 | }؛ 36 | حالت ۲: 37 | { 38 | اول = اول - دوم؛ 39 | بشکن؛ 40 | }؛ 41 | حالت ۳: 42 | { 43 | صحیح شمارنده = ۱؛ 44 | اعشاری اولیه = اول؛ 45 | وقتی (شمارنده < دوم) { 46 | اول *= اولیه؛ 47 | } 48 | }؛ 49 | پیشفرض: 50 | اول = ۰؛ 51 | تمام 52 | } 53 | 54 | // آرایه و تصادفی! 55 | { 56 | صحیح آرایه[۳]؛ 57 | صحیح ببینیم؛ 58 | 59 | آرایه[۱] = ۱۰؛ 60 | آرایه[۲] = ۲۰؛ 61 | آرایه[۳] = ۳۰؛ 62 | ببینیم = *آرایه؛ 63 | ببینیم = ؟آرایه؛ 64 | ببینیم = ؟آرایه؛ 65 | ببینیم = ؟آرایه؛ 66 | ببینیم = ؟آرایه؛ 67 | ببینیم = ؟آرایه؛ 68 | ببینیم = ؟آرایه؛ 69 | ببینیم = ؟آرایه؛ 70 | ببینیم = ؟آرایه؛ 71 | ببینیم = ؟آرایه؛ 72 | ببینیم = ؟آرایه؛ 73 | ببینیم = ؟آرایه؛ 74 | آرایه[۲] += آرایه[۳] - ۲۹ + درست و ۱۲ + آرایه[۲]؛ 75 | 76 | ببینیم = ؟۳؛ 77 | ببینیم = ؟۳؛ 78 | ببینیم = ؟۳؛ 79 | ببینیم = ؟۳؛ 80 | ببینیم = ؟۳؛ 81 | ببینیم = ؟۳؛ 82 | ببینیم = ؟۳؛ 83 | } 84 | 85 | } --------------------------------------------------------------------------------