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

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

?? prase.cpp

?? 內含源代碼和編譯實驗報告
?? CPP
?? 第 1 頁 / 共 2 頁
字號:
/******************************************************************
** 文件名: prase.cpp

** 描  述: 這是一個完整的文法分析器,實現C-語言的語法樹建立。在真正生成
**         代碼的執行過程中,語法分析與掃描是在一步中完成的。
**         構造語法樹的BNF文法將各函數的注釋中給出。
******************************************************************/
#include "globals.h"
#include "scan.h"
#include "prase.h"
#include "ExternGla"

/*********************************************
**類的靜態成員初始化,這是整棵語法樹的根結點,
**代表被分析的整個程序。
*********************************************/
CTreeNode *CPraser::m_program=NULL;

/**********************************************
**構造函數,當一個語法分析器被構造時,他完成兩項
**工作:創建一個掃描器,開始對程序進行文法分析。
**文法分析中拋出的錯誤最終都將在這里得到處理。
************************************************/
CPraser::CPraser(){
	try{
		m_indentno=-4;
		m_EnEndexp=ESEMI;
		m_Enforexp=ERROR;						//輔助標志的初始化。
		m_pScaner=new CScaner;					//創建掃描器。
		if(!m_pScaner) throw bad_alloc();
		cout<<"Building syntax tree..."<<endl;
		program();								//進行文法分析。
	}
	catch (bad_alloc){									//處理堆分配異常。
		cout<<"Can't be allocated in heap, the programme must be terminated."<<endl;
		exit(1);}
	catch (CInvalid_type& pa_Invalid_type){				//程序文法錯誤處理。
		pa_Invalid_type.Type_error();
		exit(1);}
	catch (...){
		cout<<"Something error,the program was terminated.";
		exit(1);}
}

/***********************************
**析構函數通過調用Delete_program
**回收語法樹的堆空間。
************************************/
CPraser::~CPraser(){
	delete m_pScaner;
	Delete_program(m_program);
}

void CPraser::Delete_program(CTreeNode *t){
	if(t!=NULL){
		Delete_program(t->m_pbrother);
		Delete_program(t->m_pchild[0]);
		Delete_program(t->m_pchild[1]);
		Delete_program(t->m_pchild[2]);
		delete t;
	}
	return;
}

/****************************************************
**第一個文法:program->declaration_list;
**程序由聲明的序列組成,聲明可以包括函數與全局變量。
****************************************************/
void CPraser::program(void){
	m_Entoken=m_pScaner->getToken();
	m_program=declaration_list();				//文法分析從這里開始。
	if(AllFlags.m_iTraceParse)					//如果只進行文法分析,則打印出分析結果。
		PrintTree(m_program);
}

/************************************************************************
**第二文法:declaration_list->declaration_list declaration|declaration;
**          該函數不合規范,把一些判斷處理提上前來做了,并運用迭代替換了
**          遞歸。
************************************************************************/ 
CTreeNode *CPraser::declaration_list(void){
	CTreeNode *first_declare=NULL,*temp=NULL,*temp2=NULL;
	while((m_Enfirst=m_Entoken)!=ENDFILE){
		m_Entoken=m_pScaner->getToken();
		if(m_Enfirst>FLOAT || m_Enfirst<VOID)			//聲明序列的第一個字符必為內置類型。
			throw CInvalid_type(AllGlobals.lineno,"missing storage-class or type specifiers");
		temp=declaration();
		MAKELINK								//宏,把聲明序列組織成兄弟鏈表。
	}
	return first_declare;						//返回兄弟鏈表的表頭,即源程序中的第一個函數。
}

