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

📄 cifa.cpp

📁 词法分析程序
💻 CPP
字号:
/****************************************************/
/* 文件: Cifa.cpp	                                */
/*词法分析器										*/
/*作者:赖荣凤		02282021						*/
/*2004年10月30日									*/
/****************************************************/
// Cifa.cpp: implementation of the CCifa class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "SmartC.h"
#include "Cifa.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#if !defined MYKEYWORDKEYWORD
#define MYKEYWORDKEYWORD
char MyKeyword[][8]={{"NULL"},{"if"},{"else"},
{"while"},{"return"},{"main"},{"for"},{"false"},{"ture"},{"int"},{"void"}};
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

Cifa::Cifa(CEdit* MyEdit,Error* MyError)
{
	theError=MyError;
	theEdit=MyEdit;
	int j=theEdit->GetLine(0,buf,200);
	buf[j]=0;
	lenth=strlen(buf);
	current=0;
	pchar=buf[current];
	line_no=1;
	token_lenth=0;
}
Cifa::~Cifa(void)
{
//	CMFile.Close();
}
//在buf中读下一字符,
void Cifa::GetChar(void)
{
	if(current>=lenth)//到行尾,令pchar=0
		pchar=0;
	else
	{
		current++;
		pchar=buf[current];
	}
}
//每次取token时都先调用此函数  token_lenth=0
//每次调用检查pchar是否为空,若为空反复调用GetChar直至不为空
//GetNBC还负责从文件中读字符串到buf 返回MYEOF表示到了尾,否则返回READING
int Cifa::GetNBC(void)
{
	token_lenth=0;//取下一个token了
	
	while(pchar==' '||pchar=='\t')
		GetChar();
	int linenum=theEdit->GetLineCount();
	///遇上回车 换行符 或到了buf行尾(里面的字符处理完)则读下一行
	if(pchar=='\n'||pchar==13||pchar==0)
	{
		if(line_no<=linenum)
		{
			//从控件中读数据
			int j=theEdit->GetLine(line_no,buf,200);
			buf[j]=0;
		//	if(pchar=='\r')
			line_no++;
			lenth=strlen(buf);
			current=0;
			pchar=buf[current];
			return GetNBC();
		}
		else//the end of file
			return MYEOF;//此时pchar=0
	}
	return READING;
}
//把*pchar 与token 相连接
void Cifa::Cat(void)
{
	token[token_lenth]=pchar;
	token_lenth++;
	token[token_lenth]=0;//字符串结尾标志
}
//判断*pchar中的字符是否为数字
int Cifa::Digit(void)
{
	if(pchar>='0'&&pchar<='9')
		return 1;
	else 
		return 0;
}
//判断*pchar中的字符是否为字母
int Cifa::Letter(void)
{
	if(pchar>='a'&&pchar<='z'||pchar>='A'&&pchar<='Z')
		return 1;
	else 
		return 0;
}
/*
//退回一格
void Cifa::Retract(void)
{
	current--;
	if(current<0)//正常应用GetChar 和Retract的情况下 不会出现这种情况
		current=0;
	pchar=buf[current];
}
//将token中的数字串转化为数值
int Cifa::strtoint(void)
{
	int temp=0;
	int i=0;
	while(i<strlen(token))
	{
		temp*=10;
		temp+=*pchar-'0';
	}
	return temp;
}*/
//查关键字

