自顶向下的语法分析(实验报告一)

自顶向下的语法分析(实验报告一)
自顶向下的语法分析(实验报告一)

武汉轻工大学

编译原理实验报告

姓名朱春桃

院(系)数学与计算机学院

班级软件工程1203

学号 1205110605

指导教师李禹生

2014 年11 月10 日

一、实验目的

完成自顶向下语法分析算法的程序设计。

二、实验内容

设计、调试并测试自顶向下语法分析算法程序。

三、设计思路

根据课堂讲授的自顶向下语法分析方法,可以根据递归下降子程序方法设计语法分析程序,也可以根据LL(1)算法设计语法分析程序,针对文法:G[E]

E→E+T | T

T→T*F | F

F→( E ) | i

(1)由于文法G[E]不满足LL(1)文法条件,需要进行必要的等价文法变换。变换后的等价文法为:

H[E]

E→TA

A→+TA | ε

T→FB

B→*FB | ε

F→( E ) | i

(2)等价文法H[E]不含左递归,可以证明文法H[E]满足LL(1)文法条件(3)根据递归下降子程序方法设计语法分析程序

①递归程序清单

②调试过程说明

③测试语句设计

④测试结果列表

⑤测试结论分析

(4)根据LL(1)算法设计语法分析程序

①预测分析表

②预测分析程序清单

③调试过程说明

④测试语句设计

⑤测试结果列表

⑥测试结论分析

四、程序清单

/*

E->TA,

A->+TA|ε,

T->FB,

B->*FB|ε,

F->i|(E).

*/

#include

void E(char str[80],int &i,int &err or);

void A(char str[80],int &i,int &error);

void T(char str[80],int &i,int &error);

void B(char str[80],int &i,int &error);

void F(char str[80],int &i,int &error);

void main()

{

int i=0,j=0,error=0;

char str[80];

printf("请输入字符串('#'为结束字符):");

while ((str[j]=getchar())!='#')

j++;

str[j]='#';

E(str,i,error);

if(error)

printf("error\n");

else

printf("right\n");

}

void E(char str[80],int &i,int &error)

{

printf("E->TA\n");

T(str,i,error);

A(str,i,error);

}

void A(char str[80],int &i,int &error)

