编译原理课程设计词法语法分析器.docx
《编译原理课程设计词法语法分析器.docx》由会员分享,可在线阅读,更多相关《编译原理课程设计词法语法分析器.docx(31页珍藏版)》请在冰豆网上搜索。
编译原理课程设计词法语法分析器
编译原理课程设计
CourseDesignofCompiling
(课程代码3273526)
半期题目:
词法和语法分析器
实验学期:
大三第二学期
学生班级:
2014级软件四班
学生学号:
2014112218
学生姓名:
何华均
任课教师:
丁光耀
信息科学与技术学院
2017.6
课程设计1-C语言词法分析器
1.题目
C语言词法分析
2.内容
选一个能正常运行的c语言程序,以该程序出现的字符作为单词符号集,不用处理c语言的所有单词符号。
将解析到的单词符号对应的二元组输出到文件中保存
可以将扫描缓冲区与输入缓冲区合成一个缓冲区,一次性输入源程序后就可以进行预处理了
3.设计目的
掌握词法分析算法,设计、编制并调试一个词法分析程序,加深对词法分析原理的理解
4.设计环境(电脑语言环境)
语言环境:
C语言
CPU:
i7HQ6700
内存:
8G
5.概要设计(单词符号表,状态转换图)
5.1词法分析器的结构
词法分析程序的功能:
输入:
所给文法的源程序字符串。
输出:
二元组(syn,token或sum)构成的序列。
词法分析程序可以单独为一个程序;也可以作为整个编译程序的一个子程序,当需要一个单词时,就调用此法分析子程序返回一个单词.
为便于程序实现,假设每个单词间都有界符或运算符或空格隔开,并引入下面的全局变量及子程序:
1)ch存放最新读进的源程序字符
2)strToken存放构成单词符号的字符串
3)Buffer字符缓冲区
4)structkeyType存放保留字的符号和种别
5.2待分析的简单词法
(1)保留字
break、case、char、const、int、do、while…
(2)运算符和界符
=、+、-、*、/、%、,、;、(、)、?
、#
5.3各种单词符号对应的种别码
单词符号
种别码
单词符号
种别码
ID
0
sizeof
24
INT
1
static
25
auto
2
struct
26
break
3
switch
27
case
4
typedef
28
char
5
union
29
const
6
unsigned
30
continue
7
void
31
default
8
volatile
32
do
9
while
33
double
10
=
34
else
11
+
35
enum
12
-
36
extern
13
*
37
float
14
/
38
for
15
%
39
goto
16
40
if
17
;
41
int
18
(
42
long
19
)
43
register
20
?
44
return
21
clear
45
short
22
#
46
signed
23
lettet(letter|digit)*
47
dightdight*
48
5.3状态转换图
6.详细设计(数据结构,子程序)
算法思想:
首先设置3个变量:
①strToken用来存放构成单词符号的字符串;②ch用来字符;③structkeyType用来存放单词符号的种别码。
扫描子程序主要部分流程如下图所示。
子程序结构:
子程序名
功能
GETCHAR()
读一个字符到ch中
GETBC()
读一个非空白字符到ch中
CONCAT()
把CHAR中字符连接到strToken之后
LETTER()
判断CHAR中字符是否为字母
DIGIT()
判断ch中字符是否为数字
RESERVE()
用strToken中的字符串查找保留字表,并返回保留字种别码,若返回零,则非保留字
RETRACT()
把CHAR中字符回送到缓冲区
7.程序清单
//ConsoleApplication1.cpp:
定义控制台应用程序的入口点。
//
#include"stdafx.h"
#include"stdio.h"
#include"stdlib.h"
#include"conio.h"
#include"string.h"
#defineN47
charch;
charstrToken[20];//存放构成单词符号的字符串
charbuffer[1024];//字符缓冲区
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(){
//文件操作
FILE*fp;
if((fp=fopen("E:
\\作业\\编译原理\\Ccode.txt","r"))==NULL){
printf("cannot open file/n");exit
(1);
}
while(!
feof(fp)){
if(fgets(buffer,250,fp)!
=NULL)
{
printf("E:
\\作业\\编译原理\\Ccode.txt\n");
}
}
keyTypetemp;
printf("单词\t种别号\n");
while(strlen(buffer)){
temp=ReturnWord();
printf("%s\t%d\n\n",temp.keyname,temp.value);
}
printf("theend!
\n");
getch();
return0;
}
8.运行结果
E:
/作业/编译原理/Code.txt
运行结果
九、实验体会
通过本次次法分析设计实验,我加深了对词法分析过程的理解。
并在实际的设计过程深入的了解了编译原理思想。
对编译原理课程有了更深的理解
课程设计二:
设计简单的语法分析器
一、题目
设计简单的语法分析器
二、设计内容
用算符优先分析方法设计一个分析解释程序,对输入的赋值语句、输出语句、清除语句进行词法分析、语法分析、表达式求值并存储于指定变量中;若存在错误,提示错误相关信息。
三、设计目的
了解掌握算符优先分析的基本方法、内容;
四、设计环境
语言环境:
C语言
CPU:
i7HQ6700
内存:
8G
五、概要设计
5.1设计思路
语法分析的任务:
把单词符号作为基本单位,分析程序是否为合法的程序.
算符优先分析法是自下而上的语法分析方法,即根据文法,对输入字串进行归约,若能正确地归约为文法的初始符号,则表示输入字串是合法的.主要研究对输入的赋值语句、输出语句、清除语句进行词法分析、语法分析、表达式求值并存储于指定变量中;若存在错误,提示错误相关信息。
文法表示:
S→v=E|E?
|clear
E→E+T|E-T|T
T→T*F|T/F|F
F→(E)|v|c
5.2单词种别码设计
符号
种别码
=
1
?
2
+
3
-
4
*
5
/
6
(
7
)
8
v
9
c
10
clear
11
#
12
N
13
六、详细设计
6.1变量及函数说明
变量及函数名
表示内容及操作
intpriority[NUM][NUM]
优先关系矩阵
structWordType
单词种别码结构
structVarWord
变量表中的元素结构
mainStack
归约栈
wordStack
单词串
GetwordStack()
输入串转化成单词串
GetWord()
从单词串中取单词
ClearwordStack()、ClearmainStack()
清空单词串和归约栈
CheckvarTable(chara[])
查看变量在变量表中的位置
AddvarTable(VarWorda)
变量表添加变量
InitmainStack()
初始化归约栈
AddmainStack(WordTypea)
归约栈添加
Handle()
归约处理程序
MainHandle()
归约子程序
七、程序清单
//ConsoleApplication1.cpp:
定义控制台应用程序的入口点。
//
#include"stdafx.h"
#include"stdio.h"
#include"stdlib.h"
#include"conio.h"
#include"string.h"
#defineNUM14
#defineM256
#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}};
//优先关系矩阵
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}};
structVarTable{
VarWordelem[M];
intlen;
}varTable;
structOperateStack{
WordTypeelem[M];//单词元素
intlen;
};
OperateStackmainStack;//归约栈
OperateStackwordStack;
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;
};
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