(编译原理)TINY扩充语言的语法分析

一、实验内容

扩充的语法规则有:实现while、do while、for语句和求余计算式子,具体文法规则自行构造。 

可参考:P97及P136的文法规则。 

(1)While-stmt --> while  exp  do  stmt-sequence  endwhile

(2)Dowhile-stmt-->do  stmt-sequence  while  exp 

(3)for-stmt-->for identifier:=simple-exp  to  simple-exp  do  stmt-sequence enddo    步长递增1

 (4)for-stmt-->for identifier:=simple-exp  downto  simple-exp  do  stmt-sequence enddo    步长递减1 

要求: 

(1)要提供一个源程序编辑界面,以让用户输入源程序(可保存、打开源程序)  

(2)可由用户选择是否生成语法树,并可查看所生成的语法树。  

(3)应该书写完善的软件文档

 

二、实验设备

操作系统:Windows7          

软件:VC6.0

三、   实验分析

1.由于用MFC的Windows的时候在读入文件的时候出现错误,估最后决定采用dos界面,错误界面如下:

2.扩展文法while,do while,for语句和求余计算式子

三、   实验步骤

1.     用vc6.0将《编译原理及实践》书中附录B的代码文件建立工程,并将以下文件添加进工程目录:main.c,globals.h,parse.c,parse.h,scan.c,scan.h,util.c,util.h。

2.     在globals.h文件中

a.     修改最大保留字数量#define MAXRESERVED 15。

b.    在typedef enum{} TokenType结构中增加保留字WHILE,DO,TO,DOWNTO,FOR,ENDDO,ENDWHILE,MOD。

c.     在typedef enum {} StmtKind结构中增加语句类型WhileK,DoWhileK,ForK。

3.     在scan.c文件中

a.     在static struct {} reservedWords[MAXRESERVED]中增加保留字关联字符

{"while",WHILE}{"endwhile",ENDWHILE},{"do",DO},{"to",TO},{"downto",DOWNTO},{"for",FOR},{"enddo",ENDDO}。

b.    在TokenType getToken(void)函数中switch (c)模块下增加状态

case '%':currentToken=MOD; break;

4.     在util.h文件中

a.     在void printToken( TokenType token, const char* tokenString )函数中switch (token)模块下增加状态:

case WRITE:

//增加

case WHILE:

case DO:

case TO:

case DOWNTO:

case FOR:

case ENDDO:

case ENDWHILE:

//结束

fprintf(listing,  "reserved word: %s\n",tokenString);break;

case TIMES: fprintf(listing,"*\n");break;

//增加

case MOD:fprintf(listing,"%%\n"); break;

//结束

case OVER:fprintf(listing,"/\n"); break;

b.    在void printTree( TreeNode * tree )函数中switch(tree->kind.stmt)模块下增加状态:

caseWriteK:fprintf(listing,"Write\n");break;

//增加

case WhileK:fprintf(listing,"While\n");break;

caseDoWhileK:fprintf(listing,"Do\n");break;

caseForK:fprintf(listing,"For\n");break;

//结束

default:fprintf(listing,"UnknownExpNode kind\n");break;

5.     在parse.c文件中

a.     增加静态成员函数定义static TreeNode * while_stmt(void),static TreeNode* dowhile_stmt(void),static TreeNode * for_stmt(void)。

b.    分别实现static TreeNode * while_stmt(void),staticTreeNode * dowhile_stmt(void),static TreeNode *for_stmt(void)函数,代码如下:

TreeNode* while_stmt(void)  //扩充的while 语句文法

