一、字母表(有穷符号集合)

1.1 字母表定义

字母表也即符号集,用表示,它是一个包含各种符号有穷非空集合

以汉语为例,汉语字母表就是各种汉字、数字、标点符号的集合;以英语为例,英语字母表就是各种字母、数字、标点符号的集合…那么到了编程,字母表就可能是字母、数字、各种专用符号和保留字了。

1.2 字母表上的运算:
  1. 乘积
  2. n次幂
  3. 正闭包
  4. 克林闭包

二、符号串/串

2.1 符号串相关定义:

符号串是对于字母表来说的一个概念,字母表的符号串指的就是由字母表中各个字符组成的一个有穷序列。

注意这里的“有穷”,指的是符号串本身是由有穷个符号组成但是符号串的个数是无穷多的(组合方式不同)

以字母表 ∑={0,1} 为例,它的符号串就有:0,1,00,01,10,11,000 等等。

符号串的长度指的是符号串符号的个数,以 m = 000 为例,|m|= 3。

空符号串 ε 长度为 0,表示不包含任何符号,类似于编程中的空字符串 “”。所以有 εm = mε= m。

以 m = abc 为例,它的头是 ε,a,ab,abc;它的尾是 ε,c,bc,abc。而它的固有头不考虑末尾符号 c,固有尾不考虑首部符号 a。

2.2 符号串的运算:连接、方幂
  1. 符号串的连接:连接就是两个字符串顺序拼接,比如 x = abc,y = def,那么 xy = abcdef。
  2. 符号串的方幂:如果一个符号串由多个重复符号构成,如何方便地表示它呢?

比如 y = xxxx…xxxx(n 个 x),那么就可以写成 y = x^n,此时 y 就是 x 的方幂。这点和数学是一样的。不过要注意,x^0 ≠ 1 = ε

串s的n次幂:将n个s连接起来


三、闭包

以字母表 ∑ = {a,b} 为例,任何由它的符号串作为构成元素的集合,都可以称作字母表的符号串集合。比如说 {ab},{abab,ababab} 等。

两个符号串集合的乘积定义为 AB = {xy| x∈A且y∈b},其实就是笛卡尔积

一般的字符串集合可能并不能囊括一个字母表的所有符号串,但是有一种集合却能包含所有的符号串,这种特殊的集合称为闭包,记作 ∑*。

*其实就是全选的意思(联想 CSS 中的通配选择符就好理解了)。

∑* = {ε,a,b,ab,ab,ba,aba,aab......} = ∑^0 ∪ ∑^1 ∪ ∑^2 ∪......∪ ∑^n

要注意的是,闭包也包含了空符号串

将闭包中的空符号串去掉,就成为了正闭包,也即 ∑+
显然:∑*= ∑^0 ∪ ∑+,∑+ = ∑∑* = ∑*∑。


四、文法

4.1 文法在语言体系中的位置

语言包括语法和语义两个方面,但是语法和语义都是比较抽象的东西,所以我们需要借助一些工具来阐述它们。以语法来说,文法就是阐述它的一个工具

4.2 文法的形式定义

文法是描述语言语法结构的形式规则。它的形式化定义是一个四元组,即 :

下面我们先给出一个自然语言的例子,然后借此来解释四元组的各个成分都是什么。

<句子> → <主语> <谓语><主语> → <代词> | <名词><谓语> → <动词><代词> → 你 | 我 | 他<名词> → 张三 | 教师 | 大学生<动词> → 教书 | 学习
(1)VT

VT 指的是终结符集合终结符即 terminal symbol,它是文法所定义的语言的最基本符号,这意味着一个终结符不可再细分(注意“终结”这个词)。在编程语言中,终结符其实就是之前提到的 token,比如保留字、运算符、界符等这些最最基本的符号

以上面为例,VT ={ 你,我,他,张三,教师,大学生,教书,学习 }。

终结符一般用小写字母表示

终结符符号约定:

  1. 字母表中排在前面的小写字母:如a,b,c
  2. 运算符
  3. 标点符号
  4. 数字
  5. 粗体字符串:如id,if
(2)VN

