一、实验目的
掌握中间代码的生成方法
学会临时变量的使用和分配方法。
二、实验题目
编写相应的Lex和Yacc程序,将整数表达式的翻译成三地址代码。
整数表达式中可能含有 + - * / ( ) 和 变量,
例如,下列表达式
a + b * ( c - d ) + e / ( c + d )
翻译为:
t1 = c - d
t2 = b * t1
t3 = a + t2
t4 = c + d
t5 = e / t4
t6 = t3 + t5
三、实验内容
生成表达式的三地址码表示。
尝试优化临时变量的使用(选做)。
Lex程序:
%{
#include "syntax.tab.h"
#include <stdio.h>
#include <stdlib.h>
#include "var.h"
int yyerror(const char *);
%}
letter [A-Za-z_]
digit [0-9]
identifier {letter}({letter}|{digit})*
%%
[0-9]+ { yylval = var_new_const(yytext); return INTEGER; }
{identifier} { yylval = var_find(yytext); return IDENTIFIER; }
[+\-*/()=\n] { return *yytext; /* 返回操作符 */ }
[ \t] { ; /* skip whitespace */ }
. { yyerror("invalid character"); }
%%
int yywrap() {
return 1;
}
Yacc程序:
%{
#include <stdio.h>
#include <stdlib.h>
#include "var.h"
int yylex(void);
int yyerror(const char *);
%}
%token IDENTIFIER
%token INTEGER
%right '='
%left '+' '-'
%left '*' '/'
%%
program:
program expr '\n' { }
|
;
expr:
INTEGER { $$ = $1; }
| IDENTIFIER { $$ = $1 ; }
| expr '+' expr { $$=var_new_temp(); printf(" %s = %s + %s\n", var_get_name($$), var_get_name($1), var_get_name($3)); }
| expr '-' expr { $$=var_new_temp(); printf(" %s = %s - %s\n", var_get_name($$), var_get_name($1), var_get_name($3)); }
| expr '*' expr { $$=var_new_temp(); printf(" %s = %s * %s\n", var_get_name($$), var_get_name($1), var_get_name($3)); }
| expr '/' expr { $$=var_new_temp(); printf(" %s = %s / %s\n", var_get_name($$), var_get_name($1), var_get_name($3)); }
| '(' expr ')' { $$=$2; }
| IDENTIFIER '=' expr { printf(" %s = %s\n", var_get_name($1), var_get_name($3) ); $$=$1; }
;
%%
int yyerror(const char *s) {
fprintf(stderr, "error: %s\n", s);
return 0;
}
int main() {
yyparse();
return 0;
}