DFANFA正则表达式三者都可以一一对应寻找。
结构化程序语言:
顺序、分支、循环
目前涉及到的都是结构化程序语言,非结构化程序语言不做要求。(非结构化转换成结构化再转换成正则表达式)
记住上面三种基本的转化方式即可,其余方式都是由以上的方式组合而成。
增加一个终止状态,所有原有的终止状态都有一个null输入转换为同一个终止状态,然后进行正则表达式的转换比较方便,这个时候每个输入之间就是“或”的关系。
a(ab|ba)a*b1.2 正则表达式到NFA(考点)
往回转换的话,给一个正则表达式,怎么构造自动机?
这个构造过程相当于一个逆过程,开始的时候是开始状态然后是表达式然后是终止状态。
注意一下循环的格式:2 在自己本身的同时前面和后面要有一个null输入和输出变成两个状态(其中的null可以改成其他字符)
如果不写成上述形式会出现如下问题:
【无法表示出或的关系】
- 如果只有一个状态的话:d*ab
- 如果按照上面两个状态的话:abd*
只有按照如下方法能保证自动机所能接收的串的集合和正则表达式相同(前后必须保证有null输入导致的两个状态)
(但是也不排除所有可能)
答题步骤:
- 转换成NFA
- NFA转换成DFA
- DFA最小化
前面学习了正则表达式和自动机,这两种工具都是作为描述词法的形式化工具,虽然说二者有其他的用途,但是在这里还是主要把他们作为描述单词来使用的,那么这两种工具之间有没有什么联系,即正则表达式和DFA之间的关系
词法分析器的工作过程
- 设计步骤
- 确定词法分析的接口
- 确定单词的结构
- 给出单词的描述
- 设计算法
首先根据词法描述(正则表达式)进行描述,将其转换成NFA然后进行转换和化简,通过上面的过程进行词法分析器的构建,然后将输入流的输入信息输入词法分析器进行处理得到token,也可能最后不符合词法分析器输出error。(使用switch-case语句/使用一个表格进行存储)
通过词法分析器的处理需要构造单词序列返回单词,那么这个返回的token应该包含哪些信息,只有确定了这个问题才能够来进行token的设计。
源程序的处理过程是,首先从源程序文件一个字符一个字符进行读取,并逐个分离出单词,然后构造它们的机内表示token;关于token的结构没有统一的规定,但至少要包括两部分内容:
(id,a)//单词的类型(语法信息)、单词的内容(语义信息,比如a是什么类型的标识符,在哪里声明的,生命周期如何)
以输入a为例:
开始输入a的时候标识符索引表是空的(首先在标识符索引表中查找a),开始输入的时候是一个新开始的程序,通过输入相应的标识符在标识符索引表中建立该程序所包含的全部标识符。
a->(1,1)//存储在1号表也就是标识符索引表中的第一个位置 b->(1,2)//下一个遇到的标识符是b,将b存储在标识符索引表的第二个位置 //每次先查对应类型的索引表中是否有,没有加入,有掠过 //前面的是单词的类型后面的是在每个类型中索引表里的位置程序的实现
和前面的一样,先有各种索引表,只不过标识符索引表和常量索引表是空的,这个时候如果输入的是标识符的话,首先查找保留字表(因为标识符的词法规则保留字也符合)是否是保留字,如果是将类型填入,再去保留字表中找到对应的存储位置再填入。如果不是保留字是标识符的话(常量同理),首先将当前的标识符的信息填入索引表,然后再根据索引表的信息构造token。
每一种不同的结束状态代表一种不同的字符对应不同的转化结果。
- 识别了名字要区分标识符和保留字,建保留字表或者在自动机上区分但是这种方法使用的不多;
- 第二个问题是复合单词的识别,即将其分开仍然是一个单词比如++,在处理的时候第一个终止状态后面仍然是一个终止状态,后面要继续读一下后续字符
- 向前看若干字符比如±某些语言中也有这种特殊的地方
- 数的转换,因为输入的是字符序列得到的是数所以有一个转换的过程
- 控制字符的处理,比如换行和空格,对程序的实际执行是没有意义的但是对于debug的时候很有作用;根据回车和换行构造记录行号来提醒如果出现错误在第几行的提示
- 注释的处理,遇到注释忽略



