距离上次更新已经 1534 天了,文章内容可能已经过时。

课程主页:

https://www.icourse163.org/course/NUDT-1003101005?tid=1460976445

这次回顾第3讲:高级程序设计语言的语法描述。

第3讲 高级程序设计语言的语法描述

文法

  • 文法:描述语言的语法结构的形式规则

  • 假设我们有如下文法:

  • ```
    <句子> -> <主语><谓语><间接宾语><直接宾语>
    <主语> -> <代词>
    <谓语> -> <动词>
    <间接宾语> -> <代词>
    <直接宾语> -> <冠词> <名词>
    <代词> -> He
    <代词> -> me
    <名词> -> book
    <冠词> -> a
    <动词> -> gave

    Code
    
    - 考虑句子:He gave me a book.
    
    - ```
        <句子>
      =><主语><谓语><间接宾语><直接宾语>
      =><代词><谓语><间接宾语><直接宾语>
      =>He <谓语><间接宾语><直接宾语>
      =>He <动词> <间接宾语><直接宾语>
      =>He gave <间接宾语><直接宾语>
      =>He gave <代词> <直接宾语>
      =>He gave me <直接宾语>
      =>He gave me <冠词><名词>
      =>He gave me a <名词>
      =>He gave me a book

语法描述的几个基本概念

  • 字母表:一个有穷字符集,记为Σ

  • 字母表中每个元素称为字符

  • Σ上的字(也叫字符串) 是指由Σ中的字符所构成的一个有穷序列

  • 不包含任何字符的序列称为空字,记为ε

  • Σ表示Σ上的所有字的全体,包含空字ε

    • 例如: 设 Σ={a,b},则
Σ={ε,a,b,aa,ab,ba,bb,aaa,}
  • Σ的子集UV的连接(积)定义为

    UV{αβ|αU&βV}
  • 示例:U={a,aa},V={b,bb},UV={ab,abb,aab,aabb}

  • V自身的n次积记为

    Vn=VVn
  • V0={ε}

  • VV的闭包:V=V0V1V2

  • V+V的正规闭包:V+=VV

    • 例子:

      U={a,aa}
    • 那么:

      U={ε,a,aa,aaa,aaaa,}U+={a,aa,aaa,aaaa,}

上下文无关文法

  • 上下文无关文法G是一个四元组

    G=(VT,VN,S,P)
  • 其中

    • VT:终结符(Terminal)集合(非空)
    • VN:非终结符(Noterminal)集合(非空),且VTVN=
    • S:文法的开始符号,SVN
    • P:产生式集合(有限),每个产生式形式为
      • PαPVNα(VTVN)
    • 开始符S至少必须在某个产生式的左部出现一次
  • 上下文无关文法还有一种描述形式,称为巴科斯范式(BNF)

    • “ →”用“::=”表示
例子

定义只含+的算术表达式的文法

G=<{i,+,,(,)}{E},E,P>

其中,P的定义如下:

  • Ei
  • EE+E
  • EEE
  • E(E)
一些约定
  • 约定

    Pα1Pα2 可缩写为 PαnPα1|α2|αn
  • 其中,“|”读成“或”,称αiP的一个候选式

    • 表示一个文法时,通常只给出开始符号和产生式
  • 之前的文法可以简写为

    G(E)Ei|E+E|EE|(E)

文法生成语言

推导
  • 定义:称αAβ直接推出αγβ,即

    αAβαγβ

    仅当Aγ是一个产生式,且α,β(VTVN)

  • 如果α1α2αn,则我们称这个序列是从α1αn的一个推导。若存在一个从α1αn的推导,则称α1可以推导出αn

  • 对文法G(E)Ei|E+E|EE|(E)

    E(E)(E+E)(i+E)(i+i)
  • α1αn:从α1出发,经过0步或若干步推出αn

  • α1+αn:从α1出发,经过1步或若干步推出αn

  • α𝛽 :即𝛼=𝛽α+β

    • <句子> He gave me a book
    • <句子> + He gave me a book
    • He gave <间接宾语><直接宾语>+He gave me <冠词> <名词>

之前例子的推导过程:

句型、句子和语言
  • 假定G是一个文法,S是它的开始符号。

  • 如果Sα,则称α是一个句型。

  • 仅含终结符号的句型是一个句子。

  • 文法G所产生的句子的全体是一个语言,记为L(G):

    L(G)={α|S+α,αVT}
例子

证明(ii+i)是文法

G(E)Ei|E+E|EE|(E)

的一个句子。

证明:

E(E)(E+E)(EE+E)(iE+E)(ii+E)(ii+i)