VN 指的是非终结符集合非终结符即 nonterminal symbol,它是用来表示语法成分的符号,有时候也称为“语法变量”。在编程语言中,我们可以说表达式或者赋值语句就是一个非终结符,因为它可以继续细分为多个 token。

以上面为例,VN ={ <句子>,<主语>,<谓语>,<代词>,<名词>,<动词> }。
非终结符的“非终结”,就是说“还没有到尽头”,还可以继续拆分,一般用 <> 括起来。

非终结符一般用大写字母表示

终结符和非终结符统称为文法符号
VT∪VN :文法符号集

非终结符符号约定:

  1. 字母表中排在前面的大写字母:如A,B,C等
  2. 字母S
  3. 小写,斜体的名字:如expr,stmt等
  4. 代表程序构造的大写字母:如E(表达式),T(项),F(因子)等
(3)P:

P 即 production,指的是产生式集合。终结符和非终结符的转换依靠的就是产生式(或者说生成式,推导规则)。产生式形如 a → β (或者 a : : = β ,这种表示方法即巴科斯范式 ),意思是将 a 定义为 β。a 称为产生式左部,它是非终结符集合的一个元素;而 β 称为产生式右部,它是终结符和非终结符并集的一个元素。

(4)S:

S 即 start symbol,指的是开始符号(识别符号)。它是最开始的那条产生式的左部,一切的推导都是从它这里开始进行的,可以认为它就是最大的那个成分。所以也注定了 S 必须在 P 中至少作为某一条产生式的左部(不然无从推导)。

以上面为例,S = <句子>。

4.3 文法更简洁的形式化定义

假如现在有文法 G =({S,A,B},{0,1},P,S),

其中,P = { S → 0A,S → 1B,A → 1B,B → 1 }。

是否有更简便的方法来表示它呢?事实上,这里仅从产生式集合 P 来看,完全可以在不引起歧义的情况下推断出终结符号集,非终结符号集以及开始符号。这意味着我们可以将这三者省略仅用产生式集合表达文法本身,也即:

G:
S → 0A
S → 1B
A → 1B
B → 1
B → 0

更进一步地,我们发现部分产生式的左部都是一样的,所以可以继续简写为:

G:
S → 0A | 1B
A → 1B
B → 1 | 0

此时,0A 或者 1B 称为 S 的候选式(candidate),1 或者 0 称为 B 的候选式。

4.4 推导

(1)直接推导/替换/重写:

用产生式的右部替换产生式的左部。
所有的产生式实际上都是一个直接推导。

(2)推导:

推导指的是从文法的开始符号出发,反复连续地使用产生式,对非终结符施行替换和展开,最终得到一个仅由终结符构成的符号串,推导过程的每一步都是一个直接推导。

还是以上面的文法为例,那么就有 S ⇒ 0A ⇒ 01B ⇒ 011,这个序列就是从 S 到 011 的一个推导,或者说 S 可以推导出 011。

序列可以简写为 S  +⇒ 011,表示经过一步或者多步推导,
而  S  *⇒ 011 表示经过 0 步或者多步推导。
所以,S  *⇒ 011 要么是 S = 011,要么是 S  +⇒ 011。
(3)最左/最右推导:

推导的过程并不是唯一的。对于任何一步 α ⇒ β,如果都是对 α 中的最左非终结符进行替换,那么就说最左推导,反之就是最右推导。

4.5 句型、句子、语言
  1. 句型:如果 S *⇒ a,开始符号 S 可以推导得到某个符号串,那么这个符号串 a 就称为句型

一个句型中既可包含终结符,又可包含非终结符,也可是空串

以上面文法为例,0A ,01B,011 … 都是句型

句型的短语和直接短语

2. 句子:在推导之初,句型可能既包含终结符也包含非终结符,但最终肯定只剩下终结符构成的符号串,此时这个符号串就称为句子

句子是不包含非终结符的句型

以上面文法为例,011 就是句子。

  1. 语言:文法产生的句子的全体就构成了语言,记作L(G)

以上面文法为例,L(G) = { 011,11 }。


五、语法分析树与文法的二义性