{

if(str[i]=='+')

{

printf("A->+TA|ε\n");

i++;

T(str,i,error);

A(str,i,error);

else if (str[i]=='#'||str[i]==')'){}

else

error++;

}

void T(char str[80],int &i,int &error) {

printf("T->FB\n");

F(str,i,error);

B(str,i,error);

}

void B(char str[80],int &i,int &error) {

if (str[i]=='*')

{

printf("B->*FB|ε\n");

i++;

F(str,i,error);

B(str,i,error);

}

}

void F(char str[80],int &i,int &error) {

if (str[i]=='(')

{

printf("F->i|(E)\n");

i++;

E(str,i,error);

if(str[i]==')')

{

i++;

}

else

error++;

}

else

{

if(str[i]=='i')

{

printf("F->i|(E)\n");

i++;

}

else

error++;

}

五、测试结果

六、实验总结

实验在老师提前给出的算法指导下,完成自顶向下语法分析的程序实际上是不困难的。但是老师的目的应该不在程序,而是让我们通过此次实验对课堂的理论知识有个深层次的理解。所以通过本次实验,我对自顶向下的语法分析过程有了更深的了解,结合课堂知识打下了学习其他语法分析方法的基础。

编译原理实验报告《LL(1)语法分析器构造》

《LL(1)分析器的构造》实验报告 一、实验名称 LL(1)分析器的构造 二、实验目的 设计、编制、调试一个LL(1)语法分析器,利用语法分析器对符号串的识别,加深对语法分析原理的理解。 三、实验内容和要求 设计并实现一个LL(1)语法分析器,实现对算术文法: G[E]:E->E+T|T T->T*F|F F->(E)|i 所定义的符号串进行识别,例如符号串i+i*i为文法所定义的句子,符号串ii+++*i+不是文法所定义的句子。 实验要求: 1、检测左递归,如果有则进行消除; 2、求解FIRST集和FOLLOW集; 3、构建LL(1)分析表; 4、构建LL分析程序,对于用户输入的句子,能够利用所构造的分析程序进行分析,并显示出分析过程。 四、主要仪器设备 硬件:微型计算机。 软件: Code blocks(也可以是其它集成开发环境)。 五、实验过程描述 1、程序主要框架 程序中编写了以下函数,各个函数实现的作用如下: void input_grammer(string *G);//输入文法G

//将文法G预处理得到产生式集合P,非终结符、终结符集合U、u, int eliminate_1(string *G,string *P,string U,string *GG);//消除文法G中所有直接左递归得到文法GG int* ifempty(string* P,string U,int k,int n);//判断各非终结符是否能推导为空 string* FIRST_X(string* P,string U,string u,int* empty,int k,int n);求所有非终结符的FIRST集 string FIRST(string U,string u,string* first,string s);//求符号串s=X1X2...Xn的FIRST集 string** create_table(string *P,string U,string u,int n,int t,int k,string* first);//构造分析表 void analyse(string **table,string U,string u,int t,string s);//分析符号串s 2、编写的源程序 #include #include #include using namespace std; void input_grammer(string *G)//输入文法G,n个非终结符 { int i=0;//计数 char ch='y'; while(ch=='y'){ cin>>G[i++]; cout<<"继续输入?(y/n)\n"; cin>>ch; } } void preprocess(string *G,string *P,string &U,string &u,int &n,int &t,int &k)//将文法G预处理产生式集合P,非终结符、终结符集合U、u, { int i,j,r,temp;//计数 char C;//记录规则中()后的符号 int flag;//检测到() n=t=k=0; for( i=0;i<50;i++) P[i]=" ";//字符串如果不初始化,在使用P[i][j]=a时将不能改变,可以用P[i].append(1,a) U=u=" ";//字符串如果不初始化,无法使用U[i]=a赋值,可以用U.append(1,a) for(n=0;!G[n].empty();n++) { U[n]=G[n][0]; }//非终结符集合,n为非终结符个数 for(i=0;i

编译原理词法分析器语法分析器实验报告

编译技术 班级网络0802 学号3080610052姓名叶晨舟 指导老师朱玉全2011年 7 月 4 日

一、目的 编译技术是理论与实践并重的课程,而其实验课要综合运用一、二年级所学的多门课程的内容,用来完成一个小型编译程序。从而巩固和加强对词法分析、语法分析、语义分析、代码生成和报错处理等理论的认识和理解;培养学生对完整系统的独立分析和设计的能力,进一步培养学生的独立编程能力。 二、任务及要求 基本要求: 1.词法分析器产生下述小语言的单词序列 这个小语言的所有的单词符号,以及它们的种别编码和内部值如下表: 单词符号种别编码助记符内码值 DIM IF DO STOP END 标识符 常数(整)= + * ** , ( )1 2 3 4 5 6 7 8 9 10 11 12 13 14 $DIM $IF $DO $STOP $END $ID $INT $ASSIGN $PLUS $STAR $POWER $COMMA $LPAR $RPAR - - - - - - 内部字符串 标准二进形式 - - - - - - 对于这个小语言,有几点重要的限制: 首先,所有的关键字(如IF﹑WHILE等)都是“保留字”。所谓的保留字的意思是,用户不得使用它们作为自己定义的标示符。例如,下面的写法是绝对禁止的: IF(5)=x 其次,由于把关键字作为保留字,故可以把关键字作为一类特殊标示符来处理。也就是说,对于关键字不专设对应的转换图。但把它们(及其种别编码)预先安排在一张表格中(此表叫作保留字表)。当转换图识别出一个标识符时,就去查对这张表,确定它是否为一个关键字。 再次,如果关键字、标识符和常数之间没有确定的运算符或界符作间隔,则必须至少用一个空白符作间隔(此时,空白符不再是完全没有意义的了)。例如,一个条件语句应写为

编译原理语法分析实验报告

编译原理语法分析实验报告 - 班级:XXX 学号:XXX 姓名:XXX 年月日 1、摘要: 用递归子程序法实现对pascal的子集程序设计语言的分析程序 2、实验目的: 通过完成语法分析程序,了解语法分析的过程和作用 3、任务概述 实验要求:对源程序的内码流进行分析,如为文法定义的句子输出”是”否则输出”否”,根据需要处理说明语句填写写相应的符号表供以后代码生成时使用 4、实验依据的原理 递归子程序法是一种自顶向下的语法分析方法,它要求文法是LL(1)文法。通过对文法中每个非终结符编写一个递归过程,每个过程的功能是识别由该非终结符推出的串,当某非终结符的产生式有多个候选式时,程序能够按LL(1)形式唯一地确定选择某个候选式进行推导,最终识别输入串是否与文法匹配。 递归子程序法的缺点是:对文法要求高,必须满足LL(1)文法,当然在某些语言中个别产生式的推导当不满足LL(1)而满足LL(2)时,也可以采用多向前扫描一个符号的办法;它的另一个缺点是由于递归调用多,所以速度慢占用空间多,尽管这样,它还是许多高级语言,例如PASCAL,C等编译系统常常采用的语法分析方法。

为适合递归子程序法,对实验一词法分析中的文法改写成无左递归和无左共因子的,,,如下: <程序>?<程序首部><分程序>。 <程序首部>?PROGRAM标识符; <分程序>?<常量说明部分><变量说明部分><过程说明部分> <复合语句> <常量说明部分>?CONST<常量定义><常量定义后缀>;|ε <常量定义>?标识符=无符号整数 <常量定义后缀>?,<常量定义><常量定义后缀> |ε <变量说明部分>?VAR<变量定义><变量定义后缀> |ε <变量定义>?标识符<标识符后缀>:<类型>; <标识符后缀>?,标识符<标识符后缀> |ε <变量定义后缀>?<变量定义><变量定义后缀> |ε <类型>?INTEGER | LONG <过程说明部分>?<过程首部><分程序>;<过程说明部分后缀>|ε <过程首部>?PROCEDURE标识符<参数部分>; <参数部分>?(标识符: <类型>)|ε <过程说明部分后缀>?<过程首部><分程序>;<过程说明部分后缀>|ε <语句>?<赋值或调用语句>|<条件语句>|<当型循环语句>|<读语句> |<写语句>|<复合语句>|ε <赋值或调用语句>?标识符<后缀> <后缀>?:=<表达式>|(<表达式>)|ε <条件语句>?IF<条件>THEN<语句> <当型循环语句>?WHILE<条件>DO <语句> <读语句>?READ(标识符<标识符后缀>)

自顶向下的语法分析(实验报告一)

武汉轻工大学 编译原理实验报告 姓名朱春桃 院(系)数学与计算机学院 班级软件工程1203 学号 1205110605 指导教师李禹生 2014 年11 月10 日

一、实验目的 完成自顶向下语法分析算法的程序设计。 二、实验内容 设计、调试并测试自顶向下语法分析算法程序。 三、设计思路 根据课堂讲授的自顶向下语法分析方法,可以根据递归下降子程序方法设计语法分析程序,也可以根据LL(1)算法设计语法分析程序,针对文法:G[E] E→E+T | T T→T*F | F F→( E ) | i (1)由于文法G[E]不满足LL(1)文法条件,需要进行必要的等价文法变换。变换后的等价文法为: H[E] E→TA A→+TA | ε T→FB B→*FB | ε F→( E ) | i (2)等价文法H[E]不含左递归,可以证明文法H[E]满足LL(1)文法条件(3)根据递归下降子程序方法设计语法分析程序 ①递归程序清单 ②调试过程说明 ③测试语句设计 ④测试结果列表 ⑤测试结论分析 (4)根据LL(1)算法设计语法分析程序 ①预测分析表 ②预测分析程序清单 ③调试过程说明 ④测试语句设计 ⑤测试结果列表

⑥测试结论分析 四、程序清单 /* E->TA, A->+TA|ε, T->FB, B->*FB|ε, F->i|(E). */ #include void E(char str[80],int &i,int &err or); void A(char str[80],int &i,int &error); void T(char str[80],int &i,int &error); void B(char str[80],int &i,int &error); void F(char str[80],int &i,int &error); void main() { int i=0,j=0,error=0; char str[80]; printf("请输入字符串('#'为结束字符):"); while ((str[j]=getchar())!='#') j++; str[j]='#'; E(str,i,error); if(error) printf("error\n"); else printf("right\n"); } void E(char str[80],int &i,int &error) { printf("E->TA\n"); T(str,i,error); A(str,i,error); } void A(char str[80],int &i,int &error) { if(str[i]=='+') { printf("A->+TA|ε\n"); i++; T(str,i,error); A(str,i,error);

编译原理实验报告(语法分析器)

. 编译原理实验专业:13级网络工程

语法分析器1 一、实现方法描述 所给文法为G【E】; E->TE’ E’->+TE’|空 T->FT’ T’->*FT’|空 F->i|(E) 递归子程序法: 首先计算出五个非终结符的first集合follow集,然后根据五个产生式定义了五个函数。定义字符数组vocabulary来存储输入的句子,字符指针ch指向vocabulary。从非终结符E函数出发,如果首字符属于E的first集,则依次进入T函数和E’函数,开始递归调用。在每个函数中,都要判断指针所指字符是否属于该非终结符的first集,属于则根据产生式进入下一个函数进行调用,若first集中有空字符,还要判断是否属于该非终结符的follow集。以分号作为结束符。 二、实现代码 头文件shiyan3.h #include #include

#include using namespace std; #define num 100 char vocabulary[num]; char *ch; void judge_E(); void judge_EE(); void judge_T(); void judge_TT(); void judge_F(); 源文件 #include"shiyan3.h" void judge_E() { if(*ch==';') { cout<<"该句子符合此文法!"<

int a=0; cout<<"按1结束程序"<>a; if(a==1) exit(0); } else if(*ch=='('||*ch=='i') { judge_T(); judge_EE(); } else { cout<<"该句子不匹配此文法!"<>a; if(a==1) exit(0); }

语法分析实验

一、实验目的及内容 实现下述我们定义的语言的语法分析器 这种语言的程序结构很简单,语法相当于c的函数体,即由一对大括号括起来的语句序列,没有过程或函数。声明语句、表达式语句及控制语句的写法都与c 类似,但规定:一条声明语句只能声明一个整型变量,没有数组;控制语句只是if、for和while三个语句,这三个语句本身也可以包含语句序列;表达式仅局限于布尔表达式和整型算术表达式,布尔表达式由对两个算术表达式的比较组成,该比较使用<,>,<=,>=,= =,!=比较运算符;算术表达式可以包括整型常数、变量以及+,-,*,/这四个运算符。另外,还可以有复合语句。用read和write语句实现输入输出。注释用/*和*/括起来,但注释不能嵌套。 二、实验原理及基本技术路线图(方框原理图或程序流程图) 实验所用的产生式: <程序> →‘{’ <声明序列> <语句序列> ‘}’ <声明序列> → <声明语句> { <声明语句> } <声明语句> → int <标志符>; <语句序列> → <语句> { <语句> } <语句> → | | | | | <复合语句> | <表达式语句> → if (<表达式>) <语句> [ else <语句> ] → while (<表达式>) <语句> → for (<表达式>;<表达式>;<表达式>) <语句> → read <标识符>; → write <表达式>; <复合语句> →‘{ ’ <语句序列>‘ }’ <表达式语句> → <表达式>; | ; <表达式> → <布尔表达式> | <标志符> = <布尔表达式>

TEST语言 -语法分析,词法分析实验报告

编译原理实验报告 实验名称:分析调试语义分析程序 TEST抽象机模拟器完整程序 保证能用!!!!! 一、实验目的 通过分析调试TEST语言的语义分析和中间代码生成程序,加深对语法制导翻译思想的理解,掌握将语法分析所识别的语法范畴变换为中间代码的语义翻译方法。 二、实验设计 程序流程图

extern int TESTScan(FILE *fin,FILE *fout); FILE *fin,*fout; //用于指定输入输出文件的指针 int main() { char szFinName[300]; char szFoutName[300]; printf("请输入源程序文件名(包括路径):"); scanf("%s",szFinName); printf("请输入词法分析输出文件名(包括路径):"); scanf("%s",szFoutName); if( (fin = fopen(szFinName,"r")) == NULL) { printf("\n打开词法分析输入文件出错!\n"); return 0; } if( (fout = fopen(szFoutName,"w")) == NULL) { printf("\n创建词法分析输出文件出错!\n"); return 0; } int es = TESTScan(fin,fout); fclose(fin); fclose(fout); if(es > 0) printf("词法分析有错,编译停止!共有%d个错误!\n",es); else if(es == 0) { printf("词法分析成功!\n"); int es = 0;

词法分析器实验报告

词法分析器实验报告 词法分析器设计 一、实验目的: 对C语言的一个子集设计并实现一个简单的词法分析器,掌握利用状 态转换图设计词法分析器的基本方法。利用该词法分析器完成对源程 序字符串的词法分析。输出形式是源程序的单词符号二元式的代码, 并保存到文件中。 二、实验内容: 1. 设计原理 词法分析的任务:从左至右逐个字符地对源程序进行扫描,产生一个个单词符号。 理论基础:有限自动机、正规文法、正规式 词法分析器(Lexical Analyzer) 又称扫描器(Scanner):执行词法分析的程序 2. 词法分析器的功能和输出形式 功能:输入源程序、输出单词符号 程序语言的单词符号一般分为以下五种:关键字、标识符、常数、运算符,界符 3. 输出的单词符号的表示形式: 单词种别用整数编码,关键字一字一种,标识符统归为一种,常数一种,各种符号各一种。 4. 词法分析器的结构 单词符号 5. 状态转换图实现

三、程序设计 1.总体模块设计 /*用来存储目标文件名*/ string file_name; /*提取文本文件中的信息。*/ string GetText(); /*获得一个单词符号,从位置i开始查找。并且有一个引用参数j,用来返回这个单词最后一个字符在str的位置。*/ string GetWord(string str,int i,int& j); /*这个函数用来除去字符串中连续的空格和换行 int DeleteNull(string str,int i); /*判断i当前所指的字符是否为一个分界符,是的话返回真,反之假*/ bool IsBoundary(string str,int i); /*判断i当前所指的字符是否为一个运算符,是的话返回真,反之假*/ bool IsOperation(string str,int i);

语法分析程序实验报告及代码

LL(1)语法分析实验报告 一、实验题目 LL(1)语法分析 二、实验目的 通过设计、编制、调试一个典型的语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析,检查语法错误,进一步掌握常用的语法分析方法。 三、实验内容 构造LL(1)语法分析程序,任意输入一个文法符号串,并判断它是否为文法的一个句子。程序要求为该文法构造预测分析表,并按照预测分析算法对输入串进行语法分析,判别程序是否符合已知的语法规则,如果不符合则输出错误信息。 消除递归前的文法消除递归和提取公因子后的等价文法 S →S ∨ a T | a T | ∨ a T S→aTS’ |vaTS’ T →∧ a T | ∧a S’→vaTS’ |ε T→∧ a T’ T’→∧ aT’ |ε 根据已建立的分析表,对下列输入串:a∧ a∧ a进行语法分析,判断其是否符合文法。 四、实验要求 1.根据已由的文法规则建立LL(1)分析表; 2.输出分析过程。 请输入待分析的字符串: a∧ a∧ a 符号栈输入串所用产生式

#S a∧ a∧ a# #S’Ta a∧ a∧ a# S→aTS’ #S’T ∧ a∧ a# # S’T’a∧∧ a∧ a# T→∧ a T’ # S’T’a a∧ a# # S’T’∧ a# # S’T’a∧∧ a# T’→∧ aT’ # S’ T’a a# # S’ T’# # S’ # T’→ε # # S’→ε 五、程序思路 模块结构: 1、定义部分:定义常量、变量、数据结构。 2、初始化:设立LL(1)分析表、初始化变量空间(包括堆栈、结构体等); 3、运行程序:让程序分析一个text文件,判断输入的字符串是否符合文法定义的规则; 4、利用LL(1)分析算法进行表达式处理:根据LL(1)分析表对表达式符号串进行堆栈(或其他)操作,输出分析结果,如果遇到错误则显示简单的错误提示。 六、程序源代码 /* 程序名称: LL(1)文法分析程序 */ /* S->S>aT|aT|>aT */ /* T->

编译原理LL(1)语法分析实验报告

学号20102798 专业软件工程姓名薛建东 实验日期2013.04.08 教师签字成绩实验报告 【实验名称】LL(1)语法分析 【实验目的】 通过完成预测分析法的语法分析程序,了解预测分析法和递归子程序法的区别和联系。使了解语法分析的功能,掌握语法分析程序设计的原理和构造方法,训练掌握开发应用程序的基本方法。 【实验内容】 ◆根据某一文法编制调试LL ( 1)分析程序,以便对任意输入的符号串进行分析。 ◆构造预测分析表,并利用分析表和一个栈来实现对上述程序设计语言的分析程序。 ◆分析法的功能是利用LL(1)控制程序根据显示栈栈顶内容、向前看符号以及LL(1) 分析表,对输入符号串自上而下的分析过程。 【设计思想】 (1)、LL(1)文法的定义 LL(1)分析法属于确定的自顶向下分析方法。LL(1)的含义是:第一个L表明自顶向下分析是从左向右扫描输入串,第2个L表明分析过程中将使用最左推导,1表明只需向右看一个符号便可决定如何推导,即选择哪个产生式(规则)进行推导。 LL(1)文法的判别需要依次计算FIRST集、FOLLOW集和SELLECT集,然后判断是否为LL(1)文法,最后再进行句子分析。 需要预测分析器对所给句型进行识别。即在LL(1)分析法中,每当在符号栈的栈顶出现非终极符时,要预测用哪个产生式的右部去替换该非终极符;当出现终结符时,判断其与剩余输入串的第一个字符是否匹配,如果匹配,则继续分析,否则报错。LL(1)分析方法要求文法满足如下条件:对于任一非终极符A的两个不同产生式A→α,A→β,都要满足下面条件:SELECT(A→α)∩SELECT(A→β)=? (2)、预测分析表构造 LL(1)分析表的作用是对当前非终极符和输入符号确定应该选择用哪个产生式进行推

第五章 自上而下语法分析

第五章自上而下语法分析 1、教学目的及要求: 本章介绍编译程序的第二个阶段语法分析的设计方法和实现原理,包括自上而下分析的无回朔的递归下降分析、 LL(1)分析法。要求理解递归下降分析、LL(1)文法的基本概念;掌握无回朔的递归下降分析的设计和实现、LL(1)分析表的构造与分析方法。 ◇能够对一个给定的文法判断是否是LL(1)文法; ◇能构造预测分析表; ◇能用预测分析方法判断给定的输入符号串是否是该文法的句子; ◇能对某些非LL(1)文法做等价变换: ①消除左递归 ②提取左公共因子 可能会变成LL(1)文法。这样可扩大自顶向下分析方法的应用。 2、教学内容: 语法分析器的功能,自上而下语法分析(递归下降分析法,预测分析程序),LL(1)分析法,递归下降分析程序构造,预测分析程序。 3、教学重点: 递归下降子程序,预测分析表构造,LL(1)文法。 4、教学难点: 对一个文法如何判断是否是LL(1)文法,由于在判断 LL(1)文法时用到文法符号串的开始符号集合(FIRST集)和非终结符后跟符号集合(FOLLOW集)的计算,而一般学生往往因概念不清或不够细心对这两个集合的计算常常出错,导致判断和分析结果的错误。 5、课前思考 为了了解自顶向下(自上而下)分析的一般过程和问题,请学生首先回顾本章之前介绍的有关基本概念: ◇句子、句型和语言的定义是什么? ◇什么叫最左推导? ◇什么叫最右推导和规范推导? ◇什么叫确定的自顶向下语法分析?

◇自顶向下语法分析是从文法的开始符号出发,反复使用各种产生式,寻找与输入符号匹配的推导。 ◇确定的自顶向下语法分析中用的是哪种推导? ◇在确定的自顶向下语法分析过程中,当以同一个非终结符为左部的产生式有多个不同右部时,如何选择用哪个产生式的右部替换当前的非终结符? ◇确定的自顶向下语法分析对文法有何限制? 6、章节内容 第一节概述 第二节 LL(1)分析方法 第三节递归下降分析法 5.1 概述 LL分析法 确定的自上而下分析 自上而下分析递归下降分析法 语法分析不确定的自上而下分析——即带回溯的分析方法 算符优先分析 自下而上分析 LR分析 一、带回溯的自顶向下分析方法 是自顶向下分析的一般方法,即对任一输入符号串,试图用一切可能的办法,从树根结点(识别符号)出发,根据文法自上而下地为输入串建立一棵语法树,或者说,从识别符号开始,根据文法为输入串建立一个推导序列,这种分析过程本质上是一种试探过程,是反复使用不同规则谋求匹配输入串的过程。 例有文法G[S]:S→cAd,A→ab|a,输入串w=cad。其分析过程为带回溯的。 二、存在问题及解决办法 1、左递归问题: 自顶向下分析方法只有把规则排列得合适时才能正确工作,该方法不能处理具有左递归性文法,可采取某些算法消除左递归。 2、回溯问题:

词法分析器实验报告

词法分析器实验报告 一、实验目的及要求 本次实验通过用C语言设计、编制、调试一个词法分析子程序,识别单词,实现一个C语言词法分析器,经过此过程可以加深对编译器解析单词流的过程的了解。 运行环境: 硬件:windows xp 软件:visual c++6.0 二、实验步骤 1.查询资料,了解词法分析器的工作过程与原理。 2.分析题目,整理出基本设计思路。 3.实践编码,将设计思想转换用c语言编码实现,编译运行。 4.测试功能,多次设置包含不同字符,关键字的待解析文件,仔细察看运行结果,检测该分析器的分析结果是否正确。通过最终的测试发现问题,逐渐完善代码中设置的分析对象与关键字表,拓宽分析范围提高分析能力。 三、实验内容 本实验中将c语言单词符号分成了四类:关键字key(特别的将main说明为主函数)、普通标示符、常数和界符。将关键字初始化在一个字符型指针数组*key[]中,将界符分别由程序中的case列出。在词法分析过程中,关键字表和case列出的界符的内容是固定不变的(由程序中的初始化确定),因此,从源文件字符串中识别出现的关键字,界符只能从其中选取。标识符、常数是在分析过程中不断形成的。 对于一个具体源程序而言,在扫描字符串时识别出一个单词,若这个单词的类型是关键字、普通标示符、常数或界符中之一,那么就将此单词以文字说明的形式输出.每次调用词法分析程序,它均能自动继续扫描下去,形成下一个单词,直到整个源程序全部扫描完毕,从而形成相应的单词串。 输出形式例如:void $关键字

流程图、程序流程图:

程序: #include #include #include #include //定义关键字 char *Key[10]={"main","void","int","char","printf","scanf","else","if","return"}; char Word[20],ch; // 存储识别出的单词流 int IsAlpha(char c) { //判断是否为字母 if(((c<='z')&&(c>='a'))||((c<='Z')&&(c>='A'))) return 1; else return 0; } int IsNum(char c){ //判断是否为数字 if(c>='0'&&c<='9') return 1; else return 0; } int IsKey(char *Word){ //识别关键字函数 int m,i; for(i=0;i<9;i++){ if((m=strcmp(Word,Key[i]))==0) { if(i==0) return 2; return 1; } } return 0; } void scanner(FILE *fp){ //扫描函数 char Word[20]={'\0'}; char ch; int i,c; ch=fgetc(fp); //获取字符,指针fp并自动指向下一个字符 if(IsAlpha(ch)){ //判断该字符是否是字母 Word[0]=ch; ch=fgetc(fp);

语法分析(自上而下分析)实验报告

实习二语法分析-自上而下分析 一、实验目的 使用预测分析方法对输入的表达式进行分析,掌握其具体的使用并且学会去分析一个文法。 二、实验内容 1.设计表达式的语法分析器算法(使用预测分析) 2.编写一段代码并上机调试查看其运行结果 三、实验要求 使用LL(1)分析算法设计表达式的语法分析器 LL(1)文法是一个自上而下的语法分析方法,它是从文法的开始符号出发,生成句子的最左推导,从左到右扫描源程序,每次向前查看一个字符,确定当前应该选择的产生式。 实现LL(1)分析的另一种有效方法是使用一张分析表和一个栈进行联合控制。 预测分析程序的总控程序在任何时候都是按STACK栈顶符号X和当前a的输入符号行事的。对于任何(X,a),总控程序每次都执行三种可能的动作之一。 1.若X=a=“#”,则宣布分析成功,停止分析过程 2.若X=a≠“#”,则把X从STACK栈顶逐出,让a指向下一 个输入符号。 3.若X是一个非终结符,则查看分析表。 四、运行结果

(本程序只能对由'i','+','*','(',')'构成的以'#'结束的字符串进行分析) 五、源程序实现 /*LL(1)分析法源程序,只能在VC++中运行*/ #include #include #include #include char A[20]; char B[20]; char v1[20]={'i','+','*','(',')','#'};/*终结符*/ char v2[20]={'E','G','T','S','F'};/*非终结符*/ int j=0,b=0,top=0,l;/*L为输入串长度*/

编译原理 第四章自顶向下语法分析法

第四章 自顶向下语法分析方法 语法分析是编译过程的核心部分。语法分析的任务是:按照文法,从源程序符号串中识别出各类语法成份,同时进行语法检查,为语义分析和代码生成作准备。执行语法分析任务的程序称为分析程序。也称为语法分析器,它是编译程序的主要子程序之一。 在第二章中我们已经介绍过。通过语法分析可建立起相应的语法树。按语法树的建立方法,我们将语法分析方法分成两大类,即自顶向下分析和自底向上分析。下面,我们先介绍自顶向下分析。 本章重点:自顶向下分析、LL (1)分析 第一节 自顶向下分析方法 一、带回溯的自顶向下分析算法 这是自顶向下分析的一般方法,即对任一输入符号串,试图用一切可能的方法,从识别符号出发,根据文法自上而下地为输入串建立一棵语法树。 下面用一个简单例子来说明这种过程: 假定有文法G[S]: S→c Ad A →ab|a 以及输入串w=cad 为了自上而下地构造w 的语法树,我们首先按文法的识别符号产生根结点S ,并让指示器IP 指 c S 的规则仅有一条)把这棵树发展为 ( a ) (b ) (c ) 图3-1-1 图3-1-1a 。我们希望用S 的子结从左至右匹配整个输入串w 。首先,此树的最左子结是终结符c 为标志的子结,它和输入串的第一个符号相匹配。于是,我们就把IP 调整为指向下一输入符号a ,并让第二个子结A 去进行匹配,非终结符A 有二个选择,我们试着用它的第一个选择去匹配输入串,于是把语法树发展为图3-1-1b 。子树A 的最左子结和IP 所指的符号相符,然后我们再把IP 调为指向下一符号d 并让A 的第二个子结进入工作。但A 的第二个子结为终结符号b ,与IP 当前指的符号d 不一致。因此,A 宣告失败。这意味着A 的第一个选择此刻不适用于构造w 的语法树。这时,我们应该回头(回溯)看A 是否还有别的选择。 为了实现回溯,我们一方面应把A 的第一个选择所生长的子树注销掉;另一方面,应把IP 恢复为进入A 时的原值,也就是让它重新指向第二输入符号a 。现在我们试探用A 的第二个选择,即考虑生成图3-1-1c 的语法树。 由于子树A 只有一个子结a ,而且,它和IP 所指的符号相一致,于是,A 完成了匹配任务。在A 获得匹配后,指示器指向下一个未被触及的符号d 。 在S 的第二子结A 完成匹配后,接着就轮到第三个子结d 进行工作。由于这个子结和最后一个输入符号相符,于是,我们完成了构造语法树的任务,证明了w 是文法G[ s]的一个句子。 上述自顶向下地为输入符号w 建立语法树的过程,实际上也是设法建立一个最左推导序列,以便通过一步步推导将输入串推导出来。很明显,对于输入串w 可以通过如下的推导过程将其推导出来:S ?CAd ?cad 所以用最左推导,是因为我们对输入串是自左向右扫描的,只有使用最左推导,才能保证按扫描顺序去匹配输入串。在上述推出符号串w 的过程中,由于出现在符号串中的非终结符号只有一个,因此,未明显地表现出最左推导的性质。 根据以上分析,不难编出程序来实现这种分析的算法。但是,上述这种自顶向下的分析算法存

