编译原理实验 编译器 综合报告(附源代码)_编译原理实验报告模版
编译原理实验 编译器 综合报告(附源代码)由刀豆文库小编整理,希望给你工作、学习、生活带来方便,猜你可能喜欢“编译原理实验报告模版”。
编译原理 编译器综合实验
---------------工程精品
神刀公子
一. 实验背景
编译器就是将“一种语言(通常为高级语言)”翻译为“另一种语言(通常为低级语言)”的程序。一个现代编译器的主要工作流程:源代码(source code)→ 预处理器(preproceor)→ 编译器(compiler)→ 目标代码(object code)→ 链接器(Linker)→ 可执行程序(executables)高级计算机语言便于人编写,阅读交流,维护。机器语言是计算机能直接解读、运行的。编译器将汇编或高级计算机语言源程序(Source program)作为输入,翻译成目标语言(Target language)机器代码的等价程序。源代码一般为高级语言(High-level language),如Pascal、C、C++、Java、汉语编程等或汇编语言,而目标则是机器语言的目标代码(Object code),有时也称作机器代码(Machine code)。
对于C#、VB等高级语言而言,此时编译器完成的功能是把源码(SourceCode)编译成通用中间语言(MSIL/CIL)的字节码(ByteCode)。最后运行的时候通过通用语言运行库的转换,编程最终可以被CPU直接计算的机器码(NativeCode)。
二. 算法设计
典型的编译器输出是由包含入口点的名字和地址,以及外部调用(到不在这个目标文件中的函数调用)的机器代码所组成的目标文件。一组目标文件,不必是同一编译器产生,但使用的编译器必需采用同样的输出格式,可以链接在一起并生成可以由用户直接执行的EXE, 词法分析程序 语法分析程序 语义分析程序 编译器。不断完善,不断改进。渐变的过程。
。。函数。。
void scanner();//扫描 void lrparser();
void staBlock(int *nChain);//语句块 void staString(int *nChain);//语句串 void sta(int *nChain);//语句 void fuzhi();//赋值语句
void tiaojian(int *nChain);//条件语句 void xunhuan();//循环语句 char* E();//Expresiion表达式 char* T();//Term项 char* F();//Factor因子
char *newTemp();//自动生成临时变量 void backpatch(int p,int t);//回填
int merge(int p1,int p2);//合并p1和p2 void emit(char *res,char *num1,char *op,char *num2);//生成四元式
截图说明:
综合输入:(赋值,循环,条件。。结合,自己定义即可)
源代码:
//************编译器******************** // //***Erin*** //***软件工程0801班*** //***HUST*** // //**************************************
#include #include #include #include
char prog[80];//存放所有输入字符
char token[8];//存放词组
char ch;//单个字符
int syn,p,m,n,i;//syn:种别编码
double sum;
int count;
int isSignal;//是否带正负号(0不带,1负号,2正号)int isError;int isDecimal;//是否是小数
double decimal;//小数
int isExp;//是否是指数
int index;//指数幂
int isNegative;//是否带负号
double temp;
int temp2;
int repeat;//是否连续出现+,{
if(syn==22)//+
strcpy(op,“+”);
else
strcpy(op,“-”);
scanner();
strcpy(num2,T());
strcpy(res,newTemp());
emit(res,num1,op,num2);
strcpy(num1,res);} return num1;}
char* T()//Term项 { char *res,*num1,*op,*num2;res=(char *)malloc(10);num1=(char *)malloc(10);op=(char *)malloc(10);num2=(char *)malloc(10);strcpy(num1,F());while((syn==24)||(syn==25))//* / {
if(syn==24)
strcpy(op,“*”);
else
strcpy(op,“/”);
scanner();
strcpy(num2,F());
strcpy(res,newTemp());
emit(res,num1,op,num2);
strcpy(num1,res);} return num1;}
char* F()//Factor因子 { char *res;
res=(char *)malloc(10);if(syn==10)//字符串 { strcpy(res,token);scanner();} else if(syn==20)//二进制数 {
itoa((int)sum,res,10);//整数转换为字符串
scanner();} else if(syn==26)//({
scanner();
res=E();
if(syn==27)//)
{
scanner();
}
else isError=1;} else
isError=1;return res;}
char *newTemp(){ char *p;char varTemp[10];p=(char *)malloc(10);kk++;itoa(kk,varTemp,10);strcpy(p+1,varTemp);p[0]='T';return p;}
//将p所链接的每个四元式的第四个分量都回填t void backpatch(int p,int t){ int w,circle=p;while(circle)//circle不为0的时候
{
} w=atoi(fourCom[circle].result);//四元式circle第四分量内容
//strcpy(fourCom[circle].result,t);//把t填进四元式circle的第四分量
sprintf(fourCom[circle].result,“%d”,t);circle=w;//w记录的是链条上下一个四元式,移动!} return;int merge(int p1,int p2)//合并p1和p2 { char circle,nResult;if(p2==0)
nResult=p1;else {
nResult=circle=p2;
} while(atoi(fourCom[circle].result))//四元式第四个分量不为0 { circle=atoi(fourCom[circle].result);
//strcpy(fourCom[circle].result,p1);sprintf(fourCom[circle].result,“%s”,p1);} //目的是用p1的值覆盖0 return nResult;//p2是头,p1覆盖0,接在p2后边 }
void emit(char *res,char *num1,char *op,char *num2){ strcpy(fourCom[nextq].result,res);strcpy(fourCom[nextq].arg1,num1);strcpy(fourCom[nextq].opera,op);strcpy(fourCom[nextq].arg2,num2);nextq++;}
void scanner()
{
sum=0;
decimal=0;
m=0;
for(n=0;n
token[n]=NULL;
ch=prog[p++];//从prog中读出一个字符到ch中
while(ch==' '||ch=='n')//跳过空字符(无效输入)
ch=prog[p++];
if(((ch>='a')&&(ch='A')&&(ch
{
while(((ch>='a')&&(ch='A')&&(ch='0')&&(ch
{
token[m++]=ch;//ch=>token
ch=prog[p++];//读下一个字符
}
token[m++]=' ';
p--;//回退一格
syn=10;//标识符
//如果是“begin”,“if”,“then”,“while”,“do”,“end”标识符中的一个
for(n=0;n
if(strcmp(token,rwtab[n])==0)
{
syn=n+1;
break;
}
}
else if((ch>='0')&&(ch
{
IsNum:
if(isSignal==1)
{
//token[m++]='-';
}
while((ch>='0')&&(ch
{
sum=sum*10+ch-'0';//ch中数字本身是当做字符存放的ch=prog[p++];
}
if(ch=='.')
{
isDecimal=1;
ch=prog[p++];
count=0;//之前忘了清零,123.123+123.123#两个浮点数就无法识别
while((ch>='0')&&(ch
{
//pow(x,y)计算x的y次幂
temp=(ch-'0')*pow(0.1,++count);
decimal=decimal+temp;
//AddToDec();
ch=prog[p++];
}
sum=sum+decimal;
}
if(ch=='e'||ch=='E')
{
isExp=1;
ch=prog[p++];
if(ch=='-')
{
isNegative=1;
ch=prog[p++];
}
while((ch>='0')&&(ch
{
//指数
index=index*10+ch-'0';
ch=prog[p++];
}
//10的幂
//123e3代表123*10(3)
//sum=sum*pow(10,index);是错误的if(isNegative)
sum=sum*pow(0.1,index);
else
sum=sum*pow(10,index);
}
if(isSignal==1)
{
sum=-sum;
isSignal=0;
}
p--;
syn=20;
}
else switch(ch)
{
case '
m=0;
token[m++]=ch;
ch=prog[p++];
if(ch=='=')
{
syn=35;
token[m++]=ch;
}
else
{
syn=34;
p--;
}
break;
case '>':
m=0;
token[m++]=ch;
ch=prog[p++];
if(ch=='=')
{
syn=33;
token[m++]=ch;
}
else
{
syn=32;
p--;
}
break;
case '=':
m=0;
token[m++]=ch;
ch=prog[p++];
if(ch=='=')
{
syn=36;
token[m++]=ch;
}
else
{
syn=21;
p--;
}
break;
case '+':
temp2=prog[p];
token[m++]=ch;
if((temp2>='0')&&(temp2
{
isSignal=2;
ch=prog[p++];
repeat=0;
goto IsNum;
}
if(((temp2=='+')||(temp2=='-'))&&(repeat==0))的+,-视为正负号
{
repeat=1;
//ch=prog[p++];
}
syn=22;
break;
case '-':
temp2=prog[p];
token[m++]=ch;
if((temp2>='0')&&(temp2
{
isSignal=1;
ch=prog[p++];//读“-”下一个字符
repeat=0;
goto IsNum;//转到数字的识别
}
if(((temp2=='+')||(temp2=='-'))&&(repeat==0))的+,-视为正负号
{
repeat=1;//预言会重复
//如果重复出现符号,才将后边//如果重复出现符号,才将后边
//ch=prog[p++];//读下一个字符
}
syn=23;
break;
case '*':
temp2=prog[p];
token[m++]=ch;
if(temp2=='+')
{
isSignal=2;
repeat=1;
}
else if(temp2=='-')
{
isSignal=1;
repeat=1;
}
syn=24;
break;
case '/':
syn=25;
token[m++]=ch;
break;
case '(':
temp2=prog[p];
token[m++]=ch;
if(temp2=='+')
{
isSignal=2;
repeat=1;
}
else if(temp2=='-')
{
isSignal=1;
repeat=1;
}
syn=26;
break;
case ')':
syn=27;
token[m++]=ch;
break;
case '{':
syn=28;
token[m++]=ch;
break;
case '}':
syn=29;
token[m++]=ch;
break;
case ',':
syn=30;
token[m++]=ch;
break;
case ';':
syn=31;
token[m++]=ch;
break;
case'#':
syn=0;
token[m++]=ch;
break;
default:
syn=-1;
}
}