所以(i+i)是文法G的句子,E,(E),(EE+E),,(ii+i)是句型。

从文法到语言
例1
  • 设文法G1(A)Ac|Ab
  • G1(A)产生的语言是什么?

    • c开头,后继若干个b

      L(G1)={c,cb,cbb,}
    • AcAAbcbAAbAbbAbbbAbbcbb
例2
  • 设文法

    G2(S):SABAaA|aBbB|b
  • G2(S)产生的语言是什么?

    L(G2)={ambn|m,n>0}
  • SABAaAaAaaAaaaAaaAaaaBbBbBbbBbbbBbbBbbb
例3

请给出产生语言为{anbn|n1}的文法

G3(S):SaSbSab
例4

请给出产生语言为{ambn|1nm2n}的文法

G4(S):Sab|aabSaSb|aaSb

推导与语法树

最左推导和最右推导
  • 从一个句型到另一个句型的推导往往不唯一

    E+Ei+Ei+iE+EE+ii+i
  • 最左推导:任何一步αβ都是对α中的最左非终结符进行替换

  • 最右推导:任何一步αβ都是对α中的最右非终结符进行替换

语法树
  • 用一张图表示一个句型的推导,称为语法树
  • 一棵语法树是不同推导过程的共性抽象

语法树与二义性(ambiguity)
  • 一个句型是否只对应唯一一棵语法树?考虑如下例子:

  • G(E)Ei|E+E|EE|(E)是二义的(ambiguous)

  • (ii+i)对应了两棵语法树

具体定义:

  • 文法的二义性:如果一个文法存在某个句子对应两棵不同的语法树,则说这个文法是二义的

    • 例如G(E)Ei|E+E|EE|(E)

    • 可以将其改写为无二义文法G(E)

  • 语言的二义性:一个语言是二义的,如果对它不存在无二义的文法

    • 对于语言L,可能存在GG,使得L(G)=L(G)=L,有可能其中一个文法为二义的, 另一个为无二义的
    • 例如John saw Mary in a boat.是二义的,因为in a boat可以修饰Mary或者John。
  • 二义性问题是不可判定问题,即不存在一个算法,它能在有限步骤内,确切地判定一个文法是否是二义的

  • 但可以找到一组无二义文法的充分条件

形式语言鸟瞰

  • 乔姆斯基(Chomsky)是美国当代有重大影响的语言学家

  • 乔姆斯基于1956年建立形式语言体系,他把文法分成四种类型:0,1,2,3

  • 与上下文无关文法一样,它们都由四部分组成,但对产生式的限制有所不同

    • G=(VTVNSP)

      • VT:终结符(Terminal)集合(非空)

      • VN:非终结符(Noterminal)集合(非空),且VTVN=

      • S:文法的开始符号,SVN

      • P:产生式集合(有限)

四种文法分别如下:

  • 0型(短语文法,图灵机)
    • 产生式形如:αβ
    • 其中:α(VTVN)且至少含有一个非终结符;β(VTVN)
  • 1型(上下文有关文法,线性界限自动机)
    • 产生式形如:αβ
    • 其中:|α||β|,仅Sε例外
  • 2型(上下文无关文法,非确定下推自动机)
    • 产生式形如: Aβ
    • 其中:AVNβ(VTVN)
  • 3型(正规文法,有限自动机)
    • 产生式形如:AαBAα
      • 其中:αVT;A,BVN(右线性文法)
    • 产生式形如:ABαAα
      • 其中:αVT;A,BVN(左线性文法)
四种类型文法描述能力比较

上下文无关文法与上下文有关文法
例1

L5={anbn|n1}不能由正规文法(3型)产生,但可由上下文无关文法产生

G5(S)SaSb|ab
例2

L6={anbncn|n1}不能由上下文无关文法产生,但可由上下文有关文法产生

G6(S):SaSBC|aBCCBBCaBabbBbbbCbccCcc

推导例子:

SaSBCaaSBCBCaaaBCBCBCaaaBBCCBCaaaBBCBCCaaaBBBCCCaaabBBCCCaaabbBCCCaaabbbCCCaaabbbcCCaaabbbccCaaabbbccc

小结

  • 程序设计语言不是上下文无关语言,甚至不是上下文有关语言
  • L7={αcα|α{a,b}}不能由上下文无关文法产生,甚至连上下文有关文法也不能产生,只能由0型文法产生
    • L7对应了
      • 标识符引用
      • 过程调用过程中,“形-实参数的对应性”(如个数,顺序和类型一致性)
  • 对于现今程序设计语言,在编译程序中,仍然采用上下文无关文法来描述其语言结构
    • 这是一种权衡