编译原理语法分析器实验报告

编译原理语法分析器实验报告 班级: 学号: 姓名:

实验名称语法分析器 一、实验目的 1、根据某一文法编制调试LL(1)分析程序,以便对任意输入的符号串进行分析。 2、本次实验的目的主要是加深对自上而下分析法的理解。 二、实验内容 [问题描述] 递归下降分析法: 0.定义部分:定义常量、变量、数据结构。 1.初始化:从文件将输入符号串输入到字符缓冲区中。 2.利用递归下降分析法分析,对每个非终结符编写函数,在主函数中调用文法开始符号的函数。 LL(1)分析法: 模块结构: 1、定义部分:定义常量、变量、数据结构。 2、初始化:设立LL(1)分析表、初始化变量空间(包括堆栈、结构体等); 3、运行程序:让程序分析一个text文件,判断输入的字符串是否符合文法定义的规则; 4、利用LL(1)分析算法进行表达式处理:根据LL(1)分析表对表达式 符号串进行堆栈(或其他)操作,输出分析结果,如果遇到错误则显示简 单的错误提示。 [基本要求] 1. 对数据输入读取 2. 格式化输出分析结果 2.简单的程序实现词法分析 public static void main(String args[]) { LL l = new LL(); l.setP(); String input = ""; boolean flag = true;

while (flag) { try { InputStreamReader isr = new InputStreamReader(System.in); BufferedReader br = new BufferedReader(isr); System.out.println(); System.out.print("请输入字符串(输入exit退出):"); input = br.readLine(); } catch (Exception e) { e.printStackTrace(); } if(input.equals("exit")){ flag = false; }else{ l.setInputString(input); l.setCount(1, 1, 0, 0); l.setFenxi(); System.out.println(); System.out.println("分析过程"); System.out.println("----------------------------------------------------------------------"); System.out.println(" 步骤| 分析栈 | 剩余输入串| 所用产生式"); System.out.println("----------------------------------------------------------------------"); boolean b = l.judge(); System.out.println("----------------------------------------------------------------------"); if(b){ System.out.println("您输入的字符串"+input+"是该文法的一个句子"); }else{ System.out.println("您输入的字符串"+input+"有词法错误!");

实验二语法分析

实验二、语法分析 一、实验目的: 设计MiniC的上下文无关文法,利用JavaCC生成调试递归下降分析程序,以便对任意输入的符号串进行分析。本次实验的目的主要是加深对递归下降分析法的理解。 二、语法分析器: 按照MiniC语言的语法规则检查词法分析输出的记号流是否符合这些规则,并根据这些规则所体现出的语言中的各种语法结构的层次性。把规则写入到JavaCC的.jjt文件中,可以生成树状的层次结构。 三、JavaCC: 在JavaCC的文法规范文件中,不仅可以描述语言的语法规范,而且可以描述词法规范,本次实习中,利用JavaCC以MiniC语言构造一个不含语义分析的编译器前端,包括词法分析、语法分析,并要考虑语法分析中的错误恢复问题。通过使用JavaCC, 可以体会LL(k)文法的编写特点,掌握编写JavaCC文法规范文件的方法。 内容:利用JavaCC生成一个MiniC的语法分析器; 要求: 1.用流的形式读入要分析的C语言程序,或者通过命令行输入源程序。 2.具有错误检查的能力,如果有能力可以输出错误所在的行号,并简单提示 3.如果输入的源程序符合MiniC的语法规范,输出该程序的层次结构的语法树 具体实施步骤如下: 1.把MiniC转换为文法如下 Procedure()→void main() {WhileStatement()} WhileStatement()→while(Condition()){(WhileStatement()|ass ign())} assign()→= ; expression()→term() (( + | - ) term()) term()→unary() (( * | / ) unary()) unary()→| | ( expression()) Condition()→expression()( < expression() | > expression() | >= expression() | <= expression() )

语法分析器实验报告

语法分析器的设计实验报告 一、实验内容 语法分析程序用LL(1)语法分析方法。首先输入定义好的文法书写文件(所用的文法可以用LL(1)分析),先求出所输入的文法的每个非终结符是否能推出空,再分别计算非终结符号的FIRST集合,每个非终结符号的FOLLOW集合,以及每个规则的SELECT集合,并判断任意一个非终结符号的任意两个规则的SELECT 集的交集是不是都为空,如果是,则输入文法符合LL(1)文法,可以进行分析。对于文法: G[E]: E->E+T|T T->T*F|F F->i|(E) 分析句子i+i*i是否符合文法。 二、基本思想 1、语法分析器实现 语法分析是编译过程的核心部分,它的主要任务是按照程序的语法规则,从由词法分析输出的源程序符号串中识别出各类语法成分,同时进行词法检查,为语义分析和代码生成作准备。这里采用自顶向下的LL(1)分析方法。 语法分析程序的流程图如图5-4所示。 语法分析程序流程图 该程序可分为如下几步: (1)读入文法 (2)判断正误 (3)若无误,判断是否为LL(1)文法 (4)若是,构造分析表; (5)由句型判别算法判断输入符号串是为该文法的句型。 三、核心思想 该分析程序有15部分组成: (1)首先定义各种需要用到的常量和变量;

(2)判断一个字符是否在指定字符串中; (3)读入一个文法; (4)将单个符号或符号串并入另一符号串; (5)求所有能直接推出&的符号; (6)求某一符号能否推出‘& ’; (7)判断读入的文法是否正确; (8)求单个符号的FIRST; (9)求各产生式右部的FIRST; (10)求各产生式左部的FOLLOW; (11)判断读入文法是否为一个LL(1)文法; (12)构造分析表M; (13)句型判别算法; (14)一个用户调用函数; (15)主函数; 下面是其中几部分程序段的算法思想: 1、求能推出空的非终结符集 Ⅰ、实例中求直接推出空的empty集的算法描述如下: void emp(char c){ 参数c为空符号 char temp[10];定义临时数组 int i; for(i=0;i<=count-1;i++)从文法的第一个产生式开始查找 { if 产生式右部第一个符号是空符号并且右部长度为1, then将该条产生式左部符号保存在临时数组temp中 将临时数组中的元素合并到记录可推出&符号的数组empty中。 } Ⅱ、求某一符号能否推出'&' int _emp(char c) { //若能推出&,返回1;否则,返回0 int i,j,k,result=1,mark=0; char temp[20]; temp[0]=c; temp[1]='\0'; 存放到一个临时数组empt里,标识此字符已查找其是否可推出空字 如果c在可直接推出空字的empty[]中,返回1 for(i=0;;i++) { if(i==count) return(0); 找一个左部为c的产生式 j=strlen(right[i]); //j为c所在产生式右部的长度 if 右部长度为1且右部第一个字符在empty[]中. then返回1(A->B,B可推出空) if 右部长度为1但第一个字符为终结符,then 返回0(A->a,a为终结符) else

语法分析实验报告

课程实验报告课程名称:编译原理(语法分析) 专业班级:软件工程(2)班 学号:20121344073 姓名:张伟 指导教师:顾彬 报告日期:2015.6.18 计算机科学与技术学院

1、实验目的 1)设计并编制一个语法分析程序,加深对语法分析程序中递归下降分析方法的 理解; 2)巩固对代码生成及报错处理等理论的认识; 3)培养对完整系统独立分析和设计的能力; 2、实验要求 利用C语言编制递归下降分析程序,并对简单语言进行语法分析。 2.1 待分析的简单语法的语法 用扩充的BNF表示如下: (1)<程序>::=begin <语句串> end (2)<语句串>::=<语句>{:语句} (3)<语句>::=< 赋值语句> (4)<赋值语句>::=ID := <表达式> (5)<表达死>::=<项>{+<项>|-<项>} (6)<项>::=<因子>{*<因子>|/<因子>} (7)<因子>::=ID | NUM | ( < 表达式> ) 3、词法分析程序的算法思想 算法的基本任务是从字符串中表示的源程序中识别出具有独立意义的单词符号,并通过其基本文法,正确规约到开始符号。 1)全局变量的设置 在此程序中,需要设置两个个全局变量: 关键字表retab[6]、当前识别的种别号syn。 其中retab中元素为“begin”“if”“then”“while”“do”“end”,在程序会扫描

出标识符时,首先查关键字表。如果能找到匹配的单词,则该单词为关键字,否则为一般标识符。 syn用于每一步扫描中scanner 的返回值。在整个语法分析程序中均需要使用该全局变量。 词法分析代码: /*输入:所给文法的源程序字符串。 输出:二元组(syn,token或sum)构成的序列。 其中:syn为单词种别码; token为存放的单词自身字符串; sum为整型常数。 */ #include #include /* *关键字作为特殊标识符处理,把它们预先安排在一个字符串数组中(称为rwtab), *当扫描程序识别出标识符时,查rwtab。如能查到匹配的单词,则该单词为关键字, *否则为一般标识符。其描述如下: */ const char *rwtab[6]={"begin","if","then","while","do","end"}; /* ①token用来存放构成单词符号的字符串;②sum用来整型单词;③syn用来存放单词符号的种别码。 p为记号,用来对应存放数组下标。出ch用来读入每次输入的字符 words[]用来存放读入的字符串,最大值为100 m用来指示token数组下标 */ int sum=0,syn,p,n,m=0; char words[80],token[8]; //char token[10],words[100]; char ch;

相关文档
最新文档