96778997973编译原理实验指导书(新)

96778997973编译原理实验指导书(新)
96778997973编译原理实验指导书(新)

前言

编译原理是计算机科学与技术、软件工程等专业的主干课和必修课,由于这门课程相对抽象且内容较复杂,一直是比较难学的一门课程。在编译原理的学习过程中,实验非常重要,只有通过上机实验,才能使学生对比较抽象的课程内容产生一个具体的感性认识。但是,目前国内市场上很少有较详细且比较适合我院实际的实验指导书,为此,我们特编了这份指导书,希望能对我院的《编译原理》教案工作有所帮助。

本书实验环境主要为C环境(由于兼容性问题,建议使用Turboc2.0>及一个词法分析器自动生成工具FLEX和一个语法分析器自动生成工具BISON。书中给出的参考源程序也是C源程序,但由于实验者熟悉精通的语言工具不尽相同,因而强求采用统一的编程语言编程是不现实的。实验者在掌握了编译程序各个阶段的功能和原理之后,不难借助使用其他自己熟悉的语言实现相关功能。

实验者在实验过程中应该侧重写出自己在算法分析、设计思路、实现功能或程序代码等方面的特色,写出设计和实现过程中遭遇到的难点和解决办法,可以不拘泥于实验指导给出的参考性设计思路,尽可能在深度和广度上加以拓展。只有这种各具特色的实验报告,才将更有利于体现实验者在创新思维和动手能力上的差异。

通过这些实验,能使学生对这些部份的工作机理有一个详细的了解,达到“知其然,且知其所以然”的目的。并可在C环境下对自动生成工具生成的词法、语法分析器进行编译调试。

由于手工生成词法和语法分析器的工作量太大,在实际中常用自动生成工具来完成之。这些工具中最著名的当属贝尔实验室的词法分析器生成工具LEX和语法分析器生成工具YACC。它们现已成为UNIX的标准应用程序同UNIX一起发行。与此同时GNU推出与LEX完全兼容的FLEX,与YACC完全兼容的BISON。这两个程序都在Internet上以源代码的形式免费发行,所以很容易在其它操作系统下重新编译安装。我们实验采用的就是for dos的FLEX和BISON。本书有关的编译工具及其源程序例子,可到BISON的网站上下载。关于FLEX和BISON的用法简介,参见附录,如需更详细的介绍,请参阅编译工具中帮助文件。

关于实验学时和安排,任课教师可根据实际情况,选做其中的一部份。由于这门课实验难度较大,所以希望任课教师在实验前安排好学生的预习工作。在上机前要求学生写好实验预习报告。本书中c程序均在Turboc2.0下调试通过.LEX和YACC源程序均在FLEX和BISON下调试通过. 由于编者水平有限,本书中必然存在着不少缺点,在此恳请大家给予批评和指正,我们将尽力纠正。在此特对关心支持编写本书的院系领导表示感谢。

本书中关于LEX和YACC的部份大量参考引用了何炎祥老师主编,华中理工大学出版社出版的《编译原理》一书,在此表示衷心的感谢。

周鹏杨亚会梅琴赵榕

2006年8月

目录

实验一词法分析器设计0

实验三用FLEX自动生成PL/0词法分析器9 实验四用递归下降法进行表达式分析16

实验五用算符优先法进行表达式分析17

实验六利用BISON生成逆波兰表示计算器21 实验七利用BISON生成中缀表示计算器22 附录一词法分析器生成工具FLEX简介22

附录二语法分析器生成工具YACC简介28

实验一词法分析器设计

【实验目的】

1.掌握生成词法分析器的方法,加深对词法分析原理的理解。

2.掌握设计、编制并调试词法分析程序的思想和方法。

3.本实验是高级语言程序设计、数据结构和编译原理中词法分析原理等知识的综合。

【实验内容及要求】

1.选择一种熟悉的高级语言<如C语言,C++,VB或VC等),设计、编写、调试一个词法分析子程序。

2.待分析的源程序为一个简单的C语言程序,如下所示:

