为了正常的体验网站,请在浏览器设置里面开启Javascript功能!

实验五_用语法制导方式生成中间代码生成器

2018-01-18 13页 doc 96KB 28阅读

用户头像

is_597436

暂无简介

举报
实验五_用语法制导方式生成中间代码生成器实验五_用语法制导方式生成中间代码生成器 实验5 用语法制导方式生成中间代码生成器 魏陈强 23020092204168 一、实验目的 掌握语法制导定义和翻译的原理和技术,在语法分析器的基础上,加上语义分析,构造一个中间代码生成器。 二、实验内容 在实验四生成的语法分析器基础上加入语义动作,将源程序翻译为对应的中间代码序列。 三、实验要求 1(实验报告中给出采用测试源代码片断,及其对应的三地址码形式(内部表示形式可以自行考虑)。 例如,程序片断 对应的中间代码为: 四、实验思路 在前4次实验的基础...
实验五_用语法制导方式生成中间代码生成器
实验五_用语法制导方式生成中间代码生成器 实验5 用语法制导方式生成中间代码生成器 魏陈强 23020092204168 一、实验目的 掌握语法制导定义和翻译的原理和技术,在语法器的基础上,加上语义分析,构造一个中间代码生成器。 二、实验内容 在实验四生成的语法分析器基础上加入语义动作,将源程序翻译为对应的中间代码序列。 三、实验要求 1(实验中给出采用测试源代码片断,及其对应的三地址码形式(内部示形式可以自行考虑)。 例如,程序片断 对应的中间代码为: 四、实验思路 在前4次实验的基础上进行中间代码生成的编写,采用linux环境下的lex和yacc工具。首先编写goto.c函数,该函数实现符号表、回填、创建节点、定义节点属性等功能。Lex.l文件无需修改,yacc.y文件中,在每个生成式后加上语法制导翻译,主要是依据truelist和falselist来实现回填功能。编写完后,在yacc.y中以头文件的方式加入goto.c,编译即可。 五、实验代码 1、lex.l %{ %} …… letter [A-Za-z] digit [0-9] …… %option noyywrap %% if { return( IF ); } else { return( ELSE ); } …… "<"|"<="|">"|">="|"!="|"==" { op_in(&yylval, yytext); return( REL); } …… %% 2、Yacc.y %{ #include "goto.c" #define YYSTYPE node int yyerror(); int yyerror(char* msg); extern int yylex(); codelist* list; %} %token BASIC NUMBER REAL ID TRUE FALSE %token INT CHAR BOOL FLOAT %token REL %token IF ELSE WHILE DO BREAK SWITCH CASE DEFAULT %token OR AND %left OR %left AND %right '!' %left '+' '-' %left '*' '/' %right UMINUS %right INC DEC %expect 1 %% program : block { } ; block : '{' decls statementlist '}' { } ; decls : decls decl { } | { } ; decl : type ID ';' { } ; type : type '[' NUMBER ']' { } | BASIC { } ; statementlist : statementlist M statement { backpatch(list, $1.nextlist, $2.instr); $$.nextlist = $3.nextlist; } | statement { $$.nextlist = $1.nextlist; } ; statement : IF '(' boolean ')' M statement ELSE N M statement { backpatch(list, $3.truelist, $5.instr); backpatch(list, $3.falselist, $9.instr); $6.nextlist = merge($6.nextlist, $8.nextlist); $$.nextlist = merge($6.nextlist, $10.nextlist); } | IF '(' boolean ')' M statement { backpatch(list, $3.truelist, $5.instr); $$.nextlist = merge($3.falselist, $6.nextlist); } | WHILE M '(' boolean ')' M statement { backpatch(list, $7.nextlist, $2.instr); backpatch(list, $4.truelist, $6.instr); $$.nextlist = $4.falselist; gen_goto(list, $2.instr); } | DO M statement M WHILE '(' boolean ')' M ';' { backpatch(list, $3.nextlist, $4.instr); backpatch(list, $7.truelist, $9.instr); $$.nextlist = $7.falselist; gen_goto(list, $2.instr); } | BREAK ';' { } | '{' statementlist '}' { $$.nextlist = $2.nextlist; } | assignment ';' { $$.nextlist = NULL; } ; assignment : ID '=' boolean { address(&$1, $1.lexeme); gen_assignment(list, $1, $3); } ; loc : loc '[' boolean ']' { } | ID { address(&$$, $1.lexeme); } ; boolean : boolean OR M boolean { backpatch(list, $1.falselist, $3.instr); $$.truelist = merge($1.truelist, $4.truelist); $$.falselist = $4.falselist; } | boolean AND M boolean { backpatch(list, $1.truelist, $3.instr); $$.truelist = $4.truelist; $$.falselist = merge($1.falselist, $4.falselist); } | '!' boolean { $$.truelist = $1.falselist; $$.falselist = $1.truelist; } | '(' boolean ')' { $$.truelist = $1.truelist; $$.falselist = $1.falselist; } | expression REL expression { $$.truelist = new_instrlist(nextinstr(list)); $$.falselist = new_instrlist(nextinstr(list)+1); gen_if(list, $1, $2.oper, $3); gen_goto_blank(list); } | TRUE { address(&$$, "TRUE"); gen_goto_blank(list); } | FALSE { address(&$$, "FALSE"); gen_goto_blank(list); } | expression { addr_node(&$$, $1); } ; M : { $$.instr = nextinstr(list); } ; N : { $$.nextlist = new_instrlist(nextinstr(list)); gen_goto_blank(list); } ; expression : expression '+' expression { new_temp(&$$, get_temp_index(list)); gen_3addr(list, $$, $1, "+", $3); } | expression '-' expression { new_temp(&$$, get_temp_index(list)); gen_3addr(list, $$, $1, "-", $3); } | expression '*' expression { new_temp(&$$, get_temp_index(list)); gen_3addr(list, $$, $1, "*", $3); } | expression '/' expression { new_temp(&$$, get_temp_index(list)); gen_3addr(list, $$, $1, "/", $3); } | '-' expression %prec UMINUS { new_temp(&$$, get_temp_index(list)); gen_2addr(list, $$, "-", $2); } | loc { addr_node(&$$, $1); } | NUMBER { address(&$$, $1.lexeme); } | REAL { address(&$$, $1.lexeme); } ; %% #include"lex.yy.c" int yyerror(char* msg) { printf("\nERROR with message: %s\n", msg); return 0; } int main() { list = newcodelist(); yyparse(); print(list); return 0; } 2、Goto.c #ifndef GOTO_C #define GOTO_C #include #include #include typedef struct listele { int instrno; struct listele *next; }listele; listele* new_listele(int no) { listele* p = (listele*)malloc(sizeof(listele)); p->instrno = no; p->next = NULL; return p; } typedef struct instrlist { listele *first,*last; }instrlist; instrlist* new_instrlist(int instrno) { instrlist* p = (instrlist*)malloc(sizeof(instrlist)); p->first = p->last = new_listele(instrno); return p; } instrlist* merge(instrlist *list1, instrlist *list2) { instrlist *p; if (list1 == NULL) p = list2; else { if (list2!=NULL) { if (list1->last == NULL) { list1->first = list2->first; list1->last =list2->last; }else list1->last->next = list2->first; list2->first = list2->last = NULL; free(list2); } p = list1; } return p; } typedef struct node { instrlist *truelist, *falselist, *nextlist; char addr[256]; char lexeme[256]; char oper[3]; int instr; }node; int op_in(node *dst, char *src) { strcpy(dst->oper, src); return 0; } int lexeme_in(node *dst, char *yytext) { strcpy(dst->lexeme, yytext); return 0; } int address(node *dst, char *src) { strcpy(dst->addr, src); return 0; } int new_temp(node *dst, int index) { sprintf(dst->addr, "t%d", index); return 0; } int addr_node(node *dst, node src) { strcpy(dst->addr, src.addr); return 0; } typedef struct codelist { int linecnt, capacity; int temp_index; char **code; }codelist; codelist* newcodelist() { codelist* p = (codelist*)malloc(sizeof(codelist)); p->linecnt = 0; p->capacity = 1024; p->temp_index = 0; p->code = (char**)malloc(sizeof(char*)*1024); return p; } int get_temp_index(codelist* dst) { return dst->temp_index++; } int nextinstr(codelist *dst) { return dst->linecnt; } int Gen(codelist *dst, char *str) { if (dst->linecnt >= dst->capacity) { dst->capacity += 1024; dst->code = (char**)realloc(dst->code, sizeof(char*)*dst->capacity); if (dst->code == NULL) { printf("Error!\n"); return 0; } } dst->code[dst->linecnt] = (char*)malloc(strlen(str)+20); strcpy(dst->code[dst->linecnt], str); dst->linecnt++; return 0; } char tmp[1024]; int gen_goto_blank(codelist *dst) { sprintf(tmp, "goto"); Gen(dst, tmp); return 0; } int gen_goto(codelist *dst, int instrno) { sprintf(tmp, "goto L%d", instrno); Gen(dst, tmp); return 0; } int gen_if(codelist *dst, node left, char* op, node right) { sprintf(tmp, "if %s %s %s goto", left.addr, op, right.addr); Gen(dst, tmp); return 0; } int gen_1addr(codelist *dst, node left, char* op) { sprintf(tmp, "%s %s", left.addr, op); Gen(dst, tmp); return 0; } int gen_2addr(codelist *dst, node left, char* op, node right) { sprintf(tmp, "%s = %s %s", left.addr, op, right.addr); Gen(dst, tmp); return 0; } int gen_3addr(codelist *dst, node left, node op1, char* op, node op2) { sprintf(tmp, "%s = %s %s %s", left.addr, op1.addr, op, op2.addr); Gen(dst, tmp); return 0; } int gen_assignment(codelist *dst, node left, node right) { gen_2addr(dst, left, "", right); return 0; } int backpatch(codelist *dst, instrlist *list, int instrno) { if (list!=NULL) { listele *p=list->first; char tmp[20]; sprintf(tmp, " L%d", instrno); while (p!=NULL) { if (p->instrnolinecnt) strcat(dst->code[p->instrno], tmp); p=p->next; } } return 0; } int print(codelist* dst) { int i; for (i=0; i < dst->linecnt; i++) printf("L%d: %s\n", i, dst->code[i]); return 0; } #endif 六、实验结果 1、输入程序 2、输出结果 七、实验心得 本次实验要实现中间代码生成,也是本学期的最后一次实验,要在前4次实验的基础上完成,综合比较前4次实验,感觉本次实验难度挺高,首先,前4次实验的词法分析和语法分析需要有足够高的正确率,否者本次实验中会遇到一些神奇的问题,不知道错在哪里;其次,对语法制导定义和语法制导翻译要掌握好才能把握编写思路。本次实验难度较大,编写许久任进展不佳,因此参考了往年学长的代码,主要是参考了其符号表和回填方法,并且在其代码上进行了适当的优化。小学期有时间了,还得慢慢研究下本次实验。
/
本文档为【实验五_用语法制导方式生成中间代码生成器】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索