编译原理实验,实现一个代码解析程序
来源:互联网 发布:dvd光盘修复软件 编辑:程序博客网 时间:2024/06/05 15:56
前言
本程序参考了TINY1的实现源代码,并添加了一些简单新的语法规则,最终结果是生成可阅读中间代码。部分地方没有考虑过多的容错,纯属自娱自乐。采用的语法为TINY v2的语法,老师实验课给的,自行百度。
文件读取器
头部定义一些变量
#include "FILEHANDLE.h"#include "SCAN.h"/* 定义一行能读取的最大字符数 */#define BUFLEN 256static char lineBuf[BUFLEN]; /* 储存当前行字符 */static int linepos = 0; /* 当前读取到的列的位数 */static int bufsize = 0; /* 当前行的总列数 */int lineno = 0;int EOF_flag;
接下来主要是两个函数,一个获取字符,一个回退字符
/* 获取一个字符 */int getNextChar(void){ EOF_flag = FALSE; if (!(linepos < bufsize))//判断当前行是否已经结束 { lineno++; if (fgets(lineBuf, BUFLEN - 1, source))//如果结束则读出新的一行 { //if (fprintf(listing, "%4d: %s", lineno, lineBuf)); bufsize = strlen(lineBuf); linepos = 0; return lineBuf[linepos++]; } else//读取下一行失败,说明文件到头,返回EOF标识 { EOF_flag = TRUE; return EOF; } } else return lineBuf[linepos++];//没有结束,则返回当前行的下一个字符}//回退一个字符void ungetNextChar(void){ if (!EOF_flag) linepos--;}
词法扫描器
定义状态机的状态表,和保留关键字词典
const int MAXRESERVED = 22;/* 定义能识别的所有字符 *//* 定义DFA的状态 */typedef enum{ START, INASSIGN, INCOMMENT, INNUM, INID, DONE, INCOMPARED, INSTRING}StateType;char tokenString[MAXTOKENLEN + 1];/* 定义保留字字典 */struct{ char* str; TokenType tok;} reservedWords[MAXRESERVED] = { { "true",TRUES },{ "false",FALSES },{ "or",OR },{ "and",AND },{ "not",NOT },{ "int",INT },{ "bool",BOOL },{ "string",STRING},{ "while",WHILE },{ "do",DO },{ "if",IF },{ "then",THEN },{ "else",ELSE },{ "end",END },{ "repeat",REPEAT },{ "until",UNTIL },{ "read",READ },{ "write",WRITE },{ "<",LT },{ "<=",LTEQ },{ ">",RT },{ ">=",RTEQ } };
匹配关键字词典函数,没有对应的string则认为是ID词条
static TokenType reservedLookup(char * s){ int i; for (i = 0; i < MAXRESERVED; i++) if (!strcmp(s, reservedWords[i].str)) return reservedWords[i].tok; return ID;}
编写对应的状态转移函数
static void changeBySTART(StateType& state, int& save, TokenType& currentToken, const char c) { if (isdigit(c)) { state = INNUM;//如果是数字的话,将状态置为数字态 } else if (isalpha(c)) { state = INID;//如果是字母的话,将状态置为字母态 } else if (c == ':') { state = INASSIGN;//如果是:则将状态置为赋值态 } else if ((c == '>') || (c == '<')) { state = INCOMPARED;//如果是>或者<则将状态置为比较态 } else if (c == '\'') { save = FALSE; state = INSTRING;//如果是'则将状态置为字符串态 } else if ((c == ' ') || (c == '\t') || (c == '\n')) { save = FALSE;//如果是空格,换行,制表符则跳过 } else if (c == '{') { save = FALSE; state = INCOMMENT;//如果是 { 的话,将状态置为注释态 } else { state = DONE;//剩下的是特殊标志符 switch (c) { case EOF: save = FALSE; currentToken = ENDFILE; break; case ',': currentToken = COMMA; break; case ';': currentToken = SEMI; break; case '+': currentToken = PLUS; break; case '-': currentToken = MINUS; break; case '*': currentToken = TIMES; break; case '/': currentToken = OVER; break; case '(': currentToken = LPAREN; break; case ')': currentToken = RPAREN; break; case '=': currentToken = EQ; break; case '}': currentToken = MISSLCOMMENT; break; default: break; } }}static void changeByINASSIGN(StateType& state, int& save, TokenType& currentToken, const char c) { state = DONE; if (c == '=')//如果下一个字符为=,则判断为赋值符号,否则出错 currentToken = ASSIGN; else { ungetNextChar(); save = FALSE; currentToken = MISSEQ; }}static void changeByINCOMMENT(StateType& state, int& save, TokenType& currentToken, const char c) { save = FALSE; if ((c == EOF) || (c == '\n'))//缺少右括号就换行或者结束,则报错 { state = DONE; currentToken = MISSRCOMMENT; } else if (c == '}') state = START;}static void changeByINNUM(StateType& state, int& save, TokenType& currentToken, const char c) { if (isalpha(c))//如果是字母,则报错 { save = FALSE; state = DONE; currentToken = ERRORNUM; char a = getNextChar(); while (isalpha(a) || isdigit(a)) { a = getNextChar(); } ungetNextChar(); } else if (!isdigit(c)) {//如果不是数字,则退回,标识当前为NUM ungetNextChar(); save = FALSE; state = DONE; currentToken = NUM; }}static void changeByINID(StateType& state, int& save, TokenType& currentToken, const char c) { if (!(isalpha(c) || isdigit(c))) {//如果不是字符或者数字,则退回,标识当前为ID ungetNextChar(); save = FALSE; state = DONE; currentToken = ID; }}static void changeByINCOMPARED(StateType& state, int& save, TokenType& currentToken, const char c) { if (c == '=') {//如果是=,则标识当前为ID state = DONE; currentToken = ID; } else {//否则回退标识当前为ID ungetNextChar(); save = FALSE; state = DONE; currentToken = ID; }}static void changeByINSTRING(StateType& state, int& save, TokenType& currentToken, const char c) { if (c == '\'') {//如果是’,则标识当前为STR save = FALSE; state = DONE; currentToken = STR; } else if ((c == '\n') || (c == EOF)) {//缺少‘报错 save = FALSE; state = DONE; currentToken = ERROR; }}
扫描器入口函数
TokenType getToken(void){ int tokenStringIndex = 0; TokenType currentToken; StateType state = START; int save; while (state != DONE) { char c = getNextChar(); save = TRUE; switch (state) { case START: changeBySTART(state, save, currentToken, c); break; case INASSIGN: changeByINASSIGN(state, save, currentToken, c); break; case INCOMMENT: changeByINCOMMENT(state, save, currentToken, c); break; case INNUM: changeByINNUM(state, save, currentToken, c); break; case INID: changeByINID(state, save, currentToken, c); break; case INCOMPARED: changeByINCOMPARED(state, save, currentToken, c); break; case INSTRING: changeByINSTRING(state, save, currentToken, c); break; case DONE: default: break; } if ((save) && (tokenStringIndex <= MAXTOKENLEN)) tokenString[tokenStringIndex++] = (char)c; if (state == DONE) { tokenString[tokenStringIndex] = '\0'; if (currentToken == ID) currentToken = reservedLookup(tokenString); if (currentToken == ERROR) { if (tokenStringIndex != 0) { currentToken = MISSRQUOTE; } else { currentToken = MISSLQUOTE; } } } } printf(" %d %s\n", currentToken,tokenString); printToken(currentToken, tokenString); return currentToken;}
语法解析器
匹配函数和异常输出函数
static void syntaxError(char * message){ fprintf(listing, "\n>>> "); fprintf(listing, "Syntax error at line %d: %s", lineno, message); Error = TRUE;}static void match(TokenType expected){ if (token == expected) token = getToken(); else { syntaxError("unexpected token -> "); printToken(token, tokenString); fprintf(listing, " "); }}
解析定义区语法
static void declarations(){ while ((token==INT)|| (token == BOOL) ||(token == STRING)) { match(token); do { match(ID); if (token == COMMA)match(COMMA); else break; } while (1);//逗号 match(SEMI); // 匹配分号 }}
stmt逻辑语句分析函数
//stmt-sequence -> statement [ ; stmt-sequence ]TreeNode * stmt_sequence(void){ TreeNode * t = statement(); TreeNode * p = t; while ((token != ENDFILE) && (token != END) && (token != ELSE) && (token != UNTIL)) { TreeNode * q; match(SEMI); q = statement(); if (q != NULL) { if (t == NULL) t = p = q; else /* now p cannot be NULL either */ { p->sibling = q; p = q; } } } return t;}//statement -> if-stmt | repeat-stmt | assign-stmt | read-stmt | write-stmt | while-stmtTreeNode * statement(void){ TreeNode * t = NULL; switch (token) { case IF: t = if_stmt(); break; case REPEAT: t = repeat_stmt(); break; case ID: t = assign_stmt(); break; case READ: t = read_stmt(); break; case WRITE: t = write_stmt(); break; case WHILE: t = while_stmt(); break; default: syntaxError("unexpected token -> "); printToken(token, tokenString); token = getToken(); break; } /* end case */ return t;}//if-stmt -> if logical-or-exp then stmt-sequence [else stmt-sequence] endTreeNode * if_stmt(void){ TreeNode * t = newStmtNode(IfK); match(IF); if (t != NULL) t->child[0] = log_exp(); match(THEN); if (t != NULL) t->child[1] = stmt_sequence(); if (token == ELSE) { match(ELSE); if (t != NULL) t->child[2] = stmt_sequence(); } match(END); return t;}//repeat-stm -> repeat stmt-sequence until logical-or-expTreeNode * repeat_stmt(void){ TreeNode * t = newStmtNode(RepeatK); match(REPEAT); if (t != NULL) t->child[0] = stmt_sequence(); match(UNTIL); if (t != NULL) t->child[1] = log_exp(); return t;} //assign-stmt -> identifier := logical-or-expTreeNode * assign_stmt(void){ TreeNode * t = newStmtNode(AssignK); if ((t != NULL) && (token == ID)) t->attr.name = copyString(tokenString); match(ID); match(ASSIGN); if (t != NULL) t->child[0] = log_exp(); return t;}//read-stmt -> read identifierTreeNode * read_stmt(void){ TreeNode * t = newStmtNode(ReadK); match(READ); if ((t != NULL) && (token == ID)) t->attr.name = copyString(tokenString); match(ID); return t;}//write-stmt -> write logical-or-expTreeNode * write_stmt(void){ TreeNode * t = newStmtNode(WriteK); match(WRITE); if (t != NULL) t->child[0] = log_exp(); return t;}//while-stmt -> while logical-or-exp do stmt-sequence endTreeNode * while_stmt(void){ TreeNode * t = newStmtNode(WhileK); match(WHILE); if (t != NULL) t->child[0] = log_exp(); match(DO); if (t != NULL) t->child[1] = stmt_sequence(); match(END); return t;}
exp算术语句分析函数
TreeNode * log_exp(void) { TreeNode * t = exp(); if (token == AND || token == OR) { TreeNode * p = newExpNode(OpK); if (p != NULL) { p->child[0] = t; p->attr.op = token; t = p; } match(token); if (t != NULL) t->child[1] = exp(); } return t;}TreeNode * exp(void){ TreeNode * t = simple_exp(); if ((token == LT) || (token == RT) || (token == EQ) || (token == LTEQ) || (token == RTEQ)) { TreeNode * p = newExpNode(OpK); if (p != NULL) { p->child[0] = t; p->attr.op = token; t = p; } match(token); if (t != NULL) t->child[1] = simple_exp(); } return t;}TreeNode * simple_exp(void){ TreeNode * t = term(); while ((token == PLUS) || (token == MINUS)) { TreeNode * p = newExpNode(OpK); if (p != NULL) { p->child[0] = t; p->attr.op = token; t = p; match(token); t->child[1] = term(); } } return t;}TreeNode * term(void){ TreeNode * t = factor(); while ((token == TIMES) || (token == OVER)) { TreeNode * p = newExpNode(OpK); if (p != NULL) { p->child[0] = t; p->attr.op = token; t = p; match(token); p->child[1] = factor(); } } return t;}
变量因子解析
//factor -> number | string | identifier | true | false| ( logical-or-exp )TreeNode * factor(void){ TreeNode * t = NULL; switch (token) { case NUM: t = newExpNode(ConstK); if ((t != NULL) && (token == NUM)) t->attr.val = atoi(tokenString); match(NUM); break; case ID: t = newExpNode(IdK); if ((t != NULL) && (token == ID)) t->attr.name = copyString(tokenString); match(ID); break; case TRUES: t = newExpNode(BoolK); if ((t != NULL) && (token == TRUES)) t->attr.trust = true; match(TRUES); break; case FALSES: t = newExpNode(BoolK); if ((t != NULL) && (token == FALSES)) t->attr.trust = false; match(FALSES); break; case STR: t = newExpNode(IdK); if ((t != NULL) && (token == STR)) t->attr.name = copyString(tokenString); match(STR); break; case LPAREN: match(LPAREN); t = log_exp(); match(RPAREN); break; default: syntaxError("unexpected token -> "); printToken(token, tokenString); token = getToken(); break; } return t;}
解析器入口函数
TreeNode * parse(void){ TreeNode * t; token = getToken(); declarations(); t = stmt_sequence(); if (token != ENDFILE) syntaxError("Code ends before file\n"); return t;}
中间代码生成器
前序遍历语法树,对不同的叶子节点进行输出,该部分写点有点乱,因为期末了没有时间做重复语句的优化等。将就的把语句逻辑表达了出来。
static void genStmt(TreeNode * tree) { TreeNode * p1, *p2, *p3; p1 = tree->child[0]; p2 = tree->child[1]; p3 = tree->child[2]; int tem1,tem2,tem3; switch (tree->kind.stmt) { case IfK: if (p3 != NULL) { tem1 = label++; tem2 = label++; tem3 = label++; genExp(p1, tem1,tem2); fprintf(listing, "%d) label L%d \n", linesum++, tem1); cGen(p2); fprintf(listing, "%d) goto L%d \n", linesum++, tem3); fprintf(listing, "%d) label L%d \n", linesum++, tem2); cGen(p3); fprintf(listing, "%d) label L%d \n", linesum++, tem3); } else { tem1 = label++; tem2 = label++; genExp(p1, tem1,tem2); fprintf(listing, "%d) label L%d \n", linesum++, tem1); cGen(p2); fprintf(listing, "%d) label L%d \n", linesum++, tem2); } break; case ReadK: fprintf(listing, "%d) read %s \n", linesum++, tree->attr.name); break; case WriteK: fprintf(listing, "%d) write %s \n", linesum++, p1->attr.name); break; case RepeatK: tem1 = label++; tem2 = label++; fprintf(listing, "%d) label L%d \n", linesum++, tem1); cGen(p1); genExp(p2, tem2,0); fprintf(listing, "%d) goto L%d \n", linesum++, tem1); fprintf(listing, "%d) label L%d \n", linesum++, tem2); break; case AssignK: switch (p1->kind.exp) { case OpK: genExp(p1, 0,0); fprintf(listing, "%d) %s:=%s \n", linesum++, tree->attr.name, p1->attr.name); break; break; case ConstK: fprintf(listing, "%d) %s:=%d \n", linesum++, tree->attr.name, p1->attr.val); break; case IdK: fprintf(listing, "%d) %s:=%s \n", linesum++, tree->attr.name, p1->attr.name); break; case BoolK: fprintf(listing, "%d) %s:=%d \n", linesum++, tree->attr.name, p1->attr.trust); break; default: break; } break; case WhileK: tem1 = label++; tem2 = label++; tem3 = label++; fprintf(listing, "%d) label L%d \n", linesum++, tem3); genExp(p1, tem1, tem2); //fprintf(listing, "%d) goto L%d \n", linesum++, tem2); fprintf(listing, "%d) label L%d \n", linesum++, tem1); cGen(p2); fprintf(listing, "%d) goto L%d \n", linesum++, tem3); fprintf(listing, "%d) label L%d \n", linesum++, tem2); default: break; }}static void genExp(TreeNode * tree,int sym1,int sym2) { TreeNode * p1, *p2; p1 = tree->child[0]; p2 = tree->child[1]; int tem1; switch (tree->attr.op) { case AND: tem1 = label++; genExp(p1, tem1, 0); fprintf(listing, "%d) goto L%d \n", linesum++, sym2); fprintf(listing, "%d) label L%d \n", linesum++, tem1); genExp(p2, sym1, 0); fprintf(listing, "%d) goto L%d \n", linesum++, sym2); break; case OR: genExp(p1, sym1, 0); genExp(p2, sym1, 0); fprintf(listing, "%d) goto L%d \n", linesum++, sym2); break; case LT: if (p1->kind.exp == OpK)genExp(p1, 0, 0); if (p2->kind.exp == OpK)genExp(p2, 0, 0); switch (p1->kind.exp) { case OpK: fprintf(listing, "%d) if %s<", linesum++, p1->attr.name); break; case ConstK: fprintf(listing, "%d) if %d<", linesum++, p1->attr.val); break; case IdK: fprintf(listing, "%d) if %s<", linesum++,p1->attr.name); break; default: break; } switch (p2->kind.exp) { case OpK: fprintf(listing, "%s goto L%d \n", p2->attr.name, sym1); break; case ConstK: fprintf(listing, "%d goto L%d \n", p2->attr.val, sym1); break; case IdK: fprintf(listing, "%s goto L%d \n", p2->attr.name, sym1); break; default: break; } if (sym2 != 0) { fprintf(listing, "%d) goto L%d \n", linesum++, sym2); } break; case RT: if (p1->kind.exp == OpK)genExp(p1, 0, 0); if (p2->kind.exp == OpK)genExp(p2, 0, 0); switch (p1->kind.exp) { case OpK: fprintf(listing, "%d) if %s>", linesum++, p1->attr.name); break; case ConstK: fprintf(listing, "%d) if %d>", linesum++, p1->attr.val); break; case IdK: fprintf(listing, "%d) if %s>", linesum++, p1->attr.name); break; default: break; } switch (p2->kind.exp) { case OpK: fprintf(listing, "%s goto L%d \n", p2->attr.name, sym1); break; case ConstK: fprintf(listing, "%d goto L%d \n", p2->attr.val, sym1); break; case IdK: fprintf(listing, "%s goto L%d \n", p2->attr.name, sym1); break; default: break; } if (sym2 != 0) { fprintf(listing, "%d) goto L%d \n", linesum++, sym2); } break; case EQ: if (p1->kind.exp == OpK)genExp(p1, 0, 0); if (p2->kind.exp == OpK)genExp(p2, 0, 0); switch (p1->kind.exp) { case OpK: fprintf(listing, "%d) if %s=", linesum++, p1->attr.name); break; case ConstK: fprintf(listing, "%d) if %d=", linesum++, p1->attr.val); break; case IdK: fprintf(listing, "%d) if %s=", linesum++, p1->attr.name); break; default: break; } switch (p2->kind.exp) { case OpK: fprintf(listing, "%s goto L%d \n", p2->attr.name, sym1); break; case ConstK: fprintf(listing, "%d goto L%d \n", p2->attr.val, sym1); break; case IdK: fprintf(listing, "%s goto L%d \n", p2->attr.name, sym1); break; default: break; } if (sym2 != 0) { fprintf(listing, "%d) goto L%d \n", linesum++, sym2); } break; case LTEQ: if (p1->kind.exp == OpK)genExp(p1, 0, 0); if (p2->kind.exp == OpK)genExp(p2, 0, 0); switch (p1->kind.exp) { case OpK: fprintf(listing, "%d) if %s<=", linesum++, p1->attr.name); break; case ConstK: fprintf(listing, "%d) if %d<=", linesum++, p1->attr.val); break; case IdK: fprintf(listing, "%d) if %s<=", linesum++, p1->attr.name); break; default: break; } switch (p2->kind.exp) { case OpK: fprintf(listing, "%s goto L%d \n", p2->attr.name, sym1); break; case ConstK: fprintf(listing, "%d goto L%d \n", p2->attr.val, sym1); break; case IdK: fprintf(listing, "%s goto L%d \n", p2->attr.name, sym1); break; default: break; } if (sym2 != 0) { fprintf(listing, "%d) goto L%d \n", linesum++, sym2); } break; case RTEQ: if(p1->kind.exp== OpK)genExp(p1, 0, 0); if (p2->kind.exp == OpK)genExp(p2, 0, 0); switch (p1->kind.exp) { case OpK: fprintf(listing, "%d) if %s>=", linesum++, p1->attr.name); break; case ConstK: fprintf(listing, "%d) if %d>=", linesum++, p1->attr.val); break; case IdK: fprintf(listing, "%d) if %s>=", linesum++, p1->attr.name); break; default: break; } switch (p2->kind.exp) { case OpK: fprintf(listing, "%s goto L%d \n", p2->attr.name, sym1); break; case ConstK: fprintf(listing, "%d goto L%d \n", p2->attr.val, sym1); break; case IdK: fprintf(listing, "%s goto L%d \n", p2->attr.name, sym1); break; default: break; } if (sym2 != 0) { fprintf(listing, "%d) goto L%d \n", linesum++, sym2); } break; case MINUS: tree->attr.name = (char*)malloc(5); tree->attr.name[0] = 't'; char str[3]; sprintf(str, "%d", number++); if (number >= 10) { tree->attr.name[1] = str[0]; tree->attr.name[2] = str[1]; tree->attr.name[3] = '\0'; } else { tree->attr.name[1] = str[0]; tree->attr.name[2] = '\0'; } switch (p1->kind.exp) { case OpK: genExp(p1, 0, 0); fprintf(listing, "%d) %s:=%s-", linesum++, tree->attr.name, p1->attr.name); break; case ConstK: fprintf(listing, "%d) %s:=%d-", linesum++, tree->attr.name, p1->attr.val); break; case IdK: fprintf(listing, "%d) %s:=%s-", linesum++, tree->attr.name, p1->attr.name); break; default: break; } switch (p2->kind.exp) { case OpK: genExp(p2, 0, 0); fprintf(listing, "%s \n", p2->attr.name); break; case ConstK: fprintf(listing, "%d \n", p2->attr.val); break; case IdK: fprintf(listing, "%s \n", p2->attr.name); break; default: break; } break; case PLUS: tree->attr.name = (char*)malloc(5); tree->attr.name[0] = 't'; sprintf(str, "%d", number++); if (number >= 10) { tree->attr.name[1] = str[0]; tree->attr.name[2] = str[1]; tree->attr.name[3] = '\0'; } else { tree->attr.name[1] = str[0]; tree->attr.name[2] = '\0'; } switch (p1->kind.exp) { case OpK: genExp(p1, 0, 0); fprintf(listing, "%d) %s:=%s+", linesum++, tree->attr.name, p1->attr.name); break; case ConstK: fprintf(listing, "%d) %s:=%d+", linesum++, tree->attr.name, p1->attr.val); break; case IdK: fprintf(listing, "%d) %s:=%s+", linesum++, tree->attr.name, p1->attr.name); break; default: break; } switch (p2->kind.exp) { case OpK: genExp(p2, 0, 0); fprintf(listing, "%s \n", p2->attr.name); break; case ConstK: fprintf(listing, "%d \n", p2->attr.val); break; case IdK: fprintf(listing, "%s \n", p2->attr.name); break; default: break; } break; case TIMES: tree->attr.name = (char*)malloc(5); tree->attr.name[0] = 't'; sprintf(str, "%d", number++); if (number > 10) { tree->attr.name[1] = str[0]; tree->attr.name[2] = str[1]; tree->attr.name[3] = '\0'; } else { tree->attr.name[1] = str[0]; tree->attr.name[2] = '\0'; } switch (p1->kind.exp) { case OpK: genExp(p1, 0, 0); fprintf(listing, "%d) %s:=%s*", linesum++, tree->attr.name, p1->attr.name); break; case ConstK: fprintf(listing, "%d) %s:=%d*", linesum++, tree->attr.name, p1->attr.val); break; case IdK: fprintf(listing, "%d) %s:=%s*", linesum++, tree->attr.name, p1->attr.name); break; default: break; } switch (p2->kind.exp) { case OpK: genExp(p2, 0, 0); fprintf(listing, "%s \n", p2->attr.name); break; case ConstK: fprintf(listing, "%d \n", p2->attr.val); break; case IdK: fprintf(listing, "%s \n", p2->attr.name); break; default: break; } break; case OVER: tree->attr.name = (char*)malloc(5); tree->attr.name[0] = 't'; sprintf(str, "%d", number++); if (number >= 10) { tree->attr.name[1] = str[0]; tree->attr.name[2] = str[1]; tree->attr.name[3] = '\0'; } else { tree->attr.name[1] = str[0]; tree->attr.name[2] = '\0'; } switch (p1->kind.exp) { case OpK: genExp(p1, 0, 0); fprintf(listing, "%d) %s:=%s/", linesum++, tree->attr.name,p1->attr.name); break; case ConstK: fprintf(listing, "%d) %s:=%d/", linesum++, tree->attr.name, p1->attr.val); break; case IdK: fprintf(listing, "%d) %s:=%s/", linesum++, tree->attr.name, p1->attr.name); break; default: break; } switch (p2->kind.exp) { case OpK: genExp(p2, 0, 0); fprintf(listing, "%s \n", p2->attr.name); break; case ConstK: fprintf(listing, "%d \n", p2->attr.val); break; case IdK: fprintf(listing, "%s \n", p2->attr.name); break; default: break; } break; }}static void cGen(TreeNode * tree){ if (tree != NULL) { switch (tree->nodekind) { case StmtK: genStmt(tree); break; case ExpK: genExp(tree,0,0); break; default: break; } cGen(tree->sibling); }}
生成器入口函数
void codeGen(TreeNode * syntaxTree){ cGen(syntaxTree);}
方便调试输出的工具类
新建Stmt和Exp节点函数
TreeNode * newStmtNode(StmtKind kind){ TreeNode * t = (TreeNode *)malloc(sizeof(TreeNode)); int i; if (t == NULL) fprintf(listing, "Out of memory error at line %d\n", lineno); else { for (i = 0; i<MAXCHILDREN; i++) t->child[i] = NULL; t->sibling = NULL; t->nodekind = StmtK; t->kind.stmt = kind; t->lineno = lineno; } return t;}TreeNode * newExpNode(ExpKind kind){ TreeNode * t = (TreeNode *)malloc(sizeof(TreeNode)); int i; if (t == NULL) fprintf(listing, "Out of memory error at line %d\n", lineno); else { for (i = 0; i<MAXCHILDREN; i++) t->child[i] = NULL; t->sibling = NULL; t->nodekind = ExpK; t->kind.exp = kind; t->lineno = lineno; t->type = Void; } return t;}
输出空格和字符串复制输出函数
char * copyString(char * s){ int n; char * t; if (s == NULL) return NULL; n = strlen(s) + 1; t = (char*)malloc(n); if (t == NULL) fprintf(listing, "Out of memory error at line %d\n", lineno); else strcpy(t, s); return t;}static void printSpaces(void){ int i; for (i = 0; i<indentno; i++) fprintf(listing, " ");}
输出语法树函数
void printTree(TreeNode * tree){ int i; INDENT; while (tree != NULL) { printSpaces(); if (tree->nodekind == StmtK) { switch (tree->kind.stmt) { case IfK: fprintf(listing, "If\n"); break; case RepeatK: fprintf(listing, "Repeat\n"); break; case AssignK: fprintf(listing, "Assign to: %s\n", tree->attr.name); break; case ReadK: fprintf(listing, "Read: %s\n", tree->attr.name); break; case WriteK: fprintf(listing, "Write\n"); break; case WhileK: fprintf(listing, "While\n"); break; default: fprintf(listing, "Unknown ExpNode kind\n"); break; } } else if (tree->nodekind == ExpK) { switch (tree->kind.exp) { case OpK: fprintf(listing, "Op: "); printToken(tree->attr.op, "\0"); break; case ConstK: fprintf(listing, "Const: %d\n", tree->attr.val); break; case IdK: fprintf(listing, "Id: %s\n", tree->attr.name); break; default: fprintf(listing, "Unknown ExpNode kind\n"); break; } } else fprintf(listing, "Unknown node kind\n"); for (i = 0; i<MAXCHILDREN; i++) printTree(tree->child[i]); tree = tree->sibling; } UNINDENT;}
测试主函数
using namespace std;#include"SCAN.h"#include"PARSE.h"#include"UTIL.h"#include"CGEN.h"#include"FILEHANDLE.h"#include <iostream>FILE *source;FILE *listing;int main() { char sourceName[120]; cin >> sourceName; char listingName[120]; cin >> listingName; source = fopen(sourceName,"r"); listing = fopen(listingName,"w"); codeGen(parse()); //进行中间代码生成 //printTree(parse());//输出语法树 //while (getToken() != ENDFILE);//进行词法分析 system("pause");}
阅读全文
0 0
- 编译原理实验,实现一个代码解析程序
- java程序-编译原理实验
- 编译原理实验一 词法分析程序
- 编译原理实验三:中间代码生成
- 编译原理实验六—代码优化
- 编译原理实验一:为PL/0语言编写一个词法分析程序
- 编译原理语法分析实验(Java实现)
- 小程序实现原理解析
- 吉首大学_编译原理实验题_基于预测方法的语法分析程序的设计【通过代码】
- 编译原理动手实操,用java实现一个简易编译器1-词法解析入门
- 编译原理动手实操,用java实现一个简易编译器-语法解析
- VC编译下对一个超简单的缓冲区溢出程序的原理解析以及c程序的汇编分析
- C++词法扫描程序-编译原理实验一
- 编译原理 实验1 词法分析程序的构造
- 编译原理实验:写一个PL/0的编译器
- 编译原理实验源代码
- 编译原理实验
- 编译原理课程实验
- python+django+uwsgi+nginx+virtualenv 部署高可用的python web环境
- mysql千万级数据量根据索引优化查询速度
- Java WebService 简单实例
- 【软考】原码、反码、补码
- 分治法
- 编译原理实验,实现一个代码解析程序
- 创建一个简单的maven web项目
- 51 nod 1009
- 一把钥匙开一把锁
- java编程思想阅读笔记(二)
- 使用HTMLTestRunner生成测试报告
- js动态删除table表的指定行和列
- Android 平台DES加密解密
- javabean,和map有什么区别? javabean完全可以用map替代