# mini project 1 ## len.h * 新增 tokenSet ``` c typedef enum { UNKNOWN, END, ENDFILE, INT, ID, ADDSUB, MULDIV, ASSIGN, ADDSUB_ASSIGN, INCDEC, AND, OR, XOR, LPAREN, RPAREN } TokenSet; ``` ## len.c * getToken 負責拿到當前的 Token * 協助之後判斷 expr 語法 找出 if match(Token) ``` c TokenSet getToken(void) { int i = 0; char c = '\0'; while ((c = fgetc(stdin)) == ' ' || c == '\t'); if (isdigit(c)) { lexeme[0] = c; c = fgetc(stdin); i = 1; while (isdigit(c) && i < MAXLEN) { lexeme[i] = c; ++i; c = fgetc(stdin); } ungetc(c, stdin); lexeme[i] = '\0'; return INT; } else if (c == '+' || c == '-') { lexeme[0] = c; lexeme[1] = '\0'; c = fgetc(stdin); if(c == '+' || c == '-'){ lexeme[1] = c; lexeme[2] = '\0'; return INCDEC; } else if(c == '='){ lexeme[1] = c; lexeme[2] = '\0'; return ADDSUB_ASSIGN; } ungetc(c, stdin); return ADDSUB; } else if (c == '*' || c == '/') { lexeme[0] = c; lexeme[1] = '\0'; return MULDIV; } else if (c == '\n') { lexeme[0] = '\0'; return END; } else if (c == '=') { strcpy(lexeme, "="); return ASSIGN; } else if (c == '(') { strcpy(lexeme, "("); return LPAREN; } else if (c == ')') { strcpy(lexeme, ")"); return RPAREN; } else if(c == '&'){ strcpy(lexeme, "&"); return AND; } else if(c == '|'){ strcpy(lexeme, "|"); return OR; } else if(c == '^'){ strcpy(lexeme, "^"); return XOR; } else if (isalpha(c) || c == '_') { lexeme[0] = c; int i = 1; c = fgetc(stdin); while(isalnum(c) || c == '_' && i < MAXLEN-1){ lexeme[i++] = c; c = fgetc(stdin); } ungetc(c, stdin); lexeme[i] = '\0'; return ID; } else if (c == EOF) { return ENDFILE; } else { return UNKNOWN; } } ``` ## paser.h * 根據語法創建語法樹的函式 ``` c // statement := ENDFILE | END | assign_expr END // assign_expr := ID ASSIGN assign_expr | ID ADDSUB_ASSIGN assign_expr | or_expr // or_expr := xor_expr or_expr_tail // or_expr_tail := OR xor_expr or_expr_tail | NiL // xor_expr := and_expr xor_expr_tail // xor_expr_tail := XOR and_expr xor_expr_tail | NiL // and_expr := addsub_expr and_expr_tail // and_expr_tail := AND addsub_expr and_expr_tail | NiL // addsub_expr := muldiv_expr addsub_expr_tail // addsub_expr_tail := ADDSUB muldiv_expr addsub_expr_tail | NiL // muldiv_expr := unary_expr muldiv_expr_tail // muldiv_expr_tail := MULDIV unary_expr muldiv_expr_tail | NiL // unary_expr := ADDSUB unary_expr | factor // factor := INT | ID | INCDEC ID | LPAREN assign_expr RPAREN extern void statement(); extern BTNode *assign_expr(); extern BTNode *or_expr(); extern BTNode *or_expr_tail(BTNode *left); extern BTNode *xor_expr(); extern BTNode *xor_expr_tail(BTNode *left); extern BTNode *and_expr(); extern BTNode *and_expr_tail(BTNode *left); extern BTNode *addsub_expr(); extern BTNode *addsub_expr_tail(BTNode *left); extern BTNode *muldiv_expr(); extern BTNode *muldiv_expr_tail(BTNode *left); extern BTNode *unary_expr(); extern BTNode *factor(); ``` ## paser.c * getval 負責找到該 varible 的值 沒找到 error(NOTFOUND) * setval 負責設定新的 varible 的值或者是更新 varible 的值 (不動) :::warning assign_expr 要先取or_expr 再判斷 ID 若先找 ID advance() 之後會getToken到下一個 若不是 = 或 +=,-= 就會出錯 (get之後就沒辦法往回) ::: ``` c int getval(char *str) { int i = 0; int found = 0; for (i = 0; i < sbcount; i++) if (strcmp(str, table[i].name) == 0){ found = 1; printf("MOV r%d [%d]\n", r_cnt++, i*4); return table[i].val; } if (sbcount >= TBLSIZE){ error(RUNOUT); } if(!found){ error(NOTFOUND); } return 0; } int setval(char *str, int val) { int i = 0; for (i = 0; i < sbcount; i++) { if (strcmp(str, table[i].name) == 0) { table[i].val = val; return val; } } if (sbcount >= TBLSIZE){ error(RUNOUT); } strcpy(table[sbcount].name, str); table[sbcount].val = val; sbcount++; return val; } void statement(){ if(match(ENDFILE)){ printf("MOV r0 [0]\n"); printf("MOV r1 [4]\n"); printf("MOV r2 [8]\n"); printf("EXIT 0\n"); exit(0); } else if(match(END)){ advance(); } else{ BTNode *retp = assign_expr(); if(match(END)){ evaluateTree(retp); freeTree(retp); advance(); } else{ error(SYNTAXERR); } } } // assign_expr := ID ASSIGN assign_expr | ID ADDSUB_ASSIGN assign_expr | or_expr BTNode *assign_expr(){ BTNode *retp = NULL, *left = or_expr(); if(left->data == ID){ if(match(ASSIGN)){ retp = makeNode(ASSIGN, getLexeme()); advance(); retp->left = left; retp->right = assign_expr(); return retp; } else if(match(ADDSUB_ASSIGN)){ retp = makeNode(ADDSUB_ASSIGN, getLexeme()); advance(); retp->left = left; retp->right = assign_expr(); return retp; } } return left; } // or_expr := xor_expr or_expr_tail BTNode *or_expr(){ BTNode *node = xor_expr(); return or_expr_tail(node); } // or_expr_tail := OR xor_expr or_expr_tail | NiL BTNode *or_expr_tail(BTNode *left){ BTNode *node = NULL; if(match(OR)){ node = makeNode(OR, getLexeme()); advance(); node->left = left; node->right = xor_expr(); return or_expr_tail(node); } else{ return left; } } // xor_expr := and_expr xor_expr_tail BTNode *xor_expr(){ BTNode *node = and_expr(); return xor_expr_tail(node); } // xor_expr_tail := XOR and_expr xor_expr_tail | NiL BTNode *xor_expr_tail(BTNode *left){ BTNode *node = NULL; if(match(XOR)){ node = makeNode(XOR, getLexeme()); advance(); node->left = left; node->right = and_expr(); return xor_expr_tail(node); } else{ return left; } } // and_expr := addsub_expr and_expr_tail BTNode *and_expr(){ BTNode *node = addsub_expr(); return and_expr_tail(node); } // and_expr_tail := AND addsub_expr and_expr_tail | NiL BTNode *and_expr_tail(BTNode *left){ BTNode *node = NULL; if(match(AND)){ node = makeNode(AND, getLexeme()); advance(); node->left = left; node->right = addsub_expr(); return and_expr_tail(node); } else{ return left; } } // addsub_expr := muldiv_expr addsub_expr_tail BTNode *addsub_expr(){ BTNode *node = muldiv_expr(); return addsub_expr_tail(node); } // addsub_expr_tail := ADDSUB muldiv_expr addsub_expr_tail | NiL BTNode *addsub_expr_tail(BTNode *left){ BTNode *node = NULL; if(match(ADDSUB)){ node = makeNode(ADDSUB, getLexeme()); advance(); node->left = left; node->right = muldiv_expr(); return addsub_expr_tail(node); } else{ return left; } } // muldiv_expr := unary_expr muldiv_expr_tail BTNode *muldiv_expr(){ BTNode *node = unary_expr(); return muldiv_expr_tail(node); } // muldiv_expr_tail := MULDIV unary_expr muldiv_expr_tail | NiL BTNode *muldiv_expr_tail(BTNode *left){ BTNode *node = NULL; if(match(MULDIV)){ node = makeNode(MULDIV, getLexeme()); advance(); node->left = left; node->right = unary_expr(); return muldiv_expr_tail(node); } else{ return left; } } // unary_expr := ADDSUB unary_expr | factor BTNode *unary_expr(){ BTNode *node = NULL; if(match(ADDSUB)){ node = makeNode(ADDSUB, getLexeme()); advance(); node->left = makeNode(INT, "0"); node->right = unary_expr(); return node; } else{ node = factor(); return node; } } // factor := INT | ID | INCDEC ID | LPAREN assign_expr RPAREN BTNode *factor(){ BTNode *node = NULL; if(match(INT)){ node = makeNode(INT, getLexeme()); advance(); } else if(match(ID)){ node = makeNode(ID, getLexeme()); advance(); } else if(match(INCDEC)){ node = makeNode(INCDEC, getLexeme()); advance(); if(match(ID)){ node->left = makeNode(ID, getLexeme()); advance(); } else{ error(NOTNUMID); } } else if(match(LPAREN)){ advance(); node = assign_expr(); if(match(RPAREN)){ advance(); } else{ error(MISPAREN); } } else{ error(NOTNUMID); } return node; } ``` ## codeGen.h * 新增 r_cnt, pos_cnt, find_pos_cnt, findVar * r_cnt 計算當下的 r 是第幾個 * pos_cnt 計算 varible 的位置 (第幾個 * 4) * find_pos_cnt 找到該 varible 是第幾個 (x:0 y:1 z:2...) * findVar 找 DIV 右邊是否至少有一個 varible ``` c // Evaluate the syntax tree int evaluateTree(BTNode *root); // Print the syntax tree in prefix void printPrefix(BTNode *root); int find_pos_cnt(char *name); int findVar(BTNode *root); int r_cnt; int pos_cnt; ``` ## assembly code 概念 :::info 遇到 INT, iD 時 register 會 ++ 做 operation 的時候 丟棄右子樹的 register 所以 register --- ::: * basic ![image](https://hackmd.io/_uploads/HkDK7Aykgx.png) * advance ![image](https://hackmd.io/_uploads/ryuy7F1Jgl.png) ## codeGen.c * 實作 assembly code * 遇到 ID 時的 r_cnt++ 我寫在 getval裡面 ``` c int find_pos_cnt(char *name){ int i; pos_cnt = 0; for(i=0; i<sbcount; i++){ if(strcmp(name, table[i].name) == 0) return i; } error(NOTFOUND); } int findVar(BTNode *root){ if(root == NULL) return 0; else if(root->data == ID) return 1; else if(findVar(root->left)) return 1; else if(findVar(root->right)) return 1; else return 0; } int evaluateTree(BTNode *root) { int retval = 0, lv = 0, rv = 0; if (root != NULL) { switch (root->data) { case ID: retval = getval(root->lexeme); break; case INT: retval = atoi(root->lexeme); printf("MOV r%d %d\n", r_cnt++, retval); break; case ASSIGN: // x = 3 rv = evaluateTree(root->right); retval = setval(root->left->lexeme, rv); if(root->right->data == ASSIGN || root->right->data == ADDSUB_ASSIGN || root->right->data == INCDEC){ pos_cnt = find_pos_cnt(root->right->left->lexeme); printf("MOV r%d [%d]\n", r_cnt++, pos_cnt*4); } pos_cnt = find_pos_cnt(root->left->lexeme); printf("MOV [%d] r%d\n", pos_cnt*4, r_cnt-1); r_cnt--; break; case ADDSUB_ASSIGN: // x += 3 lv = getval(root->left->lexeme); rv = evaluateTree(root->right); if(root->right->data == ASSIGN || root->right->data == ADDSUB_ASSIGN || root->right->data == INCDEC){ pos_cnt = find_pos_cnt(root->right->left->lexeme); printf("MOV r%d [%d]\n", r_cnt++, pos_cnt*4); } if(strcmp(root->lexeme, "+=") == 0){ lv += rv; retval = setval(root->left->lexeme, lv); printf("ADD r%d r%d\n", r_cnt-2, r_cnt-1); r_cnt--; } else if(strcmp(root->lexeme, "-=") == 0){ lv -= rv; retval = setval(root->left->lexeme, lv); printf("SUB r%d r%d\n", r_cnt-2, r_cnt-1); r_cnt--; } pos_cnt = find_pos_cnt(root->left->lexeme); printf("MOV [%d] r%d\n", pos_cnt*4, r_cnt-1); r_cnt--; break; case INCDEC: // ++x lv = getval(root->left->lexeme); printf("MOV r%d 1\n", r_cnt); if(strcmp(root->lexeme, "++") == 0){ lv++; retval = setval(root->left->lexeme, lv); printf("ADD r%d r%d\n", r_cnt-1, r_cnt); r_cnt--; } else if(strcmp(root->lexeme, "--") == 0){ lv--; retval = setval(root->left->lexeme, lv); printf("SUB r%d r%d\n", r_cnt-1, r_cnt); r_cnt--; } pos_cnt = find_pos_cnt(root->left->lexeme); printf("MOV [%d] r%d\n", pos_cnt*4, r_cnt); break; case ADDSUB: // x + 3 case MULDIV: case AND: case OR: case XOR: lv = evaluateTree(root->left); rv = evaluateTree(root->right); if(root->left->data == ASSIGN || root->left->data == ADDSUB_ASSIGN || root->left->data == INCDEC){ pos_cnt = find_pos_cnt(root->left->left->lexeme); printf("MOV r%d [%d]\n", r_cnt++, pos_cnt*4); } if(root->right->data == ASSIGN || root->right->data == ADDSUB_ASSIGN || root->right->data == INCDEC){ pos_cnt = find_pos_cnt(root->right->left->lexeme); printf("MOV r%d [%d]\n", r_cnt++, pos_cnt*4); } if(strcmp(root->lexeme, "+") == 0){ retval = lv + rv; printf("ADD r%d r%d\n", r_cnt-2, r_cnt-1); r_cnt--; } else if(strcmp(root->lexeme, "-") == 0){ retval = lv - rv; printf("SUB r%d r%d\n", r_cnt-2, r_cnt-1); r_cnt--; } else if(strcmp(root->lexeme, "*") == 0){ retval = lv * rv; printf("MUL r%d r%d\n", r_cnt-2, r_cnt-1); r_cnt--; } else if(strcmp(root->lexeme, "/") == 0){ if(rv == 0 && findVar(root) == 0) error(DIVZERO); retval = 0; printf("DIV r%d r%d\n", r_cnt-2, r_cnt-1); r_cnt--; } else if(strcmp(root->lexeme, "&") == 0){ retval = lv & rv; printf("AND r%d r%d\n", r_cnt-2, r_cnt-1); r_cnt--; } else if(strcmp(root->lexeme, "|") == 0){ retval = lv | rv; printf("OR r%d r%d\n", r_cnt-2, r_cnt-1); r_cnt--; } else if(strcmp(root->lexeme, "^") == 0){ retval = lv ^ rv; printf("XOR r%d r%d\n", r_cnt-2, r_cnt-1); r_cnt--; } break; default: retval = 0; } } return retval; } ``` ## AC_merge_code.c ``` c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> // for lex #define MAXLEN 256 // Token types typedef enum { UNKNOWN, END, ENDFILE, INT, ID, ADDSUB, MULDIV, ASSIGN, ADDSUB_ASSIGN, INCDEC, AND, OR, XOR, LPAREN, RPAREN } TokenSet; TokenSet getToken(void); TokenSet curToken = UNKNOWN; char lexeme[MAXLEN]; // Test if a token matches the current token int match(TokenSet token); // Get the next token void advance(void); // Get the lexeme of the current token char *getLexeme(void); // for parser #define TBLSIZE 64 // Set PRINTERR to 1 to print error message while calling error() // Make sure you set PRINTERR to 0 before you submit your code #define PRINTERR 1 // Call this macro to print error message and exit the program // This will also print where you called it in your program #define error(errorNum) { \ if (PRINTERR) \ fprintf(stderr, "error() called at %s:%d: ", __FILE__, __LINE__); \ err(errorNum); \ } // Error types typedef enum { UNDEFINED, MISPAREN, NOTNUMID, NOTFOUND, RUNOUT, NOTLVAL, DIVZERO, SYNTAXERR } ErrorType; // Structure of the symbol table typedef struct { int val; char name[MAXLEN]; } Symbol; // Structure of a tree node typedef struct _Node { TokenSet data; int val; char lexeme[MAXLEN]; struct _Node *left; struct _Node *right; } BTNode; int sbcount = 0; Symbol table[TBLSIZE]; // Initialize the symbol table with builtin variables void initTable(void); // Get the value of a variable int getval(char *str); // Set the value of a variable int setval(char *str, int val); // Make a new node according to token type and lexeme BTNode *makeNode(TokenSet tok, const char *lexe); // Free the syntax tree void freeTree(BTNode *root); extern void statement(); extern BTNode *assign_expr(); extern BTNode *or_expr(); extern BTNode *or_expr_tail(BTNode *left); extern BTNode *xor_expr(); extern BTNode *xor_expr_tail(BTNode *left); extern BTNode *and_expr(); extern BTNode *and_expr_tail(BTNode *left); extern BTNode *addsub_expr(); extern BTNode *addsub_expr_tail(BTNode *left); extern BTNode *muldiv_expr(); extern BTNode *muldiv_expr_tail(BTNode *left); extern BTNode *unary_expr(); extern BTNode *factor(); // Print error message and exit the program void err(ErrorType errorNum); // for codeGen // Evaluate the syntax tree int evaluateTree(BTNode *root); // Print the syntax tree in prefix void printPrefix(BTNode *root); int find_pos_cnt(char *name); int findVar(BTNode *root); int r_cnt; int pos_cnt; /*============================================================================================ lex implementation ============================================================================================*/ TokenSet getToken(void) { int i = 0; char c = '\0'; while ((c = fgetc(stdin)) == ' ' || c == '\t'); if (isdigit(c)) { lexeme[0] = c; c = fgetc(stdin); i = 1; while (isdigit(c) && i < MAXLEN) { lexeme[i] = c; ++i; c = fgetc(stdin); } ungetc(c, stdin); lexeme[i] = '\0'; return INT; } else if (c == '+' || c == '-') { lexeme[0] = c; lexeme[1] = '\0'; c = fgetc(stdin); if(c == '+' || c == '-'){ lexeme[1] = c; lexeme[2] = '\0'; return INCDEC; } else if(c == '='){ lexeme[1] = c; lexeme[2] = '\0'; return ADDSUB_ASSIGN; } ungetc(c, stdin); return ADDSUB; } else if (c == '*' || c == '/') { lexeme[0] = c; lexeme[1] = '\0'; return MULDIV; } else if (c == '\n') { lexeme[0] = '\0'; return END; } else if (c == '=') { strcpy(lexeme, "="); return ASSIGN; } else if (c == '(') { strcpy(lexeme, "("); return LPAREN; } else if (c == ')') { strcpy(lexeme, ")"); return RPAREN; } else if(c == '&'){ strcpy(lexeme, "&"); return AND; } else if(c == '|'){ strcpy(lexeme, "|"); return OR; } else if(c == '^'){ strcpy(lexeme, "^"); return XOR; } else if (isalpha(c) || c == '_') { lexeme[0] = c; int i = 1; c = fgetc(stdin); while(isalnum(c) || c == '_' && i < MAXLEN-1){ lexeme[i++] = c; c = fgetc(stdin); } ungetc(c, stdin); lexeme[i] = '\0'; return ID; } else if (c == EOF) { return ENDFILE; } else { return UNKNOWN; } } void advance(void) { curToken = getToken(); } int match(TokenSet token) { if (curToken == UNKNOWN) advance(); return token == curToken; } char *getLexeme(void) { return lexeme; } /*============================================================================================ parser implementation ============================================================================================*/ void initTable(void) { strcpy(table[0].name, "x"); table[0].val = 0; strcpy(table[1].name, "y"); table[1].val = 0; strcpy(table[2].name, "z"); table[2].val = 0; sbcount = 3; } int getval(char *str) { int i = 0; int found = 0; for (i = 0; i < sbcount; i++){ if (strcmp(str, table[i].name) == 0){ found = 1; printf("MOV r%d [%d]\n", r_cnt++, i*4); return table[i].val; } } if (sbcount >= TBLSIZE) error(RUNOUT); //printf("%s\n", table[0].name); if(!found) error(NOTFOUND); return 0; } int setval(char *str, int val) { int i = 0; for (i = 0; i < sbcount; i++) { if (strcmp(str, table[i].name) == 0) { table[i].val = val; return val; } } if (sbcount >= TBLSIZE) error(RUNOUT); strcpy(table[sbcount].name, str); table[sbcount].val = val; sbcount++; return val; } BTNode *makeNode(TokenSet tok, const char *lexe) { BTNode *node = (BTNode*)malloc(sizeof(BTNode)); strcpy(node->lexeme, lexe); node->data = tok; node->val = 0; node->left = NULL; node->right = NULL; return node; } void freeTree(BTNode *root) { if (root != NULL) { freeTree(root->left); freeTree(root->right); free(root); } } void statement(){ if(match(ENDFILE)){ printf("MOV r0 [0]\n"); printf("MOV r1 [4]\n"); printf("MOV r2 [8]\n"); printf("EXIT 0\n"); exit(0); } else if(match(END)){ advance(); } else{ BTNode *retp = assign_expr(); if(match(END)){ evaluateTree(retp); freeTree(retp); advance(); } else{ error(SYNTAXERR); } } } // assign_expr := ID ASSIGN assign_expr | ID ADDSUB_ASSIGN assign_expr | or_expr BTNode *assign_expr(){ BTNode *retp = NULL, *left = or_expr(); if(left->data == ID){ if(match(ASSIGN)){ retp = makeNode(ASSIGN, getLexeme()); advance(); retp->left = left; retp->right = assign_expr(); return retp; } else if(match(ADDSUB_ASSIGN)){ retp = makeNode(ADDSUB_ASSIGN, getLexeme()); advance(); retp->left = left; retp->right = assign_expr(); return retp; } } return left; } // or_expr := xor_expr or_expr_tail BTNode *or_expr(){ BTNode *node = xor_expr(); return or_expr_tail(node); } // or_expr_tail := OR xor_expr or_expr_tail | NiL BTNode *or_expr_tail(BTNode *left){ BTNode *node = NULL; if(match(OR)){ node = makeNode(OR, getLexeme()); advance(); node->left = left; node->right = xor_expr(); return or_expr_tail(node); } else{ return left; } } // xor_expr := and_expr xor_expr_tail BTNode *xor_expr(){ BTNode *node = and_expr(); return xor_expr_tail(node); } // xor_expr_tail := XOR and_expr xor_expr_tail | NiL BTNode *xor_expr_tail(BTNode *left){ BTNode *node = NULL; if(match(XOR)){ node = makeNode(XOR, getLexeme()); advance(); node->left = left; node->right = and_expr(); return xor_expr_tail(node); } else{ return left; } } // and_expr := addsub_expr and_expr_tail BTNode *and_expr(){ BTNode *node = addsub_expr(); return and_expr_tail(node); } // and_expr_tail := AND addsub_expr and_expr_tail | NiL BTNode *and_expr_tail(BTNode *left){ BTNode *node = NULL; if(match(AND)){ node = makeNode(AND, getLexeme()); advance(); node->left = left; node->right = addsub_expr(); return and_expr_tail(node); } else{ return left; } } // addsub_expr := muldiv_expr addsub_expr_tail BTNode *addsub_expr(){ BTNode *node = muldiv_expr(); return addsub_expr_tail(node); } // addsub_expr_tail := ADDSUB muldiv_expr addsub_expr_tail | NiL BTNode *addsub_expr_tail(BTNode *left){ BTNode *node = NULL; if(match(ADDSUB)){ node = makeNode(ADDSUB, getLexeme()); advance(); node->left = left; node->right = muldiv_expr(); return addsub_expr_tail(node); } else{ return left; } } // muldiv_expr := unary_expr muldiv_expr_tail BTNode *muldiv_expr(){ BTNode *node = unary_expr(); return muldiv_expr_tail(node); } // muldiv_expr_tail := MULDIV unary_expr muldiv_expr_tail | NiL BTNode *muldiv_expr_tail(BTNode *left){ BTNode *node = NULL; if(match(MULDIV)){ node = makeNode(MULDIV, getLexeme()); advance(); node->left = left; node->right = unary_expr(); return muldiv_expr_tail(node); } else{ return left; } } // unary_expr := ADDSUB unary_expr | factor BTNode *unary_expr(){ BTNode *node = NULL; if(match(ADDSUB)){ node = makeNode(ADDSUB, getLexeme()); advance(); node->left = makeNode(INT, "0"); node->right = unary_expr(); return node; } else{ node = factor(); return node; } } // factor := INT | ID | INCDEC ID | LPAREN assign_expr RPAREN BTNode *factor(){ BTNode *node = NULL; if(match(INT)){ node = makeNode(INT, getLexeme()); advance(); } else if(match(ID)){ node = makeNode(ID, getLexeme()); advance(); } else if(match(INCDEC)){ node = makeNode(INCDEC, getLexeme()); advance(); if(match(ID)){ node->left = makeNode(ID, getLexeme()); advance(); } else{ error(NOTNUMID); } } else if(match(LPAREN)){ advance(); node = assign_expr(); if(match(RPAREN)){ advance(); } else{ error(MISPAREN); } } else{ error(NOTNUMID); } return node; } void err(ErrorType errorNum) { if (PRINTERR) { fprintf(stderr, "error: "); switch (errorNum) { case MISPAREN: fprintf(stderr, "mismatched parenthesis\n"); break; case NOTNUMID: fprintf(stderr, "number or identifier expected\n"); break; case NOTFOUND: fprintf(stderr, "variable not defined\n"); break; case RUNOUT: fprintf(stderr, "out of memory\n"); break; case NOTLVAL: fprintf(stderr, "lvalue required as an operand\n"); break; case DIVZERO: fprintf(stderr, "divide by constant zero\n"); break; case SYNTAXERR: fprintf(stderr, "syntax error\n"); break; default: fprintf(stderr, "undefined error\n"); break; } printf("EXIT 1\n"); } exit(0); } /*============================================================================================ codeGen implementation ============================================================================================*/ int find_pos_cnt(char *name){ for(int i=0; i<sbcount; i++){ if(strcmp(name, table[i].name) == 0) return i; } //error(NOTFOUND); } int findVar(BTNode *root){ if(root == NULL) return 0; if(root->data == ID) return 1; if(findVar(root->left)) return 1; if(findVar(root->right)) return 1; return 0; } int evaluateTree(BTNode *root) { int retval = 0, lv = 0, rv = 0; if (root != NULL) { switch (root->data) { case ID: retval = getval(root->lexeme); break; case INT: retval = atoi(root->lexeme); printf("MOV r%d %d\n", r_cnt++, retval); break; case ASSIGN: // x = 3 rv = evaluateTree(root->right); retval = setval(root->left->lexeme, rv); if(root->right->data == ASSIGN || root->right->data == ADDSUB_ASSIGN || root->right->data == INCDEC){ pos_cnt = find_pos_cnt(root->right->left->lexeme); printf("MOV r%d [%d]\n", r_cnt++, pos_cnt*4); } pos_cnt = find_pos_cnt(root->left->lexeme); printf("MOV [%d] r%d\n", pos_cnt*4, r_cnt-1); r_cnt--; break; case ADDSUB_ASSIGN: // x += 3 lv = getval(root->left->lexeme); rv = evaluateTree(root->right); if(root->right->data == ASSIGN || root->right->data == ADDSUB_ASSIGN || root->right->data == INCDEC){ pos_cnt = find_pos_cnt(root->right->left->lexeme); printf("MOV r%d [%d]\n", r_cnt++, pos_cnt*4); } if(strcmp(root->lexeme, "+=") == 0){ lv += rv; retval = setval(root->left->lexeme, lv); printf("ADD r%d r%d\n", r_cnt-2, r_cnt-1); r_cnt--; } else if(strcmp(root->lexeme, "-=") == 0){ lv -= rv; retval = setval(root->left->lexeme, lv); printf("SUB r%d r%d\n", r_cnt-2, r_cnt-1); r_cnt--; } pos_cnt = find_pos_cnt(root->left->lexeme); printf("MOV [%d] r%d\n", pos_cnt*4, r_cnt-1); r_cnt--; break; case INCDEC: // ++x lv = getval(root->left->lexeme); printf("MOV r%d 1\n", r_cnt); if(strcmp(root->lexeme, "++") == 0){ lv++; retval = setval(root->left->lexeme, lv); printf("ADD r%d r%d\n", r_cnt-1, r_cnt); r_cnt--; } else if(strcmp(root->lexeme, "--") == 0){ lv--; retval = setval(root->left->lexeme, lv); printf("SUB r%d r%d\n", r_cnt-1, r_cnt); r_cnt--; } pos_cnt = find_pos_cnt(root->left->lexeme); printf("MOV [%d] r%d\n", pos_cnt*4, r_cnt); break; case ADDSUB: // x + 3 case MULDIV: case AND: case OR: case XOR: lv = evaluateTree(root->left); rv = evaluateTree(root->right); if(root->left->data == ASSIGN || root->left->data == ADDSUB_ASSIGN || root->left->data == INCDEC){ pos_cnt = find_pos_cnt(root->left->left->lexeme); printf("MOV r%d [%d]\n", r_cnt++, pos_cnt*4); } if(root->right->data == ASSIGN || root->right->data == ADDSUB_ASSIGN || root->right->data == INCDEC){ pos_cnt = find_pos_cnt(root->right->left->lexeme); printf("MOV r%d [%d]\n", r_cnt++, pos_cnt*4); } if(strcmp(root->lexeme, "+") == 0){ retval = lv + rv; printf("ADD r%d r%d\n", r_cnt-2, r_cnt-1); r_cnt--; } else if(strcmp(root->lexeme, "-") == 0){ retval = lv - rv; printf("SUB r%d r%d\n", r_cnt-2, r_cnt-1); r_cnt--; } else if(strcmp(root->lexeme, "*") == 0){ retval = lv * rv; printf("MUL r%d r%d\n", r_cnt-2, r_cnt-1); r_cnt--; } else if(strcmp(root->lexeme, "/") == 0){ if(rv == 0 && findVar(root) == 0) error(DIVZERO); retval = 0; printf("DIV r%d r%d\n", r_cnt-2, r_cnt-1); r_cnt--; } else if(strcmp(root->lexeme, "&") == 0){ retval = lv & rv; printf("AND r%d r%d\n", r_cnt-2, r_cnt-1); r_cnt--; } else if(strcmp(root->lexeme, "|") == 0){ retval = lv | rv; printf("OR r%d r%d\n", r_cnt-2, r_cnt-1); r_cnt--; } else if(strcmp(root->lexeme, "^") == 0){ retval = lv ^ rv; printf("XOR r%d r%d\n", r_cnt-2, r_cnt-1); r_cnt--; } break; default: retval = 0; } } return retval; } void printPrefix(BTNode *root) { if (root != NULL) { printf("%s ", root->lexeme); printPrefix(root->left); printPrefix(root->right); } } /*============================================================================================ main ============================================================================================*/ int main() { initTable(); //printf(">> "); while (1) { statement(); } return 0; } ``` ## 要感謝的人 1.陳廷恩 我不會就可以直接下去找他 debug 然後 expr 我們一起討論 2.許志希 assign_expr 卡爛 嘻嘻直接教我 code 點醒我 3.李君威 問 8 9 10測資錯誤的地方 果然是 ADDSUB_ASSIGN 的地方寫錯 我沒加\n 4.清大資工 大家 yoyoyooyoyoyoyooy 我超爛你們應該可以優化不少