《编译原理》实验三:中间代码生成器 lex + yacc 版

《编译原理》实验三:中间代码生成器 lex + yacc 版

文章来源:中间代码生成器-5-编译原理

在这里插入图片描述

在这里插入图片描述

项目结构
在这里插入图片描述
具体 lex 和 yacc 环境的安装和命令使用自行网上查询吧,我也记不得了,下面一些文件就是上面文件执行相关命令之后生成的

在这里插入图片描述

// headfile.h

#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 = 100;
        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;
         int j;
         for (j=100; j < dst->linecnt; j++);
        
        for (i=100; i < dst->linecnt; i++)
        {	
if(strcmp(dst->code[i],"goto ")==0)
{
	printf("%d:  goto %d\n", i, j);continue;
}
	 printf("%d:  %s\n", i, dst->code[i]);
        }         
        printf("%d:  halt\n", i);
        return 0;
    }


/*/
//*
    int print(codelist* dst)
    {

        int i;
        
        
        for (i=100; i < dst->linecnt; i++)
        {	

	 printf("%d:  %s\n", i, dst->code[i]);
        }         
        printf("%d:  halt\n", i);
        return 0;
    }

//*/

#endif

// lex.l

%{
    #include "yacc.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}?
halt	[EOF]
%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 ); }
"<"|"<="|">"|">="|"!="|"=="    { filloperator(&yylval, yytext); return( REL); }
"+"    	{ 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 ); }
{halt}        { filllexeme(&yylval, yytext); return( HALT ); }

%%

// yacc.y

%{
    #include "headfile.h"
    #define YYSTYPE node
    #include "yacc.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 HALT
%token REL
%token IF ELSE WHILE DO BREAK FOR SWITCH CASE DEFAULT 
%left '+' '-'
%left '*' '/'
%%


block     :  statement  { }
    ;

statement    :
     IF '(' boolean ')' statement        
		{
		 backpatch(list, $3.truelist, $5.instr);
                                 $$.nextlist = merge($3.falselist, $6.nextlist); 
		}
    | WHILE '(' boolean ')' statement    
		{
		 backpatch(list, $7.nextlist, $2.instr);
                          	 backpatch(list, $4.truelist, $6.instr);
                                 $$.nextlist = $4.falselist;
                                 gen_goto(list, $2.instr); 
		}
    | assignment ';'        { $$.nextlist = NULL; }
    | HALT        { $$.nextlist = NULL; }
    ;



assignment    : ID '=' boolean         
		 {
		   copyaddr(&$1, $1.lexeme); gen_assignment(list, $1, $3);
		 }
    ;


boolean    :  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); 
		}
   
    | expression        { copyaddr_fromnode(&$$, $1); }
    ;

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); 
		}
    | NUMBER          { copyaddr(&$$, $1.lexeme); }
    ;

%%


int yyerror(char* msg)
{
    printf("\nERROR: %s\n", msg);
    return 0;
}


int main()
{
    list = newcodelist();
	
    //打开文件
    freopen("test.in", "rt+", stdin);
    freopen("test.out", "wt+", stdout);
    
    yyparse();
    print(list);

    //关闭文件
    fclose(stdin);  
    fclose(stdout);

    return 0;
}

// test.in  输入文件

sum = 0;
	x = 9;
	while (sum <= 100) sum = sum + x;
	if (sum > 101) sum = sum - 100;

输出结果
输出结果

贵州大学编译原理CSDN,可以理解为在贵州大学学习编译原理这门课程时,有关该课程的一些学习资源来源于CSDN网站。 编译原理是计算机科学与技术专业的核心课程之一,主要研究程序的编译过程和编译器的设计原理。在贵州大学学习编译原理这门课程时,CSDN作为一个知识分享的平台,可以为学生们提供丰富的学习资料和经验分享。学生们可以通过搜索CSDN网站上的编译原理相关内容,了解该课程的基本概念、原理和实践技巧。 CSDN上有很多关于编译原理的博客、问答和教程,这些资源可以帮助学生们深入理解课程的知识点和难点。学生们可以从CSDN上了解到编译原理的相关算法和数据结构,学习编译器的核心技术,如词法分析、语法分析和语义分析等。此外,CSDN上还有一些编译原理的案例分析和实践项目,可以帮助学生们将课程中的理论知识应用到实际编译器的设计与实现中。 通过CSDN,学生们还可以参与编译原理相关的技术讨论和交流。在CSDN论坛或博客评论区,学生们可以提出自己的问题、解答他人的疑惑,与其他编译原理爱好者一同交流学习经验和心得。这种交流可以促进学生们的思考和理解,加深对编译原理的认识与兴趣。 综上所述,贵州大学编译原理CSDN可以作为学生们学习编译原理课程的一个辅助资源。通过参考CSDN上的学习资料和参与技术交流,学生们可以更加全面地掌握编译原理的知识与技能,为未来的学习和工作打下扎实的基础。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值