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

📄 morpheme.cpp

📁 词法语法语义编译器
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// Morpheme.cpp: implementation of the Morpheme class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "scanner.h"
#include "Morpheme.h"
#include "MainFrm.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

/**
 * 词法分析构造函数
 * 
 * @param  pWordCode			字符表数组
 * @param  pTokenFile			token串头指针
 * @param  pSymbolTable			符号表头指针
 * @param  pErrorCollection		错误信息头指针
 *
 */
CMorpheme::CMorpheme(const char *pWordCode[],
					 PTokenNode pTokenFile,
					 PSTable pSymbolTable,
					 PErrorNode pErrorCollection)
{		
	m_bStepOn=false;
	this->m_strSourceFile="";
	this->m_pTokenFile=pTokenFile;
	this->m_pSymbolTable=pSymbolTable;
	this->m_pErrorCollection=pErrorCollection;
	for (int i=0;i<KEYWORDCOUNT+1;i++)
	{
		this->m_pWordCode[i]=pWordCode[i];
	}
}

/**
 * 词法分析构造函数
 * 
 * @param  pWordCode			字符表数组
 * @param  pTokenFile			token串头指针
 * @param  pSymbolTable			符号表头指针
 * @param  pErrorCollection		错误信息头指针
 * @param  strSourceFile		源文件路径
 *
 */
CMorpheme::CMorpheme(const char *pWordCode[],
					 PTokenNode pTokenFile,
					 PSTable pSymbolTable,
					 PErrorNode pErrorCollection,
					 CString strSourceFile)
{
	m_bStepOn=false;
	this->m_strSourceFile=strSourceFile;
	this->m_pTokenFile=pTokenFile;
	this->m_pSymbolTable=pSymbolTable;
	this->m_pErrorCollection=pErrorCollection;
	for (int i=0;i<KEYWORDCOUNT+1;i++)
	{
		this->m_pWordCode[i]=pWordCode[i];
	}
}

/**
 * 初始化各链表头部信息
 *
 */
bool CMorpheme::Init()
{
	m_pSymbolTable->intTableSize=100;
	m_pSymbolTable->intTableLen=0;
	m_pSymbolTable->sSubTable=new SSubTable[100];
	if (m_pSymbolTable->sSubTable==NULL)
	{
		::AfxMessageBox("系统初始化失败!",MB_ICONWARNING | MB_OK);
		return false;
	}
	m_pSymbolTable->intSubTableSize=100;
	m_pSymbolTable->intSubTableLen=0;
	m_pSymbolTable->stringTable=new char[100];
	if (m_pSymbolTable->stringTable==NULL)
	{
		::AfxMessageBox("系统初始化失败!",MB_ICONWARNING | MB_OK);
		return false;
	}

	m_pTokenFile->next=NULL;
	this->m_rearToken=m_pTokenFile;

	m_pErrorCollection->next=NULL;
	this->m_rearError=m_pErrorCollection;

	// 初始化 行,列计数
	this->m_rowCount=0;
	this->m_colsCount=0;

	return true;
}

/**
 * 打开源程序文件
 *
 */
bool CMorpheme::OpenSource()
{
	this->m_finSource.open(m_strSourceFile);
	if (m_finSource.fail())
	{
		::AfxMessageBox("源程序文件打开失败!",MB_ICONWARNING | MB_OK);
		CloseSource();
		return false;
	}

	return true;
}

/**
 * 关闭源程序文件
 *
 */
void CMorpheme::CloseSource()
{
	this->m_finSource.close();
}

/**
 * 从源程序文件中度曲一行
 *
 */
int CMorpheme::ReadLine()
{
	if (!m_finSource.eof())
	{
		this->m_colsCount=0;					//列清0
		this->m_rowCount++;						//行加一

		m_finSource.getline(m_strLine,MAXLINE);
		m_strLine[MAXLINE-1]='\0';

		return 1;
	}
	else
	{
		this->m_colsCount=0;					//列清0
		this->m_strLine[0]='\0';
		return 0;
	}
	
	return -1;
}

/**
 * 从当前行中读取一个非空字符
 *
 */
