编译原理课程设计报告
设计词法分析器
目录
1 前言... 2
2 报告主体... 2
2.1 设计目的:... 2
2.2设计内容及要求:... 2
2.2.1 课程设计内容... 2
2.2.3 测试范例:... 3
2.3 实现原理... 3
2.4 算法实现流程图... 7
2.5 程序源代码... 8
2.6结果输出及分析... 13
2.7 心得体会... 14
2.8、参考资料... 15
1 前言
在网络世界中,我们往往对功能强大的程序叹为观止。而这些强大程序的背后是编译这些程序的编译软件,是这些编译软件承托起了这些功能强大的运行程序。我们有不少的同志致其自身于无尽的运行程序上。而只有很少的人搞编译程序。这就是为什么中国的可运行程序满天飞,而编译程序却很少。本课程设计就是在这方面的探索,为你解读编译程序的奥秘。
课程设计题目选择5个题目中的一个,要求根据自己的兴趣和能力,选择一个对自己意义甚大的题目。课程设计基本原理是在实践上,实现我们在课程上学习到的理论知识。通过理论联系实践,更好的掌握课本上的理论知识。
2 报告主体
2.1 设计目的:
学生在学习《编译原理》课程设计中,结合各章节的构造编译程序的基本理论,总共用一周的时间完成课程设计。要求用C或C++语言描述及上机调试,实现五个题目中任意一个,是学生将理论与实际应用结合其,起来,受到软件设计等开发过程的全面训练,从而提高学生软件开发的能力。
2.2设计内容及要求:
2.2.1 课程设计内容
设计词法分析器
2.2.2设计词法分析器
设计各单词的状态转换图,并为不同的单词设计种别码。将词法分析器设计成供语 法分析器调用的子程序。功能包括:
具备预处理功能。将不翻译的注释等符号先滤掉,只保留要翻译的符号串,即要求设计一个供词法分析调用的预处理子程序;
能够拼出语言中的各个单词;
将拼出的标识符填入符号表;
返回(种别码, 属性值)。
2.2.3 测试范例:
Begin x:=10; if x>0; then x=5/x-2*3;end
Do{ch=getchar<>;prog[p++]=ch;}
2.3 实现原理
2.3.1词法分析器的设计
(一)构造单词的分类表
单词的分类:构造上述语言中的各类单词符号及其分类码表如下:
ID和NUM的正规定义式为:
ID→letter(letter | didit)*
NUM→digit digit*
letter→a | … | z | A | … | Z
digit→ 0 | … | 9
如果关键字、标识符和常数之间没有确定的算符或界符作间隔,则至少用一个空格作间隔。空格由空白、制表符和换行符组成。
(二) 主要实验代码:
(1).全局变量:
char prog[80]={'\0'},//存放程序
char token[8]; //存放构成单词符号的字符串
char ch;//输入字符
int syn,//存放单词字符的种别码
sum, //存放整数型单词
p, //p是缓冲区prog的指针
n=-1;//记录标识符在符号表中的位置
char *keyword[6]={"else","if","int","while","void","return"};
(2).main函数
(2.1)输入源程序:
do
{
ch=getchar();
prog[p++]=ch;
}
while(ch!='#');
(2.2)循环调用子函数:
do{
scaner();
switch(syn){
case 11: printf("(%d,%d)\n",syn,sum);break;
case -1: printf("\n ERROR;\n");break;
default: printf("(%d,%s)\n",syn,token);
}
}
}while(syn!=0);
(3).子函数:
(3.1)数据初始化及定义:
void scaner(){
m=0;
sum=0;
for(n=0;n<8;n++)
token[n]='\0';
ch=prog[p++];
while(ch==' ')
ch=prog[p++];
(3.2)关键字及标识符判断
if(isalpha(ch)) /*ch为字母字符*/{
while(isalpha(ch)||isdigit(ch)) /*ch 为字母字符或者数字字符*/{
token[m++]=ch;
ch=prog[p++];}
token[m++]='\0';
ch=prog[p--];
syn=10;
(3.3)常数判别:
if(isdigit(ch)) /*ch是数字字符*/{
while(isdigit(ch)) /*ch是数字字符*/{
sum=sum*10+ch-'0';
ch=prog[p++];}
ch=prog[p--];
syn=11;}
(3.4)专用符号判断:
(3.4.1)专用符号为两个字符
以”<=”为例:
switch(ch){
case'<':m=0;token[m++]=ch;ch=prog[p++];
if(ch=='>'){
syn=21;
token[m++]=ch;}
else if(ch=='='){
syn=22;
token[m++]=ch;}
else{
syn=20;
ch=prog[p--];}
break;
(3.4.2)专用符号为一个字符:
用case语句实现
例:
case'+':syn=13;token[0]=ch;break;
case'-':syn=14;token[0]=ch;break;
default:syn=-1;
(三)DNF状态转换图
2.4 算法实现流程图
2.5 程序源代码
#include <stdio.h> /*定义I/O库所用的某些宏和变量*/
#include <string.h> /*定义字符串库函数*/
#include <conio.h> /*提供有关屏幕窗口操作函数*/
#include <ctype.h> /*分类函数*/
char prog[80]={'\0'};
char token[8]; /*存放构成单词符号的字符串*/
char ch;
int syn; /*存放单词字符的种别码*/
int n;
int sum; /*存放整数型单词*/
int m,p; /*p是缓冲区prog的指针,m是token的指针*/
char *rwtab[6]={"begin","if","then","while","do","end"};
void scaner(){
m=0;
sum=0;
for(n=0;n<8;n++)
token[n]='\0';
ch=prog[p++];
while(ch==' ')
ch=prog[p++];
if(isalpha(ch)) /*ch为字母字符*/{
while(isalpha(ch)||isdigit(ch)) /*ch 为字母字符或者数字字符*/{
token[m++]=ch;
ch=prog[p++];}
token[m++]='\0';
ch=prog[p--];
syn=10;
for(n=0;n<6;n++)
if(strcmp(token,rwtab[n])==0) /*字符串的比较*/{
syn=n+1;
break;}}
else
if(isdigit(ch)) /*ch是数字字符*/{
while(isdigit(ch)) /*ch是数字字符*/{
sum=sum*10+ch-'0';
ch=prog[p++];}
ch=prog[p--];
syn=11;}
else
switch(ch){
case'<':m=0;token[m++]=ch;ch=prog[p++];
if(ch=='>'){
syn=21;
token[m++]=ch;}
else if(ch=='='){
syn=22;
token[m++]=ch;}
else{
syn=20;
ch=prog[p--];}
break;
case'>':m=0;token[m++]=ch;ch=prog[p++];
if(ch=='='){
syn=24;
token[m++]=ch;}
else{
syn=23;
ch=prog[p--];}
break;
case':':m=0;token[m++]=ch;ch=prog[p++];
if(ch=='='){
syn=18;
token[m++]=ch;}
else{
syn=17;
ch=prog[p--];}
break;
case'+':syn=13;token[0]=ch;break;
case'-':syn=14;token[0]=ch;break;
case'*':syn=15;token[0]=ch;break;
case'/':syn=16;token[0]=ch;break;
case')':syn=19;token[0]=ch;break;
case'=':syn=25;token[0]=ch;break;
case';':syn=26;token[0]=ch;break;
case'(':syn=27;token[0]=ch;break;
case'{':syn=28;token[0]=ch;break;
case'}':syn=29;token[0]=ch;break;
case'[':syn=30;token[0]=ch;break;
case']':syn=31;token[0]=ch;break;
case'#':syn=0;token[0]=ch;break;
default:syn=-1;}}
main()
{
printf("\n\nThe significance of the figures:\n"
"数字1到6代表关键字 \n"
"数字10到11代表其他标识 \n"
"数字3到31代表操作\n");
p=0;
printf("\nplease input string:\n");
do {
ch=getchar();
prog[p++]=ch;
}while(ch!='#');
p=0;
do{
scaner();
switch(syn){
case 11: printf("(%d,%d)\n",syn,sum);break;
case -1: printf("\n ERROR;\n");break;
default: printf("(%d,%s)\n",syn,token);
}
}while(syn!=0);
getch();
}
2.6结果输出及分析
运行结果:
2.7 心得体会
通过这次实验,我对编译原理这门专业必修课有了进一步的深层次了解,把理论知识应用于实验中,也让我重新熟悉了C语言的相关内容,加深了对C语言知识的深化和用途的理解。
这次试验,激发了我对编程的兴趣,也让我认识到自身能力的不足,还有很多知识点没有掌握好,通过对同学的提问,对书籍的翻阅,把一个个问题解决了!很感谢同组同学不厌其烦的解答,让我认识到团队合作的重要性!
相信通过这次课程设计,我会在以后的工作学习上更加具有专业性!
2.8、参考资料
《编译原理》,吕映芝、张素琴、蒋维杜编著,清华大学出版社
《编译原理》,Alfred V.Aho等,李建中译,机械工业出版社