⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 grammaranalysis.cpp

📁 语法及语义分析程序
💻 CPP
📖 第 1 页 / 共 2 页
字号:
            else
            {
                sprintf(buf, "行 %d: 常量声明错误\n", lineno);
                msgOutPut(buf);
                gerrLine = lineno;
                if (ptokenid) free(ptokenid);
                if (ptoken) free(ptoken);
                if (ptokennum) free(ptokennum);
                return phead;
            }
        }
        sprintf(buf, "行 %d: 缺少标识符\n", lineno);
        msgOutPut(buf);
        gerrLine = lineno;
        return phead;
    }
    /* 程序没有常量声明部分 */
    return NULL;
}
/**
* 处理有关变量声明的程序部分
* 它将建立一个链表,指向程序中的变量序列
*/
static struct DecNode *PARSE_varDec(void)
{
    struct DecNode         *phead;
    struct TokenType    *ptoken;
    int    lineno;

    phead = NULL;
    if (ptoken = PARSE_match(VAR)) 
    {
        lineno = ptoken->lineno;
        free(ptoken);
        while (ptoken = PARSE_match(ID))
        {
            phead = PARSE_insert(phead, ptoken->lexval, PARSE_VAR, ptoken->lineno);
            if (ptoken = PARSE_match(COMMA))
            {
                free(ptoken);
                continue;
            }
            else if (ptoken = PARSE_match(COLON))
            {
                free(ptoken);
                return phead;
            } 
            else
            {
                sprintf(buf, "行 %d: 缺少逗号或分号\n", lineno);
                msgOutPut(buf);
                gerrLine = lineno;
                return phead;
            }
        }
        sprintf(buf, "行 %d: 缺少标识符\n", lineno);
        msgOutPut(buf);
        gerrLine = lineno;
        return phead;
    }
    if (ptoken)
        PARSE_ungetToken(ptoken);
    /* 程序没有变量声明部分 */
    return NULL;
}
/**
* 往常量或变量声明链表中插入常量声明或变量声明,
* 其中icval为PARSE_VAR的时候表示它是变量声明
*/
static struct DecNode *PARSE_insert(struct DecNode *phead, const char *id, int icval, int lineno)
{
    struct DecNode     *ptmp, *piter;
    
    /**
    * 先分配一个节点,然后将其内容全部赋值
    * 节点的指定空间中去
    */
    ptmp = (struct DecNode *)malloc(sizeof(struct DecNode));
    if (ptmp == NULL)
    {
        printf("%s: %d\n", __FILE__, __LINE__);
        exit(1);
    }
    strcpy(ptmp->idname, id);
    ptmp->icval = icval;
    ptmp->next= NULL;
    ptmp->lineno = lineno;
    /**
    * 将以分配好的节点插入到链表phead的末尾。
    */
    if (phead) 
    {
        piter = phead;
        while (piter->next)
        {
            piter = piter->next;
        }
        piter->next = ptmp;
        return phead;
    }
    else 
    {
        return ptmp;
    }
}
/**
* 语句分析程序,根据源程序的第一个记号来决定程序应该使用
* 哪一个程序来进行分析。
*/
static struct TreeNode *PARSE_stmt(void)
{
    struct TokenType *ptoken;

    // ID开头表明是赋值语句
    if (ptoken = PARSE_match(ID))
    {
        PARSE_ungetToken(ptoken);
        free(ptoken);
        return PARSE_assign();
    } 
    // 关键字IF开头表明是条件语句
    else if (ptoken = PARSE_match(IF))
    {
        PARSE_ungetToken(ptoken);
        free(ptoken);
        return PARSE_if();
    }
    // 关键字WHILE开头表明是循环语句
    else if (ptoken = PARSE_match(WHILE))
    {
        PARSE_ungetToken(ptoken);
        free(ptoken);
        return PARSE_while();
    }
    // 关键字BEGIN开头表明是符合语句
    else if (ptoken = PARSE_match(BEGIN))
    {
        PARSE_ungetToken(ptoken);
        free(ptoken);
        return PARSE_compound();
    }
    else
    {
        // 空语句
        return NULL;
    }
}
/**
* 分析赋值语句,依照文法依次匹配各个部分
*/
static struct TreeNode *PARSE_assign(void)
{
    struct TreeNode *phead = PARSE_newTreeNode();
    struct TokenType *ptoken;
    int    lineno;

