中南大学编译原理实验报告.docx
《中南大学编译原理实验报告.docx》由会员分享,可在线阅读,更多相关《中南大学编译原理实验报告.docx(25页珍藏版)》请在冰点文库上搜索。
中南大学编译原理实验报告
实验1《词法分析程序设计与实现》
实验学时:
4实验地点:
二综实验日期:
一、实验目的
加深对词法分析器的工作过程的理解;加强对词法分析方法的掌握;能够采用一种编程语言实现简单的词法分析程序;能够使用自己编写的分析程序对简单的程序段进行词法分析
二、实验内容
自定义一种程序设计语言,或者选择已有的一种高级语言,编制它的词法分析程序。
词法分析程序的实现可以采用任何一种编程语言和编程工具。
从输入的源程序中,识别出各个具有独立意义的单词,即关键字、标识符、常数、运算符、界符。
并依次输出各个单词的内部编码及单词符号自身值。
(遇到错误时可显示“Error”,然后跳过错误部分继续显示)
三、实验方法
用java或者C语言写出分析器
四、实验步骤
1.定义目标语言的可用符号表和构词规则;
2.依次读入源程序符号,对源程序进行单词切分和识别,直到源程序结束;
3.对正确的单词,按照它的种别以<种别码,值>的形式保存在符号表中;
对不正确的单词,做出错误处理
五、实验结果
定义种别码
finalintNONE=0;
finalintDELIMITER=1;//操作符运算符
finalintVAR=2;//字符变量
finalintNum=3;//数字
finalintCOMMAND=4;//关键字
//finalintQUOTEDSTR=5;//带引号的字符串
//程序终结符endofprogram
finalStringEOP="#";
//声明关键字
finalintunKnowKeyword=0;
finalintFI=1;
finalintIF=2;
finalintTHEN=3;
finalintWHILE=4;
finalintDO=5;
finalintEND=6;
finalintELSE=7;
finalintTO=8;
finalintREAD=9;
finalintWRITE=10;
finalintEOL=11;
六、实验结论
由文件读入和控制台输出,良好的控制了要解析的句子过长的麻烦,实验结果也符合预期
七、实验小结
完成了词法编译器,很好的了解了底层编译过程中的词法分析
关键代码:
main.java
packagecn.main;
importjava.io.BufferedInputStream;
importjava.io.BufferedReader;
importjava.io.InputStreamReader;
importcn.method.*;
classMain{
publicstaticvoidmain(Stringargs[])
{
BufferedReaderbr=newBufferedReader(newInputStreamReader(System.in));
try{
System.out.println("请输入你要解析的文件");
Stringfilename=br.readLine();
filename="src/cn/file/"+filename;
CharacterAnalysisob=newCharacterAnalysis(filename);
ob.scanDisegn();
}catch(Exceptione){
}
}
}
CharacterAnalysis.java
packagecn.method;
importjava.io.BufferedReader;
importjava.io.FileNotFoundException;
importjava.io.FileReader;
importjava.io.IOException;
publicclassCharacterAnalysis{
//声明处理字符的类型
finalintNONE=0;
finalintDELIMITER=1;//操作符运算符
finalintVAR=2;//字符变量
finalintNum=3;//数字
finalintCOMMAND=4;//关键字
//finalintQUOTEDSTR=5;//带引号的字符串
//程序终结符endofprogram
finalStringEOP="#";
//声明关键字
finalintunKnowKeyword=0;
finalintFI=1;
finalintIF=2;
finalintTHEN=3;
finalintWHILE=4;
finalintDO=5;
finalintEND=6;
finalintELSE=7;
finalintTO=8;
finalintREAD=9;
finalintWRITE=10;
finalintEOL=11;
privatechar[]prog;
privateintprogIdx;
privateStringtoken;
privateinttokType;
privateintkwToken;
finalintPROG_SIZE=100000;
//将关键字的外部表示,和内部表示保存在一个名为KwTable的表中
KeywordkwTable[]={newKeyword("fi",FI),newKeyword("if",IF),
newKeyword("then",THEN),newKeyword("while",WHILE),
newKeyword("do",DO),newKeyword("end",END),
newKeyword("else",ELSE),newKeyword("to",TO),
newKeyword("read",READ),newKeyword("write",WRITE)};
publicCharacterAnalysis(StringprogramName)throwsIOException{
chartempbuf[]=newchar[PROG_SIZE];
intsize;
size=loadProgram(tempbuf,programName);
if(size!
=-1){
prog=newchar[size];
System.arraycopy(tempbuf,0,prog,0,size);
}
}
//读入一个需要分析的程序
privateintloadProgram(char[]p,Stringfname)throwsIOException{
intsize=0;
try{
FileReaderfr=newFileReader(fname);
BufferedReaderbr=newBufferedReader(fr);
size=br.read(p,0,PROG_SIZE);
fr.close();
}catch(FileNotFoundExceptionexc){
System.out.print("没有找到该文件!
");
}
if(p[size-1]==(char)31)
size--;
returnsize;
}
//分析程序代码
privatevoidgetToken()throwsIOException{
tokType=NONE;
token="";
kwToken=unKnowKeyword;
if(progIdx==prog.length){
token=EOP;
return;
}
//跳过空格符
while(progIdxprogIdx++;
//handlecrlf
if(prog[progIdx]=='\r'){
progIdx+=2;
kwToken=EOL;
token="\r\n";
return;
}
//扫描完所有的字符,endprogram
if(progIdx==prog.length){
if(progIdx==prog.length){
token=EOP;
tokType=DELIMITER;
return;
}
}
if(isDelim(prog[progIdx])){
//是一个操作符,或者是运算符
token+=prog[progIdx];
progIdx++;
//if(progIdx>=prog.length)break;
tokType=DELIMITER;
}elseif(Character.isLetter(prog[progIdx])){
//是一个字符变量
while(!
isDelim(prog[progIdx])){
token+=prog[progIdx];
progIdx++;
if(progIdx>=prog.length)
break;
}
kwToken=lookUp(token);
//如果是字符变量,用var标记,否则是关键字,用command标记
if(kwToken==unKnowKeyword)
tokType=VAR;
else
tokType=COMMAND;
}elseif(Character.isDigit(prog[progIdx])){
//是一个数字字符
while(!
isDelim(prog[progIdx])){
token+=prog[progIdx];
progIdx++;
if(progIdx>=prog.length)
break;
}
tokType=Num;
}
}
//判断字符是否是操作符
privatebooleanisDelim(charc){
if(("\r,+-*/:
<>=();".indexOf(c)!
=-1))
returntrue;
returnfalse;
}
booleanisSpaceOrTab(charc){
if(c==''||c=='\t')
returntrue;
returnfalse;
}
//查找字符串是否为关键字
privateintlookUp(Strings){
inti;
//Converttolowercase.
s=s.toLowerCase();
//查找字符串是否为关键字
for(i=0;iif(kwTable[i].keyword.equals(s))
returnkwTable[i].keywordindex;
returnunKnowKeyword;//不是一个关键字
}
//对代码进行输出处理
publicvoidscanDisegn()throwsIOException{
//对代码扫描
do{
getToken();
//扫描到字符是变量
if(tokType==VAR){
System.out.println(token+""+"29");
}
//扫描到字符是关键字
elseif(tokType==COMMAND){
switch(kwToken){
caseFI:
System.out.println("fi"+""+"1");
break;
caseIF:
System.out.println("if"+""+"2");
break;
caseTHEN:
System.out.println("then"+""+"3");
break;
caseWHILE:
System.out.println("while"+""+"4");
break;
caseDO:
System.out.println("do"+""+"5");
break;
caseEND:
System.out.println("end"+""+"6");
break;
caseELSE:
System.out.println("else"+""+"7");
break;
caseTO:
System.out.println("to"+""+"8");
break;
caseREAD:
System.out.println("read"+""+"9");
break;
caseWRITE:
System.out.println("write"+""+"10");
break;
}
}
//扫描到字符是数字
elseif(tokType==Num){
System.out.println(token+""+"28");
}
//扫描到字符是操作符
elseif(tokType==DELIMITER){
if(token.equals("+"))
System.out.println(token+""+"14");
if(token.equals("-"))
System.out.println(token+""+"15");
if(token.equals("*"))
System.out.println(token+""+"16");
if(token.equals("/"))
System.out.println(token+""+"17");
if(token.equals(":
="))
System.out.println(token+""+"18");
if(token.equals("<"))
System.out.println(token+""+"20");
if(token.equals("<>"))
System.out.println(token+""+"21");
if(token.equals("<="))
System.out.println(token+""+"22");
if(token.equals(">"))
System.out.println(token+""+"23");
if(token.equals(">="))
System.out.println(token+""+"24");
if(token.equals("="))
System.out.println(token+""+"25");
if(token.equals(";"))
System.out.println(token+""+"26");
if(token.equals("("))
System.out.println(token+""+"27");
if(token.equals(")"))
System.out.println(token+""+"28");
}
}while(!
token.equals(EOP));
System.out.println("#"+""+"30");
System.out.println("程序分析完毕");
}
}
Keyword.java
packagecn.method;
publicclassKeyword{
Stringkeyword;
intkeywordindex;
Keyword(Stringstr,intt){
keyword=str;
keywordindex=t;
}
}
实验二预测分析法设计与实现
一、实验目的
加深对语法分析器工作过程的理解;加强对预测分析法实现语法分析程序的掌握;能够采用一种编程语言实现简单的语法分析程序;能够使用自己编写的分析程序对简单的程序段进行语法翻译。
二、实验内容
在实验1的基础上,用预测分析法编制语法分析程序,语法分析程序的实现可以采用任何一种编程语言和工具。
三、实验要求:
1.对语法规则有明确的定义;
2.编写的分析程序能够对实验一的结果进行正确的语法分析;
3.对于遇到的语法错误,能够做出简单的错误处理,给出简单的错误提示,保证顺利完成语法分析过程;
4.实验报告要求用文法的形式对语法定义做出详细说明,说明语法分析程序的工作过程,说明错误处理的实现。
四、实验步骤
1.定义目标语言的语法规则;
2.求解预测分析方法需要的符号集和分析表;
3.依次读入实验一的分析结果,根据预测分析的方法进行语法分析,直到源程序结束;
4.对遇到的语法错误做出错误处理。
五,实验小结
在实验一基础上,完成了预测分析法。
语法分析是编译过程词法分析后面的一部分,也是我们对最底层过程的很好的了解
失败:
成功:
关键代码:
Analy.cpp
#include"stdafx.h"
#include"Stack.h"
#include
usingnamespacestd;
charvn[]={'S','A','C','B'};//定义非终结符
charvt[]={'a','b','c','d','e'};//定义终结符
typedefvoid(*Act)();
Stackstack;
voidLL1();
voidfailed()
{
cout<<"分析失败!
\n";
exit(-1);
}
voidevent1()
{
stack.push('e');
stack.push('B');
stack.push('c');
stack.push('A');
stack.push('a');
}
voidevent2()
{
stack.push('C');
stack.push('b');
}
voidevent3()
{
stack.push('d');
}
voidevent4()
{
}
ActanyTable[4][6]={
{event1,failed,failed,failed,failed},
{failed,event2,failed,failed,failed},
{failed,event2,event4,failed,failed},
{failed,failed,failed,event3,failed},
};
//判断是终结符还是非终结符
boolVt(charch)
{
for(inti=0;i<5;i++)
{
if(vt[i]==ch)
returntrue;
else
continue;
}
returnfalse;
}
voidpushStack(charvn,charvt)
{
switch(vn)
{
case'S':
switch(vt)
{
case'a':
anyTable[0][0]();break;
case'b':
anyTable[0][1]();break;
case'c':
anyTable[0][2]();break;
case'd':
anyTable[0][3]();break;
case'e':
anyTable[0][4]();break;
default:
break;
}
break;
case'A
':
switch(vt)
{
case'a':
anyTable[1][0]();break;
case'b':
anyTable[1][1]();break;
case'c':
anyTable[1][2]();break;
case'd':
anyTable[1][3]();break;
case'e':
anyTable[1][4]();break;
default:
break;
}
break;
case'C':
switch(vt)
{
case'a':
anyTable[2][0]();break;
case'b':
anyTable[2][1]();break;
case'c':
anyTable[2][2]();break;
case'd':
anyTable[2][3]();brea