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

📄 scan.cpp

📁 内含源代码和编译实验报告
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/******************************************************************
** 文件名: scan.cpp
** 描  述: 这是一个完整的扫描器,实现C-语言的完整扫描功能。具体见
**     程序中的注释。
******************************************************************/
#include "globals.h"
#include "scan.h"
#include "ExternGla"

/**********************类CStates**************************************/
/***********************************
**拷贝构造函数,建立状态链表的一个结点。
************************************/
CStates::CStates(StateType pa_EnStates, 
				 void (*paStates)(),CStates *pa_pNextState){
	m_EnStates=pa_EnStates;
	fnState=paStates;
	m_pNextState=pa_pNextState;
}

/**********************类CScaner***************************************/
/**************************************
**静态数据成员进行初始化
**************************************/
CSymbols CScaner::m_ArraySymbols[10]=
			{{'+',PLUS}, {'-', MINUS}, {'*', TIMES},{',',COMMA},{':', COLON}, {'(', LLPAREN}, 
							{')', RLPAREN}, {'{', LGPAREN}, {'}', RGPAREN}, {';', SEMI}};
CReserved	CScaner::m_ReservedWords[MAXRESERVED]=
			{{"if",IF},{"else",ELSE},{"while",WHILE}, {"for",FOR},
					{"goto",GOTO},{"break",BREAK},{"continue",CONTINUE},{"return",RETURN},
							{"void",VOID},{"int",INT},{"char",CHAR},
										{"float",FLOAT},{"writeb",WRITEB},{"writed",WRITED}};
CStates		*CScaner::m_pFirstState=NULL;
StateType	CScaner::m_Enstate=START;
TokenType	CScaner::currentToken=VOID;
char		CScaner::m_chGetchar='\0';
int			CScaner::m_isave=TRUE;
int         CScaner::m_iLinepos=0;
int 		CScaner::m_iBufsize=0;
char		CScaner::m_pLineBuf[BUFLEN]=" ";

/**************************************************
**扫描器构造函数主要完成关于DFA链表的创建
**************************************************/
CScaner::CScaner(){
	AllGlobals.lineno=0;									//起初扫描行初始化为零。
	try{
		OnStates();											//完成链表的创建。
	}
	catch (bad_alloc){										//处理堆分配异常。
		cout<<"Can't be allocated in heap, the programme must be terminated."<<endl;
		exit(1);}
	catch (...){											//处理其他类型的异常。
		cout<<"Comething error."<<endl;
		exit(1);}
};

CScaner::~CScaner(){
	m_pMobileStates=m_pFirstState->m_pNextState;
	m_pFirstState->m_pNextState=NULL;
	m_pFirstState=m_pMobileStates;				//把环型链表的环打断,以利于顺序销毁。
	while(m_pFirstState!=NULL){
		m_pMobileStates=m_pFirstState->m_pNextState;
		delete m_pFirstState;
		m_pFirstState=m_pMobileStates;
	}
}

/***************************************************************************
**执行扫描的主函数
**功能简单描述:该函数在状态链表上匹配相应状态,并进行
**相应的函数进行扫描处理。
**举列如下:如扫描<=:
**     初始状态:字符数组m_tokenString为空,状态m_Enstate为START,
**          进行循环,匹配到STRAT相应的处理函数为OnStart,进行该函数,
**			该函数读取一个'<'返回状态m_Enstate为INNGT(小于等于,即'<'
**          号有可能后面还跟有'=', 保存'<',再进入INNGT的处理函数OnIngt进行
**			处理,读取到'=', 确定currentToken=NGT(不大于),最后状态m_Enstate
**          为DONE,m_tokenString="<=",扫描结束。
***************************************************************************/
TokenType CScaner::getToken(void){
	int tokenStringIndex = 0;
	m_Enstate=START;
	m_tokenString[0]='\0';							//扫描开始前,所有相关变量初始化。
	m_pMobileStates=m_pFirstState;
	while(m_Enstate != DONE){						//一个循环完成一个记号扫描。
		m_isave=TRUE;
		try{
			while(m_pMobileStates && m_Enstate != m_pMobileStates->m_EnStates)
				m_pMobileStates=m_pMobileStates->m_pNextState;
			if(m_pMobileStates) m_pMobileStates->fnState();	//执行匹配状态的相应处理函数。
			else throw CInvalid_pointer(); 
		}
		catch(CInvalid_pointer& pa_pointer){ 
			pa_pointer.Bad_pointer(); 
		}
		if((m_isave) && (tokenStringIndex <= MAXTOKENLEN))
			m_tokenString[tokenStringIndex++] =m_chGetchar;//保存读到的字符。
		if(m_Enstate==DONE){
			m_tokenString[tokenStringIndex]='\0';			
			if(currentToken == ID)
				currentToken = reservedLookup(m_tokenString); //对于ID类型,可能为保留字。
		}
	}
	if(AllFlags.m_iTraceScan==1){	  //输出扫描信息。
		cout<<AllGlobals.lineno<<"  ";
		printToken(currentToken, m_tokenString);
	}
	return currentToken;
}

