文档库 最新最全的文档下载
当前位置:文档库 › 编译原理词法分析器实验报告最终版

编译原理词法分析器实验报告最终版

编译原理词法分析器实验报告最终版
编译原理词法分析器实验报告最终版

学院(系)名称:计算机工程系

姓名学号专业班级实验项目实验一:词法分析

课程名称编译原理课程代码 0310243

2013年 4月28 日第 1、2 节实验时间实验地点第一教学楼1508 2013年5月 7 日第1 、2 节

批改意见成绩

教师签字: 实验内容:

实现标准C语言词法分析器

实验目的:

1(掌握程序设计语言词法分析的设计方法;

2(掌握DFA的设计与使用方法;

3(掌握正规式到有限自动机的构造方法;

实验要求:

1(单词种别编码要求

基本字、运算符、界符:一符一种;

标识符:统一为一种;

常量:按类型编码;

2(词法分析工作过程中建立符号表、常量表,并以文本文件形式输出;

3(词法分析的最后结果以文本文件形式输出;

4(完成对所设计词法分析器的功能测试,并给出测试数据和实验结果;

5(为增加程序可读性,请在程序中进行适当注释说明;

6(整理上机步骤,总结经验和体会;

7(认真完成并按时提交实验报告。

实验步骤:

1.基本思想:从源程序中依次读入字符并解析,与关键字、运算符、结束符进行

比较,得出其中的关键字,并将它存入到数组中去。

2.程序源代码:

#include

#include

#include

#define MaxSize1 17//关键字的个数

#define MaxSize2 20//运算符的个数

#define MaxSize3 4//结束符的个数

//数据结构

struct TNode

{

char value[20]; //存放标识符的值

int number; //存放标识符的种别码

char description[20];//描述

}KeyWords[MaxSize1],Operation[MaxSize2],EndOperation[MaxSize3];

//存放关键字的数组

char

*WordsBuff[MaxSize1]={"const","long","float","double","void","main", "if","else","then",

"break","int","char","include","for","while","printf","scanf"};

//存放运算符的数组

char

*OperationBuff[MaxSize2]={"+","-","*","/","+=","-=","*=","++","--","<","<=",">",">=","

<>","=","(",")","#","{","}"}; char EndOperationBuff[MaxSize3]={' ',';','\n','\t'};

//存放词法分析程序输出的结果

TNode Table1[500];

TNode Variable[100];//标识符表

TNode Const[100];

//关键字数组初始化

void inputKeyWords(char * buff[],int size) {

//关键字编码从1-size

for(int i=0;i

{

strcpy(KeyWords[i].value,buff[i]);

KeyWords[i].number=i+1;

strcpy(KeyWords[i].description,"关键字");

}

}

//运算符数组初始化

void inputOperation(char * buff[],int size)

{

//运算符编码从50-(50+size)

for(int i=0;i

{

strcpy(Operation[i].value,buff[i]);

Operation[i].number=i+50;

strcpy(Operation[i].description,"运算符");

}

}

//结束符数组初始化

void inputEndOperation(char buff[],int size) {

//结束符编码从100-(100+size);

for(int i=0;i

{

EndOperation[i].value[0]=buff[i]; EndOperation[i].value[1]='\0';

EndOperation[i].number=i+100;

strcpy(EndOperation[i].description,"结束符"); }

}

//输出数据结构数组中的信息

void outputInfo(TNode a[],int size)

{

for(int i=0;i

{

printf("(%d",a[i].number);

printf("\t");

printf("%s)",a[i].value);

printf("\t");

printf(a[i].description);

printf("\n");

}

}

void outInfoToFile(TNode a[],int size,FILE *out) {

//将词法分析程序的结果输出到文件中去

for(int i=0;i

{

fprintf(out,"(%d",a[i].number);

fprintf(out,"\t");

fprintf(out,"%s)",a[i].value);

fprintf(out,"\t");

fprintf(out,a[i].description);

fprintf(out,"\n");

}

}

//从文件中读取一个字符

//返回文件中读取的字符

char getChar(FILE *fp)

{

char ch=fgetc(fp);

return ch;

}

//判读是否是运算符

int isOperation(char a[]) {

//返回i表示是运算符在运算符数组中的位置//返回-1表示不是运算符

int result;

for(int i=0;i

{

result=strcmp(a,Operation[i].value); 第4页共12页

if(result==0)

{

return i;

break;

}

}

return -1;

}

//判读是否是关键字

int isKeyWords(char a[])

{

//返回i表示在关键字表中的位置

//返回-1表示不是关键字

int result;

for(int i=0;i

{

result=strcmp(a,KeyWords[i].value); if(result==0)

{

return i;

break;

}

}

return -1;

}

//判读是否是结束符

int isEndOperation(char a)

{

//返回i表示是结束符在结束符表中的位置//返回-1表示不是结束符

for(int i=0;i

{

if(a==EndOperation[i].value[0])

{

return i;

break;

}

}

return -1;

}

//判读是否是字符

int isChar(char a) { //返回1表示是字符

//返回0表示不是字符

第5页共12页

if(a>='a'&&a<='z') return 1;

else if(a>'A'&&a<='Z') return 1;

else

return 0;

}

//判读是否是数字

int isDigit(char a) {

//返回1表示是数字

//返回0表示不是数字

if(a>='0'&&a<='9') return 1;

else

return 0;

}

int count=0;//记录结果表中的关键字及运算符等表项个数,用于返回 int count1=0;//记录标识符的表项个数

int count2=0;//记录常量的表项的个数

//从屏幕上面获得字符并解析,返回在结果表中的表项 int start1(FILE *in) {

char buff[20];//用于保存单词的缓冲区

char nextchar[2];

char temp[20];//用于保存变量或常量的类型数组

int i=0;//缓冲区指针

int a;//比较的结果指针

char op[3];//用于保存第一个运算符

op[2]='\0';

nextchar[0]=fgetc(in);

nextchar[1]='\0';

while(nextchar[0]!=EOF)

{

if(isChar(nextchar[0]))

{

buff[i]=nextchar[0];i++;

nextchar[0]=fgetc(in);

}

else if(isDigit(nextchar[0]))

{

buff[i]=nextchar[0];i++;

nextchar[0]=fgetc(in);

}

else if(nextchar[0]=='\r'||nextchar[0]=='\n')

第6页共12页

{

buff[i]='\0';

a=isKeyWords(buff);

if(a!=-1&&i>0)

{

strcpy(Table1[count].value,KeyWords[a].value);

Table1[count].number=KeyWords[a].number;

strcpy(Table1[count].description,KeyWords[a].description); count++;//计数器加一

i=0;//清空缓冲区

}

else if(i>0)

{

if(isChar(buff[0]))

{

//是标识符

strcpy(Variable[count1].value,buff);

Variable[count1].number=count1;

strcpy(Variable[count1].description,"标识符");

count1++;//计数器加一

i=0;//清空缓冲区

}

else if(isDigit(buff[0]))

{

//是常量

strcpy(Const[count2].value,buff);

Const[count2].number=count2;

strcpy(Const[count2].description,"常量"); count2++;//计数器加一

i=0;//清空缓冲区

}

}

else

{

//缓冲区为空~

}

//处理回车符与换行符

nextchar[0]=fgetc(in);

}

else if(isEndOperation(nextchar[0])!=-1) {

buff[i]='\0';

a=isKeyWords(buff);

if(a!=-1&&i>0)

第7页共12页

{

strcpy(Table1[count].value,KeyWords[a].value);

Table1[count].number=KeyWords[a].number;

strcpy(Table1[count].description,KeyWords[a].description); strcpy(temp,KeyWords[a].value);

count++;//计数器加一

i=0;//清空缓冲区

}

else if(i>0)

{

if(isChar(buff[0]))

{

//是标识符

strcpy(Variable[count1].value,buff);

Variable[count1].number=count1;

strcpy(Variable[count1].description,"标识符");

count1++;//计数器加一

i=0;//清空缓冲区

}

else if(isDigit(buff[0]))

{

//是常量

strcpy(Const[count2].value,buff);

Const[count2].number=count2;

strcpy(Const[count2].description,"常量");

count2++;//计数器加一

i=0;//清空缓冲区

}

}

else

{

//缓冲区为空~

}

nextchar[0]=fgetc(in);

}

else if((a=isOperation(nextchar))!=-1)

{

//首先输出缓冲区中的数据

buff[i]='\0';

a=isKeyWords(buff);

if(a!=-1&&i>0)

{

strcpy(Table1[count].value,KeyWords[a].value);

Table1[count].number=KeyWords[a].number;

strcpy(Table1[count].description,KeyWords[a].description); 第8页共12页

count++;//计数器加一

i=0;//清空缓冲区

}

else if(i>0)

{

if(isChar(buff[0]))

{

//是标识符

strcpy(Variable[count1].value,buff);

Variable[count1].number=count1;

strcpy(Variable[count1].description,"标识符"); count1++;//计数器加一

i=0;//清空缓冲区

}

else if(isDigit(buff[0]))

{

//是常量

strcpy(Const[count2].value,buff);

Const[count2].number=count2;

strcpy(Const[count2].description,"常量"); count2++;//计数器加一

i=0;//清空缓冲区

}

}

else

{

//缓冲区为空~

}

//处理运算符

op[0]=nextchar[0];

nextchar[0]=fgetc(in);

if(nextchar[0]!='@')

{

if(isOperation(nextchar)!=-1)

{

op[1]=nextchar[0];

if((a=isOperation(op))!=-1)

{

//输出双目运算符

strcpy(Table1[count].value,Operation[a].value);

Table1[count].number=Operation[a].number;

strcpy(Table1[count].description,Operation[a].description); count++;//计数器加一

//读取下一个字符

nextchar[0]=fgetc(in);

第9页共12页

}

else

{

//错误的双目运算符

strcpy(Table1[count].value,op);

Table1[count].number=-1;

strcpy(Table1[count].description,"未定义的运算符");

count++;//计数器加一

//读取下一个字符

nextchar[0]=fgetc(in);

}

}

else

{

//输出一元运算符

op[1]='\0';

a=isOperation(op);

strcpy(Table1[count].value,Operation[a].value);

Table1[count].number=Operation[a].number;

strcpy(Table1[count].description,Operation[a].description); count++;//计数器加一

}

}

}

}

return count;

}

void main()

{

inputKeyWords(WordsBuff,MaxSize1); inputOperation(OperationBuff,MaxSize2); inputEndOperation(EndOperationBuff,MaxSize3); FILE *in,*out;

bool Flag=true;

while(Flag)

{

printf("源文件的位置:C:\\input.txt\n");

if((in=fopen("C:\\input.txt","r"))==NULL) {

printf("读取源文件失败~\n");

exit(0);

}

if((out=fopen("C:\\out.txt","w"))==NULL)

{

printf("打开文件失败~\n");

第10页共12页

exit(0);

}

int MaxSize=start1(in);

printf("关键字及运算符\n");

fprintf(out,"关键字及运算符\n"); outputInfo(Table1,MaxSize); outInfoToFile(Table1,MaxSize,out); printf("标识符表:\n");

fprintf(out,"标识符表:\n"); outputInfo(Variable,count1); outInfoToFile(Variable,count1,out); printf("常量表:\n");

fprintf(out,"常量表:\n"); outputInfo(Const,count2); outInfoToFile(Const,count2,out); Flag=false;

fclose(in);

fclose(out);

}

}

3.测试用例:

int a=3;

double b=4;

int c;

if(a>b)

c=a;

else

c=b;

4.测试结果:

第11页共12页

5.心得体会:

通过这次实验,我对编译原理这门专业必修课有了进一步的深层次了解,把

理论知识应用于实验中,实验过程中对于转义字符,结束符、欠缺了考虑,在多次的调试和改进中最终完善了程序,而在调试过程中学习的知识得到了完善和补充,对词法分析器的理解更进一步。也让我重新熟悉了 C++语言的相关内容,加深了对 C++ 语言知识的深化和用途的理解。

第12页共12页

相关文档