语义分析程序的设计与实现班号:2008211316姓名:张荣学号:08211627序号:26实验日期:2010-11-23一:实验内容:....................................................................................................................2二:实验要求:....................................................................................................................2三:实验方法:....................................................................................................................2◆由LEX建立YACC的词法分析程序...............................................................................................2◆yacc原理介绍................................................................................................................................3◆词法分析.......................................................................................................................................4◆解析器如何工作............................................................................................................................5◆Yacc环境.......................................................................................................................................6◆常用代码.......................................................................................................................................7第四:YACC内部名称:.....................................................................................................7第五:运行结果(源代码见附录).................................................................................8第六:实验总结....................................................................................................................9第七:附录..........................................................................................................................10附录一:yacc程序,加注释...........................................................................................................10附录二:词法分析器的工作原理...................................................................................................16一:实验内容:编写语法分析程序,实现对算术表达式的语法分析,要求所分析的算术表达式由如下的文法产生。◆E-E+T|E-T|T◆T-T*F|T/F|F◆F-id|(E)|num二:实验要求:在对表达式进行分析的同时,输出所采用的产生式。可以采用多种方法◆编写递归调用程序,实现自顶向下的分析。◆编写LL(1)语法分析程序,要求:◇编程实现算法4.2,为给定的文法自动构造预测分析表◇编程实现算法4.1,构造LL(1)预测分析程序,◆编写语法分析程序,实现自底向上的分析,要求:◇构造识别所有活前缀的DFA◇构造LR分析表◇编程实现算法4.3,构造LR分析程序◆利用yacc自动生成语法分析程序,调用LEX自动生成的词法分析器程序三:实验方法:◆由LEX建立YACC的词法分析程序由LEX产生的词法分析程序可用于YACC,LEX编译程序根据LEX源程序产生词法分析程序yylex(),这个名字就是YACC所需要的词法分析程序的名字。如果YACC要调用LEX产生的词法分析程序,则在YACC源程序的第三部分用语句#include“lex.yy.c”代替函数yylex()的定义,这一yylex()就可以访问YACC中记号的名字,因为LEX的输出时候YACC输出文件的一部分,所有,每个LEX的动作都返回YACC知道的终结符。在UNIX的环境下,如果LEX源程序在first.l中,YACC的源程序在second.y中,可以使用以下命令得到所需要的分析程序。Lexfirst.lYaccsecond.ycc-oyaccdemoy.tab.clex.yy.c◆yacc原理介绍Yacc是用可移植的C语言写成的。接受的规定类别是非常一般性的:带有去歧义规则的LALR(1)文法。Yacc提供了一个通用工具来在计算机程序的输入上施加结构。Yacc用户准备输入处理的规定;它包括描述输入结构的规则,在识别了这些规则的时候调用的代码,和做基本输入的一个低层例程。Yacc接着生成一个函数来控制输入处理。这个函数叫做解析器(parser),它调用用户提供的低层输入例程(词法分析器(analyzer))来从输入流中选取基本项目(叫做记号(token))。依据叫做文法规则的输入结构规则来组织这些记号;在识别了这些规则中的某一个的时候,接着调用为这个规则提供的叫做动作的用户代码;动作有能力返回值并使用其他动作的值。为了便利在动作和解析器之间的通信,对动作语句要做稍微的改动。在这个上下文中使用美元符号“$”作为给Yacc的一个信号。◆词法分析用户必须提供一个词法分析器来读取输入流并把记号(带有值,如果需要的话)传达到解析器。词法分析器使叫做yylex的整数值的函数。这个函数返回一个整数的记号编号,它表示读取的记号的种类。如果这个记号关联着一个值,应当把它赋予外部变量yylval。为使通信得以发生,解析器和词法分析器必须在记号编号上达成一致。编号可以由Yacc或用户来选择。在这两种情况下,使用C语言的“#define”机制允许词法分析器使用符号来返回这些编号。例如,假定在Yacc规定文件的声明段中已经定义记号名字DIGIT。它的意图是返回一个DIGIT记号编号,和等于这个数字的数值的一个值。倘若词法分析器代码位于规定文件的程序段,标识符DIGIT将被定义为与记号DIGIT关联的记号编号。这种机制导致清晰的、易于修改的词法分析器;唯一的缺点是在文法中需要避免使用任何在C语言或解析器中保留的或有意义的记号名字;例如,使用记号名字if或while就一定会导致编译词法分析器时出现严峻的困难。记号名字error保留给错误处理,不应该随便使用。同上所述,记号编号可以由Yacc或用户来选择。在缺省的条件下,编号由Yacc选择。文字字符的缺省记号编号是它在本地字符集中的字符数值。其他名字赋予从257开始的记号编号。要把一个记号编号赋予一个记号(包括文字),可以在声明段中记号或文字的第一次出现时直接跟随着一个非负整数。这个整数被接受为这个名字或文字的记号编号。不通过这种机制定义的名字和文字保持它们的缺省定义。所有记号编号都是不同的是很重要的。构造词法分析器的一个有用的工具是MikeLesk[8]开发的Lex程序。这些词法分析器设计用来与Yacc解析器紧密协调工作。这些词法分析器的规定使用正则表达式而不是文法规则。可以轻易的用Lex生成非常复杂的词法分析器,但是仍有一些语言(比如FORTRAN)不适应任何理论框架,它的词法分析器必须手工制作。◆解析器如何工作Yacc把规定文件转换成C程序,它依据给出的规定解析输入。做从规定到解析器转换的算法是复杂的,就不在这里讨论了(更多信息参见引用)。但是,解析器自身就相对简单了,理解它是如何工作的,尽管不是严格必须的,但会使错误修复和歧义处置更加易于理解。Yacc提供的解析器是由带有一个栈的有穷状态自动机组成。解析器自身还有能力读取和记住(叫做超前(lookahead)记号)下一个输入记号。当前状态总是在栈顶。有穷状态自动机的状态是一个给定的小整数标签(label);最初时,机器是在状态0下,栈只包含状态0,没有读取超前记号。机器对它只能获得四个动作,叫做移进(shift)、归约(reduce)、接受和错误。◆Yacc环境在用户向Yacc输入规定的时候,在多数系统上输出文件是叫做y.tab.c的一个C程序文件(因为本地文件系统惯例,它的名字在不同安装中可能是不同的)。Yacc生成的函数叫yyparse;它是整数值的函数。在调用的时候,它依次重复的调用用户提供的词法分析器yylex来获得输入记号。最终,要么是检测到一个错误,在这种情况下(如果没有错误修复是可能的)yyparse返回值1,要么词法分析器返回结束标记记号并且解析器接受。在这种情况下,yyparse返回值0。用户必须为解析器提供特定数量的环境来获得一个工作的程序。例如,同每个C程序一样,必须被定义程序调用的main(),它最终调用yyparse。此外,叫做yyerror的一个例程在检测到语法错误的时候打印一个消息。用户必须以某种形式提供这两个例程。为了减轻使用Yacc的起初努力,提供了带有缺省版本的main和yyerror的一个库。这个库的名字是依赖系统的;在很多系统上使用到装载器的-ly参数来访问这个库。到yyerror的参数是包含错误信息的字符串,通常是字符串“syntaxerror”。一般的应用可能需要更好的消息。通常,程序跟踪输入行数,并与检测到的语法错误一起打印。外部整数变量yychar在检测到错误的时候包含超前记号的编号;这对给出更好的诊断有好处。因为main程序(需要读参数等等)大多数时候是用户提供的。Yacc库只在小项目或大点的项目的早期阶段有用。外部整数变量yydebug通常设置为0。如果设置为非零的值,解析器会输出对它的动作的一个冗余的描述,包括对已经读入哪个输入符号和解析器动作是什么的讨论。依赖于操作系统,可以通过使用调试系统来设置这个变量。◆常用代码if(islower(c)){yylval=c-'a';return(LETTER);}if(isdigit(c)){yylval=c-'0';return(DIGIT);}if(c='z'&&c='a'||c='Z'&&c='A'){yylval=c;return(ID);}第四:YACC内部