亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? grammaranalysis.cpp

?? 語法及語義分析程序
?? CPP
?? 第 1 頁 / 共 2 頁
字號:
parse.h
#ifndef PARSE_H
#define PARSE_H

#define MAXCHILDNUM    3
#define INDENTADD    4
/**
 * 語法樹具有如下結構
 * 具體節點可以分為:語句節點STMT,表達式節點EXPR
 * 語句節點可以分為:賦值語句ASSIGNSTMT,條件語句IFSTMT,循環語句WHILESTMT,
 *             復合語句COMPOUNDSTMT
 * 表達式節點可以分為:操作符類型OPEXP,常數類型CONSTEXP,標識符類型IDEXP,
 *                關系操作符REALEXP
 */
enum NodeKind {
    STMT,
    EXP,
};
enum StmtKind {
    ASSIGNSTMT,
    IFSTMT,
    WHILESTMT,
}; 
enum ExpKind { 
    OPEXP,
    CONSTEXP, 
    IDEXP,
    REALEXP,
}; 
struct TreeNode {
    struct TreeNode    *child[MAXCHILDNUM];
    struct TreeNode    *sib;
    /**
     * kind用于指明該節點是語句節點STMT
     * 或是表達式節點EXP
     */
    enum NodeKind    kind;
    union {
        enum StmtKind stmt;
        enum ExpKind exp;
    } subKind;
    union {
        int    val;    /* 值 */
        LexType    op;    /* 操作符 */
        char    idname[256]; /*標識符 */
    } attr;
    int    lineno;        /* 所在行號 */
}; 
/**
 * 源程序中的聲明部分的語法樹
 */
#define PARSE_VAR  -1
struct DecNode {
    struct DecNode    *next;
    /* 標識符 */
    char    idname[256];
    /* 如果該值是PARSE_VAR則表示這個聲明是變量聲明 */
    /* 否則該值是標識符對應的常量 */
    int    icval;
    int    lineno;
};
/**
 * 程序語法樹結構
 */
struct SyntaxTree {
    /* 指向程序常量聲明部分 */
    struct DecNode    *pconstDec;
    /* 指向程序變量聲明部分 */
    struct DecNode    *pvarDec;
    /* 指向程序語句部分 */
    struct TreeNode    *pstmt;
};
/*
 * 以上所定義的節點處了語法分析要用外,語義分析
 * 用到這些節點,它會根據節點的情況去遍歷語法樹
 * 去完成相應的任務。
 */
#endif

parse.cpp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "lib.h"

#include "lex.h"
#include "parse.h"

extern int gerrLine;    // define in main.cpp
// 本地程序的聲明
static struct TreeNode *PARSE_newTreeNode(void);
static struct TokenType *PARSE_getToken(void);
static void PARSE_ungetToken(struct TokenType *ptoken);
static struct TreeNode *PARSE_expr(void);
static struct TreeNode *PARSE_factor(void);
static struct TreeNode *PARSE_term(void);
static struct TreeNode *PARSE_relationExpr(void);
static void PARSE_printExpr(struct TreeNode *phead);
static struct DecNode *PARSE_constDec(void);
static struct DecNode *PARSE_varDec(void);
static struct DecNode *PARSE_insert(struct DecNode *phead, const char *id, int icval, int lineno);
static struct TreeNode *PARSE_stmt(void);
static struct TreeNode *PARSE_assign(void);
static struct TreeNode *PARSE_if(void);
static struct TreeNode *PARSE_while(void);
static struct TreeNode *PARSE_compound(void);
static void PARSE_empty(int indent);

// 本地變量的聲明ptokenSeq指向記號流
static struct TokenSeq *ptokenSeq;
static char    buf[256];

/*
 * 語法分析主程序,它先分析程序的常量節點,然后分析程序的變量部分
 * 最后分析程序的語句部分,如果程序分析的過程中出現錯誤,就不再分
 * 析下去,而是直接返回,并做相應標記,錯誤信息寫在全局變量errMsg中。
 */
struct SyntaxTree *PARSE_parser(struct TokenSeq *phead)
{
    struct SyntaxTree    *ptree;
    struct TokenType    *ptoken;
    int    flag;