{

TreeNode * t=newStmtNode(WhileK);  

match(WHILE);  

if(t!=NULL)

t->child[0]=exp();  

match(DO);   

if(t!=NULL)

t->child[1]=stmt_sequence();  

match(ENDWHILE);  

return t;

TreeNode* dowhile_stmt(void) //扩充的dowhile语句文法

{

TreeNode *t=newStmtNode(DoWhileK);

   match(DO);  

   if(t!=NULL)

t->child[0]=stmt_sequence();  

   match(WHILE);   

   if(t!=NULL)

t->child[1]=exp();  

   return t;

TreeNode* for_stmt(void)  //扩充的for语句文法

{

TreeNode *t=newStmtNode(ForK);  

match(FOR);

if ((t!=NULL) &&(token==ID))     

t->attr.name =copyString(tokenString);  

match(ID);  

match(ASSIGN);   

if(t!=NULL)

t->child[0]=simple_exp();  

if(token==TO)   //步长递增1    

match(TO);   

if(token==DOWNTO)  //步长递减1    

match(DOWNTO);   

if(t!=NULL)    

t->child[1]=simple_exp();   

match(DO);  

if(t!=NULL)   

t->child[2]=stmt_sequence();   

match(ENDDO);  

return t;

}

c.    TreeNode *stmt_sequence(void)函数中增加stmt_sequence文法的follow集while((token!=ENDFILE)&&(token!=END)&&(token!=ELSE)&&(token!=UNTIL)&&(token!=ENDWHILE)&&(token!=WHILE)&&(token!=ENDDO))

d.    在TreeNode * statement(void)函数中switch (token)模块下增加状态:

case WHILE:t= while_stmt();break;           

case DO:t=dowhile_stmt();break;

case FOR:t=for_stmt();break;

e.     在TreeNode * term(void)增加代码while((token==TIMES)||(token==OVER)||(token==MOD))

6.     在main.c文件中,修改main函数,部分代码如下:

TreeNode* syntaxTree;

charpgm[120],ch[120];

intn,flag=1;//状态标志

while(flag){

switch(flag){

case 1:

printf("-------TINY扩充语言的语法分析-------\n");

printf("--打开文件:\n");

printf("1.SAMPLE.TNY\n");

printf("2.while_test.tny\n");

printf("3.dowhile_test.tny\n");

printf("4.for_test.tny\n");

printf("5.结束程序 \n");

printf("\n");printf("\n");

printf("请选择(1-5):");

scanf("%d",&n);

while(n<1||n>5){

printf("-----输入有误,请重新输入:\n");

scanf("%d",&n);

}

switch(n){

case 1://打开文件SAMPLE.TNY

source=fopen("SAMPLE.TNY","r");

strcpy(pgm,"SAMPLE.TNY");break;

case 2://打开文件while_test.tny

source=fopen("while_test.tny","r");

strcpy(pgm,"while_test.tny");break;

case 3://打开文件dowhile_test.tny

source=fopen("dowhile_test.tny","r");

strcpy(pgm,"dowhile_test.tny");break;

case 4://打开文件for_test.tny

source=fopen("for_test.tny","r");

strcpy(pgm,"for_test.tny");break;

case 5://结束程序

default:

fclose(source);//关闭文件

exit(0);

}

if (source==NULL){

fprintf(stderr,"File %snot found\n",pgm);exit(1);

}

case 2:

printf("*******输入源程序成功!*******\n");

printf("*******1.查看源程序\n");

printf("*******2.查看生成语法树\n");

printf("*******3.返回上一级\n");

printf("请选择(1-3):");

scanf("%d",&n);

while(n<1||n>3){

printf("*****输入有误,请重新输入:\n");

scanf("%d",&n);

}

if(n==3) {flag=1; fclose(source);break;}

else{

flag=2;

switch(n){

case 1://打开源程序

while(!feof(source)){

if(fgets(ch,120,source)!=0)printf("%s",ch);

}

fseek(source,0L,0);break;//读取结束,将文件指针指向头位置

case 2://查看生成树

listing = stdout;

fprintf(listing,"\nTINYCOMPILATION: %s\n",pgm);

syntaxTree = parse();

if (TraceParse) {

fprintf(listing,"\nSyntaxtree:\n");

printTree(syntaxTree);

}

fseek(source,0L,0);break;//查看结束,将文件指针指向头位置

}

}

case 3:

printf("\n");

printf("*****1.返回上一级\n");

printf("*****2.结束程序\n");

printf("请选择(1-2):");

scanf("%d",&n);

while(n<1||n>2){

printf("*****输入有误,请重新输入:\n");

scanf("%d",&n);

}

if(n==1)flag=2;

else if(n==2)flag=0;

}

}

fclose(source);

三、   实验结果

主界面包括选择打开四个文件和结束程序,其中四个文件分别是SAMPLE.TNY,while_test.tny,dowhile_test.tny,for_test.tny下面分别打开测试文件和其生成的语法树:

a.     测试文件SAMPLE.TNY

{Sample program

  in TINY language -

  computes factorial

}

readx; { input an integer }

if0 < x then { don't compute if x <= 0 }

  fact := 1;

  repeat

    fact := fact * x;

    x := x % 1;

  until x = 0;

  write fact { output factorial of x }

end

生成的语法树:


a.   测试文件while_test.tny:

readx; { input an integer }

while0 < x do 

  fact := 1; 

  repeat     

    fact := fact * x;   

    x := x % 2 

  until x = 0;  

  write fact

endwhile

生成的语法树:


a.   测试文件dowhile_test.tny

readx; { input an integer }

do   

  fact := 1; 

  repeat    

    fact := fact * x;   

    x := x % 2  

  until x = 0;  

  write fact

while x=0

生成的语法树:


a.   测试文件for_test.tny

readx; { input an integer }

forx:=1 to y+5 do

  fact := 1;

  repeat

    fact := fact * x;

    x := x % 2

  until x = 0;

  write fact { output factorial of x }

enddo

生成的语法树



  • 8
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值