/********************************************************************
**文法:declaration->var_declaration|fun_declaration
**   聲明可以是函數聲明,也可以是全局變量聲明。
**      兩者的區別只有讀到第三個標識('('與';')才可以看到。本來這里可以加
**      兩層遞歸來實現,考慮到效率問題,這里一下讀取三個標識。
**      m_Entoken的作用是保證每次都向前多讀一個,方便判斷。
***********************************************************************/
CTreeNode *CPraser::declaration(void){
	strcpy(m_strScope,"Global");			//作用域范圍初始化為全局。
	CTreeNode *t=NULL;
	m_EnSecond=m_Entoken;						//第一個標識在上層已被讀取,這里讀第二個。
	strcpy(m_strIDname, m_pScaner->GettokenString());
	m_Entoken=m_pScaner->getToken();
	if(m_EnSecond!=ID)							//聲明序列中,第二個標識肯定為ID。
		throw CInvalid_type(AllGlobals.lineno,"syntax error in declaration.");
	m_Enthird=m_Entoken;						//讀第三個。
	if(m_Enthird==LLPAREN)		t=fun_declaration();	//根據第三個標識即可判定。
	else if(m_Enthird==SEMI)	t=var_declaration();
	else 
		throw CInvalid_type(AllGlobals.lineno,"missing ';' after identifier");
	return t;
}

/********************************************************************
** 文法:fun-declaration->type-specifier ID(params) compound-stmt
**       type-specifier:返回值類型,(已作為判定)。
**       ID:             函數名。  (已被讀取)。
**       params          參數表。
**       compound-stmt   函數體(復合語句序列)。
**       在建樹時,函數名,返回類型保存在結點上,參數表與函數體作為兩個
**       子結點。
**********************************************************************/
CTreeNode *CPraser::fun_declaration(void){
	CTreeNode *p;
	m_Entoken=m_pScaner->getToken();
	CTreeNode *t=newNode(FuncK);				//創建函數結點。
	strcpy(m_strScope,m_strIDname);				//接下來的結點的作用域在這個函數內。
	p=t->m_pchild[0]=params();
	if(p) p->m_pfather=t;
	while(p && p->m_pbrother){
		p=p->m_pbrother;
		p->m_pfather=t;
	}
	match(LGPAREN, "missing '{'");				//括號,分號之類符號必須匹配掉。
	p=t->m_pchild[1]=compound_stmt();
	if(p) p->m_pfather=t;						//為兄弟鏈表中的每個結點指明它們的父結點。
	while(p && p->m_pbrother){
		p=p->m_pbrother;
		p->m_pfather=t;
	}
	return t;
}

/********************************************************************
**文法:var_declaration->type_specifier ID;
**      變量聲明可直接建立結點。
********************************************************************/
CTreeNode *CPraser::var_declaration(void){
	CTreeNode *t=newNode(DeclK);
	m_Entoken=m_pScaner->getToken();
	return t;
}

/*******************************************************************
** 文法:params->params, param|param
**		 param->type_specifier ID|E(表示空);
**        該函數再次以迭代來替換遞歸,并處理了兩句文法,函數有點零亂。
*********************************************************************/
CTreeNode *CPraser::params(void){
	CTreeNode *first_declare=NULL, *temp=NULL,*temp2=NULL;
	m_Enfirst=m_Entoken;
	m_Entoken=m_pScaner->getToken();
	//處理空參數表,按照定義,空參數只能寫成(),不可寫成(void)
	if(m_Enfirst==RLPAREN) return first_declare;	
	if(m_Entoken==RLPAREN)
		throw CInvalid_type(AllGlobals.lineno,"Bad parameter table.");
	while(m_Enfirst<=FLOAT && m_Enfirst>=VOID){	//順序處理參數表,只到讀到的不是內置數據類型。
		if((m_EnSecond=m_Entoken)!=ID)
			throw CInvalid_type(AllGlobals.lineno,"Invalid parameter.");
		strcpy(m_strIDname, m_pScaner->GettokenString());  //這個是相應的參數名。
		temp=newNode(ParaK);		//獲得了參數名與參數類型,建一結點。
		temp->m_pbrother=first_declare;
		first_declare=temp;
		m_Entoken=m_pScaner->getToken();
		if(m_Entoken==RLPAREN)		break; //耗去參數間的逗號,遇到右括號則結束。
		else if(m_Entoken==COMMA){
			m_Entoken=m_pScaner->getToken();
			m_Enfirst=m_Entoken;
			m_Entoken=m_pScaner->getToken();}
		else 
			throw CInvalid_type(AllGlobals.lineno,"Bad parameter table.");
	}
	m_Entoken=m_pScaner->getToken();
	return first_declare;				//參數表返回為函數結束的一個子結點。
}

