上一章讲到了语法分析中自上而下的分析方法,其主要思想是从文法的起始符出发进行句子的推导,这一章主要讲的是与其主要思想相反的自下而上的分析方法,其主要思想是从句子本身出发,进行归约,看能否把句子归约到起始符,即终结符到非终结符的归约。自下而上的分析方法主要有算符优先分析法和LR分析法。
首先要了解几个基本的概念:移进归约、短语、直接短语、句柄,这些事进行规范归约的基础,规范归约就是最右推导的逆过程。
1. 移进归约:用一个寄存符号的先进后出栈,把输入符号一个一个地移进到栈里,当栈顶形成某个产生式的候选式时,即把栈顶的这一部分替换成(归约为)该产生式的左部符号。 归约就是指根据文法的产生式规则,把产生式的右部替换成左部符号。
2. 短语:令G是一个文法,S是文法的开始符号,假定αβδ是文法G的一个句型,其中α,β,δd∈(VN∪VT)*,A∈VN ,如果有
则β称是句型αβδ相对于非终结符A的短语。
3. 直接短语:特别是,如果有A=>β,则称β是句型αβδ相对于规则A—>β的直接短语。
4. 句柄:一个句型的最左直接短语称为该句型的句柄。
通过修剪语法树,根据子树和最简子树的叶节点更直观的找出句型和短语。
用符号栈进行的自下而上的语法分析相对简单,接下来介绍算符优先分析法。
算符优先分析法思路是定义算符之间优先关系,借助这种关系来寻找“可归约串”和进行归约。算符之间的优先关系是该分析法的基础,确定好算符之间的优先级后,构造算符优先级表,可借助构造集合LASTVT(P)。
定义终结符之间的优先关系:
1. a =. b 当且仅当文法G中含有形如P→…ab…或P→…aQb…的产生式;
2. a <. b 当且仅当G中含有形如P→…aR…的产生式, 而R b…或R Qb…;
3. a>.b 当且仅当G中含有形如P→…Rb…的产生式,而 R …a或R …aQ。
第二种分析法是LR分析法。根据归约过程中向前看输入符号串中字符的个数,定义不同的LR(k)分析方法,通常,k=0,1。LR分析方法是一种适用于一大类上下文无关文法的分析方法,比较复杂,不适于用手工实现,可借助于YACC/bison实现。
LR分析法可构造LR分析器栈,由action表和goto表构成:
1. 动作表 ACTION[s,a]:当状态s面临输入符号a时,应采取什么动作,每一项ACTION[s,a]所规定的四种动作:移进、归约、接受、报错。两个状态间用终结符连接,对其进行归约或移进,从前一状态转为后状态。
2. 状态转换表 GOTO[s,X]:状态s面对文法符号X时,下一状态是什么。两个状态之间用非终结符链接。
LR(0)分析法需要知道什么是活前缀、LR(0)项目、项目集规范族、项目集的闭包、LR(0)分析表的构造。需要注意,该文法移进时不能归约,归约时只归一个产生式。
活前缀:文法G的活前缀是他的规范句型的前缀,该前缀不超过句柄的右端。
LR分析表的构造需要构造识别活前缀的有限自动机,用有限自动机中的状态表示分析表中的状态,用状态图中的状态之间的转换关系对分析表中的action、 goto函数等进行定义。
只做了部分规范归约的题目,相对于LR分析法要简单些主要练习了短语、句柄的判断,规范归约的分析过程以及算符优先级 的比较。
总的来说,算符优先分析法确实要比LR分析法简单很多,这一章我主要掌握了算符优先分析法,包括算符优先级判断、构造FIRSTVT和LASTVT的构造,以及使用符号栈表示规范归约的步骤。LR分析法并没有掌握熟练,只是对于action和goto表、活前缀了解的比较清楚。