📄 cifa.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 + -