/****************************************************************
**  文法:compound_stmt->{loal_declarations statement_list}
**        第一個循環處理:local_declarations
**        第二個處理:statement_list->statement_list statement|empty
**        該函數再次以迭代替換遞歸,影響了對文法表現的直觀性。
**        statement->selection_stmt|expression|iteration_stmt......
**        (包括switch中的所有情況。)
********************************************************************/
CTreeNode *CPraser::compound_stmt(void){
	CTreeNode *temp=NULL,*first_declare=NULL,*temp2=NULL;
	while(1){
		m_Enfirst=m_Entoken;
		if(m_Enfirst<=FLOAT && m_Enfirst>=VOID)	//第一個是內置數據類型,則必為聲明,否則轉入statement.
			temp=local_declarations();
		else	break;
		MAKELINK								//宏,把聲明序列組織成兄弟鏈表。
	}
	while(1){
		strcpy(m_strIDname, m_pScaner->GettokenString());//可能為ID名字,先拷貝備用。
		if(m_Entoken==RGPAREN)	break;					 //右大括號表示函結束。
		switch(m_Enfirst=m_Entoken){
			case IF:		temp=selection_stmt();	break;
			case NUM:
			case NOT:		temp=expression();		break;
			case WRITEB:
			case WRITED:	temp=write_stmt();		break;
			case ID:		temp=subcompound_stmt();break;
			case WHILE:		temp=iteration_stmt();	break;
			case FOR:		temp=iteration2_stmt();	break;
			case GOTO:		temp=jump_stmt();		break;
			case BREAK:		temp=break_stmt();		break;
			case CONTINUE:	temp=continue_stmt();	break;
			case RETURN:	temp=return_stmt();		break;
			default:
				throw CInvalid_type(AllGlobals.lineno,"syntax error.");
		}
		MAKELINK	
	}
	match(RGPAREN,"missing '}'");					//函數結束,把右大括號匹配掉。
	return first_declare;
}

/******************************************************************
**文法:subcompound_stmt=address|call_func|expression
**      expression中對掃描的速度有特殊要求,須向前退一個。
******************************************************************/
CTreeNode *CPraser::subcompound_stmt(void){
	CTreeNode *t=NULL; TokenType temp;
	strcpy(m_strIDname, m_pScaner->GettokenString());
	m_Enforexp=m_Entoken;				//繼續向前掃描前,當前記號可能有用(若為表達式),保留。
	m_Entoken=m_pScaner->getToken();	//向前掃描一個。
	if(m_Entoken==COLON){
		m_Enforexp=ERROR;				//判定不是表達式,則前一個保留的記號無用,可拋去。
		t=address();}
	else{
		temp=m_Entoken; 
		m_Entoken=m_Enforexp; 
		m_Enforexp=temp;				//表達式中,前一個記號有用,并且將當前記號退一個。
		t=expression();}
	return t;
}

/*******************************************************************
**文法:address->ID;
*******************************************************************/
CTreeNode *CPraser::address(void){
	m_Enfirst=VOID;							//作為地址標號的ID沒有數據類型屬性。
	CTreeNode *t=newStmtNode(AddressK);
	t->m_pchild[0]=newExpNode(IdK);
	if(t->m_pchild[0]) t->m_pchild[0]->m_pfather=t;
	match(COLON,"   ");
	return t;
}

/***************************************************************
**文法:call_func->ID(args);
***************************************************************/
CTreeNode *CPraser::call_func(void){
	m_Enfirst=VOID;	
	CTreeNode *p;
	CTreeNode *t=newStmtNode(CallK);
	t->m_pchild[0]=newExpNode(IdK);
	if(t->m_pchild[0]) t->m_pchild[0]->m_pfather=t;
	p=t->m_pchild[1]=args();
	if(p) p->m_pfather=t;
	while(p && p->m_pbrother){
		p=p->m_pbrother;
		p->m_pfather=t;
	}
	return t;
}

