一.实验题目
设计基于C语言的词法分析器
二.实验目的
通过设计编制调试 C 语言的词法分析程序,加
深对词法分析原理的理解。并掌握在对程序设计语言源程
序进行扫描过程中将其分解为各类单词的词法分析方法。
编制一个读单词过程,从输入的源程序中,识别出各个具
有独立意义的单词,即基本字、标识符、常数、运算符、
分隔符五大类。并依次输出各个单词的内部编码及单词符
号自身值.
三:程序代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include <string>
#include <iostream>
//#include<iostream.h>
using namespace std;
string keywords[20] = { "include","void","main","int",
"char","float","double","if",
"else","then","break","continue",
"for","do","while","printf","scanf",
"begin","end","return" };
char rz[99999] = " ";
string id[10000];
int pp = 0;
string nu[10000];
int qq = 0;
int isLetter(char a) //判断是否是字母
{
if ((a >= 'a' && a <= 'z')||(a >= 'A'&& a <= 'Z')) {
return 1;
}
return 0;
}
int isDigit(char a) //判断是否是数字
{
if (a <= '9' && a >= '0') {
return 1;
}
return 0;
}
int alpha(int st) //识别保留字和标识符,给此函数的的语句加上注释
{
char wordbuf[20] = " ";//定义一个数组wordbuf,用来接收rz中的字符
int n = 0;//用n来记录wordbuf的数组下标
for (;;)//用for循环,循环下列语句
{
wordbuf[n] = rz[st];//将rz数组中的元素录入wordbuf中
st++;//数组下标进行移动
n++;//数组下标进行移动
if ((isDigit(rz[st]) == 1) || (isLetter(rz[st]) == 1) || (rz[st] == '_'))
//判断是字母,数字还是_
wordbuf[n] = rz[st];//将数字,字母或'_'录入wordbuf中
else
break;//否则跳出循环
}
int flag = 0;//定义一个flag变量
for (int k = 0; k < 20; k++)//循环下列语句
{
if (strcmp(keywords[k].c_str(), wordbuf) == 0)//判断是否为关键字
flag = 1;//若是关键字flag被赋为1
}
if (flag == 0)//判断flag是否为0,等于0执行下列语句
{
int flagg = -1;//定义变量flagg,并赋值为-1
for (int t = 0; t < pp; t++)//循环下列语句
{
if (strcmp(id[t].c_str(), wordbuf) == 0)//判断字母是否相等
{
flagg = t;//相等的话把t赋给flagg
}
}
if (flagg != -1)//判断flagg的值是否不等于-1
printf(" (id,%d) ", flagg);//若不等于-1打印flagg的值
Else//flagg == -1
{
id[pp] = wordbuf;//将wordbuf数组元素赋给id数组
printf(" (id,%d) ", pp);//打印pp当前的值
pp++;//pp自增
}
}
Else//flag不等于0
{
printf(" (");//打印 (
for (int i = 0; i < n; i++)//循环打印wordbuf数组中的字符
{
printf("%c", wordbuf[i]);
}
printf(",-) ");//循环结束打印 -)
}
return st;//返回st当前的值
}
int number(int st) //识别整数
{
char numbuf[20] = " ";
int n = 0;
int k = 0;
int flag = 0;
for (;;)
{
numbuf[n] = rz[st];
st++;
n++;
if (isDigit(rz[st]) == 1)
{
numbuf[n] = rz[st];
}
else if ((k == 0) && (rz[st] == '.'))
{
numbuf[n] = rz[st];
k++;
}
else if (isLetter(rz[st]) == 1)
{
numbuf[n] = rz[st];
flag = 1;
continue;
}
else
break;
}
if (flag == 0)
{
int flagg = -1;
for (int t = 0; t < qq; t++)
if (strcmp(nu[t].c_str(), numbuf) == 0)
flagg = t;
if (flagg != -1)
printf(" (nu,%d) ", flagg);
else
{
nu[qq] = numbuf;
printf(" (nu,%d) ", qq);
qq++;
}
}
else {
printf(" (");
for (int i = 0; i < n; i++)
printf("%c", numbuf[i]);
printf(",error digital!) ");
}
return st;
}
int anotation(int st) //处理除号/和注释,给此函数的语句加上注释
{
char tabuf[9999] = " ";//定义一个tabuf数组
int n = 0;
st++;
if (rz[st] == '/')//判断rz数组中st下标对应的元素是否为 / ,是执行下列语句
{
printf(" (//,-)");//打印注释符号 '//'
st++;//st自增
while (rz[st] != 10)//循环直到rz数组中st下标对应的元素为10为止
{
tabuf[n] = rz[st];//将rz数组中st下标对应的元素赋给tabuf
st++;//st自增
n++;//n自增
}
printf(" \n 注释");//换行打印"注释"
for (int i = 0; i < n; i++)//循环打印出注释的句子
printf("%c", tabuf[i]);
}
else if (rz[st] == '*')//否则判断rz数组中st下标对应的元素是否为 * ,是执行下列语句
{
printf(" (/*,-) ");//打印注释符号 '/*'
st++;//st自增
int stt = st + 1;//定义变量stt,把st + 1赋给stt
while (1)//循环
{
if (rz[st] == '*' && rz[st + 1] == '/')//判断当前是否为注释结束符,是执行语句
break;//跳出循环
tabuf[n] = rz[st];//将rz数组中st下标对应的元素赋给tabuf
st++;//st自增
n++;//n自增
if (rz[st + 1] == '\0')//判断rz数组中st + 1下标对应的元素是否为'\n',是执行语句
{
printf("(/* error!!\n)");//打印错误
return st + 1;//返回 st + 1
}
}
printf(" \n 注释");//换行打印"注释"
for (int i = 0; i < n; i++)//循环打印注释内容
printf("%c", tabuf[i]);
printf(" (*/,-) ");//打印注释结束符
st = st + 2;//st + 2
}
else if (rz[st] == '=')//否则判断rz数组中st下标对应的元素是否为 = ,是执行下列语句
{
st++;//st自增
printf(" (/*,-) ");//打印注释开始符号
}
else printf(" (/,-) ");//否则为除号并打印
return st;//返回st
}
int other(int st) //函数识别其他特殊字符
{
switch (rz[st])
{
case'=':
st++;
if (rz[st] == '=')
{
st++;
printf(" (rlop,==) ");
}
else
printf(" (rlop,=) ");
break;
case'+':
st++;
if (rz[st] == '=')
{
st++;
printf(" (+=,-) ");
}
else if (rz[st] == '+')
{
st++;
printf(" (++,-) ");
}
else printf(" (+,-) ");
break;
case'-':
st++;
if (rz[st] == '=')
{
st++;
printf(" (-=,-) ");
}
else if (rz[st] == '-')
{
st++;
printf(" (--,-) ");
}
else
printf(" (-,-) ");
break;
case'*':
st++;
if (rz[st] == '=')
{
st++;
printf(" (*=,-) ");
}
else
printf(" (*,-) ");
break;
case'>':
st++;
if (rz[st] == '=')
{
st++;
printf(" (rlop,>=) ");
}
else printf(" (rlop,>) ");
break;
case'<':
st++;
if (rz[st] == '=')
{
st++;
printf(" (rlop,<=) ");
}
else
printf(" (rlop,<) ");
break;
case'%':
st++;
if (rz[st] == '=')
{
st++;
printf(" (\%=,-) ");
}
else
printf(" (\%,-) ");
break;
case'!':
st++;
if (rz[st] == '=')
{
st++;
printf(" (!=,-) ");
}
else
printf(" (!,wrong thing!) ");
break;
case'&':
st++;
if (rz[st] == '&')
{
st++;
printf(" (&&,-) ");
}
else printf(" (&,worng word!) ");
break;
case'|':
st++;
if (rz[st] == '|')
{
st++;
printf(" (||,-) ");
}
else
printf(" ( |,worng word ! ) ");
break;
case'{':
st++;
printf(" ({,-) ");
break;
case'}':
st++;
printf(" (},-) ");
break;
case'(':
st++;
printf(" ((,-) ");
break;
case')':
st++;
printf(" (),-) ");
break;
case'[':
st++;
printf(" ([,-) ");
break;
case']':
st++;
printf(" (],-) ");
break;
case':':
st++;
printf(" (:,-) ");
break;
case'#':st++;
printf(" (#,-) ");
break;
case';':
st++;
printf(" (;,-) ");
break;
case'.':
st++;
printf(" (.,-) ");
break;
case',':
st++;
printf(" (,,-) ");
break;
case' ':
st++;
break;
case ' ':
st++;
break;
case 10:
st++;
printf("\n");
break;
case 34:
st++;
printf(" (\",-) ");
break;
case 39:
st++;
printf(" (',-) ");
break;
default:
printf(" (%c,worngthing) ", rz[st]);
st++;
}
return st;
}
int choice(int st) //根据读入的单词的第一个字符确定调用不同的单词识别函数
{
if (isLetter(rz[st]) == 1)
st = alpha(st);
else if (isDigit(rz[st]) == 1)
st = number(st);
else if (rz[st] == '/')
st = anotation(st);
else
st = other(st);
return st;
}
int main()
{
int i = 0;
FILE* fp;
char name[10];
printf("请输入文件名:\n");
scanf("%s", &name);
if ((fp = fopen(name, "r")) == NULL)
{
printf("Open error!");
exit(0);
}
char ch = fgetc(fp);
int main()
{
int i = 0;
FILE* fp;
char name[10];
printf("请输入文件名:\n");
scanf("%s", &name);
if ((fp = fopen(name, "r")) == NULL)
{
printf("Open error!");
exit(0);
}
char ch = fgetc(fp);
while (ch != EOF)
{
rz[i] = ch;
i++;
ch = fgetc(fp);
}
fclose(fp);
int j = 0;
while (rz[j] != '\0')
j = choice(j);
cout << endl << " 程序中标示符如下 " << endl;
for (i = 0; i < pp; i++)
cout << i << " " << id[i] << endl;
cout << " 程序中数字如下" << endl;
for (j = 0; j < qq; j++)
cout << j << " " << nu[j] << endl;
system("pause");
}
四:运行结果及分析
五.实验心得
在词法分析器实验过程中,不仅仅提高了我的编程技能,而且也加深了我对编译原理的理解,通过这次实验,我更加坚信,只有通过实践才能真正掌握知识,将理论与实践相结合.