语法分析笔记
语法分析笔记(四)——LR(0) SLR LR(1) LALR
语法分析
语法分析:语法分析器从词法分析器输出的token序列中识别出各类短语,并构造语法分析树的过程。
而语法分析树则描述了语法的分析结构。
即分析句子的格式,并找到句子中各自对应的成分,例如:
输入串 | 格式(文法) | 句子类型 | 各自对应成分 |
---|---|---|---|
a=2; | <变量名> = <值> ; | 赋值语句 | <变量名>:a =:= <值>:2 ;:; |
intf(inta,intb); | <返回值类型><函数名>(<参数类型><参数名>,<参数类型><参数名>); | 函数声明语句 | <返回值类型>:int <函数名>:f (: ( <参数类型>:int <参数名>:a ,:, <参数类型>:int <参数名>:b ): ) ;:; |
不同语言对应的语法格式不同
文法
G = ( V T \ _T T,V N \ _N N,P,S )
- V T \ _T T:终极符集合(终极符是文法所定义的语言的基本符号,不可再分,也称token)
- V N \ _N N:非终极符集合(非终极符用来表示语法成分,也称语法变量)
- P:产生式集合(产生式描述将终极符和非终极符组合成串的方法)
产生式形式: α → β \alpha\rightarrow\beta α→β ,读作 α \alpha α定义为 β \beta β
α \alpha α ∈ \in ∈( V T \ _T T ∪ \cup ∪ V N \ _N N) + \ ^+ +,且 α \alpha α中至少包含V N \ _N N中的一个元素:称为产生式的头或左部
β \beta β ∈ \in ∈( V T \ _T T ∪ \cup ∪ V N \ _N N) + \ ^+ +,称为产生式的体或右部 - S ∈ \in ∈ V N \ _N N,开始符号表示的是该文法中最大的语法成分,表示最终的描述对象
推导
给定文法 G = ( V T \ _T T,V N \ _N N,P,S ),如果 α \alpha α → \rightarrow → β \beta β ∈ \in ∈ P,那么可以将符号串 γ α δ \gamma\alpha\delta γαδ中的 α \alpha α 替换为 β \beta β ,也就是说,将 γ α δ \gamma\alpha\delta γαδ 重写为 γ β δ \gamma\beta\delta γβδ ,记作 γ α δ \gamma\alpha\delta γαδ ⇒ \Rightarrow ⇒ γ β δ \gamma\beta\delta γβδ 。此时,称文法中的符号串 γ α δ \gamma\alpha\delta γαδ 直接推导出 γ β δ \gamma\beta\delta γβδ ,即用产生式的右部替换产生式的左部。
最左推导
最左推导:总是选择每个句型的最左非终极符进行替换。
从文法的开始符经过最左推导得到的句型称为最左句型。
最右推导
最右推导:总是选择每个句型的最右非终极符进行替换。
从文法的开始符经过最右推导得到的句型称为最右句型。
最右推导称为规范推导,其逆过程最左规约称为规范规约。
最左推导和最右推导具有唯一性。
规约
规约是推导的逆过程。
每次规约的符号串称为句柄。
句柄是句型的最左直接短语。
句型和句子
如果 S
⇒
∗
α
\Rightarrow^*\alpha
⇒∗α,
α
\alpha
α
∈
\in
∈ ( V
T
\ _T
T
∪
\cup
∪ V
N
\ _N
N)
∗
\ ^*
∗,则称
α
\alpha
α 是 G 的一个句型。
如果 S
⇒
∗
ω
\Rightarrow^*\omega
⇒∗ω,
ω
\omega
ω
∈
\in
∈ V
T
\ _T
T
∗
\ ^*
∗,则称
α
\alpha
α 是 G 的一个句子。
句子是不包含非终极符的句型。
文法分类
文法分析树(上下文无关文法)
短语
二义性文法及判定
自顶向下的分析方法
自顶向下的分析方法可从这两方面来理解:
- 从分析树的顶部(根节点)向底部(叶节点)方向构造语法分析树
- 从文法开始符号 S 推导出词串 ω \omega ω 的过程
自顶向下的语法分析方法采用最左推导方式
自底向上的分析方法
自底向上的分析方法可从这两方面来理解:
- 从分析树的底部(叶节点)向顶部(根节点)方向构造语法分析树
- 将输入串 ω \omega ω 规约为文法开始符号 S 的过程
自底向上的语法分析方法采用最左规约方式(反向构造最右推导)
自底向上语法分析的通用框架:移入——规约分析
移入——规约分析的工作过程:
- 在对输入串的一次从左到右扫描过程中,语法分析器将零个或多个输入符号移入到栈的顶端,直到它可以对栈顶的一个文法符号串 β \beta β进行规约为止
- 将 β \beta β规约为某个产生式的左部
- 语法分析器不断重复这个循环,直到它检测到一个语法错误,或者栈中包含了开始符号且输入缓冲区为空为止(即成功完成语法分析)
但是移入——规约分析过程也存在问题
当站内符号串末尾可同时按照不同产生式进行规约时,选择哪个产生式规约将决定最终分析的成败。
分析失败的例子:
分析成功的例子:
成功分析应是每次规约均为当前句柄,因而能否成功识别出句柄将决定分析的成败。
由于移入——规约分析存在以上的问题,为了解决以上问题,提出了LR分析法
LR分析法: 语法分析笔记(三)——LR分析法
计算机如何实现自顶向下分析?
计算机采用递归下降分析的方法
递归下降分析:
- 由一组过程组成,每个过程对应一个非终级符
- 由文法开始符号S对应的过程开始,其中递归调用文法中其他非终极符对应的过程
非终极符对应的过程是什么?以下是解释(以非终极符A为例)
void A()
{
选择一个A产生式,A->X(1)X(2)...X(k);
for(i = 1 to k)
{
if(X(i)是一个非终极符)
调用过程X(i)();
else
{
if(X(i)等于当前的输入符号a)
读入下一个输入符号;
else
error();
}
}
}
那么问题来了,如果A有多个产生式,且都含有输入符号a,那么应该怎样选择呢?
3. 逐个尝试,遇到错误就回溯,称为不确定的分析,效率低
4. 进行预测分析,通过在输入符号串中向前看固定个数(通常是1)符号来选择正确的A-产生式,不需要回溯,称为确定的分析
LL(k)文法分析:向前看k个输入符号的文法预测分析