C#词法分析器(五)转换 DFA

在上一篇文章中,已经得到了与正则表达式等价的 NFA,本篇文章会说明如何从 NFA 转换为 DFA,以及对 DFA 和字符类进行化简。

一、DFA 的表示

DFA 的表示与 NFA 比较类似,不过要简单的多,只需要一个添加新状态的方法即可。Dfa 类的代码如下所示:

namespace Cyjb.Compilers.Lexers {
    class Dfa : IList<DfaState> {
        // 在当前 DFA 中创建一个新状态。
        DfaState NewState() {}
    }
}

DFA 的状态也比较简单,必要的属性只有两个:符号索引和状态转移。

符号索引表示当前的接受状态对应的是哪个正则表达式。不过 DFA 的一个状态可能对应于 NFA 的多个状态(详见下面的子集构造法),所以 DFA 状态的符号索引是一个数组。对于普通状态,符号索引是空数组。

状态转移表示如何从当前状态转移到下一状态,由于在构造 NFA 时已经划分好了字符类,所以在 DFA 中直接使用数组记录下不同字符类对应的转移(DFA 中是不存在 转移的,而且对每个字符类有且只有一条转移)。

在 NFA 的状态定义中,还有一个状态类型属性,但是在 DFA 状态中却没有这个属性,是因为 Trailing 类型的状态会在 DFA 匹配字符串的时候处理(会在下篇文章中说明),TrailingHead 类型的状态会在构造 DFA 的时候与 Normal 类型的状态合并(详见 2.4 节)。

下面是 DfaState 类的定义:

namespace Cyjb.Compilers.Lexers {
    class DfaState {
        // 获取包含当前状态的 DFA。
        Dfa Dfa { get; private set; }
        // 获取或设置当前状态的索引。
        int Index { get; set; }
        // 获取或设置当前状态的符号索引。
        int[] SymbolIndex { get; set; }
        // 获取或设置特定字符类转移到的状态。
        DfaState this[int charClass] { get; set; }
    }
}

DFA 的状态中额外定义的两个属性 Dfa 和 Index 同样是为了方便状态的使用。

二、NFA 转换为 DFA

2.1 子集构造法

将 NFA 转换为 DFA,采用的是子集构造(subset construction)算法。该算法的过程与《C# 词法分析器(三)正则表达式》的 3.1 节中提到的 NFA 匹配过程比较相似。在 NFA 的匹配过程中,使用的都是 NFA 的一个状态集合,那么子集构造法就是用 DFA 的一个状态来对应 NFA 的一个状态集合,即 DFA 读入输入字符串 a1a2an 之后到达的状态,就对应于 NFA 读入同样的字符串 a1a2an 之后到达的状态的集合。

子集构造算法需要用到的操作有:

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索正则表达式
, 词法分析器
, 状态
, 数组匹配算法数组
, 构造器集合c#
, c# 算法 真子集
, 一个
, C#数组应用分析
, 转移
, NFA
子集
c站、c语言、cf、ch、c罗,以便于您获取更多的相关知识。

时间: 2024-10-30 08:33:15

C#词法分析器(五)转换 DFA的相关文章

ORACLE常用数值函数、转换函数、字符串函数_oracle

本文更多将会介绍三思在日常中经常会用到的,或者虽然很少用到,但是感觉挺有意思的一些函数.分二类介绍,分别是: 著名函数篇 -经常用到的函数 非著名函数篇-即虽然很少用到,但某些情况下却很实用 注:N表示数字型,C表示字符型,D表示日期型,[]表示内中参数可被忽略,fmt表示格式. 单值函数在查询中返回单个值,可被应用到select,where子句,start with以及connect by 子句和having子句. (一).数值型函数(Number Functions) 数值型函数输入数字型参

oracle常用函数汇总

以下是对oracle中的常用函数进行了汇总介绍,需要的朋友可以过来参考下   一.运算符算术运算符:+ - * / 可以在select 语句中使用 连接运算符:|| select deptno|| dname from dept; 比较运算符:> >= = != < <= like between is null in 逻辑运算符:not and or 集合运算符: intersect ,union, union all, minus 要求:对应集合的列数和数据类型相同     

oracle数据库常用日期函数讲解

调用日期函数时,首先要明确两个概念,时间戳和日期是不同的,日期中包括年月日但不包括小时分钟秒,时间戳包括年月日小时分钟秒.在oracle中,一般情况下,函数中包含date字符的和日期有关,包含timestamp的函数和时间戳有关(时间戳可以理解为时间).oracle中,日期一般以天为基本单位,时间相减时结果单位为天,时间与数字相加时,默认加对应数字的天数. 一.调用时无参无括号时间函数 1.返回系统当前日期sysdate --该函数返回值没有时间戳 select sysdate from dua

oracle数据库函数使用方法总结

函数的作用是计算一个功能,往往是用来计算并返回一个计算结果. 1.函数和存储过程的区别: 1)函数和过程比较类似,不同的是函数必须返回一个值,而过程仅是为了执行一系列的操作. 2)在调用的时候,函数可以作为表达式的一部分进行调用,并且可以使用在SELECT中.而过程只能作为一个PL/SQL语句进行调用,且不能在SELECT语句中使用. 3)函数的语法结构和过程比较类似,除了函数使用FUNCTION进行定义之外.外一个重要的特点就是,函数具有RETURN子句,指定函数的返回类型. 4)函数和存储过

oracle常用函数汇总(分享)_oracle

一.运算符算术运算符:+ - * / 可以在select 语句中使用连接运算符:|| select deptno|| dname from dept; 比较运算符:> >= = != < <= like between is null in逻辑运算符:not and or 集合运算符: intersect ,union, union all, minus 要求:对应集合的列数和数据类型相同     查询中不能包含long 列     列的标签是第一个集合的标签     使用orde

深蓝词库转换2.0发布——支持仓颉、注音、五笔、郑码、二笔等

经过了2个多月的改进,终于深蓝词库转换2.0版正式与大家见面了.在1.9版本中增加了对Rime拼音输入法的支持,也得到了网友的反馈,所以在2.0版本中增加了几个新功能: 一.支持多种编码的Rime输入法. Rime输入法是一款跨平台的输入法框架,在Windows下叫小狼毫,Linux下叫中州韵,Mac下叫鼠须管.这个输入法框架异常强大,支持各种常用的输入法,而且还可以通过简单的配置自定义输入法.深蓝词库转换在1.9版本中增加了对Rime拼音输入法的支持,现在在2.0中进行了增强,除了拼音外,还能

Java技术 汉字转换成拼音简码 和 汉字转换成五笔简码

问题描述 Java技术汉字转换成拼音简码和汉字转换成五笔简码例如输入:侃侃拼音简码:KK五笔码:WW有写好的类最好 解决方案 解决方案二:拼音的话网上有写好的包,五笔还是算了,没发现过解决方案三:这样都可以啊??学习中解决方案四:有些繁体拼音也不可以显示

分享非常有用的Java程序 (关键代码)(五)---把 Array 转换成 Map

原文:分享非常有用的Java程序 (关键代码)(五)---把 Array 转换成 Map  import java.util.Map; import org.apache.commons.lang.ArrayUtils; public class Main { public static void main(String[] args) { String[][] countries = { { "United States", "New York" }, { &qu

Java IO流学习总结五:转换流-InputStreamReader、OutputStreamWriter

Java IO流学习总结五:转换流-InputStreamReader.OutputStreamWriter 转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/54923506 本文出自[赵彦军的博客] 类的继承关系 Reader |__ BufferedReader.StringReader.InputStreamReader |__ FileReader Writer |__ BufferedWriter.StringWrite