int Cifa::Reserve(void)
{
	int i=0;
	for(i=0;i<11;i++)
	{
		if(strcmp(MyKeyword[i],token)==0)
		{
			if(i==10)
				return VOIDSY;//void
			return i;//others
		}
	}
	return -1;
}
//错误处理
void Cifa::MyError(int type,int lineno)
{
	//cout<<"Eror type:\t"<<type<<"in line: "<<lineno<<endl;
	theError->ShowError(type,lineno);
}
//获取行号
int Cifa::GetLineNO()
{
	return line_no;
}
//获取下一个token的类型和值
//应用GetChar 和Retract 使pchar总是保持为下一个要分析的字符
int Cifa::GetNextToken(TOKEN *t)
{
	int type;
	//先处理空格 换行符和读下一行
	if(GetNBC()==MYEOF)
	{
		t->tokentype=MYEOF;
		t->pchar=NULL;
		return MYEOF;
	}
	//打印行号
	//cout<<line_no<<":"<<endl;
	if(Letter())
	{
		while(Letter()||Digit())//取字串
		{
			Cat();
			GetChar();
		}
	//	Retract();//退回一格
		type=Reserve();
		if(type!=-1)//是关键字
		{
			t->tokentype=type;
			t->pchar=token;
			return type;
		}
		else
		{
			t->tokentype=IDSY;
			t->pchar=token;
			return IDSY;//是标识符
		}
	}
	else if(Digit())
	{
		while(Digit())
		{
			Cat();
			GetChar();
		}
	//	Retract();
		t->tokentype=DIGITSY;
		t->pchar=token;
		return DIGITSY;//是整数
	}
	else 
	{
		switch(pchar)
		{
		case '+':
			Cat();
			GetChar();
			if(pchar=='+')//++
			{
				Cat();
				t->tokentype=ADDADDSY;
				t->pchar=token;
				//读下一个字符,使pchar总是保持为下一个要分析的字符
				GetChar();
				return ADDADDSY;
			}
			else//+
			{
				t->tokentype=PLUSSY;
				t->pchar=token;
				return PLUSSY;
			}
			break;
		case '-':
			GetChar();
			if(pchar=='-')//--
			{
				Cat();
				t->tokentype=SUBSUBSY;
				t->pchar=token;
				//读下一个字符,使pchar总是保持为下一个要分析的字符
				GetChar();
				return SUBSUBSY;
			}
			else//-
			{
				t->tokentype=MINUSSY;
				t->pchar=token;
				return MINUSSY;
			}
			break;
		case '*':
			Cat();
			t->tokentype=STARSY;
			t->pchar=token;
			//读下一个字符,使pchar总是保持为下一个要分析的字符
			GetChar();
			return STARSY;
			break;
		case ';':
			Cat();
			t->tokentype=SEMISY;
			t->pchar=token;
			//读下一个字符,使pchar总是保持为下一个要分析的字符
			GetChar();
			return SEMISY;
			break;
		case ',':
			Cat();
			t->tokentype=COMMASY;
			t->pchar=token;
			//读下一个字符,使pchar总是保持为下一个要分析的字符
			GetChar();
			return COMMASY;
			break;
		case '(':
			Cat();
			t->tokentype=LPARSY;
			t->pchar=token;
			//读下一个字符,使pchar总是保持为下一个要分析的字符
			GetChar();
			return LPARSY;
			break;
		case ')':
			Cat();
			t->tokentype=RPARSY;
			t->pchar=token;
			//读下一个字符,使pchar总是保持为下一个要分析的字符
			GetChar();
			return RPARSY;
			break;
		case '=':
			Cat();
			GetChar();
			if(pchar=='=')//==
			{
				Cat();
				t->tokentype=EQUSY;
				t->pchar=token;
				//读下一个字符,使pchar总是保持为下一个要分析的字符
				GetChar();
				return EQUSY;//:=
			}
			else//=
			{
				t->tokentype=ASSIGNSY;
				t->pchar=token;
				return ASSIGNSY;
			}
			break;
		case '/':
			Cat();
			GetChar();
			if(pchar=='*')///*读注释
			{
				GetChar();
				while(1)
				{
					if(pchar=='*')
					{
						GetChar();
						if(pchar=='/')
							break;
						//判断是否到了行尾或文件尾
						//处理到了行尾并读文件
						if(GetNBC()==MYEOF)
						{
							MyError(NOTICE,line_no);
							break;
						}
						
					}
					else
					{
						GetChar();
						//判断是否到了行尾或文件尾
						//处理到了行尾并读文件
						if(GetNBC()==MYEOF)
						{
							MyError(NOTICE,line_no);
							break;
						}
					}
				}
				//读下一个字符,使pchar总是保持为下一个要分析的字符
				GetChar();
				return	GetNextToken(t);
			}
			else if(pchar=='/') // is // 行注釋
			{
				while(pchar!=0)
					GetChar();
				return GetNextToken(t);
			}
			else// /
			{
				t->tokentype=DIVISY;
				t->pchar=token;
				return DIVISY;
			}
			break;
		case '<':
			Cat();
			GetChar();
			if(pchar=='=')//<=
			{
				Cat();
				t->tokentype=LESSEQUSY;
				t->pchar=token;
				//读下一个字符,使pchar总是保持为下一个要分析的字符
				GetChar();
				return LESSEQUSY;
			}
			else if(pchar=='<')//<<
			{
				Cat();
				t->tokentype=OUTPUTSY;
				t->pchar=token;
				//读下一个字符,使pchar总是保持为下一个要分析的字符
				GetChar();
				return OUTPUTSY;
			}
			else//<
			{
				t->tokentype=LESSSY;
				t->pchar=token;
				return LESSSY;
			}
			break;
		case '>':
			Cat();
			GetChar();
			if(pchar=='=')//>=
			{
				Cat();
				t->tokentype=GREATEQUSY;
				t->pchar=token;
				//读下一个字符,使pchar总是保持为下一个要分析的字符
				GetChar();
				return GREATEQUSY;
			}
			else if(pchar=='<')//>>
			{
				Cat();
				t->tokentype=INPUTSY;
				t->pchar=token;
				//读下一个字符,使pchar总是保持为下一个要分析的字符
				GetChar();
				return INPUTSY;
			}
			else//>
			{
				t->tokentype=GREATSY;
				t->pchar=token;
				return GREATSY;
			}
			break;
		case '!':
			Cat();
			GetChar();
			if(pchar=='=')//!=
			{
				Cat();
				t->tokentype=UNEQUSY;
				t->pchar=token;
				//读下一个字符,使pchar总是保持为下一个要分析的字符
				GetChar();
				return UNEQUSY;
			}
			else//!
			{
				t->tokentype=NOTSY;
				t->pchar=token;
				return NOTSY;
			}
			break;
		case '[':
			Cat();
			t->tokentype=LMPARSY;
			t->pchar=token;
			//读下一个字符,使pchar总是保持为下一个要分析的字符
			GetChar();
			return LMPARSY;
			break;
		case ']':
			Cat();
			t->tokentype=RMPARSY;
			t->pchar=token;
			//读下一个字符,使pchar总是保持为下一个要分析的字符
			GetChar();
			return RMPARSY;
			break;
		case '{':
			Cat();
			t->tokentype=LBPARSY;
			t->pchar=token;
			//读下一个字符,使pchar总是保持为下一个要分析的字符
			GetChar();
			return LBPARSY;
			break;
		case '}':
			Cat();
			t->tokentype=RBPARSY;
			t->pchar=token;
			//读下一个字符,使pchar总是保持为下一个要分析的字符
			GetChar();
			return RBPARSY;
			break;
		case '\"'://"
			//Cat(); delete "
			GetChar();
			//34=\"
			while(pchar!='\"')//在没有遇到下一个"时一直读取到token中,按字符串处理
			{
				if(pchar!=0)
				{
					Cat();
					GetChar();
				}
				else//end of line
				{
					MyError(CSTRINGSY,line_no);
					return GetNextToken(t);
					break;
				}
			}
			if(pchar=='\"')//安全退出while
			{
				t->tokentype=CSTRINGSY;
				t->pchar=token;
				GetChar();//读下一个字符,使pchar总是保持为下一个要分析的字符
				return CSTRINGSY;
			}
			else
				return GetNextToken(t);
			break;
		case '|':
			Cat();
			GetChar();
			if(pchar=='|')//||
			{
				Cat();
				t->tokentype=ORSY;
				t->pchar=token;
				//读下一个字符,使pchar总是保持为下一个要分析的字符
				GetChar();
				return ORSY;
			}
			else
			{
				MyError(ORSY,line_no);
				return GetNextToken(t);
			}
			break;
		case '&':
			Cat();
			GetChar();
			if(pchar=='&')//&&
			{
				Cat();
				t->tokentype=ANDSY;
				t->pchar=token;
				//读下一个字符,使pchar总是保持为下一个要分析的字符
				GetChar();
				return ANDSY;
			}
			else
			{
				MyError(ANDSY,line_no);
				return GetNextToken(t);
			}
			break;
		default:
			MyError(0,line_no);
			//读下一个字符,使pchar总是保持为下一个要分析的字符
			GetChar();
			return	GetNextToken(t);
			break;
		}
	}
}

⌨️ 快捷键说明

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