# h1 ```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, LPAREN, RPAREN, INCDEC, OR,AND,XOR, } 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 // Error types // 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,ever; 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); BTNode *factor(void); BTNode *assign_expr(void); BTNode *or_expr(void); BTNode *xor_expr(void); BTNode *or_expr_tail(BTNode *left); BTNode *and_expr(void); BTNode *xor_expr_tail(BTNode *left); BTNode *and_expr_tail(BTNode *left); BTNode *addsub_expr(void); BTNode *addsub_expr_tail(BTNode *left); BTNode *muldiv_expr(void); BTNode *muldiv_expr_tail(BTNode *left); BTNode *unary_expr(void); /* statement := END | assign_expr END assign_expr := ID 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 | NiL 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. //finish? */ BTNode *term(void); BTNode *term_tail(BTNode *left); BTNode *expr(void); BTNode *expr_tail(BTNode *left); void printPrefix(BTNode *root); void statement(void); // Print error message and exit the program // for codeGen //remember register's position int r=-1,ok = 0, newone, flag=0; BTNode *check=NULL; // Evaluate the syntax tree void search_div(BTNode *root); void search_id(BTNode *root); int evaluate(BTNode *root); int evaluateTree(BTNode *root,int r); // Print the syntax tree in prefix /*============================================================================================ lex implementation ============================================================================================*/ TokenSet getToken(void) { int i = 0; char c = '\0', cc = '\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; cc=fgetc(stdin); if((c=='+'&&cc=='+')||(c=='-'&&cc=='-')){ lexeme[1]=c; lexeme[2]='\0'; return INCDEC; } else { ungetc(cc,stdin); lexeme[1] = '\0'; return ADDSUB; } } else if (c == '*' || c == '/') { lexeme[0] = c; lexeme[1] = '\0'; return MULDIV; } else if (c=='&'){ lexeme[0]=c; lexeme[1]='\0'; return AND; } else if (c=='^'){ lexeme[0]=c; lexeme[1]='\0'; return XOR; } else if (c=='|'){ lexeme[0]=c; lexeme[1]='\0'; return OR; } 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 (isalpha(c)) { lexeme[0] = c; c = fgetc(stdin); i = 1; while (( isalpha(c) || c=='_' ||isdigit(c) )&& i < MAXLEN) { lexeme[i] = c; ++i; 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 getid(char *str){ for(int i=0;i<sbcount;i++){ if(strcmp(str,table[i].name)==0){ return i; } } printf("EXIT 1\n"); exit(0); } int getval(char *str) { //取得ID int i = 0; for (i = 0; i < sbcount; i++){ if (strcmp(str, table[i].name) == 0) { return i*4; }//有找到的情況 } if (sbcount >= TBLSIZE) { printf("EXIT 1\n");exit(0); } strcpy(table[sbcount].name, str);//沒找到的情況 table[sbcount].val = 0; sbcount++; return sbcount*4-4; } int setval(char *str, int val) { //指派值給table 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) { printf("EXIT 1\n");exit(0); } 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); } } /* statement := END | assign_expr END assign_expr := ID 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 | NiL 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. //finish? */ //factor := INT. | ID. | INCDEC ID. | LPAREN assign_expr RPAREN. BTNode *factor(void) { BTNode *retp, *left; if (match(INT)) { retp = makeNode(INT, getLexeme()); advance(); } else if (match(ID)) { left = makeNode(ID, getLexeme()); advance(); retp=left; } else if (match(INCDEC)){ retp = makeNode(INCDEC,getLexeme()); advance(); if(match(ID)){ retp->left = makeNode(ID,getLexeme()); advance(); retp->right = makeNode(INT,"1"); } else { printf("EXIT 1\n"); exit(0); } ///////////////////////////////////// // node(maybe '+', maybe '-') // // / \ // // ID 1 // ///////////////////////////////////// } else if (match(LPAREN)) { advance(); retp = assign_expr(); if (match(RPAREN)) advance(); else{ printf("EXIT 1\n");exit(0); } } else { printf("EXIT 1\n");exit(0); } return retp; } //assign_expr := ID ASSIGN assign_expr | or_expr BTNode *assign_expr(void){ BTNode *retp,*left; retp = or_expr(); if(match(ASSIGN)&&retp->data==ID){ left = retp; retp = makeNode(ASSIGN,getLexeme()); advance(); retp->left = left; retp->right = assign_expr(); } return retp; } //or_expr := xor_expr or_expr_tail BTNode *or_expr(void){ BTNode *retp=xor_expr(); return or_expr_tail(retp); } //xor_expr := and_expr xor_expr_tail BTNode *xor_expr(void){ BTNode *retp=and_expr(); return xor_expr_tail(retp); } //or_expr_tail := OR xor_expr or_expr_tail | NiL BTNode *or_expr_tail(BTNode *left){ BTNode *retp=NULL; if(match(OR)){ retp = makeNode(OR,getLexeme()); advance(); retp->left=left; retp->right=xor_expr(); return or_expr_tail(retp); }else { return left; } } //xor_expr_tail := XOR and_expr xor_expr_tail | NiL BTNode *xor_expr_tail(BTNode *left){ BTNode *retp=NULL; if(match(XOR)){ retp = makeNode(XOR,getLexeme()); advance(); retp->left=left; retp->right=and_expr(); return xor_expr_tail(retp); } else { return left; } } //and_expr := addsub_expr and_expr_tail BTNode *and_expr(void){ BTNode *retp=addsub_expr(); return and_expr_tail(retp); } //and_expr_tail := AND addsub_expr and_expr_tail | NiL BTNode *and_expr_tail(BTNode *left){ BTNode *retp=NULL; if(match(AND)){ retp = makeNode(AND,getLexeme()); advance(); retp->left=left; retp->right=addsub_expr(); return and_expr_tail(retp); } else{ return left; } } //addsub_expr := muldiv_expr addsub_expr_tail BTNode *addsub_expr(void){ BTNode *retp=muldiv_expr(); return addsub_expr_tail(retp); } //addsub_expr_tail := ADDSUB muldiv_expr addsub_expr_tail | NiL BTNode *addsub_expr_tail(BTNode *left){ BTNode *retp=NULL; if(match(ADDSUB)){ retp = makeNode(ADDSUB,getLexeme()); advance(); retp->left=left; retp->right=muldiv_expr(); return addsub_expr_tail(retp); } else{ return left; } } //muldiv_expr := unary_expr muldiv_expr_tail BTNode *muldiv_expr(void){ BTNode *retp=unary_expr(); return muldiv_expr_tail(retp); } //muldiv_expr_tail := MULDIV unary_expr muldiv_expr_tail | NiL BTNode *muldiv_expr_tail(BTNode *left){ BTNode *retp=NULL; if(match(MULDIV)){ retp = makeNode(MULDIV,getLexeme()); advance(); retp->left=left; retp->right=unary_expr(); return muldiv_expr_tail(retp); } else{ return left; } } //unary_expr := ADDSUB unary_expr | factor BTNode *unary_expr(void){ BTNode *retp; if(match(ADDSUB)){ retp = makeNode(ADDSUB,getLexeme()); advance(); retp->left = makeNode(INT,"0"); retp->right = unary_expr(); ///////////////////////////////////// // node(maybe '+', maybe '-') // // / \ // // 0 unary_expr() // ///////////////////////////////////// } else{ retp = factor(); } return retp; } //statement := END | assign_expr END void statement(void) { BTNode *retp = NULL,*tmp; advance(); if(match(ENDFILE)){ printf("MOV r0 [0]\nMOV r1 [4]\nMOV r2 [8]\nEXIT 0\n"); exit(0); } else if (match(END)) { advance(); } else { retp = assign_expr(); if (match(END)) { //printPrefix(retp); evaluateTree(retp,0); } else { printf("EXIT 1\n"); exit(0); } } } /*============================================================================================ codeGen implementation ============================================================================================*/ //mark my idea: //if(ID):= print(MOV reg[k] ID([k])) //if(int):= print(MOV reg[k] INT([k])) //if(strcmp(root->lexeme,'+')==0) := print(ADD reg[ki] reg[kj]) //if(strcmp(root->lexeme,'-')==0) := print(SUB reg[ki] reg[kj]) //if(strcmp(root->lexeme,'*')==0) := print(MUL reg[ki] reg[kj]) //if(strcmp(root->lexeme,'/')==0) := print(DIV reg[ki] reg[kj]) //現在我需要的東西: //利用evaluateTree(root)去把東西印出來 //簡而言之,可以說是不需要把值算出來 /* void search_div(BTNode *root){ if(root!=NULL){ if(strcmp(root->lexeme,"/")==0) check = root; else search_div(root->left),search_div(root->right); } return; } void search_id(BTNode *root){ if(root!=NULL){ if(root->data == ID) ok = 1; else search_id(root->left),search_id(root->right); } return; } int evaluate(BTNode *root){ int retval = 0, lv = 0, rv = 0; if (root != NULL) { switch (root->data) { case ID: for (int i = 0; i < sbcount; i++){ if (strcmp(root->lexeme, table[i].name) == 0) retval = table[i].val; } break; case INT: retval = atoi(root->lexeme); break; case ASSIGN: rv = evaluate(root->right); retval = setval(root->left->lexeme, rv); break; case ADDSUB: case MULDIV: case OR: case XOR: case AND: case INCDEC: lv = evaluate(root->left); rv = evaluate(root->right); if (strcmp(root->lexeme, "+") == 0) {retval = lv + rv;} else if (strcmp(root->lexeme, "-") == 0) {retval = lv - rv;} else if (strcmp(root->lexeme, "*") == 0) {retval = lv * rv;} else if (strcmp(root->lexeme, "|") == 0) {retval = lv | rv;} else if (strcmp(root->lexeme, "&") == 0) {retval = lv & rv;} else if (strcmp(root->lexeme, "^") == 0) {retval = lv ^ rv;} else if (strcmp(root->lexeme, "++") == 0) {retval = lv + 1;} else if (strcmp(root->lexeme, "--") == 0) {retval = lv - 1;} else if (strcmp(root->lexeme, "/") == 0) { retval = lv / rv; } break; default: retval = 0; } } return retval; } */ int evaluateTree(BTNode *root, int r) { int retval = 0, ne, tmp, rr, ll; if (root != NULL) { switch (root->data) { case ID: //找table裡面有沒有存過root->lexeme,如果有就直接用,沒有就創一個新的 //有用過->1,沒出現過->0 //之前印過的就不印了! newone=getid(root->lexeme); ne = getval(root->lexeme); flag=1; if(r>=8){ strcpy(table[sbcount].name, "\0");//沒找到的情況 table[sbcount].val = 0; sbcount++;root->ever = sbcount*4-4; printf("MOV [%d] r%d\n",root->ever,r%8); } else root->ever = 0; printf("MOV r%d [%d]\n",r%8,ne); break; case INT: retval = atoi(root->lexeme); if(r>=8){ strcpy(table[sbcount].name, "\0");//沒找到的情況 table[sbcount].val = 0; sbcount++;root->ever = sbcount*4-4; printf("MOV [%d] r%d\n",root->ever,r%8); } else root->ever = 0; printf("MOV r%d %d\n",r%8,retval); //把root->lexeme的char值強制轉換成int break; case ASSIGN: rr = evaluateTree(root->right,r); //利用遞迴,搜尋root右邊的值 retval = setval(root->left->lexeme, rr); newone=getid(root->left->lexeme); tmp = getval(root->left->lexeme); //把左邊的值,交給右邊 root->ever = 0; printf("MOV [%d] r%d\n",tmp,r%8); break; case ADDSUB: case MULDIV: case OR: case XOR: case AND: case INCDEC: ll = evaluateTree(root->left, r); //先遞迴找左邊 if(strcmp(root->lexeme,"/")==0) flag=0; rr = evaluateTree(root->right, r+1); //再遞迴找右邊 if (strcmp(root->lexeme, "+") == 0) { printf("ADD r%d r%d\n",r%8,(r+1)%8);retval = ll + rr; if(root->right->ever != 0) printf("MOV r%d [%d]\n",(r+1)%8,root->right->ever),root->ever = root->left->ever;} else if (strcmp(root->lexeme,"++") == 0){ printf("ADD r%d r%d\n",r%8,(r+1)%8); printf("MOV [%d] r%d\n",getid(root->left->lexeme)*4,r%8); retval = ll + 1; if(root->right->ever != 0) printf("MOV r%d [%d]\n",(r+1)%8,root->right->ever),root->ever = root->left->ever;} else if (strcmp(root->lexeme, "-") == 0) { printf("SUB r%d r%d\n",r%8,(r+1)%8);retval = ll - rr; if(root->right->ever != 0) printf("MOV r%d [%d]\n",(r+1)%8,root->right->ever),root->ever = root->left->ever;} else if (strcmp(root->lexeme,"--") == 0){ printf("SUB r%d r%d\n",r%8,(r+1)%8); printf("MOV [%d] r%d\n",getid(root->left->lexeme)*4,r%8); retval = ll -1; if(root->right->ever != 0) printf("MOV r%d [%d]\n",(r+1)%8,root->right->ever),root->ever = root->left->ever;} else if (strcmp(root->lexeme, "*") == 0) { printf("MUL r%d r%d\n",r%8,(r+1)%8);retval = ll * rr; if(root->right->ever != 0) printf("MOV r%d [%d]\n",(r+1)%8,root->right->ever),root->ever = root->left->ever;} else if (strcmp(root->lexeme, "/") == 0) { if(rr==0&&!flag){printf("EXIT 1\n");exit(0);} printf("DIV r%d r%d\n",r%8,(r+1)%8); if(root->right->ever != 0) printf("MOV r%d [%d]\n",(r+1)%8,root->right->ever),root->ever = root->left->ever;} else if (strcmp(root->lexeme, "|") == 0 ){ printf("OR r%d r%d\n",r%8,(r+1)%8);retval = ll | rr; if(root->right->ever != 0) printf("MOV r%d [%d]\n",(r+1)%8,root->right->ever),root->ever = root->left->ever;} else if (strcmp(root->lexeme, "^") == 0 ){ printf("XOR r%d r%d\n",r%8,(r+1)%8);retval = ll ^ rr; if(root->right->ever != 0) printf("MOV r%d [%d]\n",(r+1)%8,root->right->ever),root->ever = root->left->ever;} else if (strcmp(root->lexeme, "&") == 0){ printf("AND r%d r%d\n",r%8,(r+1)%8);retval = ll & rr; if(root->right->ever != 0) printf("MOV r%d [%d]\n",(r+1)%8,root->right->ever),root->ever = root->left->ever;} break; default: retval = 0; break; } } return retval; } void printPrefix(BTNode *root) { if (root != NULL) { printf("%s ", root->lexeme); printPrefix(root->left); printPrefix(root->right); } } /*============================================================================================ main ============================================================================================*/ // This package is a calculator // It works like a Python interpretor // Example: // >> y = 2 // >> z = 2 // >> x = 3 * y + 4 / (2 * z) // It will print the answer of every line // You should turn it into an expression compiler // And print the assembly code according to the input // This is the grammar used in this package // You can modify it according to the spec and the slide // statement := ENDFILE | END | expr END // expr := term expr_tail // expr_tail := ADDSUB term expr_tail | NiL // term := factor term_tail // term_tail := MULDIV factor term_tail| NiL // factor := INT | ADDSUB INT | // ID | ADDSUB ID | // ID ASSIGN expr | // LPAREN expr RPAREN | // ADDSUB LPAREN expr RPAREN int main() { initTable(); while (1) { statement(); } return 0; } ```