    ptokenSeq = phead;
    ptree = (struct SyntaxTree *)malloc(sizeof(struct SyntaxTree));
    if (ptree == NULL)
    {
        // TODO 內存分配錯誤
        exit(1);
    }
    ptree->pvarDec = NULL;
    ptree->pstmt = NULL;
    ptree->pconstDec = PARSE_constDec();
    if (gerrLine == -1)
    {
        // 如果常量分析沒有錯誤,就進行變量分析
        // 否則程序就返回,不再分析下去。
        ptree->pvarDec = PARSE_varDec();
        if (gerrLine == -1)
        {
            // 如果對程序變量分析沒有錯誤,就分析程序的
            // 語句,否則程序就返回,不再分析下去。
            ptree->pstmt = PARSE_stmt();
            if (gerrLine == -1)
            {
                flag = 0;
                while (ptoken = PARSE_getToken())
                {
                    if (!flag) {
                        flag = ptoken->lineno;
                        sprintf(buf, "行 %d:多于的記號 %s\n", ptoken->lineno, ptoken->lexval);
                    }
                    free(ptoken);
                }
                if (flag) 
                {
                    msgOutPut(buf);
                    gerrLine = flag;
                }
            }
        }
    }
    return ptree;
}
// 分配一個新的樹節點,并將節點中的區域初始化。
static struct TreeNode *PARSE_newTreeNode(void)
{
    struct TreeNode *ptmp;
    
    ptmp = (struct TreeNode *)malloc(sizeof(struct TreeNode));
    if (ptmp == NULL)
    {
        printf("%s: %d\n", __FILE__, __LINE__);
        exit(1);
    }
    memset(ptmp->child, 0, sizeof(ptmp->child));
    ptmp->sib = NULL;
    return ptmp;
}
/**
* 從記號流中獲取一個記號,并將他的地址返回
* 如果記號流中已經沒有則返回NULL代表沒有
* 記號流中已經沒有記號了。
*/
static struct TokenType *PARSE_getToken(void)
{
    struct TokenType    *ptoken;
    struct TokenSeq        *ptmp;
    
    if (ptokenSeq) 
    {
        ptoken = (struct TokenType *)malloc(sizeof(struct TokenType));
        if (ptoken == NULL)
        {
            printf("%s: %d\n", __FILE__, __LINE__);
            exit(1);
        }
        /**
        * v
        */
        *ptoken = ptokenSeq->token;
        ptmp = ptokenSeq;
        ptokenSeq = ptokenSeq->next;
        free(ptmp);
        return ptoken;
    }
    return NULL;
}
/**
* 將參數所指的記號回退到記號流中去,如果參數為空
* 直接返回
*/
static void PARSE_ungetToken(struct TokenType *ptoken)
{
    struct TokenSeq        *ptmp;
    
    if (!ptoken) return;    
    ptmp = (struct TokenSeq *)malloc(sizeof(struct TokenSeq));
    if (ptmp == NULL)
    {
        printf("%s: %d\n", __FILE__, __LINE__);
        exit(1);
    }
    ptmp->token = *ptoken;
    ptmp->next = ptokenSeq;
    ptokenSeq = ptmp;
}
/**
* 分析表達式
*    expr -> term {+term}
*    term -> factor {*factor}
*    factor -> (expr) | number
*/
static struct TreeNode *PARSE_expr(void)
{
    struct TreeNode *phead, *ptmp;
    struct TokenType *ptoken;
    
    phead = PARSE_term();
    ptoken = PARSE_getToken();
    if (!ptoken || gerrLine != -1) 
    {
        return phead;
    }
    while (ptoken && (ptoken->lextype == ADD || ptoken->lextype == SUB)) 
    {
        ptmp = PARSE_newTreeNode();
        ptmp->lineno = ptoken->lineno;
        ptmp->kind = EXP;
        ptmp->subKind.exp = OPEXP;
        ptmp->attr.op = ptoken->lextype;
        ptmp->child[0] = phead;
        ptmp->child[1] = PARSE_term();
        phead = ptmp;
        if (gerrLine != -1) return phead;
        ptoken = PARSE_getToken();
    }
    if (ptoken)
    {
        PARSE_ungetToken(ptoken);
    }
    return phead;
}
/*
*    term -> factor {*factor}
*    factor -> (expr) | number
*/
static struct TreeNode *PARSE_term(void)
{
    struct TreeNode *phead, *ptmp;
    struct TokenType *ptoken;
    
