编译原理实验,实现一个代码解析程序

来源:互联网 发布: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");}