(完整word版)自动生成LR0分析表
使用Word进行数据分析和统计的常用方法

使用Word进行数据分析和统计的常用方法在当今信息爆炸的时代,数据分析和统计已经成为了各行各业不可或缺的一部分。
而对于一些初学者来说,使用专业的数据分析软件可能会感到有些困难和复杂。
然而,不用担心,Word作为一款常见的办公软件,也提供了一些简单易用的数据分析和统计功能,下面将介绍一些常用的方法。
一、创建数据表格首先,我们需要将数据整理成表格的形式,以便更好地进行分析和统计。
在Word中,可以通过插入表格的功能来创建数据表格。
选择“插入”选项卡,然后点击“表格”按钮,选择需要的行列数,即可创建一个空的数据表格。
二、计算数据总和在进行数据分析和统计时,计算数据的总和是一个常见的需求。
在Word中,可以使用公式来计算数据的总和。
首先,选中需要计算总和的数据所在的单元格,然后在“布局”选项卡中的“公式”组中,选择“求和”按钮,即可自动计算出数据的总和。
三、计算数据平均值除了计算数据的总和,计算数据的平均值也是一项常用的统计方法。
在Word 中,同样可以使用公式来计算数据的平均值。
选中需要计算平均值的数据所在的单元格,然后在“布局”选项卡中的“公式”组中,选择“平均值”按钮,即可自动计算出数据的平均值。
四、绘制数据图表数据图表是一种直观地展示数据分析和统计结果的方式。
在Word中,可以使用插入图表的功能来绘制数据图表。
选中需要绘制图表的数据范围,然后在“插入”选项卡中的“图表”组中,选择需要的图表类型,即可自动生成相应的数据图表。
五、使用排序功能在进行数据分析和统计时,对数据进行排序是一个常见的操作。
在Word中,可以使用排序功能来对数据进行排序。
选中需要排序的数据范围,然后在“布局”选项卡中的“数据”组中,选择“排序”按钮,按照需要的排序方式进行设置,即可对数据进行排序。
六、使用筛选功能除了排序,筛选数据也是一个常用的操作。
在Word中,可以使用筛选功能来筛选数据。
选中需要筛选的数据范围,然后在“布局”选项卡中的“数据”组中,选择“筛选”按钮,按照需要的筛选条件进行设置,即可筛选出符合条件的数据。
编译原理课程设计(LR(0)分析表的构造)

引言《编译原理》是计算机专业的一门重要的专业课程,其中包含大量软件设计思想。
通过课程设计,实现一些重要的算法,或设计一个完整的编译程序模型,能够进一步加深理解和掌握所学知识,对提高自己的软件设计水平具有十分重要的意义。
语法分析是编译过程的第二阶段,是编译器前端的核心组成部分,在编译系统中起到了至关重要的作用。
自底向上的语法分析与自顶向下的语法分析相比,对将要分析的源程序有着更大的分析空间,从而受到了广泛的运用。
LR(0)分析是自底向上LR类语法分析的基础,自底向上语法分析方法是一种移进-规约过程,在当前分析的栈顶符号串形成句柄时就采取规约动作,因此最终目标是如何在分析过程中确定句柄。
LR分析法是给出一种能根据当前分析栈中的符号串和向右顺序查看k个符号串就可以唯一地确定分析器动作:是移进还是规约,采用哪条产生式。
LR(0)分析器是在分析过程中,不需要向后查看输入串符号,因此它对文法的限制较大。
对绝大多数高级语言语法分析器是不适用的,但是它是构造其他LR分析器的基础。
LR(0)最终存在的问题和需要解决的问题是在构造LR(0)分析表的时候,在LR(0)项目集规范族中,有移进项目和规约项目、规约项目和规约项目同时存在的现象,形成移进-规约冲突和规约-规约冲突,直接导致语法分析器无法在某一状态进行移进还是规约。
为了能够解决这一问题,我们需要再向后查看一个输入字符(也就是当前字符的FOLLOW集)以确定下一步操作是否能够进行。
我班选择的是老师给的LR(1)语法分析构造器的设计,即对任意给定的文法G构造LR(1)项目集规范族,其中要实现CLOSURE(I)、GO(I,X)、FIRST集合等。
在此基础上,构造了LR(1)分析表。
然后对输入的句子进行语法分析,给出接受或出错报告。
程序采用文件输入输出方式。
其中包括两个输入文件:文法grammar.txt,以及输入串input.txt;两个输出文件:项目集items.txt和文法的LR(1)分析表action_table.txt。
编译原理实验自动生成LR分析表

编译原理实验自动生成LR分析表2016.12.14自动生成LR(0)分析表目录一、实验名称 (2)二、实验目的 (2)三、实验原理 (2)1、闭包closure(I) (2)2、转换函数GO(I,X) (2)3、ACTION子表和GOTO子表的构造 (2)四、实验思路 (3)1、输入 (3)2、建立项目 (3)3、closure算法 (3)4、转向函数GO(I,X)的算法 (3)5、建立状态及对应的项目集 (3)6、ACTION子表的构造 (4)7、GOTO子表的构造 (4)五、实验小结 (4)六、附件 (5)1、源代码 (5)2、运行结果截图 (9)一、实验名称自动生成LR(0)分析表二、实验目的1、实现计算闭包函数CLOSURE的算法。
2、实现转向函数GO(I,X)的算法。
3、实现ACTION子表和GOTO子表的构造算法。
4、输入任意的压缩了的上下文无关文法,输出相应的LR(0)分析表(以表格形式输出)。
三、实验原理1、闭包closure(I)若文法G已拓广为G’,而S为文法G的开始符号,拓广后增加产生式S’->S。
如果I是文法G’的一个项目集,定义和构造I的闭包closure(I)如下:a.I的项目在closure(I)中。
b.若A->α?Bβ属于closure(I),则每一形如B->?γ的项目也属于closure(I)。
c.重复b直到不出现新的项目为止。
即closure(I)不再扩大。
2、转换函数GO(I,X)GO(I,X)=closure(J)其中:I为包含某一项目集的状态。
X为一文法符号,X∈Vn∪VtJ={任何形如A->α?Xβ的项目|A->αX?β属于I}3、ACTION子表和GOTO子表的构造a.若项目A→α.aβ属于Ik且GO (Ik, a)= Ij, a为终结符,则置ACTION[k, a]为“把状态j和符号a移进栈”,简记为“sj”;b.若项目A→α.属于Ik,那么,对任何终结符a,置ACTION[k,a]为“用产生式A→α进行规约”,简记为“rj”;其中,假定A→α为文法G'的第j个产生式c.若项目S'→S.属于Ik, 则置ACTION[k, #]为“接受”,简记为“acc”;d.若GO (Ik, A)= Ij, A为非终结符,则置GOTO[k, A]=j;e.分析表中凡不能用上述1至4填入信息的空白格均置上“出错标志”。
(完整word版)计算机编译原理名词解释_总结版

2.二义性文法:如果一个文法存在某个句子对应两棵不同的语法树,则称这个文法是二义性文法。
5.最左推导:任何一步α=>β都是对α中的最右非终结符替换。
6.语法:一组规则,用它可形成和产生一组合式的程序。
7.文法:描述语言的语法结构的形式规则。
8.基本块:指程序中一顺序执行的语句序列,其中只有一个入口和一个出口,入口就是其中的第一个语句,出口就是其中的最后一个语句。
10.短语:令G 是一个文法,S 划文法的开始符号,假定αβδ是文法G 的一个句型,如果有S αAδ且A β,则称β是句型αβδ相对非终结符A 的短语。
12.规范句型:由规范推导所得到的句型。
13.扫描器:执行词法分析的程序。
15.句柄:一个句型的最左直接短语。
16.语法制导翻译:在语法分析过程中,根据每个产生式所对应的语义程序进行翻译的方法 叫做语法制导翻译。
18.素短语:素短语是指这样一个短语,至少含有一个终结符,并且,除它自身外不再含任何更小的素短语。
20.语义:定义程序的意义的一组规则。
三种级别:局部优化、循环优化、全局优化21.词法分析词法分析的主要任务是从左向右扫描每行源程序的符号,按照词法规则从构成源程序的字符串中识别出一个个具有独立意义的最小语法单位,并转换成统一的内部表示(token),送给语法分析程序。
23.语法树句子的树结构表示法称为语法树(语法分析树或语法推导树)。
给定文法G=(V N ,V T ,P ,S),对于G 的任何句型都能构造与之关联的语法树。
这棵树具有下列特征:(1)根节点的标记是开始符号S 。
(2)每个节点的标记都是V 中的一个符号。
(3)若一棵子树的根节点为A ,且其所有直接子孙的标记从左向右的排列次序为A 1A 2…A R ,那么A →A 1A 2…A R 一定是P 中的一条产生式。
(4)若一标记为A 的节点至少有一个除它以外的子孙,则A ∈V N 。
(5)若树的所有叶节点上的标记从左到右排列为字符串w ,则w 是文法G 的句型;若w 中仅含终结符号,则w 为文法G 所产生的句子。
(完整word版)编译原理试卷及答案

东 北 大 学秦 皇 岛 分 校课程名称: 编译原理 试卷: (B )答案 考试形式: 闭卷授课专业: 计算机科学与技术 考试日期: 年 月 日 试卷:共 2 页题号 一 二 三 四 总分得分 阅卷人一、填空题(每空2分,共30分)1、编译程序的整个过程可以从逻辑上划分为词法分析、 语法分析 、语义分析、中间代码生成、 代码优化 和目标代码生成等几个阶段,另外还有两个重要的工 作是 理 和出错处理。
表格管2、规范规约中的可归约串是 句柄 ,算符优先分析中的可归约串是 最左素短语 。
3、语法分析方法主要可分为 自顶向下 和 自底向上 两大类。
4、LR (0)文法的项目集中不会出现 移进-归约 冲突和 归约-归约 冲突。
5、数据空间的动态存储分配方式可分为 栈式 和 堆式 两种。
6、编译程序是指能将 源语言 程序翻译成 目标语言 程序的程序。
7、确定有穷自动机DFA 是 NFA 的一个特例。
8、表达式 (a+b)*c 的逆波兰表示为 ab+c* 。
二、选择题(每题2分,共20分)1、LR 语法分析栈中存放的状态是识别 B 的DFA 状态。
A 、前缀B 、可归前缀C 、项目D 、句柄 2、 D 不可能是目标代码。
A 、汇编指令代码B 、可重定位指令代码C 、绝对机器指令代码D 、中间代码 3、一个控制流程图就是具有 C 的有向图A 、唯一入口结点B 、唯一出口结点C 、唯一首结点D 、唯一尾结点 4、设有文法G[S]:S →b|bBB →bS ,则该文法所描述的语言是C 。
A 、L (G )={b i |i ≥0}B 、L (G )={b 2i |i ≥0}C 、L (G )={b 2i+1|i ≥0}D 、L (G )={b 2i+1|i ≥1}5、把汇编语言程序翻译成机器可执行的目标程序的工作是由 B 完成的。
A 、编译器B 、汇编器C 、解释器D 、预处理器 6、在目标代码生成阶段,符号表用于 D 。
LR(0)分析表构造

编译原理实验报告实验名称自动生成LR(0)分析表实验时间 2013、12、10 院系计算机科学与电子技术系班级 2011级计算机软件学号 JV114023 JV114052 JV114078 段国顺立冬黄磊一、实验目的输入:任意的压缩了的上下文无关文法。
输出:相应的LR(0)分析表。
二、实验原理对于LR文法,我们可以自动构造相应的LR分析表。
为了构造LR分析表,我们需要定义一个重要概念——文法的规句型“活前缀”。
这种句柄之后不含任何符号的前缀称为活前缀。
在LR分析工作过程中的任何时候,栈里的文法符号(自栈底而上)X1X2 (X)m应该构成活前缀,把输入串的剩余部分配上之后即应成为规句型(如果整个输入串确实构成一个句子)。
因此,只要输入串的已扫描部分保持可归约成一个活前缀,那就意味着所扫描过的部分没有错误。
对于一个文法G,我们可以构造一个有限自动机,它能识别G的所有活前缀,然后把这个自动机转变成LR分析表,按照该LR分析表进行LR分析,就能保证在分析的过程中,如果分析的句子是正确的,栈里的文法符号(自栈底而上)始终构成活前缀。
假若一个文法G的拓广文法G 的活前缀识别自动机中的每个状态(项目集)不存在下述情况:(1)既含移进项目又含归约项目;(2)含有多个归约项目,则称G是一个LR(0)文法。
该自动机的状态集合即为该文法的LR(0)项目集规族。
构造识别文法活前缀DFA有3种方法:(1)根据形式定义求出活前缀的正则表达式,然后由此正则表达式构造NFA 再确定为DFA;(2)求出文法的所有项目,按一定规则构造识别活前缀的NFA再确定化为DFA;(3)使用闭包函数(CLOSURE)和转向函数(GO(I,X))构造文法G’的LR(0)的项目集规族,再由转换函数建立状态之间的连接关系来得到识别活前缀的DFA。
符号串的前缀是指该符号串的任意首部,包括空串ε。
例如,对于符号串abc,其前缀有ε,a,ab,abc。
(完整word版)编译原理课后答案
第二章 高级语言及其语法描述4.令+、*和↑代表加,乘和乘幂,按如下的非标准优先级和结合性质的约定,计算1+1*2↑2*1↑2的值:(1) 优先顺序(从高至低)为+,*和↑,同级优先采用左结合。
(2) 优先顺序为↑,+,*,同级优先采用右结合。
解:(1)1+1*2↑2*1↑2=2*2↑1*1↑2=4↑1↑2=4↑2=16 (2)1+1*2↑2*1↑2=1+1*2*1=2*2*1=2*2=46.令文法G6为 N →D|NDD →0|1|2|3|4|5|6|7|8|9 (1) G6 的语言L (G6)是什么?(2) 给出句子0127、34和568的最左推导和最右推导。
解:(1)L (G6)={a|a ∈∑+,∑=﹛0,1,2,3,4,5,6,7,8,9}}(2)N =>ND => NDD => NDDD => DDDD => 0DDD => 01DD => 012D => 0127 N => ND => N7=> ND7=> N27=> ND27=> N127=> D127=> 0127 N => ND => DD => 3D => 34 N => ND => N4=> D4 =>34N => ND => NDD => DDD => 5DD => 56D => 568 N => ND => N8=> ND8=> N68=> D68=> 5687.写一个文法,使其语言是奇数集,且每个奇数不以0开头。
解:A →SN, S →+|-|∑, N →D|MDD →1|3|5|7|9, M →MB|1|2|3|4|5|6|7|8|9 B →0|1|2|3|4|5|6|7|8|9 8. 文法:E T E T E T TF T F T F F E i→+-→→|||*|/()| 最左推导:E E T T TF T i T i T F i F F i i F i i i E T T F F F i F i E i E T i T T i F T i i T i i F i i i ⇒+⇒+⇒+⇒+⇒+⇒+⇒+⇒+⇒⇒⇒⇒⇒⇒+⇒+⇒+⇒+⇒+⇒+********()*()*()*()*()*()*()最右推导:E E T E TF E T i E F i E i i T i i F i i i i i E T F T F F F E F E T F E F F E i F T i F F i F i i i i i ⇒+⇒+⇒+⇒+⇒+⇒+⇒+⇒+⇒⇒⇒⇒⇒+⇒+⇒+⇒+⇒+⇒+⇒+**********()*()*()*()*()*()*()*()语法树:/********************************EE FTE +T F F T +iiiEEFTE-T F F T -iiiEEFT+T F FTiii*i+i+ii-i-ii+i*i*****************/9.证明下面的文法是二义的:S → iSeS|iS|I解:因为iiiiei 有两种最左推导,所以此文法是二义的。
自己动手制作excel成绩分析表(一劳永逸)转
原文地址:自己动手制作excel成绩分析表(一劳永逸)作者:李国磊效果图如下:表一:文科成绩表二:理科成绩表三:文科成绩统计分析表四:理科成绩统计分析同一个文件中有四个工作表:“文科”“理科”“文科统计”“理科统计”其中成绩表中包含有:总分,年级名次(相同的分数相同的名次),班级名次(在不用分班的情况下统计班级名次),单科年级名次,与上一次考试的对比(是进不了还是退步了)统计表中包含有:每个班各个分数段的人数,年级各个分数段的人数,年级累计人数,每个班年级前多少名的人数对于我们老师来说,这样的一张表足可以满足我们分析成绩的需要,如果每次考试都统计一次,工作量就会增加很多,并且是无效的重复劳动,为此鄙人用了四个小时的时间制作了这样的一张模板表,每次我们只需要把单科的成绩复制进来,就会自动求出总分,排出单科的名次,年级名次,班级名次以及与上一次的对比情况,还有各个分数段的人数,可以为我们省去很多不必要的麻烦,先将制作方法说明如下,有兴趣的朋友我们一起探讨,设计出更好的模板。
1、求总分这个大家都会,就不过多解释了,直接用SUM函数就行了2、怎样排出年级名次,要求同一个分数有相同的名次,如效果图方法:在G2单元格中输入=RANK(F2,F:F)就可以了,RANK是排序函数,参数的意义是按照F列的数据排序3、怎样在不分班的情况下,在不改变年级名次的情况下,排出班级名次?如上图方法:在H2单元格个输入=SUMPRODUCT(($E$2:$E$1000=E2)*(F$2:$F$1000>F2))+14、怎样统计各个班在每个分数段的人数?效果如表三、表四方法:在B2中输入=SUMPRODUCT((文科!E$2:文科!E$1000=A2)*(文科!F$2:文科!F$1000>=600))在B3中输入=SUMPRODUCT((文科!E$2:文科!E$1000=A2)*(文科!F$2:文科!F$1000<<fontcolor="#FF0000">600)*(文科!F$2:文科!F$1000>=590))直接往后面复制,改变红色数字就可统计出各个分数段的人数理科统计表不用再逐个输入了,直接复制文科统计表,然后“编辑——替换”就行了5、怎样在统计表中出现文科(理科)成绩表中的最高分,及对应的名字和班级?统计文科(理科)成绩表中的最高分A2=MAX(INDIRECT("文科!"&CHAR(64+ROW(C5))&2):INDIRECT("文科!"&CHAR(64+ROW(C5))&1000)) CHAR()返回单元格中的字符ROW( ) 返回单元格所在的行“64+row()”的含义是,65对应A,66对应B,……比如上面表一中总分在D列,所以就是64+ROW(C5)调出姓名=LOOKUP(2,1/((文科!D$2:D$1000=MAX((文科!D$2:D$1000=A2)*文科!D$2:D$1000))),文科!B$2:B$1000) A2是刚返回的最高分D列是分数B列是姓名调出班级=LOOKUP(2,1/((文科!D$2:D$1000=MAX((文科!D$2:D$1000=A2)*文科!D$2:D$1000))),文科!C$2:C$1000) C列是班级6、怎样统计各个班在年级前多少名的人数?方法:在B19中输入=SUMPRODUCT((文科!E$2:文科!E$1000=A19)*(文科!G$2:文科!G$1000<=50)) 在C19中输入=SUMPRODUCT((文科!E$2:文科!E$1000=A19)*(文科!G$2:文科!G$1000<=100))后面的就不用说了吧7、单元格里面都好多零好难看又影响看数据,怎样隐藏这些0?方法:“工具——选项——视图——零值前面的钩去掉就行了”效果如下:好了,一张适用的成绩分析表就做好了,以后拿了直接用就OK了,凌晨一点了,睡觉去…… (范文素材和资料部分来自网络,供参考。
LR(0)分析法
LR(0)分析法LR(0)是⼀种⾃底向上的语法分析⽅法。
两个基本动作是移进和规约。
具体例⼦如下已知⽂法G[E](1) E→aА(2) E→bB(3) A→cА(4) A→d(5) B→cB(6) B→d编写LR(0)分析算法,⽤于识别符号串是否为合法的句⼦。
设计⽅法a.将⽂法 G[E]拓⼴为⽂法 G[E'](0) S'→E(1) E→aA(2) E→bB(3) A→cA(4) A→d(5) B→cB(6) B→db.构造识别可归约前缀的 NFAc. 将识别可归约前缀的 NFA 确定化成DFAd. 根据识别可归约前缀的 DFA 构造⽂法的 LR(0)分析表表2-1 LR(0)分析表状态a b c d#E A B0S1S231S4S562S7S893acc4S4S5105r4r4r4r4r46r1r1r1r1r17S7S8118r6r6r6r6r69r2r2r2r2r210r3r3r3r3r311r5r5r5r5r5e. 设计 LR(0)分析程序⾃底向上的语法分析的两个基本动作就是,移进与规约。
分析⼀下表 2-1 中⽂法的 LR(0)分析表,可以发现这两个动作在表中都有。
进⼀步分析可知,这些移进与规约动作在表的前⾯终结符列中,因此,这部分称之为 ACTION 表。
表中不但给出了两个基本动作,还给出了规约时,弹出产⽣式右部,压⼊左部之后,应该转换到的状态。
例如,当前状态为 9,状态 9 为句柄识别态,查表得:r2,表⽰使⽤第⼆个产⽣式E→bB 进⾏规约。
规约动作分为两步:第⼀步弹出句柄 bB,从识别⽂法可归约前缀的 DFA 中可知,弹出句柄 bB后,从当前状态为 9 回到状态 0;第⼆步就是压⼊左部 E,从当前状态 0,转换到状态 3。
在表中的第 0 ⾏第 E 列中就给出状态 3。
分析表可知,表中的⾮终结符列填⼊的是某⼀规约动作,压⼊产⽣式左部(⾮终结符)之后,转换到的状态。
因此,这部分称之为 GOTO 表。
(完整word版)编译原理练习题
一章:1、编译程序各阶段都涉及。
A、词法分析B、表格管理C、语法分析D、语义分析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、过程1、扫描器的任务是从源程序中识别出一个个单词符号。
2、高级语言源程序有两种执行方式,即解释和编译。
判断:高级语言编写的源程序都必须通过编译,产生目标代码后才能运行。
多遍扫描的编译程序的多遍是指多次重复读源程序。
高级语言程序到低级语言程序的转换是基于语义的等价变换。
编译程序中错误处理的任务是对检查出的错误进行修改。
目标程序一定是机器语言程序。
连接装配程序可把经编译程序产生的目标程序变成可执行的机器语言程序。
简答题:1、请指出下列错误信息可能是编译的哪个阶段报告的?①else没有匹配的if;②数组下标越界;③使用的函数没有定义;④在数中出现了非数字信息。
答:①语法分析阶段②语义分析与中间代码生成阶段③语义分析与中间代码生成阶段④词法分析阶段2、何谓源程序、中间代码和目标代码?它们三者之间有何种关系?答:所谓源程序是指用某种高级语言编写的程序,它是编译程序的加工对象。
目标程序是指低级语言(机器语言或汇编语言)编写的程序,它是编译程序的加工结果。
中间代码是其结构介于源程序和目标程序之间的一种机内表示形式,它是编译程序产生的中间临时结果。
它们三者之间的关系是等价关系,即结构不同,但语义相同。
二章:1、文法G:S-xSx|y所识别的语言是。
A、xyx B 、(xyx)* C、x n yx n(n≥0) D、x*yx*2、设有文法G[S]=({S,B},{b},{S-b|bB,B-bS},S),该文法所描述的语言是。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
编译原理实验报告实验名称自动生成LR(0)分析表实验时间2011年6月13日院系计算机科学与技术班级08计算机科技一班学号E10814065姓名王全鸿1.试验目的输入:任意的压缩了的上下文无关文法。
输出:相应的LR(0)分析表。
2.实验原理在LR分析工作过程中的任何时候,栈里的文法符号(自栈底而上)X1X2…Xm应该构成活前缀,把输入串的剩余部分配上之后即应成为规范句型(如果整个输入串确实构成一个句子)。
因此,只要输入串的已扫描部分保持可归约成一个活前缀,那就意味着所扫描过的部分没有错误。
构造识别文法活前缀DFA有3种方法:(1)根据形式定义求出活前缀的正则表达式,然后由此正则表达式构造NFA再确定为DFA;(2)求出文法的所有项目,按一定规则构造识别活前缀的NFA再确定化为DFA;(3)使用闭包函数(CLOSURE)和转向函数(GO(I,X))构造文法G’的LR(0)的项目集规范族,再由转换函数建立状态之间的连接关系来得到识别活前缀的DFA。
对于LR(0)文法,我们可以直接从它的项目集规范族C和活前缀识别自动机的状态转换函数GO构造出LR分析表。
下面是构造LR(0)分析表的算法。
假定C={I0, I1,…,In},令每个项目集Ik的下标k为分析器的一个状态,因此,G'的LR(0)分析表含有状态0,1,…,n。
令那个含有项目S'→.S的Ik的下标k为初态。
ACTION子表和GOTO子表可按如下方法构造:(1)若项目A→α.aβ属于Ik且GO (Ik, a)= Ij, a为终结符,则置ACTION[k, a]为“把状态j和符号a移进栈”,简记为“sj”;(2)若项目A→α.属于Ik,那么,对任何终结符a,置ACTION[k,a]为“用产生式A→α进行规约”,简记为“rj”;其中,假定A→α为文法G'的第j个产生式;(3)若项目S'→S.属于Ik, 则置ACTION[k, #]为“接受”,简记为“acc”;(4)若GO (Ik, A)= Ij, A为非终结符,则置GOTO[k, A]=j;(5)分析表中凡不能用上述1至4填入信息的空白格均置上“出错标志”。
按上述算法构造的含有ACTION和GOTO两部分的分析表,如果每个入口不含多重定义,则称它为文法G的一张LR(0)分析表。
具有LR(0)表的文法G称为一个LR(0)文法,LR(0)文法是无二义的。
3.实验内容(1) 实现计算闭包closure(I)的算法;(2) 实现转向函数Go(q,a)的算法;(3)构造文法项目集函数CreateProjectSet();定义数据结构:typedef struct{SElemType *base,*top;int stacksize;}SqStack;struct grammer{char **g;char vt[127];char vn[27];char s;int line;};typedef struct prjset{int id;//项目集编号,从10000开始,与项目编号(从0开始)区别struct prjset *next;//指向下个项目集charprjt[PROJECT_SET_SIZE+1];//PROJECT_SET_SI ZE个单元,存储项目的编号,prjt[0]项目编号的个数char pointafter[PROJECT_SET_SIZE+1];//圆点后的字符,pointafter[0]字符个数struct prjset *actorgo[PROJECT_SET_SIZE];char pointbefore;}prjset,*pprjset;4.实验心得通过这次实验我对LR(0)语法分析有了一个更熟悉的掌握,对预先定义的文法规则,并集成词法分析、符号表管理等程序来生成LR(0)分析表有了清醒的认识,并且对高级程序语言一般结构和主要共同特征有了全面的认识和理解.5.实验代码void CreateProjectSet(){//构造文法的项目集int i;int j;int k;int id = ID;pprjset p,q;root.I = root.tail = NULL;if((p = (pprjset)malloc(sizeof(prjset))) == NULL) exit(1);p->id = id;p->next = NULL;p->prjt[0] = 0;p->pointafter[0] = 0;p->pointbefore = '\0';for(j=0; j<PROJECT_SET_SIZE; j++)p->actorgo[j] = NULL;for(j=0; j<PROJECT_SET_SIZE; j++)p->actorgo[j] = NULL;root.I = p;root.tail = p;root.size = 1;for(i=0; i<project.line; i++){if(project.s==project.gp[i][GRAMMER_START_CHAR_POS]&&DOT==project.gp[i][GRAMMER_START_CHAR_POS+1]){JoinSet(root.I->prjt, project.gp[i][PROJECT_ID_POS]);JoinSet(root.I->pointafter, project.gp[i][AFCHAR_POS]);break;}//if}//forClosure(root.I);int pos;for(q=root.I; q!=NULL; q=q->next){for(i=1; i<=q->pointafter[0]; i++){pos = i;pos--;if((p = (pprjset)malloc(sizeof(prjset))) == NULL) exit(1);p->next = NULL;p->prjt[0] = 0;p->pointafter[0] = 0;p->pointbefore = q->pointafter[i];for(j=0; j<PROJECT_SET_SIZE; j++)p->actorgo[j] = NULL;for(j=1; j<=q->prjt[0]; j++){if(project.gp[q->prjt[j]][AFCHAR_POS] == p->pointbefore)go(q->prjt[j], p);}//forClosure(p);//判断p指向的项目集是否已存在pprjset ptr;int flag;int flagsame;flagsame = 1;flag = 1;for(ptr=root.I; ptr!=NULL; ptr=ptr->next){flag = 1;if(p->prjt[0] == ptr->prjt[0]){for(k=1;k<=p->prjt[0]; k++){if(!IsInSet(ptr->prjt, p->prjt[k])){flag = 0;break;}//if}//for}//ifelse{flag = 0;}//elseif(flag == 0)flagsame = 0;else{flagsame = 1; break;} }//forif(flagsame)//flagsame == 1 , 有与*p相同的项目集,删除*p{q->actorgo[i-1] = ptr;free(p);}else//将p挂到root.tail{q->actorgo[i-1] = p;p->id = ++id;root.tail->next = p;root.tail = p;root.size++;} }//for}//for}//CreateProjectSetvoid Closure(prjset *pset){//rk 为项目的编号,prjset指向项目集int i;int j;int rk;for(i=1; i<=pset->prjt[0]; i++){rk = pset->prjt[i];if(IsInSet(g.vn,project.gp[rk][AFCHAR_POS]))//若圆点后字符为vn{for(j=0; j<project.line; j++){if(project.gp[j][GRAMMER_START_CHAR_POS]==project.gp[rk][AFCHAR_POS]&&project.gp[j][GRAMMER_START_CHAR_POS+1] ==DOT){JoinSet(pset->prjt, project.gp[j][PROJECT_ID_POS]);JoinSet(pset->pointafter,project.gp[j][AFCHAR_POS]);}//if}//for}//if}//for}//Closureint go(int rk, pprjset prjset){//rk为项目编号,将rk的去向加入prjset 指向的项目集中,返回项目编号,若无返回-1 int i;int j;int rksize;char rkS;char rkpointafter;if((rkpointafter = project.gp[rk][AFCHAR_POS]) == '\0'){ return -1; }int pointpos;pointpos = IsInSet(&project.gp[rk][PROJECT_LEN_POS], DOT);pointpos += PROJECT_LEN_POS;rksize = project.gp[rk][PROJECT_LEN_POS];rkS = project.gp[rk][GRAMMER_START_CHAR_POS] ;for(i=0; i<project.line; i++){if(project.gp[i][GRAMMER_START_CHAR_POS]==rkS&&project.gp[i][PROJECT_LEN_POS] == rksize &&project.gp[i][BFCHAR_POS] ==rkpointafter){int flag;flag = 1;for(j=pointpos+2;j<=project.gp[iPROJECT_LEN_POS]+PROJECT_LEN_POS; j++){if(project.gp[i][j] != project.gp[rk][j]){flag = 0;break;}}//forif(flag){JoinSet(prjset->prjt,project.gp[i][PROJECT_ID_POS]);//将项目加入项目集if(project.gp[i][AFCHAR_POS] != '\0'){JoinSet(prjset->pointafter,project.gp[i][AFCHAR_POS]);}//将项目圆点后的字符加入returnproject.gp[i][PROJECT_ID_POS];}//ifelsereturn -1;}//if}//for}//govoid main(){Init();printf("请输入所要分析的文法(#结束):\n");Input();CreateProjectSet();CreateAnalysisForm();PrintForm();}//main。