编译原理-文法

557 阅读4分钟

编译原理-文法

1.文法

1.1 什么是文法

一个程序设计语言是一个记号系统如同自然语言一样,它的完整定义应包括语法和语义两个方面。所谓一个语言的语法是指一组规则,用它可以形成和产生一个合适的程序目前广泛使用的手段是上下文无关文法,即用上下文无关文法作为程序设计语言语法的描述工具。

上下文无关是指: 一句话的含义与其前后的内容没有或者几乎没有关系,只由自己决定,把它剪切到其他任何位置,也还是原有的意思。

例如:

a=0;a = 0;

这是一个赋值语句,无论此语句的前后是什么代码,此语句所代表的操作是确定的。即:

给变量a赋予值0

换句话说,CPU遇到什么语句就执行什么语句,不用管其他的。

1.2 编程语言为什么不用人类的语言(自然语言),而是用上下文无关的文法呢?

  1. 便于设计编译器。试想一下,如果可以用自然语言写代码,那不就是实现了人工智能了吗?客观上技术目前无法实现。
  2. 便于代码开发维护。如果开发出来的代码像高考的语文阅读理解一样,每个人都有不同的理解,那么,到底哪个才是作者真正想要表达的?如果人类都确定不了含义,那计算机同样也确定不了,最终结果就是错误执行或无法执行。
  3. 汇编语言/机器语言是上下文无关的。CPU执行指令时,读到哪条执行哪条。如果CPU需要考虑上下文,来决定一个语句到底要做什么,那么CPU执行一条语句会比现在慢千倍万倍。考虑上下文的事情,完全可以用户在编程的时候用算法实现。既然机器语言是上下文无关的,那高级语言也基本上是上下文无关的,可能有某些个别语法为了方便使用,设计成了上下文相关的,比如脚本语言的弱类型。在便于使用的同时,增加了解析器的复杂度。

综上:编程语言基本上都采用上下文无关的原则设计语法。

1.3 EBNF 扩展的巴科斯范式

用来描述计算机语言语法的符号集。现在,几乎每一位新编程语言书籍的作者都使用巴科斯范式来定义编程语言的语法规则。

扩展巴科斯-瑙尔范式(EBNF)是表达作为描述计算机编程语言和形式语言的正规方式的上下文无关文法的元语法符号表示法。它是基本巴科斯范式(BNF)元语法符号表示法的一种扩展。

如“我是大学生”是汉语的一个句子。汉语句子可以由主语后随谓语而成,构成谓语的是动词和直接宾语,采用第1章使用过的 EBNF 来表示这种句子的构成规则:

<句子>::=<主语><谓语><主语>::=<代词><名词><代词>::=<名词>::=王明大学生工人英语<谓语>::=<动词><直接宾语><动词>::=学习<直接宾语>::=<代词><名词>\begin{aligned} &<句子>::=<主语><谓语> \\ &<主语>::=<代词>|<名词> \\ &<代词>::=我|你|他 \\ &<名词>::=王明|大学生|工人|英语 \\ &<谓语>::=<动词><直接宾语> \\ &<动词>::=是|学习 \\ &<直接宾语>::=<代词>|<名词> \\ \end{aligned}

将这些规则看成是一种元语言,用它描述汉语。这里仅仅涉及汉语句子的结构描述。这样的语言描述称为文法。

<句子><主语><谓语><代词><谓语><谓语><动词><直接宾语>我是<直接宾语>我是<名词>我是大学生\begin{aligned} <句子>&\Rarr<主语><谓语>\\ &\Rarr<代词><谓语>\\ &\Rarr我<谓语>\\ &\Rarr我<动词><直接宾语>\\ &\Rarr我是<直接宾语>\\ &\Rarr我是<名词>\\ &\Rarr我是大学生 \end{aligned}

1.4 上下文无关文法的形式定义

上下文无关文法G是一个四元组G={VT,VN,S,P}G=\{V_T, V_N, S, P\},其中:

  • VTV_T: 终结符(Terminal)集合(非空),不可再分的原子单位,如He, book等
  • VNV_N: 非终结符(Terminal)集合(非空),且VTVN=V_T \cap V_N= \varnothing(表明不允许一个符号既是终结符又是非终结符),可再分单元,如<句子>, <谓语>等。
  • SS: 文法的开始符号, SVNS \in V_N
  • PP: 产生式集合(有限), 每个产生式形式为Pα,PVN,α(VTVN)P \rarr α, P \in V_N, α \in (V_T \cup V_N)*