char CMorpheme::GetCharNoNULL()
{
	int readFlg;

	while (m_strLine[m_colsCount]==' ' || m_strLine[m_colsCount]=='\t' || m_strLine[m_colsCount]=='\0')
	{
		if (m_strLine[m_colsCount]=='\0')
		{
			readFlg=ReadLine();

			if (readFlg==-1)
			{
				AfxMessageBox("系统错误!",MB_ICONWARNING | MB_OK);
				return -1;
			}
			if (readFlg==0)
			{
				return -1;
			}
			m_colsCount--;
		}
		m_colsCount++;
	}

	m_colsCount++;

	return m_strLine[m_colsCount-1];

}

/**
 * 从当前行中读取一个字符
 *
 */
char CMorpheme::GetChar()
{	
	if (this->m_strLine[m_colsCount]=='\0')
	{		
		return -1;
	}

	m_colsCount++;

	if (m_strLine[m_colsCount-1]==' ' || m_strLine[m_colsCount-1]=='\t')
	{
		return -2;
	}	

	return m_strLine[m_colsCount-1];

}

/**
 * 判断当前给定的字符串是否是关键字
 *
 * @param  str		给定的字符串
 *
 */
unsigned int CMorpheme::IsKeyId(const char *str)
{
	for (int i=1;i<KEYWORDCOUNT;i++)
	{
		if (strcmp(str,m_pWordCode[i])==0)
		{
			return i;
		}
	}

	return 0;//不存在
}

/**
 * 查找当前给定的关键字在字符表中的索引号
 *
 * @param  str		给定的字符串
 *
 */
unsigned int CMorpheme::FindKeyId(const char *str)
{
	if (strcmp(str,"constchar")==0)
	{//字符常数
		return 32;
	}
	if (strcmp(str,"constfloat")==0)
	{//实常数
		return 33;
	}
	if (strcmp(str,"constint")==0)
	{//整常数
		return 34;
	}
	if (strcmp(str,"identifier")==0)
	{//标识符
		return 40;
	}

	for (int i=1;i<KEYWORDCOUNT;i++)
	{
		if (strcmp(str,m_pWordCode[i])==0)
		{
			return i;
		}
	}

	return 0;//不存在
}

/**
 * 开始识别标示符
 *
 * @param  ch		给定的开始字符
 *
 */
bool CMorpheme::RecogId(char ch)
{
	bool returnValue=true;
	CString word="";
	word+=ch;

	char charGet=GetChar();
	while (('0'<=charGet && charGet<='9') || ('a'<=charGet && charGet<='z') || ('A'<=charGet && charGet<='Z'))
	{
		word+=charGet;
		charGet=GetChar();
	}

	unsigned keyId;

	if (charGet!=-2 && charGet!=-1)
	{
		char chch[2];
		chch[0]=charGet;
		chch[1]='\0';
		keyId=IsKeyId(chch);
		if (keyId!=0)
		{
			this->m_colsCount--;//列计数-1
		}
		else
		{//非法字符
			AddError(this->m_rowCount,this->m_colsCount,"非法字符!");
			returnValue=false;
		}
	}
	
	keyId=IsKeyId((LPCTSTR)word);
	if (keyId > 0)
	{//关键字
		//添加token
		this->AddToken(keyId,0);
	}
	else
	{
		//标识符种别码
		unsigned id=this->FindKeyId("identifier");
		//入口地址
		unsigned entry=this->LookUp((LPCTSTR)word,Identifier);
		//添加token
		this->AddToken(id,entry);
	}

	return returnValue;
}

/**
 * 添加错误信息
 *
 * @param  rows			行号
 * @param  cols			列号
 * @param  description	错误描述信息
 *
 */
bool CMorpheme::AddError(const char *description,unsigned int rows/*=0*/,unsigned int cols/*=0*/)
{
	return AddError(rows,cols,description);
}

/**
 * 添加错误信息
 *
 * @param  rows			行号
 * @param  cols			列号
 * @param  description	错误描述信息
 *
 */
bool CMorpheme::AddError(unsigned int rows,unsigned int cols,const char *description)
{
	m_rearError->next=new ErrorNode;
	char *ch=new char[strlen(description)+1];
	if (m_rearError->next==NULL || ch==NULL)
	{
		AfxMessageBox("内存分配失败!",MB_ICONWARNING | MB_OK);
		return false;
	}
	m_rearError=m_rearError->next;
	m_rearError->intCols=cols;
	m_rearError->intRows=rows;
	strcpy(ch,description);
	m_rearError->description=ch;
	m_rearError->next=NULL;

	return true;
}

/**
 * 添加token信息
 *
 * @param  keycode		类型种别码
 * @param  strId		自身值
 *
 */
