中间代码生成器 

一、实验目的

掌握中间代码生成器的构造原理和编程方法。

 

二、实验内容

用自顶向下方法或Yacc进行语法分析的基础上,编写一个中间代码生成程序。见教材附录 A.1p394

program      → block

block     →   { decls stmts }

decls  →   decls decl | e

decl   →   type id ;

type   →   type [num]   //数组可以不做

| basic        //四种基本数据类型 int | float | char | bool

stmts     → stmts stmt | e

       stmt       →   id= expr ;

|      if ( bool ) stmt

|      if ( bool) stmt else stmt

|      while (bool) stmt

|      do stmt while (bool ) ;

|      break ;    //break可以不做

|      block

bool        →  bool || join  |  join

join     →   join  && equality | equality

equality  →  equality == rel  |  equality != rel  |  rel

rel      →  expr < expr

|    expr <= expr

|     expr > expr

|     expr >= expr

|     expr

expr      → expr + term

|     expr - term

|     term

term      → term * unary

|   term / unary

|     unary

      unary  →  !unary  |  - unary  |  factor

factor     → ( expr ) | id| num 

三、实验要求

1.个人完成,提交实验报告。

2.实验的结果为:生成中间代码 (三地址码)

{

a=10;

x = b - c;

y = a * x;

z = x * d;

abcd = a + x +y;

if(a>10)

a=a+1;

a=a+2;

}

实验结果生成的代码片段

0:  a =  10

1:  t0 = b - c

2:  x =  t0

3:  t1 = a * x

4:  y =  t1

5:  t2 = x * d

6:  z =  t2

7:  t3 = a + x

8:  t4 = t3 + y

9:  abcd =  t4

10:  if a > 10 goto 12

11:  goto 14

12:  t5 = a + 1

13:  a =  t5

14:  t6 = a + 2

15:  a =  t6

个人对于本次中间代码生成器-编译实验的心得:

View Code

       #define YYSTYPE node:定义符号栈属性结点类型typedef struct node{instrlist *truelist, *falselist, *nextlist;//相当于有一个 正确链表与 错误链表 每个链表结点都有个值char addr[256];//    地址字段       存放具体结点的内容比如 a 8 10 等char lexeme[256];//字符串指端char oper[3];//操作符字段           具体存放操作符对应的字符串int instr; //是否要回填指示          具体内容是行号

}node;int main(){list = newcodelist();//申请一个内存空间给list// int linecnt, capacity;   行数  与  最大行数// int temp_index;         // char **code;                     总代码
freopen("test.in", "rt+", stdin);freopen("test.out", "wt+", stdout);//打开文件
yyparse();print(list);fclose(stdin);//关闭文件
fclose(stdout);//关闭文件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);       //将tmp的内容存放到 总字符串                list的code字段当中return 0;}    int Gen(codelist *dst, char *str)  //输入 第一个参数为 list  第二个参数是 总字符串 tmp[1024]
{                             //目标是   将tmp的内容存放到 总字符串           list的code字段当中if (dst->linecnt >= dst->capacity){dst->capacity += 1024;dst->code = (char**)realloc(dst->code, sizeof(char*)*dst->capacity);if (dst->code == NULL){printf("short of memeory\n");return 0;}}dst->code[dst->linecnt] = (char*)malloc(strlen(str)+20);     //申请一个内存空间存放中间字符串
strcpy(dst->code[dst->linecnt], str);                    //字符串复制
dst->linecnt++;                                  //行号加1return 0;}int backpatch(codelist *dst, instrlist *list, int instrno)     //总代码 dst  错误列表list   错误的指向行数
{if (list!=NULL)                                          //如果错误的列表不为空
{listele *p=list->first;     char tmp[20];sprintf(tmp, " %d", instrno);                     取出一个while (p!=NULL){if (p->instrno<dst->linecnt)strcat(dst->code[p->instrno], tmp);   //错误列表:1 2 3 4  假设都指向instrno=6 那么将6转化为字符串tmp//再添加到每个字符串的末尾
p=p->next;}}return 0;}// int linecnt, capacity; 行数  与  最大行数// int temp_index;       // char **code;     

重点是对课上的回填技术,还有

栈中的可能属性类别也就是node结点的属性种类,还有的是全局变量list使用的结点除了行号,最大行号,还有就是三地址码存放的chor **类型的code。

jia.l

View Code

%{#include "jia.tab.h"
%}
delim        [ \t\n\r]
ws        {delim}+
letter        [A-Za-z]
digit        [0-9]
id        {letter}({letter}|{digit})*
integer        {digit}+
exponent    E[+-]?{integer}
number        {integer}{exponent}?
real        integer(\.integer)?{exponent}?
%option noyywrap
%%
if    { return( IF ); }
else     { return( ELSE ); }
while    { return( WHILE ); }
do    { return( DO ); }
for    { return( FOR ); }
switch    { return( SWITCH ); }
case    { return( CASE ); }
default    { return( DEFAULT ); }
break    { return( BREAK ); }
true    { return( TRUE ); }
false    { return( FALSE ); }
int    { return( INT ); }
long    { return( LONG ); }
char    { return( CHAR ); }
bool    { return( BOOL ); }
float    { return( FLOAT ); }
double    { return( DOUBLE ); }
"&&"    { return( AND ); }
"||"    { return( OR ); }
"!"    { return( '!'); }
"<"|"<="|">"|">="|"!="|"=="    { filloperator(&yylval, yytext); return( REL); }
"++"    { return( INC ); }
"--"    { return( DEC ); }
"+"    { return( '+' ); }
"-"    { return( '-' ); }
"*"    { return( '*' ); }
"/"    { return( '/' ); }
"="    { return( '=' ); }
"{"    { return( '{' ); }
"}"    { return( '}' ); }
"["    { return( '[' ); }
"]"    { return( ']' ); }
"("    { return( '(' ); }
")"    { return( ')' ); }";"    { return( ';' ); }
{ws}    { }
{id}    { filllexeme(&yylval, yytext); return( ID ); }
{number}    { filllexeme(&yylval, yytext); return( NUMBER ); }
{real}        { filllexeme(&yylval, yytext); return( REAL ); }
%%

jia.y

View Code

%{#include "xu.h"#define YYSTYPE node#include "jia.tab.h"int yyerror();int yyerror(char* msg);extern int yylex();codelist* list;
%}
%token BASIC NUMBER REAL ID TRUE FALSE
%token INT LONG CHAR BOOL FLOAT DOUBLE
%token REL
%token IF ELSE WHILE DO BREAK FOR SWITCH CASE DEFAULT
%token OR AND
%left OR
%left AND
%right '!'
%left '+' '-'
%left '*' '/'
%right UMINUS
%right INC DEC
%%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); }| FOR '(' assignment ';' M boolean ';' M assignment ')' N M statement { backpatch(list, $6.truelist, $12.instr);backpatch(list, $11.nextlist, $5.instr);backpatch(list, $13.nextlist, $8.instr);$$.nextlist = $6.falselist;gen_goto(list, $8.instr); }| BREAK ';'                {  }| '{' statementlist '}'                { $$.nextlist = $2.nextlist; } | assignment ';'        { $$.nextlist = NULL; };assignment    : ID '=' boolean          { copyaddr(&$1, $1.lexeme); gen_assignment(list, $1, $3); };loc    : loc '[' boolean ']'    {  }| ID            { copyaddr(&$$, $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            { copyaddr(&$$, "TRUE");gen_goto_blank(list); }| FALSE                { copyaddr(&$$, "FALSE");gen_goto_blank(list); }| expression        { copyaddr_fromnode(&$$, $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            { copyaddr_fromnode(&$$, $1); }| NUMBER            { copyaddr(&$$, $1.lexeme); }| REAL            { copyaddr(&$$, $1.lexeme); };%%int yyerror(char* msg)
{printf("\nERROR with message: %s\n", msg);return 0;
}int main()
{list = newcodelist();
//申请一个内存空间给list
// int linecnt, capacity;
// int temp_index;
// char **code;freopen("test.in", "rt+", stdin);freopen("test.out", "wt+", stdout);
//打开文件
    yyparse();print(list);fclose(stdin);
//关闭文件
    fclose(stdout);
//关闭文件return 0;
}

xu.h

View Code

#ifndef CP_H
#define CP_H#include <stdio.h>
#include <string.h>
#include <malloc.h>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 filloperator(node *dst, char *src){strcpy(dst->oper, src);return 0;}    int filllexeme(node *dst, char *yytext){strcpy(dst->lexeme, yytext);return 0;}int copyaddr(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 copyaddr_fromnode(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("short of memeory\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 %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, " %d", instrno);while (p!=NULL){if (p->instrno<dst->linecnt)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("%5d:  %s\n", i, dst->code[i]);return 0;}#endif

test.in

View Code

{a=10;
x = b - c;
y = a * x;
z = x * d;
abcd = a + x +y;
if(a>10)
a=a+1;
a=a+2;
while(a>0)
a=a-1;
b=b+1;
}

最终老师给的代码暂未公开

课件

转载于:https://www.cnblogs.com/xjx-user/archive/2012/12/16/2820682.html

中间代码生成器-5-编译原理相关推荐

  1. 编译原理实验七:中间代码生成器

    实现一门语言的中间代码生成器(4小时) 实验目的 通过本次实验,加深对中间代码生成的理解,学会编制中间代码生成器. 实验任务 用C.JAVA或其他语言编写一门语言的中间代码生成器,所选实现语言应与之前 ...

  2. java pl0 四元式,【编译原理】c++实现自下而上语法分析及中间代码(四元式)生成...

    写在前面:本博客为本人原创,严禁任何形式的转载!本博客只允许放在博客园(.cnblogs.com),如果您在其他网站看到这篇博文,请通过下面这个唯一的合法链接转到原文! 本博客全网唯一合法URL:ht ...

  3. 学了编译原理能否用 Java 写一个编译器或解释器?

    16 个回答 默认排序​ RednaxelaFX JavaScript.编译原理.编程 等 7 个话题的优秀回答者 282 人赞同了该回答 能.我一开始学编译原理的时候就是用Java写了好多小编译器和 ...

  4. 编译原理什么是移进规约冲突_编译原理复习题

    可以微信扫码观看 河南城建 <编译原理>复习题丨杨海振整理丨20150521 一.单项选择题 1.构造编译程序应掌握   .D a. 源程序                         ...

  5. 编译原理语义分析_编译原理 第一章 绪论

    编译原理系列,是在学习本校 "编译技术" 这门课程时,所作记录,参考教材为 <编译技术基础教程>清华大学出版社和<程序设计语言编译原理>国防工业出版社(陈火 ...

  6. 编译原理_P1004

    龙书相关知识点总结 //*************************引论***********************************// 1. 编译器(compiler):从一中语言( ...

  7. lr1分析器c语言实验报告怎么写,编译原理课程的设计构造LR分析法语法分析器.doc...

    编译原理课程的设计构造LR分析法语法分析器 太 原 学 院 课程设计报告书 课程名称 设计题目 构造LR(0)分析法语法分析器 专业班级 学 号 姓 名 指导教师 2016年 12 月 15日 目 录 ...

  8. 【编译原理】山东大学编译原理复习提纲

    涵盖所有考点,复习绝对高效,点赞+留邮箱获取pdf版本. 山东大学编译原理复习提纲 一.简答与计算 1.1 必考 1. 编译过程 画图表示编译过程的各阶段,并简要说明各阶段的功能: 词法分析器:输入源 ...

  9. 编译原理MOOC笔记

    编译原理笔记 正规文法和正规式 词法分析 前端 词法分析器的任务 词法分析器的实现方法 正则表达式 有限状态自动机 正则表达式到非确定有限状态自动机 语法分析 自上而下的语法分析 直接左递归的消除 间 ...

最新文章

  1. 原生js实现点击按钮切换全屏!
  2. java400状态,java – HttpURLConnection:如何读取400响应的有效负载
  3. 学生信息管理系统小结
  4. C#集合类(HashTable, Dictionary, ArrayList)与HashTable线程安全
  5. 大数据学习(10)--流计算
  6. ipconfig和ping 命令的各种参数
  7. 小红书重拳治理虚假种草 再起诉3家通告平台、MCN机构
  8. Java面向对象之构造方法、构造方法重载
  9. 恒丰银行助手提示注册表异常但修复不了的解决方法
  10. HDU 5938 2016CCPC杭州 F: Four Operations
  11. Volatile的实现原理(看这篇就够了)
  12. 豆瓣电影、纪录片、书籍......下载神器
  13. 开源项目SmartImageView的引用
  14. [视频]AI 机器学习 深度学习 视频教程汇总
  15. 【AI视野·今日CV 计算机视觉论文速览 第187期 part1】Fri, 18 Dec 2020
  16. 【计算机图形学】Bezier曲线软件及操作
  17. windows xp 下载老版本的chrome浏览器
  18. 网络请求分析实战篇(01)—— 爬取amazon搜索栏的关联关键词
  19. JQuery验证手机号电话号码
  20. 什么是用户感?看看这4个产品经理的感性设计

热门文章

  1. Spring Boot MongoDB 入门
  2. 遇到洋妞不敢搭讪,程序员的羞涩你不懂
  3. Java 集合框架综述
  4. 实用技巧:教你如何在没有网络的Linux机器上快速安装软件
  5. 工程化专题之Maven(上)
  6. Java线程详解(4)-线程状态的转换
  7. 多线程:AQS的一些心得
  8. 向量笛卡尔积_如何创建向量的矢量的笛卡尔积?
  9. java 处理异常的场景_Java高级----异常处理机制、自定义异常----含思维导图
  10. c语言删除s字符串中所有子串t,从串s中删除所有和串t相同的子串的算法