文法的概念

每一种自然语言或者是编程语言都需要文法来描述,文法相当于语言学的语义分析,即分析每一句话所表示的含义,编译器需要利用文法来完成其语法分析和语义分析。

在目前编程语言领域,上下文无关文法作为程序语言的描述工具,比如a = b + c是一个合法的赋值语句。

符号和符号串的定义

每个程序都可以看成是一个“基本符号”串,如果有一个基本符号集,那么C语言等编程语言可以看成是在这个基本符号集上定义的、按照一定规则构成的一切基本符号串组成的集合。

字母表是元素的非空有穷集合,字母表中的元素称之为符号,因此字母表也称之为符号集。例如C语言中的字母表由字母、数字、关键字等组成。

符号串就是由符号集中的元素组成的序列。例如给定符号集{a,b,c},那么abcabbac就是由该符号集组成的符号串。

文法的形式化定义

文法的形式化定义可以表述为 G = ( V T , V N , P , S ) G=(V_T,V_N,P,S) G=(VT​,VN​,P,S) ,其中:

  • V T V_T VT​ 为终结符集合
  • V N V_N VN​为非终结符集合
  • P P P 为产生式集合
  • S S S 为开始符号

何为终结符?在编程语言中,终结符可以理解为不能再进行拆分的基本符号,例如C语言中的ifelsewhile关键字,也可以是一个变量名、数字。

和终结符相反,非终结符就是可以再进行拆分的符号,它可以推出其它的语法成分。如果要对一个非终结符进行语法分析,就需要对它需要进行递归分析。在C语言的if-else文法中,if或者else后面跟着的代码块可以看成是非终结符。

一个文法含有一个或多个产生式,产生式描述了将终结符集合和非终结符集合组合成串的方法。其一般形式为 α → β α→β α→β,其中:

  • α α α称之为产生式的左部,并且 α ∈ ( V T ∪ V N ) + α∈(V_T∪V_N)^+ α∈(VT​∪VN​)+ ,表示至少要包含 ( V T ∪ V N ) (V_T∪V_N) (VT​∪VN​)中的一个元素。
  • β β β称之为产生式的右部,并且 β ∈ ( V T ∪ V N ) ∗ β∈(V_T∪V_N)^* β∈(VT​∪VN​)∗,表示可以包含零个或多个 ( V T ∪ V N ) (V_T∪V_N) (VT​∪VN​)中的元素。

对于文法产生式当中的符号,我们约定终结符为:

  • 英文小写字母,如abc
  • 运算符,如+*
  • 标点符号,如逗号,括号等
  • 数字
  • 粗体字符串,如ifelse
  • 希腊字母ε为空串

非终结符约定为:

  • 英文大写字母,如ABC等。其中字母S通常表示为开始符号
  • 小写、斜体的名字,如exprstmt
  • 代表程序构造的大写字母。如E(表达式)、T(项)和F(因子)
  • 字母表中排在后面的大写字母(如X、Y、Z)表示文法符号(即终结符或非终结符)
  • 字母表中排在后面的小写字母(主要是u、v、…、z)表示终结符号串(包括空串)
  • 小写希腊字母,如αβγ,表示文法符号串(包括空串)

如非特别说明,第一个产生式的左部就是开始符号。

文法的分类

文法分为0型、1型、2型、3型四种,它们之间的差别在于对产生式施加的不同限制,形似于数据库不同范式之间的差异。我们在判断时,一般先核对该文法是否是3型文法,如果不是再核对是否是2型文法,依次往下推。

下面给出各个文法的定义

0型文法

当文法 G = ( V T , V N , P , S ) G=(V_T,V_N,P,S) G=(VT​,VN​,P,S) 的每个产生式 α → β α→β α→β 满足以下条件:

  • α ∈ ( V T ∪ V N ) ∗ α∈(V_T∪V_N)^* α∈(VT​∪VN​)∗
  • β ∈ ( V T ∪ V N ) ∗ β∈(V_T∪V_N)^* β∈(VT​∪VN​)∗
  • 至少含有一个非终结符

则称文法 G G G 为0型文法。0型文法又称短语文法,任何0型语言都是递归可枚举的,反过来也成立。

1型文法

文法 G = ( V T , V N , P , S ) G=(V_T,V_N,P,S) G=(VT​,VN​,P,S) 的每个产生式在 α → β α→β α→β 满足0型文法的要求外,还满足以下要求:

  • ∣ β ∣ > = ∣ α ∣ |β|>=|α| ∣β∣>=∣α∣(绝对值符号代表集合中元素的个数)
  • S → ε S→ε S→ε 除外

则称文法 G G G 为1型文法,又称上下文有关文法

