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

本文介绍了一个基于 TINYv2 语言的小型编译器实现过程,包括词法分析、语法分析及中间代码生成等核心环节。通过状态机和递归下降解析器实现了对 TINYv2 语言的词法和语法分析,并生成了可读性强的中间代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

本程序参考了TINY1的实现源代码,并添加了一些简单新的语法规则,最终结果是生成可阅读中间代码。部分地方没有考虑过多的容错,纯属自娱自乐。采用的语法为TINY v2的语法,老师实验课给的,自行百度。


文件读取器

头部定义一些变量

#include "FILEHANDLE.h"
#include "SCAN.h"

/* 定义一行能读取的最大字符数 */
#define BUFLEN 256

static 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-stmt
TreeNode * 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] end
TreeNode * 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-exp
TreeNode * 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-exp
TreeNode * 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 identifier
TreeNode * 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-exp
TreeNode * 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 end
TreeNode * 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");
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值