    phead->kind = STMT;
    phead->subKind.stmt = ASSIGNSTMT;
    ptoken = PARSE_match(ID);
    if (ptoken)
    {
        strcpy(phead->attr.idname, ptoken->lexval);
    } 
    else
    {
        printf("%s: %d\n", __FILE__, __LINE__);
        exit(1);
    }
    phead->lineno = ptoken->lineno;
    lineno = ptoken->lineno;
    free(ptoken);
    if (ptoken = PARSE_match(ASSIGN))
    {
        free(ptoken);
    } 
    else 
    {
        sprintf(buf, "行 %d: 缺少赋值号\n", lineno);
        msgOutPut(buf);
        gerrLine = lineno;
        free(phead);
        return NULL;
    }
    phead->child[0] = PARSE_expr();
    return phead;
}
/**
* 分析条件语句,依照文法依次匹配各个部分
*/
static struct TreeNode *PARSE_if(void)
{
    struct TreeNode *phead = PARSE_newTreeNode();
    struct TokenType *ptoken;    
    int    lineno;

    phead->kind = STMT;
    phead->subKind.stmt = IFSTMT;
    ptoken = PARSE_match(IF);
    lineno = ptoken->lineno;
    free(ptoken);
    phead->child[0] = PARSE_relationExpr();
    if (gerrLine != -1) return phead;
    if (ptoken = PARSE_match(THEN))
    {
        free(ptoken);
    }
    else
    {
        sprintf(buf, "行 %d: 缺少关键字then\n", lineno);
        msgOutPut(buf);
        gerrLine = lineno;
        return phead;
    }
    phead->child[1] = PARSE_stmt();
    if (gerrLine != -1)
    {
        return phead;
    }
    if (ptoken = PARSE_match(ELSE))
    {
        free(ptoken);
        phead->child[2] = PARSE_stmt();
    }
    return phead;
}
/**
* 分析循环语句,依照文法依次匹配各个部分
*/
static struct TreeNode *PARSE_while(void)
{
    struct TreeNode *phead = PARSE_newTreeNode();
    struct TokenType *ptoken;
    int    lineno;

    phead->kind = STMT;
    phead->subKind.stmt = WHILESTMT;
    ptoken = PARSE_match(WHILE);
    lineno = ptoken->lineno;
    free(ptoken);
    phead->child[0] = PARSE_relationExpr();
    if (gerrLine != -1)
    {
        return phead;
    }
    if (ptoken = PARSE_match(DO))
    {
        free(ptoken);
    }
    else
    {
        sprintf(buf, "行 %d: 缺少关键字do\n", lineno);
        msgOutPut(buf);
        gerrLine = lineno;
        return phead;
    }
    phead->child[1] = PARSE_stmt();
    return phead;
}
/**
* 分析复合语句,依照文法依次匹配各个部分
*/
static struct TreeNode *PARSE_compound(void)
{
    struct TreeNode *ptmp, *phead; 
    struct TokenType    *ptoken;
    int    lineno;
    
    ptoken = PARSE_match(BEGIN);
    lineno = ptoken->lineno;
    free(ptoken);
    phead = PARSE_stmt();
    if (gerrLine != -1)
    {
        return phead;
    }
    while (ptoken = PARSE_match(COLON))
    {
        /* 表明还有下一条语句 */
        ptmp = phead;
        while (ptmp->sib)
        {
            ptmp = ptmp->sib;
        }
        ptmp->sib = PARSE_stmt();
        if (gerrLine != -1)
        {
            return phead;
        }
    }
    if (ptoken = PARSE_match(END))
    {
        free(ptoken);
    }
    else
    {
        sprintf(buf, "行 %d: 缺少关键字end\n", lineno);
        msgOutPut(buf);
        gerrLine = lineno;
    }
    return phead;
}
/*******************************************************************/
/**
* 往文件流中输出phead指向的表达式
*/
static void PARSE_printExpr(struct TreeNode *phead)
{
    if (phead) 
    {
        parseOutPut("(");
        PARSE_printExpr(phead->child[0]);
        if (phead->subKind.exp == OPEXP)
        {
            switch (phead->attr.op)
            {
            case ADD:
                parseOutPut("+");
                break;
            case SUB:
                parseOutPut("-");
                break;
            case MUL:
                parseOutPut("*");
                break;
            case DIV:
                parseOutPut("/");
                break;
            default:
                printf("%s: %d\n", __FILE__, __LINE__);
                exit(1);
            }
        }
        else if (phead->subKind.exp == REALEXP) 
        {
            switch (phead->attr.op)
            {
            case EQ:
                parseOutPut("==");
                break;
            case NE:
                parseOutPut("<>");
                break;
            case LT:
                parseOutPut("<");
                break;
            case LE:
                parseOutPut("<=");
                break;
            case GT:
                parseOutPut(">");
                break;
            case GE:
                parseOutPut(">=");
                break;
            default:
                printf("%s: %d\n", __FILE__, __LINE__);
                exit(1);
            }
        }
        else if (phead->subKind.exp == CONSTEXP)
        {
            memset(buf, 0, sizeof(buf));
            sprintf(buf, "%d", phead->attr.val);
            parseOutPut(buf);
        } 
        else if (phead->subKind.exp == IDEXP) 
        {
            memset(buf, 0, sizeof(buf));
            sprintf(buf, "%s", phead->attr.idname);
            parseOutPut(buf);
        } 
        else 
        {
            printf("%s: %d\n", __FILE__, __LINE__);
            exit(1);
        }
        PARSE_printExpr(phead->child[1]);
        parseOutPut(")");
    }
}

