精品文档
编译技术 班 级 网络 0802
学 号 3080610052
姓 名 叶晨舟
指导老师 朱 玉 全
2011年 7 月 4 日
一、目的编译技术是理论与实践并重的课程,而其实验课要综合运用一、二年级所学的多门课程的内容,用来完成一个小型编译程序。从而巩固和加强对词法分析、语法分析、语义分析、代码生成和报错处理等理论的认识和理解;培养学生对完整系统的独立分析和设计的能力,进一步培养学生的独立编程能力。
二、任务及要求
基本要求:
词法分析器 产生下述小语言的单词序列
这个小语言的所有的单词符号,以及它们的种别编码和内部值如下表:
单词符号
种别编码
助记符
内码值
DIM
IF
DO
STOP
END
标识符
常数(整)
=
+
*
**
,
(
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
$DIM
$IF
$DO
$STOP
$END
$ID
$INT
$ASSIGN
$PLUS
$STAR
$POWER
$COMMA
$LPAR
$RPAR
-
-
-
-
-
-
内部字符串
标准二进形式
-
-
-
-
-
-
对于这个小语言,有几点重要的限制:
首先,所有的关键字(如IF﹑WHILE等)都是“保留字”。所谓的保留字的意思是,用户不得使用它们作为自己定义的标示符。例如,下面的写法是绝对禁止的:
IF(5)=x
其次,由于把关键字作为保留字,故可以把关键字作为一类特殊标示符来处理。也就是说,对于关键字不专设对应的转换图。但把它们(及其种别编码)预先安排在一张表格中(此表叫作保留字表)。当转换图识别出一个标识符时,就去查对这张表,确定它是否为一个关键字。
再次,如果关键字、标识符和常数之间没有确定的运算符或界符作间隔,则必须至少用一个空白符作间隔(此时,空白符不再是完全没有意义的了)。例如,一个条件语句应写为
IF i>0 i= 1;
而绝对不要写成
IFi>0 i=1;
因为对于后者,我们的分析器将无条件地将IFI看成一个标识符。
这个小语言的单词符号的状态转换图,如下图:
语法分析器 能识别由加+ 减- 乘* 除/ 乘方^ 括号()操作数所组成的算术表达式,其文法如下:
E→E+T|E-T|T
T→T*F|T/F|F
F→P^F|P
p→(E)|i
使用的算法可以是:预测分析法;递归下降分析法;算符优先分析法;LR分析法等。
中间代码生成器 产生上述算术表达式的中间代码(四元式序列)
三、实现过程
给出各题目的详细算法描述,数据结构和函数说明,流程图。
1、词法分析器的流程图
2、语法分析器主程序图
3、中间代码生成器流程图:
四、源程序
词法分析器:
#include<string.h>
#include<malloc.h>
#include<iostream>
using namespace std;
typedef struct table //分析表存储结构
{
char m[100];
}table;
table M[100][100]; //定义分析表
typedef struct stacknode //定义栈内元素节点 (带头结点(为空)的)
{
char data;
struct stacknode *next;
}stackk;
void initlink(stackk *&s) //初始化新栈
{
s=(stackk *)malloc(sizeof(stackk));
s->next=NULL;
}
void poplink(stackk *&s) //顶元素出栈
{
stackk *p;char v;
if(s->next!=NULL)
{
p=s->next;
v=p->data;
s->next=p->next;
}
free(p);
}
void pushlink(stackk *&s,char x) //新 元 素 入 栈
{
stackk *p;
p=(stackk *)malloc(sizeof(stackk));
p->data=x;
p->next=s->next;
s->next=p;
}
void display(stackk *s) //打印 现实显示 栈内元素
{
stackk *p;
int i=0,j;
char st[100];
p=s->next;
while(p!=NULL)
{
st[i++]=p->data;
p=p->next;
}
for(j=i-1;j>=0;j--)
printf("%c",st[j]);
for(j=0;j<16-i;j++) //打印 对齐格式
printf("%c",' ');
}
char gettop(stackk *s) //返 回 栈 顶 元 素 值
{
if(s->next==NULL)
return 0;
else
return s->next->data;
}
int find(char c,char array[]) //查找函数,
{
int i;
int flag=0;
for(i=0;i<100;i++)
{
if(c==array[i])
flag=1;
}
return flag;
}
int location(char c,char array[]) //定位函数,指出字符所在位置
{
int i;
for(i=0;i<100;i++)
{
if(c==array[i])
return i;
}
}
void error() //出错函数定义
{
printf("%15c出错!\n",' ');
}
void analyse(char Vn[],char Vt[])
{
int i,j,m,p,q,length,t,h;
char w,X;
char str[100];
opt0:
scanf("%s",str);
for(i=0;i<strlen(str);i++)
{
if(!find(str[i],Vt))
{
printf("输入字符串有误!请重新输入!");
goto opt0;
break;
}
}
stackk *st;
initlink(st);
pushlink(st,'#');
pushlink(st,Vn[0]); //#与识别符号入栈
j=0;
h=1;
w=str[0];
printf("步骤%-12c分析栈%-24c剩余输入串%-12c所用产生式\n",' ',' ',' ');
opt1:
printf("%-16d",h); //显示步骤
h++;
display(st); //显示分析栈中内容
X=gettop(st); //上托栈顶符号放入X
poplink(st);
for(int k=0;k<14+j;k++) //打印对齐格式
printf("%c",' ');
for(t=j;t<strlen(str);t++)
{
printf("%c",str[t]); //显示剩余字符串
}
if(find(X,Vt)&& X!='#') //分析栈的栈顶元素和剩余输入串的第一个元素相比较
{
if(X==w)
{
printf("%15c匹配\n",X);
j++;
w=str[j];
goto opt1;
}
else
error();
}
else
{
if(X=='#')
{
if(X==w)
{
printf("%8c是该文法的句子!\n",' ');
}
else
error();
}
else
{
p=location(X,Vn);
q=location(w,Vt);
char *S1="null",*S2="NULL";
if(strcmp(M[p][q].m,S1)==0||strcmp(M[p][q].m,S2)==0) //查找产生式
error();
else
{
char str0[100];
strcpy(str0,M[p][q].m);
printf("%15c-->%s\n",X,str0); //显示对应的产生式
if(strcmp(str0,"$")==0)
goto opt1;
else
{
length=strlen(str0); //逆序进栈
for(m=length-1;m>=0;m--)
{
pushlink(st,str0[m]);
}
goto opt1;
}
}
}
}
}
int main()
{
int i,k,n,r;
char Vn[100],Vt[100],select;
printf("******************************************************************\n");
printf("对任意输入LL(1)文法的分析表,判断验证字符串是否为该文法的句子 \n");
printf("并能给出分析和演示过程。
\n");
printf("******************************************************************\n");
opt2:
printf("请输入各终结符(#号表示结束 )Vt[i]:\n");
for(i=0;i<100;i++)
{
scanf("%c",&Vt[i]);
if(Vt[i]=='#')
{
r=i;
break;
}
}
printf("请输入非终结符个数:\n");
scanf("%d",&n);
getchar();
for (i=0;i<n;i++)
{
printf("请输入非终结符Vn[%d]:\n",i);
scanf("%c",&Vn[i]);
getchar();
printf("请输入此非终结符对应各终结符的产生式右部(null或NULL表示出错;$表示空串):\n");
for(k=0;k<=r;k++)
{
scanf("%s",M[i][k].m);
getchar();
}
}
opt3:
printf("请输入要分析的字符串,且以#结束:\n");
analyse(Vn, Vt);
printf("********************请选择***********************\n");
printf(" 1: 输入字符串 \n");
printf(" 2: 输入新分析表 \n");
printf(" 0: 退 出 \n");
printf("*************************************************\n");
opt4:
cin>>select;
switch(select)
{
case '1': {goto opt3;break;}
case '2': {goto opt2;}
case '0': {break;}
default: {printf("输入错误!请重新选择:");
goto opt4;
break;}
}
return 0;
}
运行结果:
语法分析器 源程序:
#include<string.h>
#include<iostream>
using namespace std;
char prog[100],token[10];
char ch;
int syn,p,m=0,n,row,sum=0;
char *rwtab[20]={"dim","if","do","stop","end" ,"and","begin","bool","case","char",
"false","for","int","not","or","set","then","true","until","while"
};
void scaner()
{
for(n=0;n<9;n++) token[n]=NULL;
ch=prog[p++];
while(ch==' ')
{
ch=prog[p];
p++;
}
if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z'))
{
m=0;
while((ch>='0'&&ch<='9')||(ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z'))
{
token[m++]=ch;
ch=prog[p++];
}
token[m++]='\0';
p--;
syn=21;
for(n=0;n<20;n++)
{
if(strcmp(token,rwtab[n])==0)
{
syn=n+1;
break;
}
}
}
else if((ch>='0'&&ch<='9'))
{
{
sum=0;
while((ch>='0'&&ch<='9'))
{
sum=sum*10+ch-'0';
ch=prog[p++];
}
}
p--;
syn=7+15;
if(sum>32767)
syn=-1;
}
else switch(ch)
{
case'=':syn=8+15;token[0]=ch;break;
case'+':syn=9+15;token[0]=ch;break;
case'*':
m=0;
token[m++]=ch;
ch=prog[p++];
if(ch=='*')
{
syn=11+15;
token[m++]=ch;
}
else
{
syn=10+15;
p--;
}
break;
case',':syn=12+15;token[0]=ch;break;
case'(':syn=13+15;token[0]=ch;break;
case')':syn=14+15;token[0]=ch;break;
case'#':syn=0;token[0]=ch;break;
case'<':m=0;token[m++]=ch;
ch=prog[p++];
if(ch=='>')
{
syn=17+15;
token[m++]=ch;
}
else if(ch=='=')
{
syn=16+15;
token[m++]=ch;
}
else
{
syn=15+15;
p--;
}
break;
case'>':m=0;token[m++]=ch;
ch=prog[p++];
if(ch=='=')
{
syn=19+15;
token[m++]=ch;
}
else
{
syn=18+15;
p--;
}
break;
case':':m=0;token[m++]=ch;
ch=prog[p++];
if(ch=='=')
{
syn=21+15;
token[m++]=ch;
}
else
{
syn=20+15;
p--;
}
break;
case'/':syn=22+15;token[0]=ch;break;
case'-':syn=23+15;token[0]=ch;break;
case';':syn=24+15;token[0]=ch;break;
default: syn=-1;break;
}
}
void main()
{
p=0;
row=1;
cout<<endl<<endl<<endl;
cout<<"***************************小型词法分析器**********************************"<<endl<<endl;
cout<<"请输入一段程序(以#结束):";
do
{
cin.get(ch);
prog[p++]=ch;
}
while(ch!='#');
p=0;
cout<<endl<<"**************************词法分析结果如下*********************************"<<endl;
cout<<" 种别编码 自身值"<<endl;
do
{
scaner();
switch(syn)
{
case 22 : cout<<" ("<<syn<<" , "<<sum<<")"<<endl; break;
case -1: cout<< " Error in row"<<row<<"!"<<endl; break;
default: cout<<" ("<<syn<<" , "<<token<<")"<<endl;break;
}
}
while (syn!=0);
}
运行结果:
}
中间代码生成器源程序:
表达式生成四元式
递归子程序法
#include<string>
#include <iostream>
using namespace std;
#define DEFAULT_SIZE 100
char EMachine(char w); //表达式E的自动机
char TMachine(char w); //表达式T的自动机
char FMachine(char w); //表达式F的自动机
bool ZMachine(); //表达式Z的自动机
string intToString(int a); //整形变成字符串形函数
class stack //栈类定义
{
private:
int top;
string *stacka;
int maxsize;
public:
stack(int size=DEFAULT_SIZE);
~stack(){ delete [] stacka; }
void push(const string &item);
string pop(void);
string gettop(void) const ;
bool empty(void) const { return (top==-1); }
bool full(void) const { return (top==maxsize-1); }
void clear(void) { top=-1; }
};
stack::stack(int size) //栈类的构造函数
{
top=-1;
maxsize=size;
stacka=new string[maxsize];
if(!stacka)
{
cerr<<"allocate memory failed."<<endl;
exit(1);
}
}
void stack::push(const string &item) //压栈操作
{
if(full())
{
cerr<<"stack full, cannot push."<<endl;
return;
}
top++;
stacka[top]=item;
}
string stack::pop(void) //出栈操作
{
if(empty())
{
cerr<<"stack empty, cannot pop."<<endl;
exit(1) ;
}
string item=stacka[top];
top--;
return item;
}
string stack::gettop(void) const //取栈顶操作
{
if(empty())
{
cerr<<"stack empty, cannot gettop."<<endl;
exit(1) ;
}
return stacka[top];
}
static stack wordStack; //符号栈
static int noOfQuet=0; //静态四元式个数记录
static int noOfT = 1; //静态状态个数记录
void main(){ //主函数
char yesOrNo; //进行一个循环操作控制
do{
cout<<"请输入算术表达式:"<<endl;
noOfT = 1; //每次结束询问
ZMachine();
cout<<endl<<"Continue?Yes or Not:";
cin>>yesOrNo; //输入“Y”则继续
}while(yesOrNo=='y'); //否则程序结束
}
bool ZMachine(){ //Z自动机
char w;
cin>>w;
w = EMachine(w); //调用E自动机
if(w=='#'){ //遇到“#”则结束
return true;
}
else{
return false;
}
}
char EMachine(char w){ //E自动机
string operate,a,b,c;
string state[5];
w = TMachine(w); //调用T自动机
while(w=='+'||w=='-'){ //是加或减符号
operate = w;
cin>>w; //读入下一字符
w = TMachine(w); //调用T自动机
b = wordStack.pop(); //字符栈弹出
a = wordStack.pop(); //两个操作字符
cout<<"(\""<<operate<<"\","<<a<<","<<b<<",t"<<noOfT<<")"<<endl;
c = "t"+intToString(noOfT); //输出四元式
wordStack.push(c); //新状态压栈
noOfT++; //状态计数加一
}
return w;
}
char TMachine(char w){
string operate,a,b,c;
string state[5];
w = FMachine(w); //调用F自动机
while(w=='*'||w=='/'){ //是乘除号
operate = w;
cin>>w; //读取下一字符
w = FMachine(w); //调用F自动机
b = wordStack.pop(); //符号栈弹出
a = wordStack.pop(); //两个操作字符
cout<<"(\""<<operate<<"\","<<a<<","<<b<<",t"<<noOfT<<")"<<endl;
c = "t"+intToString(noOfT); //输出四元式
wordStack.push(c); //新状态压栈
noOfT++; //状态计数加1
}
return w;
}
char FMachine(char w){ //F自动机
string theWord;
if(w>='a'&&w<='z'||w>='A'&&w<='Z'){
theWord = w; //当前字符是字母
wordStack.push(theWord); //则压栈
}
else if(w == '('){ //是左括号
cin>>w; //则读取下一字符
w = EMachine(w); //调用E自动机
if(w!=')'){ //不是右括号则输入有误,报错
cerr<<"the input is wrong!"<<endl;
exit(0);
}
}
else{ //否则有误,报错
cerr<<"the input is wrong!"<<endl;
exit(0);
}
cin>>w; //读取下一字符
return w;
}
string intToString(int a){ //整形变字符串形函数
string d;
char b='0',c;
int i;
while(a!=0){
i = a%10;
a = a/10;
c = (int)b + i;
d = c + d;
}
return d;
}
//Y=a+b*(c+(-d)*(e+f))
//Y=(a+b*(c-d*e/f+g*(h-i*x*(j+k*(-l)*(j+k)))+w))
//H=(d+a-(c+b-q)*a)+c-(a+b*(c+d))
六、总结
通过这次实验,我对编译原理这门专业必修课有了进一步的深层次了解,把理论知识应用于实验中,也让我重新熟悉了C++语言的相关内容,加深了对C++语言知识的深化和用途的理解。相信在以后的毕业设计以及读研自己做项目时可以有更大的提升。
售后服务方案(赠送)
1.售后服务概述
公司长期以来一直致力于提供高质量、完善的支持服务,确保用户的系统稳定运行。
公司拥有一批资深的施工人员,具有丰富的经验,能够很好的解决设备各类故障,强大的用户支持队伍和良好的用户满意度是我们的一大优势。
维护计划及承诺
?一、 项目售后服务内容承诺
我公司贯彻执行:“诚信正直、成就客户、完善自我、追求卓越”的宗旨,对于已经竣工、验收合格的项目进行质量跟踪服务,本着技术精益求精的精神,向用户奉献一流的技术和一流的维护服务。
我公司如果承接了端拾器项目,将严格遵循标书及合同的规定,在保证期内向业主提供该项目的责任和义务。在保修期之后,考虑到设备维护的连续性,建议业主与我公司签订维护合同,以确保此系统项目的正常运行所必需的技术支持和管理支持。
二、 服务与保证期
?在项目验收合格之日起,开始进行售后服务工作,包括以下几个方面:
1、售后服务期; ?2、维护人员; 3、售后服务项目; 4、服务响应时间。
? 三、 售后服务期
? 在项目验收合格之日起,即进入了售后服务期。
售后服务期=质量保证期+质量维护期
? 质量保证期:在质量保证期内,如因质量问题造成的故障,实行免费更换设备、元器件及材料。如因非质量因素造成的故障,收取更换设备、元器件及材料成本费。
质量维护期:在质量保证期之后,即自行进入质量维护期。
我方对所承担端拾器项目提供终身质量维护服务,以不高于本合同设备单价的优惠价格提供所需更换的元器件及材料,另收维护人员工本费。
四、 具体措施承诺
? 1、首先在签订项目合同的同时与客户签订售后服务保证协议书,排除客户的后顾之忧,对客户做出实事求是的、客观的承诺。
2、对已经验收合格交付用户的端拾器项目,在合同期内与用户进行联系,记录用户使用情况,系统运行状况等进行质量跟踪调查,变被动服务为主动服务。
3、对已交工的端拾器项目建立系统运行档案,并进行质量跟踪。
4、系统运行档案记录其端拾器项目运行情况、各类设备使用情况、操作人员操作水平情况及人员流动情况。
5、针对各用户单位操作人员出现的代表性问题,定期对操作人员进行技术培训或到现场培训及指导。
6、正在使用中的系统、设备出现故障时,公司维修服务人员接到报告后及时赴现场处理、维修。
7、对于运行时间较长的端拾器项目,公司维修服务人员定期与客户进行联系询问情况,定期到客户方进行巡视、检查,并做出记录,记录归档保存。
8、施工保证
将选派具有丰富经验的技术人员负责端拾器项目具体施工,保证安装质量及系统使用功能,并保证整个系统运行平稳、高效、可靠。
9、系统保修
作为项目承包单位,我公司将严格遵循招标文件及合同的规定,向业主提供端拾器项目最终验收合格之日起,在保质期范围内免费维修。
10、保修期内设备损坏,经鉴定为设备本身原因造成的故障,我方负责免费维修或者更换;同时负责在保修期内定期对设备提供保养维护服务。
总之,为使业主使用放心、使用方便、保证端拾器项目正常运行,公司全体技术、维护人员本着客户第一的原则,全心全意地为客户着想,全力以赴的进行工作,让我们共同携手,为创造美好的明天而努力工作。
五、保修服务内容及范围
我公司将为所承担的各个端拾器项目提供保修服务,有效期从项目验收后,业主在竣工报告上签字之日起。
1、 响应时间:具体的响应时间将按故障级别划分;
2、 维修地点:用户现场。
我公司负责实施的所有系统项目,在正常环境下做适当使用时所发生的故障,我公司将提供约定保修服务。非当前故障,我公司安排提供服务,但需按收费标准另收费用。
我公司的保修服务仅限于经我公司认定的合格产品。所谓不合格的产品包括:非经我公司供应的产品、非经我公司认定合格的产品及顾客不允许我公司做功能改进的产品。
下列情况所发生的系统损害不包括在保修服务范围内:
1、 使用不适当的工具进行系统维护时造成的系统设备损坏;
2、 现场环境不符合我公司建议的规范;
3、 意外、自然灾害、疏忽及不当使用、战争、暴动、罢工、雷击或电力故障、顾客搬运不当的损坏,经由非我公司人员或其授权的子承包商对系统进行修改和变动;
4.设备的维护和信息处理方式。
六、 系统维护
1、系统运行管理工作
为了保证系统能够长时间的正常运行,我们将进行完善的系统培训,同时制定各个系统项目操作规程,并配合业主制定操作人员责任界面及合理的交接班制度。
2、系统维护保养
我公司的售后服务人员在维护期内将对贵方的系统项目提供服务,使它们保持良好的运行状态。
? 3、月度保养
? 坚持月度维护保养,保证每个系统项目机械装置保持最佳工作状态。
七、维护及服务支持措施
1、电话支持服务
电话服务热线号码以我方提供给业主的号码为准(包括电话和传真号码)。如有更改,我方至少在自更改之日起3天内以电子邮件、传真、电话的方式通知业主。
2、现场排除故障或技术指导
我方在接到业主的电话支持服务请求后,如果不能通过电话支持服务解决设备或产品发生的技术故障,且经双方商议确认需要进行现场支持的情况下,我方将派专业项目技术人员及时前往现场协助业主排除故障。
3、电话咨询服务
对业主在使用设备或产品过程中产生的非故障类问题,我方提供电话咨询服务。
4、投诉受理服务
我方在公司设有用户投诉电话