⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 grammer.y

📁 这是我自己实现的一个微小的编译程序,附可执行代码的虚拟机,是理解编译原理的绝好材料.
💻 Y
📖 第 1 页 / 共 2 页
字号:
/*author 谭添升
	南京大学计算机科学与技术系
	lilotom@gmail.com(有bug请联系)
	2006年5月20日
	edit by UltraEdit
*/

/*
	2006年5月28日,加入浮点处理部分,
	以及生成浮点指令的emitFCode函数
*/

/*
	2006年5月29日.加入movf,readf,writef等处理浮点常数,或者变量的指令.
	能够处理浮点数直接对整数值赋值
*/
/*
	2006年5月29日晚,修正write语句不能正确回填的bug.测试源文件见code/float.txt,bug原因在于
	赋值语句的nextlist没有正确设置.
	
	修正生成类型转换指令的bug,原先是直接在原变量空间上转换,但变量如果被多次使用的话,则被转换多次,显然会出现错误.
	后想出解决方法是,转换后把相应存储空间的类型给修改了,但新问题是,如果把原定义段定义的变量类型改掉,如后有writef指令,
	会出现问题,因为它输出了转换后的类型,而编程者的原意并不是这种类型,
	最终解决办法是,所有涉及到类型转换都先mov到一个临时变量,转换后再使用,
	这个临时变量的作用域是以当前以下两条指令,所以只要保证当前分配给它的空间没被别人使用即可,
	所以使用了temp=mem_off,mem_off当前值能保证其对应空间没有被其它变量使用,而这之后,temp不再有效,
	当然可以被其它变量使用,所以不用有mem_off++的操作,这样可以节省对内存的使用.
*/

%union{
	double dval;
	int ival;
	int sym_off;					/*符号表中的offset*/
	int relop;
	int idname;					/*变量名指针*/
}							/*not need semicon*/

%{
#include<stdio.h>
#include "global.h"
int defid=-1;
extern char yytext[];
extern int yylineno;

void yyerror();
void type_error();
int lookup(int nameoff);
void addType(int sym_off,int type);
void emitFCode( enum code_ops operation, double src1 ,int src2 , int dest );
void emitFCode( enum code_ops operation, double src1 ,int src2 , int dest );
void backpatch( struct Jmplist * list, int jmp_dest);
void enterID(int offset,int nameoff,int type);		/*原由于此处原少了分号,产生非常多的warning*/
struct Jmplist * makelist(int i);


int offset = 0  , name_off = 0 , mem_off = 0 , sym_off = 0 , code_off = 0;
int operator = 0;
Code code[NUM_INS];				/*存储生成的指令*/
char str[20];
struct Symtable symtab[SYMTAB_LEN];
char name[NAME_LEN];


%}


%token NOT
%token INT REAL	BOOL
%token READ WRITE
%token ASSIGN IF THEN ELSE FI BEGINS END AND OR XOR VAR WHILE DO identifier
%token RelOP
%token RA RAE RB RBE RE					/*R represents relationship即关系运算*/
%token realConst integerConst
%start P
						/*文法开始符号*/
%%
P	:M Dec  Body					{int i;printf("sym_off(符号个数)=%d\ncode_off(代码行数)=%d\n",sym_off,code_off);YYACCEPT;}
	;
M	:						{offset = 0;};		/*此处加入空规则,其实YACC可以自动插入*/
Dec	:VarDec	';' Dec					{}/*此处有移入归约冲突*/
	|VarDec						{}
	;
VarDec	:VAR identifier ':' Type			{int p = lookup($2.idname);
							 if(p!=-1){printf("error: line %d variable %s redefinition",yylineno,name+$2.idname);exit(1);}
							 
							 //$2.sym_off=p;
							 
							 enterID(sym_off,$2.idname,symtab[$4.sym_off].type);
							 $2.sym_off=sym_off++;
							 addType($2.sym_off,symtab[$4.sym_off].type);/*变量合法,add type and alloc memery space*/}
	;
Type	:REAL						{$$.sym_off=sym_off++;symtab[$$.sym_off].type=REAL;}
	|INT						{$$.sym_off=sym_off++;symtab[$$.sym_off].type=INT;}
	;
Body	:CompSt	M1					{backpatch(symtab[$1.sym_off].nextlist,symtab[$2.sym_off].place);}
	;
CompSt	:BEGINS StatementList END			{$$.sym_off=sym_off++;
							 symtab[$$.sym_off].nextlist=symtab[$2.sym_off].nextlist;
							 }
	;
StatementList	:Statement ';' M1 StatementList		{backpatch(symtab[$1.sym_off].nextlist,symtab[$3.sym_off].place);
							 $$.sym_off=$4.sym_off;						}
	|Statement					{$$.sym_off=$1.sym_off;}
	;
Statement	:CompSt					{$$.sym_off=$1.sym_off;}
	|IfSt						{$$.sym_off=$1.sym_off;}
	|WhileSt					{$$.sym_off=$1.sym_off;}
	|AssignSt					{$$.sym_off=$1.sym_off;}
	|ReadSt						{$$.sym_off=$1.sym_off;}
	|WriteSt					{$$.sym_off=$1.sym_off;}
	;
