编译原理实验报告词法分析器.docx
《编译原理实验报告词法分析器.docx》由会员分享,可在线阅读,更多相关《编译原理实验报告词法分析器.docx(21页珍藏版)》请在冰豆网上搜索。
![编译原理实验报告词法分析器.docx](https://file1.bdocx.com/fileroot1/2023-1/30/d091a730-e9bf-47b1-894f-44d834b74aaa/d091a730-e9bf-47b1-894f-44d834b74aaa1.gif)
编译原理实验报告词法分析器
编译原理实验—词法分析器
一、实验目的
通过动手实践,使学生对构造编译系统的基本理论、编译程序的基本结构有更为深入的理解和掌握;使学生掌握编译程序设计的基本方法和步骤;能够设计实现编译系统的重要环节。
同时增强编写和调试程序的能力。
二、实验内容及要求
对某特定语言A,构造其词法规则。
该语言的单词符号包括:
保留字(见左下表)、标识符(字母大小写不敏感)、整型常数、界符及运算符(见右下表)。
功能要求如下所示:
·按单词符号出现的顺序,返回二元组序列,并输出。
·出现的标识符存放在标识符表,整型常数存放在常数表,并输出这两个表格。
·如果出现词法错误,报出:
错误类型,位置(行,列)。
·处理段注释(/**/),行注释(//)。
·有段注释时仍可以正确指出词法错误位置(行,列)。
三、实验过程
1、词法形式化描述
使用正则文法进行描述,则可以得到如下的正规式:
其中ID表示标识符,NUM表示整型常量,RES表示保留字,DEL表示界符,OPR表示运算符。
A→(ID|NUM|RES|DEL|OPR)*
ID→letter(letter|didit)*
NUM→digitdigit*
letter→a|…|z|A|…|Z
digit→0|…|9
RES→program|begin|end|var|int|and|or|not|if|then|else|while|do
DEL→(|)|.|;|,
OPR→+|*|:
=|>|<|=|>=|<=|<>
如果关键字、标识符和常数之间没有确定的算符或界符作间隔,则至少用一个空格作间隔。
空格由空白、制表符和换行符组成。
2、单词种别定义;
A语言中的单词符号及其对应的种别编码如下表所示:
单词符号
种别编码
单词符号
种别编码
program
1
+
16
begin
2
*
17
end
3
(
18
var
4
)
19
int
5
20
and
6
.
21
or
7
:
=
22
not
8
;
23
if
9
>
24
then
10
<
25
else
11
=
26
while
12
>=
27
do
13
<=
28
标识符
14
<>
29
整型常量
15
-
30
3、状态转换图;
语言A的词法分析的状态转换图如下所示:
空格符,制表符
或回车符字母或数字
数字
4、运行环境介绍;
本次实验采用MyEclipse进行代码的编写和编译及运行,编写语言为java语言;程序的运行环境为windows7旗舰版
5、关键算法的流程图及文字解释;
程序中用到的函数列表:
A类定义各种类函数以及包含主函数publicstaticvoidmain()
变量ch储存当前最新读进的字符的地址
strToken存放当前字符串
main()//主函数
Analysis()//分析函数,每次读入一行文件,进行识别处理;
charGetChar();//取得当前位置的字符的内容放入ch,并提前指向下一个字符;
charGetNextChar();//取得当前位置的下一位置的字符,
StringConCat();//将ch指向的字符连接到strToken后面
isLetter();//判断ch指向的字符是否字母
isDigit();//判断ch指向的字符是否数字
add(p,str);//向p表中插入当前strToken的字符串
BooleanfindKeyWord(str);//检测当前strToken中的字符串是否保留字,若是,则执行getKeyWordKey(str),返回保留字的id,否则,判别其是否是已存在的标示符,若是,返回标示符的id以及该标示符在表中的位置;
findPunctuation()//判断是否是一个保留的符号;
getindex()//返回已经识别的标示符或者是数字的位置下标;
Booleanexist();//检测当前strToken中的字符串是否在标识符表中已存在,若是,则返回true,否则返回false
voidcallError();//出错处理过程,将错误的位置报告出来
(1)main()函数的流程图如下:
(2)具体分析流程图:
继续判读
IndexoutofBound
6、测试报告(测试用例,测试结果);
首先输入一个不含错误的程序(两种注释)进行检测:
运行后在控制台上得到的结果如下所示:
得到的二元组序列如下:
经检验,输出的是正确的二元组序列。
再输入一个含有错误的程序(含有注释)进行检验:
运行后在控制台上得到的结果如下所示:
经检验,错误的位置是正确的
如果是空文件,编译也会通过;
四、实验总结
通过本次试验,我加深了对编译原理中的词法分析的理解,同时通过动手,更加锻炼了自己。
本次试验由于使用的刚刚学习的java语言,通过这次机会加强了自己对java语言的熟悉的使用。
在这次试验中,感谢老师的认真的讲解与同学的无私的帮助。
总结来说,自己在这次试验中收获很大。
附:
以下为本次实验的源代码:
packageAnalysis;
importjava.io.BufferedReader;
importjava.io.File;
importjava.io.FileReader;
importjava.io.IOException;
importjava.util.ArrayList;
importjava.util.HashMap;
importjava.util.Map;
publicclassA{
privatestaticcharch;
privatestaticStringstrToken;
privatestaticintindex=0;
privatestaticintline=1;
privatestaticbooleannoteTag=false;
privateMapkeywords;
privateHashMappunctuations;
privatestaticArrayListp=newArrayList();
privatestaticArrayListq=newArrayList();
//getandset函数
publicchargetCh(){
returnch;
}
publicvoidsetCh(charch){
A.ch=ch;
}
publicStringgetStrToken(){
returnstrToken;
}
publicvoidsetStrToken(StringstrToken){
A.strToken=strToken;
}
publicvoidsetPunctuations(HashMappunctuations){
this.punctuations=punctuations;
}
publicMapgetPunctuations(){
returnpunctuations;
}
publicvoidsetKeywords(Mapkeywords){
this.keywords=keywords;
}
publicMapgetKeywords(){
returnkeywords;
}
//构造函数
publicA(){
this.keywords=newHashMap();
keywords.put(1,"Program");
keywords.put(2,"begin");
keywords.put(3,"end");
keywords.put(4,"var");
keywords.put(5,"int");
keywords.put(6,"and");
keywords.put(7,"or");
keywords.put(8,"not");
keywords.put(9,"if");
keywords.put(10,"then");
keywords.put(11,"else");
keywords.put(12,"while");
keywords.put(13,"do");
this.punctuations=newHashMap();
punctuations.put("+",16);
punctuations.put("*",17);
punctuations.put("(",18);
punctuations.put(")",19);
punctuations.put(",",20);
punctuations.put(";",21);
punctuations.put(":
=",22);
punctuations.put(">",23);
punctuations.put(">=",24);
punctuations.put("<",25);
punctuations.put("<=",26);
punctuations.put(".",27);
punctuations.put("<>",28);
punctuations.put("=",29);
}
//函数定义(词法分析函数)
publicbooleanAnalyse(char[]strArray){
index=0;//每次分析一行完成后就将index置0
chartemp1;
introwLength=strArray.length;
outer:
while(indexstrToken="";
ch=GetChar(strArray);
if(ch==';'){
System.out.println("(21,;)");
}
elseif(ch==':
')
{
index++;
System.out.println("(22,:
=)");
}
elseif(ch=='.')
{
System.out.println("(27,.)");
}
elseif(ch=='>')
{
if((temp1=this.getNextChar(strArray))=='=')
System.out.println("(24,>=)");
else
{
index--;
System.out.println("(23,>)");
}
}
elseif(ch=='<')
{
if((temp1=this.getNextChar(strArray))=='=')
System.out.println("(26,<=)");
elseif(temp1=='>')
System.out.println("(28,<>)");
else
{
index--;
System.out.println("(25,<)");
}
}
elseif(ch=='*'&¬eTag==false)
{
System.out.println("(17,*)");
}
elseif(java.lang.Character.isLetter(ch)&¬eTag==false){
strToken=contact(strToken,ch);
ch=getNextChar(strArray);
while((java.lang.Character.isLetter(ch))
||(java.lang.Character.isDigit(ch))){
strToken=contact(strToken,ch);
ch=getNextChar(strArray);
}
index--;
//System.err.println(""+strToken);
if(findKeyword(strToken)){
//System.out.println("(15,"+strToken.toString()+")\n");
inti=getKeyWordKey(strToken);
System.out.println("("+i+",--)");
}else
{
if(!
exist(p,strToken))
p.add(strToken);
inti=getindex(p,strToken);
//System.out.println("(14,"+strToken.toString()+")\n");
System.out.println("(14,"+i+")");
}
}elseif(java.lang.Character.isDigit(ch)&¬eTag==false){
strToken=this.contact(strToken,ch);
ch=this.getNextChar(strArray);
while(java.lang.Character.isDigit(ch)){
strToken=this.contact(strToken,ch);
ch=this.getNextChar(strArray);
}
index--;
//System.out.println("(15,"+strToken.toString()+")\n");
if(!
exist(q,strToken))
q.add(strToken);
inti=getindex(q,strToken);
System.out.println("(15,"+i+")");
strToken="";
}elseif(ch=='/'||noteTag==true){
intstartj=index;//注释起始位置标记
intstarti=line;
if(noteTag==false){
//System.out.println("该部分是注释注释,从第"+starti+"行第"+startj+"列开始");
}
chartemp=this.getNextChar(strArray);
if(temp=='*'&¬eTag==false){
temp=this.getNextChar(strArray);
while(indextemp=this.getNextChar(strArray);
if(temp=='*'&&(temp1=this.getNextChar(strArray))=='/')
{
index--;
break;
}
if(index>=rowLength)
{
noteTag=true;
breakouter;
}
}
}
elseif(noteTag==true&&ch!
='*')
{
while(indextemp=this.getNextChar(strArray);
if(temp=='*'&&(temp1=this.getNextChar(strArray))=='/')
{
noteTag=false;
//System.out.println(/*"该部分是注释注释,从第"+starti+"行第"+startj+"列开始*/"到第"+line+"行"+"第"+(index-0)+"列为止");
break;
}
}
}
elseif(temp=='/')
{
while(true)
{
index++;
if(index>=rowLength)
breakouter;
}
}
else
returnfalse;
}else{
Stringkey=String.valueOf(ch);
if(this.findPunctuation(key)){
System.out.println("("+this.getPunctuation(key)+","
+key+")");
}elseif(key.equals("")||key.equals("")){//***********************
break;
}else
returnfalse;
//System.out.println("[未知符号]"+key+"\n");
//strToken="";
}
}
returntrue;
}
publiccharGetChar(char[]array){
try{
while((array[index])==''){
index++;
}
index++;//提前指向下一个字符********************
}catch(ArrayIndexOutOfBoundsExceptione){
return'';
}
returnarray[index-1];
}
publicchargetNextChar(char[]strChar){
index++;
returnstrChar[index-1];
}
publicStringcontact(Stringtoken,charch){
returntoken+String.valueOf(ch);
}
publicbooleanfindKeyword(Stringstr){
for(inti=0;i<13;i++){
if(str.equalsIgnoreCase(this.keywords.get(i)))
returntrue;
}
returnfalse;
}
publicbooleanfindPunctuation(Stringstr){
if(this.punctuations.containsKey(str)){
returntrue;
}else
returnfalse;
}
publicintgetPunctuation(Stringstr){
returnthis.punctuations.get(str);
}
publicbooleanClean(){
returntrue;
}
publicvoidcallError(intline){
System.out.println("出现错误,错误位置在第"+line+"行,第"+index+"列");
}
publicbooleanexist(ArrayListp,StringstrToken)
{
if(p.contains(getStrToken()))
returntrue;
else
returnfalse;
}
publicintgetKeyWordKey(Stringstr)
{
for(inti=1;i<=13;i++)
{
if(str.equalsIgnoreCase(this.keywords.get(i)))
returni;
}
return10000;
}
publicintgetindex(ArrayListp,StringStr)
{
returnp.lastIndexOf(Str)+1;
/*intj=0;
for(inti=0;i
{
if(p.get(i).equals(Str))
j++;
}
returnj;*/
}
publicstaticvoidmain(Stringargs[]){
Filefile=newFile("F:
\\sample.txt");
Aa=newA();
char[]strChar=newchar[100];//限制每行代码字符数不超过100
BufferedReaderreader=nu