编译原理上机指导.docx
- 文档编号:16506744
- 上传时间:2023-07-14
- 格式:DOCX
- 页数:40
- 大小:74.19KB
编译原理上机指导.docx
《编译原理上机指导.docx》由会员分享,可在线阅读,更多相关《编译原理上机指导.docx(40页珍藏版)》请在冰点文库上搜索。
编译原理上机指导
))))))
实验一、简单的扫描器设计_源程序代码:
#includestdafx.h
#includestring.h
#defineN15
structTokenType
{intcode,value;};
char*keywords[]={program,procedure,egin,end,while,do,
+,*,:
:
=,=,,,;,(,)};//关键字表、界符表
charID[10][10];//符号表
intm;
intCons[10];//常数表
intn;
voidPrint(structTokenTypetoken)//输出Token
{
printf((%d%d),token.code,token.value);
}
voidProcError()
{
printf(err!
);
}
intIsLetter(charch)//判断ch是否为字母
{if(ch>='A'&&ch<='Z'||ch>='a'&&ch<='z')
return1;
else
return0;
}
intIsDigit(charch)//判断ch是否为数字
{if(ch>='0'&&ch<='9')
return1;
else
return0;
}
intReserve(char*strToken)
//用strToken中的单词去查关键字表。
查到了,则返回该关键字的编码;
//否则,返回0
{inti=0;
while(i {if(! strcmp(keywords[i],strToken)) return(i+3); i++; } return0; ))))). )))))) } intInsertID(char*strToken) //用strToken中的单词去查符号表。 查到了,则返回该单词在表中的位置值; //否则,将strToken中的单词插入符号表的尾部,并返回位置值 {inti=0; while(i {if(! strcmp(ID[i],strToken)) returni; i++; } strcpy(ID[i],strToken); m++; returni; } inttrans(char*str) { intnum,i; num=i=0; while(str[i]) num=10*num+str[i++]-48; returnnum; } intInsertConst(char*strToken) //用strToken中的单词去查常数表。 查到了,则返回该单词在表中的位置值; //否则,将strToken中的单词插入常数表的尾部,并返回位置值 {inti=0; intnum; num=trans(strToken);//将常数串转换为数字 while(i {if(Cons[i]==num) returni; i++; } Cons[i]=num; n++; returni; } intmain(intargc,char*argv[]) { charline[]=while(x1=10)doy: =x1;; inti_line; charch;//当前字符 charstrToken[15];//当前单词 inti_str; structTokenTypeToken[50];//Token数组 ))))). )))))) intcode,value; inti; i=0; i_line=0; ch=line[i_line++];//读取当前字符到ch while(ch) { i_str=0; while(ch=='') ch=line[i_line++]; if(IsLetter(ch)) { while(IsLetter(ch)||IsDigit(ch))//拼关键字或标识符 ch中的字符拼接到strToken中//将{strToken[i_str++]=ch; ch=line[i_line++]; } //Retract()i_line--; strToken[i_str]='\0'; //查关键字表;code=Reserve(strToken); if(! code)//未查到,是一个标识符 { //value=InsertID(strToken);将strToken中的单词插入到符号表中 Token[i].code=1; Token[i].value=value; //输出TokenPrint(Token[i++]); } else { Token[i].code=code; Token[i].value=-1; //输出Print(Token[i++]);Token } } //elseif(IsDigit(ch))处理常数; { 拼常数//while(IsDigit(ch)) 中{strToken[i_str++]=ch;strTokench//将中的字符拼接到ch=line[i_line++]; } i_line--;//Retract() strToken[i_str]='\0'; value=InsertConst(strToken);strToken将//中的单词插入到常数表中Token[i].code=2; Token[i].value=value; Print(Token[i++]);Token输出// } ))))). )))))) else//处理界符或错误处理; { strToken[i_str++]=ch;//将ch中的字符拼接到strToken中; if(ch==': ')//处理双界符? 尽; { ch=line[i_line++]; if(ch=='=') strToken[i_str++]=ch; else i_line--;//回溯一个字符 } strToken[i_str]='\0'; code=Reserve(strToken);//查界符表 //未查到if(! code) 错误处理//ProcError(); Token//生成并输出一个界符;else { Token[i].code=code; Token[i].value=-1; Print(Token[i++]);Token输出// } } ch=line[i_line++]; } printf(\ ); for(i=0;i printf(%s,ID[i]); printf(\ ); for(i=0;i printf(%d,Cons[i]); printf(\ ); } ))))). )))))) 实验二、Pascal常数处理机类的设计_源程序代码 #includemath.h #include intPas_aut[8][5]={2,0,0,0,0, 2,3,5,0,8, 4,0,0,0,0, 4,0,5,0,8, 7,0,0,6,0, 7,0,0,0,0, 7,0,0,0,8, 0,0,0,0,0};//状态转换矩阵 charline[30];//常数字符串 inti_line=0;//指针 classPascalCons { private: intaut[8][5];//状态转换矩阵 ints;//当前状态 intn,p,m,e,t;//尾数值,指数值,小数位数,指数符号,类型 doublenum;//常数 charch;//当前符号 public: PascalCons(); doublenumber(int*i);// private: voidProcError(); intmap(charch);//当前符号到自动机矩阵的列标记的映射 intfind(ints,charch);//查矩阵 voidact(ints,charch);//结点处的语义动作 }; PascalCons: : PascalCons() { inti,j; for(i=0;i<8;i++)//自动机转换矩阵初始化 for(j=0;j<5;j++) aut[i][j]=Pas_aut[i][j]; ch=''; }; voidPascalCons: : ProcError() { cout< < }; ))))). )))))) intPascalCons: : map(charch) {intj; if(ch>='0'&&ch<='9') j=0; elseif(ch=='.') j=1; elseif(ch=='E'||ch=='e') j=2; elseif(ch=='+'||ch=='-') j=3; else j=4; returnj; } intPascalCons: : find(ints,charch)//s---当前状态;ch---当前符号 {inti,j;//行和列 i=s-1;//将s映射到行标记i j=map(ch);//将ch映射到列标记j returnaut[i][j];//返回下一个状态值 } voidPascalCons: : act(ints,charch) { switch(s) { case1: n=0;m=0;p=0;t=0;e=1;num=0;break; case2: n=10*n+ch-48;break; case3: t=1;break; case4: n=10*n+ch-48;m++;break; case5: t=1;break; case6: if(ch=='-')e=-1;break; case7: p=10*p+ch-48;break; case8: num=n*pow(10,e*p-m); } } doublePascalCons: : number(int*p) { s=1; act(s,ch);//执行q1 while(s! =8) { ch=line[*p];//读取当前符号到ch中 (*p)++; s=find(s,ch);//查状态表 if(s==0) break; act(s,ch);//执行qs ))))). )))))) } if(s==8) returnnum;//输出num else { ProcError(); return0;//错误处理 } }; intmain(intargc,char*argv[]) { PascalConsa; cout< ; cin>>line;//读入常数字符串 cout< return0; } ))))). )))))) 实验三、表达式语法分析设计 (1) 一、实验目的: 熟悉递归下降语法分析器设计 二、实验内容: 1.设计递归下降语法分析器算法; 2.编写代码并上机调试运行通过。 ·要求: 输入——表达式; 输出——表达式语法是否正确。 三、概要设计 设计算术表达式的递归下降子程序语法分析器设计: 1. (1)算术表达式文法 G(E): E? EωT|T0 T? TωF|F 1 F? i|(E) (2)文法变换: G'(E)E? T{ωT}0 T? F{ωF} 1 F? i|(E) (3)递归下降子程序框图: T: E: 入口入口 TF n? n? 0yy 出出 read(w)read(w) TF F: 主程序: Z? E入 开始 (? ni? nerr read(w) read(w) E E errn#? errn)? y y read(w) 结束出口 ))))). )))))) 四、源程序清单: #includeiostream #includestring.h usingnamespacestd; charexp[50];//算术表达式区 inti=0; interr=0; charw; intprinterr() { cout< err=1; }; voidE(); voidF() { if(w=='(') { w=exp[i++];//read(w) E(); if(w! =')') if(! err){ printerr(); } else //read(w)w=exp[i++]; } elseif((w>='a'&&w<='p')||(w>='0'&&w<='9')) { //read(w)w=exp[i++]; } else {if(! err) printerr();} }; voidT() { F(); while(w=='*'||w=='/') { ))))). )))))) w=exp[i++];//read(w) F(); } };//当前单词 voidE() { T(); while(w=='+'||w=='-') { w=exp[i++];//read(w) T(); } }; intmain(intargc,char*argv[]) { cout< < cin>>exp;//输入表达式 w=exp[i++];//read(w) E(); if(! err) {if(w=='#') cout< < else cout< return0; }运行结果 ))))). )))))) 实验四、表达式语法分析设计 (2) 一、实验目的: 熟悉LR语法分析器设计 二、实验内容: 1.设计SLR (1)语法分析器算法; 2.编写代码并上机调试运行通过。 ·要求: 输入——表达式; 输出——表达式语法是否正确。 三、语法分析器设计 1.算术表达式文法 G(E): E'? E[0] E? E+T[1] E? T[2] ))))). )))))) [3] ? T*FT[4]T? F [5](E)F? [6]F? i 分析表: SLR (1)1. 状ACTIONGOTO 态i+*()#ETF 0s500s400123 1s6A0 2r2s7r2r2 3r4r4r4r4 4s5s4823 5r6r6r6r6 6s5s493 7s5s410 8s6s11 9r1s7r1r1 10r3r3r3r3 11r5r5r5r5 四、程序实现 ·数据结构: charsyn[15];//语法栈 intsta[15];//状态栈 inttop;//栈顶指针 charw;//当前单词 charexp[15];//表达式区 inti_exp=0;//表达式指针 structActType//Action表项类型 { charact;//sorr intrule_num;//iorj }; intGoto[12][3];//Goto分析表 ActTypeAction[12][6];//Action分析表 inti,j;//表行和列 ActTypecode_act;//Action表项 intcode_goto;//Goto表项 struct ))))). )))))) { charVn; intlen; len,右部长度//产生式左部Vn}rules[N]; ·算法设计: 开始 PUSH(SYN,#) PUSH(STA,0) read(w)——读单词 ——移进PUSH(SYN,w)ACTION(STA(top),w) REDUCE归约——yerr? 空n PUSH(STA,i) yacc? n 结 /ii ·算法求精: 查Action表(STA(top),w): i=sta[top];//定位行和列 j=map(w); code_act.act=Action[i][j].act;//查表 code_act.rule_num=Action[i][j].rule_num; PUSH(SYN,w): syn[++top]=w; PUSH(STA,i): sta[top]=code_act.rule_num; REDUCE: A? β for(j=0;j top--; //查Goto表(STA[top],A) i=sta[top];// ))))). )))))) j=map(rules[code_act.rule_num].Vn); code_goto=Goto[i][j]; syn[++top]=rules[code_act.rule_num].Vn;//PUSH(SYN,A) sta[top]=code_goto;//PUSH(STA,Goto(STA[top],A)) 五、源程序清单 #includestring.h #defineN7 structActType//表项 { //sorrcharact; //iorjintrule_num; }; charitem_act[12][6]={'s','','','s','','', '','s','','','','A', '','r','s','','r','r', '','r','r','','r','r', 's','','','s','','', '','r','r','','r','r', 's','','','s','','', 's','','','s','','', '','s','','','s','', '','r','s','','r','r', '','r','r','','r','r', '','r','r','','r','r'}; intitem_num[12][6]={5,0,0,4,0,0,0,6,0,0,0,0, 0,2,7,0,2,2,0,4,4,0,4,4, 5,0,0,4,0,0,0,6,6,0,6,6, 5,0,0,4,0,0,5,0,0,4,0,0, 0,6,0,0,11,0,0,1,7,0,1,1, 0,3,3,0,3,3,0,5,5,0,5,5}; 确定表列//intmap(charch) { charAction[7]={'i','+','*','(',')','#'}; charGoto[4]={'E','T','F'}; char*p; p=strchr(Action,ch); if(p==NULL) { p=strchr(Goto,ch); if(
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 编译 原理 上机 指导