词法分析程序的设计与实现

一、实验目的
加深对词法分析器的过程的理解;加强对词法分析方法的掌握;能够采用一种编程语言实现简单的词法分析程序;能够使用自己编写的分析程序对简单的程序段进行词法分析。
二、实验内容
自定义一种程序设计语言,或选择已有的一种高级语言(C语言),编制它的词法分析程序。
三、实验要求
1.对单词的构成规则有明确的定义
2.编写的程序能够正确识别源程序中的单词符号
3.识别出的单词以<种别码,值>的形式保存在符号表中
4.词法分析中源程序和分析后的符号表均保存在.txt文件中
5.有一定的检查错误的能力。遇到错误时可显示“Error”,然后跳过错误部分继续显示。
6. 实验报告包括以下内容
(1)编程思路、流程图、源代码
(2)上机调试时发现的问题,以及解决的过程
(3)所使用的测试数据及结果
(4)心得体会
四、实验步骤
1.给出目标语言的所有单词符号及种别编码、单词符号的状态转换图。
2.依次读入源程序,对源程序进行单词切分和识别,直到源程序结束。
3.对正确的单词,按照它的种别以<种别码,值>的形式保存在符号表中。
4.对不正确的单词,做出错误处理。
五、实验条件:
VC++,visio
六、实验内容:
1.编程思路、流程图、源代码;
编程思路:
词法分析是编译的第一个阶段,主要任务是从左至右逐个字符地对源程序进行扫描,产生一个个单词序列,这些单词符号分为五类,分别是标识符、保留字、常数、运算符、界符,用于语法分析。词法分析程序在识别出下一个单词同时验证其正确性之后,词法分析程序将其以二元组的形式输出(种别码,单词符号),对于不正确的单词,给出错误提示(ERROR),然后跳过并继续识别下一个单词。
流程图:
词法分析程序的设计与实现
源代码:
#include<stdio.h>
#include<conio.h>
#include<math.h>
#include<string.h>
#include<stdlib.h>
#define MAXSIZE 50
int i, row = 0, line = 0;
char a[1000]; //程序
int number[1000][100]; //常数表
char mark[100][5]; //标识符表
char file,file1;
FILE fp,fwp;
//词法分析
int wordanalysis()
{
if ((a[i] >= ‘A’&&a[i] <= ‘Z’)||(a[i]>=‘a’&&a[i]<=‘z’)) //分析标识符和保留字
{
char word[10];
char pro[100][100] = {“char”,“int”,“if”,“else”,“return”,“break”,“do”,“while”,“for”,“double”,“float”,“short”};
int n = 0;
word[n++] = a[i++];
//若字符为AZ或09,则继续读取
while ((a[i] >= ‘A’&&a[i] <= ‘Z’) || (a[i] >= ‘0’ && a[i] <= ‘9’)||(a[i]>=‘a’&&a[i]<=‘z’))
{
word[n++] = a[i++];
}
word[n] =’\0’;//字符串结束符
i–;
//判断该标识符是否为保留字
for (n = 0; n < 100; n++)
{
if (strcmp(word, pro[n]) == 0)
{
printf("( %d,%s) 关键字\n", n + 1,pro[n]);
fprintf(fwp,"( %d,%s) 关键字\n", n + 1,pro[n]);
return 3;
}
}
//判断标识符长度是否超出规定
if (strlen(word)>10)
{
printf("%s\tERROR\n",word);
fprintf(fwp,"%s\tERROR\n",word );
return 3;
}
//判断该标识符是否存在标识符表中
int m = 0;
if (line != 0)
{
int q = 0;
while (q<line)
{
if (strcmp(word, mark[q++]) == 0)
{
printf("( %d,%s) 标识符\n", q,word);
fprintf(fwp,"( %d,%s) 标识符\n", q,word);
return 3;
}
}
}
//将该标识符保存到标识符表中
strcpy(mark[line], word);
printf("( %d,%s ) 标识符\n", line + 1,word);
fprintf(fwp,"( %d,%s ) 标识符\n", line + 1,word);
line++;
return 3;
}
//判断该标识符是否存在标识符表中
else if (a[i] >= ‘0’ && a[i] <= ‘9’) //分析常数
{
char x[100];
int n = 0, sum;
x[n++] = a[i++];
//判断字符是否是0~9
while (a[i] >= ‘0’ && a[i] <= ‘9’)
{
x[n++] = a[i++];
}
x[n] = ‘\0’;
i–;
int num = atoi(x); //将字符串转换成int型
//判断该常数是否存在于常数表中
if (row != 0)
{
int y;
for (y = 0; y < 1000; y++)
{
int w = number[y][0];
sum = 0;
int d;
for (d = 1; d <= number[y][0]; d++)
{
w = w - 1;
sum = sum + number[y][d] * pow(2, w);
}
if (num == sum)
{
printf("( %d,%d ) 数字\n", y + 1,num);
fprintf(fwp,"( %d,%d ) 数字\n", y + 1,num);
return 3;
}
}
}
int z = num, c = num;
int m = 0;
do //计算是几位二进制数
{
z = z / 2;
m++;
} while (z != 0);
for (n = m; n > 0; n–) //将二进制保存于常数表中
{
number[row][n] = c % 2;
c = c / 2;
}
number[row][0] = m;
int line = row;
printf("( %d,%d ) 数字\n", line + 1,num);
fprintf(fwp,"( %d,%d ) 数字\n", line + 1,num);
row++;
return 3;
}
else //分析符号
switch (a[i])
{
case ’ ':
case ‘\n’:return -1;
case ‘#’: return 0;
case ‘=’:printf("( 14,= ) 运算符\n"); fprintf(fwp,"( 14,= ) 运算符\n");return 3;
case ‘<’:
i++;
if (a[i] == ‘=’)
{
printf("( 16,<= ) 运算符\n"); fprintf(fwp,"( 16,<= ) 运算符\n");return 3;
}
else if (a[i] == ‘>’)
{
printf("( 19,<> ) 界符\n"); fprintf(fwp,"( 19,<> ) 界符\n");return 3;
}
else
{
i–;
printf("( 15,< ) 运算符\n"); fprintf(fwp,"( 15,< ) 运算符\n"); return 3;
}
case ‘>’:
i++;
if (a[i] == ‘=’)
{
printf("( 18,>= ) 运算符\n"); fprintf(fwp,"( 18,>= ) 运算符\n"); return 3;
}
else
{
i–;
printf("( 17,> ) 运算符\n"); fprintf(fwp,"( 17,> ) 运算符\n"); return 3;
}
case ‘+’: printf("( 20,+ ) 运算符\n"); fprintf(fwp,"( 20,+ ) 运算符\n"); return 3;
case ‘-’: printf("( 21,- ) 运算符\n");fprintf(fwp,"( 21,- ) 运算符\n"); return 3;
case '
’: printf("( 22,
) 运算符\n"); fprintf(fwp,"( 21,
) 运算符\n"); return 3;
case ‘/’:
i++;
if(a[i]!=’/’){
i–;
printf("( 23,/ ) 运算符\n");fprintf(fwp,"( 23,/ ) 运算符\n"); return 3;
}
else{
while(1){
if(a[i++]==’\n’)
return -1;
}
printf("( 35,// ) 界符\n");fprintf(fwp,"( 35,// ) 界符\n");return 3;
}
case ‘:’: printf("( 24,: ) 界符\n");fprintf(fwp,"( 24,: ) 界符\n"); return 3;
case ‘;’: printf("( 25,; ) 界符\n");fprintf(fwp,"( 25,; ) 界符\n"); return 3;
case ‘(’: printf("( 26,( ) 界符\n");fprintf(fwp,"( 26,( ) 界符\n"); return 3;
case ‘)’: printf("( 27,) ) 界符\n");fprintf(fwp,"( 27,) ) 界符\n"); return 3;
case ‘{’: printf("( 28,{ ) 界符\n");fprintf(fwp,"( 28,{ ) 界符\n"); return 3;
case ‘}’: printf("( 29,} ) 界符\n");fprintf(fwp,"( 29,} ) 界符\n"); return 3;
case ‘[’: printf("( 30,[ ) 界符\n");fprintf(fwp,"( 30,[ ) 界符\n"); return 3;
case ‘]’: printf("( 31,] ) 界符\n");fprintf(fwp,"( 31,] ) 界符\n"); return 3;
case ‘|’: printf("( 32,| ) 运算符\n");fprintf(fwp,"( 32,| ) 运算符\n"); return 3;
case ‘!’: printf("( 33,! ) 界符\n");fprintf(fwp,"( 33,! ) 界符\n"); return 3;
case ‘,’: printf("( 34, ) 界符\n");fprintf(fwp,"( 34, ) 界符\n"); return 3;
case ‘~’: printf("( 35,~ ) 运算符\n");fprintf(fwp,"( 35,~ ) 运算符\n"); return 3;
case ‘&’:
i++;
if(a[i]!=’&’){
i–;
printf("( 37,& ) 运算符\n");fprintf(fwp,"( 37,& ) 运算符\n"); return 3;
}
else{
printf("( 38,&& ) 运算符\n");fprintf(fwp,"( 38,&& ) 运算符\n"); return 3;
}
case ‘\’: printf("( 39,\ ) 界符\n");fprintf(fwp,"( 39,\ ) 界符\n"); return 3;
}
fclose(fwp);
}
int main()
{
int l = 0;
int m;
i = 0;
file=(char
)malloc(sizeof(char)MAXSIZE);
file1=(char
)malloc(sizeof(char)MAXSIZE);
printf(" 词法分析器
*\n");
printf(“请输入要进行词法分析的文件名(含路径):”);
gets(file);
if(!(fp=fopen(file,“r”)))
{
puts(“打开文件失败!\n”);
printf(“请重新输入要进行词法分析的文件名(含路径):”);
gets(file);
}
else
{
printf(“成功打开文件%s!\n”,file);
}
printf(“请输入词法分析结果要存放的文件名(含路径):”);
gets(file1);
if(!(fwp=fopen(file1,“w”)))
{
printf(“该文件不存在!\n”);
}
else {
fwp = fopen(file1,“w”);//打开文档,写入
while (!feof(fp))//检测流上的文件结束符,文件结束,返回非0值,否则返回0
{
a[l++] = fgetc(fp);
}
a[l] = ‘#’;
do
{
m = wordanalysis();
switch (m)
{
case -1:i++; break;
case 0: i++; break;
case 3: i++; break;
}
} while (m != 0);
}
return 0;
}
运行结果:词法分析程序的设计与实现
词法分析程序的设计与实现