概述
1956年,语言学家Chomsky提出了形式语言理论,极大的促进了程序语言的发展,也促进了编译理论的发展。编译原理的主要内容就是应用形式语言理论,它贯穿于词法分析和语法分析两个阶段。
为了更系统的理解编译过程中的分析阶段,我们需要掌握一定的语言理论,而描述一个语言的语法与结构的规则称为文法。
形式描述
在深入理解编译是如何应用语言理论之前,需要先了解一些符号更方便的来描述,下面对一些符号及其定义做一些简单介绍。
- 字母表,字符:字母表用 ∑ \sum ∑来表示,它是字符的非空有穷集合,字符是 ∑ \sum ∑中的元素。如 ∑ = { a , p , l , e } \sum=\{a,p,l,e\} ∑={a,p,l,e}。
- 字符串:字符串是由 ∑ \sum ∑组成的有穷序列。如"h"、“hi”、"hello"都是 ∑ \sum ∑上的字符串。
- 字符串的长度:一般形容串长度用绝对符号来表示。如 ∣ h e l l o ∣ = 5 |hello|=5 ∣hello∣=5。
- 空串:由零个字符组成的序列,空串用 ε \varepsilon ε来表示, ∣ ε ∣ = 0 |\varepsilon|=0 ∣ε∣=0
- 连接:字符串S和T的连接指将字符串T接在S后,又表示为 S ⋅ T S \cdot T S⋅T或 S T ST ST。另对于 ∑ \sum ∑上的任何字符串S都满足 S ⋅ ε = ε ⋅ S = S S \cdot \varepsilon = \varepsilon \cdot S = S S⋅ε=ε⋅S=S。
- ∑ ∗ \sum^* ∑∗:指包括 ε \varepsilon ε在内的 ∑ \sum ∑上所有字符串的集合。
- 字符串的幂:即把字符串 α \alpha α自身连接n次的字符串,称为 α \alpha α的n次幂,记为 σ n \sigma ^n σn,一些特殊规则与集合运算相同。
- 字符串集合运算:如设A、B代表
∑
\sum
∑上的两个字符串集合。
- 或(合并): A ⋃ B = { α ∣ α ∈ A 或 α ∈ B } A \bigcup B = \{ \alpha | \alpha \in A 或 \alpha \in B \} A⋃B={α∣α∈A或α∈B}。
- 积(连接): A B = { α β ∣ α ∈ A 且 β ∈ B } AB = \{ \alpha \beta | \alpha \in A 且 \beta\in B \} AB={αβ∣α∈A且β∈B},且也可以用逗号代替。
- 幂: A n = A A n − 1 = A n − 1 A ( n > 0 ) A^n = A A^{n-1} = A^{n-1}A (n>0) An=AAn−1=An−1A(n>0),并规定 A 0 = ε A^0 = \varepsilon A0=ε。
- 正则闭包+: A + = A 1 ⋃ A 2 ⋃ A 3 ⋃ ⋯ ⋃ A n ⋃ … A^+ = A^1 \bigcup A^2 \bigcup A^3 \bigcup \dots \bigcup A^n \bigcup \dots A+=A1⋃A2⋃A3⋃⋯⋃An⋃…
- 闭包*: A ∗ = A 0 ⋃ A + A^* = A^0 \bigcup A^+ A∗=A0⋃A+。显然又有: ∑ ∗ = ∑ 0 ⋃ ∑ 1 ⋃ ∑ 2 ⋃ ⋯ ⋃ ∑ n ⋃ … \sum^* = \sum^0 \bigcup \sum^1 \bigcup \sum^2 \bigcup \dots \bigcup \sum^n \bigcup \dots ∑∗=∑0⋃∑1⋃∑2⋃⋯⋃∑n⋃…
文法与语言的形式定义
Chomsky将文法G定义为四元组: G = ( V N , V T , P , S ) G = (V_N, V_T, P, S) G=(VN,VT,P,S)。
其中:
- V N V_N VN 是非空有限集,其中每个元素都为非终结符,因此也叫做非终结符集。
-
V
T
V_T
VT 也是非空有限集,但其中每个元素均为终结符,因此也叫做终结符集。
- 另外, V N ⋂ V T = ∅ V_N \bigcap V_T = \empty VN⋂VT=∅,即两者之间无公共元素。
- P 是产生式的有限集,产生式的形式是写作“
α
→
b
e
t
a
\alpha \to beta
α→beta”的规则,其中
α
\alpha
α称为产生式左部,
β
\beta
β称为产生式的右部。
- 其中, α ∈ V + \alpha \in V^+ α∈V+,且 α \alpha α中至少含有一个非终结符。且, β ∈ V ∗ \beta \in V^* β∈V∗。
- 若干个产生式如: α → β 1 , α → β 2 , … , α → β n \alpha \to \beta_1, \alpha \to \beta_2, \dots, \alpha \to \beta_n α→β1,α→β2,…,α→βn的左部相同情形时,可简写为: α → β 1 ∣ β 2 ∣ … ∣ β n \alpha \to \beta_1 | \beta_2 | \dots | \beta_n α→β1∣β2∣…∣βn,称作 β i ( 1 ≤ i ≤ n ) \beta_i (1 \leq i \leq n) βi(1≤i≤n)为 α \alpha α的一个候选式。
- S是文法的开始符号,至少要在一条产生式的左部中出现, S ∈ V N S \in V_N S∈VN。
文法的分类
文法分为0型、1型、2型、3型共4种类型,它们之间的差别主要是产生式的约束不同。其中,0型文法又是基础,其余文法均基于0型之上。如2型文法的约束必须同时满足0型与2型的约束。
-
0型文法
G的任一产生式 α → β \alpha \to \beta α→β ,均有 α ∈ ( V N ⋃ V T ) + \alpha \in (V_N \bigcup V_T)^+ α∈(VN⋃VT)+, α \alpha α至少含有一个非终结符,且 β ∈ ( V N ⋃ V T ) ∗ \beta \in (V_N \bigcup V_T)^* β∈(VN⋃VT)∗。
-
1型文法
G的任一产生式 α → β ( S → ε 除 外 ) \alpha \to \beta (S \to \varepsilon除外) α→β(S→ε除外) ,均有 ∣ α ∣ ≤ ∣ β ∣ |\alpha| \leq |\beta| ∣α∣≤∣β∣。
-
2型文法
G的任一产生式形式 A → β A \to \beta A→β ,均有 A ∈ V N , β ∈ ( V N ⋃ V T ) ∗ A \in V_N, \beta \in (V_N \bigcup V_T)^* A∈VN,β∈(VN⋃VT)∗。
-
3型文法
G的任一产生式形式 A → a A \to a A→a 或 A → a B ( 或 A → B a ) A \to aB(或A\to Ba) A→aB(或A→Ba),均有 A , B ∈ V N A, B \in V_N A,B∈VN,另有 a ∈ V T a \in V_T a∈VT。
从分类定义中可知,0型文法具有最少的限制,逐级递增。
其中,0型文法又称为短语文法或无限制文法,它几乎对产生式没有任何限制。任何的0型语言都是递归可枚举的;反之任何递归可枚举的文法也必然是0型语言。
1型文法称为长度增加文法或上下文有关文法(CSG, Context-Sensitive Grammar),这种文法意味着终结符的替换与上下文关联,并且不允许替换为 ε \varepsilon ε。如:若 α A B → α γ β \alpha AB \to \alpha \gamma \beta αAB→αγβ是1型文法的产生式,且 α , β \alpha, \beta α,β不全为空。则非终结符A只有在左边是 α \alpha α,右边是 β \beta β的上下文中才能替换成 γ \gamma γ。
2型文法称为上下文无关文法(CFG, Context-Free Grammar),其非终结符的替换无需考虑上下文。
3型文法称为正规文法(RG, Regular Grammar)或线性文法。
另外,识别0型语言的自动机称作图灵机;识别1型语言的自动机称作线性界限自动机;识别2型语言的自动机称作下推自动机;识别3型语言的自动机称作有限状态自动机。
程序语言中的语法和词法规则主要是2、3型文法。另外,还对产生式增加两点限制:
- 不存在 P → P P \to P P→P的产生式,因为除了增加二义性外毫无意义。
- 产生式中出现的非终结符 P P P必须是可达的,并且能推出终结符串,即存在并满足( ⇒ \Rightarrow ⇒的含义见推导与直接推导): S ⇒ ∗ α P β , P ⇒ + γ , γ ∈ V T ∗ , ( α , β ∈ V ∗ ) S \Rightarrow^* \alpha P \beta, P \Rightarrow^+ \gamma, \gamma \in V^*_T, (\alpha , \beta \in V^*) S⇒∗αPβ,P⇒+γ,γ∈VT∗,(α,β∈V∗)
句子和语言的产生
上面介绍了文法的基本概况,文法本质上是用来指导语法和结构的,因此接下来就要看看如何使用文法、产生式等内容产生符合文法的语言及该过程的一些表示方法。
推导与直接推导
推导即从文法的开始符出发,反复使用产生式,将产生式左部的非终结符替换为右部的文法符号序列(展开产生式用 ⇒ \Rightarrow ⇒表示),直到最终产生一个终结符的序列为止。
如有产生式 α → β ∈ P , γ , δ ∈ V ∗ \alpha \to \beta \in P, \gamma, \delta \in V^* α→β∈P,γ,δ∈V∗,则 γ α δ ⇒ γ β δ \gamma \alpha \delta \Rightarrow \gamma \beta \delta γαδ⇒γβδ称为文法中的直接推导,并称 γ α δ \gamma \alpha \delta γαδ可直接推导出 γ β δ \gamma \beta \delta γβδ。
对于P中的每个产生式 α → β \alpha \to \beta α→β显然都有 α ⇒ β \alpha \Rightarrow \beta α⇒β。
若文法中存在一个直接推导序列,即 α 0 ⇒ α 1 ⇒ α 2 ⇒ … α n ( n > 0 ) \alpha_0 \Rightarrow \alpha_1 \Rightarrow \alpha_2 \Rightarrow \dots \alpha_n (n > 0) α0⇒α1⇒α2⇒…αn(n>0)。则称 α 0 \alpha_0 α0可推导出 α n \alpha_n αn, α n \alpha_n αn是 α 0 \alpha_0 α0的一个推导,记为 α 0 ⇒ + α n \alpha_0 \Rightarrow^+ \alpha_n α0⇒+αn。另外,用 α 0 ⇒ ∗ α n \alpha_0 \Rightarrow^* \alpha_n α0⇒∗αn表示 α 0 = α n \alpha_0 = \alpha_n α0=αn。
归约与直接规约
归约和直接归约即推导与直接推导的逆过程。
若文法中有一个直接推导 α ⇒ β \alpha \Rightarrow \beta α⇒β,则称 β \beta β可直接归约成 α \alpha α,或称 α \alpha α是 β \beta β的直接归约。
若文法中有一个推导 γ ⇒ ∗ δ \gamma \Rightarrow^* \delta γ⇒∗δ,则称 δ \delta δ可归约成 γ \gamma γ,或称 γ \gamma γ是 δ \delta δ的归约。
句型、句子
从开始符能推导出的符号串称为文法的句型,即 α \alpha α是文法的一个句型,当且仅当存在推导 S ⇒ ∗ α , α ∈ V ∗ S \Rightarrow^* \alpha, \alpha \in V^* S⇒∗α,α∈V∗。
若X为文法的一个句型,且 X ∈ V T ∗ X \in V^*_T X∈VT∗,则称X是文法的一个句子,即仅含终结符的句型是一个句子。
语言
从文法的开始符出发,能推导出的所有句子称为文法G产生的语言,记为 L ( G ) L(G) L(G)。
若有文法 G 1 G_1 G1与文法 G 2 G_2 G2产生的语言相同( L ( G 1 ) = L ( G 2 ) L(G_1) = L(G_2) L(G1)=L(G2)),则称这两个文法等价。
文法应用的一些例子
-
设 G 1 = ( { S } , { a , b } , P , S ) G_1 = ( \{S\}, \{ a, b\}, P, S ) G1=({S},{a,b},P,S)
其中,P为:
- ① S → a S S \to aS S→aS
- ② S → a S \to a S→a
- ③ S → b S \to b S→b
这是一种3型文法,其所能产生的语言分析如下:
若选①号产生式,发现其是递归的,所以需要使用②、③产生式来作为出口终止递归,因此其可以产生的语言是 { a i ( a ∣ b ) ∣ i ≥ 1 } \{ a^i(a|b) | i \geq 1 \} {ai(a∣b)∣i≥1}(其中第一个|表示"或",后一个表示分离符,是i需满足的条件,下同);而仅选②、③产生式可以产生的语言是 { a ∣ b } \{ a|b \} {a∣b}。
因此 G 1 G_1 G1可以产生的语言: L ( G 1 ) = { a i ( a ∣ b ) ∣ i ≥ 1 } ⋃ { a ∣ b } = { a i ( a ∣ b ) ∣ i ≥ 0 } L(G_1) = \{ a^i (a|b) \space | i \geq 1 \} \bigcup \{a|b \} = \{a^i (a|b) \space | i \geq 0 \} L(G1)={ai(a∣b) ∣i≥1}⋃{a∣b}={ai(a∣b) ∣i≥0}
-
设 G 2 = ( { S } , { a , b } , P , S ) G_2 = (\{S\}, \{a, b\}, P, S ) G2=({S},{a,b},P,S)
其中,P为:
- ① S → a S b S \to aSb S→aSb
- ② S → a b S \to ab S→ab
这是一种2型文法,其所能产生的语言分析如下:
若选①号产生式,发现其是递归的,需要用①号产生式作为出口。因此,①产生的语言为 { a n b n ∣ n ≥ 2 } \{ a^n b^n | n \geq 2 \} {anbn∣n≥2};若用②号产生式,则能产生的语言为 { a b } \{ab\} {ab}。
不妨试试推导看看,假定我们用①号产生式递归两次后使用②号产生式,则推导展开如下 S ⇒ ① a S b ⇒ ① a a S b b ⇒ ② a a a b b b S \Rightarrow ①aSb \Rightarrow ①aaSbb \Rightarrow ②aaabbb S⇒①aSb⇒①aaSbb⇒②aaabbb。可以发现,产生的语言中a的个数与b的完全相同。其中的非终结符具有自嵌套特性,所以又称其实自嵌套的上下文无关文法。
所以 G 2 G_2 G2可以产生的语言为: L ( G 2 ) = { a n b n ∣ n ≥ 1 } L(G_2) = \{ a^nb^n | n \geq 1 \} L(G2)={anbn∣n≥1}。