📄 grammer.y
字号:
/*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 + -