词法分析器——C++实现


单词符号表示
(1)标识符:以字母开头的包含字母和数字的符号
(2)保留字:while、if、else、switch、case
(3)常数:数字0~9
(4)运算符:+、-、*、<、<=、==、=
(5)界符:;
(6)需略除的:空格、制表符、换行符
主要函数
concatenation() //连接token和character中字符作为token中新的字符串
letter ()//判断是否字母
digit() //判断是否数字
reserve() //按照token数组中的字符串查找表判断是否为保留字,是返回编码,否则返回0
retract() //扫描指针回退一个字符,同时将character置换为空白
buildlist() //将标识符登录到符号表中或将常数登录到常数表中
error() //出现非法字符,显示错误信息
getchar_syx()//读取数据
getbe() //剔除多余的空白符
solve() //进行测试
代码实现
变量
const int N = 1005;
const char keyWord[][20] = {"while", "if", "else", "switch", "case"};
int number_table[N], number_point, id_point; //常数表,常数数量,标识符数量
char identifier_table[N][105]; //标识符表
int present_point; //当前点位
char inn[N]; //输入
int inn_point;
char character; //字符,存最新读入的源程序字符
char token[N]; //字符数组,存构成单词符号的字符串
int token_point; //字符串当前字符
连接字符串
void concatenation() //连接token和character中字符作为token中新的字符串
{
token[token_point] = character;
token_point++;
token[token_point] = '\0';
}
判断字母或数字
bool letter(char tem) //判断是否字母
{
if (tem >= 'a' && tem <= 'z')
return true;
if (tem >= 'A' && tem <= 'Z')
return true;
return false;
}
bool digit(char tem) //判断是否数字
{
if (tem >= '0' && tem <= '9')
return true;
return false;
}
查找保留字符串
int reserve() //按照token数组中的字符串查找表判断是否为保留字,是返回编码,否则返回0
{
for (int i = 0; i < 5; i++)
{
if (!strcmp(token, keyWord[i]))
return i + 1;
}
return 0;
}
回退字符
void retract() //扫描指针回退一个字符,同时将character置换为空白
{
inn_point--;
character = ' ';
}
登录到表中
void buildlist() //将标识符登录到符号表中或将常数登录到常数表中
{
char temp = token[0] - '0'; //用于判断当前token中的字符串是标识符还是常数
int temp_num = 0; //存放转换后的常数值
/*******************************常数登记到常数表中*********************************/
if (temp >= 0 && temp <= 9)
{
temp_num = atoi(token); //将token中的字符串转换成常数
int i;
for (i = 0; i < number_point; i++)
{
if (temp_num == number_table[i])
{ //如果常数表中已存在该常数
present_point = i;
cout << "已存在该常数"
<< " ";
break;
}
}
if (i == number_point)
{ //如果常数表中没有该常数,则登记该常数
number_table[number_point] = temp_num;
present_point = number_point;
number_point++;
}
}
/************************将标识符登记到常数表中*****************************/
else
{
int i = 0;
for (i; i < id_point; i++)
{
if (strcmp(token, identifier_table[i]) == 0)
{ //如果标识符表中已存在该字符串
present_point = i;
cout << "已存在该字符串"
<< " ";
break;
}
}
if (i == id_point)
{ //如果标识符表中没有该字符串,则登记该标识符
strcpy_s(identifier_table[i], sizeof(token), token);
present_point = id_point;
id_point++;
}
}
}
错误信息
void error() //出现非法字符,显示错误信息
{
printf("非法字符:%c\n", character);
}
扫描数据
void getchar_syx()
{
character = inn[inn_point++];
}
去除空格
void getbe() //剔除多余的空白符
{
while (character == ' ')
{
character = inn[inn_point++];
}
}
进行测试
void solve()
{
token_point = 0; // token指针初始化
getchar_syx(); //获取字符
getbe(); //滤除空格
if (character >= 'a' && character <= 'z'||character >= 'A' && character <= 'Z')
{
/*字母开头,为标识符/保留字*/
while (letter(character) || digit(character))
{
/*标识符包括字母和数字*/
concatenation(); //将当前读入的字符送入token数组
getchar_syx();
}
retract(); //扫描指针回退一个字符
int c = reserve();
if (c == 0)
{
buildlist(); //将标识符登录到符号表中
cout << identifier_table[present_point] << " " << present_point << endl;
}
else
{
cout << c << " " << keyWord[c - 1] << endl;
}
}
else if (character >= '0' && character <= '9')
{
/*数字开头,为常数*/
while (digit(character))
{
/*常数只包括数字*/
concatenation();
getchar_syx();
}
retract();
buildlist(); //将常数登录到常数表中
cout << number_table[present_point] << " " << present_point << endl;
}
else if (character == '+')
cout << "+" << endl;
else if (character == '-')
cout << "-" << endl;
else if (character == '*')
cout << "*" << endl;
else if (character == '<')
{
getchar_syx();
if (character == '=')
cout << "relop"
<< ","
<< "LE" << endl;
else
{
retract();
cout << "relop"
<< ","
<< "LT" << endl;
}
}
else if (character == '=')
{
getchar_syx();
if (character == '=')
cout << "relop"
<< ","
<< "EQ" << endl;
else
{
retract();
cout << "=" << endl;
}
}
else if (character == ';')
cout << ";" << endl;
else
{
if (character == '\n' || character == '\t' || character == EOF)
return;
error(); //出错
}
}
主函数
int main()
{
strcpy(inn, "this is test one AXasd fDSxt 123321 +asd123 555<=124 55==45"); //测试数据
inn_point = 0;
while (inn[inn_point] != '\0')
{
solve();
}
return 0;
}
样例输出
this 0
is 1
test 2
one 3
AXasd 4
fDSxt 5
123321 0
+
asd123 6
555 1
relop,LE
124 2
55 3
relop,EQ
45 4
这篇博客介绍了一个用C++编写的词法分析器,它能够识别和处理标识符、保留字、常数、运算符、界符等基本元素。程序包括了对字符的判断、保留字查找、符号表登记等功能,并提供了错误处理机制。通过示例输入和输出展示了其工作过程。
1万+





