目录
重点掌握:
(1) 给定语言,构造文法
(2) 给定文法,写出语言 (可以用规范的数学描述方式,也可以用自然语言方式)
文法的引入
- 文法:语言的定义装置
- 自动机:语言的识别装置
例
下面用文法定义语言,即“由加号和减号分隔的数字序列” (递归定义)
<
l
i
s
t
>
→
<
l
i
s
t
>
+
<
d
i
g
i
t
>
∣
<
l
i
s
t
>
−
<
d
i
g
i
t
>
∣
<
d
i
g
i
t
>
<
d
i
g
i
t
>
→
0
∣
1
∣
2
∣
3
∣
4
∣
5
∣
6
∣
7
∣
8
∣
9
\begin{aligned}<list>&→<list>+<digit>|<list>-<digit>|<digit>\\ <digit>&→0| 1| 2| 3| 4| 5| 6| 7| 8| 9 \end{aligned}
<list><digit>→<list>+<digit>∣<list>−<digit>∣<digit>→0∣1∣2∣3∣4∣5∣6∣7∣8∣9
- 其中 l i s t list list 代表的语法单位名是数字序列, d i g i t digit digit 代表的语法单位名是数字。它们都是需要进一步定义的抽象的语法单位,称为非终极符。 + + + 和 − - − 运算符以及数字称为该文法的终极符
- 该文法定义的语言的一些合法的句子是:
2 + 3 + 4 、 5 − 2 + 3 、 7 + 8 2+3+4、 5-2+3、7+8 2+3+4、5−2+3、7+8 - 利用文法进行推导并产生句子
5
−
2
+
3
5-2+3
5−2+3 的过程:
< l i s t > ⇒ < l i s t > + < d i g i t > ⇒ < l i s t > − < d i g i t > + < d i g i t > ⇒ < d i g i t > − < d i g i t > + < d i g i t > ⇒ 5 − < d i g i t > + < d i g i t > ⇒ 5 – 2 + < d i g i t > ⇒ 5 − 2 + 3 \begin{aligned}<list> &\Rightarrow<list>+<digit> \\& \Rightarrow<list>-<digit>+<digit> \\&\Rightarrow<digit>-<digit>+<digit>\\& \Rightarrow5 - <digit>+<digit> \\& \Rightarrow5 – 2 + <digit> \\& \Rightarrow5- 2 + 3\end{aligned} <list>⇒<list>+<digit>⇒<list>−<digit>+<digit>⇒<digit>−<digit>+<digit>⇒5−<digit>+<digit>⇒5–2+<digit>⇒5−2+3
文法的 EBNF 表示
EBNF:扩展巴科斯范式
元语言:用来定义一种语言的语言(可描述文法规则)
(注意 与 源语言 的区别)
下面是用来描述规则的元语言符号:
- → / : = \rightarrow\ /:= → /:= :代表“定义为”
- ∣ | ∣ :代表“或者”
- < Z > <Z> <Z>: 代表 Z Z Z 是需要进一步加以定义的抽象的语法单位名,即文法的非终结符号
-
{
Z
}
\{Z\}
{Z}: 代表
Z
Z
Z 出现 0 或任意次
{ Z } n m \{Z\}^m_n {Z}nm:代表符号串 Z Z Z 可重复连接 n n n 到 m m m 次 (很少使用) - [ Z ] [Z] [Z]: 代表 Z Z Z 最多出现一次
-
(
)
(\ )
( ):表示括号内的成分优先。常用于在规则中提取公因子
- 例如: U → x y ∣ x w ∣ … … ∣ x z U→xy|xw|……|xz U→xy∣xw∣……∣xz;可写成: U → x ( y ∣ w ∣ … … ∣ z ) U→x(y|w|……|z) U→x(y∣w∣……∣z)
例
字母打头、后面可跟数字或字母的不超过8个字符的标识符文法:
<
标
识
符
>
→
<
字
母
>
{
<
字
母
>
∣
<
数
字
>
}
0
7
<标识符>→<字母>\{<字母>|<数字>\}_0^7
<标识符>→<字母>{<字母>∣<数字>}07
字母表和符号串
- 任何一种语言都是由该语言的基本符号所组成的符号串集合的子集
- 例如,C语言的基本符号有
i f , w h i l e , f o r , … , 字 母 、 数 字 和 + 、 − 、 ( 、 ) 、 > = if,while,for,…,字母、数字和+、-、(、)、>= if,while,for,…,字母、数字和+、−、(、)、>= 等分界符
- 例如,C语言的基本符号有
字母表
- “字母表
∑
∑
∑” 是元素的非空有穷集合。字母表中的每个元素称为“符号”
- 例如:集合 { a , b , c , + , ∗ } \{a,b,c,+,*\} {a,b,c,+,∗}是一个含有5个符号的字母表
符号串
- “符号串” 是由字母表上0个或多个符号所组成的任何有穷序列
- “空串”:不包含任何符号的串,记为 ε ε ε
- ∑ ∑ ∑ 上全部有穷长符号串的集合记作 ∑ ∗ ∑^* ∑∗
例
∑
=
{
a
,
b
}
∑=\{a,b\}
∑={a,b},则
ε
,
a
,
b
,
a
a
,
b
b
,
a
b
a
ε,a,b,aa,bb,aba
ε,a,b,aa,bb,aba等都是
∑
∑
∑ 上的符号串
符号串及其集合的运算
- 符号串的长度:记为
∣
x
∣
|x|
∣x∣
- 如 ∣ a b c ∣ = 3 |abc|=3 ∣abc∣=3
- 符号串的连接:
x
y
xy
xy 表示将符号串
y
y
y 连接在符号串
x
x
x 的后面
- 注意:连接没有交换律,即 x y ≠ y x xy ≠ yx xy=yx
- 对于空串 ε ε ε ,有 ε x = x ε = x εx=xε=x εx=xε=x
- 集合的乘积运算:设
U
、
V
⊂
∑
∗
U、V\subset ∑*
U、V⊂∑∗,
U
U
U 和
V
V
V 的积(连接)定义为:
U ⋅ V = U V = { α β ∣ ( α ∈ U ) ∧ ( β ∈ V ) } U·V=UV=\{αβ|(α∈U)∧(β∈V)\} U⋅V=UV={αβ∣(α∈U)∧(β∈V)}- 例如: A = { a , b } , B = { c , d } A=\{a,b\} ,B=\{c,d\} A={a,b},B={c,d},则 A B = { a c , a d , b c , b d } AB=\{ac,ad,bc,bd\} AB={ac,ad,bc,bd}
- 对于空集合 { ε } \{ε\} {ε} 有: U { ε } = { ε } U = U U\{ε\}=\{ε\}U=U U{ε}={ε}U=U
- 符号串的幂运算:若
x
x
x 是符号串,则:
x 0 = ε , x 1 = x , x 2 = x x , … , x n = x x … x = x x n − 1 = x n − 1 x x^0=ε, x^1=x , x^2=xx ,…,x^n=xx…x=xx^{ n-1}=x^ {n-1} x x0=ε,x1=x,x2=xx,…,xn=xx…x=xxn−1=xn−1x 其中 n > 0 n>0 n>0 - 集合的幂运算:设
A
A
A 为符号串集合,则:
A 0 = { ε } , A 1 = A , A 2 = A A … … A n = A A … A = A A n − 1 = A n − 1 A A^0=\{ε\},A^1=A, A^2=AA……A^n=AA…A=AA^{n-1} =A^{n-1}A A0={ε},A1=A,A2=AA……An=AA…A=AAn−1=An−1A 其中 n > 0 n>0 n>0 - 集合的正闭包和集合的闭包:设
A
A
A 为一个集合,则集合
A
A
A 的正闭包用
A
+
A^+
A+ 表示,定义为:
A + = A 1 ∪ A 2 ∪ … . ∪ A n ∪ … A^+ =A^1 ∪A^2 ∪…. ∪A^n ∪… A+=A1∪A2∪….∪An∪…集合 A A A 的闭包用 A ∗ A^* A∗表示,定义为:
A ∗ = A 0 ∪ A + A^* =A^0 ∪A^+ A∗=A0∪A+ 显然有 A + = A A ∗ = A ∗ A A^+=AA^*=A^*A A+=AA∗=A∗A- 例如:
A
=
{
a
,
b
}
A = \{a,b\}
A={a,b},则
A
+
=
{
a
,
b
,
a
a
,
a
b
,
b
a
,
b
b
,
a
a
a
,
a
a
b
,
…
}
A^+ =\{a,b,aa,ab,ba,bb,aaa,aab,…\}
A+={a,b,aa,ab,ba,bb,aaa,aab,…},
A
∗
=
{
ε
,
a
,
b
,
a
a
,
a
b
,
b
a
,
b
b
,
a
a
a
,
a
a
b
,
…
}
A^* =\{ε ,a,b,aa,ab,ba,bb,aaa,aab,…\}
A∗={ε,a,b,aa,ab,ba,bb,aaa,aab,…}
一个集合的闭包比正闭包多个 ε ε ε
- 例如:
A
=
{
a
,
b
}
A = \{a,b\}
A={a,b},则
A
+
=
{
a
,
b
,
a
a
,
a
b
,
b
a
,
b
b
,
a
a
a
,
a
a
b
,
…
}
A^+ =\{a,b,aa,ab,ba,bb,aaa,aab,…\}
A+={a,b,aa,ab,ba,bb,aaa,aab,…},
A
∗
=
{
ε
,
a
,
b
,
a
a
,
a
b
,
b
a
,
b
b
,
a
a
a
,
a
a
b
,
…
}
A^* =\{ε ,a,b,aa,ab,ba,bb,aaa,aab,…\}
A∗={ε,a,b,aa,ab,ba,bb,aaa,aab,…}
文法和语言的形式定义
文法
G
G
G(grammar)为一个四元组
G
=
(
V
N
,
V
T
,
P
,
S
)
G = (V_N,V_T,P,S )
G=(VN,VT,P,S)
- V T V_T VT:终结符集的非空有穷集 (Terminal)
-
V
N
V_N
VN:非终结符集的非空有穷集
-
V
=
V
N
∪
V
T
V = V^N ∪ V^T
V=VN∪VT 是词汇表 / 字母表
( V V V 中符号为文法符号, V N ∩ V T = φ V^N ∩V^T = φ VN∩VT=φ )
-
V
=
V
N
∪
V
T
V = V^N ∪ V^T
V=VN∪VT 是词汇表 / 字母表
-
P
P
P:语法规则的非空有穷集 (Producer),也称为 产生式
- 即 α → β \alpha\rightarrow\beta α→β 的形式 ( α ∈ V ∗ V N V ∗ , β ∈ V ∗ \alpha\in V^*V_NV^*,\beta\in V^* α∈V∗VNV∗,β∈V∗)
- S ∈ V N S\in V_N S∈VN:文法的开始符号 (Start Symbol)
一般约定用小写字母表示终结符号;大写字母表示非终结符号
- 写文法时,可省略 V N V_N VN 和 V T V_T VT ,直接写出规则即可。但要注意要写出开始符号。例如: G [ S ] G[S] G[S] 表示 S S S 为开始符号
例
产生语言 {标识符} 的文法
解
G
[
I
]
:
I
→
L
∣
I
L
∣
I
D
L
→
a
∣
b
∣
…
∣
z
D
→
0
∣
1
∣
2
∣
3
∣
4
∣
5
∣
6
∣
7
∣
8
∣
9
\begin{aligned} G[I]: I&→L | IL | ID\\ L&→a | b |… | z \\D&→0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9\end{aligned}
G[I]:ILD→L∣IL∣ID→a∣b∣…∣z→0∣1∣2∣3∣4∣5∣6∣7∣8∣9
( I , L , D I,L,D I,L,D 分别表示标识符、字母、数字)
例
生成语言
L
=
{
a
n
b
m
∣
n
,
m
≥
1
}
L=\{a^n b^m| n, m \geq1\}
L={anbm∣n,m≥1} 的文法
解
G
[
S
]
:
S
→
A
B
A
→
a
A
∣
a
B
→
b
B
∣
b
\begin{aligned} G[S]:S&→AB\\ A&→aA | a\\ B&→bB | b\end{aligned}
G[S]:SAB→AB→aA∣a→bB∣b
例
给出语言 {无符号整数} 的文法
解
<
n
u
m
>
→
<
n
u
m
>
<
d
i
g
i
t
>
∣
<
d
i
g
i
t
>
<
d
i
g
i
t
>
→
0
∣
1
∣
2
∣
3
∣
4
∣
5
∣
6
∣
7
∣
8
∣
9
\begin{aligned} <num>&→<num><digit> | <digit>\\ <digit>&→0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9\end{aligned}
<num><digit>→<num><digit>∣<digit>→0∣1∣2∣3∣4∣5∣6∣7∣8∣9分别用推导和语法树表示
248
248
248 的生成过程:
<
n
u
m
>
⇒
<
n
u
m
>
<
d
i
g
i
t
>
⇒
<
n
u
m
>
<
d
i
g
i
t
>
<
d
i
g
i
t
>
⇒
<
d
i
g
i
t
>
<
d
i
g
i
t
>
<
d
i
g
i
t
>
⇒
2
<
d
i
g
i
t
>
<
d
i
g
i
t
>
⇒
24
<
d
i
g
i
t
>
⇒
248
\begin{aligned} <num>&\Rightarrow<num><digit>\\&\Rightarrow<num><digit><digit>\\&\Rightarrow <digit><digit><digit>\\&\Rightarrow2 <digit><digit> \\&\Rightarrow24<digit> \\&\Rightarrow248\end{aligned}
<num>⇒<num><digit>⇒<num><digit><digit>⇒<digit><digit><digit>⇒2<digit><digit>⇒24<digit>⇒248
语法树 (以开始符号为根结点):
例
函数调用中的参数列表对应的文法
例
- 分号的放置方式很微妙。它们出现在所有不以 s t m t stmt stmt 结尾的产生式的末尾。这种方法可以避免在 i f if if 或 w h i l e while while 这样的语句后面出现多余的分号,因为 i f if if 和 w h i l e while while 语句的最后是一个嵌套的子语句。当嵌套子语句是一个赋值语句或 d o do do- w h i l e while while 语句时,分号将作为这个子语句的一部分被生成
例
- 证明:用下面文法生成的所有二进制串的值都能被3整除
- 该文法是否能够生成所有能被 3 整除的二进制串?
n u m → 11 ∣ 1001 ∣ n u m 0 ∣ n u m n u m num \rightarrow 11 | 1001 | num\ 0 | num\ num num→11∣1001∣num 0∣num num
解
- 显然该文法生成的所有二进制串都能被3整除
- 假设该文法能够生成所有能被 3 整除的二进制串,则可得到如下结果:
3 k = n u m → 11 ∣ 1001 ∣ n u m 0 ∣ n u m n u m k = n u m / 3 → 01 ∣ 0011 ∣ k 0 ∣ k k k → 01 ∣ 0011 ∣ k 0 ∣ k k \begin{aligned}3k = num &\rightarrow 11 | 1001 | num\ 0 | num\ num\\ k = num/3 &\rightarrow 01 | 0011 | k\ 0 | k\ k\\ k & \rightarrow 01 | 0011 | k\ 0 | k\ k\end{aligned} 3k=numk=num/3k→11∣1001∣num 0∣num num→01∣0011∣k 0∣k k→01∣0011∣k 0∣k k k k k 只能含有不超过两个连续的1,因此类似 k = 111 k=111 k=111 ( 3 k = 21 = 10101 3k=21=10101 3k=21=10101) 这种3的倍数就无法被生成
推导
- 直接推导
⇒
\Rightarrow
⇒
α → β α→β α→β 是文法 G G G 的产生式,若有 v , w v, w v,w 满足: v = γ α δ , w = γ β δ v=γαδ, w= γβδ v=γαδ,w=γβδ, 其中 γ ∈ V ∗ , δ ∈ V ∗ γ∈V*,δ∈V* γ∈V∗,δ∈V∗,则称 v v v 直接推导到 w w w,记作 v ⇒ w v \Rightarrow w v⇒w- 例:
G
[
S
]
:
S
→
0
S
1
,
S
→
01
G[S]: S→0S1, S→01
G[S]:S→0S1,S→01
S ⇒ 0 S 1 ⇒ 00 S 11 S \Rightarrow0S1 \Rightarrow00S11 S⇒0S1⇒00S11
- 例:
G
[
S
]
:
S
→
0
S
1
,
S
→
01
G[S]: S→0S1, S→01
G[S]:S→0S1,S→01
- 推导
⇒
∗
\Rightarrow^*
⇒∗ ( 0 次或任意多次复合 )
- 若存在 α 0 ⇒ α 1 ⇒ . . . ⇒ α n α_0 \Rightarrow α_1\Rightarrow ...\Rightarrow α_n α0⇒α1⇒...⇒αn, ( n > 0 ) (n>0) (n>0),则记为 α 0 ⇒ + α n α_0 \Rightarrow^+ α_n α0⇒+αn (正闭包),称作 α 0 α_0 α0 推导出 α n α_n αn ,或 α n α_n αn 归约到 α 0 α_0 α0
- 若有 α 0 ⇒ + α n α_0 \Rightarrow^+ α_n α0⇒+αn 或 α 0 = α n α_0 = α_n α0=αn , 则记为 α 0 ⇒ ∗ α n α_0 \Rightarrow^* α_n α0⇒∗αn(自反传递闭包)
- 若从 α 0 α_0 α0 出发,经过 k k k 次推导,可推出 α n α_n αn,记为: α 0 ⇒ k α n α_0 \Rightarrow^k α_n α0⇒kαn ( k k k 次复合)
句型、句子的定义
句型
- 文法 G = ( V N , V T , P , S ) G=(V_N, V_T, P, S) G=(VN,VT,P,S) ,若 S ⇒ ∗ x S \Rightarrow^* x S⇒∗x,且 x ∈ ( V N ∪ V T ) ∗ x∈(V_N∪V_T)^* x∈(VN∪VT)∗ ,则称 x x x 是文法 G G G 的句型
句子
- 有文法 G G G,若 S ⇒ ∗ x S \Rightarrow^* x S⇒∗x,且 x ∈ V T ∗ x∈V_T^* x∈VT∗,则称 x x x 是文法 G G G 的句子。即可由开始符号推出的,仅由终极符组成的句型
例
G
[
S
]
:
S
→
0
S
1
,
S
→
01
S
⇒
0
S
1
⇒
00
S
11
⇒
000
S
111
⇒
00001111
G[S]: S→0S1, S→01\\ S \Rightarrow0S1 \Rightarrow00S11 \Rightarrow000S111 \Rightarrow00001111
G[S]:S→0S1,S→01S⇒0S1⇒00S11⇒000S111⇒00001111
- G G G 的句型: S , 0 S 1 , 00 S 11 , 000 S 111 , 00001111 … S,0S1 ,00S11 ,000S111,00001111… S,0S1,00S11,000S111,00001111…
- G G G的句子: 00001111 , 01 … 00001111, 01… 00001111,01…
(文法生成的) 语言的定义
语言
- 由文法
G
G
G 生成的语言记为
L
(
G
)
L(G)
L(G) ,它是文法
G
G
G 的一切句子的集合:
L ( G ) = { x ∣ S ⇒ ∗ x , 其 中 S 为 文 法 的 开 始 符 号 , 且 x ∈ V T ∗ } L(G)=\{x|S \Rightarrow^* x,其中S为文法的开始符号,且x ∈V_T^*\} L(G)={x∣S⇒∗x,其中S为文法的开始符号,且x∈VT∗}
等价文法
- 给定一个文法, 就能从结构上唯一的确定其语言
- 给定一种语言, 能确定其文法, 但不唯一
- 如果两个不同的文法可描述相同的语言,那么我们称这两个文法为等价文法 (若 L ( G 1 ) = L ( G 2 ) L(G_1)=L(G_2) L(G1)=L(G2),则称文法 G 1 G_1 G1 和 G 2 G_2 G2 是等价的)
例
G
[
Z
]
:
Z
→
a
Z
b
∣
a
b
G[Z]:Z→ aZb| ab
G[Z]:Z→aZb∣ab求该文法确定的语言
解
从识别符号开始推导,反复用规则1可得:
Z
⇒
a
Z
b
⇒
a
2
Z
b
2
⇒
…
⇒
a
n
−
1
Z
b
n
−
1
Z \Rightarrow aZb \Rightarrow a^2Zb^2 \Rightarrow … \Rightarrow a^{n-1} Zb^{n-1}
Z⇒aZb⇒a2Zb2⇒…⇒an−1Zbn−1最后用规则2可得:
Z
⇒
a
Z
b
⇒
a
2
Z
b
2
⇒
…
⇒
a
n
−
1
Z
b
n
−
1
⇒
a
n
b
n
Z \Rightarrow aZb \Rightarrow a^2Zb^2 \Rightarrow … \Rightarrow a^{n-1} Zb^{n-1} \Rightarrow a^nb^n
Z⇒aZb⇒a2Zb2⇒…⇒an−1Zbn−1⇒anbn
∴
L
(
G
[
Z
]
)
=
{
a
n
b
n
∣
n
≥
1
}
\therefore L(G[Z])=\{a^nb^n|n≥1\}
∴L(G[Z])={anbn∣n≥1}
递归规则与递归文法
句子的个数是有穷还是无穷取决于文法是否是递归的。递归文法使我们能用有穷的文法刻画无穷的语言
- 递归规则:在规则的右部含有与规则左部相同符号
- 若文法中至少包含一条递归规则, 则称文法是直接递归的。有些文法,表面看上去没有递归规则,但经过几步推导,也能造成文法的递归性,则称为间接递归文法
- 例如,有文法为: U → V x , V → U y ∣ v U → Vx , V → Uy|v U→Vx,V→Uy∣v,有推导过程 U ⇒ V x ⇒ U y x U\Rightarrow Vx\Rightarrow Uyx U⇒Vx⇒Uyx,所以该文法为间接递归文法
- 若文法中至少包含一条递归规则, 则称文法是直接递归的。有些文法,表面看上去没有递归规则,但经过几步推导,也能造成文法的递归性,则称为间接递归文法
- 如果这个相同的符号出现在右部的最左端,则为左递归规则
如 U : : = U y U::=Uy U::=Uy - 如果这个相同的符号出现在右部的最右端,则为右递归规则
如 U : : = x U U::=xU U::=xU
写文法一般采用“串联”和“并联”两种手段
- “串联”:把一个句子结构分解为几个相连接的子结构 (如例1、例2)
- “并联”:难以用统一形式表达的句子,可用几种不同方式表达出来,构成不相交的划分 (如例3中把正偶数分为一位正偶数和多位正偶数分别进行表示)
例1
已知语言
{
a
n
b
n
a
m
b
m
∣
n
,
m
≥
0
}
\{a^nb^na^mb^m | n, m≥0\}
{anbnambm∣n,m≥0},求文法
解
S
→
A
A
A
→
a
A
b
∣
ε
S→AA\\ A→aAb |ε
S→AAA→aAb∣ε
例2
已知语言
{
a
i
b
a
j
∣
i
,
j
≥
0
}
\{a^iba^j | i, j≥0\}
{aibaj∣i,j≥0},求文法
解
S
→
A
b
A
A
→
a
A
∣
ε
S→AbA\\ A→aA |ε
S→AbAA→aA∣ε或者
S
→
a
S
∣
b
A
A
→
a
A
∣
ε
S→aS | bA \\A→aA | ε
S→aS∣bAA→aA∣ε
例3
给出生成非零开头的正偶数集合的文法
解
S
→
A
B
C
∣
2
∣
4
∣
6
∣
8
A
→
1
∣
2
∣
3
∣
4
∣
5
∣
6
∣
7
∣
8
∣
9
B
→
A
B
∣
0
B
∣
ε
C
→
0
∣
2
∣
4
∣
6
∣
8
S→ABC | 2 | 4 | 6 | 8\\ A→1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 \\B→AB| 0B |ε\\ C→0 | 2 | 4 | 6 | 8
S→ABC∣2∣4∣6∣8A→1∣2∣3∣4∣5∣6∣7∣8∣9B→AB∣0B∣εC→0∣2∣4∣6∣8
例
已知下列文法,求文法生成的语言是什么 ?
S
→
0
S
0
∣
1
S
1
∣
ε
S→0S0 | 1S1 |ε
S→0S0∣1S1∣ε
解
文法产生的句子形式为:00,11,0110,1001,…,其特点是镜像结构
L
(
G
)
=
{
X
X
−
1
∣
X
∈
{
0
,
1
}
∗
,
X
−
1
为
X
的
逆
,
没
有
中
心
元
素
的
镜
像
结
构
语
言
}
L(G)=\{XX^{-1} | X∈\{0, 1\}^*,X^{-1}为X的逆,没有中心元素的镜像结构语言\}
L(G)={XX−1∣X∈{0,1}∗,X−1为X的逆,没有中心元素的镜像结构语言}
例
已知下列文法,求文法生成的语言是什么 ?
S
→
S
(
S
)
S
∣
ε
S→S(S)S |ε
S→S(S)S∣ε
解
- 首先文法的终极符是
(
(
( 和
)
)
),即句子只能是左、右圆括号组成。而
S
S
S 的每一次非
ε
ε
ε 推导,都会产生一对左右圆括号。并且在已产生的
(
)
(\ )
( ) 的前面、后面和里面都可以产生圆括号对,且能递归分析下去。若使用
S
→
ε
S→ε
S→ε 产生式,将去掉句型中的某个
S
S
S,这就使得句子中左右圆括号的配对和嵌套具有随意性
L ( G ) = { α ∣ α 为 空 串 或 可 任 意 嵌 套 的 配 对 的 左 右 圆 括 号 序 列 } L(G)=\{α|α为空串或可任意嵌套的配对的左右圆括号序列 \} L(G)={α∣α为空串或可任意嵌套的配对的左右圆括号序列}
例题
- 一个文法 G [ S ] G[S] G[S] 若存在推导序列 S ⇒ + … S … S\Rightarrow^+…S… S⇒+…S…, 则称 G [ S ] G[S] G[S] 是____文法,该文法产生的句子有____个
- 文法
G
G
G 所描述的语言是____的集合
A.文法 G G G 的词汇表 V V V 中所有符号组成的符号串
B.文法 G G G 的词汇表 V V V 的闭包 V ∗ V^* V∗ 中的所有符号串
C.由文法的识别符号推出的所有符号串
D.由文法的识别符号推出的所有终结符号串 - BNF是一种广泛采用的____的工具
A. 描述规则 B.描述语言
C.描述文法 D.描述句子
答案:
- 递归,无数
- D
- C
文法和语言分类
0型文法 (规则不受限制的文法)
- 若文法中有如下形式的规则:
α → β , 其 中 α ∈ V ∗ V N V ∗ , β ∈ V ∗ , V = V N ∪ V T α→β ,其中α∈V^* V_N V^* ,β∈V^* ,V= V_N∪V_T α→β,其中α∈V∗VNV∗,β∈V∗,V=VN∪VT且对 α , β α,β α,β 不加任何其它的限制。则为0型文法
规则的右边不受限制,左边至少含有一个非终结符号
- 0型文法描述的语言为0型语言,用 L 0 L_0 L0 表示
**例
G
[
S
]
:
S
→
A
C
a
B
,
C
a
→
a
a
C
,
C
B
→
D
B
,
C
B
→
E
,
a
D
→
D
a
,
A
D
→
A
C
,
a
E
→
E
a
,
A
E
→
ε
\begin{aligned}G[S]: S&→ACaB,\\Ca&→aaC,\\CB&→DB,\\CB&→E,\\aD&→Da,\\AD&→AC, \\aE&→Ea,\\AE&→ε\end{aligned}
G[S]:SCaCBCBaDADaEAE→ACaB,→aaC,→DB,→E,→Da,→AC,→Ea,→ε
L [ G ] = { a i ∣ i 为 2 的 正 整 次 方 } , 即 L = { a a , a a a a , a a a a a a a a , … } L[G]=\{a^i | i 为2的正整次方\},即L=\{aa, aaaa, aaaaaaaa, …\} L[G]={ai∣i为2的正整次方},即L={aa,aaaa,aaaaaaaa,…}
1型文法 (上下文有关文法, CSG)
Context-Sensitive-Grammar
- 若一个0型文法
G
G
G 中有如下形式的规则:
α U β → α u β , 其 中 U ∈ V N , α 、 β ∈ V ∗ , u ∈ V + , V = V N ∪ V T αUβ→αuβ,其中 U∈V_N,α、β∈V^*, u ∈V^+ ,V= V_N∪V_T αUβ→αuβ,其中U∈VN,α、β∈V∗,u∈V+,V=VN∪VT则为1型文法- 当把规则应用到推导中,只有在上下文 α α α 和 β β β 中,才能把 U U U 重写为 u u u
u ∈ V + u ∈V^+ u∈V+ 表示 u u u 非空
- 1型文法描述的语言为1型语言,用 L 1 L_1 L1 表示
- 1型文法的另一等价定义:
若一个0型文法 G G G 中所有产生式 α → β α→β α→β 都满足如下的条件:
∣ α ∣ ≤ ∣ β ∣ ( α , β ∈ V + ) |α|≤|β|(α,β∈V^+) ∣α∣≤∣β∣(α,β∈V+),则称 G G G 为1型文法
**例
已知语言
{
a
n
b
n
c
n
∣
n
≥
1
}
\{a^nb^nc^n | n≥1\}
{anbncn∣n≥1} ,求文法
解
仿照
{
a
n
b
n
∣
n
≥
1
}
\{a^nb^n | n≥1\}
{anbn∣n≥1} 的产生式,则
{
a
n
b
n
c
n
∣
n
≥
1
}
\{a^nb^nc^n | n≥1\}
{anbncn∣n≥1} 的文法可能是
S
→
a
S
b
c
∣
a
b
c
S→aSbc | abc
S→aSbc∣abc。然而,这个文法生成的一个句子是
a
a
a
b
c
b
c
b
c
aaabcbcbc
aaabcbcbc,而原题中语言的一个合法句子是
a
a
a
b
b
b
c
c
c
aaabbbccc
aaabbbccc。显然必须实现
c
c
c 与
b
b
b 的换位,但由于无法通过终极符换位,所以考虑用非终极符
B
B
B 和
C
C
C 标记
b
b
b 和
c
c
c,修改文法:
S
→
a
B
C
∣
a
S
B
C
C
B
→
B
C
S→aBC | aSBC\\ CB→BC
S→aBC∣aSBCCB→BC新添加的一条文法使得
B
B
B 不断前移,
C
C
C 不断后移。此时产生的一个句子是:
a
a
a
B
B
B
C
C
C
aaaBBBCCC
aaaBBBCCC
由于只有
B
B
B 的前面是
a
a
a 或
b
b
b,才能将
B
B
B 重写为
b
b
b,即
a
B
→
a
b
,
b
B
→
b
b
aB→ab,bB→bb
aB→ab,bB→bb。同理,只有
C
C
C 的前面是
b
b
b 或
c
c
c,才能将
C
C
C 重写为
c
c
c,即
b
C
→
b
c
,
c
C
→
c
c
bC→bc,cC→cc
bC→bc,cC→cc。因此文法
G
(
S
)
G(S)
G(S) 为:
S
→
a
B
C
∣
a
S
B
C
(
1
)
C
B
→
B
C
(
2
)
b
B
→
b
b
(
3
)
a
B
→
a
b
(
4
)
b
C
→
b
c
(
5
)
c
C
→
c
c
(
6
)
\begin{aligned}S→aBC | aSBC\ \ \ \ \ \ \ (1)\\ CB→BC\ \ \ \ \ \ \ (2)\\ bB→bb\ \ \ \ \ \ \ (3)\\ aB→ab\ \ \ \ \ \ \ (4)\\ bC→bc\ \ \ \ \ \ \ (5)\\ cC→cc\ \ \ \ \ \ \ (6)\end{aligned}
S→aBC∣aSBC (1)CB→BC (2)bB→bb (3)aB→ab (4)bC→bc (5)cC→cc (6)下面更详细的分析一下上述文法生成的语言就是
{
a
n
b
n
c
n
∣
n
≥
1
}
\{a^nb^nc^n | n≥1\}
{anbncn∣n≥1} :
首先,通过之前的分析应该能看出,该文法生成的语言一定包括了句子
a
n
b
n
e
n
a^nb^ne^n
anbnen。那么就只要说明
a
n
b
n
e
n
a^nb^ne^n
anbnen 是该文法唯一形式的终结符号串:
可以看出,在使用
(
1
)
(1)
(1) 的后半部分产生式消去
S
S
S 之前,
(
3
)
(3)
(3)
(
4
)
(4)
(4)
(
5
)
(5)
(5)
(
6
)
(6)
(6) 都使用不了。而在消去
S
S
S 之后,句型就由
n
n
n 个
a
a
a,后面跟某种次序的
n
n
n 个
B
B
B 和
n
n
n 个
E
E
E 组成。由于没有了
S
S
S,此后就不能使用
(
1
)
(1)
(1) 了。目前句型的特点是前面为终结符,后面为非终结符。而
(
3
)
(3)
(3)
(
4
)
(4)
(4)
(
5
)
(5)
(5)
(
6
)
(6)
(6) 都只能在终结符和非终结符的边缘使用,并且在任何
C
C
C 被转化为
c
c
c 之前,所有的
B
B
B 都必须在终结符和非终结符的边缘被转化为
b
b
b,否则假设有一个
C
C
C 在
B
B
B 的右边被转化为了
c
c
c,那么句型为
a
n
b
i
c
α
a^nb^ic\alpha
anbicα,
α
\alpha
α 为由
B
,
C
B,C
B,C 组成的串,此时只能使用
(
2
)
(2)
(2)
(
6
)
(6)
(6),而无论哪个规则都无法消去
B
B
B,因此假设不成立,进而成功证明
a
n
b
n
e
n
a^nb^ne^n
anbnen 是该文法唯一形式的终结符号串
2型文法 (上下文无关文法, CFG)
Context-Free-Grammars
- 若一个1型文法
G
G
G 中的规则都具有如下形式:
A → u , 其 中 A ∈ V N , u ∈ V ∗ , V = V N ∪ V T A→u, 其中 A∈ V_N , u∈ V^*,V=V_N∪V_T A→u,其中A∈VN,u∈V∗,V=VN∪VT则称 G G G 为2型文法,又称为上下文无关文法 - 2型文法所定义的语言是2型语言或称为上下文无关语言,用 L 2 L_2 L2 表示
如果 A → β A→β A→β 是2型文法的产生式,则无论 A A A 出现在句型中的任何位置,都可将 A A A 替换为 β β β 而不需考虑 A A A 的上下文。这种特性使得对程序设计语言的语法分析(推导或归约)变得相对简单。目前大多数的高级程序设计语言的语法特性都是上下文无关的
例
L
=
{
a
m
b
n
∣
m
>
n
≥
0
}
L=\{a^mb^n |m>n\geq0\}
L={ambn∣m>n≥0}
解
S
→
a
S
∣
a
B
B
→
a
B
b
∣
ε
\begin{aligned}S&→aS|aB\\ B&→aBb| ε\end{aligned}
SB→aS∣aB→aBb∣ε
或者
S
→
A
B
A
→
a
A
∣
a
B
→
a
B
b
∣
ε
\begin{aligned}S&→AB\\ A&→aA|a\\ B&→aBb| ε\end{aligned}
SAB→AB→aA∣a→aBb∣ε2型文法,语言属于2型语言
例
L
=
{
a
m
b
c
m
∣
m
≥
1
}
∪
{
a
n
b
n
c
m
d
m
∣
m
,
n
≥
1
}
L=\{a^mbc^m |m\geq1\} ∪\{a^nb^nc^md^m|m,n \geq1\}
L={ambcm∣m≥1}∪{anbncmdm∣m,n≥1}
解
G
[
S
]
:
S
→
D
∣
A
B
D
→
a
D
c
∣
a
b
c
A
→
a
A
b
∣
a
b
B
→
c
B
d
∣
c
d
\begin{aligned}G[S]: S&→D|AB\\ D&→aDc| abc\\ A&→aAb| ab\\ B&→cBd| cd\end{aligned}
G[S]:SDAB→D∣AB→aDc∣abc→aAb∣ab→cBd∣cd
例
给出下面文法
G
[
S
]
G[S]
G[S] 所产生的语言.
S
→
a
S
∣
b
A
∣
ε
①
A
→
a
S
∣
a
②
\begin{aligned}S&→aS|bA| ε①\\ A&→aS|a ②\end{aligned}
SA→aS∣bA∣ε①→aS∣a②
解
②代入①:
G
[
S
]
:
S
→
a
S
∣
b
(
a
S
∣
a
)
∣
ε
S
→
a
S
∣
b
a
S
∣
b
a
∣
ε
S
→
(
a
∣
b
a
)
S
∣
(
b
a
∣
ε
)
\begin{aligned}G[S]: S&→aS| b(aS|a )| ε\\ S&→aS| baS|ba | ε\\ S&→(a|ba)S| (ba| ε)\end{aligned}
G[S]:SSS→aS∣b(aS∣a)∣ε→aS∣baS∣ba∣ε→(a∣ba)S∣(ba∣ε)所以
S
=
(
a
∣
b
a
)
∗
(
b
a
∣
ε
)
S=(a|ba)^* (ba| ε)
S=(a∣ba)∗(ba∣ε)
3型文法(正则文法,Regular Grammar,RG)
- 若在一个2型文法中仅含有如下形式的产生式:
U → a 或 U → a W ( 即 : 右 线 性 文 法 ) 其 中 U , W ∈ V N , a ∈ V T ∗ U→a 或U→aW( 即:右线性文法)其中 U,W∈ V_N, a∈ V_T^* U→a或U→aW(即:右线性文法)其中U,W∈VN,a∈VT∗则称 G G G 为3型文法,又称为正则文法 - 而仅含有如下形式的产生式
U → a 或 U → W a U→a 或 U →Wa U→a或U→Wa则称为左线性文法。左线性文法也生成3型语言,即正则语言
左线性文法和右线性文法都称为线性文法,二者是等价的
- 3 型文法描述的语言为3型语言、正则语言,用
L
3
L_3
L3 表示。3型文法可用于描述高级程序设计语言的单词符号。但无法描述嵌套结构
- 如:标识符、无符号整数…都是采用3型文法来描述的
< I D > → a ∣ b ∣ … ∣ z ∣ < I D > a ∣ … ∣ < I D > z ∣ < I D > 0 ∣ … ∣ < I D > 9 < N U M > → 0 ∣ 1 ∣ … ∣ 9 ∣ 0 < N U M > ∣ 1 < N U M > ∣ … ∣ 9 < N U M > \begin{aligned}<ID>→&a | b | …|z \\ &| <ID> a |…| <ID> z\\ &| <ID>0 |… | <ID>9\\ <NUM>→&0 | 1| …|9\\ &| 0<NUM> | 1<NUM> |…| 9<NUM> \end{aligned} <ID>→<NUM>→a∣b∣…∣z∣<ID>a∣…∣<ID>z∣<ID>0∣…∣<ID>90∣1∣…∣9∣0<NUM>∣1<NUM>∣…∣9<NUM>
- 如:标识符、无符号整数…都是采用3型文法来描述的
注意:同一文法中,既有左线性、又有右线性规则,不能称之为正则文法
例如:生成语言 { 0 n 1 n ∣ n ≥ 1 } \{0^n1^n | n≥1\} {0n1n∣n≥1} 的文法: G : S → 0 S 1 ∣ 01 G:S→0S1 | 01 G:S→0S1∣01(是2型文法)。可改写为: G 1 : S → 0 A ∣ 01 , A → S 1 G_1:S→0A | 01,A→S1 G1:S→0A∣01,A→S1,同时有左线性、右线性规则,不是正则文法。该文法生成的语言是2型语言,即上下文无关语言
例
写出生成下述语言的文法,并指出该语言属于2型还是3型语言
L = { a n b m ∣ n , m ≥ 1 } L=\{a^n b^m| n, m \geq1\} L={anbm∣n,m≥1}
解
G
[
S
]
:
S
→
A
B
A
→
a
A
∣
a
B
→
b
B
∣
b
\begin{aligned}G[S]:S&→AB\\ A&→aA | a\\ B&→bB | b \end{aligned}
G[S]:SAB→AB→aA∣a→bB∣b
或
G
[
S
]
:
S
→
a
S
∣
a
B
B
→
b
B
∣
b
\begin{aligned}G[S]:S&→aS|aB\\ B&→bB | b\end{aligned}
G[S]:SB→aS∣aB→bB∣b
语言属于3型语言(可写成正则式:
a
a
∗
b
b
∗
aa^*bb^*
aa∗bb∗)
上题中第一个文法是二型文法,但是描述的语言却是三型语言
四类文法的比较
在上述四类文法中,从0型到3型文法对规则的限制逐渐增加,产生的语言类却逐步缩小,即:
- 0型语言包含1型语言,1型语言包含2型语言,2型语言包含3型语言
- 上述定义的4类文法在描述语言的能力上是从0型开始依次减弱(但规则的限制逐步增强)
- 我们主要研究 2、3型文法
例
语言的文法规则为:
S
→
A
∣
A
B
,
A
→
0
∣
0
A
,
B
→
1
∣
11
S→A | AB , A→0 | 0A ,B→1 | 11
S→A∣AB,A→0∣0A,B→1∣11,试写出语言
解
S
⇒
A
,
S
⇒
A
B
A
⇒
0
A
⇒
00
A
.
.
.
⇒
00...00...
∴
L
(
A
)
=
{
0
n
∣
n
≥
1
}
∵
B
⇒
1
,
B
⇒
11
∴
L
(
B
)
=
{
1
,
11
}
L
(
S
)
=
L
(
A
)
∪
L
(
A
)
L
(
B
)
=
{
0
,
00
,
…
}
∪
{
01
,
001
,
0001
,
…
}
∪
{
011
,
0011
,
00011
,
…
}
S \Rightarrow A,S \Rightarrow AB\\ A\Rightarrow 0A\Rightarrow 00A ...\Rightarrow 00...00...\\\therefore L(A)=\{0^n | n≥1\}\\ \because B\Rightarrow 1,B \Rightarrow 11\\ \therefore L(B)=\{1, 11\}\\L(S)=L(A)∪L(A)L(B)=\{0, 00, …\}∪\{01, 001, 0001, …\}∪\{011, 0011, 00011, …\}
S⇒A,S⇒ABA⇒0A⇒00A...⇒00...00...∴L(A)={0n∣n≥1}∵B⇒1,B⇒11∴L(B)={1,11}L(S)=L(A)∪L(A)L(B)={0,00,…}∪{01,001,0001,…}∪{011,0011,00011,…}
例
求下列语言的文法
(1)语言
{
a
n
b
m
c
m
d
n
∣
n
,
m
≥
1
}
\{a^nb^mc^md^n | n,m\geq1\}
{anbmcmdn∣n,m≥1}
(2)语言
{
a
n
b
n
c
m
d
m
∣
n
,
m
≥
1
}
\{a^nb^nc^md^m | n,m\geq1\}
{anbncmdm∣n,m≥1}
(3)语言
{
w
c
w
∣
w
∈
{
a
,
b
}
∗
}
\{wcw| w\in\{a,b\}^*\}
{wcw∣w∈{a,b}∗}
(4)语言
{
a
n
b
m
c
n
d
m
∣
n
,
m
≥
0
}
\{a^nb^mc^nd^m| n,m\geq0\}
{anbmcndm∣n,m≥0}
解
(1) 该语言是上下文无关的
S
→
a
S
d
∣
a
A
d
A
→
b
A
c
∣
b
c
S→aSd| aAd\\ A→bAc | bc
S→aSd∣aAdA→bAc∣bc
(2) 该语言是上下文无关的
S
→
A
B
A
→
a
A
b
∣
a
b
B
→
c
B
d
∣
c
d
S→AB \\A→aAb | ab \\B→cBd | cd
S→ABA→aAb∣abB→cBd∣cd
(3) 该语言是一个抽象语言,第1个
w
w
w 代表标识符的声明,第2个
w
w
w 代表标识符的引用。这个语言是关于检查程序中标识符的声明应先于其使用的问题的抽象。因此该语言是上下文敏感的。
由于程序设计语言的语法特性绝大多数是上下文无关的,因此编译器是在语法分析阶段检查上下文无关的语法特性,而上下文敏感的语法特性在语义分析阶段检查。
(4) 该语言是关于检查过程声明的形参个数和过程调用的实参个数一致的问题的抽象,是上下文敏感语言。编译器在语义分析阶段检查参数的匹配问题。
例如,
a
n
,
b
m
a^n,b^m
an,bm 代表两个过程定义的形参表中形参个数分别是
n
,
m
n,m
n,m。
c
n
,
d
m
c^n,d^m
cn,dm 代表两个过程调用的实参表中实参个数分别是
n
,
m
n,m
n,m
**例
为语言
{
w
w
∣
w
∈
{
a
,
b
}
+
}
\{ww| w\in\{a,b\}^+\}
{ww∣w∈{a,b}+},构造文法
解
S
→
a
S
A
∣
b
S
B
∣
a
C
A
∣
b
C
B
∣
a
a
∣
b
b
a
A
→
A
a
b
A
→
A
b
b
B
→
B
b
a
B
→
B
a
C
A
→
C
a
∣
a
C
B
→
C
b
∣
b
S→aSA|bSB|aCA|bCB|aa|bb\\ aA→Aa\\ bA→Ab\\ bB→Bb\\ aB→Ba\\ CA→Ca|a \\ CB→Cb|b
S→aSA∣bSB∣aCA∣bCB∣aa∣bbaA→AabA→AbbB→BbaB→BaCA→Ca∣aCB→Cb∣b解析:第一条规则每循环一次,就生成一对
a
A
aA
aA 或
b
B
bB
bB,中间为
C
C
C、如:
a
a
b
a
C
A
B
A
A
aabaCABAA
aabaCABAA;最后两条规则将靠近
C
C
C 的
A
A
A 和
B
B
B 分别变为
a
a
a 和
b
b
b,剩下的四条规则负责将生成的中间的
a
a
a 和
b
b
b 移到最后,从而使生成的句子前后两部分相同
例
令
∑
=
{
0
,
1
}
∑=\{0,1\}
∑={0,1},下列语言在结构上有什么样的特点?
(1)
L
1
=
{
00
,
01
,
10
,
11
}
L_1=\{00,01,10,11\}
L1={00,01,10,11}
(2)
L
2
=
{
0
,
1
,
00
,
01
,
10
,
11
,
000
,
…
}
=
∑
+
(
正
闭
包
)
L_2=\{0,1,00,01,10,11,000,…\} =∑^+(正闭包)
L2={0,1,00,01,10,11,000,…}=∑+(正闭包)(0、1上的所有非空串)
(3)
L
3
=
{
ε
,
0
,
1
,
00
,
01
,
10
,
11
,
000
,
…
}
=
∑
∗
(
克
林
闭
包
)
L_3=\{ε,0,1,00,01,10,11,000,…\} = ∑*(克林闭包)
L3={ε,0,1,00,01,10,11,000,…}=∑∗(克林闭包)
(4)
L
4
=
{
0
n
∣
n
≥
1
}
L_4=\{ 0^n| n\geq1\}
L4={0n∣n≥1}
(5)
L
5
=
{
0
n
1
n
∣
n
≥
1
}
L_5=\{0^n1^n| n\geq1\}
L5={0n1n∣n≥1}
(6)
L
6
=
{
0
n
1
m
∣
n
,
m
≥
1
}
L_6=\{0^n1^m| n,m\geq1\}
L6={0n1m∣n,m≥1}
(7)
L
7
=
{
0
n
1
n
0
n
∣
n
≥
1
}
L_7 =\{0^n1^n0^n| n\geq1\}
L7={0n1n0n∣n≥1}
(8)
L
8
=
{
0
n
1
m
0
k
∣
n
,
m
,
k
≥
1
}
L_8 =\{0^n1^m0^k| n,m,k\geq1\}
L8={0n1m0k∣n,m,k≥1}
(9)
L
9
=
{
x
∣
x
∈
∑
+
,
且
x
中
0
和
1
的
个
数
相
同
}
L_9 =\{x|x∈∑^+,且x中0和1的个数相同\}
L9={x∣x∈∑+,且x中0和1的个数相同}
(10)
L
10
=
{
0
n
1
m
0
n
∣
n
,
m
≥
1
}
L_{10} =\{0^n1^m0^n| n,m\geq1\}
L10={0n1m0n∣n,m≥1}
(11)
L
11
=
{
x
x
R
∣
x
∈
(
0
∣
1
)
∗
,
x
R
是
x
的
逆
}
L_{11}=\{xx^R | x∈(0|1)*, x^R是x的逆 \}
L11={xxR∣x∈(0∣1)∗,xR是x的逆}
解
(1)~(4) 3型
(5) 2型 (嵌套结构:2型)
(6) 3型 (
G
(
S
)
:
S
→
0
S
∣
0
A
,
A
→
1
A
∣
1
G(S):S\rightarrow0S|0A,A\rightarrow 1A|1
G(S):S→0S∣0A,A→1A∣1)
(7) 1型
(8) 3型
(9)~(11) 2型
例
设
G
=
{
N
,
T
,
P
,
S
}
,
N
=
{
S
,
A
,
B
}
,
T
=
{
a
,
b
}
G=\{N,T,P,S\}, N=\{S,A,B\}, T=\{a,b\}
G={N,T,P,S},N={S,A,B},T={a,b}
P
:
S
→
a
B
∣
b
A
A
→
a
∣
a
S
∣
b
A
A
B
→
b
∣
b
S
∣
a
B
B
\begin{aligned} P: S&→aB|bA\\ A&→a|aS|bAA\\ B&→b|bS|aBB \end{aligned}
P:SAB→aB∣bA→a∣aS∣bAA→b∣bS∣aBB求产生的语言
解
由相同个数的
a
、
b
a、b
a、b 组成的串的集合
(可用数学归纳法证明)(
H
i
n
t
:
Hint:
Hint: 如果
S
S
S 中
a
,
b
a,b
a,b 数量相等,那么
B
B
B 中
b
b
b 比
a
a
a 多一个,
A
A
A 中
a
a
a 比
b
b
b 多一个)
例
给出生成下述语言的文法,并指出语言类型
语
言
L
=
{
a
i
b
j
∣
i
≠
j
,
i
,
j
>
0
}
语言 L = \{ a^ib^j | i≠j, i,j>0 \}
语言L={aibj∣i=j,i,j>0}
解
该语言可视为两个语言的并集:
L
1
=
{
a
i
b
j
∣
i
>
j
>
0
}
,
L
2
=
{
a
i
b
j
∣
j
>
i
>
0
}
L_1 = \{ a^ib^j | i>j>0\}, L_2 = \{ a^ib^j | j>i>0 \}
L1={aibj∣i>j>0},L2={aibj∣j>i>0}
文法如下
S
→
A
C
∣
C
B
A
→
a
A
∣
a
B
→
b
B
∣
b
C
→
a
C
b
∣
a
b
S→AC|CB \\ A→aA|a \\B→bB|b \\C→aCb|ab
S→AC∣CBA→aA∣aB→bB∣bC→aCb∣ab具有嵌套结构,因此为2型文法
上下文无关文法及其语法树
语法树(推导树)定义
定义1
设
G
=
{
V
N
,
V
T
,
P
,
S
}
G=\{ V_N,V_T,P,S\}
G={VN,VT,P,S} 是给定的上下文无关文法,对于
G
G
G 的任何句型,则称满足下列条件的树为
G
G
G 的一棵语法树:
- 每个结点都有 G G G 的一个文法符号,且根结点标有初始符 S S S,非叶结点标有非终极符
- 如果结点 n n n 有标记 A A A,其直接子孙结点从左到右的次序是 n 1 , n 2 , … , n k n_1, n_2,…,n_k n1,n2,…,nk,其标记分别为 A 1 , A 2 , … , A k A_1,A_2,…,A_k A1,A2,…,Ak,那么 A → A 1 A 2 … A k A→A_1A_2…A_k A→A1A2…Ak 一定是 P P P 中的一个产生式
语法树是句型推导的直观表示。语法树的结果为:从左到右读出叶子的标记而构成的行
例
G
[
E
]
:
E
→
E
+
T
∣
T
T
→
T
∗
F
∣
F
F
→
(
E
)
∣
a
\begin{aligned} G[E]: E&→E+T|T\\ T&→T*F|F \\F&→(E)|a \end{aligned}
G[E]:ETF→E+T∣T→T∗F∣F→(E)∣a
句型推导:
E
⇒
E
+
T
⇒
T
+
T
⇒
F
+
T
⇒
a
+
T
⇒
a
+
T
∗
F
⇒
a
+
F
∗
F
⇒
a
+
a
∗
F
⇒
a
+
a
∗
a
\begin{aligned} E&\Rightarrow E+T \\&\Rightarrow T+T \\&\Rightarrow F+T \\&\Rightarrow a+T \\&\Rightarrow a+T*F\\&\Rightarrow a+F*F \\&\Rightarrow a+a*F \\&\Rightarrow a+a*a \end{aligned}
E⇒E+T⇒T+T⇒F+T⇒a+T⇒a+T∗F⇒a+F∗F⇒a+a∗F⇒a+a∗a(上述推导为 最左推导:每次只替换最左边的非终结符)
上述句型推导对应的语法树:
同一句型可能对应不同的语法树
- 对于一个句子的多种推导(若文法是无二义性的),采用各种推导过程,画出的分析树是一样的
(分析树并未描述推导过程。因此不同的推导可能对应相同的语法树)
如何画出分析树
- 自顶向下 (最左推导)
- 自底向上 (最右推导)
最左 / 右推导 左 / 右句型
- 最左推导:在推导的任何一步 α ⇒ β α\Rightarrow β α⇒β,其中 α 、 β α、β α、β 是句型,都是对 α α α 中的最左非终结符进行替换
- 最右推导:在推导的任何一步 α ⇒ β α\Rightarrow β α⇒β,其中 α 、 β α、β α、β 是句型,都是对 α α α 中的最右非终结符进行替换。最右推导被称为规范推导
- 由最左推导所得的句型称为左句型
- 由最右推导所得的句型称为右句型(规范句型)
- 左分析:由文法的开始符号 S S S 到句子 x x x 的最左推导中所用规则序列称为 x x x 的一个左分析。按左分析来建立句子的语法树,则语法树的生长次序是自顶向下的(根→叶子)。因此左分析又称自顶向下分析
- 右分析:由文法的开始符号 S S S 到句子 x x x 的最右推导中所用规则的逆序列称为 x x x 的一个右分析。按右分析来建立句子的语法树,则语法树的生长次序是自底向上的。因此右分析又称自底向上分析
例
G
[
S
]
:
G[S]:
G[S]:
- S → a A S S→aAS S→aAS
- A → S b A A→SbA A→SbA
- A → S S A→SS A→SS
- S → a S→a S→a
- A → b a A→ba A→ba
句型 a a b b a a aabbaa aabbaa 的左推导序列如下:
- 左推导:
S
⇒
a
A
S
⇒
a
S
b
A
S
⇒
a
a
b
A
S
⇒
a
a
b
b
a
S
⇒
a
a
b
b
a
a
S\Rightarrow aAS\Rightarrow aSbAS\Rightarrow aabAS\Rightarrow aabbaS\Rightarrow aabbaa
S⇒aAS⇒aSbAS⇒aabAS⇒aabbaS⇒aabbaa
对应左分析为: 12454 12454 12454
例
文法
G
:
S
→
c
A
d
,
A
→
a
b
,
A
→
a
G: S → cAd, A → ab, A → a
G:S→cAd,A→ab,A→a
识别输入串
w
=
c
a
b
d
w=cabd
w=cabd 是否为该文法的句子
自上而下的语法分析
自下而上的语法分析
子树
一棵分析树中一个特有的结点连同它的全部后裔,连接这些后裔的边以及这些结点的标记称为子树
- 短语:一棵子树的所有叶子自左至右排列起来形成一个相对于子树根的短语 (其实短语就是可规约串,每一个短语都可以向上进行归约)
- 直接短语:仅有父子两代的一棵子树,它的所有叶子自左至右排列起来所形成的符号串
- 句柄:一个句型的分析树中最左最下那棵只有父子两代的子树的所有叶子的自左至右排列 (即:最左直接短语) (无二义的文法,句柄唯一)
可以进一步给出它们对应的数学定义:
- 短语:设
G
=
(
V
N
,
V
T
,
P
,
S
)
G=(V_N, V_T, P, S)
G=(VN,VT,P,S),
α
β
δ
\alpha\beta\delta
αβδ 是文法
G
G
G 的一个句型。若有:
S
⇒
∗
α
A
δ
S\Rightarrow^* αAδ
S⇒∗αAδ 且
A
⇒
+
β
A\Rightarrow^+ β
A⇒+β,则称
β
β
β 是句型
α
β
δ
αβδ
αβδ 相对于
A
A
A 的短语 (
β
β
β 可以向上归约为
A
A
A,
A
A
A 与短语的上下文一起,依然能构成原来的句型)
- 特别地,如有 A ⇒ β A\Rightarrowβ A⇒β,称 β β β 是相对于 A → β A\rightarrowβ A→β 的直接短语 (代表可立即归约的串)
- 一个句型的最左直接短语称为该句型的句柄
句型的分析
- 自顶向下分析:
- 从文法的开始符号出发,反复使用各种产生式,寻找”匹配“于输入符号串的推导
- 在自顶向下的分析中,难点是用正确的规则去替代非终结符 (回溯:如果使用了错误的规则,确认推不出该句子,就应该退回去,再试另外的选择)
- 自底向上分析:
- 从输入符号串开始,逐步进行”归约“,直至归约到文法的开始符号
- 在自底向上的分析中,每一步都是选择一个子串,将其规约为某个非终结符。这个子串可以称为”可规约串“。难点是每一步如何确定这个”可规约串“。在一种称为”规范规约“的分析中,这种可规约串称为”句柄“
例
对表达式文法
G
[
E
]
G[E]
G[E] 和句子
a
1
+
a
2
∗
a
3
a_1+a_2*a_3
a1+a2∗a3,挑选出推导过程中产生的句型中的短语,直接短语,句柄
自顶向下分析:
有下划线的是直接短语
自底向上分析:
句柄在自底向上归约中作为可规约串
歧义文法(二义文法)
- 歧义文法 / 二义文法:如果
L
(
G
)
L(G)
L(G) 中至少存在一个句子,它有两棵以上的语法树(或有两个不同的最左(右)推导),则称文法
G
G
G 是歧义的
- 文法歧义不等价于语言歧义。只有当产生一个语言的所有文法都是歧义的,这个语言才被认为是歧义的
- 只有文法是非歧义的,语法分析才可唯一进行
- 因此,需要设计出无二义性的文法,或者在使用二义性文法时使用附加的规则来消除二义性 (例如:结合性、运算符的优先级…)
例
S
→
a
∣
S
+
S
∣
S
S
∣
S
∗
∣
(
S
)
S\rightarrow a |S + S| S S|S * | (S)
S→a∣S+S∣SS∣S∗∣(S)分析该文法是否为二义性文法
解
- 是二义性文法
例
有文法
G
1
[
E
]
:
E
→
E
+
E
∣
E
∗
E
∣
(
E
)
∣
i
d
∣
n
u
m
G_1[E]:E → E+E | E*E |(E)| id| num
G1[E]:E→E+E∣E∗E∣(E)∣id∣num,分析该文法是否为二义性文法
解
- 该文法产生语言 { 算 术 表 达 式 } \{算术表达式\} {算术表达式}。文法中的非终极符 E E E 代表算术表达式 ( e x p r expr expr),其中助记符 i d id id 代表标识符, n u m num num 代表无符号整数
- 为了判断该文法是否为二义性文法,我们找一个句子 i d + i d ∗ i d id+id*id id+id∗id,如果能够构造出两个不同的语法树,则说明该文法是二义性文法
- 如上图所示,显然该文法是二义性文法。产生歧义的原因是文法没有限定运算符的优先级和结合性:
- 由于图 (a) 语法树1中的 ∗ * ∗ 先作为句柄归约,可理解成 ∗ * ∗ 优先于 + + + 进行运算,而图 (b) 语法树2中的 + + + 先作为句柄归约,表示 + + + 优先于 ∗ * ∗ 进行运算
- 由于文法的二义性会造成不同的分析结果,所以,从而避免二义性
下面我们尝试通过 规定结合性和优先级 来构造 无二义性的算术表达式 (与上面的二义性算术表达式文法都产生相同的语言 { 算 术 表 达 式 } \{算术表达式\} {算术表达式},因此它们是等价文法):
- 暂时只涉及 + − ∗ / +-*/ +−∗/ 四种符号,它们均为左结合性
- 优先级分为两级: ∗ / */ ∗/ 高于 + − +- +−
- 因此我们用两个非终结符号
E
E
E (
e
x
p
r
expr
expr),
T
T
T (项,
t
e
r
m
term
term) 分别对应于两个优先级层次,并使用
F
F
F (因子,
f
a
c
t
o
r
factor
factor) 来生成表达式中的基本单元
- 表达式的基本单元是数位和带括号的表达式:
F
→
(
E
)
∣
i
F →(E) | i
F→(E)∣i
- f a c t o r factor factor 是不能被任何运算符分开的表达式,即在任意因子的任意一边放置一个运算符,都不会导致这个因子的任何部分分离出来,成为这个运算符的运算分量
- 现在我们考虑具有最高优先级的二目运算符
∗
/
*/
∗/。这些运算符是左结合的:
T
→
F
∣
T
∗
F
∣
T
/
F
T → F \ |\ T*F\ |\ T/F
T→F ∣ T∗F ∣ T/F (按照这样左递归定义,生成的语法树是向左下端生长的,对应左结合律)
- 一个(不是因子的)项 ( t e r m term term) 是一个可能被高优先级的运算符*和/分开,但不能被低优先级运算符分开的表达式
- 最后,由
E
E
E 生成由加减运算符分隔的
t
e
r
m
term
term 列表:
E
→
T
∣
E
+
T
∣
E
−
T
E → T\ |\ E+T\ |\ E-T
E→T ∣ E+T ∣ E−T
- 一个(不是因子也不是项的)表达式可能被任何一个运算符分开
- 表达式的基本单元是数位和带括号的表达式:
F
→
(
E
)
∣
i
F →(E) | i
F→(E)∣i
- 最终得到的文法为
G
2
[
E
]
G_2[E]
G2[E]:
E → T ∣ E + T ∣ E − T T → F ∣ T ∗ F ∣ T / F F → ( E ) ∣ i E → T\ |\ E+T\ |\ E-T\\ T → F \ |\ T*F\ |\ T/F\\ F →(E) | i E→T ∣ E+T ∣ E−TT→F ∣ T∗F ∣ T/FF→(E)∣i - 我们可以把上面按照优先等级设计文法的思想推广到具有任意
n
n
n 层优先级的情况。我们需要
n
+
1
n + 1
n+1 个非终结符号
- 首先, f a c t o r factor factor 不可被分开。通常,这个非终结符号的产生式体只能是单个运算分量或括号括起来的表达式
- 然后,对于每个优先级都有一个非终结符,表示能被该优先级或更高优先级的运算符分开的表达式。通常,这个非终结符的产生式有一些产生式体表示了该优先级的运算符的应用;另有一个产生式体只包含了代表更高一层优先级的非终结符号
- 例如,在上面的算术表达式文法中增加单目运算符
+
,
−
+,-
+,−:
e x p r → e x p r + t e r m ∣ e x p r − t e r m ∣ t e r m t e r m → t e r m ∗ u n a r y ∣ t e r m / u n a r y ∣ u n a r y u n a r y → + f a c t o r ∣ − f a c t o r ∣ f a c t o r f a c t o r → i d ∣ n u m ∣ ( e x p r ) \begin{aligned}expr&→ expr + term | expr - term | term\\ term&→ term * unary | term / unary | unary\\ unary &→ + factor | - factor | factor\\ factor&→ id | num | (expr)\end{aligned} exprtermunaryfactor→expr+term∣expr−term∣term→term∗unary∣term/unary∣unary→+factor∣−factor∣factor→id∣num∣(expr)
例
程序设计语言中的嵌套 IF 语句都要求 ELSE 与最近的 IF 配对,也是因为 IF 语句的文法存在二义性
例:IF语句文法如下:
<
语
句
>
→
I
F
<
布
尔
表
达
式
>
T
H
E
N
<
语
句
>
∣
I
F
<
布
尔
表
达
式
>
T
H
E
N
<
语
句
>
E
L
S
E
<
语
句
>
∣
<
其
它
>
\begin{aligned}<语句> &→ IF<布尔表达式>THEN<语句>\\&|IF<布尔表达式>THEN<语句>ELSE<语句>\\&|<其它>\end{aligned}
<语句>→IF<布尔表达式>THEN<语句>∣IF<布尔表达式>THEN<语句>ELSE<语句>∣<其它>说明该文法是二义性文法
解
假设有一个IF语句嵌套的句型为:
I
F
<
布
尔
表
达
式
>
T
H
E
N
I
F
<
布
尔
表
达
式
>
T
H
E
N
<
语
句
>
E
L
S
E
<
语
句
>
IF<布尔表达式>THEN\ IF<布尔表达式>THEN<语句>ELSE <语句>
IF<布尔表达式>THEN IF<布尔表达式>THEN<语句>ELSE<语句>
根据文法可构造两棵语法树如图 (a)和图(b)所示:
- 由于这两棵语法树不同,所以该文法是二义性文法
- 图 (a) IF 语句的语法树意味着 ELSE 和第2个 THEN 配对(就近配对
- 图 (b) IF 语句的语法树表示 ELSE 和第1个 THEN 配对
对实用文法的限制与扩充
简化文法
从实用角度来说,编译原理中所讨论的文法是被简化的文法,即:
- 文法中不存在 P → P P→P P→P 的规则( P ∈ V N P∈V_N P∈VN),这是一个有害规则,会产生二义性
- 每个非终极符都必须是可达和可终止的
设 S S S 是文法的开始符号,对任意 P ∈ V N P∈V_N P∈VN,若存在 S ⇒ ∗ α P β S \Rightarrow^* αPβ S⇒∗αPβ,则称 P P P 是可达的;同时 P ⇒ ∗ γ ( γ ∈ V T ∗ ) P \Rightarrow^* γ(γ∈V_T^*) P⇒∗γ(γ∈VT∗),称 P P P 是可终止的,又称为活符号
例
化简文法
①
S
→
a
A
a
②
A
→
S
b
③
A
→
b
B
B
④
B
→
a
C
⑤
B
→
a
b
b
⑥
C
→
a
C
A
\begin{aligned}&① S→aAa\\ &② A→Sb\\ &③ A→bBB\\ &④ B→aC\\ &⑤ B→abb\\ &⑥ C→aCA\end{aligned}
①S→aAa②A→Sb③A→bBB④B→aC⑤B→abb⑥C→aCA
解
- 求活符号(Active)
W [ 1 ] = { B } ( 先 从 能 直 接 用 终 结 符 表 示 的 非 终 结 符 开 始 ) W [ 2 ] = { B , A } ( 加 入 能 直 接 用 终 结 符 以 及 B 表 示 的 非 终 结 符 ) W [ 3 ] = { A , B , S } W [ 4 ] = W [ 3 ] ( 没 有 增 加 新 的 活 符 号 。 查 找 结 束 ) \begin{aligned}&W [1]=\{B\}\ \ \ \ \ (先从能直接用终结符表示的非终结符开始)\\ &W [2]=\{B, A\}\ \ \ \ \ (加入能直接用终结符以及B表示的非终结符) \\ &W [3]=\{A, B, S\} \\&W [4]=W [3]\ \ \ \ \ (没有增加新的活符号。查找结束)\end{aligned} W[1]={B} (先从能直接用终结符表示的非终结符开始)W[2]={B,A} (加入能直接用终结符以及B表示的非终结符)W[3]={A,B,S}W[4]=W[3] (没有增加新的活符号。查找结束) C C C 不是活符号,因此去掉④和⑥两个含有 C C C 的产生式。余①②③⑤
待进一步化简文法:
①
S
→
a
A
a
②
A
→
S
b
③
A
→
b
B
B
⑤
B
→
a
b
b
\begin{aligned}&① S→aAa\\ &② A→Sb\\ &③ A→bBB\\ &⑤ B→abb\end{aligned}
①S→aAa②A→Sb③A→bBB⑤B→abb
2. 求可达符(reachable)
W
[
1
]
=
{
S
}
(
从
S
开
始
)
W
[
2
]
=
{
S
,
a
,
A
}
W
[
3
]
=
{
S
,
a
,
A
,
B
,
b
}
W
[
3
]
=
W
[
4
]
\begin{aligned}&W [1]=\{S\}\ \ \ \ \ \ \ \ (从S开始)\\ &W [2]=\{S, a, A\}\\ &W [3]=\{S, a, A, B, b\} \\ &W [3]=W [4]\end{aligned}
W[1]={S} (从S开始)W[2]={S,a,A}W[3]={S,a,A,B,b}W[3]=W[4]简化后的文法:
S
→
a
A
a
,
A
→
S
b
,
A
→
b
B
B
,
B
→
a
b
b
S→aAa,A→Sb,A→bBB, B→abb
S→aAa,A→Sb,A→bBB,B→abb
不能先求可达符号,再求活符号:
例如文法 S → a S b , S → b A B , S → a , B → d , A → a A c S→aSb,S→bAB,S→a,B→d,A→aAc S→aSb,S→bAB,S→a,B→d,A→aAc。如果先求可达符号,再求活符号,会得到 S → a S b , S → a , B → d S→aSb,S→a,B→d S→aSb,S→a,B→d,而这里 B B B 明显是不可达的。究其原因是因为先求可达符号无法消去那些非活符号,进而无法消去一些规则,导致误判可达性
空规则与文法扩充
- 上下文无关文法中某些规则可具有形式 A → ε A→ε A→ε,称这种规则为 ε ε ε 规则(空规则)
引进空规则,给文法的构造带来很大方便,但它使得对文法所定义语言的分析变得较为复杂
例
描述语言
{
a
n
b
a
m
∣
n
,
m
≥
0
}
\{a^nba^m | n, m≥0\}
{anbam∣n,m≥0} 的文法
解
① 不带
ε
ε
ε 规则的文法
G
[
S
]
:
S
→
a
S
∣
b
A
∣
b
A
→
a
A
∣
a
G[S]: S→aS | bA | b\\ A→aA | a
G[S]:S→aS∣bA∣bA→aA∣a
② 引进空规则
G
[
S
]
:
S
→
A
b
A
A
→
a
A
∣
ε
G[S]: S→AbA\\ A→aA |ε
G[S]:S→AbAA→aA∣ε
或
G
’
[
S
]
:
S
→
a
S
∣
b
A
A
→
a
A
∣
ε
G’[S]: S→aS | bA\\ A→aA | ε
G’[S]:S→aS∣bAA→aA∣ε
- 对给定的带 ε ε ε 规则的文法,在不生成空串的情况下,可构造出一个不带空规则的等价文法
- 不带 ε ε ε 规则的文法不能生成空串
- 对任意文法中的任意非终极符 A A A,形如 A → ε A→ε A→ε 的产生式不会改变文法的语言类型,因此在需要时,可以出现形如 A → ε A→ε A→ε 的产生式
- 原来的1型~3型文法,若想生成空串,可在文法规则
P
P
P 中增加新的开始符号
S
′
S^′
S′ 及新的产生式
S
′
→
S
S^′→S
S′→S,
S
′
→
ε
S^′→ε
S′→ε。而不影响文法的分类
(1型文法要求规则 α → β \alpha\rightarrow\beta α→β中, ∣ α ∣ ≤ ∣ β ∣ |\alpha|\leq|\beta| ∣α∣≤∣β∣,因此右边不可能是 ε ε ε.因此,需要单独引入 ε ε ε)
- 定理1
设 G = ( V , T , P , S ) G=(V, T, P, S) G=(V,T,P,S) 为一文法,则存在与 G G G 同类型的文法 G ’ = ( V ’ , T , P ’ , S ’ ) G’=(V’, T, P’, S’) G’=(V’,T,P’,S’) ,使得 L ( G ) = L ( G ’ ) L(G)=L(G’) L(G)=L(G’),但 G ’ G’ G’ 的开始符号 S ’ S’ S’ 不出现在任何产生式的右部 - 定义1
设 G = ( V , T , P , S ) G=(V, T, P, S) G=(V,T,P,S) 为一文法,如果 S S S 不出现在 G G G 的任何产生式的右部,则
(1)如果 G G G 是 CSG,则仍然称 G = ( V , T , P ∪ S → ε , S ) G=(V, T, P∪ {S→ε}, S) G=(V,T,P∪S→ε,S)为 CSG; G G G 产生的语言仍然称为 CSL
(2)如果 G G G 是 CFG,则仍然称 G = ( V , T , P ∪ S → ε , S ) G=(V, T, P∪ {S→ε}, S) G=(V,T,P∪S→ε,S) 为 CFG; G G G 产生的语言仍然称为 CFL
(3)如果 G G G 是 RG,则仍然称 G = ( V , T , P ∪ S → ε , S ) G=(V, T, P∪ {S→ε}, S) G=(V,T,P∪S→ε,S) 为 RG; G G G 产生的语言仍然称为 RL - 定理2
(1)如果 L L L 是 CSL,则 L ∪ { ε } L∪\{ε\} L∪{ε} 仍然是CSL
(2)如果 L L L 是 CFL,则 L ∪ { ε } L∪\{ε\} L∪{ε} 仍然是CFL
(3)如果 L L L 是 RL,则 L ∪ { ε } L∪\{ε\} L∪{ε} 仍然是RL - 定理3
(1)如果 L L L 是 CSL,则 L − { ε } L-\{ε\} L−{ε} 仍然是CSL
(2)如果 L L L 是 CFL,则 L − { ε } L-\{ε\} L−{ε} 仍然是CFL
(3)如果 L L L 是 RL,则 L − { ε } L-\{ε\} L−{ε} 仍然是RL