/**************建立状态链表的函数*****************/
void CScaner::OnStates(void){
	CStates	*pMobileStates;
	AddStates(DONE, OnDone);
	CStates	*tempState=pMobileStates;
	AddStates(INCOMMENT, OnIncomment);
	AddStates(INNEQ, OnInneq);
	AddStates(INAND, OnInand);
	AddStates(INOR, OnInor);
	AddStates(INNGT, OnInngt);
	AddStates(INNLT, OnInnlt);
	AddStates(INASSIGN, OnInassigh);
	AddStates(INCHAR,OnInchar);
	AddStates(INNUM, OnInnum);
	AddStates(INID, OnInid);
	AddStates(START, OnStart);
	tempState->m_pNextState=m_pFirstState;
	return;
}

/*******************************************************
**从文件缓冲区中读入一个字符,若读完,则从文件中读入一行。
*******************************************************/
char CScaner::getNextChar(void){
	if(!(m_iLinepos<m_iBufsize)){			//注意,他们的初始状态都为零,所以文件被读取。
		if(AllFlags.m_iTraceScan==1)	cout<<endl;
		if(AllGlobals.source.getline(m_pLineBuf,BUFLEN)){
			AllGlobals.lineno++;			//读入一行,文件行数加一。
			if(AllFlags.m_iTraceScan==1)
				cout<<AllGlobals.lineno<<":"<<m_pLineBuf<<endl;
			m_iBufsize=strlen(m_pLineBuf);
			m_iLinepos=0;					//缓冲区位置指针归零。
			return m_pLineBuf[m_iLinepos++];
		}
		else return EOF;
	}
	
	else return m_pLineBuf[m_iLinepos++];
};

void CScaner::ungetNextChar(void){
	m_iLinepos--;
}

/*************************************************
** 每个记号扫描的起始状态从这里开始,记号被分成三种,
** "- * ,  ( ) { } ; + :"共十个为无二义性的单字符
** 记号,被保存在静态数组m_ArraySymbols[]中; 字符,
** 数字, 空格,换行,tab为第二类,单独处理。
** 第三类如'<'跟'<="等,第一个字符相同,需另加状态加于
** 处理。
****************************************************/
void CScaner::OnStart(void){
	m_chGetchar=getNextChar();
	int i=0;
	while(i<=9 && m_ArraySymbols[i].m_chSymbols!=m_chGetchar) i++;
	if(i<10){
		currentToken=m_ArraySymbols[i].m_EnSymbols;
		m_Enstate=DONE;
		return;
	}															//处理第一类记号。
	if(isdigit(m_chGetchar))			m_Enstate=INNUM;
	else if (isalpha(m_chGetchar))		m_Enstate=INID;
	else if((m_chGetchar==' ') || (m_chGetchar=='\t') 
					|| (m_chGetchar=='\n') || (m_chGetchar==NULL))
						m_isave=FALSE;							//处理第二类记号。
	else{
		 switch(m_chGetchar){
			case EOF:
				m_isave=FALSE;
				m_Enstate=DONE;
				currentToken = ENDFILE;
				break;
			case '=':		
				m_Enstate=INASSIGN;
				break;
			case '<':
				m_Enstate=INNGT;
				break;
			case '>':
				m_Enstate=INNLT;
				break;
			case '!':
				m_Enstate=INNEQ;
				break;
			case '&':
				m_Enstate=INAND;
				break;
			case '|':
				m_Enstate=INOR;
				break;
			case '\'':
				m_isave=FALSE;
				m_Enstate=INCHAR;
				break;
			case '/':
				m_isave=FALSE;
				m_Enstate=INCOMMENT;
				break;
			default:
				m_Enstate=DONE;

⌨️ 快捷键说明

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