IfSt	:IF BE M1 THEN Statement ELSE M1 Statement FI	{if(symtab[$2.sym_off].type==BOOL/*&&symtab[$4.sym_off].type==symtab[$6.sym_off].type*/)
							 {/*不对语句设置类型*/
							  $$.sym_off = sym_off++;
							  backpatch(symtab[$2.sym_off].truelist,symtab[$3.sym_off].place);
							  backpatch(symtab[$2.sym_off].falselist,symtab[$7.sym_off].place);
							  symtab[$$.sym_off].nextlist = merge(symtab[$5.sym_off].nextlist,symtab[$8.sym_off].nextlist);
							  //symtab[$$.sym_off].nextlist = merge(symtab[$$.sym_off].nextlist,symtab[$6.sym_off].nextlist); //开始按照教材上写,在ELSE前有符号N,再加上这一句,不能正确回填,去掉后正常
							 }
							 else type_error();}
	|IF BE M1 THEN Statement FI			 {if(symtab[$2.sym_off].type==BOOL)
							  {
							 	$$.sym_off = sym_off++;
							 	backpatch(symtab[$2.sym_off].truelist,symtab[$3.sym_off].place);
							 	symtab[$$.sym_off].nextlist=merge(symtab[$2.sym_off].falselist,symtab[$5.sym_off].nextlist);
							  }
							  else type_error();}
	;
M1	:						{$$.sym_off=sym_off++;symtab[$$.sym_off].place=code_off;}/*此处用place属性代替pos,节省空间*/
	;
WhileSt	:WHILE M1 BE DO M1 Statement 			{
								backpatch(symtab[$6.sym_off].nextlist,symtab[$2.sym_off].place);
								backpatch(symtab[$3.sym_off].truelist,symtab[$5.sym_off].place);
								symtab[$$.sym_off].nextlist=symtab[$3.sym_off].falselist;
								//emitCode(op_jmp,-1,-1,symtab[$2.sym_off].place);
							}
	;
AssignSt:identifier ASSIGN E				{int temp=0;
							 int p=lookup($1.idname);
							 if(p==-1){printf("ERROR: line %d identifier %s undefined.",yylineno,name+$1.idname);exit(1);}
							 $1.sym_off=p;
							 $$.sym_off=sym_off++;
							 
							 if(symtab[$1.sym_off].type==symtab[$3.sym_off].type)
							 {
							 	symtab[$$.sym_off].nextlist = makelist(code_off+1);
							 	emitCode(op_mov,symtab[$3.sym_off].place,-1,symtab[$1.sym_off].place);
							 	emitCode(op_jmp,-1,-1,-1);
							 }
							 else if(symtab[$1.sym_off].type==REAL&&symtab[$3.sym_off].type==INT)/*需要类型转换*/
							 {
							 	//symtab[$3.sym_off].type=REAL;				//不能修改变量类型,原为bug
							 	symtab[$$.sym_off].nextlist = makelist(code_off+3);
							 	temp=mem_off;
							 	emitCode(op_mov,symtab[$3.sym_off].place,-1,temp);
							 	emitCode(op_inttoreal,temp,-1,temp);/*考虑到表达式的值只是临时变量,所以就在其上类型转换*/
							 	emitCode(op_mov,temp,-1,symtab[$1.sym_off].place);
							 	emitCode(op_jmp,-1,-1,-1);
							 }
							 else if(symtab[$1.sym_off].type==INT&&symtab[$3.sym_off].type==REAL)/*需要类型转换*/
							 {
							 	//symtab[$3.sym_off].type=INT;
							 	symtab[$$.sym_off].nextlist = makelist(code_off+3);	//此处设置不正确,导致bug
							 	temp=mem_off;
							 	emitCode(op_mov,symtab[$3.sym_off].place,-1,temp);
							 	emitCode(op_realtoint,temp,-1,temp);/*考虑到表达式的值只是临时变量,所以就在其上类型转换*/
							 	emitCode(op_mov,temp,-1,symtab[$1.sym_off].place);
							 	emitCode(op_jmp,-1,-1,-1);
							 }
							 else type_error();}
	;
ReadSt 	:READ identifier				{int p=lookup($2.idname);
							 if(p==-1){printf("ERROR: line %d identifier %s is undefined.",yylineno,name+$2.idname);exit(1);}
							 $2.sym_off=p;
							 $$.sym_off=sym_off++;
							 symtab[$$.sym_off].nextlist = makelist(code_off+1);
							 emitCode((symtab[$2.sym_off].type==INT)?op_read:op_readf,-1,-1,symtab[$2.sym_off].place);
							 emitCode(op_jmp,-1,-1,-1);
							}
	;
WriteSt	:WRITE identifier				{int p=lookup($2.idname);
							 if(p==-1){printf("ERROR: line %d identifier %s is undefined.",yylineno,name+$2.idname);exit(1);}
							 $2.sym_off=p;
							 $$.sym_off=sym_off++;
							 symtab[$$.sym_off].nextlist=makelist(code_off+1);
							 emitCode((symtab[$2.sym_off].type==INT)?op_write:op_writef,-1,-1,symtab[$2.sym_off].place);
							 emitCode(op_jmp,-1,-1,-1);}
	;