void PARSE_empty(int indent)
{
    int    i;
    
    for (i = 0; i < indent; i++)
        parseOutPut(" ");
}
void PARSE_printConstDec(struct DecNode *pconst, int indent)
{
    PARSE_empty(indent);
    parseOutPut("const declare\n");
    indent += 4;
    while (pconst) 
    {
        PARSE_empty(indent);
        memset(buf, 0, sizeof(buf));
        sprintf(buf, "%s = %d\n", pconst->idname, pconst->icval);
        parseOutPut(buf);
        pconst = pconst->next;
    }
}
void PARSE_printVarDec(struct DecNode *pvar, int indent)
{
    PARSE_empty(indent);
    parseOutPut("var declare\n");
    indent += 4;
    while (pvar)
    {
        PARSE_empty(indent);
        memset(buf, 0, sizeof(buf));
        sprintf(buf, "%s\n", pvar->idname);
        parseOutPut(buf);
        pvar = pvar->next;
    }
}
void PARSE_printStmt(struct TreeNode *stmt, int indent)
{
    int    indent2 = indent;
    
    PARSE_empty(indent2);
    parseOutPut("stmt begin\n");
    if (stmt) 
    {
        indent += INDENTADD;
        while (stmt)
        {
            switch (stmt->subKind.stmt)
            {
            case ASSIGNSTMT:
                PARSE_empty(indent);
                parseOutPut("assign stmt\n");
                PARSE_empty(indent + INDENTADD);
                memset(buf, 0, sizeof(buf));
                sprintf(buf, "%s = ", stmt->attr.idname);
                parseOutPut(buf);
                PARSE_printExpr(stmt->child[0]);
                parseOutPut("\n");
                break;
            case IFSTMT:
                PARSE_empty(indent);
                memset(buf, 0, sizeof(buf));
                parseOutPut("if stmt\n");
                PARSE_empty(indent + INDENTADD);
                PARSE_printExpr(stmt->child[0]); 
                parseOutPut("\n");
                PARSE_printStmt(stmt->child[1], indent + INDENTADD);
                if (stmt->child[2]) 
                {
                    PARSE_printStmt(stmt->child[2], indent + INDENTADD);
                    
                }
                parseOutPut("\n");
                break;
            case WHILESTMT:
                PARSE_empty(indent);
                parseOutPut("while stmt\n");
                PARSE_empty(indent + INDENTADD);
                PARSE_printExpr(stmt->child[0]); 
                parseOutPut("\n");
                PARSE_printStmt(stmt->child[1], indent + INDENTADD);
                parseOutPut("\n");
                break;
            default:
                printf("%s: %d\n", __FILE__, __LINE__);
                exit(1);
            }
            stmt = stmt->sib;
        }
    }
    PARSE_empty(indent2);
    parseOutPut("stmt end\n");
}
/*
 * 打印函数,将语法树打印到程序指定的文件中去
 */
void PARSE_printSyntaxTree(struct SyntaxTree *ptree)
{
    int        indent = INDENTADD;
    
    parseOutPut("Syntax Tree\n");
    PARSE_printConstDec(ptree->pconstDec, 4);
    PARSE_printVarDec(ptree->pvarDec, 4);
    PARSE_printStmt(ptree->pstmt, 4);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -