哈尔滨工程大学编译原理实验词法分析程序Word格式.docx
- 文档编号:21716320
- 上传时间:2023-01-31
- 格式:DOCX
- 页数:17
- 大小:89.60KB
哈尔滨工程大学编译原理实验词法分析程序Word格式.docx
《哈尔滨工程大学编译原理实验词法分析程序Word格式.docx》由会员分享,可在线阅读,更多相关《哈尔滨工程大学编译原理实验词法分析程序Word格式.docx(17页珍藏版)》请在冰豆网上搜索。
E2——>
1|2|3|4|5|6|7
F2——>
GF|ε
D2——>
H2F2
H2——>
G2——>
0|1|2|3|4|5|6|7
对于十六进制:
A3——>
0xB3
B3——>
C3D3
C3——>
E3C3|ε
E3——>
0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f
D3——>
F3C3
F3——>
对于运算符和分隔符:
A4——>
+|-|*|/|>
|<
|=|(|)|;
对于标识符和关键字:
A5——>
B5C5
B5——>
D5E5
D5——>
a|b|……|y|z
E5——>
F5E5|ε
F5——>
a|b|……|y|z|0|1|2|3|4|5|6|7|8|9
C5——>
G5E5
G5——>
综上正规文法为:
S——>
A1|A2|A3|A4|A5
D1B1|ε
C2D2
4、状态图
实验记录
1、程序源代码
#include<
string.h>
stdio.h>
//#include"
stdafx.h"
unionchars{//联合,可存储字符串,整型和浮点型
charpro_char[15];
intpro_number;
floatreal;
};
structdata{//将每个单元用一个结构来存储,其内容包括:
类型,所属的具体类型,以及属性值
charkind[7];
intid;
unioncharspro;
intscan(char*a);
//对每个用空格打断的单元进行进一步的分析,对其进行进一步的分类
voidPrints(chara[15],intid,inta_long);
//将分析后的每个token输出
voidsave(char*a,intid,intx,floaty);
//将分析后的结果保存到一个结构数组中
charnowChar[15];
//临时的存储单元,用来存储被空格打断以后单元
charkinds[11][8]={"
"
"
INT10"
INT8"
INT16"
IDN"
REAL10"
REAL8"
REAL16"
//单词的不同种别
structdatalink[100];
//用来存放词法分析以后的结果的结构数组
intlink_long=0;
//全局变量
intscan(char*a)
{
inta_long=0;
intdoc=0;
while(*a!
=NULL){
nowChar[0]='
\0'
;
a_long=0;
doc=0;
//对数值的判断及处理
if('
0'
<
=*a&
&
*a<
='
9'
){//如果第一个字符为数值
nowChar[a_long]=*a;
*a++;
a_long++;
//对十六进制的判断及处理
if(nowChar[0]=='
(*a=='
x'
||*a=='
X'
)){//如果第一个字符为0且第二个字符为x,则为十六进制数
=NULL&
(('
)||('
a'
f'
A'
F'
)||*a=='
.'
)){
//一直将此十六进制数完全读入,若为浮点型的,则加以标记
if(*a=='
)
doc=1;
}
nowChar[a_long]='
//判断输入的十六进制数是否合法
if(a_long==2){//输入的只有0x,则输入错误
Prints(nowChar,7,a_long);
return0;
if(doc)//输入的十六进制数是浮点型的
Prints(nowChar,10,a_long);
//则将其具体的类型属性定为10
else//输入的十六进制数是整型的
Prints(nowChar,3,a_long);
//则将其具体的类型属性定义为3
continue;
//对八进制的判断及处理
'
7'
){//如果第一个字符为0且第二个字符为0~7,则为八进制数
//一直将此八进制数完全读入,若为浮点型的,则加以标记
if(doc)//输入的八进制数是浮点型的
Prints(nowChar,9,a_long);
//则将其具体的类型属性定为9
Prints(nowChar,2,a_long);
//则将其具体的类型属性定义为2
//对十进制数的判断及处理
else{
//一直将此十进制数完全读入,若为浮点型的,则加以标记
if(doc)//输入的十进制数是浮点型的
Prints(nowChar,8,a_long);
//则将其具体的类型属性定为8
else//输入的十进制数是整型的
Prints(nowChar,1,a_long);
//则将其具体的类型属性定义为1
}//完成了对数值的判断及处理
//对字符的判断及处理
//判断输入的字符是否为运算符或其他的分隔符
switch(nowChar[0])
case'
+'
:
-'
*'
/'
>
('
)'
Prints(nowChar,5,a_long);
//将其具体的类型属性定义为5
default:
break;
//判断输入的第一个字符是否为字母
if(('
=nowChar[0]&
nowChar[0]<
z'
Z'
)||(*a=='
_'
)))
{//一直将此字符串完全读入
//判断输入的字符串是否为特殊的标识符,若是,则将其具体类型值定义为6
//判断输入的字符串是否为特殊的字符串if
if(a_long==2&
strcmp(nowChar,"
if"
)==0){
Prints(nowChar,6,a_long);
//判断输入的字符串是否为特殊的字符串then
if(a_long==4&
then"
//判断输入的字符串是否为特殊的字符串else
else"
//判断输入的字符串是否为特殊的字符串while
if(a_long==5&
while"
//判断输入的字符串是否为特殊的字符串do
do"
)==0)
//若输入的字符串不符合以上几种情况,则输入的为变量
//若输入的字符串为变量,则将其具体属性值定义为4
Prints(nowChar,4,a_long);
//如果输入的既不是数值也不是字符串,则输入错误,将其具体类型之定义为7
else
return1;
main()
printf("
请输入句子:
"
);
charbuf[100];
//用来存储从键盘上输入一串字符
char*tokenPtr;
//用来存储用空格打断后的单元
intid=1;
//用来存储具体的类型号
link_long=0;
while(id){
gets(buf);
//从键盘上输入一串字符
tokenPtr=strtok(buf,"
//用空格将字符串打断
while(id&
*tokenPtr!
=NULL)
{//分割出来的单元不为空
id=scan(tokenPtr);
//将此单元进行继续分析,并返回其具体的类型值
tokenPtr=strtok(NULL,"
//将字符串继续用空格进行分割
printf("
\n\n"
getchar();
//将所分解后的单元存入结构数组中
voidsave(char*a,intid,intx,floaty)
inti;
if(link_long<
100){
link[link_long].id=id;
//将具体的类型值存入
if(id>
=5){
=8){
//id=8,9,10
//若为浮点型的数值,则将浮点型的y值(转换后的)存入其属性当中且存入单词的种别
for(i=0;
i<
9&
kinds[id][i]!
i++)
link[link_long].kind[i]=kinds[id][i];
link[link_long].pro.real=y;
//id=5,6,7
//若为标识符,则将单词种别定为自身,属性值定为空
15&
a[i]!
link[link_long].kind[i]=a[i];
link[link_long].pro.pro_char[0]='
link[link_long].pro.pro_char[1]='
link_long++;
//id=1,2,3,4
8&
//若分解后的token为变量或者整型数值,则将其单词种别直接输出
if(id==4){//若token为变量,则将其属性值设为自身
link[link_long].pro.pro_char[i]=a[i];
link[link_long].pro.pro_char[i]='
else//若token为整型数值,则将其相应的十进制数值赋给其属性值
link[link_long].pro.pro_number=x;
//继续存入下一个token
Full100\n"
//结构数组已经存满
return;
//将词法分析器分解后的结果输出出来
voidPrints(chara[15],intid,inta_long){
intx=0;
floaty=0;
//intfloat1;
//char*c;
if(id==1){//若为十进制整数
for(i=1;
a_long&
x=x*10+(a[i]-48);
INT10\t%s\n"
a);
save(a,id,x,y);
//存入结构数组
if(id==2){//若为八进制整数
x=x*8+(a[i]-48);
//换算为十进制数
INT8\t%d\n"
x);
if(id==3){//若为十六进制整数
for(i=2;
i++){
=a[i]&
a[i]<
x=x*16+(a[i]-48);
x=x*16+(a[i]-87);
x=x*16+(a[i]-55);
INT16\t%d\n"
if(id==4){//若为变量
IDN\t%s\n"
if(id==5||id==6){//若为标识符(+,-,*,/,++以及if,else,while,then,do)
%s\t-\n"
if(id==8){//若为十进制浮点型
for(i=strlen(a)-1;
i>
=0&
i--)
y=(y+(a[i]-48))/10;
y=y+x;
//整数部分与小数部分换算后相加
REAL10\t%f\n"
y);
if(id==9){//若为八进制浮点型
y=(y+(a[i]-48))/8;
REAL8\t%f\n"
if(id==10){//若为十六进制浮点型
i++)//将整数部分与小数部分分割开,并进行相应的换算
y=(y+(a[i]-48))/16;
REAL16\t%f\n"
WrongEnter"
//所得的具体类型值为7,则输入有错误
return;
2、运行截图
输入:
9800–>
tyywhile
实验总结
本次的实验使我对词法分析的过程有了全新的了解,同时也明白了词法分析何时可以采用空格来区分单词,明白了程序设计中影响词法分析的效率的环节。
比如,关键字的识别过程。
因为当词法分析器识别出一个标识符时,就去和保留字表中的关键字进行比较,以确定它是否是关键字。
如果关键字和标识符比较少,标识符在表中采取顺序比较的时间还可以接受,但如果关键字和标识符都比较多,那么查询比较的平均时间就会比较长,就会影响到词法分析的效率。
且每一次比较都是字符串之间的比较,也很耽误时间。
因此,我们讨论出了采取比较好的预选方式,如对标识符先进行筛选,有些不可能是关键字的标识符就可以不再与保留字表中的关键字进行比较了。
如某种语言的关键字最长为8个字符,那么对于长度大过8的标识符被“筛下”了。
当然进行“筛选”,也要付出一定的代价。
对于这次的实验,从中积累了很多的经验,同时也总结了一些编程出现的问题。
1、在调试的过程中添加语句时经常忘记加分号。
2、在编写时对于多层括号的,时常少一边的括号,这个可以采用在编写时直接将完整的括号编写上去,不要只先写一边的括号。
3、经常未经定义便使用该变量。
4、注意前后的函数名的大小写,保持前后一致,避免出现原本前后是同一个函数,但由于字母的大小写,而导致是表示两个不同的函数。
5、要判断好某个函数是否需要返回其函数值。
6、判断好该代码需要在什么环境先实现的,是C还是C++。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 哈尔滨工程 大学 编译 原理 实验 词法 分析 程序