2021-03-29 编译原理简介(一 词法分析)

本文主要记录一下编译原理的学习路径,由于龙书等著作已近给出了详细介绍,本文只给出算法介绍;本文不会写的特别严谨,主要是介绍算法。

词法分析器的实现主要有几个核心概念:
1,正则表达式
2,抽象语法树
3,NFA(不确定有穷状态机)
4, DFA(确定有穷状态机)

1,正则表达式:
通俗理解:
可以看成一个符号序列,中间含若干确定运算符;最基础的正则表达式就是字符;每个正则表达式唯一对应一个该正则表达式表达的语言,语言指的是以字符串序列为元素的确定集合;正则表达式的复合对应的语言集合的复合。
因此正则表达式在数学上可以看成是一系列集合运算;每个正则表达式就对应唯一一个集合,正则表达式的运算对应集合的运算,集合运算的结果仍然是集合

下文中用L(x)表示正则表达式x对应的语言。

定义:
1)给定两个字符串s_1,s_2s_1s_2表示两者前后相连所得字符串;
2)如果S_1是一个字符串序列的集合,S_2也是一个字符串序列的集合,则 S_1S_2表示S_1中任意一个字符串后接S_2中任意一个字符串所得的集合
3)S是一个字符串序列组成的集合,则S^i:= SSS...(共i个S),当i=0时,S^0定义为\epsilon(空串)
4)S^* : = S^0 \cup S \cup S^2 \cup S^3...

正则表达式官方定义:

  1. \epsilon是一个正则表达式,L(\epsilon) = \emptyset
  2. 给定符号集S,则S中每个元素x都是一个正则表达式,其对应语言为L(x)= {x}
    3)如果a是正则表达式,则(a)也是正则表达式,且L((a))=L(a)
  3. 如果(a),(b)是两个正则表达式;则
    (a)|(b)是一个正则表达式, L((a)|(b))= L(a)\cup L(b)
    4)(a)(b)是一个正则表达式,L((a)(b)) = L(a)L(b)
    5)(r)^*是一个正则表达式,表示语言 L(r)^*

可以用以正则表达式定义的语言叫做正则集合

2,正则表达式的抽象语法树
通俗解释: 由于正则表达式只包含2元和1元运算符,因此正则表达式可以表示为一棵树的形状
举例: (a|b)*abb 的抽象语法树为:

                _
             /       \         
           _         b
         /    \
       _      b
     /    \
    *     a
    |
    (|)
   /   \
 a      b

其中用 _ 表示两个正则表达式连接

3,NFA:
通俗解释:可以看成一个不含重边的有向图,图的有向边上关联着符号,同一个节点发出的多条边上可能关联相同的符号;
4,DFA:
基本同上,不过同一个节点发出的多条边上的符号都不相同

下面基于以上概念快速实现词法分析器:
一个DFA基本上等价于一个词法分析器了,而输入的词法单元可以对应为一门语言,也就对应到一个正则表达式;

因此,实现词法分析器的过程,也就是:
根据正则表达式 构建 DFA的过程,方法为:
正则表达式-> 抽象语法树-> NFA->DFA

1,正则表达式 -> 抽象语法树
这一步基本没什么难度,手写都可以,略去

2,抽象语法树->NFA
给抽象语法树的所有非\epsilon叶子节点标上数字(随意标,不重复即可,不过一般从1,递增标)这些数字称为节点的位置,可同时也 称为节点上符号的位置(一个符号允许对应多个位置)
计算 每个节点的三个参数:
nullable, firstpos, lastpos ,
和每个位置 的 followpos
定义:
nullable(n) :是一个bool值,当且仅当 以n为根的子树对应的正则表达式的语言中 包含 \epsilon
firstpos(n): 是一个位置集合,一个位置属于该集合 当且仅当 以n为根的子树对应正则表达式的语言中存在一个符号串满足其首字母 按照这颗树解析时 刚好解析到这个位置;
lastpos(n): 位置集合 ,一个位置属于该集合 当且仅当 n为根的子树对应的正则表达式的语言中存在一个符号串 满足其尾字母 按照这颗树解析时 刚好解析到这个位置;
followpos(p): 是一个和位置p相关的位置集合。 一个位置q属于该集合当且仅当 L中的某个川 x=a_1a_2...a_n按照抽象语法树解析时,p和某个a_i匹配而 qa_{i+1}匹配
算法:
每种类型对应的 nullabel 值 和 firstpos值 分别为:
\epsilon叶子节点: true , \emptyset
位置为i的叶子节点: false , {i}
or节点n=c_1|c_2: nullable(c_1) 或者 nullabel(c_2) ,firstpos(c_1) \cup firstpos(c_2)
cat-节点 n=c_1c_2: nullable(c_1) \quad and\quad nullable(c_2),
if(nullabel(c_1)) firstpos(c_1)\cup firstpos(c_2) else firstpos(c_1)
start-节点n=c^*: true, firstpos(c)
由对称性容易推出 lastpos的公式,略过;
followpos计算法则如下:
1,如果n是 cat节点,左右子节点为c_1,c_2,则lastpos(c_1)中每个位置i ,firstpos(c_2)中所有都位于 followpos(i)
2,如果nstart节点,并且ilastpos(n)中的一个位置,firstpos(n)中的所有位置都位于 followpos(i)

按照以上方法,计算出nullabel,firstpos,lastpos,followpos之后,可以用一个有向图 来表示 followpos, 每个位置对应图中一个节点,位置i到位置j 存在一条有限边当且仅当 j在followpos(i)中,
然后做三件事:
1把该图firstpos所有位置设为 开始状态
2每条i到j的有向边上添加位置i上的符号
3 把和结尾#关联的位置作为接受状态
至此,得到 NFA

3,NFA -> DFA
之后利用以下伪代码算法就可以计算出 DFA了:
初始化Dstates, 使之只包含未标记状态 firstpos(n_0)$ n_0为抽象语法树根节点
while( Dstates 中存在未标记的状态S){
标记S,
for( 每个输入符号a){
U :=S中和a对应的所有位置p的followpos(p)的并集 (和a对应的意思NFA中该位置的节点有一个用a标记的发出边)
if(U不在Dstates中)将U作为未标记态加入Dstates;
Dtran[S,a] = U;
}
}
注:其中Dran的就是待求DFA的状态边转移关系,也就是状态S通过标记了a的有向边转换到 U;

之后,还有一些优化减少DFA节点数目,这里略过;

至此,我们快速的实现了一个词法分析器。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,539评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,911评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,337评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,723评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,795评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,762评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,742评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,508评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,954评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,247评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,404评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,104评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,736评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,352评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,557评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,371评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,292评论 2 352

推荐阅读更多精彩内容