《编译原理》实验报告课程编译原理实验名称编译原理综合实验专业班级姓名学号完成日期2013/6/5目录实验一 (2)实验目的和内容 (2)PL/0语言描述 (2)内部码对照表 (3)实验过程及方法 (4)实验结果 (4)总结 (5)实验二 (5)实验目的 (5)实验内容及要求 (6)实验算法 (7)实验结果 (7)总结 (8)实验三 (8)实验目的 (8)实验内容 (9)实现算法 (9)实验结果 (9)总结 (12)实验一实验目的和内容1.实验目的:通过完成词法分析程序,了解词法分析的过程。
2.实验内容:用C/C++实现对Pascal的子集程序设计语言的词法识别程序。
3.实验要求:将该语言的源程序,也就是相应字符流转换成内码,并根据需要是否对于标识符填写相应的符号表供编译程序的以后各阶段使用。
PL/0语言描述PL/0程序设计语言是一个较简单的语言,它以赋值语句为基础,包括顺序、条件和循环三种控制结构。
PL/0有子程序(即函数)概念。
PL/0中唯一的数据类型是整型,可以用来说明该类型的常量和变量。
当然PL/0也具有通常的算术运算和关系运算。
具体的PL/0语法描述如下(采用扩充的BNF表示)。
<程序>→<程序首部> <分程序> {<分程序>}.<程序首部>→PROGRAM标识符;<分程序>→<过程首部> [<常量说明部分>] [<变量说明部分>] <复合语句><常量说明部分>→CONST <常量定义> {,<常量定义> } ;<常量定义>→标识符= 无符号整数<变量说明部分>→V AR <变量定义> {;<变量定义>};<变量定义>→标识符{,标识符}:<类型><类型>→INTEGER<过程首部>→PROCEDURE标识符;| PROCEDURE标识符(标识符:<类型>);<复合语句>→BEGIN<语句>{;<语句>}END<语句>→<赋值语句>|<条件语句>|<当型循环语句>|<过程调用语句>|<读语句>|<写语句>|<复合语句>|ε<赋值语句>→标识符:=<表达式><条件语句>→IF<条件>THEN<语句><条件语句> → if<布尔表达式> then <语句>|if<布尔表达式> then <语句> else <语句> <布尔表达式> → <条件> | !<布尔表达式>| <布尔表达式> && <布尔表达式><当型循环语句>→WHILE<条件>DO<语句><过程调用语句>→CALL 标识符| CALL 标识符(<表达式>)<读语句>→READ(标识符{,标识符} )<写语句>→WRITE(<表达式>{,<表达式>})<条件>→<表达式><关系运算符><表达式> | ODD<表达式><表达式>→<项>{<加型运算符><项>}<项>→<因子>{<乘型运算符><因子>}<因子>→标识符| 无符号整数| (<表达式>)<加型运算符>→+|-<乘型运算符>→* | /<关系运算符>→=|<>|<|<=|>|>=内部码对照表表1-1 内部码对照表内码单词内码单词内码单词内码单词1 PROGRAM2 CONST3 V AR4 INTEGER5 Call6 PROCEDURE7 IF8 THEN9 WHILE 10 DO 11 READ 12 WRITE 13 BEGIN 14 END 15 ODD 16 + 17 - 18 * 19 / 20 = 21 <> 22 < 23 <= 24 > 25 >= 26 , 27 . 28 ; 29 : 30 := 31 ( 32 ) 33 无符号整数34 标识符35 # 36 else实验过程及方法1.将上述内部码对照表输入TINY.L文件中2.利用FLEX.EXE程序根据TINY.L文件生成词法自动编译的C程序lex.yy.c文件3.运行lex.yy.c文件,读取所需编译程序的文件,生成一个词法分析结果的txt文件实验结果1.根据内部码对照表所编写的TINY.L文件见词法文件夹2.生成的lex.yy.c文件见词法文件夹中的源文件3.所需测试的程序代码存于test1.c文件中programabc;PROCEDURE ABC;vara,b,c:integer;begina:=1;b:=2;c:=1+2*3end.4.生成的词法分析结果如下(见out.txt)总结词法分析的代码编写没有花很多时间,只是在老师给的参考资料中稍微改了一些数据,就可以得到所需要的词法分析文件,但是此时词法分析的结果很重要,因为它涉及到后面的几个实验,决定了后面的实验能否顺利完成实验二实验目的通过完成语法分析程序,了解语法分析的过程和作用实验内容及要求实验内容:用递归子程序法实现对pascal的子集程序设计语言的分析程序实验要求:对源程序的内码流进行分析,如为文法定义的句子输出“success!”,否则,输出“compiler failed!”,以及出错的地方。
根据需要处理说明语句填写写相应的符号表供以后代码生成时使用。
注:语法定义为:<程序>→<程序首部> <分程序> {<分程序>}.<程序首部>→PROGRAM标识符;<分程序>→<过程首部> [<常量说明部分>] [<变量说明部分>] <复合语句><常量说明部分>→CONST <常量定义> {,<常量定义> } ;<常量定义>→标识符= 无符号整数<变量说明部分>→V AR <变量定义> {;<变量定义>};<变量定义>→标识符{,标识符}:<类型><类型>→INTEGER<过程首部>→PROCEDURE标识符;| PROCEDURE标识符(标识符:<类型>);<复合语句>→BEGIN<语句>{;<语句>}END<语句>→<赋值语句>|<条件语句>|<当型循环语句>|<过程调用语句>|<读语句>|<写语句>|<复合语句>|ε<赋值语句>→标识符:=<表达式><条件语句>→IF<条件>THEN<语句><当型循环语句>→WHILE<条件>DO<语句><过程调用语句>→CALL 标识符| CALL 标识符(<表达式>)<读语句>→READ(标识符{,标识符} )<写语句>→WRITE(<表达式>{,<表达式>})<条件>→<表达式><关系运算符><表达式> | ODD<表达式><表达式>→<项>{<加型运算符><项>}<项>→<因子>{<乘型运算符><因子>}<因子>→标识符| 无符号整数| (<表达式>)<加型运算符>→+|-<乘型运算符>→* | /<关系运算符>→=|<>|<|<=|>|>=说明:①<>:用左右尖括号括起来的是非终结符;②{}大括号相当于正则表达式中的()*,表示其中内容重复0次或N多次;③[]大括号表示可有可无,即方括号内的内容出现0次或1次;④注:该语言是大小写不敏感的,例如,IF与if是同一个单词。
实验算法对于每一个非终结元素都写出一个函数,根据文法中的语句推导得到函数的调用顺序,运用函数的嵌套调用,完成对语法的判断实验结果1.程序源代码见:语法.cpp函数说明:void token(); // 读取void Program(); //程序void HeadofProgram(); //程序首部void error(int n); //错误信息输出void Program_f(); //分程序void ConstState(); //常量说明部分void VARState(); //变量说明部分void VARDef(); //变量定义void type(); //数据类型void ProgressState(); //过程说明void HeadofProcess(); //过程首部void Sentence(); //句子void EvaluatSentence(); //赋值语句void ConditionSentence(); //条件语句void CirculateSentence(); //循环语句void CallProgressSentence();//过程调用语句void ReadSentence(); //读语句void WriteSentence(); //写语句void CompoundSentence(); //复合语句void Condition(); //条件void Expression(); //表达式void Term(); //项void Factor(); //因子void ADD(); //加减void Relation(); //关系运算符void MUL(); //乘除void BoolExpression(); //布尔表达式2.所需读入数据文件即为前面词法的输出文件out.txt3.根据前面词法的输出结果测的的语法分析结果如下:当测试程序为下面程序时的运行结果总结语法相对于词法来说,难度大了很多,对于函数的嵌套调用有很高的要求,调用函数的时候出现任何错误,都会使结果出错,代码也超过了500行,花费了很多时间来测试和修改。