编译原理实验报告
- 格式:doc
- 大小:145.00 KB
- 文档页数:16
编译原理实验报告 王德奎03091364
一.实验目的 设计并且编写一个编译器,加深对编译器工作原理的认识和理解。 二.实验要求 能实现四则运算,布尔运算,if语句判断,while循环。另外,还可以实现注释功能和打印。 1.四则运算包括: 加(+),减(—),乘(*),除(/),求余(%) 2.布尔运算包括: 大于等于(>=),小于等于(<=),等于(==),不等于(!=), 不等于(<>),与运算(&&),或运算(||),非运算(!) 3.If语句 4.while语句
关键字: +,-,*,/,%, >=,<=,<,>,!=,<>,&&,||,!,==, print,while,if,else,{,}false,true 各种单词对应的记号如下: /* */ 不返回记号 "while" WHILE "if" IF "else" ELSE "print" PRINT "false" INTEGER "true" INTEGER [a-z] VARIABLE [0-9]+ INTEGER -()<>=+*/%;{} 返回本身 ">=" GE "<=" LE "==" EQ "!=" NE "<>" NE "&&" AND "||" OR "!" NOT [ \t\n]+ 不返回记号 三.实验基本思想 首先是对输入的程序扫描,进行词法分析,并返回记号。在c语言头文件中定义了一个结构体,用来存放记号的类型和值(如果有的话)。在语法分析中,规定了优先级和结合性。根据输入语句的类型而进行不同的操作。
四.源代码 1. Lex词法分析代码: %{ #include #include "node.h" #include "myparser.h" void yyerror(char *); %}
%% "/*"([^\*]|(\*)*[^\*/])*(\*)*"*/" ; //注释 "while" {return WHILE;} "if" {return IF;} "else" {return ELSE;} "print" {return PRINT;} "false" {yylval.iValue = 0; return INTEGER; } "true" {yylval.iValue = 1; return INTEGER; }
[a-z] {yylval.sIndex = *yytext - 'a'; return VARIABLE; }
[0-9]+ {yylval.iValue = atoi(yytext); return INTEGER; }
[-()<>=+*/%;{}.] {return *yytext;} ">=" {return GE;} "<=" {return LE;} "==" {return EQ;} "!=" {return NE;} "<>" {return NE;} "&&" {return AND;} "||" {return OR;} "!" {return NOT;}
[ \t\n]+ ; /* 去除空格,回车 */ . printf("unknow symbol:[%s]\n",yytext); %% int yywrap(void) { return 1; }
2. Yacc语法分析源代码: %{
#include #include #include #include "node.h" /* 属性操作类型 */ Node *opr(int name, int num, ...);
Node *set_index(int value); Node *set_content(int value);
void freeNode(Node *p); int exeNode(Node *p); int yylexeNode(void); void yyerror(char *s);
int Var[26]; /* 变量数组 */ %}
%union { int iValue; /* 变量值 */ char sIndex; /* 变量数组索引 */ Node *nPtr; /* 结点地址 */ }
%token VARIABLE %token INTEGER %token WHILE IF PRINT %nonassoc IFX %nonassoc ELSE %left AND OR GE LE EQ NE '>' '<' %right NOT %left '+' '-' %left '*' '/' '%' %nonassoc UMINUS //不具有结合性 %type stmt expr stmt_list %% program: function { exit(0); } ; function: function stmt { exeNode($2); freeNode($2); } | /* NULL */ ; stmt: ';' { $$ = opr(';', 2, NULL, NULL); } | expr ';' { $$ = $1; } | PRINT expr ';' { $$ = opr(PRINT, 1, $2); } | VARIABLE '=' expr ';' { $$ = opr('=', 2, set_index($1), $3); } | WHILE '(' expr ')' stmt { $$ = opr(WHILE, 2, $3, $5); } | IF '(' expr ')' stmt %prec IFX { $$ = opr(IF, 2, $3, $5); } | IF '(' expr ')' stmt ELSE stmt %prec ELSE { $$ = opr(IF, 3, $3, $5, $7); } | '{' stmt_list '}' { $$ = $2; } ; stmt_list: stmt { $$ = $1; } | stmt_list stmt { $$ = opr(';', 2, $2, $1); } ; expr: INTEGER { $$ = set_content($1); } | VARIABLE { $$ = set_index($1); } | expr '+' expr { $$ = opr('+', 2, $1, $3); } | expr '-' expr { $$ = opr('-', 2, $1, $3); } | expr '*' expr { $$ = opr('*', 2, $1, $3); } | expr '/' expr { $$ = opr('/', 2, $1, $3); } | expr '%' expr { $$ = opr('%', 2, $1, $3); } | expr '<' expr { $$ = opr('<', 2, $1, $3); } | expr '>' expr { $$ = opr('>', 2, $1, $3); } | expr GE expr { $$ = opr(GE, 2, $1, $3); } | expr LE expr { $$ = opr(LE, 2, $1, $3); } | expr NE expr { $$ = opr(NE, 2, $1, $3); } | expr EQ expr { $$ = opr(EQ, 2, $1, $3); } | expr AND expr { $$ = opr(AND, 2, $1, $3); } | expr OR expr { $$ = opr(OR, 2, $1, $3); } | NOT expr { $$ = opr(NOT, 1, $2); } | '-' expr %prec UMINUS { $$ = opr(UMINUS, 1, $2); } | '(' expr ')' { $$ = $2; } ; %% #define SIZE_OF_NODE ((char *)&p->content - (char *)p)
Node *set_content(int value) { Node *p; size_t sizeNode;
/* 分配结点空间 */ sizeNode = SIZE_OF_NODE + sizeof(int); if ((p = malloc(sizeNode)) == NULL) yyerror("out of memory"); /* 复制内容 */ p->type = TYPE_CONTENT; p->content = value;
return p; }
Node *set_index(int value) {
Node *p; size_t sizeNode; /* 分配结点空间 */ sizeNode = SIZE_OF_NODE + sizeof(int);
if ((p = malloc(sizeNode)) == NULL) yyerror("out of memory");
/* 复制内容 */ p->type = TYPE_INDEX; p->index = value;