    phead = NULL;
    phead = PARSE_factor();
    ptoken = PARSE_getToken();
    if (!ptoken || gerrLine != -1) return phead;
    while (ptoken && (ptoken->lextype == MUL || ptoken->lextype == DIV))
    {
        ptmp = PARSE_newTreeNode();
        ptmp->lineno = ptoken->lineno;
        ptmp->kind = EXP;
        ptmp->subKind.exp = OPEXP;
        ptmp->attr.op = ptoken->lextype;
        ptmp->child[0] = phead;
        ptmp->child[1] = PARSE_factor();
        phead = ptmp;
        if (gerrLine != -1) return phead;
        ptoken = PARSE_getToken();
    }
    if (ptoken)
        PARSE_ungetToken(ptoken);
    return phead;
}
//factor -> (expr) | number
static struct TreeNode *PARSE_factor(void)
{
    struct TreeNode *phead;
    struct TokenType *ptoken;
    int        lineno;
    
    phead = NULL;
    ptoken = PARSE_getToken();
    if (!ptoken) return NULL;
    lineno = ptoken->lineno;
    if (ptoken->lextype == LBR) 
    {
        free(ptoken);
        phead = PARSE_expr();
        if (gerrLine != -1) return phead;
        ptoken = PARSE_getToken();
        if (ptoken && ptoken->lextype != RBR) 
        {
            sprintf(buf, "行 %d,括號不匹配\n", lineno);
            msgOutPut(buf);
            gerrLine = ptoken->lineno;
            return phead;
        }
        if (ptoken) free(ptoken);
    } 
    else 
    {
        if (ptoken->lextype != NUM 
            && ptoken->lextype != ID)
        {
            sprintf(buf, "行 %d,因子不是數字或標識符\n", lineno);
            msgOutPut(buf);
            gerrLine = ptoken->lineno;
            free(ptoken);
            return phead;
        }
        phead = PARSE_newTreeNode();
        phead->kind = EXP;
        lineno = phead->lineno = ptoken->lineno;
        if (ptoken->lextype == NUM) 
        {
            phead->subKind.exp = CONSTEXP;
            sscanf(ptoken->lexval, "%d", &phead->attr.val);
        } 
        else 
        {
            phead->subKind.exp = IDEXP;
            if (ptoken->lextype == ID)
            {
                strcpy(phead->attr.idname, ptoken->lexval);
                free(ptoken);
            }
            else
            {
                sprintf(buf, "行 %d,因子不是標識符\n", lineno);
                msgOutPut(buf);
                gerrLine = lineno;    
                return phead;
            }
        }
    }
    return phead;
}
/**
* 關系表達式節點,他的左邊和右邊都是表達式
* 中間是關系運算符
*/
static struct TreeNode *PARSE_relationExpr(void)
{
    struct TreeNode    *phead;
    struct TokenType *ptmp;
    
    phead = PARSE_newTreeNode();
    phead->child[0] = PARSE_expr();
    if (gerrLine != -1) return phead;
    ptmp = PARSE_getToken();
    phead->lineno = ptmp->lineno;
    switch (ptmp->lextype)
    {
    case EQ:
        phead->kind = EXP;
        phead->subKind.exp = REALEXP;
        phead->attr.op = ptmp->lextype;
        break;
    case NE:
        phead->kind = EXP;
        phead->subKind.exp = REALEXP;
        phead->attr.op = ptmp->lextype;
        break;
    case LT:
        phead->kind = EXP;
        phead->subKind.exp = REALEXP;
        phead->attr.op = ptmp->lextype;
        break;
    case LE:
        phead->kind = EXP;
        phead->subKind.exp = REALEXP;
        phead->attr.op = ptmp->lextype;
        break;
    case GT:
        phead->kind = EXP;
        phead->subKind.exp = REALEXP;
        phead->attr.op = ptmp->lextype;
        break;
    case GE:
        phead->kind = EXP;
        phead->subKind.exp = REALEXP;
        phead->attr.op = ptmp->lextype;
        break;
    default:
        // 程序中沒有關系運算符,程序中盡量少用exit(1)
        // 免得誤用是程序異常退出。
        gerrLine = ptmp->lineno;
        phead->child[1] = NULL;
        sprintf(buf, "行 %d: 缺少關系運算符\n", ptmp->lineno);
        msgOutPut(buf);
        return phead;
    }
    phead->child[1] = PARSE_expr();
    return phead;
}
/**
* 匹配記號程序,如果記號流中有一個記號和
* 要匹配的記號不同,就簡單的忽略這個記號
* 并返回NULL
*/
static struct TokenType *PARSE_match(enum LexType lextype)
{
    struct TokenType *ptoken;
    
