编译原理词法分析报告.docx
- 文档编号:8287760
- 上传时间:2023-01-30
- 格式:DOCX
- 页数:35
- 大小:110.23KB
编译原理词法分析报告.docx
《编译原理词法分析报告.docx》由会员分享,可在线阅读,更多相关《编译原理词法分析报告.docx(35页珍藏版)》请在冰豆网上搜索。
编译原理词法分析报告
1、实验目的
1、为初等函数运算语言构造词法分析器。
2、掌握生成词法分析器的方法,加深对词法分析原理的理解。
3、掌握设计、编制并调试词法分析程序的思想和方法
2、实验内容
一、根据下面的要求设计初等函数运算语言的词法模式,并用正则式表达出来
1、初等函数运算语言的常量为实数类型,其定义方式为实数的最一般书写方式,如:
123.321。
具体要求:
不支持整数部分大于。
时首数字为0;不支持小数点后结尾为0;不支持科学记数法;不支持仅为整数时有小数点;支持负数符号,不支持正数符号。
2、初等函数运算语言的变量采用与C语言的标识符定义一样的方式:
首字符为字母或下划线;其他的为字母、数字及下划线的混合串;区分大小写;变量长度不超过32个字符。
3、初等函数运算语言需要处理的函数仅为表一中所列举的内容。
函数的格式及参数内容也如表一所示。
4、初等函数运算语言支持四则运算,其计算的符号与C语言相同,为:
+-*/。
5、初等函数运算语言的合法的分隔符包括:
空格、制表符、、分行符圆括号(左、右)、分号。
其中空格、制表符、分行符可以出现在任何两个不同的单词中间;圆括号(左、右)用于表达式中,用于改变运算的优先级,以及标识函数的参数;分号用于标识一个语句的结束。
6、初等函数运算语言支持的常量还包括:
PI,Eo其中,PI为圆周率,E为自然常数。
二、将正则式转化为最小DFA,给出该DFA的形式化表示和图形表示。
三、根据DFA给出状态转换表。
四、给出初等函数运算语言的记号表,即词法分析中,语言中的记号将分为多少类,每一类型的编码、类型、属性等内容是什么。
五、编写词法分析器,将输入的字符串转化成为记号流,便于后续的语法分析工作。
要求词法分析器中能够识别词法错误。
2.1词法模式设计/正则式
分隔符compart=\t|\n|(|)|;|空格
运算符:
operation=+|-|*|/|=|^
变量:
variable=[a~zA~Z]([a~zA~Z_0~9])*
常量:
constant=(ε|-)((0|(1~9)(0~9)*)(.(0~9)*(1~9)|ε))|PI|E
2.2DFA
注:
id表示字母,num表示数字
2.3状态转换表
id
0
1-9
下划线
减号
小数点
0
1
3
4
1
2
8
1
1
1
1
1
9
8
2
8
3
4
8
8
8
3
8
8
8
8
9
6
4
8
4
4
8
9
6
6
8
6
7
8
8
8
7
8
6
7
8
9
8
8
8
8
8
8
8
8
注:
0是初态,2,6是中间状态,1,3,4,7是终态,其中1表示标示符,3,4,7是实数,8表示不合法的状态,9表示'-'为减号
2.4记号表
符号
Sin
Cos
tg
ctg
log
lg
In
(
)
;
?
+
记号
0
1
2
3
4
5
6
7
8
9
10
11
符号
-
*
/
=
常量
变量
无法识别的标示符
^
{
}
记号
12
13
14
15
16
17
18
19
20
21
22
3、实验程序清单
#include
#include
usingnamespacestd;
#definemax10
charch='';
stringkey[7]={"sin","cos","tg","ctg","log","lg","ln"};//关键字
charcompart[6]={'\t','\n','(',')',';',''};//分隔符
charoperation[5]={'+','-','*','/','='};//运算符
//ints[8]={0,1,2,3,4,6,7,8};//状态集合,0是初态,2,6是中间状态,1,3,4,7是终态,其中1
表示标示符,3,4,7是实数,8表示不合法的状态
inttoken[23]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22};
//0表示sin,1表示cos,2表示tg,3表示ctg,4表示log,5表示lg,6表示ln,7表示(,8表
示),9表示;,10表示?
,11表示+,12表示-,13表示*,14表示/,15表示=,
//16表示常量,17表示变量,18表示不可识别标示符,19表示^,20表示逗号,21表示{,22
表示}
chararr[32];
intstate=0;
ints=0;
booltag=0;//tag=0表示'-'为负数的负号,tag=1表示'-'为减号
FILE*fp;
intIsKey(stringc)
{//判断是否为关键字
for(inti=0;i<7;i++)
{
if(key[i].compare(c)==0)returni;//返回下标,下标和其token记号一致
}
return-1;
}
boolIsLetter(charc)
{//判断是否为字母
if(((c<='z')&&(c>='a'))||((c<='Z')&&(c>='A')))
return1;
else
return0;
}
boolIsNum(charc)
{//判断是否为1-9的数字
if(c>='1'&&c<='9')
return1;
else
return0;
}
boolIsUnderline(charc)
{//判断是否为下划线
if(c=='_')
return1;
else
return0;
}
voidmove(charch,ints)
{//在状态s接收字符ch后,移动的新状态
//arr=arr+ch;
switch(s)
{
case0:
{
if(ch=='_'||IsLetter(ch))
state=1;
else
{
if(ch=='0')
state=3;
else
if(IsNum(ch))
state=4;
else
if(ch=='-')
state=2;
else
state=8;
}
break;
}
case1:
{
if(IsNum(ch)||ch=='_'||IsLetter(ch)||ch=='0')
state=1;
else
if(ch=='-')
state=9;
else
state=8;
break;
}
case2:
{
if(ch=='0')
state=3;
else
if(IsNum(ch))
state=4;
else
state=8;
break;
}
case3:
{
if(ch=='.')
state=6;
else
if(ch=='-')
state=9;
else
state=8;
break;
}
case4:
{
if(IsNum(ch)||ch=='0')
state=4;
else
if(ch=='-')
state=9;
else
if(ch=='.')
state=6;
else
state=8;
break;
}
case6:
{
if(ch=='0')
state=6;
else
if(IsNum(ch))
state=7;
else
state=8;
break;
}
case7:
{
if(ch=='0')
state=6;
else
if(IsNum(ch))
state=7;
else
if(ch=='-')
state=9;
else
state=8;
break;
}
case8:
{
if(ch=='-')
state=9;
else
state=8;
break;
}
}//switch
}
voidjudge(chararr[])
{
if(s==3||s==4||s==7)
cout<<"("< else { if(s==1) { if(! strcmp(arr,"PI")||! strcmp(arr,"E")) cout<<"("< else { if(IsKey(arr)==-1) cout<<"("< else cout<<"("< } } else if(s==9) cout<<"("< if(s==8) cout<<"("< } switch(ch) { case'+': cout<<"("< case'*': cout<<"("< case'=': cout<<"("< case'/': cout<<"("< case'^': cout<<"("< case'(': cout<<"("< case')': cout<<"("< case';': cout<<"("< case',': cout<<"("< case'{': cout<<"("< case'}': cout<<"("< case'? ': cout<<"("< case'': case'/t': case'/n': {} } } voidanalyse(FILE*fp) { inti=0; while(ch! ='EOF') { chararr[32]={'\0'}; while(ch! ='('&&ch! =')'&&ch! =' '&&ch! ='\t'&&ch! ='\n'&&ch! ='{'&&ch! ='}'&&ch! =','&&ch! ='? '&&ch! ='-' &&ch! ='^'&&ch! =';'&&ch! ='+'&&ch! ='*'&&ch! ='/'&&ch! ='='&&ch! ='EOF') { if(i<32) { arr[i]=ch; move(ch,s); s=state; } i++; ch=fgetc(fp); }//while judge(arr); if(ch=='-') { chararr[32]={'\0'}; i=0; while(ch! ='('&&ch! =')'&&ch! =' '&&ch! ='\t'&&ch! ='\n'&&ch! ='{'&&ch! ='}'&&ch! =','&&ch! ='? ' &&ch! ='^'&&ch! =';'&&ch! ='+'&&ch! ='*'&&ch! ='/'&&ch! ='='&&ch! ='EOF') { move(ch,s); s=state; arr[i]=ch; if(state! =9) { i++; ch=fgetc(fp); } else {//s=9为减号时 chararr[32]={'\0'}; break; } }//while judge(arr); s=0; i=0; ch=fgetc(fp); } else { chararr[32]={'\0'}; ch=fgetc(fp); i=0; s=0; } }//while } voidmain() { charin_fn[30]; FILE*fp; cout<<"请输入源文件名(包括路径和后缀名): "; for(;;) { cin>>in_fn; if((fp=fopen(in_fn,"r"))! =NULL)//意思是文件指针fpin在调用fopen打开文件如果失 败,则会成为一个空指针! break;//文件顺利打开后,指向该流的文件指针就会 被返回。 else cout<<"文件路径错误! 请输入源文件名(包括路径和后缀名): "; } cout<<"\n********************分析如下*********************"< ch=fgetc(fp); chararr[32]={'\0'}; arr[0]=ch; //fseek(fp,-1,1); analyse(fp); fclose(fp); cout< inta; cin>>a; } 4、调试过程和运行结果 5、程序的主要部分及其功能说明 由DFN得到的状态转换程序: voidmove(charch,ints) {//在状态s接收字符ch后,移动的新状态 switch(s) { //状态0时,当接收到字符ch为字母或下划线时状态S转移到状态1,ch为0时转 移到状态3,ch为1-9时转移到状态4,ch为‘-’时,转移到状态2,否则转移到 状态8 case0: { if(ch=='_'||IsLetter(ch)) state=1; else { if(ch=='0') state=3; else if(IsNum(ch)) state=4; else if(ch=='-') state=2; else state=8; } break; } case1: { if(IsNum(ch)||ch=='_'||IsLetter(ch)||ch=='0') state=1; else if(ch=='-') state=9; else state=8; break; } case2: { if(ch=='0') state=3; else if(IsNum(ch)) state=4; else state=8; break; } case3: { if(ch=='.') state=6; else if(ch=='-') state=9; else state=8; break; } case4: { if(IsNum(ch)||ch=='0') state=4; else if(ch=='-') state=9; else if(ch=='.') state=6; else state=8; break; } case6: { if(ch=='0') state=6; else if(IsNum(ch)) state=7; else state=8; break; } case7: { if(ch=='0') state=6; else if(IsNum(ch)) state=7; else if(ch=='-') state=9; else state=8; break; } case8: state=8; }//switch } 从文件读字符,并进行词法分析,当读入的字符不为运算符和界符时就往下读, 并将读到的字符存入数组arr,当遇到运算符和界符时调用judge(arr)进行分析,输出 arr所存字符串及其属性,当遇到‘-’时,需要判断它是表示减号还是表示负数的 负号,主要是根据其状态来判断,如果输入‘-’后,若其状态没有调到状态9,则 其为负数的负号,否则为减号。 主要程序如下: voidanalyse(FILE*fp) { inti=0; while(ch! ='EOF') { chararr[32]={'\0'}; while(ch! ='('&&ch! =')'&&ch! =' '&&ch! ='\t'&&ch! ='\n'&&ch! ='{'&&ch! ='}'&&ch! =','&&ch! ='? '&&ch! ='-' &&ch! ='^'&&ch! =';'&&ch! ='+'&&ch! ='*'&&ch! ='/'&&ch! ='='&&ch! ='EOF') { if(i<32) { arr[i]=ch; move(ch,s); s=state; } i++; ch=fgetc(fp); }//while judge(arr); if(ch=='-')//如果遇到‘-’ { chararr[32]={'\0'}; i=0; while(ch! ='('&&ch! =')'&&ch! =' '&&ch! ='\t'&&ch! ='\n'&&ch! ='{'&&ch! ='}'&&ch! =','&&ch! ='? ' &&ch! ='^'&&ch! =';'&&ch! ='+'&&ch! ='*'&&ch! ='/'&&ch! ='='&&ch! ='EOF') { move(ch,s); s=state; arr[i]=ch; if(state! =9) { i++; ch=fgetc(fp); } else {//s=9为减号时 chararr[32]={'\0'}; break; } }//while judge(arr); s=0; i=0; ch=fgetc(fp); } else {//是除‘-’外的运算符和界符时 chararr[32]={'\0'}; ch=fgetc(fp); i=0; s=0; } }//while } 6、实验收获体会 通过实验,我理解了如何通过DFA的状态转换来构造词法分析器,掌握了生成词法分析器的方法,加深了对词法分析原理的理解。 同时在编程的过程中提高了编程能力。 7、改进意见 该词法分析器所能识别的字符串是有限的,不够完全,像main,void,double,int等许多关键字都没有定义到关键字的数组里面去,仅能被识别为一个变量。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 编译 原理 词法 分析 报告