西南交大编译原理课程设计词法分析器和语法分析器.docx
《西南交大编译原理课程设计词法分析器和语法分析器.docx》由会员分享,可在线阅读,更多相关《西南交大编译原理课程设计词法分析器和语法分析器.docx(22页珍藏版)》请在冰豆网上搜索。
西南交大编译原理课程设计词法分析器和语法分析器
编译原理
课程设计报告
院系
专业
年级
学号
姓名
课程设计一:
手工设计C语言的词法分析器
一、设计内容
手工设计c语言的词法分析器,结合状态转换图的原理完成对c语言源程序的基本单词的分析及提取,并设计相应的数据结构保存提取出来的单词。
以及对c语言中的保留字的处理策略,实现一个完整的C语言的词法分析器的编写。
二、设计目的
通过本实验的设计更具体的理解词法分析器的工作机制。
同时更理解C语言的结构体系。
从而更深刻的透析编译原理过程。
三、设计平台
1、硬件环境
(1)Intel(R)Core(TM)i3-2310MCPU@2.10GHz2.10GHz
(2)内存4G
2、软件环境
(1)Window8Professor
(2)VisualC++6.0开发软件
3、开发语言:
C语言。
四、需求分析:
词法分析程序又称词法分析器或词法扫描器。
可以单独为一个程序;也可以作为整个编译程序的一个子程序,当需要一个单词时,就调用此法分析子程序返回一个单词,这里,作为子程序
词法分析器的结构:
状态转换图的程序实现
为便于程序实现,假设每个单词间都有界符或运算符或空格隔开,并引入下面的全局变量及子程序:
1)ch存放最新读进的源程序字符
2)strToken存放构成单词符号的字符串
3)Buffer字符缓冲区
4)structkeyType存放保留字的符号和种别
五、概要设计
保留字表的设计结构:
基本功能状态转换:
六、详细设计
1.GETCHAR读一个字符到ch中
2.GETBC读一个非空白字符到ch中
3.CONCAT把CHAR中字符连接到strToken之后
4.LETTER判断CHAR中字符是否为字母
5.DIGIT判断ch中字符是否为数字
6.RESERVE用strToken中的字符串查找保留字表,并返回保留字种别码,若返回零,则非保留字
7.RETRACT把CHAR中字符回送到缓冲区
源程序:
#include"stdio.h"
#include"stdlib.h"
#include"conio.h"
#include"string.h"
#defineN47//保留字个数
charch='\0';//存放最新读进的源程序字符
charstrToken[20]="\0";//存放构成单词符号的字符串
charbuffer[257]="\0";//字符缓冲区
/*------------保留字结构-------------*/
structkeyType{
charkeyname[256];
intvalue;
}Key[N]={{"$ID",0},{"$INT",1},{"auto",2},{"break",3},{"case",4},
{"char",5},{"const",6},{"continue",7},{"default",8},{"do",9},
{"double",10},{"else",11},{"enum",12},{"extern",13},{"float",14},
{"for",15},{"goto",16},{"if",17},{"int",18},{"long",19},{"register",20},
{"return",21},{"short",22},{"signed",23},{"sizeof",24},{"static",25},
{"struct",26},{"switch",27},{"typedef",28},{"union",29},{"unsigned",30},
{"void",31},{"volatile",32},{"while",33},{"=",34},{"+",35},{"-",36},{"*",37},
{"/",38},{"%",39},{",",40},{";",41},{"(",42},{")",43},{"?
",44},{"clear",45},{"#",46}};
/*-------------子过程-------------*/
voidGetChar()//读一个字符到ch中
{inti;
if(strlen(buffer)>0){
ch=buffer[0];
for(i=0;i<256;i++)
buffer[i]=buffer[i+1];
}
else
ch='\0';
}
voidGetBC()//读一个非空白字符到ch中
{inti;
while(strlen(buffer)){
i=0;
ch=buffer[i];
for(;i<256;i++)buffer[i]=buffer[i+1];
if(ch!
=''&&ch!
='\n'&&ch!
='\0')break;
}
}
voidConCat()//把ch连接到strToken之后
{chartemp[2];
temp[0]=ch;
temp[1]='\0';
strcat(strToken,temp);
}
boolLetter()//判断ch是否为字母
{if(ch>='A'&&ch<='Z'||ch>='a'&&ch<='z')
returntrue;
else
returnfalse;
}
boolDigit()//判断ch是否为数字
{if(ch>='0'&&ch<='9')
returntrue;
else
returnfalse;
}
intReserve()//用strToken中的字符查找保留字表,并返回保留字种别码,若返回0,则非保留字
{inti;
for(i=0;iif(strcmp(strToken,Key[i].keyname)==0)
returnKey[i].value;
return0;
}
voidRetract()//把ch中的字符回送到缓冲区
{inti;
if(ch!
='\0'){
buffer[256]='\0';
for(i=255;i>0;i--)
buffer[i]=buffer[i-1];
buffer[0]=ch;
}
ch='\0';
}
/*----------词法分析器------------*/
keyTypeReturnWord()
{strcpy(strToken,"\0");
intc;
keyTypetempkey;
GetBC();
if(ch>='A'&&ch<='Z'||ch>='a'&&ch<='z'){
ConCat();
GetChar();
while(Letter()||Digit()){
ConCat();
GetChar();
}
Retract();
c=Reserve();
strcpy(tempkey.keyname,strToken);
if(c==0)
tempkey.value=0;
else
tempkey.value=Key[c].value;
}
elseif(ch>='0'&&ch<='9'){
ConCat();
GetChar();
while(Digit()){
ConCat();
GetChar();
}
Retract();
strcpy(tempkey.keyname,strToken);
tempkey.value=1;
}
else{
ConCat();
strcpy(tempkey.keyname,strToken);
tempkey.value=Reserve();
}
returntempkey;
}
/*-------------主函数-------------*/
intmain(){
keyTypetemp;
strcpy(buffer,"if(a>0)a=b+c;");
printf("buffer:
\n%s\n\t\t单词\t种别号\n",buffer);
while(strlen(buffer)){
printf("按任意键提出一个词:
");
getch();
temp=ReturnWord();
printf("%s\t%d\n\n",temp.keyname,temp.value);
}
printf("theend!
\n");
return0;
}
七、测试
当输入字符“if(i>0)a=b+c”,当缓冲区接受这串字符后,通过调用词法分析子程序,可有如下的显示结果:
八、结束语
通过对C语言词法分析器的设计和编写,更加了解了编译程序在编译过程中的效用。
同时,也更加了解了C语言的结构。
对于词法分析器这一章的理论知识也有了较深入的理解。
课程设计二:
手工设计简单的语法分析器
一、设计内容
用算符优先分析方法设计一个分析解释程序,对输入的赋值语句、输出语句、清除语句进行词法分析、语法分析、表达式求值并存储于指定变量中;若存在错误,提示错误相关信息。
二、设计目的
了解掌握算符优先分析的基本方法、内容;
学会科学思考并解决问题,提高程序设计能力。
三、设计平台
1、硬件环境
(1)Intel(R)Core(TM)i3-2310MCPU@2.10GHz2.10GHz
(2)内存4G
2、软件环境
(1)Window8Professor
(2)VisualC++6.0开发软件
3、开发语言:
C语言。
四、需求分析:
语法分析的任务:
把单词符号作为基本单位,分析程序是否为合法的程序.
算符优先分析法是自下而上的语法分析方法,即根据文法,对输入字串进行归约,若能正确地归约为文法的初始符号,则表示输入字串是合法的.
该试验主要研究对输入的赋值语句、输出语句、清除语句进行词法分析、语法分析、表达式求值并存储于指定变量中;若存在错误,提示错误相关信息。
文法表示:
S→v=E|E?
|clear
E→E+T|E-T|T
T→T*F|T/F|F
F→(E)|v|c
五、概要设计
单词种别码设计:
符号
种别码
=
1
?
2
+
3
-
4
*
5
/
6
(
7
)
8
v
9
c
10
clear
11
#
12
N
13
六、详细设计
1.优先关系矩阵:
intpriority[NUM][NUM]
2.单词种别码结构:
structWordType
3.变量表中的元素结构:
structVarWord
4.变量表结构:
structVarTable
5.归约栈:
mainStack
6.单词串:
wordStack
7.输入串转化成单词串:
GetwordStack()
8.从单词串中取单词:
GetWord()
9.清空单词串和归约栈:
ClearwordStack()、ClearmainStack()
10.查看变量在变量表中的位置:
CheckvarTable(chara[])
11.变量表添加变量:
AddvarTable(VarWorda)
12.初始化归约栈:
InitmainStack()
13.归约栈添加:
AddmainStack(WordTypea)
14.归约处理程序:
Handle()
15.归约子程序:
MainHandle()
源程序:
#include"stdio.h"
#include"stdlib.h"
#include"conio.h"
#include"string.h"
#defineNUM14
#defineM256
//优先关系矩阵
intpriority[NUM][NUM]={{0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,1,0},
{0,0,0,1,1,-1,-1,-1,1,-1,0,0,1,0},
{0,0,0,1,1,-1,-1,-1,1,-1,0,0,1,0},
{0,0,0,1,1,1,1,-1,1,-1,0,0,1,0},
{0,0,0,1,1,1,1,-1,1,-1,0,0,1,0},
{0,0,0,-1,-1,-1,-1,-1,2,-1,0,0,0,0},
{0,0,0,1,1,1,1,0,1,0,0,0,1,0},
{0,0,1,1,1,1,1,0,1,0,0,0,1,0},
{0,0,0,0,0,0,0,0,0,0,0,0,1,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,-1,-1,-1,-1,-1,0,0,0,0,3,0},
{0,0,1,0,0,0,0,0,0,0,0,0,1,0}};
/*--------单词,种别码---------*/
structWordType{
charword[M];
intvalue;
}wordType[NUM]={{"error",0},{"=",1},{"?
",2},{"+",3},{"-",4},{"*",5},{"/",6},{"(",7},{")",8},{"$i",9},{"$c",10},{"clear",11},{"#",12},{"$N",13}};
/*---------变量表-------------*/
structVarWord{
charvarname[M];//变量名
charvalue[M];//变量值
boolflag;//变量是否赋值标志
};
structVarTable{
VarWordelem[M];//变量数组
intlen;//变量表的长度
}varTable;
/*----------单词栈-----------*/
structOperateStack{
WordTypeelem[M];//单词元素
intlen;//栈的长度
};
OperateStackmainStack;//归约栈
OperateStackwordStack;//单词串
/*-------------------输入串转化成单词串---------------*/
boolGetwordStack(){
inti;
wordStack.len=0;
keyTypetemp;
while(strlen(buffer)){
temp=ReturnWord();//词法分析器获得一个分析词
if(temp.value==1)//常数("$c",10)
{strcpy(wordStack.elem[wordStack.len].word,temp.keyname);
wordStack.elem[wordStack.len].value=10;
}
elseif(temp.value==0)//变量("$i",9)
{strcpy(wordStack.elem[wordStack.len].word,temp.keyname);
wordStack.elem[wordStack.len].value=9;
}
else{
for(i=0;iif(strcmp(temp.keyname,wordType[i].word)==0)//关键字
{wordStack.elem[wordStack.len]=wordType[i];
break;
}
elseif(i==NUM-1){
printf("输入串中出现未识别单词!
\n");
returnfalse;
}
}
}
wordStack.len++;
}
wordStack.elem[wordStack.len++]=wordType[12];
returntrue;
}
/*---------------------从单词串中取单词---------------*/
WordTypeGetWord(){
WordTypetemp=wordStack.elem[0];
for(inti=0;iwordStack.elem[i]=wordStack.elem[i+1];
wordStack.len--;
returntemp;
}
/*---------------------清空栈-------------------------*/
voidClearwordStack()//清空单词串
{wordStack.len=0;}
voidClearmainStack()//清空归约栈
{mainStack.len=0;}
/*---------------查看变量在变量表中的位置-------------*/
intCheckvarTable(chara[]){
for(inti=0;iif(strcmp(a,varTable.elem[i].varname)==0)
returni;
elseif(i==M-1)
return-1;
}
/*-------------------添加变量-------------------------*/
voidAddvarTable(VarWorda){
varTable.elem[varTable.len]=a;
varTable.len++;
}
/*-------------------初始化归约栈---------------------*/
voidInitmainStack()
{mainStack.elem[0]=wordType[12];
mainStack.len=1;
}
/*-------------------添加归约栈-----------------------*/
voidAddmainStack(WordTypea)
{mainStack.elem[mainStack.len]=a;
mainStack.len++;
}
/*----------------------归约--------------------------*/
boolHandle()
{inti;
//常量归约
if(mainStack.elem[mainStack.len-1].value==10){
mainStack.elem[mainStack.len-1].value=13;
}
//变量归约
elseif(mainStack.elem[mainStack.len-1].value==9){
mainStack.elem[mainStack.len-1].value=13;
i=CheckvarTable(mainStack.elem[mainStack.len-1].word);
if(i<0){
printf("\n变量%s未定义!
",mainStack.elem[mainStack.len-1].word);
returnfalse;
}
else
strcpy(mainStack.elem[mainStack.len-1].word,varTable.elem[i].value);
}
//赋值归约
elseif(mainStack.elem[mainStack.len-2].value==1){
if(mainStack.elem[mainStack.len-3].value==9){
i=CheckvarTable(mainStack.elem[mainStack.len-3].word);
if(i<0){
VarWordtemp;
strcpy(temp.varname,mainStack.elem[mainStack.len-3].word);
strcpy(temp.value,mainStack.elem[mainStack.len-1].word);
temp.flag=true;
AddvarTable(temp);
}
else
strcpy(varTable.elem[i].value,mainStack.elem[mainStack.len-1].word);
strcpy(mainStack.elem[mainStack.len-3].word,mainStack.elem[mainStack.len-1].word);
mainStack.elem[mainStack.len-3].value=13;
}
elseif(mainStack.elem[mainStack.len-3].value==13)
strcpy(mainStack.elem[mainStack.len-3].word,mainStack.elem[mainStack.len-1].word);
mainStack.len=mainStack.len-2;
}
//运算归约
elseif(mainStack.elem[mainStack.len-2].value==3){
inta,b;
a=atoi(mainStack.elem[mainStack.len-1].word);
b=atoi(mainStack.elem[mainStack.len-3].word);
a=a+b;
itoa(a,mainStack.elem[mainStack.len-3].word,10);
mainStack.len=mainStack.len-2;
}
elseif(mainStack.elem[mainStack.len-2].value==5){
inta,b;
a=atoi(mainStack.elem[mainStack.len-1].word);
b=atoi(mainStack.elem[mainStack