编译原理期末实验报告
目录
词法分析程序设计 ............................................................................... - 2 - 词法分析程序设计 ............................................................................... - 8 - 逆波兰式的翻译和计算 .......................................................................... 16
- 1 -
编译原理期末实验报告
南昌大学实验报告一
姓名: 马海亮 学 号: 6100409101 专业班级: 计算机科学与技术091班 实验类型:□验证 □ 综合■设计 □创新 实验日期:2012.4 实验成绩:
词法分析程序设计
一、实验目的
掌握计算机语言的词法分析程序的开发方法。
二、实验内容
编制一个能够分析三种整数、标识符、主要运算符和主要关键字的词法分析程序。
三、实验要求
1、根据状态图,设计词法分析函数int scan( ),完成以下功能:
1) 从文本文件中读入测试源代码,根据状态转换图,分析出一个单词, 2) 以二元式形式输出单词<单词种类,单词属性>
其中单词种类用整数表示: 0:标识符 1:十进制整数 2:八进制整数 3:十六进制整数
运算符和界符,关键字采用一字一符,不编码 其中单词属性表示如下:
标识符,整数由于采用一类一符,属性用单词表示 运算符和界符,关键字采用一字一符,属性为空
2、编写测试程序,反复调用函数scan( ),输出单词种别和属性。
四、实验环境
PC微机
DOS操作系统或 Windows 操作系统
Turbo C 程序集成环境或 Visual C++ 程序集成环境
五、实验步骤
编辑一个文本文件program.txt,在文件中输入如下内容:
if data+92>0x3f then data=data+01; else data=data-01; - 2 -
编译原理期末实验报告
正确结果:
【实验代码】 #include *keyword[11]={\"if\ bool search(char searchstr[])//查找是否是系统关键字或运算符或界符 { int i; for(i=0;i<=5;i++) { if(strcmp(keyword[i],searchstr)==0) return true; } return false; } /*******************************************************************/ char letterprocess (char ch) //字母处理程序 { int i=-1; char letter[30]; - 3 - 编译原理期末实验报告 while (isalnum(ch)!=0) { letter[++i]=ch; ch=fgetc(fp); } letter[i+1]='\\0'; if (search(letter)) { cout< /***********************************************************************************/ char numberprocess(char ch) //数字处理程序 { int i=-1; char num[20]; while (isdigit(ch)!=0) - 4 - 编译原理期末实验报告 { num[++i]=ch; ch=fgetc(fp); } if(isalpha(ch)!=0) { while(isspace(ch)==0) { num[++i]=ch; ch=fgetc(fp); } num[i+1]='\\0'; if(num[0]=='0') { if(num[1]=='x'||num[1]=='X') { int k=1; for(int j=2;j<=i;j++) { if((num[j]<='0'&&num[j]>='9')||(num[j]<='A'&&num[j]>='F')||(num[j]<='a'&&num[j]>='f')) { k=0;break;} } if(k==1) cout< - 5 - 编译原理期末实验报告 } if((isspace(ch)==0)&&(isalnum(ch)==0)) { switch(ch) { cout< 编译原理期末实验报告 else ch=fgetc(fp); goto u; } u: return (ch); } /***********************************************************************************/ int main() { char str; cout<<\"*******************************************************\\n\"; cout<<\"* 词法分析器 *\\n\"; cout<<\"*******************************************************\\n\"; if ((fp=fopen(\"test.txt\ cout<<\"源程序无法打开!\\n\"; else { cout<<\"词法分析如下:\"< - 7 - 编译原理期末实验报告 南昌大学实验报告二 姓名: 马海亮 学 号: 6100409101 专业班级: 计算机科学与技术091班 实验类型:□验证 □ 综合■设计 □创新 实验日期:2012.5 实验成绩: 目录 词法分析程序设计 ............................................................................... - 2 - 词法分析程序设计 ............................................................................... - 8 - 词法分析程序设计 一、实验目的 通过设计、编制、调试一个典型的语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析,进一步掌握常用的语法分析中算法优先分析方法。 二、实验内容 编制一个能够分析三种整数、标识符、主要运算符和主要关键字的词法分析程序。 三、实验要求 1、给出文法如下: G[E] E->T|E+T; T->F|T*F; F->i(E); 可以构造算符优先表如下: + * ( ) + * ( ) i - 8 - 编译原理期末实验报告 i 2、计算机中表示上述优先关系,优先关系的机内存放方式有两种1)直接存放,2)为优先关系建立优先函数,这里由学生自己选择一种方式; 1、 给出算符优先分析算法如下: k:=1; S[k]:=‘#’; REPEAT 把下一个输入符号读进a中; IF S[k]∈VT THEN j:=k ELSE j:=k-1; WHILE S[j] a DO BEGIN REPEAT Q:=S[j]; IF S[j-1]∈VT THEN j:=j-1 ELSE j:=j-2 UNTIL S[j] Q 把S[j+1]…S[k]归约为某个N; k:=j+1; S[k]:=N; END OF WHILE; IF S[j] a OR S[j] a THEN BEGIN k:=k+1;S[k]:=a END ELSE ERROR UNTIL a=‘#’ 1、 根据给出算法,利用适当的数据结构实现算符优先分析程序; 2、 利用算符优先分析程序完成下列功能: 1) 手工将测试的表达式写入文本文件,每个表达式写一行,用“;”表示结束; 2) 读入文本文件中的表达式; 3) 调用实验2中的词法分析程序搜索单词; 4) 把单词送入算法优先分析程序,判断表达式是否正确(是否是给出文法的语 言),若错误,应给出错误信息; 5) 完成上述功能,有余力的同学可以对正确的表达式计算出结果。 四、实验环境 PC微机 DOS操作系统或 Windows 操作系统 Turbo C 程序集成环境或 Visual C++ 程序集成环境 五、实验步骤 1、分析文法中终结符号的优先关系; 2、存放优先关系或构造优先函数; - 9 - 编译原理期末实验报告 1、 利用算符优先分析的算法编写分析程序; 4、写测试程序,包括表达式的读入和结果的输出; 1、 程序运行效果,测试数据可以参考下列给出的数据。 六、测试数据 输入数据: 编辑一个文本文文件expression.txt,在文件中输入如下内容: 10; 1+2; (1+2)*3+(5+6*7); ((1+2)*3+4; 1+2+3+(*4+5); (a+b)*(c+d); ((ab3+de4)**5)+1; 正确结果: (1)10; 输出:正确 (2)1+2; 输出:正确 (3)(1+2)*3+(5+6*7); 输出:正确 (4)((1+2)*3+4 【试验代码】 #include #define O_NUMBER 6 #define O_PLUS 0 #define O_TIMES 1 #define O_L_PAREN 2 #define O_R_PAREN 3 #define O_IDENT 4 #define O_NUL 5 char Buffer[1000]; int ipBuffer=0; char O_Table[O_NUMBER][O_NUMBER] = { {'>','<','<','>','<','>'}, {'>','>','<','>','<','>'}, 输出:错误 (5)1+2+3+(*4+5) 输出:错误 (6)(a+b)*(c+d) 输出:正确 (7)((ab3+de4)**5)+1 输出:错误 {'<','<','<','=','<','-'}, {'>','>','-','>','-','>'}, {'>','>','-','>','-','>'}, {'<','<','<','-','<','='} }; #define OG_NUMBER 4 char OG[OG_NUMBER][4]={\"E+E\ typedef struct { char ch; int No; } SToken; SToken Token[100]; int TokenNumber=0; - 10 - 编译原理期末实验报告 int ipToken=0; SToken Stack[1000]; int ipStack=0; char ch; void Push(SToken Token) { Stack[ipStack++] = Token; } bool PopUp(int n) { if(ipStack<2) return false; if(n>ipStack-1) n=ipStack-1; ipStack-=n; return true; } void PushToken(char ch, int O_No) { SToken Token; Token.ch=ch; Token.No=O_No; Push(Token); } char GetChar() { if((ch=Buffer[ipBuffer])!='\\0') ipBuffer ++; return ch; } char GetFirstChar() { while(GetChar()!='\\0') { return ch; } return '\\0'; } SToken Peek(int n) { SToken Token; if(n>0||n else if(n<0) Token=Stack[ipStack-1]; else Token=Stack[0]; return Token; } int FindPriorOp(int Begin) { int n; n=Begin+1; while(Peek(n).ch=='E') { n ++; } return n; } bool IsOK() { if(Peek(0).ch=='E'&&Peek(1).ch=='#'&&Token[ipToken].ch=='#') return true; else return false; } int MoveIn() { SToken s,t; char r; s=Peek(FindPriorOp(-1)); t=Token[ipToken]; r=O_Table[s.No][t.No]; if(t.ch=='#') return 1; else { if(r=='<'|| r=='=') 11 编译原理期末实验报告 { Push(t); ipToken ++; return 2; } else if(r=='>') return 1; else { return -1; } } } bool GuiYueN(int n) { int i,j; bool k; for(i=0;i } } if(k) continue; if(OG[i][n+1]=='\\0') { PopUp(n+1); PushToken('E',O_IDENT); return true; } } return false; } int GuiYue() { int n0,n; char r; n = FindPriorOp(-1); if(Peek(n).ch =='#') { if(IsOK()) return 2; else return -1; } while(true) { n0 = n; n = FindPriorOp(n0); if(n-n0>2) return-1; r O_Table[Peek(n).No][Peek(n0).No]; if(r=='<') { if(!GuiYueN(n-1)) return -1; else { if(IsOK()) return 2; else return 1; } } else if(r=='=') { continue; } else return -1; } } bool Judge() { ipToken=0;ipStack=0; = 12 编译原理期末实验报告 PushToken('#',O_NUL); while(true) { switch(MoveIn()) { case 1: switch(GuiYue()) { case 1: } bool ChangeToTokens() { ipBuffer=0; if(n>0) return true; else return false; break; case 2: return true; default: return false; } break; case 2: break; default: return false; } } } bool ReadFormula() { int n=0; bool k=false; while(true) { if((Buffer[n]=fgetc(fTestIn))!=EOF) { if(Buffer[n]==';') break; n++; } else { k=true; break; } } Buffer[n]='\\0'; TokenNumber = 0; if(GetFirstChar()=='\\0') {} while(true) { if(ch<=32&& ch>0) GetFirstChar(); switch(ch) { case '\\0': Token[TokenNumber].ch='#'; Token[TokenNumber].No=O_NUL; return true; case '+': Token[TokenNumber].ch='+'; Token[TokenNumber].No=O_PLUS; GetChar(); break; case '*': Token[TokenNumber].ch='*'; Token[TokenNumber].No=O_TIMES; GetChar(); break; case '(': Token[TokenNumber].ch='('; Token[TokenNumber].No=O_L_PAREN; GetChar(); break; case ')': Token[TokenNumber].ch=')'; Token[TokenNumber].No=O_R_PAREN; GetChar(); break; 13 编译原理期末实验报告 default: if(ch>='0'&&ch<='9') { while(GetChar()>0) { if(ch <'0'||ch>'9') if(ChangeToTokens()) { if(Judge()) cout< Token[TokenNumber].ch='i'; Token[TokenNumber].No=O_IDENT; } else if(ch>='a'&& ch<='z') { while(GetChar()>0) { if(ch<'a'||ch>'z') break; } Token[TokenNumber].ch='i'; Token[TokenNumber].No=O_IDENT; } else { cout<<\"表达式中含有非法字 符。\"; } break; } TokenNumber++; } } void main() { if((fTestIn = fopen(\"test.txt\\"r\"))= NULL) cout<<\"不能打开测试文件!\"; fTestIn = fopen(\"test.txt\ while(ReadFormula()) { cout< 误!\"< 错误\"< fclose(fTestIn); } 14 编译原理期末实验报告 【试验截图】 15 编译原理期末实验报告 南昌大学实验报告三 姓名: 马海亮 学 号: 6100409101 专业班级: 计算机科学与技术091班 实验类型:□验证 □ 综合■设计 □创新 实验日期:2012.5 实验成绩: 逆波兰式的翻译和计算 一、实验目的 通过实验加深对语法指导翻译原理的理解,掌握算符优先分析的方法,将语法分析所识别的表达式变换成中间代码的翻译方法。 二、实验内容 设计一个表示能把普通表达式(中缀式)翻译成后缀式,并计算出结果的程序。 三、实验要求 1、给出文法如下: G[E] E->T|E+T; T->F|T*F; F->i(E); 对应的转化为逆波兰式的语义动作如下: (1)(2)(1)(2) E-> Eop E {E.CODE:= E.CODE||E.CODE||op} (1)(1) E->(E) { E.CODE := E.CODE} E->id { E.CODE := id} 2、利用实验5中的算符优先分析算法,结合上面给出的语义动作实现逆波兰式的构造; 3、利用栈,计算生成的逆波兰式,步骤如下: 1) 中缀表达式,从文本文件读入,每一行存放一个表达式,为了降低难度,表达 式采用常数表达式; 2) 利用结合语法制导翻译的算符优先分析,构造逆波兰式; 3) 利用栈计算出后缀式的结果,并输出; 4) 四、实验环境 PC微机 DOS操作系统或 Windows 操作系统 Turbo C 程序集成环境或 Visual C++ 程序集成环境 五、实验步骤 【实验代码】 16 编译原理期末实验报告 #include using namespace std; double cast(string& sstr)//将string类型转型为double { double dou=0; for(string::iterator Iter=sstr.begin();Iter!=sstr.end();++Iter) { dou=dou*10+(*Iter)-'0'; } return dou; } int main(int argc, char *argv[]) { stack string str,str1[100],str2;//str1[100]存放后缀表达式 cout<<\"请输入要计算的表达式:\"; cin>>str;//原表达式 cout<<\"原来的表达式是:\"< while(iter!=str.end()&&(*iter)!='#')//扫描原表达式中的每一个字符 { if((*iter)>='0'&&(*iter)<='9')//如果是数字则存入str2中 { str2+=(*iter); } else//如果不是数字 { if(str2!=\"\")//如果str2不为空则将其存入后缀表达式 { str1[size]=str2; ++size; str2=\"\"; } if((*iter)!=')')//如果原表达式中字符不是右括号 { if((*iter)=='+'||(*iter)=='-') 17 编译原理期末实验报告 { while(!sta.empty()&&sta.top()!='(')//直到遇到栈里面的左括号前将栈顶元素存入后缀表达式中 { str1[size]=sta.top(); ++size; sta.pop(); } } if(!sta.empty()&&((*iter)=='*'||(*iter)=='/')&&(sta.top()=='*'||sta.top()=='/'))//如果当前字符是*或者/且前一个运算符也是*或者/则将前一个运算符存入后缀表达式 { str1[size]=sta.top(); ++size; sta.pop(); } sta.push((*iter));//将当前字符压栈 } else//如果是右括号 { while(sta.top()!='(')//直到遇到栈里面的左括号前将栈顶元素存入后缀表达式中 { str1[size]=sta.top(); ++size; sta.pop(); } sta.pop();//将左括号出栈 } } ++iter; } if(str2!=\"\")//将原表达式最后的数字存入后缀表达式 { str1[size]=str2; ++size; } while(!sta.empty())//将栈中的运算符全部存入后缀表达式 { str1[size]=sta.top(); ++size; sta.pop(); } cout<<\"后缀表达式是:\"; 18 编译原理期末实验报告 for(int i=0;i!=size;++i) { cout< double dou1=dou.top(); dou.pop(); double dou2=dou.top(); dou.pop(); if(str1[i]==\"+\") dou.push(dou2+dou1); if(str1[i]==\"-\") dou.push(dou2-dou1); if(str1[i]==\"*\") dou.push(dou2*dou1); if(str1[i]==\"/\") dou.push(dou2/dou1); } else//如果是数字则将其存入double栈中 dou.push(cast(str1[i])); } cout< 输入数据: 1+2; (1+2)*3; (10+20)*30+(50+60*70); 正确结果: (1)1+2; 输出:1,2,+ 3 (2)(1+2)*3; 输出:1,2,+,3,* 9 (3)(10+20)*30+(50+60*70) 输出:10,20,+30,*50,60,70,*,+,+ 5150 【试验截图】 19 编译原理期末实验报告 20 因篇幅问题不能全部显示,请点此查看更多更全内容