E 	:E '+' T					{int temp=0;
							 $$.sym_off=sym_off++;
							 if((symtab[$1.sym_off].type==INT)&&(symtab[$3.sym_off].type==INT))
							 {
							 	symtab[$$.sym_off].type=INT;
							 	symtab[$$.sym_off].place = mem_off++;
							 	emitCode(op_add,symtab[$1.sym_off].place,symtab[$3.sym_off].place,symtab[$$.sym_off].place);
							 }
							 else if((symtab[$1.sym_off].type==INT)&&(symtab[$3.sym_off].type==REAL))
							 {
							 	symtab[$$.sym_off].type=REAL;
							 	symtab[$$.sym_off].place = mem_off++;
							 	//symtab[$1.sym_off].type=REAL;		/*如果存储是常量或变量被以后用到,为避免再次转换,所以要设置类型,否则生成代码产生错误结果*/
							 	temp=mem_off;
							 	emitCode(op_mov,symtab[$1.sym_off].place,-1,temp);
							 	emitCode(op_inttoreal,temp,-1,temp);
							 	emitCode(op_fadd,temp,symtab[$3.sym_off].place,symtab[$$.sym_off].place);
							 }
							 else if((symtab[$1.sym_off].type==REAL)&&(symtab[$3.sym_off].type==INT))
							 {
							 	symtab[$$.sym_off].type=REAL;
							 	symtab[$$.sym_off].place = mem_off++;
							 	//symtab[$1.sym_off].type=REAL;		/*如果存储是常量或变量被以后用到,为避免再次转换,所以要设置类型,否则生成代码产生错误结果*/
							 	temp=mem_off;
							 	emitCode(op_mov,symtab[$1.sym_off].place,-1,temp);
							 	emitCode(op_inttoreal,temp,-1,temp);
							 	emitCode(op_fadd,temp,symtab[$3.sym_off].place,symtab[$$.sym_off].place);
							 	
							 }
							 else if((symtab[$1.sym_off].type==REAL)&&(symtab[$3.sym_off].type==REAL))
							 {
							 	symtab[$$.sym_off].type=REAL;
							 	symtab[$$.sym_off].place = mem_off++;
							 	emitCode(op_fadd,symtab[$1.sym_off].place,symtab[$3.sym_off].place,symtab[$$.sym_off].place);
							 	
							 }
							 else
							 {
							 	type_error();
							 }
							}
	|E '-' T					{int temp=0;
							 $$.sym_off=sym_off++;
							 if((symtab[$1.sym_off].type==INT)&&(symtab[$3.sym_off].type==INT))
							 {
							 	symtab[$$.sym_off].type=INT;
							 	symtab[$$.sym_off].place = mem_off++;
							 	emitCode(op_minus,symtab[$1.sym_off].place,symtab[$3.sym_off].place,symtab[$$.sym_off].place);
							 }
							 else if((symtab[$1.sym_off].type==INT)&&(symtab[$3.sym_off].type==REAL))
							 {
							 	symtab[$$.sym_off].type=REAL;
							 	symtab[$$.sym_off].place = mem_off++;
							 	//symtab[$1.sym_off].type=REAL;		/*如果存储是常量或变量被以后用到,为避免再次转换,所以要设置类型,否则生成代码产生错误结果*/
							 	temp=mem_off;
							 	emitCode(op_mov,symtab[$1.sym_off].place,-1,temp);
							 	emitCode(op_inttoreal,temp,-1,temp);
							 	emitCode(op_fminus,temp,symtab[$3.sym_off].place,symtab[$$.sym_off].place);
							 }
							 else if((symtab[$1.sym_off].type==REAL)&&(symtab[$3.sym_off].type==INT))
							 {
							 	symtab[$$.sym_off].type=REAL;
							 	symtab[$$.sym_off].place = mem_off++;
							 	//symtab[$1.sym_off].type=REAL;		/*如果存储是常量或变量被以后用到,为避免再次转换,所以要设置类型,否则生成代码产生错误结果*/
							 	temp=mem_off;
							 	emitCode(op_mov,symtab[$1.sym_off].place,-1,temp);
							 	emitCode(op_inttoreal,temp,-1,temp);
							 	emitCode(op_fminus,temp,symtab[$3.sym_off].place,symtab[$$.sym_off].place);
							 	
							 }
							 else if((symtab[$1.sym_off].type==REAL)&&(symtab[$3.sym_off].type==REAL))
							 {
							 	symtab[$$.sym_off].type=REAL;
							 	symtab[$$.sym_off].place = mem_off++;
							 	emitCode(op_fminus,symtab[$1.sym_off].place,symtab[$3.sym_off].place,symtab[$$.sym_off].place);
							 	
							 }
							 else
							 {
							 	type_error();
							 }
							}
	|T						{
								$$.sym_off=$1.sym_off;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -