编译原理 lex yacc 的联合使用 实验报告

更新时间:2023-09-01 21:24:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

《编译原理》课程

实验报告

题目 lex yacc 的联合使用 专业 班级 学号 姓名

一. 实验题目

lex yacc 的联合使用

二. 实验日期

三. 实验环境(操作系统,开发语言)

操作系统是Windows

开发语言是C语言

四. 实验内容(实验要求)

目的:熟悉lex和yacc的接口

要求:

(1)能对整数、实数进行带变量的四则运算

(2)词法分析用lex实现

(3)语法分析用yacc实现

(4)交源代码和实验报告

五. 实验步骤

1.在实验二的基础上修改代码,并添加上以下的代码:

double { return DOUBLE;}

EOF { return 0;}

{ID} { return ID;}

2.在DOS环境下按照之前的步骤利用flex运行myleb.l,修改其中的错误之后,生成lex.yy.c文件。

3.参照书中第14章第7节和myparser-fifth.y文件中的代码,和老师说的思路修改myparser-sixth.y文件,按照实验要求修改代码。

4.在DOS环境下利用yacc运行myparser-sixth.y文件,会有出错提示,按照出错的地方指示,修改代码,使其最终能通过运行,生成y.tab.c文件。(此步骤还未完成)

5.打开c-free5.0,新建工程,在Source files文件夹中添加之前生成的lex.yy.c文件和y.tab.c文件,然后找到已给的calc.h文件,将其添加到新建工程中的Header files文件夹中,这时就能将三个文件组成一个类似于.exe文件类型的文件,最后运行。

6.运行并调试成功。

六. 实验体会(包括收获、心得体会、存在的问题及解决问题的方法、建议等)

这是最后一次实验了,但这次的难度是有史以来最难的一次实验,因为要结合之前我们学到的所有东西。

首先要修改.l文件的代码,再把此文件用lex运行,即词法分析部分用lex完成;然后是修改myparser-sixth.y文件,尽管有参照的代码,但是要自己实现能对整数和实数进行带变量的四则运算,对于还没有完全掌握.y文件编写的我还是太有难度了,自己先是完成了只对实数的运算,也能运行,但只要添加上实数就会出错,研究了很久,还是没有找出来哪里还有错误;有时候也会出现用yacc运行没错误,但用c-free运行就会出错,提示说.h文件有错误,找了半天,也修改了很多。却仍然不知道哪里有错。

总的来说,虽然没有完成最终的目的,但是我已经尽力了。

七. 实验结果(关键源代码)

Myleb.l文件代码:

%option noyywrap

DIGIT[0-9]

ID[a-zA-Z][a-zA-Z0-9]*

%{

#include<stdio.h>

%}

%%

{DIGIT}+"."{DIGIT}* { return NUM;}

"/*"[^}\n]*"*/" printf("33 \n");

"^"

"+"

"-"

"*"

"/"

"(" printf("34 %s\n",yytext); printf("35 %s\n",yytext); printf("36 %s\n",yytext); printf("37 %s\n",yytext); printf("38 %s\n",yytext); printf("39 %s\n",yytext);

")"

"["

"]"

"{"

"}" printf("40 %s\n",yytext); printf("41 %s\n",yytext); printf("42 %s\n",yytext); printf("43 %s\n",yytext); printf("44 %s\n",yytext);

double { return DOUBLE;}

EOF { return 0;}

{ID} { return ID;}

.

%%

main(void)

{

yylex();

}

myparser-sixth.y文件代码:

/*带 整数 int 和实数 double 变量声明的加减乘除四则运算 */

%{

#include <stdio.h>

#include <math.h>

#include <ctype.h>

#include <string.h>

#include "genMidCode.h"

extern char yytext[20]; printf("100 %s\n",yytext);

extern SYMREC *sym_table;

int id_type;

SYMREC *sym;

typedef struct{

union inval{

double do;

int in;

}

int valType;

} VALUE;

%}

//定义语义栈的数据类型 有两种数据类型 整数和实数 仿照 p252 union部分

%union {

VALUE val;

SYMREC *tptr;

int type;

}

// 终结符和非终结符对应的符号类型,自己定义

%token < val > NUMDOU

%token < val > NUMINT

%token < tptr> ID

%token < type > DOUBLE

%token < type > INTEGER

%type < val > exp

%start program

%left '-' '+' 中间

%left '*' '/'

%left UMINUS

%%

program : func '#' ;

func:

|func declaration_part |func assign_stmt ;

declaration_part: DOUBLE {id_type = DOUBLE ; } declaration_list ';' | INTEGER {id_type = INTEGER ; } declaration_list ';' ;

declaration_list : declaration_list ',' declaration

|declaration ;

declaration: ID { sym_table = putsym2(yytext,id_type); }

| ID '=' NUMDOU { if (id_type == INTEGER)

= sym_table

putsym3(yytext,id_type,$3); /* 把整型值放入符号表 */

| ID '=' NUMINT { if (id_type == DOUBLE)

sym_table

putsym3(yytext,id_type,$3);} /* 把实型值放入符号表 */

;

assign_stmt: '\n'

| ID '=' exp ';' { if((sym = getsym(yytext) != NULL ){ =

if ($3.valType == 1) /* exp里是实

数 */

sym_table

putsym3(yytext,id_type,$3.inval.do);

else

sym_table

putsym3(yytext,id_type,$3.inval.in);

}

}

; = =

exp: NUMDOU { $$.valType =1; $$.inval.do= $1.inval.do;} /* valType =1代表实数 */

| NUMINT { $$.valType =2; $$.inval.in= $2.inval.in;} /* valType =2代表整数 */

| ID { if((sym = getsym(yytext)) != NULL )

if (id_type == INTEGER)

{ $$.valType =2; $$.inval.in = sym->value;} /* valType =2代表整数 */

else { $$.valType =1; $$.inval.do = sym->value;} /* valType =1代表实数 */

else ("此变量没定义\n "); }

| exp '+' exp { { if($1.valType ==1 && $3.valType ==1 ) { $$.valType =1 ;$$.inval.do= $1.inval.do + $3.inval.do ;}

else }

| exp '-' exp

| exp '*' exp

| exp '/' exp

| '-' exp %prec UMINUS

;

%%

int yyerror(char *s) {

printf("%s\n", s);

return 0;

}

int main(void) {

yyparse();

return 0;

}

int yylex() // 用lex实现如下的功能

{

int c; while ((c = getchar())==' ' || c=='\t'); if (c == '.' || isdigit(c)) { } ungetc(c,stdin); scanf("%lf",&yylval.val); return NUMDOU;

if(isalpha(c)){ ungetc(c,stdin); symbuf[i] = '\0'; // 还要能识别 int a 中的关键字 char symbuf[20]; int i=0; do{ symbuf[i] = c; i++; c = getchar(); }while(c != EOF && isalnum(c)); int,如果遇见int 返回 INTEGER

strcpy(yytext,symbuf); if (strcmp("double",yytext) == 0) return DOUBLE ; //遇见 double 返回 DOUBLE

} return ID; } if (c==EOF) return 0; return c;

本文来源:https://www.bwwdw.com/article/kebi.html

Top