编译技术课程设计实验报告Word文件下载.docx
《编译技术课程设计实验报告Word文件下载.docx》由会员分享,可在线阅读,更多相关《编译技术课程设计实验报告Word文件下载.docx(49页珍藏版)》请在冰豆网上搜索。
/
25
(
26
)
27
{
28
}
29
30
;
31
>
32
33
<
34
35
==
36
!
37
(2)语法结构定义
程序>
:
:
=main()<
语句块>
=‘{‘<
语句串>
’}’
=<
语句>
{;
};
赋值语句>
|<
条件语句>
循环语句>
=ID=<
表达式>
=if<
条件>
[else<
]
=do<
while<
关系运算符>
=<
项>
{+<
|-<
因子>
{*<
|/<
=ID|num|(<
num:
=(+|-|ε)数字*(.数字数字*|ε)(e(+|-|ε)数字数字*|ε)
ID:
=字母(字母|d数字)*
字母:
=a|b|c…|z|A|B|C…|Z
数字:
=0|1|2…|9
=|>
|>
=|==|!
实验目的:
1、通过该课程设计,熟练应用编译原理的基本理论和方法
2、学会用C/C++高级程序设计语言设计一个编译器的技术
3、加深对编译原理的分析理论的理解,培养动手实践能力
4、通过设计、编制、调试一个编译器,掌握其设计方法和技术,提高解决实际问题的综合素质
实验要求:
处理用户提交的符合上述文法的源代码序列,生成四元式中间代码或X86平台上的目标代码。
实验步骤:
(1)画出识别上述语言单词的状态转换图
(2)用C/C++语言编写词法分析程序(应考虑能被语法分析程序调用)
(3)预处理,去除注释、多余空格、回车换行符等
(3)设计实现语法分析程序(调用上述词法程序分析单词)
(4)设计构造属性文法及中间代码序列结构
(5)采用语法制导翻译法,完成语义分析程序设计,生成四元式中间代码
(6)或将生成的四元式中间代码转换成X86平台上的目标代码
(7)设计若干用例,上机测试并通过所设计实现的编译器
实验方案设计与实现:
总体设计思想
经过分析,由于存在冲突项目,上述文法的语法分析无法使用LR(0)分析法,但是上述文法却满足LL
(1)文法,故其语法分析可以采用递归下降分析法。
故在实验二语法分析的基础上,每当成功识别一个非终结符,根据属性文法的要求采取相应的语义动作,在此过程中可以生成相应的四元式。
因此本实验的重点在于四元式结构的定义和生成四元式。
详细算法设计
数据结构:
存储已被识别出单词的结构体
四元式定义
四元式链表
辅助功能模块:
分配临时变量
回填
语法分析模块:
识别每一个终结符,并同时根据语义需要生成四元式
流程框图:
识别单词流程图(对应scanner())
拼数流程图(对于manageNumberWithoutSign())
递归下降分析法中识别非终结符的伪码:
Word*element()
如果当前单词是数字或标号
{
生成一个包含上述单词信息的word;
识别下一个单词;
返回上述word的指针;
}
否则如果当前单词是左括号
识别下一个单词;
word=expression();
如果当前单词是右括号
{
识别下一个单词;
返回word;
}
否则报错;
否则报错;
返回空指针;
Word*item()
arg1=element();
while当前单词是乘除
arg2=element();
获得临时变量
生成新四元式并加入四元式链表中;
arg1=临时变量;
returnarg1;
Word*expression()
arg1=item();
while当前单词是加减
voidcondition()
arg1=expression();
如果当前单词是比较运算符
识别下一个单词
arg2=expression();
生成新四元式并加入四元式链表中;
voidassignSentence()
如果当前单词是标号
{
如果当前单词是浮点数
{
生成新四元式并加入四元式链表中;
voidconditionSentence()
如果当前单词是if
condition();
回填true入口;
添加goto判断为假应执行的语句块的四元式;
//:
=A
sentenceBlock();
如果当前单词是else
添加判断为真时避开执行为假时语句块的goto四元式;
//:
=B
回填A;
sentenceBlock();
回填B;
else
回填A;
else
error();
voidloopSentence()
如果当前单词是do
识别下一个单词
记录下一个四元式编号;
如果当前单词是while
识别下一个单词
condition();
生成goto四元式,并把记录的四元式编号填入
voidsentence()
assignSentence();
否则如果当前单词是if
conditionSentence();
否则如果当前单词是do
loopSentence();
voidsentenceSeries()
do
sentence();
如果当前单词是;
}while(当前单词不是‘}’);
voidsentenceBlock()
如果当前单词是{
sentenceSeries();
如果当前单词是}
voidprogram()
如果当前单词是main
如果当前单词是(
如果当前单词是)
{
识别下一个单词;
sentenceBlock();
}
否则报错;
函数相关说明:
intisDigit(charc)判断给定字符是否是数字
intisLetter(charc)判断给定字符是否是字母
intisBlank(charc)判断给定字符是否是空白字符
voidgotoUnblankChar()读到第一个非空字符
voidgetLabelOrKey()读出标识符或者变量名
voidreserve()判断标识符是否是关键字
intisVar()判断当前单词是否是符号数或者标识符
intisRelationOperator()判断当前单词是否关系运算符
voidmanageNumberWithoutSign()拼符号数
voidscanner()识别单词
voidgetProgram()从控制台读入源代码
voidgetProgramFromFile()从文件读入源代码
voidlink(Ptqptq)//向四元式链表尾添加一个四元式
voidprintQuaternion()//打印四元式
Word*getNewTempVariety()//返回一个临时变量
Word*getLabel(inti)//返回一个记录回填位置的单词
voiderror()//错误处理
Word*element();
//识别因子
Word*item();
//识别项
Word*expression();
//识别表达式
voidcondition();
//识别条件
voidassignSentence();
//识别赋值语句
voidconditionSentence();
//识别条件语句
voidloopSentence();
//识别循环语句
voidsentence();
//识别语句
voidsentenceSeries();
//识别语句序列
voidsentenceBlock();
//识别语句块
voidprogram();
//识别程序
输入与输出(包括出错处理)
源程序通过文件输入,控制台上显示
输出:
语法正确与否,如果正确输出四元式,否则输出错误的地方附近的语句和错误的单词;
程序运行结果:
语法正确时
语法错误时
编译器使用说明:
在VisualC++6.0中运行,输入文件在C盘的program.txt文件下,使用前需要新建该文件并在该文件中输入源程序。
实验心得体会:
学了这么长时间的编译原理,总是感觉很多有东西虽然知道是什么原理,却并不清楚具体怎么实现。
这次实验给了一个机会,本想好好做一做实验,做一个实用的编译器。
可惜时间太短了,甚至连目标代码还没有来得及翻译,实验课已经结束。
不过这可以理解,上课和实验的时间比较有限,真正的学习是在课程结束后的实践。
源程序清单:
//编译技术课程设计.cpp:
定义控制台应用程序的入口点。
//作者:
#include"
stdafx.h"
#include<
string.h>
stdlib.h>
//***************************辅助判断小函数**********************
intisDigit(charc)//是否是数字
if(47<
c&
&
c<
58)
return1;
return0;
intisLetter(charc)//是否是字母
if(64<
91||96<
123)
intisBlank(charc)//是否是空白字符
if(c=='
\r'
||c=='
\n'
'
||c=='
\t'
/****************************全局变量和函数*********************///作者:
//一些最大长度限制
#definemaxProgramLength10000//程序最长长度限制
#definemaxWordLength20//单词最长长度限制
#definemaxSignLength3
charprog[maxProgramLength];
//源程序
voidgetProgramFromScreen()//源程序输入
printf("
请输入程序:
\n"
);
intp=0;
charc;
c=getchar();
prog[p++]=c;
}while(c!
='
#'
voidgetProgramFromFile()//源程序输入
FILE*fp;
fp=fopen("
C:
\\program.txt"
"
r"
//C:
\\Users\\x\\Desktop
if(fp!
=NULL)
c=fgetc(fp);
while((c!
='
)&
(c!
=EOF))
prog[p++]=c;
c=fgetc(fp);
prog[p++]='
fclose(fp);
printf("
源码:
\n%s\n"
prog);
文件打开失败\n"
pressanykeytoexit"
getchar();
exit(0);
/****************************词法分析要求
***********************//作者:
main1
int2
float3
double4
char5
if6
else7
do8
while9
l(l|d)*10
(+|-|ε)dd*(.dd*|ε)(e(+|-|ε)dd*|ε)20
=21
+22
-23
*24
/25
(26
)27
{28
}29
30
31
32
=33
34
=35
==36
=37
*****************************************************************/
//******************************词法分析变量*********************
typedefstructWORDCONTENT//存储词的内容
doublei;
//可能的值
charstring[maxWordLength];
//源字符串
}WordContent;
typedefstructWORD//识别的单词的全部信息
inttype;
//单词的类型
WordContentvalue;
//单词的内容
}Word;
//关键字
#definekeysNunber9
char*key[keysNunber]={"
main"
int"
float"
double"
char"
if"
else"
"
do"
"
while"
Wordword;
//读出的单词
charc;
//当前字符
intp;
//源程序中指针指向的位置
intn;
//单词中指针指向的位置
//******************************词法分析辅助函数******************
intisVar()//判断是否是变量
if(word.type==10||word.type==20)
intisRelationOperator()
if(word.type>
31&
word.type<
38)
voidgotoUnblankChar()//读到第一个非空字符
c=prog[p++];
while(isBlank(c))
c=prog[p++];
voidgetLabelOrKey()//读出标识符或者变量名
while(isLetter(c)||isDigit(c))
word.value.string[n++]=c;
p--;
word.value.string[n++]='
\0'
voidreserve()//判断是否是关键字
word.type=10;
for(intk=0;
k<
keysNunber;
k++)
if(strcmp(word.value.string,key[k])==0)
word.type=k+1;
break;
voidmanageNumberWithoutSign()
while(isDigit(c))
c=prog[p];
if(c=='
.'
p++;
if(isDigit(prog[p]))
c=prog[p++];
while(isDigit(c))
word.value.string[n++]=c;
c=prog[p++];
p--;
word.type=-1;
word.value.string[n++]='
return;
if(prog[p]=='
e'
word.value.string[n++]=prog[p];
if(prog[p]=='
+'
||prog[p]=='
-'
word.value.string[n++]=prog[p];
p++;
word.type=20;
word.value.i=atof(word.value.string);
//******************************词法分析**************************
voidscanner()
n=0;
gotoUnblankChar();
if(isDigit(c))
p--;
manageNumberWithoutSign();
elseif(isLetter(c))
getLabelOrKey();
reserve();
switch(c)
case'
if(prog[p++]=='
{
word.type=36;
word.value.string[n++]='
}
else
word.type=21;
p--;
word.value.string[n++]='
break;
if(isDigit(prog[p])&
!
isVar())
manageNumberWithoutSign();
break;
word.type=22;
word.type=23;
*'
word.type=24;
case'
/'
word.type=25;
('
word.type=26;
)'
word.type=27;