📄 scanner.cpp
字号:
#include "scanner.h"
#define TOKEN_LEN 100
static FILE *InFile; //输入的文件
unsigned int LineNo; //记录记号所在位置(行数)
static char TokenBuffer[TOKEN_LEN]; //记号缓冲区
//初始化词法分析器
int InitScanner(const char *Filename)
{
LineNo=1;
InFile=fopen(Filename,"r"); //打开文件
if(InFile!=NULL)return 1; //打开文件成功
else return 0; //打开文件失败
}
//关闭词法分析器
void CloseScanner(void)
{
if(InFile!=NULL)fclose(InFile);//关闭所打开的文件
}
//从文件中获取一个字符
static char GetChar(void)
{
int Char=getc(InFile); //获取字符
return toupper(Char); //保持大小写一致
}
//把预读的字符回退到输入源程序中
static void BackChar(char Char)
{
if(Char!=EOF)ungetc(Char,InFile);//当不是文件结束符时回退字符
}
//将字符加入记号缓冲区
static void AddCharTokenString(char Char)
{
int TokenLength=strlen(TokenBuffer); //获取当前字符缓冲区的长度
if(TokenLength+1>=sizeof(TokenBuffer))return;//判断长度是否超出缓冲区范围
TokenBuffer[TokenLength]=Char; //将当前字符加入字符缓冲区
TokenBuffer[TokenLength+1]='\0'; //将下一位置为结束符
}
//清空记号缓冲区
static void EmptyTokenString()
{
memset(TokenBuffer,0,TOKEN_LEN);
}
//判断所给字符是否在符号表中
static Token JudgeKeyToken(const char*IDString)
{
int loop; //定义循环变量
for(loop=0;loop<sizeof(TokenTab)/sizeof(TokenTab[0]);loop++)
//判断所给字符是否在符号表中
{
//符号表存在该符号
if(strcmp(TokenTab[loop].lexeme,IDString)==0)
return TokenTab[loop];
}
//不存在该符号,进行出错处理
Token errortoken;
memset(&errortoken,0,sizeof(Token));
errortoken.type=ERRTOKEN;
return errortoken;
}
//获取一个记号
extern Token GetToken(void)
{
Token token;
int Char;
memset(&token,0,sizeof(Token));
EmptyTokenString();
token.lexeme=TokenBuffer;
for(;;)//过滤源程序中的空格、TAB、回车等,遇到文件结束符返回空记号
{
Char=GetChar();//获取一个字符
if(Char==EOF)//判断是否是文件结束符
{
token.type=NONTOKEN;
return token;
}
if(Char=='\n')LineNo++;//当是回车符时,行数加一
if(!isspace(Char))break;//不是空格,则跳出循环,进行字符判断
}
AddCharTokenString(Char);//将当前记号加入记号缓冲区
if(isalpha(Char))//判断记号是否是保留字或参数名
{
for(;;)//将整个记号存入记号缓冲区
{
Char=GetChar();
if(isalnum(Char))AddCharTokenString(Char);
else break;
}
BackChar(Char);
token=JudgeKeyToken(TokenBuffer);//判断记号类别
token.lexeme=TokenBuffer;//获得记号
return token;
}
else if(isdigit(Char))//判断记号是否是数字
{
for(;;)//获得整个整数并存入记号缓冲区
{
Char=GetChar();
if(isdigit(Char))AddCharTokenString(Char);
else break;
}
if(Char=='.')//若存在小数,则将小数部分也存入记号缓冲区
{
AddCharTokenString(Char);
for(;;)
{
Char=GetChar();
if(isdigit(Char))AddCharTokenString(Char);
else break;
}
}
BackChar(Char);
token.type=CONST_ID;
token.value=atof(TokenBuffer);//获得数字的值
return token;
}
else //不是字符和数字,则一定是运算符或分割符
{
switch(Char)
{ case';':token.type=SEMICO;break;
case'(':token.type=L_BRACKET;break;
case')':token.type=R_BRACKET;break;
case',':token.type=COMMA;break;
case'+':token.type=PLUS;break;
case'-':
Char=GetChar();
if(Char=='-')//若是双减号,表示注释符
{
while(Char!='\n'&&Char!=EOF)Char=GetChar();
BackChar(Char);
return GetToken();
}
else//若是单减号,就表示减法
{
BackChar(Char);
token.type=MINUS;
break;
}
case'/':
Char=GetChar();
if(Char=='/')//若是双除号,表示注释符
{
while(Char!='\n'&&Char!=EOF)Char=GetChar();
BackChar(Char);
return GetToken();
}
else//若是单除号,表示是除法
{
BackChar(Char);
token.type=DIV;
break;
}
case'*':
Char=GetChar();
if(Char=='*')//若是双乘号,表示乘方运算
{
token.type=POWER;
break;
}
else//若是单乘号,表示乘法
{
BackChar(Char);
token.type=MUL;
break;
}
default:token.type=ERRTOKEN;break;
}
}
return token;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -