Compiler Principles 语法分析
语法分析的两种思维方式;
1:自顶向下分析 :从语法树的根部推下来一直推到需要确认的终结符号串为止;就是为了找到一个符号串的最左推导
自顶向下分析,因为文法有些是以非终结符开头的另外文法中还可能含有右部为空的推导;(为了能让机器决定下
一步采取那个推导式子)前者情况决定需要求所谓的FIRST集、后者决定需要求FOLLOW集(例如F->空|非空; 那么当能推导
过程中遇到F时因为F可能为空所以就需要求一下F后边可能后随的符号即FLLOW集以判断F是否可以取空;当然此时必须要求
F的后随符号(FOLLOW)集不能与F的FIRST集有相同的符号;试想如果能有相同那么就不能确定F是取空还是继续按照非空推导
,对吧,嘿嘿,其实道理很简单),CFG文法是“单入口的”即因为所有文法都是从一个相同的开始符号开始所以保证了利用
FIRST集来选取对应的推导公式必然唯一的而后续的推导也是从一个入口也就是保证了语法树不会是二义的(只要字符串符符
合对应文法那么只有唯一的一个最左推导与之对应,当然首先保证文法是LL(1)文法-就是对于一个推导公式右部如果无空的则
首符号集合不能有相同(保证可以唯一的选取),如果右部有空的那么相互之间的后随和前缀不能有相同的(前边解释过)就是
书中讲的 啊 要如何如何才能是LL1文法 balabalabala),至此,神马老师上课讲的乱七八糟的东西就这么简明的理解掉了~
所谓的预测分析表不就是列各表这样比较方便推导的时候找用哪个推导公式方便而已;(ps其实能想到这种方法的人也不见得
有多聪明,按照惯常思维完全就可以把这个想到,只是我大天朝一些编书的人和讲书的人故作深沉这样显得有学问╮(╯▽╰)╭
最后让我们觉得自己好笨啊 编译原理好难啊 坑爹!一个老师曾上课曰过,一篇好论文就是写的让人看的似懂非懂才算是好论文,
让人一看就懂的不是好论文,让人什么都看不懂的也不是好论文,很有些道理,不要标榜自己抬高搞得被人都是傻逼,写书的写
的复杂那或许无可厚非,但是讲书的讲的依旧复杂,那就是人云亦云了,可惜没办法这样的老师还是不少的,No complaint!
善哉善哉)
2:自底向上分析 :从终结符号串的开始进行最左规约一直规约到文法开始符号,从树的概念上即是形成整棵语法分析树并且树根
为文法开始符号;
一句话就是找句柄(最左直接短语:最左边直接短语,即最左边的可以符合某一文法公式右部可以一步规约为左步的一串
符号组合) 然后规约,一直规约到文法开始符号;大致想想一下如果按照这个想法的话似乎对文法的要求不是特别高,只要
每次规约时候找到一个合适切唯一的可归约公式就可以了,不用考虑什么首符号集必须不同后随符号集如何如何(当然上述
想法不完全正确)。
自底向上分析分为两种方法:优先法:算符优先分析法和状态法;
一、 算符优先分析法 就是先寻找文法中中各个终结符的优先关系;若用算符优先分析法进行分析那么必须能用算符文法来描述—
算符文法的每个产生式的右部都不能有两个语法变量直接相邻,并且没有空产生式;
根据已知文法进行算符优先分析的步骤是
1:首先分析各个文法符号之间的关系 求各个语法变量的FIRSTOP和LASTOP 再根据
文法来确定“算符”(即终结符不要理解那么狭隘)之间的优先关系
2:根据优先关系构造算符优先矩阵
3:判断是否有冲突如果有冲突则不能进行算符优先分析。由于算符优先文法只是根据非终结符进行分析规约所以规约的句柄
不是严格意义上的句柄(也就是算符优先进行规约的只看终结符,语法变量是否正确这个不管只要符合比如A+B的形式他就按照
F->A+B进行规约它不管你现在实际是C+F还是其他,只要符合形式就规约,所以从这个层面来讲算算符这里形成的句柄不是真正
的句柄,此句柄称为“最左素短语”我的理解就是略微不同于最左直接短语的短语:形式相同语法变量可能不同)。
二、LR分析法、
LR(0):构造LR(0)分析表
从文法得到拓广文法;求S'->S的项目集闭包项目I(0);
求I(0)后继项目集得到项目规范族;
判断项目集规范族各个成员是否相容 如果相容则是LR(0)文法(没有移进移进冲突和移进规约冲突)
SLR(1):构造SLR(1)分析表 注意:是在LR(0)的基础上进行的。(解决移进规约冲突)
所谓移进规约冲突的概念:如果一个项目集有如下状态 E->T. and E->T.*S; 那么该项目集遇到下一个符号既可以移进又可以
规约,如何判断呢?让分析器进行检查下一个输入符号,如果:输入属于FOLLOW(E)才可以进行规约,否则不能规约,因为生活总是
要继续呀你规约之后分析可能还没有结束,后续还得要能识别呀,如果不能识别那就规约错喽
LR(1):构造LR(1)分析表 注意到前边进行SLR(1)分析的时候只是在遇到移进规约冲突时候根据的FOLLOW集进行了大致判断,但是
没有考虑到 1:如果输入符号属于FOLLOW集那么分析仍然是存在冲突的还是所谓的移进规约冲突并没有完全解决而且我觉得
这种情况应该也不少;2:归约归约冲突的问题仍然存在;
为了解决这样的问题,LR(1)文法的规则产生了,LR1文法每个状态公式都有一个前瞻符号,从而能记住本公式从哪里来到哪里
去这个哲学命题的答案;可是具体为什么这样就能够保证不存在移进移进冲突我也不甚理解 ╮(╯▽╰)╭ ;似乎是因为不同的前
瞻符号代表不同的路,公式相同但前瞻符号不同还是不一样的 这样就区分了,一开始就不同结果肯定不同,虽然结果可能相同但是
回望一下想回去的路还是不同的,也就是进行归约时候使用同一个公式但是Go的状态还是不一样的。
LALR(1)文法:构造LALR(1)分析表,将LR(1)中的同心分量合并得到的表;当然肯定会存在问题,前提是如果合并之后项目集中
不存在冲突那么成为符合LALR(1)文法;(合并之后即使存在冲突冲突只会是归约归约冲突)
语法分析中用到的一些方法和形式语言中有很多类似之处;很多思想贯穿在里边,比如自底向上分析法中的算符优先分析,
我会想到逆波兰式和算法中的凸包问题的一种解法比较相似都是用栈来进行判断栈中符合神马条件然后就对栈中元素进行处理,
似乎有点意思。