编译原理综训报告词法分析器.docx
《编译原理综训报告词法分析器.docx》由会员分享,可在线阅读,更多相关《编译原理综训报告词法分析器.docx(27页珍藏版)》请在冰豆网上搜索。
![编译原理综训报告词法分析器.docx](https://file1.bdocx.com/fileroot1/2023-5/25/96b1eacc-4914-49ec-a762-9d13078f427c/96b1eacc-4914-49ec-a762-9d13078f427c1.gif)
编译原理综训报告词法分析器
软件学院
综合训练项目报告书
课程名称编译原理
项目名称词法分析器的设计
专业班级
组别
姓名
成员
任课教师郭伟
2015年6月
1设计时间
2015年6月24
2设计任务
编译原理涉及词法分析,语法分析,语义分析及优化设计等各方面。
词法分析阶段是编译过程的第一个阶段,是编译的基础。
这个阶段的任务是从左到右一个字符一个字符地读入源程序,即对构成源程序的字符流进行扫描然后根据构词规则识别单词(也称单词符号或符号)。
词法分析程序实现这个任务。
词法分析程序可以使用Lex等工具自动生成。
从左到右逐个字符对构成源程序的字符串进行扫描,依据词法规则,识别出一个一个的标记(token),把源程序变为等价的标记串序列。
执行词法分析的程序称为词法分析器,也称为扫描器。
词法分析是所有分析优化的基础,涉及的知识较少,如状态转换图等,易于实现。
本次实验使用java代码实现。
3设计内容
3.1设计要求
掌握词法分析设计的基本原理及思想,巩固所学的理论知识,培养综合运用所学知识解决实际问题的能力。
设计要求:
1)用C语言开发一个词法分析程序,词法分析程序可以分析包含以下符号测试代码;
关键字:
if、int、for、while、do、return、break、continue;单词种别码为1。
标识符;单词种别码为2。
常数为无符号整形数;单词种别码为3。
分隔符包括:
、;、{、}、(、);单词种别码为4。
运算符包括:
+、-、*、/、=、、<、=、<=、!
=;单词种别码为5。
2)以<种别码,值>的形式存储符号表;
3)删除注释、空格和无用符号 ,将删除后的程序代码输出在控制台上;
4)发现并定位词法错误,需要输出错误的位置在源程序中的第几行,将错误信息(错误信息为错误种类,错误种类包括未知的标识符、操作符、错误格式)输出到屏幕上;
5)对于普通标识符和常量,分别建立标识符表和常量表(使用线性表存储),在控制台中输出的符号表(来自测试代码中出现的符号)。
其中符号表含有的属性列为:
单词符号和种别码。
3.2问题分析
3.2.1单词的构词规则
对某特定语言A,构造其词法规则。
A的内容如下:
表1构词规则表
该语言的单词符号包括
1、关键字
if
int
for
while
do
return
break
continue
表2关键字表
2、运算符及界符
表3运算符及界符表
3、标识符(字母大小写不敏感),整型常数
3.2.2词汇表
对于后文正则式中可能出现的符号定义如下,以便清晰地描述A语言的正则式
符号
说明
a
字母
b
数字
c
符号(不包括字母和数字)
*
闭包运算符
|
或运算符
.
连接运算符(可省略)
空
#
结束符
表4词汇表
3.2.3单词种别定义
if
1
contine
1
)
4
!
=
5
int
1
标识符
2
+
5
/
5
for
1
常数
3
*
5
;
5
while
1
,
4
-
5
do
1
{
4
=
5
return
1
}
4
<
5
break
1
(
4
<=
5
表5单词种别表
对于标识符或保留字的推导对于常数的推导
对于符号的推导
`
3.3程序设计
3.3.1总体设计
图一、扫描子程序主要部分流程
3.3.2状态转换图
图二读取状态转换
3.4测试与分析
3.4.1测试
我们对程序的测试如下,采用如下用例
用例:
运行结果为:
错误:
常数表:
标志符表:
保留字及符号对应的二元组表:
二元组及错误信息均无误,且注释成功跳过
`
3.5代码
publicclassCompilerextendsJFrameimplementsActionListener{
introw=1;
intline=1;
interr=0;
JMenuBarmb=newJMenuBar();
JMenufileMenu=newJMenu("文件");
JMenuactionMenu=newJMenu("词法分析");
JMenuItemcloseWindow=newJMenuItem("退出");
JMenuItemopenFile=newJMenuItem("打开");
JMenuItemlexical_check=newJMenuItem("开始");
intbegin=0;
intend=0;
TextAreatext=newTextArea();
TextAreaerror_text=newTextArea();
TextAreaend_text=newTextArea();
FileDialogfile_dialog_load=newFileDialog(this,"Openfile...",ileDialog.LOAD);
JPanelpan1=newJPanel();
JPanelpan2=newJPanel();
Compiler(){
this.add(end_text);end_text.setEditable(false);
this.add(text);
this.add(error_text);error_text.setEditable(false);
pan1.setLayout(newGridLayout(1,1));pan1.add(text);
pan2.setLayout(newGridLayout(2,1));
pan2.add(error_text,"North");
pan2.add(end_text,"South");
getContentPane().add(pan1,"West");
getContentPane().add(pan2,"Center");
this.setJMenuBar(mb);
mb.add(fileMenu);
mb.add(actionMenu);
fileMenu.add(openFile);
fileMenu.add(closeWindow);
actionMenu.add(lexical_check);
error_text.setText("----------------词法分析---------------------\n");
end_text.setText("-----------词法分析错误信息--------------\n");
closeWindow.addActionListener(this);
openFile.addActionListener(this);
lexical_check.addActionListener(this);
pack();
this.addWindowListener(newWindowAdapter(){
publicvoidwindowClosing(WindowEvente){
System.exit(0);}
});
this.setVisible(true);}
publicstaticvoidmain(String[]args){
Compilercompiler=newCompiler();}
publicvoidactionPerformed(ActionEvente){
if(e.getSource()==closeWindow){
intflag=JOptionPane.showConfirmDialog(null,"是否退出");
System.out.println("flag="+flag);
if(flag==0){
System.exit(0);
}elseif(flag==1){
}
}elseif(e.getSource()==openFile){
file_dialog_load.setVisible(true);
Filemyfile=newFile(file_dialog_load.getDirectory(),file_dialog_load.getFile());
try{
BufferedReaderbufReader=newBufferedReader(newFileReader(myfile));
newtestxiaochu(myfile);
try{
neweryuandanci(myfile);
}catch(Exceptione1){
//TODOAuto-generatedcatchblock
e1.printStackTrace();}
Stringcontent="";
Stringstr;
while((str=bufReader.readLine())!
=null){
content+=str+"\n";
text.setText(content);
}
}catch(IOExceptionie){
System.out.println("IOexceptionoccurs...");
}
}elseif(e.getSource()==lexical_check){
error_text.setText("");
row=0;
line=1;
checkLexical();
}
}
publicvoidcheckLexical(){
Stringerror_info=error_text.getText();
Stringcontent=text.getText();
if(content.equals("")){
error_info+="文件尚未载入!
\n";
error_text.setText(error_info);
}else{
inti=0;//选择第i个字符进行检测。
intN=content.length();//文件大小
intstate=0;//状态标志
for(i=0;irow++;
charc=content.charAt(i);
switch(state){
case0:
if(c==','||c==''||c=='\t'||c=='{'||c=='}'||c=='('||
c==')'||c==';'||c=='['||c==']'){
if(isDigit(content.charAt(i-1))&&isDigit(content.charAt(begin))){
end=i;
error_text.append("\t数值\t"+"200"+
content.substring(begin,end)+'\n');
}
if(c==',')error_text.append("\t界符\t"+"\t501"+"\t,"+'\n');
if(c==';')error_text.append("\t界符\t"+"\t502"+"\t;"+'\n');
if(c=='{')error_text.append("\t界符\t"+"\t503"+"\t{"+'\n');
if(c=='}')error_text.append("\t界符\t"+"\t504"+"\t}"+'\n');
if(c=='(')error_text.append("\t界符\t"+"\t505"+"\t("+'\n');
if(c==')')error_text.append("\t界符\t"+"\t506"+"\t)"+'\n');
if(c=='[')error_text.append("\t界符\t"+"\t508"+"\t["+'\n');
if(c==']')error_text.append("\t界符\t"+"\t509"+"\t]"+'\n');
state=0;
}elseif(c=='+')state=1;
elseif(c=='-')state=2;
elseif(c=='*')state=3;
elseif(c=='/')state=4;
elseif(c=='!
')state=5;
elseif(c=='>')state=6;
elseif(c=='<')state=7;
elseif(c=='=')state=8;
elseif(c=='.')state=17;
elseif(c=='~')state=18;
elseif(c=='%')state=19;
elseif(c=='^')state=20;
elseif(((int)c)==10){
state=9;//输入为回车
error_text.append("Line"+line+"\n\n");
}elseif(isLetter(c)){
state=10;
begin=i;
}
elseif(isDigit(c)){
begin=i;
state=11;
}elseif(c=='#')state=12;
elseif(c=='&')state=14;
elseif(c=='|')state=15;
elseif(c=='"')state=16;
else{
err++;
Stringa=end_text.getText();
a+="错误:
line:
"+line+"row:
"+row+"error:
'"+c+"'Undefinedcharacter!
\n";
end_text.setText(a);
error_text.append("错误:
line:
"+line+"row:
"+row+"error:
'"+c+"'Undefinedcharacter!
\n");
}
break;
case1:
//标志符是+
if(c=='+'){
state=0;
error_text.append("\t运算符\t\t401"+"\t++"+'\n');
}elseif(c=='='){
state=0;
error_text.append("\t运算符\t\t402"+"\t+="+'\n');
}else{
state=0;
if(isDigit(content.charAt(i-2)))
error_text.append("\t数值\t"+"\t200"+
content.substring(begin,i-1)+'\n');
error_text.append("\t运算符\t\t403"+"\t+"+'\n');
i--;
row--;
}
break;
case2:
//标志符是-
if(c=='-')
error_text.append("\t运算符\t\t404"+"\t--"+'\n');
elseif(c=='=')
error_text.append("\t运算符\t\t405"+"\t-="+'\n');
elseif(c=='>')
error_text.append("\t运算符\t\t423"+"\t->"+'\n');
else{
error_text.append("\t运算符\t\t406"+"\t-"+'\n');
i--;
row--;
}
state=0;
break;
case3:
//标志符是*
if(c=='=')
error_text.append("\t运算符\t\t407"+"\t*="+'\n');
else{
error_text.append("\t运算符\t\t408"+"\t*"+'\n');
i--;
row--;
}
state=0;
break;
case4:
//标志符是/
if(c=='/'){
while((c)!
='\n'){
c=content.charAt(i);
i++;
}
state=0;
error_text.append("\t注释部分\t\t//\n");
}elseif(c=='='){
state=0;
error_text.append("\t运算符\t\t409"+"\t/="+'\n');
}else{
state=0;
error_text.append("\t运算符\t\t410"+"\t/"+'\n');
i--;
row--;
}
//state=0;
break;
case5:
//标志符是!
if(c=='='){
error_text.append("\t运算符\t\t411"+"\t!
="+'\n');
state=0;
}else{
state=0;
i--;
row--;
error_text.append("\t运算符\t\t412"+"\t!
"+'\n');
}
break;
case6:
//标志符是>
if(c=='='){
error_text.append("\t运算符\t\t413"+"\t>="+'\n');
state=0;
}
if(c=='>'){
error_text.append("\t运算符\t\t426"+"\t>>"+'\n');
state=0;
}else{
state=0;
i--;
row--;
error_text.append("\t运算符\t\t414"+"\t>"+'\n');
}
//state=0;
break;
case7:
//标志符是<
if(c=='='){
error_text.append("\t运算符\t\t415"+"\t<="+'\n');
state=0;
}
if(c=='<'){
error_text.append("\t运算符\t\t427"+"\t<<"+'\n');
state=0;
}else{
state=0;
i--;
row--;
error_text.append("\t运算符\t\t416"+"\t<"+'\n');
}
break;
case8:
//标志符是=
if(c=='='){
error_text.append("\t运算符\t\t417"+"\t=="+'\n');
state=0;
}else{
state=0;
i--;
row--;
error_text.append("\t运算符\t\t418"+"\t="+'\n');
}
break;
case9:
//标志符是回车
state=0;
i--;
row=1;
line++;
break;
case10:
//标志符是字母
if(isLetter(c)||isDigit(c)){
state=10;
}else{
end=i;
Stringid=content.substring(begin,end);
if(isKey(id)!
=0){
intt=isKey(id);
error_text.append("\t关键字\t\t"+t+id+'\n');
}else
error_text.append("\t标志符\t"+"\t100"+id+'\n');
i--;
row--;
state=0;
}
//state=0;
break;
case11:
//标志符是数字
if(c=='e'||c=='E')
state=13;
elseif(isDigit(c)||c=='.'){
//省略跳过,i加一操作
}else{
if(isLetter(c)){
err++;
Stringb=end_text.getText();
b+="错误:
line"+line+"row"+row+"数字格式错误或者标志符错误\n";
end_text.setText(b);
error_text.append("错误:
line"+line+"row"+row+"数字格式错误或者标志符错误\n");
}
inttemp=i;
i=find(i,content);
row+=(i-temp);
state=0;
}
break;
case12:
//标志符是#
Stringid="";
while(c!
='<'){
id+=c;
i++;
c=content.charAt(i);
}
if(id.trim().equals("include")){
while(c!
='>'&&(c!
='\n')){
i++;
c=content.charAt(i);
}
if(c=='>')
error_text.append("\t头文件引入\n");
}else{
err++;
Stringd=end_text.getText();
d+="错误:
"+"line