1.5 练习题

例题1:证明:(ii+i)是文法G(E):EiE+EEE(E)的一个句子。例题1: 证明: (i * i + i)是文法G(E): E → i | E+E | E*E | (E)的一个句子。

证:

E(E)(E+E)(EE+E)(iE+E)(ii+E)(ii+i)证毕。\begin{aligned} E &\Rarr (E) \\ &\Rarr (E+E) \\ &\Rarr (E*E+E) \\ &\Rarr (i*E+E) \\ &\Rarr (i*i+E) \\ &\Rarr (i*i+i) \\ \end{aligned} \\ 证毕。\\
也可以推导出E,(E),(EE+E),..,(ii+i)都是文法的合法句型。也可以推导出E, (E), (E*E+E),..,(i * i + i)都是文法的合法句型。
例题2:设文法G(A):AcAb,G(A)产生的语言是什么?例题2: 设文法 G(A): A → c | Ab, G(A)产生的语言是什么?
:c开头,后继若干个b,L(G)=c,cb,cbb,...答: 以c开头, 后继若干个b, L(G) = {c, cb, cbb, ...}
例题3:设文法G(S):SAB,AaAa,BbBb,G(S)产生的语言是什么?例题3: 设文法G(S): S→AB, A→aA|a,B→bB|b, G(S)产生的语言是什么?
:L(G)=anbmm>0,n>0答: L(G)={a^nb^m | m>0,n>0}
例题4:请给出产生语言为anbnn>1的文法例题4: 请给出产生语言为{a^nb^n|n>1}的文法
:G(S):Sab,SaSb答: G(S): S→ab,S→aSb
例题5:请给出产生语言为ambn1nm2n的文法例题5: 请给出产生语言为{a^mb^n|1≤n≤m≤2n}的文法
:G(S):Sabaab,SaSbaaSb答: G(S): S→ab|aab,S→aSb|aaSb

1.6 语言的二义性

例如: 英语是个二义性的语言

"John saw Marry in the boat." 介词短语in the boat 既可修饰saw这个谓语动词, 也可修饰Marry, 因此英语是一种二义性的语言。

大多数语言都是二义性的语言, 这也是自然语言处理之所以困难的根本原因之一

E: Expression , T: Term , F: Factor

二义性问题是不可判定问题, 即不存在一个算法能在有限步骤内, 确切地判定一个文法是否是二义的。(证明略)

1.7 上下文有关文法

例题:L=anbncnn1不能由上下文无关文法产生,但可由上下文有关文法产生例题: L={a^nb^nc^n|n≥1}不能由上下文无关文法产生, 但可由上下文有关文法产生
G(S):SaSBCaBCCBBCaBabbBbbbCbccCcc\begin{aligned} G(S): & S→aSBC|aBC \\ & CB→BC \\ & aB→ab \\ & bB→bb \\ & bC→bc \\ & cC→cc \\ \end{aligned}
SaSBCaaSBCBCaaaBCBCBCaaaBBCCBCaaaBBCBCCaaaBBBCCCaaabBBCCCaaabbBCCCaaabbbCCCaaabbbcCCaaabbbccCaaabbbccc\begin{aligned} S & \Rarr aSBC \\ & \Rarr aaSBCBC \\ & \Rarr aaaBCBCBC \\ & \Rarr aaaBBCCBC \\ & \Rarr aaaBBCBCC \\ & \Rarr aaaBBBCCC \\ & \Rarr aaabBBCCC \\ & \Rarr aaabbBCCC \\ & \Rarr aaabbbCCC \\ & \Rarr aaabbbcCC \\ & \Rarr aaabbbccC \\ & \Rarr aaabbbccc \end{aligned}

程序设计语言不是上下文无关语言,甚至不是上下文有关语言,对于现今程序设计语言,在编译程序中,仍然采用上下文无关文法来描述其语言结构。虽然上下文无关文法无法完全实现程序设计语言的所有约束,但在实际工作中,我们仍然用它来实现大部分语言的规定, 超出了它能力范围的,就用其它方法来实现, 这体现了计算思维中的权衡思想。

理论研究重在探寻问题求解的方法,对于理论成果的研究运用又需要在能力和运用中做出权衡。