例如文法 G = ( V T , V N , P , S ) G=(V_T,V_N,P,S) G=(VT​,VN​,P,S), V N = { S , B , E } V_N=\{S,B,E\} VN​={S,B,E}、 V T = { a , b , e } V_T=\{a,b,e\} VT​={a,b,e}的产生式为:
S → a S B E S→aSBE S→aSBE
S → a B E S→aBE S→aBE
E B → B E EB→BE EB→BE
a B → a b aB→ab aB→ab
b B → b b bB→bb bB→bb
b E → b e bE→be bE→be
e E → e e eE→ee eE→ee

因为每个产生式都满足右部元素数量大于等于左部数量,并且没有产生式为 S → ε S→ε S→ε ,所以文法 G G G 是一个1型文法。

2型文法

文法 G = ( V T , V N , P , S ) G=(V_T,V_N,P,S) G=(VT​,VN​,P,S) 的每个产生式 α → β α→β α→β 在满足1型文法的要求外,还满足以下要求:

  • α α α 仅仅是一个非终结符
  • β ∈ ( V T ∪ V N ) ∗ β∈(V_T∪V_N)^* β∈(VT​∪VN​)∗

则称此文法是2型文法,又称上下文无关文法

例如文法 G = ( V T , V N , P , S ) G=(V_T,V_N,P,S) G=(VT​,VN​,P,S) , V N = { S } V_N=\{S\} VN​={S}、 V T = { 0 , 1 } V_T=\{0,1\} VT​={0,1},产生式为:
S → 0 S 1 ∣ 01 S→0S1|01 S→0S1∣01(等价于两个产生式: S → 0 S 1 S→0S1 S→0S1 和 S → 01 S→01 S→01,符号|含义为“或”)
该文法就是一个2型文法。

3型文法

文法 G = ( V T , V N , P , S ) G=(V_T,V_N,P,S) G=(VT​,VN​,P,S) 的每个产生式满足2型文法外,还满足以下要求:

  • 形如 A → a A→a A→a 和 A → a B A→aB A→aB,
  • A A A 、 B B B都是非终结符
  • a ∈ V T ∗ a∈V_T^* a∈VT∗​( a a a为非终结符的零个或多个元素)

则称文法 G G G 为3型文法,又称正规文法

语法树

语法树又称语法分析树或分析树。
给定文法 G = ( V T , V N , P , S ) G=(V_T,V_N,P,S) G=(VT​,VN​,P,S) ,对于 G G G 的任何句型都能够构造出与之相关的语法树,这颗树满足4个条件:

  • 每个结点都有一个标记,这个标记属于 V T V_T VT​ 或者 V N V_N VN​
  • 根的标记是 S S S
  • 若一个结点 A A A 至少有一个子结点,那么 A ∈ V N A∈V_N A∈VN​
  • 如果结点 n n n 的直接子节点从左到右的顺序为 n 1 , n 2 , n 3 , . . . , n k n_1,n_2,n_3,...,n_k n1​,n2​,n3​,...,nk​,其标记分别为 A 1 , A 2 , A 3 , . . . , A k A_1,A_2,A_3,...,A_k A1​,A2​,A3​,...,Ak​,那么产生式 A → A 1 A 2 A 3 . . . A k A→A_1A_2A_3...A_k A→A1​A2​A3​...Ak​ 一定是文法 G G G 产生式集合 P P P 中的元素。

语法树表示了在推导过程中采取了哪个产生式和使用在了哪个非终结符上,它并没有表明采用的产生式的顺序
根据语法树定义,我们可以画出文法 G G G 的语法树。

例题:给出文法 G = ( { S , A } , { a , b } , P , S ) G=(\{S,A\},\{a,b\},P,S) G=({S,A},{a,b},P,S),其中 P P P 包含:
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

上述文法可以有三种推导方式:

  • S ⇒ a A S ⇒ a A a ⇒ a S b A a ⇒ a S b b a a ⇒ a a b b a a S⇒aAS⇒aAa⇒aSbAa⇒aSbbaa⇒aabbaa S⇒aAS⇒aAa⇒aSbAa⇒aSbbaa⇒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⇒aAS⇒aSbAS⇒aabAS⇒aabbaS⇒aabbaa S⇒aAS⇒aSbAS⇒aabAS⇒aabbaS⇒aabbaa
    该推导总是选择最左边的非终结符,并找出以该非终结符为左部的产生式进行递归推导,该推导方式为最左推导
  • S ⇒ a A S ⇒ a S b A S ⇒ a S b A a ⇒ a a b A a ⇒ a a b b a a S⇒aAS⇒aSbAS⇒aSbAa⇒aabAa⇒aabbaa S⇒aAS⇒aSbAS⇒aSbAa⇒aabAa⇒aabbaa
    该推导则是根据情况选择不同的产生式来替换非终结符

上述三种推导方式得到的语法树都为:

如果一个文法存在某个句子对应两棵语法树,那么则称该文法是二义的。根据现有理论,无法判断一个文法是否是二义的,因为这个问题是递归不可解的。

