📄 scanner.cpp
字号:
#include "scanner.h"
#define TOKEN_LEN 100 //记号最大长度
unsigned int LineNo; //跟踪源文件行号
static FILE *InFile; //输入文件流
static char TokenBuffer[TOKEN_LEN]; //记号字符缓冲
//--------------初始化词法分析器
extern int InitScanner(const char *FileName)
{
LineNo = 1;
InFile = fopen(FileName, "r");
if (InFile != NULL) return 1;
else return 0;
}
//-------------关闭词法分析器
extern 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)) //若 char是A-Za-z,则一定是函数、关键字、PI、E等
{
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.values = 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 + -