/***********************************************************
**文法:args=arsgs,expression|empty;
**      這是函數調用語句的實參表,以迭代替換遞歸。
***********************************************************/
CTreeNode *CPraser::args(void){
	CTreeNode *temp=NULL,*first_declare=NULL,*temp2=NULL;
	if(m_Enforexp!=ERROR){	//m_Enforexp不為ERROR,說明它保留著下一個記號,不必從文件中讀取了。
		READSYMBOL}
	else{
		m_Entoken=m_pScaner->getToken();
		strcpy(m_strIDname, m_pScaner->GettokenString());
		m_Enforexp=m_pScaner->getToken();}
	READSYMBOL
	if(m_Entoken==RLPAREN)
		return first_declare;							//函數調用的參數表為空。
	while(m_Entoken==ID || m_Entoken==NUM){
		m_EnEndexp=ECOMMA;									//指示表達式必須以','結尾
		temp=expression();
		MAKELINK;
		if(m_EnEndexp==ERPAREN){
			m_EnEndexp=ESEMI;				//接到已讀到)的通知,說明實參表讀完。恢復缺省。
			return first_declare;
		}
		m_Entoken=m_Enforexp;
		strcpy(m_strIDname, m_pScaner->GettokenString());
		m_Enforexp=ERROR;
	}
	throw CInvalid_type(AllGlobals.lineno,"syntax error.");
}

/*************************************************************
**文法:local_declarations->local_declarations var_declaration|empty
**      由于上層函數處理得過多,這個函數也不完全符合文法。
****************************************************************/
CTreeNode *CPraser::local_declarations(void){
	m_Entoken=m_pScaner->getToken();
	strcpy(m_strIDname, m_pScaner->GettokenString());
	CTreeNode *t=NULL;
	m_EnSecond=m_Entoken;
	if(m_EnSecond!=ID)
		throw CInvalid_type(AllGlobals.lineno,"syntax error in declaration.");
	t=var_declaration();
	match(SEMI,"missing ';'");
	return t;
}
		
/***********************************************************
** 文法:selection_stmt->if(expression)compound_stmt
**							|if(expression)compound_stmt else compound_stmt
*************************************************************/
CTreeNode *CPraser::selection_stmt(void){
	CTreeNode *t=newStmtNode(IfK);
	CTreeNode *p;
	m_Entoken=m_pScaner->getToken();
	match(LLPAREN, "missing '(' befor 'if'");
	m_EnEndexp=ERPAREN;							//指示下一個表達式將以)結尾。
	t->m_pchild[0]=expression();
	if(t->m_pchild[0]) t->m_pchild[0]->m_pfather=t;
	match(LGPAREN,"missing '{' after 'if'");
	p=t->m_pchild[1]=compound_stmt();
	if(p) p->m_pfather=t;
	while(p && p->m_pbrother){
		p=p->m_pbrother;
		p->m_pfather=t;
	}
	if(m_Entoken==ELSE){
		match(ELSE, " ");
		match(LGPAREN, "missing '{' after 'else'");
		p=t->m_pchild[2]=compound_stmt();
		if(p) p->m_pfather=t;
		while(p && p->m_pbrother){
			p=p->m_pbrother;
			p->m_pfather=t;
		}
	}
	return t;
}

/**************************************************************
**文法: write_stmt->writeb(expression); | writed(expresstion);
***************************************************************/
CTreeNode *CPraser::write_stmt(void){
	CTreeNode *t;
	if(m_Entoken==WRITEB)
		t=newStmtNode(WritebK);
	else if(m_Entoken==WRITED)
		t=newStmtNode(WritedK);
	m_Entoken=m_pScaner->getToken();
	match(LLPAREN, "missing '(' befor 'if'");
	m_EnEndexp=ERPAREN;							//指示下一個表達式將以)結尾。
	t->m_pchild[0]=expression();
	if(t->m_pchild[0]) t->m_pchild[0]->m_pfather=t;
	match(SEMI,"missing ';' after expression");
	return t;
}

