编译原理:词法分析概览

词法分析的目的在于对输入的字符串进行扫描并将其中匹配的词素找寻出来转换为词法单元然后将其添加入符号表或者送给语法分析器。

比如说有这样一个语句:
int x = 1;
词法分析器会将其中的{int, x, =, 1}提取出来,每一项都会生成一个词法单元,某些词法单元不仅有词法单元名,也保有属性值,比如说int就只有一个词法单元名,所以它的表示就是(这个词法单元名是临时编的,逗号后面没有写内容就说明它的属性值为空),再来看1生成的词法单元,它的词法单元名是NUM,属性值是1。还有很多种类的词法单元可以参考相关书籍。

我们可以通过正则表达式来识别不同类型的词素,比如使用letter_(letter_|digit)*就可以识别C语言的一个标识符。以此类推就可以使用正则表达式识别各种关键字、运算符、操作符等等各种我们平时遇到的东西。

但下面的问题是我们应该如何写出使用正则表达式规则进行匹配的程序?也就是说我怎么实现这个正则表达式?(这里不是说像java和python直接调用相关库函数即可,我们要做的是自己写出正则表达式的实现!)

其实实现了正则表达式,我们的词法分析器核心部分也就完成了!

有限状态机可以做到实现正则表达式

有穷状态机分为DFA(确定有穷状态机)和NFA(非确定有穷状态机)

实现正则表达式

正则表达式的实现实际上是利用了有限状态机,在这里我们可以通过如下三中方法对正则表达式进行实现:

1.正则表达式->NFA->DFA
2.正则表达式->NFA
3.正则表达式->DFA

(详见龙书)

1.正则表达式->NFA->DFA
  正则表达式r转为NFA,先将r分解为最小子表达式然后根据构造NFA的基本规则归纳规则进行NFA的构造,详见龙书3.7.4节。然后通过子集构造法将NFA转换为DFA,详见龙书3.7.1节。
  最后我们会得到一个下图所示的DFA,依据此DFA就可以实现相应的正则表达式
编译原理:词法分析概览_第1张图片
2.正则表达式->NFA
  根据龙书3.7.4节生成的NFA其实可以直接用来对字符串进行识别而无需转化为DFA(至于为什么很多时候要转化为DFA在后面会说),但是一个NFA只能识别一种词法单元,比如说某个NFA只能识别标识符,对于数字123的识别无能为力,于是我们只能构建一个新的NFA对数字进行识别,一来二去我们就会产生许多的NFA。为了统一,我们可以把这么多的NFA合并在一起形成一个新的NFA。

  但是这些NFA统一起来会形成一个问题。

  见下图,如果有一个字符串abb,那么我们究竟是匹配住第二个模式还是第三个模式呢?所以在遇到这种情况的时候我们需要人为的设定另一种规则,即当某个字符串符合多个模式的时候我们应该遵循什么样的原则从这些个模式中选出最终的那个。(说白了就是有多个选手进入了决赛,但是第一名只能有一个,我们必须要有一个方法从这些人中角逐出第一名)
编译原理:词法分析概览_第2张图片
3.正则表达式->DFA
  1.根据正则构造语法树T
  2.计算得到T的nullable、firstpos、lastpos和followpos
  3.根据图3-62构造出D的状态集Dstates和D的转换函数Dtran

  针对3补充:
  图3-62中的“每个输入符号a”指的是以Dstates中的符号作为输入,  例如初始状态集合{1,2,3}有a和b两个字符,我们就以a和b作为输入;
  转换表示的是在某个状态下将其状态中的某个符号a输入之后这个状态会转换到哪些状态中去
  得出所有状态和所有转换函数后NFA图自然就被构造出来了
编译原理:词法分析概览_第3张图片

关于状态机的几个问题必须理清楚:
1.如何确定分析结束的时机?换句话说我们何时给出词素判断的结果是yes还是no?

  首先明确我们有两种状态结束的表示方式,一个是带*,另一个是不带星号。详见龙书3.4.1节。
  我们到达了一个接受状态并不是说判断就结束了,这次词素已经被识别出了yes。如下图所示,如果要匹配abb势必会经过{2,4,7}状态,但到达了这个状态并不表示我们的判断已经得出结论可以返回,事实上这个状态仍有后续转移状态,所以如果字符串输入没有停止我们必须继续判断。
编译原理:词法分析概览_第4张图片
  判断结束的标志有两个:
    1.所处状态为空状态
      这种发生情况为字符不断被输入,直至输入一个不能被模式匹配的字符。
      假设我们要在这个NFA中识别aaba字符串,当状态集接收第三个a后便会转入一个空状态集说明输入了一个不能被模式匹配的字符(这个空状态集没有在图3-52中标出,但它确实是存在),然后按照原来的路径回溯直至找到一个接收状态。
编译原理:词法分析概览_第5张图片
编译原理:词法分析概览_第6张图片
    2.字符串已经到达eof输入停止
      当输入字符为EOF时就说明我们已经读完了所有字符,这时候不应该继续进行状态转移,而是跳出循环针对现在所处状态进行分析,如果现在所处状态和接收状态集交集不为空则表示词素成功被匹配,反之失败。
      代码见下图
编译原理:词法分析概览_第7张图片

可能补充…

你可能感兴趣的:(编程语言,正则表达式,字符串)