main(>

{ int x,a,b。

float y,c,d。

x = a + b。

y=c / d。

if(x>y>

x = 10。

else

y=100。

}

将该源程序的源文件经词法分析后输出以二元组形式表示的单词符号序列。

3.编写的程序具有一定的查错能力。提交的实验报告中要有实验名称、实验目的、实验内容、实验程序清单、调试过程和运行结果,程序的主要部分作出功能说明,并有实验收获体会或改进意见等内容。

4.实验前请仔细阅读实验预习提示,提示中程序仅供参考。

5.本实验建议学时数为4学时。

【实验预习提示】

1.词法分析器的功能和输出格式

词法分析器的功能是输入以字符串表示的源程序,输出单词符号或单词符号序列。词法分析器的单词符号常常表示成以下的二元组(单词的种别码,单词符号的属性值>。本实验中,采用的是一符一种种别码的方式。

2.调试程序文法的EBNF<扩展巴科斯范式)表示如下

<程序>::= main(><语句串>

<语句串>::=<语句> {;<语句>}

<语句>::=<赋值语句>|<条件语句>|<循环语句>

<赋值语句>::= <变量>=<表达式>

<条件语句>::= if<条件>then<语句>

<循环语句>::= while<条件><语句串>

<条件>::= <表达式><关系运算符><表达式>

<表达式>::= <项>{+<项>|—<项>}

<项>::= <因子>{*<因子>|/<因子>}

<无符号整数>::= <数字>{<数字>}

<变量>::=<标识符>

<标识符>::= <字母>{<字母>|<数字>|<下划线>}

<关系运算符>::= >|<|>=|<=|==|!=

<字母>::= A|B|C|……|Z|a|b|c|……|z (要求不区分大小写>

<数字>::= 0|1|2|3|4|5|6|7|8|9

3.“超前搜索”方法

词法分析时,常常会用到超前搜索方法。如当前待分析字符串为“a>+”,当前字符

为’>’,此时,分析器倒底是将其分析为大于关系运算符还是大于等于关系运算符

呢?显然,只有知道下一个字符是什么才能下结论。于是分析器读入下一个字

符’+’,这时可知应将’>’解释为大于运算符。但此时,超前读了一个字符’+’,

所以要回退一个字符,词法分析器才能正常运行。在分析标识符,无符号整数等时也有

类似情况。

4.词法分析程序主程序的算法思想

算法的基本思想是根据扫描到单词符号的第一个字符的种类,拼写出相应的单词符号,其

现的基本任务是从字符串表示的源程序中识别出相应的具有独立意义的单词符号。主程序示

意图如图1.1

图1.1 词法分析主程序示意图

其中设置初始值包括两个方面:

<1)关键字表的初值

关键字作为特殊标识符处理,把它们预先安排在一张表中,称这张表为关键字表,当扫描程序

识别出标识符时,查关键字表,若能查找到匹配的单词,则该单词是关键字,否则为一般标识

符。关键字表为一个字符串数组,其描述为:

char

*KEY_WORDS[8]={“main”,”int”, ”char”,”if”,”else”,”while”,”for”}。

<2)程序中需要用到的主要变量为syn,token和sum。

5.参考部分源程序

[1]globals.h /*本头文件定义分析器需要的一些数据结构和宏等*/

#ifndef _GLOBALS_H

#define _GLOBALS_H

#include

#include

#include

#define _SYN_MAIN 1

#define _SYN_INT 2

#define _SYN_CHAR 3

#define _SYN_IF 4

#define _SYN_ELSE 5

#define _SYN_FOR 6

#define _SYN_WHILE7

/*以上为关键字的单词种别码*/

#define _SYN_ID 10 /*标识符的单词种别码*/

#define _SYN_NUM 11 /*整数的单词种别码*/

#define _SYN_PLUS 13 /* 算术运算符“+”的单词种别码 */ #define _SYN_MINUS 14/* 算术运算符“-”的单词种别码 */ #define _SYN_TIMES 15/* 算术运算符“*”的单词种别码 */ #define _SYN_DIVIDE 16/* 算术运算符“/”的单词种别码 */ #define _SYN_ASSIGN 17 /* = */

#define _SYN_SEMICOLON 18 /* 。 */

#define _SYN_LT 20 /* < */

#define _SYN_NE 21 /* != */

#define _SYN_LE 22 /* <= */

#define _SYN_LG 23 /* > */

#define _SYN_ME 24 /* >= */

#define _SYN_EQ 25 /* = */

#define _SYN_LPAREN 28 /* ( */

#define _SYN_RPAREN 29 /* > */

#define _SYN_OVER 0 /* # 即源程序结束标志*/

#define MAXLENGTH 255/* 一行允许的字符个数 */

union WORDCONTENT {/*存放单词内容的联合*/

char T1[MAXLENGTH]。

int T2。

char T3。

}。

typedef struct WORD { /*单词二元组*/

int syn。

union WORDCONTENT value。

#endif

[2]scan.h/*本头文件定义词法分析器的接口*/

#ifndef _SCAN_H

#define _SCAN_H

#define _TAB_LEGNTH 4/*一个TAB占用的空格数*/

#define _KEY_WORD_END "waiting for expanding" /*关键字结束标志*/

void Scaner(void>。 /*函数scaner得到源程序里的下一个单词符号*/

#endif

[3]Symbol.c

#include "basedata.h"

#include "symbol.h"

#include

#include

#include

char *WORD[WORDLEN]={"BEGIN","CALL","CONST","DO", "END","IF","ODD","PROCEDURE",

"READ","THEN","VAR","WHILE",

"WRITE"

}。//保留字字符串表,用于将保留字种别码转为字符串输出SYMBOL WSYM[WORDLEN]={BEGINSYM,CALLSYM,CONSTSYM,

DOSYM,ENDSYM,IFSYM,ODDSYM,

PROCSYM,READSYM,THENSYM,

VARSYM,WHILESYM,WRITESYM}。//保留字种别码表

char* SNAME[SYMBOLNUM]= {"NOL","IDENT","NUMBER","PLUS","MINUS","TIMES",

"SLASH","ODDSYM","EQL","NEQ","LSS","LEQ","GTR",

"GEQ","LPAREN","RPAREN","COMMA","SEMICOLON",

"PERIOD","BECOMES","BEGINSYM","ENDSYM","IFSYM",

"THENSYM","WHILESYM","WRITESYM","READSYM",

"DOSYM","CALLSYM","CONSTSYM","VARSYM","PROCSYM"}。

//单词字符串表,用于将保留字种别码转为字符串输出

SYMBOL sym。//最近已识的单词种别码

char token[MAXIDLEN+1]。//最近已识别的单词

int num。//最近已识别的数字值

char ch。//最近已识别的字符

int col=1,row=1。//当前行和列值

FILE *fd。//指向待编译文件

extern FILE *fout。//指向存放结果文件

void Getchar(void>

{

ch=fgetc(fd>。

if(ch!=EOF && ch!='\n'>

col++。

return。

}

void Getbc(void>

{

while(ch==SPACE ||ch==TABLE ||ch=='\n'>

{

if(ch=='\n'> {row++。col=1。}

Getchar(>。

}//为空字符则一直读至不为空字符

}

void Retract(void>

{

fseek(fd,-1l,SEEK_CUR>。

col--。

}

void Concat(void>

{

char temp[2]。

temp[0]=ch。temp[1]='\0'。

strcat(token,temp>。

}

int Reserve(void>

{

int i,j。

char temp[60]。

j=strlen(token>。

for(i=0。i

{

temp[i]=toupper(token[i]>。//将当前token字以大写形式存入temp中 }

temp[i]='\0'。

for(i=0。i

{

if(!strcmp(WORD[i],temp>>

break。

}//判断当前token是否是保留字

if(i>=WORDLEN> i=-1。

return i。

}

void Errorsym(void>

{

fprintf(fout,

"There is error @row: %5d, @col: %5d",

row,col>。

}

int Getsym(void>

{

int k。

int flag=TRUE。

Getchar(>。

Getbc(>。//滤掉白字符

strcpy(token,"">。

if(isalpha(ch>>

{

//以字母开头则是标识符

num=0。

Concat(>。

Getchar(>。

while(isalnum(ch>>

{

Concat(>。

Getchar(>。

}

Retract(>。//由于超前搜索了,所以回退一个字符

k=Reserve(>。//判断此标识符是否是保留字

if(k!=-1>

{

sym=WSYM[k]。//将保留字种别码存入sym中

}

else

{

sym=IDENT。//将一般标识符种别码存入sym中

}//end else k!=-1。

}//end of if isalpha

{

//以数字开头则为无符号整数

Concat(>。

Getchar(>。

while(isdigit(ch>>

{

Concat(>。

Getchar(>。

}

if(isalpha(ch>>

{

flag=FALSE。

while(isalnum(ch>>

{

Concat(>。

Getchar(>。

}

}//end of flag=FALSE

Retract(>。//回退

if(flag>//若是无符号整数,则将整数值存于num中 {sym=NUMBER。num=atoi(token>。}

}//end of if isdigit

else

{

num=0。

switch (ch>

{

case '+':Concat(>。sym=PLUS。break。

case '-':Concat(>。sym=MINUS。break。

case '*':Concat(>。sym=TIMES。break。

case '/':Concat(>。sym=SLASH。break。

case '(':Concat(>。sym=LPAREN。break。

case '>':Concat(>。sym=RPAREN。break。

case '=':Concat(>。sym=EQL。break。

case '#':Concat(>。sym=NEQ。break。

/*

ODDSYM,EQL,NEQ,LSS,LEQ,GTR,GEQ,LPAREN,

RPAREN,COMMA,SEMICOLON,PERIOD,BECOMES,

*/

case ',':Concat(>。sym=COMMA。break。

case '.':Concat(>。sym=PERIOD。break。

case '。':Concat(>。sym=SEMICOLON。break。

case '>':

Concat(>。Getchar(>。

{sym=GTR。Retract(>。}

else

{Concat(>。sym=GEQ。}

break。

case '<':Concat(>。Getchar(>。

if(ch!='='>

{sym=LSS。Retract(>。}

else

{Concat(>。sym=LEQ。}

break。

case ':':Concat(>。Getchar(>。

if(ch!='='>

{flag=FALSE。Retract(>。}

else

{Concat(>。sym=BECOMES。}

break。

default :Concat(>。flag=FALSE。break。

}//end of switch else char

}//end of else char

return flag。

}

[4]Testsym.c

#include "basedata.h"

#include "symbol.h"

#include

extern char *WORD[WORDLEN]。

extern int WSYM[WORDLEN]。

extern char* SNAME[SYMBOLNUM]。

extern SYMBOL sym。//last readed word type。

extern char token[MAXIDLEN+1]。//last readed word extern int num。//last readed num。

extern char ch。//last readed char。

extern int col,row。

extern FILE *fd。

FILE *fout。

void Init(void>。

void Quit(void>。

{

int flag。

Init(>。

fprintf(fout,"\n TOKEN SYM NUM">。

do{

flag=Getsym(>。

if(flag>

{

fprintf(fout,"\n%10s %10s %d",token,SNAME[sym],num>。

}

else if(ch!=EOF>

{

fprintf(fout,"\n%10s",token>。

Errorsym(>。

}

}while(ch!=EOF>。//反复调用Getsym(>识别单词,将输出结果存入fout中Quit(>。

}

//======================================

void Init(void>

{

char temp[30]。

printf("\nPlease input your file name:">。

gets(temp>。

if ((fd = fopen(temp,"rt">>

== NULL>

{

fprintf(stderr, "Cannot open input file %s.\n",temp>。

getch(>。

return 。

}//将fd指针指向待分析源文件

if ((fout = fopen("mydata.dat", "wt">>

== NULL>

{

fprintf(stderr, "Cannot open input file.\n">。

getch(>。

return 。

}//将fout指向文件mydata.dat

}

void Quit(void>

fclose(fd>。

fclose(fout>。

}

实验二熟悉FLEX使用方法

【实验目的】

1.掌握FLEX基本使用方法

2.掌握如何将通过FLEX生成的C语言模块加入到自已的程序中

【实验要求】

1.编制FLEX源程序,分别统计文本文件a.txt中出现的标识符和整数个数,并显示之。

标识符定义为字母开头,后跟若干个字母,数字或下划线。整数可以带+或-号,也可

不带,且不以0开头。非单词和非整数则忽略不记,将之滤掉不显示。

2.编制一FLEX源程序,分别求出文件hh.c中字母,数字,回车符的个数。

3.思考:若main函数不在FLEX中实现,应该如何实现?

4.本次实验建议学时2学时。

【实验预习提示】

参见附录一。在看懂的基础上将之调试通过。

实验三用FLEX自动生成PL/0词法分析器【实验目的】

熟练掌握FLEX,并通过其生成一个词法分析器

【实验要求】

1.通过FLEX生成一词法分析器函数int Getsym(>,其功能同实验一中词法分析器函数类似。

2.生成一工程文件,调用1中生成的函数Getsym(>,对一指定的文件进行词法分析,要求分析出单词的类型和值。并将分析结果存入一文件Mydata.dat中。

3.本实验建议学时4学时。

【实验预习提示】

FLEX可自动生成函数int yylex(>,则int Getsym(>可通过调用yylex(>实现。

1.由于FLEX生成的C程序模块lex.yy.c过于复杂,基本不可读,所以不要直接修改它,可将它看成一个“黑箱”,即不需要清楚知道其内部结构,只需要知道其接口

即可。可通过修改FLEX源程序间接修改之。关于lex.yy.c中常用变量和函数,在

附录中有详细说明。

2.编制一FLEX源程序,不妨取名为sym.l,通过FLEX生成lex.yy.c,并将之加入到工程文件中。

生成一工程文件,不妨取名为test.prj,将文件Symbol.c,lex.yy.c,testsym.c 加入之。源程序参考如下:

[1]Basedata.h

同实验一中Basedata.h

[2]Symbol.h

#include

#include

#define WORDLEN 13 /*保留字个数*/

#define MAXIDLEN 50 /*标识符最长长度*/

#define SYMBOLNUM 32 /*种别码个数*/

typedef enum SYMBOL

{NOL,IDENT,NUMBER,PLUS,MINUS,TIMES,SLASH,

ODDSYM,EQL,NEQ,LSS,LEQ,GTR,GEQ,LPAREN,

RPAREN,COMMA,SEMICOLON,PERIOD,BECOMES,

BEGINSYM,ENDSYM,IFSYM,THENSYM,WHILESYM,

WRITESYM,READSYM,DOSYM,CALLSYM,CONSTSYM,

VARSYM,PROCSYM} SYMBOL。/*定义种别码*/

int Reserve(void>。

/*判断token字中单词是否是保留字*/

int Getsym(void>。

/*从当前文件中识别出一单词,并给出其类型和值*/

void MyError(void>。

/*打印错误信息*/

#endif

[3]symbol.c

#include "Basedata.h"

#include "Symbol.h"

#include

#include

#include

char *WORD[WORDLEN]={"BEGIN","CALL","CONST","DO", "END","IF","ODD","PROCEDURE",

"READ","THEN","VAR","WHILE",

}。/*保留字字符串表,用于将保留字种别码转为字符串输出*/

SYMBOL WSYM[WORDLEN]={BEGINSYM,CALLSYM,CONSTSYM,

DOSYM,ENDSYM,IFSYM,ODDSYM,

PROCSYM,READSYM,THENSYM,

VARSYM,WHILESYM,WRITESYM}。/*保留字种别码表*/

char* SNAME[SYMBOLNUM]=

{"NOL","IDENT","NUMBER","PLUS","MINUS","TIMES",

"SLASH","ODDSYM","EQL","NEQ","LSS","LEQ","GTR",

"GEQ","LPAREN","RPAREN","COMMA","SEMICOLON",

"PERIOD","BECOMES","BEGINSYM","ENDSYM","IFSYM",

"THENSYM","WHILESYM","WRITESYM","READSYM",

"DOSYM","CALLSYM","CONSTSYM","VARSYM","PROCSYM"}。

/*单词字符串表,用于将保留字种别码转为字符串输出*/

SYMBOL sym。/*最近已识的单词种别码*/

char token[MAXIDLEN+1]。/*最近已识别的单词*/

int num。/*最近已识别的数字值*/

char ch。/*最近已识别的字符*/

int col=1,row=1。/*当前行和列值*/

int k。

int flag。

extern FILE *yyin, *yyout。

extern int yylex(void>。

int Reserve(void>

{

int i,j。

char temp[60]。

j=strlen(token>。

for(i=0。i

{

temp[i]=toupper(token[i]>。/*将当前token字以大写形式存入temp中*/

}

temp[i]='\0'。

for(i=0。i

{

if(!strcmp(WORD[i],temp>>

break。

}/*判断当前token是否是保留字*/

if(i>=WORDLEN> i=-1。

}

void MyError(void>

{

fprintf(yyout,

"There is error @row: %5d, @col: %5d",

row,col>。

}

int Getsym(void>

{

return yylex(>。

}

[4]Testsym.c

#include "Basedata.h"

#include "Symbol.h"

#include

extern char *WORD。

extern SYMBOL WSYM[WORDLEN]。

extern char* SNAME[SYMBOLNUM]。

extern SYMBOL sym。

extern char token[MAXIDLEN+1]。

extern int num。

extern char ch。

extern int col,row。

extern int k。

extern int flag。

extern FILE *yyin,*yyout。

void Init(void>。

void Quit(void>。

void main(>

{

int flag。

Init(>。

if(!yyin>

return。

fprintf(yyout,"\n TOKEN SYM NUM">。 do{

if(flag==ENDFILE>

return。

if(flag>

{

fprintf(yyout,"\n%10s%10s %d",token,SNAME[sym],num>。

}

else

{

fprintf(yyout,"\n%10s",token>。

MyError(>。

}

}while(ch!=EOF>。/*反复调用Getsym(>识别单词,将输出结果存入fout 中*/

Quit(>。

}

/*======================================*/

void Init(void>

{

char temp[30]。

printf("\nPlease input your file name:">。

gets(temp>。

if ((yyin = fopen(temp,"rt">>

== NULL>

{

fprintf(stderr, "Cannot open input file %s.\n",temp>。

getch(>。

return 。

}/*将fd指针指向待分析源文件*/

if ((yyout = fopen("mydata.dat", "wt">>

== NULL>

{

fprintf(stderr, "Cannot open input file.\n">。

getch(>。

return 。

}/*将fout指向文件mydata.dat*/

}

void Quit(void>

{

fclose(yyin>。

fclose(yyout>。

}

[5]FLEX 源程序sym.l

%{

#include "Basedata.h"

#include "Symbol.h"

#include

#include

#include

extern char *WORD。

extern SYMBOL WSYM[WORDLEN]。

extern char* SNAME[SYMBOLNUM]。

extern SYMBOL sym。

extern char token[MAXIDLEN+1]。

extern int num。

extern char ch。

extern int col,row。

extern int k。

extern int flag。

%}

%%

[\t] {col+=8。}

[\n] {row+=1。col=1。}

[ ] {

col+=1。/*空格则列位置加1*/

}

[a-zA-Z][a-zA-Z_0-9]* {

num=0。

strcpy(token,yytext>。

/*将当前识别出字符串转为大写形式后存入token*/

k=Reserve(>。/*判断此标识符是否是保留字*/

if(k!=-1>

{

sym=WSYM[k]。/*将保留字种别码存入sym中*/

}

else

{

}/*end else k!=-1。 */

col+=strlen(token>。/*改变列位置*/

flag=TRUE。

return flag。

/*识别出一个单词,退出yylex,下次再调用时*/

/*从当前位置再继续分析 */

}

[0-9][0-9]* {

strcpy(token,yytext>。

sym=NUMBER。num=atoi(token>。

/*若是无符号整数,则将整数值存于num中*/

col+=strlen(token>。/*改变列位置*/

flag=TRUE。

return flag。

}

[+] {strcpy(token,yytext>。num=0。sym=PLUS。flag=TRUE。col++。return flag。} [-] {strcpy(token,yytext>。num=0。sym=MINUS。flag=TRUE。col++。return flag。}

[*] {strcpy(token,yytext>。num=0。sym=TIMES。flag=TRUE。col++。return flag。}

\( {strcpy(token,yytext>。num=0。sym=LPAREN。flag=TRUE。col++。return flag。} [/] {strcpy(token,yytext>。num=0。sym=SLASH。flag=TRUE。col++。return flag。} \>{strcpy(token,yytext>。num=0。sym=RPAREN。flag=TRUE。col++。return flag。}

[=] {strcpy(token,yytext>。num=0。sym=EQL。flag=TRUE。col++。return flag。}

[#] {strcpy(token,yytext>。num=0。sym=NEQ。flag=TRUE。col++。return flag。}

[,]{strcpy(token,yytext>。num=0。sym=COMMA。flag=TRUE。col++。return flag。}

[.] {strcpy(token,yytext>。num=0。sym=PERIOD。flag=TRUE。col++。return flag。}

[。] {strcpy(token,yytext>。num=0。sym=SEMICOLON。flag=TRUE。col++。return flag。}

[>] {strcpy(token,yytext>。num=0。sym=GTR。flag=TRUE。col++。return flag。}

">=" {strcpy(token,yytext>。num=0。sym=GEQ。flag=TRUE。col+=2。return flag。}

[<] {strcpy(token,yytext>。num=0。sym=LSS。flag=TRUE。col++。return flag。}

"<=" {strcpy(token,yytext>。num=0。sym=LEQ。flag=TRUE。col+=2。return flag。}

":=" {strcpy(token,yytext>。num=0。sym=BECOMES。flag=TRUE。col+=2。return flag。}

<> {flag=ENDFILE。return flag。}

. {

strcpy(token,yytext>。

col+=strlen(yytext>。/*改变列位置*/

flag=FALSE。

}

%%

int yywrap(>

{

return 1。

}

实验四用递归下降法进行表达式分析【实验目的】

1.掌握用递归下降分析法进行语法分析的方法。加深对自顶向下语法分析原理的理解。

2.掌握设计、编制并调试自顶向下语法分析程序的思想和方法。

3.本实验是高级语言程序设计、数据结构和编译原理中词法分析、自顶向下语法分析原理等知

识的综合。由于语法分析是在词法分析的基础上进行的,且词法分析器输出的结果即单词符号

或单词符号序列是语法分析的输入。

【实验要求】

已知表达式文法的扩充巴克斯范式为

S->E#

E->T{+T | -T}

T->F{*F | /F}

F->(E> | i

上式中,#可用文件结束符Ctrl+z代替。i为整数。

从键盘输入表达式,利用递归下降法求出其值,如输入表达式有错,则给出报错提示。

例:输入表达式串为:13+5*4则应给出结果为33。

本实验建议学时2学时。

【实验预习提示】

1、词法分析器可用以前所编的的int Getsym(void>函数。

2、自编工程文件,仿照前面几次实验对要用到的文件进行组织。

3、对表达式文法中每一非终结符均可通过一个函数进行识别,现就非终结符S和E的函数

提示如下。其它非

4、终结符对应的函数自编之。

int S(void>

{

int a。

a=E(>。

if(flag==ENDFILE>

return a。

else

}

int E(void>

{

int a,b。

SYMBOL t。

a=T(>。

while (sym==PLUS || sym==MINUS>

{

t=sym。

flag=Getsym(>。

if(!flag>

{

MyError(>。

exit(0>。

}

b=T(>。

if (t==PLUS>

a=a+b。

else

a=a-b。

}

return a。

}

实验五用算符优先法进行表达式分析【实验目的】

1.掌握用算符优先分析法进行语法分析的方法。加深对自底向上语法分析原理的理解。

2.掌握设计、编制并调试自底向上语法分析程序的思想和方法。

3.本实验是高级语言程序设计、数据结构和编译原理中词法分析、自底向上语法分析原理等知

识的综合。由于语法分析是在词法分析的基础上进行的,且词法分析器输出的结果即单词符

号或单词符号序列是语法分析的输入。

【实验要求】

从键盘输入表达式,利用递归下降法求出其值,如输入表达式有错,则给出报错提示。表达式以;结尾。例:以于如下的输入表达式串: 13+5*4;则应给出结果为33。

【实验提示】

1.实验原理

我们要分析的表达式满足下面的算符优先矩阵

编译原理实验指导

编译原理实验指导 实验安排: 上机实践按小组完成实验任务。每小组三人,分别完成TEST语言的词法分析、语法分析、语义分析和中间代码生成三个题目,语法分析部分可任意选择一种语法分析方法。先各自调试运行,然后每小组将程序连接在一起调试,构成一个相对完整的编译器。 实验报告: 上机结束后提交实验报告,报告内容: 1.小组成员; 2.个人完成的任务; 3.分析及设计的过程; 4.程序的连接; 5.设计中遇到的问题及解决方案; 6.总结。

实验一词法分析 一、实验目的 通过设计编制调试TEST语言的词法分析程序,加深对词法分析原理的理解。并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。 编制一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本字、标识符、常数、运算符、分隔符五大类。并依次输出各个单词的内部编码及单词符号自身值。 二、实验预习提示 1.词法分析器的功能和输出格式 词法分析器的功能是输入源程序,输出单词符号。词法分析器的单词符号常常表示 成以下的二元式(单词种别码,单词符号的属性值)。 2.TEST语言的词法规则 |ID|ID |NUM →a|b|…|z|A|B|…|Z →1|2|…|9|0 →+|-|*|/|=|(|)|{|}|:|,|;|<|>|! →>=|<=|!=|== →/* →*/ 三、实验过程和指导 1.阅读课本有关章节,明确语言的语法,画出状态图和词法分析算法流程图。 2.编制好程序。 3.准备好多组测试数据。 4.程序要求 程序输入/输出示例:

编译原理实验报告实验一编写词法分析程序

编译原理实验报告实验名称:实验一编写词法分析程序 实验类型:验证型实验 指导教师:何中胜 专业班级:13软件四 姓名:丁越 学号: 电子邮箱: 实验地点:秋白楼B720 实验成绩: 日期:2016年3 月18 日

一、实验目的 通过设计、调试词法分析程序,实现从源程序中分出各种单词的方法;熟悉词法分析 程序所用的工具自动机,进一步理解自动机理论。掌握文法转换成自动机的技术及有穷自动机实现的方法。确定词法分析器的输出形式及标识符与关键字的区分方法。加深对课堂教学的理解;提高词法分析方法的实践能力。通过本实验,应达到以下目标: 1、掌握从源程序文件中读取有效字符的方法和产生源程序的内部表示文件的方法。 2、掌握词法分析的实现方法。 3、上机调试编出的词法分析程序。 二、实验过程 以编写PASCAL子集的词法分析程序为例 1.理论部分 (1)主程序设计考虑 主程序的说明部分为各种表格和变量安排空间。 数组 k为关键字表,每个数组元素存放一个关键字。采用定长的方式,较短的关键字 后面补空格。 P数组存放分界符。为了简单起见,分界符、算术运算符和关系运算符都放在 p表中 (编程时,还应建立算术运算符表和关系运算符表,并且各有类号),合并成一类。 id和ci数组分别存放标识符和常数。 instring数组为输入源程序的单词缓存。 outtoken记录为输出内部表示缓存。 还有一些为造表填表设置的变量。 主程序开始后,先以人工方式输入关键字,造 k表;再输入分界符等造p表。 主程序的工作部分设计成便于调试的循环结构。每个循环处理一个单词;接收键盘上 送来的一个单词;调用词法分析过程;输出每个单词的内部码。 ⑵词法分析过程考虑 将词法分析程序设计成独立一遍扫描源程序的结构。其流程图见图1-1。 图1-1 该过程取名为 lexical,它根据输入单词的第一个字符(有时还需读第二个字符),判断单词类,产生类号:以字符 k表示关键字;i表示标识符;c表示常数;p表示分界符;s表示运算符(编程时类号分别为 1,2,3,4,5)。 对于标识符和常数,需分别与标识符表和常数表中已登记的元素相比较,如表中已有 该元素,则记录其在表中的位置,如未出现过,将标识符按顺序填入数组id中,将常数 变为二进制形式存入数组中 ci中,并记录其在表中的位置。 lexical过程中嵌有两个小过程:一个名为getchar,其功能为从instring中按顺序取出一个字符,并将其指针pint加1;另一个名为error,当出现错误时,调用这个过程, 输出错误编号。 2.实践部分

编译原理实验指导书2010

《编译原理》课程实验指导书 课程编号: 课程名称:编译原理/Compiler Principles 实验总学时数: 8 适用专业:计算机科学与技术、软件工程 承担实验室:计算机学院计算机科学系中心实验室、计算机技术系中心实验室 一、实验教学的目的与要求 上机实习是对学生的一种全面综合训练,是与课堂听讲、自学和练习相辅相成的必不可少的一个教学环节。通常,实习题中的问题比平时的练习题要复杂,也更接近实际。编译原理这门课程安排的2次上机实验都属于一种设计类型的实验,每个实验的训练重点在于基本的编译技术和方法,而不强调面面俱到;实验的目的是旨在使学生进一步巩固课堂上所学的理论知识,深化理解和灵活掌握教学内容;培养学生编制算法的能力和编程解决实际问题的动手能力。 要求学生在上机前应认真做好各种准备工作,熟悉机器的操作系统和语言的集成环境,独立完成算法设计和程序代码的编写;上机时应随带有关的编译原理教材或参考书;要学会程序调试与纠错。 每次实验后要交实验报告,实验报告的内容应包括: (1)实验题目、班级、学号、姓名、完成日期; (2)简要的需求分析与概要设计; (3)详细的算法描述; (4)源程序清单; (5)给出软件的测试方法和测试结果; (6)实验的评价、收获与体会。 开发工具: (1)DOS环境下使用Turbo C; (2)Windows环境下使用Visual C++ 。 考核: 实验成绩占编译原理课程结业成绩的10%。 三、单项实验的内容和要求: 要求每个实验保证每个学生一台微机。 实验一(4学时):单词的词法分析程序设计。 (一)目的与要求 1.目的 通过设计、编制、调试一个具体的词法分析程序,加深对词法分析原理的理解,并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。

编译原理实验报告

编译原理实验报告 姓名: 学号: 班级: 学院: 南昌大学信息工程学院计算机系 2014年6月

目录 实验一 (3) 实验二 (8) 实验三 (15)

实验1 词法分析程序的设计 学生姓名:学号:专业班级: 实验类型:□验证□综合□设计□创新实验日期:实验成绩: 一、实验目的 掌握计算机语言的词法分析程序的开发方法。 二、实验内容 编制一个能够分析三种整数、标识符、主要运算符和主要关键字的词法分析程序。 三、实验要求 1、根据以下的正规式,编制正规文法,画出状态图; 标识符<字母>(<字母>|<数字字符>)* 十进制整数0 |(1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)* 如有余力,则进一步分析八进制和十六进制整数,其正规式如下: 八进制整数0(1|2|3|4|5|6|7)(0|1|2|3|4|5|6|7)* 十六进制整数0x(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)* 运算符和界符+ - * / > < =<= >=( ) ;{ } 关键字main if then else while do int (可根据需要添加) 2、根据状态图,设计词法分析函数int scan( ),完成以下功能: 1)从文本文件中读入测试源代码,根据状态转换图,分析出一个单词, 2)以二元式形式输出单词<单词种类,单词属性> 其中单词种类用整数表示: 0:标识符 1:十进制整数 2:八进制整数 3:十六进制整数 运算符和界符,关键字采用一字一符,不编码 其中单词属性表示如下: 标识符,整数由于采用一类一符,属性用单词表示 运算符和界符,关键字采用一字一符,属性为空 3、编写测试程序,反复调用函数scan( ),输出单词种别和属性。 四、实验环境 PC微机 DOS操作系统或Windows 操作系统 Turbo C 程序集成环境或Visual C++ 程序集成环境

《编译原理》实验指导书-2015

武汉科技大学计算机科学与技术学院 编译原理实验指导书

实验一词法分析器设计 【实验目的】 1.熟悉词法分析的基本原理,词法分析的过程以及词法分析中要注意的问题。 2.复习高级语言,进一步加强用高级语言来解决实际问题的能力。 3.通过完成词法分析程序,了解词法分析的过程。 【实验内容】 用C语言编写一个PL/0词法分析器,为语法语义分析提供单词,使之能把输入的字符串形式的源程序分割成一个个单词符号传递给语法语义分析,并把分析结果(基本字,运算符,标识符,常数以及界符)输出。 【实验要求】 1.要求绘出词法分析过程的流程图。 2.根据词法分析的目的以及内容,确定完成分析过程所需模块。 3.写出每个模块的源代码,并给出注释。 4.整理程序清单及所得结果。 【说明】 运行成功以后,检查程序,并将运行结果截图打印粘贴到实验报告上。 辅助库函数scanerLib设计以及使用说明: 下面内容给出了一个辅助库函数的接口说明以及具体实现。 接口设计 //字符类 class Token { TokenType type; String str; Int line; } //词法分析结果输出操作类 class TokenWriter { ArrayList tokens; //用来记录所识别出来的token TokenWriter(); //构造函数指定输入文件名,创建文件输出流 V oid Add(Token); //将词法分析器中分析得到的Token添加到tokens中 WriteXML(); //将tokens写出到目标文件.xml中 } //词法分析操作词法分析生成文件接口<暂时不需要对该类的操作;下一步做语法分析的时候使用> class TokenReader

编译原理实验报告

编译原理实验报告 班级 姓名: 学号: 自我评定:

实验一词法分析程序实现 一、实验目的与要求 通过编写和调试一个词法分析程序,掌握在对程序设计语言的源程序进行扫描的过程中,将字符形式的源程序流转化为一个由各类单词符号组成的流的词法分析方法。 二、实验内容 根据教学要求并结合学生自己的兴趣和具体情况,从具有代表性的高级程序设计语言的各类典型单词中,选取一个适当大小的子集。例如,可以完成无符号常数这一类典型单词的识别后,再完成一个尽可能兼顾到各种常数、关键字、标识符和各种运算符的扫描器的设计和实现。 输入:由符合或不符合所规定的单词类别结构的各类单词组成的源程序。 输出:把单词的字符形式的表示翻译成编译器的内部表示,即确定单词串的输出形式。例如,所输出的每一单词均按形如(CLASS,VALUE)的二元式编码。对于变量和常数,CLASS字段为相应的类别码;VALUE字段则是该标识符、常数的具体值或在其符号表中登记项的序号(要求在变量名表登记项中存放该标识符的字符串;常数表登记项中则存放该常数的二进制形式)。对于关键字和运算符,采用一词一类的编码形式;由于采用一词一类的编码方式,所以仅需在二元式的CLASS字段上放置相应的单词的类别码,VALUE字段则为“空”。另外,为便于查看由词法分析程序所输出的单词串,要求在CLASS字段上放置单词类别的助记符。 三、实现方法与环境 词法分析是编译程序的第一个处理阶段,可以通过两种途径来构造词法分析程序。其一是根据对语言中各类单词的某种描述或定义(如BNF),用手工的方式(例如可用C语言)构造词法分析程序。一般地,可以根据文法或状态转换图构造相应的状态矩阵,该状态矩阵同控制程序便组成了编译器的词法分析程序;也可以根据文法或状态转换图直接编写词法分析程序。构造词法分析程序的另外一种途径是所谓的词法分析程序的自动生成,即首先用正规式对语言中的各类单词符号进行词型描述,并分别指出在识别单词时,词法分析程序所应进行的语义处理工作,然后由一个所谓词法分析程序的构造程序对上述信息进行加工。如美国BELL实验室研制的LEX就是一个被广泛使用的词法分析程序的自动生成工具。 总的来说,开发一种新语言时,由于它的单词符号在不停地修改,采用LEX等工具生成的词法分析程序比较易于修改和维护。一旦一种语言确定了,则采用手工编写词法分析程序效率更高。 四、实验设计 1)题目1:试用手工编码方式构造识别以下给定单词的某一语言的词法分析程序。 语言中具有的单词包括五个有代表性的关键字begin、end、if、then、else;标识符;整型常数;六种关系运算符;一个赋值符和四个算术运算符。参考实现方法简述如下。 单词的分类:构造上述语言中的各类单词符号及其分类码表。 表I 语言中的各类单词符号及其分类码表 单词符号类别编码类别码的助记符单词值

编译原理实验报告一 简单样本语言的词法分析器

理工大学信息工程与自动化学院学生实验报告 (2012 —2013学年第一学期) 一、实验目的及容 编译技术是理论与实践并重的课程,而其实验课要综合运用所学的多门课程的容,用来完成一个小型编译程序。从而巩固和加强对词法分析、语法分析、语义分析、代码生成和报错处理等理论的认识和理解;培养学生对完整系统的独立分析和设计的能力,进一步培养学生的独立编程能力。 调试并完成一个词法分析程序,加深对词法分析原理的理解。 二、实验原理及基本技术路线图(框原理图或程序流程图) 1、待分析的简单语言的词法 (1)关键字: begin if then while do end 所有关键字都是小写。 (2)运算符和界符: := + –* / < <= <> > >= = ; ( ) #

(3)其他单词是标识符(ID)和整型常数(NUM),通过以下正规式定义:ID=letter(letter| digit)* NUM=digit digit * (4)空格由空白、制表符和换行符组成。空格一般用来分隔ID、NUM,运算符、界符和关键字,词法分析阶段通常被忽略。 2、各种单词符号对应的种别码 3、词法分析程序的功能 输入:所给文法的源程序字符串。 输出:二元组(syn,token或sum)构成的序列。 其中:syn为单词种别码; token为存放的单词自身字符串; sum为整型常数。 二、所用仪器、材料(设备名称、型号、规格等或使用软件)

1台PC以及VISUAL C++6.0软件。 三、实验法、步骤(或:程序代码或操作过程) (1)程序代码: #include #include #include char prog[80],token[8]; char ch; int syn,p,m=0,n,row,sum=0; char *rwtab[6]={"begin","if","then","while","do","end"}; void scaner() { for(n=0;n<8;n++) token[n]=NULL; ch=prog[p++]; while(ch==' ') { ch=prog[p]; p++; } if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')) { m=0; while((ch>='0'&&ch<='9')||(ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')) { token[m++]=ch; ch=prog[p++]; } token[m++]='\0'; p--; syn=10; for(n=0;n<6;n++)

编译原理综合实验题

编译原理综合实验指导书 一、实验任务 设计、编制并调试一个中缀表达转换为后缀表达的实验程序,加深对词法分析、语法分析、语义分析及代码生成的理解。 二、实验内容 1、词法 输入:扩展ASCII码字符集字符。除大小写26英文字母(letter)和数字0-9(digit)以及+ - * / ^ = ; , ( )以外,所有其他字符一律按等同于空格处理,一般用来分隔单词。 输出:识别单词,单词包括关键字、运算符、界符、标识符和整型常数。 (1)关键字:var (2)运算符和界符:+ - * / ^ = ; , ( ) 其中:乘除运算符(*, /)返回具有不同属性值的单词mulop, 加减运算符(+, -)返回具有不同属性值的单词addop。 (3)标识符(id)和整型常数(num): 标识符(id)和整型常数(num)最大长度为8个字符,定义如下。 id = letter (letter | digit)* num = digit digit* 2、语法 根据输入的单词序列,分析是否符合语法规则,如果不符合,应指明位置与理由;如果符合,则执行相应的语义子程序完成语义分析及中缀表达转换为后缀表达的过程。需注意的是,这里给出的是二义文法,从语义上考虑,表达式的计算按先幂次运算(^),再乘除运算(*, /)的最后加减运算(+, - )的优先顺序;括号((, ))用于调整运算先后顺序,既括号内部分先计算;赋值运算(=)最后进行。本实验系统的语法规则是: program → compound compound → declaration assignstatement compound | ε declaration → var identifier_list ; | ε dentifier_list →id, dentifier_list | id assignstatement →id= expression ; | ε expression → expression addop expression | expression mulop expression | expression ^ expression | ( expression ) | id | num 3、语义分析及代码生成 语义分析的主要任务是判断变量是否先定义后使用。代码生成的的主要任务是将赋值语句从中缀表达转换为后缀表达。

编译原理实验指导书

编译原理 实 验 指 导 书 作者:莫礼平 2011年3月

实验一简单词法分析程序设计 一、实验目的 了解词法分析程序的基本构造原理,掌握词法分析程序的手工构造方法。 二、实验内容 1、了解编译程序的词法分析过程。 2、根据PASCAL语言的说明语句形式,用手工方法构造一个对说明语句进行词法分析的程序。该程序能对从键盘输入或从文件读入的形如: “const count=10,sum=81.5,char1=’f’,string1=”hj”, max=169;” 的常量说明串进行处理,分析常量说明串中各常量名、常量类型及常量值,并统计各种类型常量个数。 三、实验要求 1、输入的常量说明串,要求最后以分号作结束标志; 2、根据输入串或读入的文本文件中第一个单词是否为“const”判断输入串或文本文件是否为常量说明内容; 3、识别输入串或打开的文本文件中的常量名。常量名必须是标识符,定义为字母开头,后跟若干个字母,数字或下划线; 4、根据各常量名紧跟等号“=”后面的内容判断常量的类型。其中:字符型常量定 义为放在单引号内的一个字符;字符串常量定义为放在双引号内所有内容;整型常量定 义为带或不带+、- 号,不以0开头的若干数字的组合;实型常量定义为带或不带+、- 号, 不以0开头的若干数字加上小数点再后跟若干数字的组合; 5、统计并输出串或文件中包含的各种类型的常量个数; 6、以二元组(类型,值)的形式输出各常量的类型和值; 7、根据常量说明串置于高级语言源程序中时可能出现的错误情况,模仿高级语言编 译器对不同错误情况做出相应处理。 四、运行结果 1、输入如下正确的常量说明串: const count=10,sum=81.5,char1=‘f’,max=169,str1=“h*54 2..4S!AAsj”, char2=‘@’,str2=“aa!+h”; 输出: count(integer,10) sum(float,81.5) char1(char, ‘f’) max(integer,169) str1(string,“h*54 2..4S!AAsj”) char2(char, ‘@’) str2(string,“aa!+h”) int_num=2; char_num=2; string_num=2; float_num=1. 2、输入类似如下的保留字const错误的常量说明串: Aconstt count=10,sum=81.5,char1=‘f’; 输出类似下面的错误提示信息:

编译原理实验报告总结

学年第学期《编译原理》实验报告 学院(系):计算机科学与工程学院 班级:11303070A 学号:11303070*** 姓名:无名氏 指导教师:保密式 时间:2016 年7 月

目录 1.实验目的 (1) 2.实验内容及要求 (1) 3.实验方案设计 (1) 3.1 编译系统原理介绍 (1) 3.1.1 编译程序介绍 (2) 3.1.2 对所写编译程序的源语言的描述 (2) 3.2 词法分析程序的设计 (3) 3.3 语法分析程序设计 (4) 3.4 语义分析和中间代码生成程序的设计 (4) 4. 结果及测试分析 (4) 4.1软件运行环境及限制 (4) 4.2测试数据说明 (5) 4.3运行结果及功能说明 (5) 5.总结及心得体会 (7)

1.实验目的 根据Sample语言或者自定义的某种语言,设计该语言的编译前端。包括词法分析,语法分析、语义分析及中间代码生成部分。 2.实验内容及要求 (1)词法分析器 输入源程序,输出对应的token表,符号表和词法错误信息。按规则拼单词,并转换成二元形式;滤掉空白符,跳过注释、换行符及一些无用的符号;进行行列计数,用于指出出错的行列号,并复制出错部分;列表打印源程序;发现并定位词法错误; (2)语法分析器 输入token串,通过语法分析,寻找其中的语法错误。要求能实现Sample 语言或自定义语言中几种最常见的、基本的语法单位的分析:算术表达式、布尔表达式、赋值语句、if语句、for语句、while语句、do while语句等。 (3)语义分析和中间代码生成 输入token串,进行语义分析,修改符号表,寻找其中的语义错误,并生 成中间代码。要求能实现Sample语言或自定义语言中几种最常见的、基本的语法单位的分析:算术表达式、布尔表达式、赋值语句、if语句、for语句、while 语句、do while语句等。 实验要求:功能相对完善,有输入、输出描述,有测试数据,并介绍不足。3.实验方案设计 3.1 编译系统原理介绍 编译器逐行扫描高级语言程序源程序,编译的过程如下: (1).词法分析 识别关键字、字面量、标识符(变量名、数据名)、运算符、注释行(给人看的,一般不处理)、特殊符号(续行、语句结束、数组)等六类符号,分别归类等待处理。 (2).语法分析 一个语句看作一串记号(Token)流,由语法分析器进行处理。按照语言的文法检查判定是否是合乎语法的句子。如果是合法句子就以内部格式保存,否则报错。直至检查完整个程序。 (3).语义分析 语义分析器对各句子的语法做检查:运算符两边类型是否相兼容;该做哪些类型转换(例如,实数向整数赋值要"取整");控制转移是否到不该去的地方;是

编译原理实验报告5

编译原理实验报告五年月日 姓名学号姓名学号 系年级 2012级专业计算机科目编译原理 题目验证Yacc的使用 实验目的 熟悉语法分析器生成工具Yacc的使用,并学会在cygwin下使用bison工具编译Yacc文法说明文件。学习如何使用lex和yacc合作进行语法分析。 实验内容 根据给出的calculator例子 (calculator0,calculator1,calculator2,calculator3)完成下面题目:用lex 和yacc写一个计算布尔表达式真值的计算器。 实验要求 输入为一个布尔表达式,以换行结束。输出为这个布尔表达式的真值(true 或false)。尝试二义文法和非二义文法两种不同的实现方式。布尔表达式二义文法为:S –> S or S | S and S | not S | (S) | true | false,其中优先级or < and < not,or 和 and 左结合,not 右结合。非二义文法请参照表达式非二义文法自己写出来。 cygwin下用flex,bison和gcc工具将实验调试通过,并写出测试例测试正确性。 实验参考: calculator0-3这四个例子。请认真阅读例子,发现错误及时提出。 代码编写或修改 实验结果

非二义: 二义(版本1,未去掉对于运算结合性的定义):

以上的内容按照我们的计算顺序都是对的,一开始无法相通为什么二义与非二义的结果相同,后来明白了,于是有了下面的一个版本的结果。 二义(版本2,去掉了运算结合性的定义) 这两项本来应该的结果与其相反,说明了二义文法如果不进行运算符优先性、结合性的定义,则会造成预料不到的结果。 实验心得 1.要深刻理解二义与非二义文法的内涵与区别,才能更好地完成这个实验;

大学编译原理课程复习试题及答案

编译原理复习材料 选择题 1. 文法S→0S | S1 | 0的语言是( )。 A. { 0 m1m| m >=0 } B. { 0 m1m| m >=1 } C. { 0 m1n | m>=1,n>=0 } D. { 0 m1n | m>=0,n>=1 } 2. 描述程序语言所采用的Ⅲ型文法是( )。 A. 短语文法 B.正规文法 C.上下文无关文法 D.上下文有关文法 3. 状态转换图实现的简单方法是使每个状态结对应( )。 A.一个终结符 B.一个非终结符 C.一段小程序 D.一个函数 4. 规范归约的关键问题是寻找( )。 A. 最左素短语 B.句柄 C.直接短语 D.短语 5. 一个算符文法的任何产生式的右部都不含有两个相继的( )。 A.终结符 B.非终结符 C.终结符和非终结符 D.空字 6. 算符优先分析法的关键在于规定( )。 A.算符优先顺序和结合性质 B.算符优先顺序 C.结合性质 D.终结符和非终结符之间关系 7. 优先函数的优点是( )。 A.形象直观 B.便于进行比较运算 C.语法分析速度快 D.语法分析方法简单 8. 文法符号的属性通常分为( )两类。 A. 共用属性和私有属性 B.固有属性和可变属性 C.语法属性和语义属性 D.综合属性和继承属性 9. 在程序流图中,组成循环的结点序列应满足( ) A. 它们是强连通的 B.它们中间有唯一的入口结点 C.它们中间有一条回边 D.它们是强连通的且有唯一的入 口结点 10. 在利用寄存器R生成T1:=C/B的目标代码同时,还应记录信息( )。 A. C/B在T1中 B. T1在C/B中 C. R含有T1, T1在R中 D. R含有C/B, C/B在R中 1.D 2.B 3.C 4.B 5.B 6.A 7.B 8.D 9.D 10.C

编译原理实验指导书-语法分析

编译原理实验指导书 实验2 语法分析 实验目的 1.巩固对语法分析的基本功能和原理的认识。 2.通过对语法分析表的自动生成加深语法分析表的认识。 3.理解并处理语法分析中的异常和错误。 实验要求 一、对学生要求: 1.掌握语法分析程序的总体框架,并将其实现。 2.掌握语法分析表的构造方法 3.掌握语法分析的异常和错误处理。 二、对实验指导教师要求: 1.明确语法分析的基本功能和原理。 2.语法分析程序的总体结构及其关键之处。 3.语法分析表的生成程序。 4.语法分析的异常和错误处理。 5.编写并运行该题目程序代码,具有该题目的参考答案。 6.深刻理解题目内涵,能够清晰描述问题,掌握该题目涉及的知识点,指导学生实验时需要注意的问题。 实验内容 采用至少一种语法分析技术(LL(1)、SLR(1)、LR(1)或LALR(1))分析类高级语言中的基本语句(至少包括函数定义、变量说明、赋值、循环、分支等语句)。 对如下工作进行展开描述 (1)给出如下语言成分的文法描述 ?函数定义(或过程定义) ?变量说明 ?赋值

?表达式 ?循环 ?分支 (2) 语法分析程序的总体结构及物理实现(程序框图) (3) 核心数据结构和功能函数的设计 (4) 错误处理 错误的位置及类型等 实验评分标准 一、课堂表现(10分) 1.出勤情况(按时,迟到,早退,缺席) 2.是否遵守课堂纪律 二、实验结果(50分) 1.当堂按时完成(10分) 2.独立完成(10分),(和同学协商完成,在老师帮助下完成)3.结果正确无误(15分)其中分析表的输出占5分 4.功能齐全,界面美观,具有较好演示效果(10分) 5.在源程序中有必要的注释和说明,程序文档齐全(5分)三、实验报告(40分) 1.语言的文法描述(10分) 2.语法分析程序的模块结构图(10分) 3.核心数据结构的设计(10分) 4.错误处理(5分) 5.实验过程中遇到的问题的总结及实验的体会(5分)

编 译 原 理 实 验 报 告

编译原理实验报告 课程:编译原理 系别:计算机系 班级:11网络 姓名:王佳明 学号:110912049 教师:刘老师 实验小组:第二组 1

实验一熟悉C程序开发环境、进行简单程序的调试 实验目的: 1、初步了解vc++6.0环境; 2、熟悉掌握调试c程序的步骤: 实验内容: 1、输入下列程序,练习Turbo C 程序的编辑、编译、运行。 #include main() { printf(“Programming is fun.\n”); } 2、分析程序,预测其运行结果,并上机检测你的预测。 #include main() { printf(“*\n”); printf(“* * *\n”); printf(“* * * * *\n”); printf(“* * * * * * *\n”); } 3、下面是一个加法程序,程序运行时等待用户从键盘输入两个整数,然后求出它们的和并输出。观察运行结果(程序输出),上机验证该程序。 #include main() { int a,b,c; printf(“Please input a,b:”); scanf(“%d,%d”,&a,&b); c=a+b; printf(“%d+%d=%d\n”,a,b,c); } 2

实验二词法分析器 一、实验目的: 设计、编制、调试一个词法分析子程序-识别单词,加深对词法分析原理的理解。 二、实验要求: 1.对给定的程序通过词法分析器弄够识别一个个单词符号,并以二元式(单词种别码,单词符号的属性值)显示。而本程序则是通过对给定路径的文件的分析后以单词符号和文字提示显示。 2.本程序自行规定: (1)关键字"begin","end","if","then","else","while","write","read", "do", "call","const","char","until","procedure","repeat" (2)运算符:"+","-","*","/","=" (3)界符:"{","}","[","]",";",",",".","(",")",":" (4)其他标记如字符串,表示以字母开头的标识符。 (5)空格、回车、换行符跳过。 在屏幕上显示如下: ( 1 , 无符号整数) ( begin , 关键字) ( if , 关键字) ( +, 运算符) ( ;, 界符) ( a , 普通标识符) 三、使用环境: Windows下的visual c++6.0; 四、调试程序: 1.举例说明文件位置:f:、、11.txt目标程序如下: begin x:=9 if x>0 then x:=x+1; while a:=0 do 3

编译原理实验报告一

实验一词法分析程序实现 一、实验目得与要求 通过编写与调试一个词法分析程序,掌握在对程序设计语言得源程序进行扫描得过程中,将字符流形式得源程序转化为一个由各类单词符号组成得流得词法分析方法 二、实验内容 基本实验题目:若某一程序设计语言中得单词包括五个关键字begin、end、if、then、else;标识符;无符号常数;六种关系运算符;一个赋值符与四个算术运算符,试构造能识别这些单词得词法分析程序(各类单词得分类码参见表I)。 表I语言中得各类单词符号及其分类码表 输入:由符合与不符合所规定得单词类别结构得各类单词组成得源程序文件。 输出:把所识别出得每一单词均按形如(CLASS,VALUE)得二元式形式输出,并将结果放到某个文件中。对于标识符与无符号常数,CLASS字段为相应得类别码得助记符;V AL UE字段则就是该标识符、常数得具体值;对于关键字与运算符,采用一词一类得编码形式,仅需在二元式得CLASS字段上放置相应单词得类别码得助记符,V ALUE字段则为“空". 三、实现方法与环境 词法分析就是编译程序得第一个处理阶段,可以通过两种途径来构造词法分析程序.其一就是根据对语言中各类单词得某种描述或定义(如BNF),用手工得方式(例如可用C语言)构造词法分析程序。一般地,可以根据文法或状态转换图构造相应得状态矩阵,该状态矩阵连同控制程序一起便组成了编译器得词法分析程序;也可以根据文法或状态转换图直接编写词法分析程序。构造词法分析程序得另外一种途径就是所谓得词法分析程序得自动生成,即首先用正规式对语言中得各类单词符号进行词型描述,并分别指出在识别单词时,词法分析程

编译原理实验题目及报告要求

编译原理上机实验试题 一、实验目的 通过本实验使学生进一步熟悉和掌握程序设计语言的词法分析程序的设计原理及相关的设计技术, 如何针对确定的有限状态自动机进行编程序;熟悉和 掌握程序设计语言的语法分析程序的设计原理、熟悉 和掌握算符优先分析方法。 二、实验要求 本实验要求:①要求能熟练使用程序设计语言编程;②在上机之前要有详细的设计报告(预习报告); ③要编写出完成相应任务的程序并在计算机上准确 地运行;④实验结束后要写出上机实验报告。 三、实验题目 针对下面文法G(S): S→v = E E→E+E│E-E│E*E│E/E│(E)│v │i 其中,v为标识符,i为整型或实型数。要求完成 ①使用自动机技术实现一个词法分析程序; ②使用算符优先分析方法实现其语法分析程序,在 语法分析过程中同时完成常量表达式的计算。

1、题目(见“编译原理---实验题目.doc,“实验题目”中的第一项) 2、目的与要求(见“编译原理---实验题目.doc”) 3、设计原理: (1)单词分类:标识符,保留字,常数,运算符,分隔符等等 (2)单词类型编码 (3)自动机 4、程序流程框图 5、函数原型(参数,返回值) 6、关键代码(可打印,只打印关键代码) 7、调试: (1)调试过程中遇到的错误,如何改进的; (2)需要准备测试用例(至少3个,包含输入和输出)——(可打印) 8、思考: (1)你编写的程序有哪些要求是没有完成的,你觉得该采用什么方法去完成; (2)或者是你觉得程序有哪些地方可以进一步完善,简述你的完善方案。

1、题目(见“编译原理---实验题目.doc,“实验题目”中的第二项) 2、目的与要求(见“编译原理---实验题目.doc”) 3、设计原理:构造出算法优先关系表 4、程序流程框图 5、函数原型(参数,返回值) 6、关键代码(可打印,只打印关键代码) 7、调试: (1)调试过程中遇到的错误,如何改进的; (2)需要准备测试用例(至少3个,包含输入和输出)——(可打印) 8、思考: (1)你编写的程序有哪些要求是没有完成的,你觉得该采用什么方法去完成; (2)或者是你觉得程序有哪些地方可以进一步完善,简述你的完善方案。

编译原理实验指导书

编译原理实验指导 书

《编译原理》实验指导书 太原科技大学计算机学院 -3-1

序 《编译原理》是国内外各高等院校计算机科学技术类专业,特别是计算机软件专业的一门重要专业课程。该课程系统地向学生介绍编译程序的结构、工作流程及编译程序各组成部分的设计原理和实现技术。由于该课程理论性和实践性都比较强,内容较为抽象复杂,涉及到大量的软件设计和算法,因此,一直是一门比较难学的课程。为了使学生更好地理解和掌握编译原理和技术的基本概念、基本原理和实现方法,实践环节非常重要,只有经过上机进行程序设计,才能使学生对比较抽象的教学内容产生具体的感性认识,增强学生综合分析问题、解决问题的能力,并对提高学生软件设计水平大有益处。 为了配合《编译原理》课程的教学,考虑到本课程的内容和特点,本指导书设置了七个综合性实验,分别侧重于词法分析、NFA的确定化、非递归预测分析、算符优先分析器的构造、LR分析、语义分析和中间代码的生成、基于DAG的基本块优化,以支持编译程序的各个阶段,基本涵盖了《编译原理》课程的主要内容。 本指导书可作为《编译原理》课程的实验或课程设计内容,在课程教学的同时,安排学生进行相关的实验。实验平台可选择在MS-DOS或Windows操作系统环境,使用C/C++的任何版本作为开发工具。学生在做完试验后,应认真撰写实验报告,内容应

包括实验名称、实验目的、实验要求、实验内容、测试或运行结果等。

目录 实验一词法分析 ........................................................... 错误!未定义书签。实验二 NFA的确定化.................................................... 错误!未定义书签。实验三非递归预测分析 ............................................... 错误!未定义书签。实验四算符优先分析器的构造................................... 错误!未定义书签。实验五 LR分析 .............................................................. 错误!未定义书签。实验六语义分析和中间代码生成................................ 错误!未定义书签。实验七基于DAG的基本块优化................................... 错误!未定义书签。

编译原理实验报告

《编译原理》实验报告软件131 陈万全132852

一、需求分析 通过对一个常用高级程序设计语言的简单语言子集编译系统中词法分析、语法分析、语义处理模块的设计、开发,掌握实际编译系统的核心结构、工作流程及其实现技术,获得分析、设计、实现编译程序等方面的实际操作能力,增强设计、编写和调试程序的能力。 通过开源编译器分析、编译过程可视化等扩展实验,促进学生增强复杂系统分析、设计和实现能力,鼓励学生创新意识和能力。 1、词法分析程序设计与实现 假定一种高级程序设计语言中的单词主要包括五个关键字begin、end、if、then、else;标识符;无符号常数;六种关系运算符;一个赋值符和四个算术运算符,试构造能识别这些单词的词法分析程序。 输入:由符合和不符合所规定的单词类别结构的各类单词组成的源程序文件。 输出:把所识别出的每一单词均按形如(CLASS,VALUE)的二元式形式输出,并将结果放到某个文件中。对于标识符和无符号常数,CLASS字段为相应的类别码的助记符;VALUE字段则是该标识符、常数的具体值;对于关键字和运算符,采用一词一类的编码形式,仅需在二元式的CLASS字段上放置相应单词的类别码的助记符,VALUE字段则为“空”。 2、语法分析程序设计与实现 选择对各种常见高级程序设计语言都较为通用的语法结构——算术表达式的

一个简化子集——作为分析对象,根据如下描述其语法结构的BNF定义G2[<算术表达式>],任选一种学过的语法分析方法,针对运算对象为无符号常数和变量的四则运算,设计并实现一个语法分析程序。 G2[<算术表达式>]: <算术表达式>→<项> | <算术表达式>+<项> | <算术表达式>-<项> <项>→<因式>|<项>*<因式>|<项>/<因式> <因式>→<运算对象> | (<算术表达式>) 若将语法范畴<算术表达式>、<项>、<因式>和<运算对象>分别用E、T、F和i 代表,则G2可写成: G2[E]:E → T | E+T | E-T T → F | T*F | T/F F → i | (E) 输入:由实验一输出的单词串,例如:UCON,PL,UCON,MU,ID······输出:若输入源程序中的符号串是给定文法的句子,则输出“RIGHT”,并且给出每一步分析过程;若不是句子,即输入串有错误,则输出“ERROR”,并且显示分析至此所得的中间结果,如分析栈、符号栈中的信息等,以及必要的出错说明信息。 3、语义分析程序设计与实现 对文法G2[<算术表达式>]中的产生式添加语义处理子程序,完成运算对象是简单变量(标识符)和无符号数的四则运算的计值处理,将输入的四则运算转换为四元式形式的中间代码。 输入:包含测试用例(由标识符、无符号数和+、?、*、/、(、)构成的算术表达式)的源程序文件。 输出:将源程序转换为中间代码形式表示,并将中间代码序列输出到文件中。 若源程序中有错误,应指出错误信息 二、设计思路 1、词法分析程序设计与实现 1)单词分类 为了编程的实现。我们假定要编译的语言中,全部关键字都是保留字,程序员不得将它们作为源程序中的标识符;作了这些限制以后,就可以把关键字和标识符的识别统一进行处理。即每当开始识别一个单词时,若扫视到的第一个字符为字母,则把后续输入的字母或数字字符依次进行拼接,直至扫视到非字母、数字字符为止,以期获得一个尽可能长的字母数字字符串,然后以此字符串查所谓保留字表(此保留字表要事先造好),若查到此字符串,则取出相应的类别码;反之,则表明该字符串应为一标识符。

编译原理标准实验报告

电子科技大学 实验报告 学生姓名:学号:指导教师: 实验地点:实验时间: 一、实验室名称:计算机学院软件工程实验室 二、实验项目名称:词法分析器的设计与实现 三、实验学时:4学时 四、实验原理 1.编译程序要求对高级语言编写的源程序进行分析和合成,生成目标程序。词法分析是对源程序进行的首次分析,实现词法分析的程序为词法分析程序。 2.词法分析的功能是从左到右逐个地扫描源程序字符串,按照词法规则识别出单词符号作为输出,对识别过程中发现的词法错误,输出相关信息。 3.状态转换图是有限有向图,是设计词法分析器的有效工具。 五、实验目的 通过设计词法分析器的实验,使同学们了解和掌握词法分析程序设计的原理及相应的程序设计方法,同时提高编程能力。 六、实验内容 实现求n!的极小语言的词法分析程序,返回二元式作为输出。 七、实验器材(设备、元器件) 1.操作系统:Windows XP

2.开发工具:VC6.0 3.普通PC即可 八、实验步骤 (1)启动VC6.0,创建空白工程项目。选择菜单中的“文件”->“新建”->“项目”,在弹出的对话框中,左边的“项目类型”框中,选择“Visual C++ 项目”,在右边框中,选择“空项目(.Net)”,在对话框下边,选择工程文件存放目录及输入名称,如Example1,单击“确定”。 (2)建立相应的单词符号与种别对照表; (3)根据状态转换图编写相应的处理函数; (4)完成词法分析器; (5)编译与调试以上程序; (6)生成相应的*.dyd文件,作为后面语法分析的输入文件。 九、实验数据及结果分析

可以对源程序进行词法分析,如果有错给出出错信息和所在行数,如果无错则生成二元式文件。 十、实验结论 本实验程序较好地完成了词法分析程序的设计与实现,能够对所给文法的程序进行词法分析,在没有词法错误的时候生成相应的二元式文件。该实验程序可一次性给出源程序中的词法错误。 十一、总结及心得体会 通过该实验,对词法分析程序的设计,以及运用C语言进行编程有了更深刻的理解,同时加深了自己对词法分析程序的原理的理解与掌握,提高了自己的动手能力。 十二、对本实验过程及方法、手段的改进建议 程序设计合理,代码可进一步优化。 报告评分: 指导教师签字:

相关文档
最新文档