您的当前位置:首页正文

南昌大学编译原理实验报告

2022-09-27 来源:好走旅游网


编译原理期末实验报告

目录

词法分析程序设计 ............................................................................... - 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 -

编译原理期末实验报告

正确结果:

<0 , data> <+ , -> <1 , 92> <> , -> <3 , 3f> <0 , data> <= , > <0 , data> <+ , -> <2 , 1> <; ,-> <0 , data> <= , -> <0 , data> <- , -> <2 , -> <; , ->

【实验代码】

#include #include #include using namespace std; FILE *fp; char ch; char

*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<\"<\"<\"<\"<\"<else if(letter[0]=='x'||letter[0]=='X') { int k=1; for(int j=1;j<=i;j++) if(!(letter[j]>='0'&&letter[j]<='8')) { k=0;break;} if(k==1) cout<1,\"<\"<0,\"<\"<\"<a:return(ch); }

/***********************************************************************************/ 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<3,\"<\"<0,\"<\"<='7') { k=0;break;} if(k==1) cout<\"<\"<cout<\"</************************************************************************************/ char otherprocess(char ch) //运算符和界符处理程序 { char aaa='@'; int i=-1; if (isspace(ch)!=0) { ch=fgetc(fp); goto u;

- 5 -

编译原理期末实验报告

}

if((isspace(ch)==0)&&(isalnum(ch)==0)) { switch(ch) { cout<\"<\"<\"<\"<\"<\"<\"<\"<case'>':{ch=fgetc(fp); if(ch=='=') cout<=\"<<\">\"<\"<<\">\"<case'!':{ch=fgetc(fp); if(ch=='=') cout<\"<\"<\"<\"<\"<\"<\"<\"<- 6 -

编译原理期末实验报告

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 using namespace std; FILE * fTestIn;

#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||nToken=Stack[ipStack-n-1];

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=0;j--) { if(OG[i][n-j]!=Peek(j).ch) { k = true; break;

}

}

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<

误!\"<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 #include #include #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 dou;//存放表达式中的数字 stack sta;//存放运算符

string str,str1[100],str2;//str1[100]存放后缀表达式 cout<<\"请输入要计算的表达式:\"; cin>>str;//原表达式

cout<<\"原来的表达式是:\"<string::iterator iter=str.begin();

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<if(str1[i]==\"+\"||str1[i]==\"-\"||str1[i]==\"*\"||str1[i]==\"/\")//一旦遇到运算符则将double栈中的前两个数计算 {

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<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

因篇幅问题不能全部显示,请点此查看更多更全内容