/************************************************************
**文法: iteration_stmt->while (expression){compound_stmt}
*************************************************************/
CTreeNode *CPraser::iteration_stmt(void){
	CTreeNode *t=newStmtNode(WhileK);
	CTreeNode *p;
	m_Entoken=m_pScaner->getToken();
	match(LLPAREN, "missing '(' after 'while'");
	m_EnEndexp=ERPAREN;							//指示下一個表達式將以)結尾。
	t->m_pchild[0]=expression();
	if(t->m_pchild[0]) t->m_pchild[0]->m_pfather=t;
	match(LGPAREN,"missing '{' after 'while'");
	p=t->m_pchild[1]=compound_stmt();
	if(p) p->m_pfather=t;
	while(p && p->m_pbrother){
		p=p->m_pbrother;
		p->m_pfather=t;
	}
	return t;
}

/*************************************************************
**文法:iteration2_stmt->for(var=expression;expression;var=expression)
**															{compound_stmt}
****************************************************************/
CTreeNode *CPraser::iteration2_stmt(void){

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
一本色道久久综合狠狠躁的推荐| 亚洲图片有声小说| 26uuuu精品一区二区| 日韩一级欧美一级| 欧美xxxxx牲另类人与| 精品国产伦一区二区三区免费 | 欧美色区777第一页| 91色|porny| 在线一区二区三区做爰视频网站| 91精品办公室少妇高潮对白| 欧美视频你懂的| 日韩欧美在线一区二区三区| 久久久精品影视| 国产精品久线在线观看| 一区在线观看免费| 亚洲成在线观看| 久久国产夜色精品鲁鲁99| 韩国一区二区三区| 99视频精品在线| 欧美性三三影院| 欧美精品一区二区三区高清aⅴ | 亚洲黄色小视频| 午夜一区二区三区在线观看| 美女视频免费一区| 国产精品69毛片高清亚洲| 色综合久久综合网| 欧美日产国产精品| 国产色爱av资源综合区| 亚洲精品网站在线观看| 七七婷婷婷婷精品国产| 懂色av一区二区夜夜嗨| 欧美日韩精品一区二区在线播放| 欧美tk—视频vk| 一区二区三区色| 国产自产v一区二区三区c| 色激情天天射综合网| 日韩视频免费直播| 亚洲精品第1页| 狠狠狠色丁香婷婷综合激情| 日本精品裸体写真集在线观看| 欧美日韩久久久| 欧美国产精品一区二区三区| 日日摸夜夜添夜夜添国产精品 | 91香蕉视频污在线| 欧美视频精品在线观看| 国产精品久久精品日日| 日本大胆欧美人术艺术动态 | 国内精品伊人久久久久av一坑| jlzzjlzz亚洲女人18| 日韩天堂在线观看| 亚洲一区在线电影| 粉嫩蜜臀av国产精品网站| 欧美伦理电影网| 亚洲精品午夜久久久| 紧缚奴在线一区二区三区| 欧美日韩国产在线播放网站| 亚洲欧美一区二区三区孕妇| 国产一区二区伦理| 欧美videossexotv100| 亚洲h动漫在线| 色欧美88888久久久久久影院| 国产色产综合色产在线视频| 精品一区二区三区在线视频| 欧美一区二区三区免费视频| 亚洲电影一级黄| 在线观看亚洲专区| 一区二区三区鲁丝不卡| 成人精品小蝌蚪| 国产精品区一区二区三区| 国产麻豆欧美日韩一区| 久久亚洲精品小早川怜子| 日韩一区欧美二区| 制服丝袜日韩国产| 视频一区二区中文字幕| 欧美精品自拍偷拍动漫精品| 亚洲成人免费看| 制服丝袜成人动漫| 卡一卡二国产精品 | 国产不卡视频在线观看| 久久久国产精品午夜一区ai换脸| 国产一区二区三区四区五区入口 | 欧美一区二区在线免费播放 | 中文字幕的久久| 成人91在线观看| 亚洲嫩草精品久久| 欧美日韩在线一区二区| 男男成人高潮片免费网站| 欧美精品久久久久久久久老牛影院| 亚洲丰满少妇videoshd| 日韩一区国产二区欧美三区| 国产精品成人在线观看| 91色在线porny| 亚洲成av人片一区二区| 91精品国产91久久久久久一区二区| 久久狠狠亚洲综合| 国产欧美精品日韩区二区麻豆天美| 国产91色综合久久免费分享| 一区二区三区四区国产精品| 在线播放视频一区| 高清不卡一区二区在线| 一区二区三区四区在线播放| 日韩欧美一级二级三级久久久| 亚洲国产综合人成综合网站| 欧美变态口味重另类| 99精品久久免费看蜜臀剧情介绍 | 欧美第一区第二区| 99免费精品视频| 蜜芽一区二区三区| 日韩精品一二三区| 精品日韩成人av| 欧美亚洲自拍偷拍| 国内精品自线一区二区三区视频| 亚洲情趣在线观看| 久久久精品国产免费观看同学| 91视频国产资源| 午夜精品久久一牛影视| 久久影院电视剧免费观看| 色狠狠一区二区| 成人高清av在线| 美脚の诱脚舐め脚责91| 国产精品视频免费| 欧美性大战久久| 国产在线播放一区| 日韩精品午夜视频| 国产日韩欧美综合一区| 日韩一区二区免费高清| 色国产综合视频| 成人激情开心网| 国产综合色在线| 免费一级欧美片在线观看| 亚洲综合色网站| 中文字幕中文乱码欧美一区二区 | 亚洲午夜久久久久中文字幕久| 久久精品一二三| 精品粉嫩aⅴ一区二区三区四区| 欧美在线你懂的| 色综合中文字幕国产| 国产不卡免费视频| 国产久卡久卡久卡久卡视频精品| 日韩av中文在线观看| 亚洲午夜免费电影| 亚洲国产精品一区二区www| 中文字幕在线一区免费| 国产精品热久久久久夜色精品三区 | 看片网站欧美日韩| 美女精品一区二区| 日韩电影在线一区二区| 日韩精品乱码免费| 日本视频一区二区| 奇米精品一区二区三区在线观看一| 亚洲自拍偷拍网站| 天天色综合天天| 美国十次了思思久久精品导航| 国产精品久久免费看| 国产精品你懂的在线欣赏| 国产视频911| 亚洲人成影院在线观看| 一区二区三区在线视频免费观看| |精品福利一区二区三区| 亚洲黄色免费电影| 三级在线观看一区二区| 美国十次了思思久久精品导航| 另类调教123区| 久久精品国产亚洲a| 国产精品一区二区在线播放| 久久99久久99小草精品免视看| 国内精品久久久久影院色 | 欧美性生活久久| 337p亚洲精品色噜噜噜| 久久新电视剧免费观看| 国产欧美一区二区三区鸳鸯浴 | 欧美亚洲一区二区在线观看| 欧美精品第一页| 精品三级av在线| 国产香蕉久久精品综合网| 18欧美亚洲精品| 日韩高清不卡一区二区三区| 国产主播一区二区三区| 色综合久久久久综合| 7777精品伊人久久久大香线蕉超级流畅 | 国产在线不卡一卡二卡三卡四卡| 国产一区二区伦理| 精品视频一区二区不卡| 久久综合久久综合九色| 亚洲乱码日产精品bd| 蜜臀久久99精品久久久画质超高清 | 精品国产乱码久久久久久图片 | 欧美国产乱子伦 | 亚洲精品视频观看| 香蕉久久夜色精品国产使用方法 | 欧美成人性战久久| 中文字幕亚洲在| 久久99最新地址| 日本精品视频一区二区| 国产日韩欧美a| 亚洲午夜精品久久久久久久久| 国产乱人伦偷精品视频免下载 | 裸体一区二区三区| 一本色道**综合亚洲精品蜜桃冫| 精品国产免费久久|