    ptoken = PARSE_getToken(); 
    if (ptoken && ptoken->lextype == lextype)
        return ptoken;
    if (ptoken)
    {
        /* 如果不匹配就將這個記號回退到記號流中去 */
        PARSE_ungetToken(ptoken);
        free(ptoken);
        return NULL;
    }
    else
    {
        return NULL;
    }
}
/**
* 處理有關常量聲明或變量聲明的程序部分
* 它將建立一個鏈表,指向程序中的常量序列
*/
static struct DecNode *PARSE_constDec(void)
{
    struct DecNode         *phead;
    struct TokenType    *ptoken, *ptokenid, *ptokennum;
    char    idname[256];
    int        icval, lineno;
    
    phead = NULL;
    if (ptoken = PARSE_match(CONST))
    {
        lineno = ptoken->lineno;
        /* 處理常量聲明部分,并將聲明部分節點插入到鏈表中去 */
        while (ptokenid = PARSE_match(ID))
        {
            lineno = ptokenid->lineno;
            ptoken = PARSE_match(ASSIGN);
            ptokennum = PARSE_match(NUM);
            if (ptokenid && ptoken && ptokennum)
            {
                /* 將一個常量定義放到鏈表中去 */
                strcpy(idname, ptokenid->lexval);
                sscanf(ptokennum->lexval, "%d", &icval);
                phead = PARSE_insert(phead, idname, icval, ptokennum->lineno);
                free(ptokenid);
                free(ptoken);
                free(ptokennum);
                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;
                }
            }

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
欧美在线|欧美| 国产色爱av资源综合区| 国产日韩欧美亚洲| 五月婷婷激情综合| 成人小视频免费观看| 日韩三级精品电影久久久| 亚洲日本欧美天堂| 东方aⅴ免费观看久久av| 91精品国产乱码| 一个色综合网站| 成人av网址在线| 久久婷婷久久一区二区三区| 婷婷国产在线综合| 欧美在线小视频| 亚洲精品国产视频| 91小视频在线| 亚洲特黄一级片| 国产69精品久久久久777| 精品国产污污免费网站入口| 免费在线观看一区| 日韩欧美亚洲另类制服综合在线| 亚洲一区二区在线免费观看视频| 99riav久久精品riav| 国产精品久久久久影院亚瑟| 成人免费观看视频| 国产精品另类一区| 国产白丝网站精品污在线入口| 久久亚洲精品小早川怜子| 狠狠色综合日日| 久久久99久久精品欧美| 国产精品一区不卡| 国产精品免费视频一区| jlzzjlzz欧美大全| 中文字幕一区二区日韩精品绯色| 成人黄色av电影| 亚洲人吸女人奶水| 欧美性生活影院| 午夜国产精品一区| 日韩一卡二卡三卡四卡| 精品综合久久久久久8888| 精品久久一区二区三区| 国产成人av一区| 亚洲欧美视频在线观看视频| 在线观看国产一区二区| 五月激情丁香一区二区三区| 91精品国产品国语在线不卡| 久久 天天综合| 久久久国产综合精品女国产盗摄| 成人免费毛片a| 亚洲人成网站在线| 欧美一级xxx| 国产不卡视频在线播放| 亚洲精品国久久99热| 91精品国产综合久久小美女| 国产精品一级在线| 亚洲精品国产高清久久伦理二区| 欧美日韩aaaaaa| 国产精品一区二区不卡| 亚洲综合在线免费观看| 日韩欧美一区二区视频| 成人动漫一区二区三区| 亚洲电影一级黄| 久久影视一区二区| 欧美综合色免费| 国内精品久久久久影院薰衣草| **欧美大码日韩| 日韩欧美一区二区免费| 99精品热视频| 蜜臀精品一区二区三区在线观看 | 国产色产综合产在线视频| 色婷婷亚洲综合| 久久国产欧美日韩精品| 亚洲欧美另类小说视频| 亚洲精品一线二线三线| 欧美制服丝袜第一页| 国产成人精品aa毛片| 日韩精品欧美精品| 中文字幕日本不卡| 久久久精品人体av艺术| 欧美理论电影在线| 91在线视频观看| 狠狠色狠狠色合久久伊人| 亚洲国产成人porn| 国产精品久久久久久亚洲伦 | 国产精品的网站| 欧美成人a视频| 欧美亚洲动漫制服丝袜| 成人免费高清视频| 狠狠色丁香久久婷婷综合丁香| 亚洲v日本v欧美v久久精品| 国产精品网站在线观看| 久久一留热品黄| 日韩精品中文字幕一区二区三区 | 97精品电影院| 国产激情视频一区二区三区欧美| 日韩av中文在线观看| 亚洲一级在线观看| 一区二区三区中文免费| 国产精品无码永久免费888| 久久久久久久网| 欧美精品一区二区高清在线观看| 91精选在线观看| 欧美电影在线免费观看| 欧美日韩精品一区二区| 在线观看日韩毛片| 欧美中文字幕不卡| 欧美色图在线观看| 欧美视频在线一区| 欧美最猛性xxxxx直播| 色欧美88888久久久久久影院| 97久久久精品综合88久久| eeuss影院一区二区三区 | 黑人精品欧美一区二区蜜桃| 日韩成人伦理电影在线观看| 婷婷国产v国产偷v亚洲高清| 石原莉奈一区二区三区在线观看| 亚洲午夜视频在线观看| 天天免费综合色| 日韩成人一区二区| 久久99九九99精品| 国产露脸91国语对白| 国产成a人无v码亚洲福利| 波多野结衣中文一区| av在线不卡电影| 欧美色网一区二区| 日韩欧美高清一区| 国产网红主播福利一区二区| 中文字幕va一区二区三区| 综合久久久久久久| 午夜私人影院久久久久| 久久精品国产精品亚洲精品| 国产精一品亚洲二区在线视频| 国产成人日日夜夜| 日本高清无吗v一区| 91精品国产91热久久久做人人| 欧美精品一区二区三区四区| 中文一区在线播放| 亚洲v中文字幕| 国产精品一二三四区| 91色综合久久久久婷婷| 4438成人网| 欧美激情一区二区三区| 亚洲在线中文字幕| 久久99国内精品| 91国在线观看| 精品国产免费人成电影在线观看四季| 国产精品视频免费| 亚洲成人在线网站| 国产成人午夜99999| 欧美日韩综合在线| 久久综合资源网| 亚洲成人免费在线| 成人一区在线看| 777奇米四色成人影色区| 国产亚洲婷婷免费| 五月激情六月综合| 91丨porny丨中文| 精品国产一区a| 亚洲成人自拍偷拍| 成人少妇影院yyyy| 欧美成人高清电影在线| 一区二区三区在线播放| 国产自产视频一区二区三区| 欧美性一级生活| 中文字幕在线不卡国产视频| 久久av资源站| 欧美视频在线播放| 亚洲日本va在线观看| 国产一区二区在线观看免费| 欧美日韩一区视频| 亚洲欧美日韩久久| 顶级嫩模精品视频在线看| 精品久久国产老人久久综合| 亚洲高清不卡在线观看| av电影在线观看一区| 久久久www免费人成精品| 久久精品国产一区二区三区免费看 | 色成人在线视频| 国产午夜精品福利| 国产在线视频精品一区| 日韩一区二区三区观看| 水蜜桃久久夜色精品一区的特点| 色视频一区二区| 亚洲特黄一级片| 99re视频精品| 成人欧美一区二区三区小说 | 国产乱子伦一区二区三区国色天香| 欧美亚洲综合久久| 亚洲自拍另类综合| 在线区一区二视频| 一区二区在线观看视频在线观看| 成人免费视频免费观看| 国产精品萝li| 波多野结衣中文字幕一区| 国产精品少妇自拍| 成人不卡免费av| 国产精品色在线观看| 成人av资源网站| 亚洲精品一二三| 欧美性受xxxx黑人xyx性爽|