编译原理——文法的基本概念相关推荐

  1. #编译原理# 文法和内容(二)

    文法和内容 编译原理笔记第二部分,内容参考:北航软院教师邵兵课堂课件及内容.张莉著<编译原理及编译程序构造>.国防工业出版社的<编译原理--学习指导与典型题解析>.AlvinZ ...

  2. python编译原理_编译原理实战课 带你吃透编译技术核心概念与算法

    编译原理实战课,我们到底要学些什么? 在这门课程里,宫老师精选出了Java.Java JIT.Python.JavaScript.Julia.Go.MySQL这7种真实编程语言的编译器,带你阅读它们的 ...

  3. 编译原理-正则文法与正则表达式的相互转化

    正则文法与正则表达式的相互转化 前言 一.正则文法 1.定义 2.例子 二.正则表达式 1.定义 2.例子 三.转换规则 1.正则文法转换为正则表达式 2.正则表达式转换为正则文法 四.转换例子 1. ...

  4. 编译原理实验c语言cfg文法,编译原理

    地址在符号表中引入指针previous,来连接上一个符号的首地址运行时存储空间组织活动记录用于管理函数变量的信息栈式存储过程进入和返回通过变更top和sp指针,实现活动记录的栈式处理静态链实现局部变量 ...

  5. 理解前端Babel编译原理

    大厂技术  坚持周更  精选好文 背景 我们知道编程语言主要分为「编译型语言」和「解释型语言」,编译型语言是在代码运行前编译器将编程语言转换成机器语言,运行时不需要重新翻译,直接使用编译的结果就行了. ...

  6. 由 Babel 理解前端编译原理

    大厂技术  坚持周更  精选好文 背景 我们知道编程语言主要分为「编译型语言」和「解释型语言」,编译型语言是在代码运行前编译器将编程语言转换成机器语言,运行时不需要重新翻译,直接使用编译的结果就行了. ...

  7. 由Babel理解前端编译原理

    背景 我们知道编程语言主要分为「编译型语言」和「解释型语言」,编译型语言是在代码运行前编译器将编程语言转换成机器语言,运行时不需要重新翻译,直接使用编译的结果就行了.而解释型语言也是需要将编程语言转换 ...

  8. 北京工业大学 编译原理 国家级精品课程

    北京工业大学 编译原理 国家级精品课程 蒋宗礼 北京工业大学为北京市属的国家"211工程"建设大学,旨在为北京市的建设培养高水平的工程应用型人才.计算机科学与技术专业致力于培养计算 ...

  9. 编译原理lr(0)c语言,关于编译原理:LR(1)LR(0)文法判断?

    "编译原理"是大学计算机类专业的一门主干课程.设置本课程的目的,在于系统的向学生讲述编译系统的结构.工程流程以及编译程序各组成部分的设计原理和实现技术,使学生通过本课程的学习,既掌 ...

最新文章

  1. linux 安装安装rz/sz 和 ssh
  2. 信科c语言实验程序修改题_豆瓣评分 9.3,史上最好的 C 语言著作,竟然翻车了.........
  3. 用类模拟C风格的赋值+返回值
  4. hi3559 目标检测
  5. centos下yum安装mysql5.7_CentOS下yum安装mysql5.7
  6. python项目部署失败的原因_python项目环境部署(一)
  7. 10没有基于策略的qos_WebRTC QoS | NACK 格式与发送策略
  8. HDU - 6746 Civilization(贪心+模拟)
  9. Linux网络编程 | 信号 :信号函数、信号集、统一事件源 、网络编程相关信号
  10. Eclipse maven工程 Missing artifact com.sun:tools:jar:1.5.0:system 解决方法
  11. Java --- 基础学习Ⅰ
  12. 工程图样中粗实线的用途_图纸天天画,粗实线和细实线的线宽比例是多少?2:1还是3:1?...
  13. [AGC031E] Snuke the Phantom Thief(网络流)
  14. linux更新命令yum,Linux中升级更新命令yum upgrade和yum update的区别
  15. SQL查询成绩前3的student
  16. python 平方根_数的Python平方根
  17. python绘制玫瑰花代码视频_python turtle玫瑰花绘制效果和源代码
  18. linux 桥接stp原理,Linux 中的网桥技术
  19. 效率低下的不良习惯与解决办法
  20. GeForce Desktop Products Compute Capability

热门文章

  1. 行业资讯 | 做到这几点,Revit建模效率提升,实用.
  2. LAN IP,WAN IP和Global IP
  3. 南卡315打假!揭露山寨耳机“十宗罪”!
  4. 状态码502和504分析
  5. 中秋国庆旅游 App 市场竞争激烈!工具类 App 更易被苹果推荐!
  6. Java异常的根类似_Java异常(Exception)类型及处理
  7. PMOS和NMOS开关应用
  8. 如何关闭iPhone浏览器自动将数字识别为电话号码
  9. 你真的认为自己熟练Python?带你一篇文章 查漏补缺,感受自己离深入掌握 Python 还有多远。
  10. idea前进和后退光标位置的快捷键和设置按钮的方法