bool CMorpheme::AddToken(unsigned char keycode,unsigned int strId)
{
	m_rearToken->next=new TokenNode;
	if (m_rearToken->next==NULL)
	{
		AfxMessageBox("内存分配失败!",MB_ICONWARNING | MB_OK);
		return false;
	}
	m_rearToken=m_rearToken->next;
	m_rearToken->strId=strId;
	m_rearToken->keycode=keycode;
	m_rearToken->next=NULL;

	return true;
}

/**
 * 删除token字
 *
 * @param  pToken		给定删除token字
 *
 */
bool CMorpheme::DeleteToken(PTokenNode pToken)
{
	PTokenNode pPreToken=NULL,pCurToken=NULL;

	if (this->m_pTokenFile->next==NULL) return false;
	if (pToken==NULL) return true;
	pPreToken=this->m_pTokenFile;
	pCurToken=this->m_pTokenFile->next;

	while (pCurToken!=NULL && pCurToken!=pToken)
	{
		pPreToken=pCurToken;
		pCurToken=pCurToken->next;
	}

	if (pToken==pCurToken)
	{
		pPreToken->next=pCurToken->next;

		if (pCurToken==this->m_rearToken)
		{
			this->m_rearToken=pPreToken;
			this->m_rearToken->next=NULL;
		}	
		
		delete (pCurToken);		
	}
	else
	{
		return false;
	}

	return true;
}

/**
 * 开始识别界限符
 *
 * @param  ch		给定的开始字符
 *
 */
bool CMorpheme::RecogDel(char ch)
{
	unsigned int keyId;
	char ch2;
	char chch[3]={'\0','\0','\0'};
	chch[0]=ch;

	switch(ch)
	{
	case '(':
	case ')':		
	case '*':
	case '+':
	case ',':
	case '-':
	case ';':
	case '[':
	case ']':
	case '=':
		//单字符界限符
		break;
	case '.':
		ch2=this->GetChar();
		if (ch2=='.')
		{
			chch[1]='.';
		}
		else if (ch2!=-1)
		{
			this->m_colsCount--;
		}
		break;
	case ':':
		ch2=this->GetChar();
		if (ch2=='=')
		{
			chch[1]='=';
		}
		else if (ch2!=-1)
		{
			this->m_colsCount--;
		}
		break;
	case '<':
		ch2=this->GetChar();
		if (ch2=='=' || ch2=='>')
		{
			chch[1]=ch2;
		}
		else if (ch2!=-1)
		{
			this->m_colsCount--;
		}
		break;
	case '>':
		ch2=this->GetChar();
		if (ch2=='=')
		{
			chch[1]='=';
		}
		else if (ch2!=-1)
		{
			this->m_colsCount--;
		}
		break;
	default:
		AddError(this->m_rowCount,this->m_colsCount,"非法字符!");
		return false;
		break;
	}

	keyId=this->FindKeyId(chch);
	this->AddToken(keyId,0);

	return true;
}

/**
 * 开始识别数字常数
 *
 * @param  ch		给定的开始字符
 *
 */
bool CMorpheme::RecogDigit(char ch)
{
	CString word="";
	word+=ch;

	char charGet=GetChar();
	bool firstDot=true;
	::SType digitType=Integer;
	while (('0'<=charGet && charGet<='9') || (charGet=='.'))
	{
		if (charGet=='.')
		{
			//当读入两个'.'时,出错
			if (!firstDot) break;

			char ch2=this->GetChar();
			if (ch2=='.')
			{
				//整数常数识别成功;识别了标识符 ..
				this->m_colsCount--;
				break;
			}
			else if (ch2==-2 || ch2==-1)
			{
				//实数常数识别成功
				digitType=Real;
				break;
			}
			else
			{
				this->m_colsCount--;
				firstDot=false;
			}
		}		
		word+=charGet;
		charGet=GetChar();
	}
	//列计数-1
	if (charGet!=-1) this->m_colsCount--;	
	if (!firstDot) digitType=Real;
	unsigned id;
	//数字常数种别码
	if (digitType==Real)
	{
		id=this->FindKeyId("constfloat");
	}
	else
	{
		id=this->FindKeyId("constint");
	}
	//入口地址
	unsigned entry=this->LookUp((LPCTSTR)word,digitType);
	//添加token
	this->AddToken(id,entry);
	return true;
}

/**
 * 开始识别字符常数

⌨️ 快捷键说明

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