《编译原理》实验指导书-2015
民生—编译原理实验指导书
编译原理实验指导书实验一词法分析一、实验目的通过实现PL/0语言(一种示例小语言)的词法分析器,理解词法分析过程,掌握程序各部分之间的接口安排。
二、实验要求1、要求每位同学单独完成词法分析器,并接受检查;2、撰写实验报告。
(1) 用有限自动机画出“三、实验内容”中的词法规则;(2) 实验报告不要摘抄全部代码,但需要流程图的形式描述程序结构;(3) 必须书写设计和实现的过程中出现的一些问题以及解决方法。
三、实验内容1、PL/0语言的单词结构关键字(10个):begin, end ,if ,then, while, do, const, var,call,procedure标识符:字母序列,最大长度10常数:整型常数算符和界符(17个):+,-,*,/,odd,=,<>,<,>,<=,>=,:=,(,) ,, ,.,;2、单词的种别划分标识符作为一种常数作为一种算符和界符每个单词作为一个单独种别3、PL/0的语言的词法分析器将要完成以下工作:(1)跳过分隔符(如空格,回车,制表符);(2)识别诸如begin,end,if,while等保留字;(3)识别非保留字的一般标识符。
(4)识别数字序列。
(5)识别:=,<=,>=之类的特殊符号。
4、词法分析器的实现方式:把词法分析器设计成一个独立子程序,以便于语法分析器调用。
词法分析器运行一次产生一个单词符号。
5、词法分析器的输出(单词种别编码,单词本身的值)说明:词法分析器的输出应该是(种别编码,属性值),但当种别不能唯一代表单词本身时,就需要组织符号表了。
为了降低实验难度,实验输出就改成了(种别编码,单词本身的值)。
6、词法分析器和语法分析器的接口设计要把词法分析器设计成独立的子程序,以便于被语法分析器调用,每调用语法分析器一次,就识别出一个单词符号。
实验二利用算符优先分析方法设计一个计算器一、实验目的在实验一的基础上,利用算符优先分析方法设计一个计算器,以加深对算符优先分析过程和语义分析过程的理解。
编译原理实验指导书
编译原理实验指导书《编译原理》实验指导书太原科技大学计算机学院 -3-1序《编译原理》是国内外各高等院校计算机科学技术类专业,特别是计算机软件专业的一门重要专业课程。
该课程系统地向学生介绍编译程序的结构、工作流程及编译程序各组成部分的设计原理和实现技术。
由于该课程理论性和实践性都比较强,内容较为抽象复杂,涉及到大量的软件设计和算法,因此,一直是一门比较难学的课程。
为了使学生更好地理解和掌握编译原理和技术的基本概念、基本原理和实现方法,实践环节非常重要,只有经过上机进行程序设计,才能使学生对比较抽象的教学内容产生具体的感性认识,增强学生综合分析问题、解决问题的能力,并对提高学生软件设计水平大有益处。
为了配合《编译原理》课程的教学,考虑到本课程的内容和特点,本指导书设置了七个综合性实验,分别侧重于词法分析、NFA的确定化、非递归预测分析、算符优先分析器的构造、LR分析、语义分析和中间代码的生成、基于DAG的基本块优化,以支持编译程序的各个阶段,基本涵盖了《编译原理》课程的主要内容。
本指导书可作为《编译原理》课程的实验或课程设计内容,在课程教学的同时,安排学生进行相关的实验。
实验平台可选择在MS-DOS或Windows操作系统环境,使用C/C++的任何版本作为开发工具。
学生在做完试验后,应认真撰写实验报告,内容应包括实验名称、实验目的、实验要求、实验内容、测试或运行结果等。
目录实验一词法分析 ........................................................... 错误!未定义书签。
实验二 NFA的确定化.................................................... 错误!未定义书签。
实验三非递归预测分析 ............................................... 错误!未定义书签。
编译原理实验指导书
编译原理实验指导书计算机学院实验1 词法分析程序一、实验目的构造simple语言的词法分析程序,程序要求能对输入的字符串流进行词法分析。
在实验的过程中,学会应用单词分析的方法——NFA(非确定有穷自动机)和DFA(确定有穷自动机),加深对词法分析原理的理解。
二、实验内容编写为任一正则文法(见实验参考(一)simple惯用的词法)构造非确定有穷自动机NFA并转换成确定有穷自动机DFA,并对任给的一个输入串(见实验参考(二)测试用输入串)进行词法分析的程序,程序的输出为单词的序列(见实验参考(三)程序输出形式)。
三、实验参考(一)simple 惯用的词法1. 下面是语言的关键字:Begin if then while do end所有的关键字都是保留字,并且必须是小写。
2. 下面是专用符号::= + * / < <= <> > >= = ; ( ) #3. 其他单词是标识符(ID)和整型常数(NUM),通过下列正规式定义:ID = letter(letter| digit)*NUM = digit digit*letter = a |…| z | A |…| Zdigit = 0 |…| 9小写和大写字母是有区别的。
思考:构造实数的正规表达式,力争实现对实数的识别及表示。
4. 空格由空白、换行符和制表符组成。
空格一般用来分隔ID、NUM、运算符和关键字,词法分析阶段通常被忽略。
5. 各种单词符号对应的种别码如下表所示:(二)词法分析程序的功能1. 输入为所给文法的源程序字符串。
2. 程序的输出形式为单词串的输出形式。
所输出的每一单词,均按形如(syn,token和sum)的二元式编码。
其中,syn 为单词种别码;token为存放的单词自身字符串;sum为整型常数。
3.测试源程序片断:begin x:=9; if x>0 then x:=2*x+1/3;end #。
编译原理实验指导书
陕西理工学院数学与计算机科学学院《编译原理》实验指导班级网络10级指导教师曹阳计算机工程教研室2012年8月25日编译原理实验指导书一、实验的目的《编译原理》是针对计算机专业的学生开设的一门专业基础课程,对引导学生进行科学思维和提高学生解决实际问题的能力有重要的作用。
开设“编译原理实验”的主要目的是让学生加深理解编译原理的基本理论、方法、词法分析、语法分析、中间代码的生成直到最后的代码生成,了解编译器原理,从而提高学生分析问、题解决问题的能力。
通过实验实现以下基本目标:1.深化已学的知识,完成从理论到实践的转化通过实验,进一步加深对编译原理基本思想、原理的了解。
2. 提高分析和解决实际问题的能力实验不仅是编译原理的一次模拟训练,同时通过实验,积累经验,提高分析和解决问题的能力。
3.培养“开拓创新”能力大力提倡和鼓励在程序中使用新方法,新技术。
激发学生实践的积极性与创造性,开拓思路,设计新算法,进行新创意,培养创造性能力。
二、参加实验的学生应具备的条件参加实验的学生应当具备计算机程序设计的一些基础的知识。
即学生应当熟练掌握和使用一种计算机操作系统(windows操作系统等)、一种程序设计语言(vb、vc、c、delphi等)。
三、实验要求实验的要求体现于整个工作的各个阶段中,可根据所选课题的特点而有所侧重,但应达到如下的基本要求:(1) 根据课题任务制定合理、可行的工作计划任务;(2) 制定适当的技术方案;(3) 学生在老师的指导下独立完成设计过程;(4) 撰写实验报告(包括实验内容中各个阶段所要求的文字材料);(5) 通过实验检查评定;四、实验项目与内容提要五、实验课程考核办法1、该实验课程考核成绩按百分制计算,满分为100分,60分为及格,60分以上者可获取该学分。
2、该实验课考核由三部分组成:实验课前预习(20%),实验操作(60%),实验报告(20%)。
3、各部分成绩由实验指导教师在每个实验项目完成后分别给出,在学期结束后或完成全部实验项目后综合给出该门实验课的成绩。
刘军_编译原理实验指导书_09软件1-2班
《编译原理》课程实验指导书一、使用说明《编译原理》课程实验指导书(以下简称:指导书)是针对计算机学院所开设的对应课程的上机实验而编写的教学文件,供学生上机实验时使用。
上机的工作环境要求:Windows 2000或以上操作系统、C++ 6.0或者其它高级程序设计语言。
学生应按指导教师的要求独立完成实验,并按要求撰写实验报告。
每一个实验,编程上机调试并且提交电子文档实验报告,以学号姓名作为文件名上传。
报告内容至少包含如下内容:1、学生基本情况:专业班级、学号、姓名2、实验题目、实验内容3、设计分析4、源程序代码5、测试用例(尽量覆盖所有分支)6、实验总结二、实验说明1、实验一:词法分析器设计实验类别:基础性实验实验学时:4分组人数:1人/组1、实验目的:(1)掌握词法分析器的构造过程以及基本方法。
(2)理解正规式、NFA、DFA及最小化DFA的转换过程和方法。
2、实验内容给定一个正规式R=XY*|YX*Y|XYX,请先在练习本上将此正规式转变为NFA、DFA、最小化DFA;对你所完成的最小化DFA进行编程,完成词法分析器工作。
2、实验二:算术表达式递归下降分析程序设计实验类别:设计性实验实验学时:4分组人数:1人/组1、实验目的:(1)掌握自上而下语法分析的要求与特点。
(2)掌握递归下降语法分析的基本原理和方法。
(3)掌握相应数据结构的设计方法。
2、实验内容:编程实现给定算术表达式的递归下降分析器。
算术表达式文法如下:E→E+T | TT→T*F | FF→(E) | i3、设计说明:首先改写文法为LL(1)文法;然后为每一个非终结符,构造相应的递归过程,过程的名字表示规则左部的非终结符;过程体按规则右部符号串的顺序编写。
编写者签字:刘军审阅者签字:张俊分管实验教学领导签字:王海晖。
编译原理实验指导书
编译原理实验指导书第1节概述1、本课程实践的目的和任务编译原理是一门实践性很强的课程,只有通过实践,才能真正掌握。
实际的编译程序是十分复杂的,有时由多达十几万条指令组成。
为此,编译原理的实践教学,采用简化编译过程的办法,选择最关键的3个环节──词法分析、语法分析(包括语义处理、产生无优化的目标指令)、连接调试,进行编程和调试训练。
每个环节作为一个实践课题。
2、实践方法任何一个实用的高级语言,其语法都比较复杂,如选其作为源语言,很难实践全过程。
故本实践将定义一个简化的语言──PASCAL语言的一个子集作为源语言,也可以自行定义一个简单的C语言子集,在3个题目中选择两个题目,也可以自行选择与编译技术相关的实验题目,设计调试出它的编译程序。
前后贯穿这一条主线进行实践。
每次都可利用课余时间编程,利用上机时间进行输入和调试。
建议使用C或C++或JAVA语言。
3、实践报告的规范和要求每个课题完成后写出实践报告。
实践报告包括程序设计时考虑的算法和方法;调试过程中出现的问题和解决的措施;提交电子版的程序清单和调试时所用的源程序。
4、简化的PASCAL语言子集的定义〈PASCAL子集程序〉→〈变量说明〉〈分程序〉。
〈变量说明〉→〈空〉|VAR〈变量表〉:INTEGER;〈变量表〉→〈变量〉|〈变量〉,〈变量表〉〈变量〉→〈标识符〉〈分程序〉→BEGIN〈语句组〉END〈语句组〉→〈语句〉|〈语句〉;〈语句组〉〈语句〉→〈赋值语句〉|〈条件语句〉|〈WHILE语句〉|〈分程序〉〈赋值语句〉→〈变量〉:=〈算术表达式〉〈条件语句〉→IF〈布尔表达式〉THEN〈语句〉ELSE〈语句〉〈WHILE语句〉→WHILE〈布尔表达式〉DO〈语句〉〈算术表达式〉→〈项〉|〈算术表达式〉+〈项〉|〈算术表达式〉-〈项〉〈项〉→〈初等量〉|〈项〉*〈初等量〉|〈项〉/〈初等量〉〈初等量〉→〈无符号数〉|〈变量〉|(〈算术表达式〉)〈关系表达式〉→〈算术表达式〉〈关系运算符〉〈算术表达式〉〈标识符〉→〈字母〉|〈标识符〉〈字母〉|〈标识符〉〈数字〉〈无符号数〉→〈数字〉|〈无符号数〉〈数字〉〈关系运算符〉→〈|〈=| =| 〉=| 〉|〈〉〈字母〉→ A│B│C│D│E│F│G│H│I│J│K│L│M│N│O│P│Q│R│S│T││U│V│W│X│Y│Z〈数字〉→ 1│2│3│4│5│6│7│8│9│0第2节词法分析本节进行词法分析程序的编程与调试。
编译原理实验指导书
《编译原理》实验指导书别小川于枫编写适用专业:计算机科学与应用江苏科技大学电子信息学院2005年2月前言《编译原理》是计算机专业的一门核心课程,在计算机本科教学中占有十分重要的地位。
由于《编译原理》课程兼有很强的理论性和实践性,并且编译程序构造的算法比较复杂,因而让学生在学习时普遍感到内容抽象、不易理解,难易掌握。
但是掌握编译原理的基本理论和设计思想是非常重要的,尤其是将本课程的理论知识与计算机应用中的许多领域紧密联系与广泛应用结合。
将有利于学生提高专业素质和适应社会多方面需要的能力。
因此,通过理论授课和上机实践,使学生对编译的基本概念、原理和方法有完整的和清楚的理解,并能正确地、熟练地加以运用。
通过实验逐步提高学生的编程能力和调试程序的能力以及解决实际问题的能力。
使学生培养出扎实的软件开发基本技能,并养成良好的编程风格,为进一步学习后续课程和将来从事应用软件开发奠定良好的基础。
实验课时具体内容安排如下:一、实验课的性质和目的(1)深刻理解程序语言编译系统的结构及各部分的功能。
(2)熟练掌握设计和构造程序语言编译系统的基本原理和技术。
(3)能独立编写清晰、工整、结论正确的编译原理的源程序。
(4)能学会上机进行正确调试,并进行程序修改。
即培养发现程序错误,排除错误的能力和经验。
二、实验课的基本要求:(1)掌握编译程序的功能和结构。
(2)掌握词法分析器的设计方法与实现步骤加深对讲授内容的理解,尤其是一些语法给定,通过上机实验帮助掌握。
(3)掌握语法分析器的设计方法与实现步骤。
(4)掌握符号表和存储空间的组织。
(5)掌握代码优化的作用与实现方法(6)掌握错误的诊断和校正方法。
三、主要实验教学方法实验前,由任课教师落实实验任务,每个学生必须事先独立完成好程序的设计的源程序编写工作。
实验课上对疑难点作集中辅导。
实验过程中随时针对不同的情况作个别启发式辅导。
实验后,学生撰写并提交实验报告。
最后,由实验教师根据每个学生的编程、上机调试能力、编程能力和实验结果及实验报告综合评定学生的实验成绩。
《编译原理》实验教学大纲
《编译原理》实验教学大纲一、实验目的和任务编译原理是计算机科学与技术专业的一门重要课程,它主要研究的是将高级语言程序翻译成机器语言程序的方法和技术。
通过本实验课程的学习,旨在使学生掌握编译原理的基本原理和方法,培养学生对编译器结构与构造技术的专门知识和技能,为学生今后进行编译器设计与实现打下基础。
二、实验设备和工具1.计算机和相关硬件设备2. 编程语言的开发环境,如C/C++或Java三、实验内容1.实验一:词法分析器设计与实现a)实验目的:学习词法分析器的原理和设计方法,掌握正则表达式、DFA和NFA的转换方法。
b)实验任务:i.设计并实现一个词法分析器的原型,能够正确地识别出给定的程序中的词法单元。
ii. 使用给定的正则表达式设计并实现识别给定程序中的关键字、标识符、常量等的词法分析器。
2.实验二:语法分析器设计与实现a)实验目的:学习语法分析器的原理和设计方法,掌握上下文无关文法和LR分析表的构造方法。
b)实验任务:i.学习并理解上下文无关文法和LR分析表的构造方法。
ii. 设计并实现一个简单的递归下降语法分析器。
3.实验三:语义分析器设计与实现a)实验目的:学习语义分析器的原理和设计方法,掌握语义动作的定义和处理方法。
b)实验任务:i.学习并理解语义分析器的原理和设计方法。
ii. 设计并实现一个简单的语义分析器,能够对给定的程序进行语义分析和语义动作的处理。
4.实验四:中间代码生成器设计与实现a)实验目的:学习中间代码生成器的原理和设计方法,掌握中间代码的生成和优化方法。
b)实验任务:i.学习并理解中间代码生成器的原理和设计方法。
ii. 设计并实现一个简单的中间代码生成器,能够将给定的程序翻译成中间代码。
5.实验五:目标代码生成器设计与实现a)实验目的:学习目标代码生成器的原理和设计方法,掌握目标代码的生成和优化方法。
b)实验任务:i.学习并理解目标代码生成器的原理和设计方法。
ii. 设计并实现一个简单的目标代码生成器,能够将中间代码翻译成目标代码。
《编译原理》实验指导书(程细柱)
前言“编译原理”课程是计算机本科专业的必选课程,上机实验是该课程的重要环节,应开实验数约为12学时。
一个编译程序把源程序翻译成等价的目标程序,一般应做词法分析、语法分析、语义分析、代码生成和代码优化等五个方面的工作,为了使学生对其有较深的理解,必须根据这五个方面设计实验。
本指导书正是根据课程的内容,将实验分为前期准备阶段、基本操作阶段和技术提高阶段三个阶段进行:①前期准备阶段的实验主要是为后续实验做好准备,应围绕编译原理课程进行设计,如:学生可根据教科书的内容,设计一个源程序的输入和扫描程序,并完成相应的设计报告;②基本操作阶段的实验是围绕着编译原理的五个方面的工作来进行,其内容主要是词法分析、语法分析、语义分析、代码生成和代码优化等,如:简单的词法分析程序、LL(1) 分析法算法、语义分析程序、中间代码和目标代码生成算法的实验,这些实验基本上包括了以上知识要点,学生可结合书本上有关的知识来完成;③技术提高阶段的实验是综合性课程设计实验,根据编译原理编制应用程序,不仅要求把书本上的内容掌握好,同时还需要自学一些相关的知识。
1目录第1章实验的一般知识 (3)1—1 软件实验室规则及安全守则 (3)1-2 实验条件 (3)1—3 实验的基本要求 (3)第2章实验技术及原理 (3)第3章实验项目 (4)实验一:源程序的输入和扫描(2学时) (4)实验二:词法分析算法(2学时) (6)实验三:LL(1) 分析算法(2学时) (8)实验四:语义分析算法(2学时) (11)实验五:中间代码生成算法(2学时) (14)实验六:目标代码生成算法(4学时) (14)实验七:“编译原理”课程设计(8学时) (14)附录:实验报告示例:有限自动机的运行实验 (16)参考文献:《编译原理》吕映芝、张素琴、蒋维杜等主编清华大学出版社《编译原理与实现》..金成植编高教出版社《编译程序设计原理》..杜淑敏王永宁编北大出版社2第1章实验的一般知识1—1 软件实验室规则及安全守则见《软件实验室规则及安全守则》)。
编译原理实验指导书(-).docx
编译原理实验指导书合肥学院计算编译原理实验指导书实验一词法分析一、实验目的:通过设计编制调试一个具体的词法分析程序,加深对词法分析原理的理解。
并掌握在对程序设计语言源程序进行扫描过程屮将其分解为各类单词的词法分析方法。
编制一个读单词过程,从输入的源程序中,识別出各个具有独立意义的单词, 即基木保留字、标识符、常数、运算符、分隔符五大类。
并依次输出各个单词的内部编码及单词符号自身值。
(遇到错误时可显示“Error”,然后跳过错误部分继续显示)二、实验预习提示1、词法分析器的功能和输出格式词法分析器的功能是输入源程序,输出单词符号。
词法分析器的单词符号常常农示成以下的二元式(单词种别码,单词符号的属性值)。
本实验中,采用的是一类符号一种别码的方式。
2、单词的BNF表示<标识符> -V字母〉v字母数字串〉V字母数字串一V字母〉V字母数字串>|v数字〉V字母数字串〉Iv下划线>v字母数字串I e<无符号整数一V数字〉v数字串〉V数字串〉一V数字〉V数字串〉v加法运算符>-+<减法运算符〉->・V大于关系运算符>->>V大于等于关系运算符>-> =3、“超前搜索”方法词法分析时,常常会用到超前搜索方法。
如当前待分析字符串为“”,当前字符为此时,分析器倒底是将其分析为犬于关系运算符还是犬于等于关系运算符呢?显然,只有知道下一个字符是什么才能下结论。
超前读了一个字符所以要回退一个字符,词法分析器才能正常运行。
在分析标识符,无符号整数等时也有类似情况。
4、模块结构Y饗冲区扫播一个辛閒N ▼三、实验过程和指导:(-)准备:1・阅读课木有关章节,明确语言的语法,写出基木保留字、标识符、常'数、运算符、分隔符和程序例。
2 .初步编制好程序。
3•准备好多组测试数据。
(二)上课上机: 将源代码拷贝到机上调试,发现错误,再修改完善。
第二次上机调试通过。
(三)程序要求:程序输入/输出示例:如源程序为C语言。
输入如卜•一段:main(){int a,b;a = 1 0;b = a 4- 20;}要求输出如下图。
实验指导书编译原理
编译原理实验教学指导书计算机科学与工程学院华南理工大学目录1 实验简介 (3)2 TINY+语言介绍 (4)2.1 TINY+语言的词法定义 (4)2.2 TINY+的语法定义 (5)2.3 TINY+的语义定义 (7)2.4 用TINY+语言编写的示例程序 (7)3 实验1:实现TINY+语言的词法分析器 (9)3.1 实验目的 (9)3.2 实验要求 (10)3.3 TINY+的测试程序及词法分析器的输出 (10)4 实验2:实现TINY+的语法分析器、语义分析器以及中间代码生成器 (13)4.1 实验目的 (13)4.2 实验要求 (14)4.3 TINY+示例程序及其输出 (14)附录:和TINY+文法规则对应的生成三地址中间代码的属性文法 (16)1 实验简介学生在实验中,构造一个将TINY+高级程序设计语言转换为TINY+虚拟机上的中间代码的编译器。
整个实验包括两个部分:实验一完成TINY+编译器的词法分析器部分;实验二完成TINY+编译器的语法分析器部分、语义分析器部分及中间代码生成器部分。
每个同学必须独立完成自己的实验,与其他同学的讨论或合作是允许的,但必须是有限度的,可以互相交流想法和方法,但不能抄袭。
学术不端将导致成绩为零。
TINY+的编译器必须用C语言或C++语言实现(推荐使用Microsoft Visual Studio)。
2 TINY+语言介绍实验定义了一种叫TINY+的高级程序设计语言,该语言是对TINY 语言的一个扩充,TINY+比TINY增加了程序的声明部分,while语句,字符串类型定义等等,在本节的描述中,用蓝色字体标识的是TINY语言原有的词法及语法规定,而用红色字体标识的是TINY+语言扩充的词法及语法规定。
本节主要是对TINY+语言的介绍,具体包括:1)TINY+语言的词法定义,包括对TINY+语言的单词(token)的描述;2)TINY+语言语法结构的EBNF描述;3)TINY+语言主要的语义描述;4)TINY+的实例程序2.1 TINY+语言的词法定义1.TINY+语言的关键字(keyword)包括:or and int bool char while doif then else end repeat until read write所有的关键字是程序设计语言保留使用的,并且用小写字母表示,用户自己定义的标识符不能和关键字重复。
《编译原理》课程实验指导书(2015)
编译原理实验指导书上海大学计算机学院《编译原理》课程组2014年2月目录一、课程简介 (2)二、实验目的 (2)三、实验环境 (2)四、实验任务 (2)五、PL0语言简介 (2)1.PL/0语言文法的EBNF (3)2.PL/0语言的词汇表 (4)六、实验项目 (5)实验一识别标识符 (5)实验二词法分析 (7)实验三语法分析 (10)实验四语义分析 (12)实验五中间代码生成 (13)实验六代码优化 (14)七、参考文献 (16)八、附录——PL0语言编译源程序清单(部分) (17)编译原理实验指导书一、课程简介1.课程名称:编译原理(Principle of Compiler)2.课程编码:083050133.课程总学时:60学时[理论:30学时;研讨:10学时;实验:20学时]4.课程总学分:5学分二、实验目的编译原理是计算机类专业特别是计算机软件专业的一门重要专业课。
设置该课程的目的在于系统地向学生讲述编译系统的结构、工作流程及编译程序各组成部分的设计原理和实现技术,使学生通过学习既掌握编译理论和方法方面的基本知识,也具有设计、实现、分析和维护编译程序等方面的初步能力。
编译原理是一门理论性和实践性都比较强的课程。
进行上机实验的目的是使学生通过完成上机实验题目加深对课堂教学内容的理解。
同时培养学生实际动手能力。
三、实验环境微机CPU P4以上,256M以上内存,安装好C语言,或C++,或Visual C++开发环境。
四、实验任务用C/C++/Visual C++语言编写PL/0语言的词法分析程序、语法分析程序、语义分析程序、中间代码生成程序。
五、PL0语言简介PL/0语言功能简单、结构清晰、可读性强,而又具备了一般高级程序设计语言的必须部分,因而PL/0语言的编译程序能充分体现一个高级语言编译程序实现的基本方法和技术。
1.PL/0语言文法的EBNF<程序>::=<分程序>.<分程序> ::=[<常量说明>][<变量说明>][<过程说明>]<语句><常量说明> ::=CONST<常量定义>{,<常量定义>};<常量定义> ::=<标识符>=<无符号整数><无符号整数> ::= <数字>{<数字>}<变量说明> ::=V AR <标识符>{, <标识符>};<标识符> ::=<字母>{<字母>|<数字>}<过程说明> ::=<过程首部><分程序>{; <过程说明> };<过程首部> ::=PROCEDURE <标识符>;<语句> ::=<赋值语句>|<条件语句>|<当循环语句>|<过程调用语句>|<复合语句>|<读语句><写语句>|<空> <赋值语句> ::=<标识符>:=<表达式><复合语句> ::=BEGIN <语句> {;<语句> }END<条件表达式> ::= <表达式> <关系运算符> <表达式> |ODD<表达式> <表达式> ::= [+|-]<项>{<加法运算符> <项>}<项> ::= <因子>{<乘法运算符> <因子>}<因子> ::= <标识符>|<无符号整数>| ‘(’<表达式>‘)’<加法运算符> ::= +|-<乘法运算符> ::= *|/<关系运算符> ::= =|#|<|<=|>|>=<条件语句> ::= IF <条件表达式> THEN <语句><过程调用语句> ::= CALL 标识符<当循环语句> ::= WHILE <条件表达式> DO <语句> <读语句> ::= READ‘(’<标识符>{,<标识符>}‘)’<写语句> ::= WRITE‘(’<表达式>{,<表达式>}‘)’<字母> ::= a|b|…|X|Y|Z<数字> ::= 0|1|…|8|92.PL/0语言的词汇表六、实验项目实验一识别标识符1.实验目的●根据PL/0语言的文法规范,编写PL/0语言的标识符识别程序。
编译原理实验指导书(2015)
LIAOCHENG UNIVERSITY编译原理实验指导书聊城大学计算机学院2011年3月目录《编译原理》课程实验教学大纲 (1)实验一词法分析器的设计 (3)基本信息 (3)实验目的 (3)实验内容 (3)实验扩充 (5)实验说明 (5)实验考核方式 (5)实验辅导 (5)实验二语法分析器的设计 (10)基本信息 (10)实验目的 (10)实验内容 (10)实验说明: (10)实验考核方式: (10)实验辅导 (11)能力扩展 (19)附录 (19)《编译原理》课程实验教学大纲课程名称:编译原理英文名称:Compile principles设置形式:非独立设课课程模块:专业方向课实验课性质:专业实验课程编号:509615课程负责人:姜华大纲主撰人:姜华大纲审核人:左风朝一、学时、学分课程总学时:72实验学时:8课程学分:4二、适用专业及年级计算机科学与技术、软件工程三年级三、课程目标与基本要求《编译原理》课程是计算机专业的核心课程,是培养计算机技术高级人才的必修课程。
该课程通过程序设计语言和语言处理软件的理论与技术的教学,培养学生利用计算机语言处理技术进行系统分析和软件设计的能力。
<<编译原理>>是理论与实践并重的课程,这门实验课要综合运用一、二、三年级所学的多门课程的内容。
实验目标与要求;1.学会用高级程序设计语言设计词法分析器。
2.学会用高级程序设计语言设计语法分析器。
四、主要仪器设备Windows操作系统,编程语言采用C、C++,集成调试环境采用TC或Microsoft Visual Studio 6五、实验项目及教学安排六、考核方式及成绩评定根据学生实验出勤情况、实验态度、实验报告成绩等方面评定实验成绩。
实验报告平均成绩(含实验理论)占实验成绩的50%,实验技能平均成绩(含实验态度)占实验成绩的50%。
实验成绩占该课程考试总成绩的10%—20%。
在机器上将程序及运行结果上传至服务器,由实习教师给出优、良、中、及格、不及格。
《编译原理》科学实验指导说明书
《编译原理》实验指导书实验一词法分析器的设计一、实验目的和要求加深对状态转换图的实现及词法分析器的理解。
熟悉词法分析器的主要算法及实现过程。
要求学生掌握词法分析器的设计过程,并实现词法分析。
二、实验基本内容给出一个简单语言的词法规则,画出状态转换图,并依据状态转换图编制出词法分析程序,能从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类。
并依次输出各个单Error”,然后跳过错误部分继续显示)词法规则如下:三、实验时间:上机三次。
第一次按照自己的思路设计一个程序。
第二、三次在理论课学习后修改程序,使得程序结构更加合理。
四、实验过程和指导:(一)准备:1.阅读课本有关章节(c/c++,数据结构),花一周时间明确语言的语法,写出基本算法以及采用的数据结构和要测试的程序例。
2.初步编制好程序。
3.准备好多组测试数据。
(二)上课上机:将源代码拷贝到机上调试,发现错误,再修改完善。
(三)程序要求:程序输入/输出示例:输入如下一段:main(){/*一个简单的c++程序*/int a,b; //定义变量a = 10;b = a + 20;}要求输出如右图。
要求:(1) 剔除注解符(2) 常数为无符号整数(可增加实型数,字符型数等)(四)练习该实验的目的和思路:程序开始变得复杂起来,可能是大家以前编过的程序中最复杂的,但相对于以后的程序来说还是简单的。
因此要认真把握这个过渡期的练习。
程序规模大概为200行及以上。
通过练习,掌握对字符进行灵活处理的方法。
(五)为了能设计好程序,注意以下事情:1.模块设计:将程序分成合理的多个模块(函数/类),每个模块(类)做具体的同一事情。
2.写出(画出)设计方案:模块关系简图、流程图、全局变量、函数接口等。
3.编程时注意编程风格:空行的使用、注释的使用、缩进的使用等。
4.程序设计语言不限,建议使用面向对象技术及可视化编程语言,如C++,VC,JA V A,VJ++等。
编译原理实验指导
编译原理实验指导目录实验1:文法的读入和输出 (3)实验2:词法分析程序的设计 (5)实验3:LL(1)文法构造 (7)实验4:语法分析程序的设计(1) (9)实验5:语法分析程序的设计(2) (11)实验6:逆波兰式的翻译和计算 (15)实验7:语法制导的三地址代码生成 (17)实验1 文法的读入和输出一、实验目的熟悉文法的结构,了解文法在计算机内的表示方法。
二、实验内容1、设计一个表示文法的数据结构;2、从文本文件中读入文法,利用定义的数据结构存放文法,并输出;3、本实验结果还将用于实验3。
三、实验要求1、了解文法定义的4个部分:G(Vn, Vt, S, P)Vn 文法的非终结符号集合,在实验中用大写的英文字母表示;Vt 文法的终结符号集合,在实验中用小写的英文字母表示;S 开始符号,在实验中是Vn集合中的一个元素;P 产生式,分左部和右部,左部为非终结符号中的一个,右部为终结符号或非终结符号组成的字符串,如S->ab|c2、根据文法各个部分的性质,设计一个合理的数据结构用来表示文法,1)若使用C语言编写,则文法可以设计成结构体形式,结构体中应包含上述的4部分,2)若使用C++语言编写,则文法可以设计成文法类形式,类中至少含有4个数据成员,分别表示上述4个部分文法数据结构的具体设计由学生根据自己想法完成,并使用C或C++语言实现设计的数据结构。
3、利用完成的数据结构完成以下功能:1)从文本文件中读入文法(文法事先应写入文本文件);2)根据文法产生式的结构,分析出文法的4个部分,分别写入定义好的文法数据结构的相应部分;3)整理文法的结构;4)在计算机屏幕或者文本框中输出文法,文法输出按照一个非终结符号一行,开始符号引出的产生式写在第一行,同一个非终结符号的候选式用“|”分隔的方式输出。
四、实验环境PC微机DOS操作系统或Windows 操作系统Turbo C 程序集成环境或Visual C++ 程序集成环境五、实验步骤1、根据文法定义,设计出文法数据结构2、用学生选择的语言,实现文法的数据结构3、编写调试文法读入和输出程序,4、测试程序运行效果:从文本文件中读入一个文法,在屏幕上输出,检查输出结果。
《编译原理实验》实验指导书
《编译原理实验》实验指导书编辑整理:尊敬的读者朋友们:这里是精品文档编辑中心,本文档内容是由我和我的同事精心编辑整理后发布的,发布之前我们对文中内容进行仔细校对,但是难免会有疏漏的地方,但是任然希望(《编译原理实验》实验指导书)的内容能够给您的工作和学习带来便利。
同时也真诚的希望收到您的建议和反馈,这将是我们进步的源泉,前进的动力。
本文可编辑可修改,如果觉得对您有帮助请收藏以便随时查阅,最后祝您生活愉快业绩进步,以下为《编译原理实验》实验指导书的全部内容。
广州大学实验课程建设项目《编译原理实验》实验指导书广州大学计算机科学与教育软件学院2015年3月实验过程要求在《面向对象设计与开发》的课程实验过程中,要求学生做到:(1)预习实验指导书有关部分,认真做好实验内容的准备,就实验可能出现的情况提前思考和分析.(2)仔细观察上机时出现的各种现象,记录主要情况,做出必要说明和分析.(3)认真书写实验报告。
实验报告包括实验目的和要求,实验情况及其分析。
对需编程的实验,写出程序设计说明,给出源程序框图和清单。
(4)遵守机房纪律,服从辅导教师指挥,爱护实验设备.(5)每次上机应按照实际所用的机器在签到表内的签名栏签到登记。
若所用机器编号大于50(签到表最大编号),则应在实际编号-50所得的编号行内账户名栏内签到,并在姓名前后用括号括起来。
第一次上机时选择与自己的班序号相同编号的机器。
此后每次使用第一次签到所用的机器(如忘记,可参考考勤签到表上的第1次签名),不得自行更改。
如确需换机,须征得老师的同意后在第1次上机签名栏内注明变更机号(原机号不得涂抹掉)并按新机号上机,否则后果自负。
教师将以登记的(第一次)机号作为学生考勤与课堂纪律巡查的依据。
如果登记的机号上无人,则视为该机号登记的学生缺勤。
如果签到的机号上没有人,则该签到的学生将被视为作弊而受到惩罚.假设姓名为“张三”,签到格式为: 机器号帐户名 签名 3(53)机器号 帐户名 签名 3(53)若所使用的机器不在课表指定的课室,则还应注明课室号,如下图所示:机器号帐户名 签名 3(53)机器号 帐户名 签名 3(53)如果登记的机器出现故障,需要换机时,应首先告知指导教师,经确认后可以换到其它没有被占用的机器,并要求在课程的后续上机中使用该机器、签到.若在课中更换了机器,则需在第一次签名处标注新机号,同时在签到表的下部空表中注明用小号字体注明换机原因并通知机房管理员:机器号(6)考勤员/学委/班长/其他班干部/其他同学在上课前到机房管理室417领取实验日志并填写实验项目、时间等内容后传给各位同学签名,课后放回原处.(7)实验课程不得迟到。
编译原理实验指导书1524
《编译原理》实验指导书适用专业:运算机科学与技术网络工程软件工程物联网工程编写者:编译原理课程组修订时刻:2015年9月一、课程的教学目标本课程融验证性实验与创新设计实验于一体,使学生把构造程序语言编译系统的大体原理和技术应用于实践,把握设计和构造程序语言编译系统的工作框架和开发实现进程,增强学生开发较大型系统软件的能力。
通过对一个经常使用高级程序设计语言的简单语言子集编译系统中词法分析、语法分析、语义处置模块的设计、开发,把握实际编译系统的核心结构、工作流程及其实现技术,取得分析、设计、实现编译程序等方面的实际操作能力,增强设计、编写和调试程序的能力。
通过开源编译器分析、编译进程可视化等扩展实验,增进学生增强复杂系统分析、设计和实现能力,鼓舞学生创新意识和能力。
二、实验内容本课程的实验内容分为三个实验项目,词法分析程序设计与实现、语法分析程序设计与实现、语义处置程序设计与实现,总的实验学时为30课时,各项实验学时分派表如表1。
表1:各项实验学时分派表体实验部份要求每一个同窗完成,扩展实验部份供实践能力较强的学生选做。
三、实验要求1、每次实验前学生应详细阅读实验指导书,做好实验的设计和预备工作。
2、独立完成实验,程序书写符合程序书写标准,踊跃配合实验进度检查和演示。
3、按要求完成实验报告。
不同意不完整的实验报告或说明与程序、运行结果不符合的作业。
4、实验报告电子版实验报告和源程序在最后一次机时后的一周内上交。
每人上交一个紧缩文件,其命名格式为“学号_姓名.rar”(“组长学号_姓名.rar”),内含实验报告和一个命名为“源程序”的文件夹,其中包括一个说明文件和源程序,说明文件描述程序运行环境和利用方式,源程序应是通过调试、测试成功的程序,并应有相应的注释、运行环境和利用方式简介。
四、实验报告每一个人针对所完成的实验内容撰写实验报告,实验报告要紧包括三方面内容:一、实验设计:实验采纳的实现方式和依据,如描述语言的文法及其机内表示,词法分析的单词分类码表、状态转换图或状态矩阵等,语法分析顶用到的分析表或优先矩阵等,语法制导翻译中文法的拆分和语义动作的设计编写等;具体的设计结果,应包括整体设计思想和实现算法,程序结构的描述,各部份要紧功能的说明,和所用数据结构的介绍等。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
武汉科技大学计算机科学与技术学院编译原理实验指导书实验一词法分析器设计【实验目的】1.熟悉词法分析的基本原理,词法分析的过程以及词法分析中要注意的问题。
2.复习高级语言,进一步加强用高级语言来解决实际问题的能力。
3.通过完成词法分析程序,了解词法分析的过程。
【实验内容】用C语言编写一个PL/0词法分析器,为语法语义分析提供单词,使之能把输入的字符串形式的源程序分割成一个个单词符号传递给语法语义分析,并把分析结果(基本字,运算符,标识符,常数以及界符)输出。
【实验要求】1.要求绘出词法分析过程的流程图。
2.根据词法分析的目的以及内容,确定完成分析过程所需模块。
3.写出每个模块的源代码,并给出注释。
4.整理程序清单及所得结果。
【说明】运行成功以后,检查程序,并将运行结果截图打印粘贴到实验报告上。
辅助库函数scanerLib设计以及使用说明:下面内容给出了一个辅助库函数的接口说明以及具体实现。
接口设计//字符类class Token{TokenType type;String str;Int line;}//词法分析结果输出操作类class TokenWriter{ArrayList tokens; //用来记录所识别出来的tokenTokenWriter(); //构造函数指定输入文件名,创建文件输出流V oid Add(Token); //将词法分析器中分析得到的Token添加到tokens中WriteXML(); //将tokens写出到目标文件.xml中}//词法分析操作词法分析生成文件接口<暂时不需要对该类的操作;下一步做语法分析的时候使用>class TokenReader{ArrayList tokens;TokenReader(); //构造函数输入文件名;初始化Token Next(); //返回下一个Token;Token Back(); //回退一个Token,并返回回退后的当前Token ReadXML(); //从文件中读出所有Token到tokens}使用:TokenWriter tw = new TokenWriter();While() {Token tok = getToken();Tw.Add(tok);}tw.WriteXML();TokenReader tr = new TokenReader();Tok,ReadXML();Token tok = new Token();While() {Tok = tr.Next();Process(tok);}类图:TokenWriter-tokens : ArrayList-scanfile : string+TokenWriter(string)+Add(Token) : void+WriteXML() : voidTokenReader-tokens : ArrayList-scanfile : string-pos : int+TokenWriter(string)+Next() : Token+Back() : Token+WriteXML() : void操作类库源码Token.cs //字符类ReservedWord.cs //保留字类TokenWriter.cs //结果输出TokenReader.cs //操作词法分析生成文件,进行下一步的工作使用时注意事项:1)定义文法中涉及到的所有字符类型,修改Token.cs文件中public enum TokenType{//自己定义的所有字符类型};2)对于保留字,在词法分析的过程中进行定义,例如:Hashtable reservedWords = new Hashtable();reservedWords.Add("if",TokenType.IF);reservedWords.Add("else",TokenType.ELSE);reservedWords.Add("while",TokenType.WHILE);reservedWords.Add("return",TokenType.RETURN);reservedWords.Add("void",TokenType.VOID);reservedWords.Add("int",TokenType.INT);可以继续添加其它的保留字;也可以将保留字表定义为其它的类型结构进行存储。
3)进行词法分析,词法分析的过程中,可以使用Token、ReservedWord的类型定义以及TokenWriter类中给出的接口函数进行操作。
4)同时还给出了一个较复杂的语言文法的词法分析程序scanner.cs。
示例程序举例:设置输入:prime.cm输出:prime.xml实验二 LL(1)语法分析程序设计【实验目的】1.熟悉判断LL(1)文法的方法及对某一输入串的分析过程。
2.学会构造表达式文法的预测分析表。
【实验内容】编写一个语法分析程序,对于给定的输入串,能够判断识别该串是否为给定文法的句型。
【实验要求】1.输入一个LL(1)文法,构造相应的LL(1)预测分析表。
2.从键盘读入输入串,由算法判断该输入串是否为该文法的句子,若正确,就通过,若错误就报错。
(可参考教材96页的例题1)【说明】语法分析主要是将从词法分析那里得来的记号构成一棵语法树。
例:SHMA#adbe#S->aHH->aMdH->dM->AbM->A->aMA->e分析例句:aaabd#/*-------------------LL(1)语法分析--------------------*/#include "stdio.h"#include "stdlib.h"#define MaxRuleNum 8#define MaxVnNum 5#define MaxVtNum 5#define MaxStackDepth 20#define MaxPLength 20#define MaxStLength 50struct pRNode/*产生式右部结构*/{int rCursor;/*右部序号*/struct pRNode *next;};struct pNode/*产生式结点结构*/{int lCursor;/*左部符号序号*/int rLength;/*右部长度*//*注当rLength = 1 时,rCursor = -1为空产生式*/struct pRNode *rHead;/*右部结点头指针*/};char Vn[MaxVnNum + 1];/*非终结符集*/int vnNum;char Vt[MaxVtNum + 1];/*终结符集*/int vtNum;struct pNode P[MaxRuleNum];/*产生式*/int PNum;/*产生式实际个数*/char buffer[MaxPLength + 1];char ch;/*符号或string ch;*/char st[MaxStLength]; /*要分析的符号串*/struct collectNode/*集合元素结点结构*/{int nVt;/*在终结符集中的下标*/struct collectNode *next;};struct collectNode* first[MaxVnNum + 1];/*first集*/struct collectNode* follow[MaxVnNum + 1];/*follow集*/int analyseTable[MaxVnNum + 1][MaxVtNum + 1 + 1];/*预测分析表存放为产生式的编号,+1用于存放结束符,多+1用于存放#(-1)*/ int analyseStack[MaxStackDepth + 1];/*分析栈*/int topAnalyse;/*分析栈顶*//*int reverseStack[MaxStackDepth + 1];/*颠倒顺序栈*//*int topReverse;/*倒叙栈顶*/void Init();/*初始化*/int IndexCh(char ch);/*返回Vn在Vn表中的位置+100、Vt在Vt表中的位置,-1表示未找到*/void InputVt();/*输入终结符*/void InputVn();/*输入非终结符*/void ShowChArray(char* collect, int num);/*输出Vn或Vt的内容*/void InputP();/*产生式输入*/bool CheckP(char * st);/*判断产生式正确性*/void First(int U);/*计算first集,U->xx...*/void AddFirst(int U, int nCh);/*加入first集*/bool HaveEmpty(int nVn); /*判断first集中是否有空(-1)*/void Follow(int V);/*计算follow集*/void AddFollow(int V, int nCh, int kind);/*加入follow集,kind = 0表加入follow集,kind = 1加入first集*/void ShowCollect(struct collectNode **collect);/*输出first或follow集*/void FirstFollow();/*计算first和follow*/void CreateAT();/*构造预测分析表*/void ShowAT();/*输出分析表*/void Identify(char *st);/*主控程序,为操作方便*//*分析过程显示操作为本行变换所用,与教程的显示方式不同*/ void InitStack();/*初始化栈及符号串*/void ShowStack();/*显示符号栈中内容*/void Pop();/*栈顶出栈*/void Push(int r);/*使用产生式入栈操作*/#include "LL1.h"void main(void){char todo,ch;Init();InputVn();InputVt();InputP();getchar();FirstFollow();printf("所得first集为:");ShowCollect(first);printf("所得follow集为:");ShowCollect(follow);CreateAT();ShowAT();todo = 'y';while('y' == todo){printf("\n是否继续进行句型分析?(y / n):");todo = getchar();while('y' != todo && 'n' != todo){printf("\n(y / n)? ");todo = getchar();}if('y' == todo){int i;InitStack();printf("请输入符号串(以#结束) : ");ch = getchar();i = 0;while('#' != ch && i < MaxStLength) {if(' ' != ch && '\n' != ch){st[i++] = ch;}ch = getchar();}if('#' == ch && i < MaxStLength){st[i] = ch;Identify(st);}elseprintf("输入出错!\n");}}getchar();}void Init(){int i,j;vnNum = 0;vtNum = 0;PNum = 0;for(i = 0; i <= MaxVnNum; i++)Vn[i] = '\0';for(i = 0; i <= MaxVtNum; i++)Vt[i] = '\0';for(i = 0; i < MaxRuleNum; i++){P[i].lCursor = NULL;P[i].rHead = NULL;P[i].rLength = 0;}PNum = 0;for(i = 0; i <= MaxPLength; i++) buffer[i] = '\0';for(i = 0; i < MaxVnNum; i++){first[i] = NULL;follow[i] = NULL;}for(i = 0; i <= MaxVnNum; i++){for(j = 0; j <= MaxVnNum + 1; j++)analyseTable[i][j] = -1;}}/*返回Vn在Vn表中的位置+100、Vt在Vt表中的位置,-1表示未找到*/ int IndexCh(char ch){int n;n = 0;/*is Vn?*/while(ch != Vn[n] && '\0' != Vn[n])n++;if('\0' != Vn[n])return 100 + n;n = 0;/*is Vt?*/while(ch != Vt[n] && '\0' != Vt[n])n++;if('\0' != Vt[n])return n;return -1;}/*输出Vn或Vt的内容*/void ShowChArray(char* collect){int k = 0;while('\0' != collect[k]){printf(" %c ", collect[k++]);}printf("\n");}/*输入非终结符*/void InputVn(){int inErr = 1;int n,k;char ch;while(inErr){printf("\n请输入所有的非终结符,注意:");printf("请将开始符放在第一位,并以#号结束:\n");ch = ' ';n = 0;/*初始化数组*/while(n < MaxVnNum){Vn[n++] = '\0';}n = 0;while(('#' != ch) && (n < MaxVnNum)){if(' ' != ch && '\n' != ch && -1 == IndexCh(ch)) {Vn[n++] = ch;vnNum++;}ch = getchar();}Vn[n] = '#';/*以“#”标志结束用于判断长度是否合法*/ k = n;/*k用于记录n以便改Vn[n]='\0'*/if('#' != ch){if( '#' != (ch = getchar())){while('#' != (ch = getchar()));printf("\n符号数目超过限制!\n");inErr = 1;continue;}}/*正确性确认,正确则,执行下下面,否则重新输入*/Vn[k] = '\0';ShowChArray(Vn);ch = ' ';while('y' != ch && 'n' != ch){if('\n' != ch){printf("输入正确确认?(y/n):");}scanf("%c", &ch);}if('n' == ch){printf("录入错误重新输入!\n");inErr = 1;}else{inErr = 0;}}}/*输入终结符*/void InputVt(){int inErr = 1;int n,k;char ch;while(inErr){printf("\n请输入所有的终结符,注意:");printf("以#号结束:\n");ch = ' ';n = 0;/*初始化数组*/while(n < MaxVtNum){Vt[n++] = '\0';}n = 0;while(('#' != ch) && (n < MaxVtNum)){if(' '!= ch && '\n' != ch && -1 == IndexCh(ch)) {Vt[n++] = ch;vtNum++;}ch = getchar();}Vt[n] = '#';/*以“#”标志结束*/k = n;/*k用于记录n以便改Vt[n]='\0'*/if('#' != ch){if( '#' != (ch = getchar())){while('#' != (ch = getchar()))printf("\n符号数目超过限制!\n");inErr = 1;continue;}}/*正确性确认,正确则,执行下下面,否则重新输入*/Vt[k] = '\0';ShowChArray(Vt);ch =' ';while('y' != ch && 'n' != ch){if('\n' != ch){printf("输入正确确认?(y/n):");}scanf("%c", &ch);}if('n' == ch){printf("录入错误重新输入!\n");inErr = 1;}else{inErr = 0;}}}/*产生式输入*/void InputP(){char ch;int i = 0, n,num;printf("请输入文法产生式的个数:");scanf("%d", &num);PNum = num;getchar();/*消除回车符*/printf("\n请输入文法的%d个产生式,并以回车分隔每个产生式:", num); printf("\n");while(i < num){printf("第%d个:", i);/*初始化*/for(n =0; n < MaxPLength; n++)buffer[n] = '\0';/*输入产生式串*/ch = ' ';n = 0;while('\n' != (ch = getchar()) && n < MaxPLength) {if(' ' != ch)buffer[n++] = ch;}buffer[n] = '\0';/*printf("%s", buffer);*/if(CheckP(buffer)){/*填写入产生式结构体*/pRNode *pt, *qt;P[i].lCursor = IndexCh(buffer[0]);pt = (pRNode*)malloc(sizeof(pRNode));pt->rCursor = IndexCh(buffer[3]);pt->next = NULL;P[i].rHead = pt;n = 4;while('\0' != buffer[n]){qt = (pRNode*)malloc(sizeof(pRNode));qt->rCursor = IndexCh(buffer[n]);qt->next = NULL;pt->next = qt;pt = qt;n++;}P[i].rLength = n - 3;i++;/*调试时使用*/}elseprintf("输入符号含非法在成分,请重新输入!\n"); }}/*判断产生式正确性*/bool CheckP(char * st){int n;if(100 > IndexCh(st[0]))return false;if('-' != st[1])return false;if('>' != st[2])return false;for(n = 3; '\0' != st[n]; n ++){if(-1 == IndexCh(st[n]))return false;}return true;}/*====================first & follow======================*/ /*计算first集,U->xx...*/void First(int U){int i,j;for(i = 0; i < PNum; i++){if(P[i].lCursor == U){struct pRNode* pt;pt = P[i].rHead;j = 0;while(j < P[i].rLength){if(100 > pt->rCursor){/*注:此处因编程出错,使空产生式时rlength同样是1,故此处同样可处理空产生式*/AddFirst(U, pt->rCursor);break;}else{if(NULL == first[pt->rCursor - 100]){First(pt->rCursor);}AddFirst(U, pt->rCursor);if(!HaveEmpty(pt->rCursor)){break;}else{pt = pt->next;}}j++;}if(j >= P[i].rLength)/*当产生式右部都能推出空时*/AddFirst(U, -1);}}}/*加入first集*/void AddFirst(int U, int nCh)/*当数值小于100时nCh为Vt*//*当处理非终结符时,AddFirst不添加空项(-1)*/{struct collectNode *pt, *qt;int ch;/*用于处理Vn*/pt = NULL;qt = NULL;if(nCh < 100){pt = first[U - 100];while(NULL != pt){if(pt->nVt == nCh)break;else{qt = pt;pt = pt->next;}}if(NULL == pt){pt = (struct collectNode *)malloc(sizeof(struct collectNode));pt->nVt = nCh;pt->next = NULL;if(NULL == first[U - 100]){first[U - 100] = pt;}else{qt->next = pt;/*qt指向first集的最后一个元素*/}pt = pt->next;}}else{pt = first[nCh - 100];while(NULL != pt){ch = pt->nVt;if(-1 != ch){AddFirst(U, ch);}pt = pt->next;}}}/*判断first集中是否有空(-1)*/bool HaveEmpty(int nVn){if(nVn < 100)/*为终结符时(含-1),在follow集中用到*/return false;struct collectNode *pt;pt = first[nVn - 100];while(NULL != pt){if(-1 == pt->nVt)return true;pt = pt->next;}return false;}/*计算follow集,例:U->xVy,U->xV.(注:初始符必含#——"-1")*/void Follow(int V){int i;struct pRNode *pt;if(100 == V)/*当为初始符时*/AddFollow(V, -1, 0 );for(i = 0; i < PNum; i++){pt = P[i].rHead;while(NULL != pt && pt->rCursor != V) /*注此不能处理:U->xVyVz的情况*/ pt = pt->next;if(NULL != pt){pt = pt->next;/*V右侧的符号*/if(NULL == pt)/*当V后为空时V->xV,将左符的follow集并入V的follow集中*/ {if(NULL == follow[P[i].lCursor - 100] && P[i].lCursor != V){Follow(P[i].lCursor);}AddFollow(V, P[i].lCursor, 0);}else/*不为空时V->xVy,(注意:y->),调用AddFollow加入Vt或y的first集*/ {while(NULL != pt && HaveEmpty(pt->rCursor)){AddFollow(V, pt->rCursor, 1);/*y的前缀中有空时,加如first集*/pt = pt->next;}if(NULL == pt)/*当后面的字符可以推出空时*/{if(NULL == follow[P[i].lCursor - 100] && P[i].lCursor != V){Follow(P[i].lCursor);}AddFollow(V, P[i].lCursor, 0);}else/*发现不为空的字符时*/{AddFollow(V, pt->rCursor, 1);}}}}}/*当数值小于100时nCh为Vt*//*#用-1表示,kind用于区分是并入符号的first集,还是follow集kind = 0表加入follow集,kind = 1加入first集*/void AddFollow(int V, int nCh, int kind){struct collectNode *pt, *qt;int ch;/*用于处理Vn*/pt = NULL;qt = NULL;if(nCh < 100)/*为终结符时*/{pt = follow[V - 100];while(NULL != pt)if(pt->nVt == nCh)break;else{qt = pt;pt = pt->next;}}if(NULL == pt){pt = (struct collectNode *)malloc(sizeof(struct collectNode)); pt->nVt = nCh;pt->next = NULL;if(NULL == follow[V - 100]){follow[V - 100] = pt;}else{qt->next = pt;/*qt指向follow集的最后一个元素*/}pt = pt->next;}}else/*为非终结符时,要区分是加first还是follow*/{if(0 == kind){pt = follow[nCh - 100];while(NULL != pt){ch = pt->nVt;AddFollow(V, ch, 0);pt = pt->next;}}else{pt = first[nCh - 100];while(NULL != pt){ch = pt->nVt;if(-1 != ch)AddFollow(V, ch, 1);}pt = pt->next;}}}}/*输出first或follow集*/void ShowCollect(struct collectNode **collect) {int i;struct collectNode *pt;i = 0;while(NULL != collect[i]){pt = collect[i];printf("\n%c:\t", Vn[i]);while(NULL != pt){if(-1 != pt->nVt){printf(" %c", Vt[pt->nVt]);}elseprintf(" #");pt = pt->next;}i++;}printf("\n");}/*计算first和follow*/void FirstFollow(){int i;i = 0;while('\0' != Vn[i]){if(NULL == first[i])First(100 + i);i++;}i = 0;while('\0' != Vn[i]){if(NULL == follow[i])Follow(100 + i);i++;}}/*=================构造预测分析表,例:U::xyz=============*/ void CreateAT(){int i;struct pRNode *pt;struct collectNode *ct;for(i = 0; i < PNum; i++){pt = P[i].rHead;while(NULL != pt && HaveEmpty(pt->rCursor)){/*处理非终结符,当为终结符时,定含空为假跳出*/ct = first[pt->rCursor - 100];while(NULL != ct){if(-1 != ct->nVt)analyseTable[P[i].lCursor - 100][ct->nVt] = i;ct = ct->next;}pt = pt->next;}if(NULL == pt){/*NULL == pt,说明xyz->,用到follow中的符号*/ct = follow[P[i].lCursor - 100];while(NULL != ct){if(-1 != ct->nVt)analyseTable[P[i].lCursor - 100][ct->nVt] = i;else/*当含有#号时*/analyseTable[P[i].lCursor - 100][vtNum] = i;ct = ct->next;}}else{if(100 <= pt->rCursor)/*不含空的非终结符*/{ct = first[pt->rCursor - 100];while(NULL != ct){analyseTable[P[i].lCursor - 100][ct->nVt] = i;ct = ct->next;}}else/*终结符或者空*/{if(-1 == pt->rCursor)/*-1为空产生式时*/{ct = follow[P[i].lCursor - 100];while(NULL != ct){if(-1 != ct->nVt)analyseTable[P[i].lCursor - 100][ct->nVt] = i;else/*当含有#号时*/analyseTable[P[i].lCursor - 100][vtNum] = i;ct = ct->next;}}else/*为终结符*/{analyseTable[P[i].lCursor - 100][pt->rCursor] = i;}}}}}/*输出分析表*/void ShowAT(){int i,j;printf("构造预测分析表如下:\n");printf("\t|\t");for(i = 0; i < vtNum; i++){printf("%c\t", Vt[i]);}printf("#\t\n");printf("- - -\t|- - -\t");for(i = 0; i <= vtNum; i++)printf("- - -\t");printf("\n");for(i = 0; i < vnNum; i++){printf("%c\t|\t", Vn[i]);for(j = 0; j <= vtNum; j++){if(-1 != analyseTable[i][j])printf("R(%d)\t", analyseTable[i][j]);elseprintf("error\t");}printf("\n");}}/*=================主控程序=====================*/void Identify(char *st){int current,step,r;/*r表使用的产生式的序号*/printf("\n%s的分析过程:\n", st);printf("步骤\t分析符号栈\t当前指示字符\t使用产生式序号\n");step = 0;current = 0;/*符号串指示器*/printf("%d\t",step);ShowStack();printf("\t\t%c\t\t- -\n", st[current]);while('#' != st[current]){if(100 > analyseStack[topAnalyse])/*当为终结符时*/{if(analyseStack[topAnalyse] == IndexCh(st[current])){/*匹配出栈,指示器后移*/Pop();current++;step++;printf("%d\t", step);ShowStack();printf("\t\t%c\t\t出栈、后移\n", st[current]);}else{printf("%c-%c不匹配!", analyseStack[topAnalyse], st[current]);printf("此串不是此文法的句子!\n");return;}}else/*当为非终结符时*/{r = analyseTable[analyseStack[topAnalyse] - 100][IndexCh(st[current])]; if(-1 != r){Push(r);/*产生式右部代替左部,指示器不移动*/step++;printf("%d\t", step);ShowStack();printf("\t\t%c\t\t%d\n", st[current], r);}else{printf("无可用产生式,此串不是此文法的句子!\n");return;}}}if('#' == st[current]){if(0 == topAnalyse && '#' == st[current]){step++;printf("%d\t", step);ShowStack();printf("\t\t%c\t\t分析成功!\n", st[current]);printf("%s是给定文法的句子!\n", st);}else{while(topAnalyse > 0){if(100 > analyseStack[topAnalyse])/*当为终结符时*/{printf("无可用产生式,此串不是此文法的句子!\n");return;}else{r = analyseTable[analyseStack[topAnalyse] - 100][vtNum];if(-1 != r){Push(r);/*产生式右部代替左部,指示器不移动*/step++;printf("%d\t", step);ShowStack();if(0 == topAnalyse && '#' == st[current]){printf("\t\t%c\t\t分析成功!\n", st[current]);printf("%s是给定文法的句子!\n", st);}elseprintf("\t\t%c\t\t%d\n", st[current], r);}else{printf("无可用产生式,此串不是此文法的句子!\n");return;}}}}}}/*初始化栈及符号串*/void InitStack(){int i;/*分析栈的初始化*/for(i = 0; i < MaxStLength; i++)st[i] = '\0';analyseStack[0] = -1;/*#(-1)入栈*/analyseStack[1] = 100;/*初始符入栈*/topAnalyse = 1;}/*显示符号栈中内容*/void ShowStack(){int i;for(i = 0; i <= topAnalyse; i++){if(100 <= analyseStack[i])printf("%c", Vn[analyseStack[i] - 100]);else{if(-1 != analyseStack[i])printf("%c", Vt[analyseStack[i]]);elseprintf("#");}}}/*栈顶出栈*/void Pop(){topAnalyse--;}/*使用产生式入栈操作*/void Push(int r){int i;struct pRNode *pt;Pop();pt = P[r].rHead;if(-1 == pt->rCursor)/*为空产生式时*/return;topAnalyse += P[r].rLength;for(i = 0; i < P[r].rLength; i++){/*不为空产生式时*/analyseStack[topAnalyse - i] = pt->rCursor;/*逆序入栈*/ pt = pt->next;}/*循环未完时pt为空,则说明rLength记录等出错*/}。