我们可以借助语法分析树(这里的语法分析树是具体语法树,即 parse tree,不是抽象语法树)这个结构来描述句型的推导

比如给定文法 G:G = ( {S,A},{a,b},P,S ),其中 P ={ S → aAS,A → SbA,A → SS,S → a,A → ba }
可以这样推导出句子 aabbaa:S ⇒ aAS ⇒ aSbAS ⇒ aabAS ⇒ aabbaS ⇒ aabbaa

那么如何用分析树表达这个句子呢?如图所示:

用根节点代表开始符号,随着推导的进行,当某个非终结符被它的候选式所替换时,这个非终结符的相应结点就会产生下一代子结点,以此类推。

有时候,对于某个句子,由于它的推导过程不唯一,所以会导致它的分析树也不唯一。

之前的例子中,我们给定了文法 G:E → E + E | E * E | (E) | i,由这个文法推导出句子 (i * i + i),实际上有两种方式:
E ⇒ (E) ⇒ ( E + E ) ⇒ ( E + i ) ⇒ ( E * E + i ) ⇒ ( E * i + i ) ⇒ ( i * i + i )
E ⇒ (E) ⇒ (E * E ) ⇒ ( i * E ) ⇒ ( i * E + E) ⇒ ( i * i + E) ⇒ ( i * i + i )

对应地有两种分析树:

由于这个文法存在着某个句子对应着两棵不同的分析树,所以这个文法是二义(歧义的。

显然,程序语言不能出现歧义。消除歧义的方法之一是改写语法,但这种改写非常困难;另一种方法就是引入优先级 ,利用符号的优先级来选择需要的推导方式。

作为描述程序语言上下文无关文法,我们对它还有一些限制:

  1. 文法中不包含形如 P → P 的产生式
  2. 每个非终结符一定可以被用到,或者本身被 S 推导得到,或者本身推导得到其它终结符串。

六、文法类型

乔姆斯基把文法划分为四种类型,这四种类型层层增强,越到后面限制越大

(1) 0 型文法(短语文法/无限制文法)

0 型文法也叫短语文法。设 G = { VN, VT , P , S },如果它的每个产生式 α→β 都满足:

“α∈(VN∪VT)* 且至少含有一个非终结符,而 β∈(VN∪VT)*

其中,VN∪VT 代表的是终结符合集和非终结符号集的并集,注意这同样是一个字母集,所以外面加上星号,就成为我们开篇所说的字母集的闭包。也就是说,产生式的左部或者右部,必须是由终结符和非终结符构成的符号串。

(2) 1 型文法(上下文有关文法)

1 型文法也叫上下文有关文法在 0 型文法的基础上加以限制,规定对于每一个 α→β,都必须满足 |α| <= |β|。也就是说,产生式左部符号串长度必须小于等于右部符号串长度

这里要注意一个特例就是:α → ε,虽然左部长度一定大于右部长度,但它仍然符合 1 型文法。

(3) 2 型文法(上下文无关文法)

2 型文法也叫上下文无关文法。在 1 型文法的基础上加以限制,规定对于每一个 α→β,都必须满足 α 是一个非终结符。也就是说,产生式左部必须得是一个非终结符。

(4) 3 型文法(正则文法)

3 型文法也叫正规文法。在 2 型文法的基础上加以限制,规定对于每一个 α→β,要么必须满足 A→ α | αB(右线性),要么必须满足 A→ α | Bα(左线性)。这里的 AB 代表非终极符号。


参考文章:

  1. 一篇微信公众号的文章
  2. 哈工大编译原理课的PPT

编译原理基本概念和术语相关推荐

  1. 编译原理 --- 语法分析概念,自上而下分析面临的问题以及如何消除左递归问题

    第一部分 --- 语法分析基本概念 1.上面这个箭头 --> 符号表示的意思是P被 α 定义 A是一个非终止符,γ是一个和α,β属于同一个集合的元素 1.一个双箭头符号表示的是直接推出,而一个双 ...

  2. 句型与句子,编译原理基本概念

    字母表:符号的有限集合. 记作: Σ 例如:{a, b, - , x, m} 字符串(符号串): 通常我们用到建立在 Σ 上的字符串:有穷的符号序 列. 例如:对于 Σ={a, b, c}, &quo ...

  3. Scons环境搭建和编译原理概述及嵌入式开发常用模板

    Scons环境搭建和编译原理概述及嵌入式开发常用模板 Scons是用python实现的一个类似makefile的软件构建工具.其官网是SCons: A software construction to ...

  4. 前端零基础编译原理科普

    本文是 @神说要有光 对编译小白 ssh 的一次答疑解惑,很适合零基础的新手第一次了解编译原理的概念,故分享出来. 近些年,编译原理在前端领域的应用越来越多,大家比较熟悉的有工程化领域各种转译器:ba ...

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

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

  6. 计算机编译原理 张,计算机编译原理概念总结

    <计算机编译原理概念总结>由会员分享,可在线阅读,更多相关<计算机编译原理概念总结(11页珍藏版)>请在人人文库网上搜索. 1.第一章 引论?为什么要用编译器? 与编译器相关的 ...

  7. 【编译原理】期末 龙书概念梳理+做题方法(混子保过指南+学霸提分秘籍)

    编译原理期末总结 龙书概念梳理+做题方法 目录 编译原理期末总结 龙书概念梳理+做题方法 编译概述 1 编译过程 2 编译&解释 3 GCC的处理过程 词法分析 1 词法分析的任务 2 词法分 ...

  8. 编译原理学习笔记一(待续)

    这几天忙着学英语,同时在学习编译原理,对这门课很感兴趣,已经制作了词法分析器,同时还在补充这个分析器的功能,也准备着手开始写语法分析器,看到最后能不能连在一起,我想如果能够将整套编译器的流程跑下来真的 ...

  9. 深入剖析ASP.NET的编译原理之二:预编译(Precompilation)

    (转载)在本篇文章的第一部分:[原创]深入剖析ASP.NET的编译原理之一:动态编译(Dynamical Compilation),详细讨论了ASP.NET如何进行动态编译的,现在我们来谈谈另外一种重 ...

  10. 编译原理_P1004

    龙书相关知识点总结 //*************************引论***********************************// 1. 编译器(compiler):从一中语言( ...

最新文章

  1. C++模板:模板简述,函数模板详细说明【C++模板】(56)
  2. webservice框架_聊聊从RPC到服务治理框架
  3. 服务器物理内存总是九十几,Solr总是使用超过90%的物理内存(Solr always use more than 90% of physical memory)...
  4. python八角图形绘制_(Python)从零开始,简单快速学机器仿人视觉Opencv—第四节:OpenCV处理鼠标事件...
  5. 听说你想进玩TikTok?
  6. 【Oracle】查询当前SCN
  7. 学习第四章与第五章的感悟
  8. springboot - 应用实践(2)第一个springboot应用
  9. atitit.为什么笔记本跟个手机不能组装而pc可以
  10. Java 分页工具类
  11. web test performance tools / linux performance tools / windows performance tools
  12. http解析库http-parser
  13. win7音量图标不见了 点显示它图标和通知 提示但前未处于活动
  14. android 通话录音
  15. html5视频制作,iH5最专业的H5制作工具
  16. Zrlog开源博客网站 安装教程
  17. VMware Workstation 12 Pro虚拟机下载(含序列号)
  18. pandas 数据查询实例
  19. mark mark mark
  20. Java随机生成验证码

热门文章

  1. 嵌入式芯片调试神器-J-Link RTT详解
  2. 基于jQuery省市县联动插件
  3. 前端实现H5制作海报
  4. 计算机网络安全 的论文,计算机网络安全论文6000字
  5. 第六课:计算两数的GCF(最大公因数)(基于AndroidStudio3.2)
  6. CF633H Fibonacci-ish II 莫队、线段树、矩阵乘法
  7. Rust reqwest框架开启cookie
  8. 高仿网易评论列表效果之界面分析(一)
  9. 计算机备注用if函数怎么算,Excel中IF函数使用操作的设置技巧
  10. 干货分享:PDF分割合并工具免费哪个好用?