C#词法分析器(四)构造 NFA

有了上一节中得到的正则表达式,那么就可以用来构造 NFA 了。NFA 可以很容易的从正则表达式转换而来,也有助于理解正则表达式表示的模式。

一、NFA 的表示方法

在这里,一个 NFA 至少具有两个状态:首状态和尾状态,如图 1 所示,正则表达式 t 对应的 NFA 是 N(t),它的首状态是 H,尾状态是 T。图中仅仅画出了首尾两个状态,其它的状态和状态间的转移都没有表示出来,这是因为在下面介绍的递归算法中,仅需要知道 NFA 的首尾状态,其它的信息并不需要关心。

图 1 NFA 的表示

我使用下面的 Nfa 类来表示一个 NFA,只包含首状态、尾状态和一个添加新状态的方法。

namespace Cyjb.Compilers.Lexers {
    class Nfa : IList<NfaState> {
        // 获取或设置 NFA 的首状态。
        NfaState HeadState { get; set; }
        // 获取或设置 NFA 的尾状态。
        NfaState TailState { get; set; }
        // 在当前 NFA 中创建一个新状态。
        NfaState NewState() {}
    }
}

NFA 的状态中,必要的属性只有三个:符号索引、状态转移和状态类型。只有接受状态的符号索引才有意义,它表示当前的接受状态对应的是哪个正则表达式,对于其它状态,都会被设为 -1。

状态转移表示如何从当前状态转移到下一状态,虽然 NFA 的定义中,每个节点都可能包含多个 $\epsilon$转移和多个字符转移(就是边上标有字符的转移)。但在这里,字符转移至多有一个,这是由之后给出的 NFA 构造算法的特点所决定的。

状态类型则是为了支持向前看符号而定义的,它可能是 Normal、TrailingHead 和 Trailing 三个枚举值之一,这个属性将在处理向前看符号的部分详细说明。

下面是 NfaState 类的定义:

namespace Cyjb.Compilers.Lexers {
    class NfaState {
        // 获取包含当前状态的 NFA。
        Nfa Nfa;
        // 获取当前状态的索引。
        int Index;
        // 获取或设置当前状态的符号索引。
        int SymbolIndex;
        // 获取或设置当前状态的类型。
        NfaStateType StateType;
        // 获取字符类的转移对应的字符类列表。
        ISet<int> CharClassTransition;
        // 获取字符类转移的目标状态。
        NfaState CharClassTarget;
        // 获取  转移的集合。
        IList<NfaState> EpsilonTransitions;
        // 添加一个到特定状态的转移。
        void Add(NfaState state, char ch);
        // 添加一个到特定状态的转移。
        void Add(NfaState state, string charClass);
        // 添加一个到特定状态的ε转移。
        void Add(NfaState state);
    }
}

我在 NfaState 类中额外定义的两个属性 Nfa 和 Index 单纯是为了方便状态的使用。$\epsilon$ 转移直接被定义为一个列表,而字符转移则被定义为两个属性:CharClassTarget 和 CharClassTransition,CharClassTarget 表示目标状态,CharClassTransition 表示字符类,字符类会在下面详细解释。

NfaState 类中还定义了三个 Add 方法,分别是用来添加单个字符的转移、字符类的转移和 $\epsilon$ 转移的。

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

时间: 2024-11-02 00:51:27

C#词法分析器(四)构造 NFA的相关文章

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

在上一篇文章中,已经得到了与正则表达式等价的 NFA,本篇文章会说明如何从 NFA 转换为 DFA,以及对 DFA 和字符类进行化简. 一.DFA 的表示 DFA 的表示与 NFA 比较类似,不过要简单的多,只需要一个添加新状态的方法即可.Dfa 类的代码如下所示: namespace Cyjb.Compilers.Lexers { class Dfa : IList<DfaState> { // 在当前 DFA 中创建一个新状态. DfaState NewState() {} } } DFA

《编译与反编译技术实战 》一3.2 词法分析器的手工实现

3.2 词法分析器的手工实现 手工构造词法分析器首先需要将描述单词符号的正规文法或者正规式转化为状态转换图,然后再依据状态转换图进行词法分析器的构造.状态转换图是一个有限方向图,结点代表状态,用圆圈表示:状态之间用箭弧连接,箭弧上的标记(字符)代表射出结点状态下可能出现的输入字符或字符类.一张转换图只包含有限个状态,其中有一个为初态,至少要有一个终态(用双圈表示).大多数程序语言的单词符号都可以用状态转换图予以识别.具体过程如下: 1)从初始状态出发. 2)读入一个字符. 3)按当前字符转入下一

《编译与反编译技术实战》——3.2节词法分析器的手工实现

3.2 词法分析器的手工实现 手工构造词法分析器首先需要将描述单词符号的正规文法或者正规式转化为状态转换图,然后再依据状态转换图进行词法分析器的构造.状态转换图是一个有限方向图,结点代表状态,用圆圈表示:状态之间用箭弧连接,箭弧上的标记(字符)代表射出结点状态下可能出现的输入字符或字符类.一张转换图只包含有限个状态,其中有一个为初态,至少要有一个终态(用双圈表示).大多数程序语言的单词符号都可以用状态转换图予以识别.具体过程如下: 1)从初始状态出发. 2)读入一个字符. 3)按当前字符转入下一

用Ruby写了个NFA

今天有点空闲,想想用Ruby写个NFA试试.从正则表达式构造NFA采用经典的Thompson算法:正则表达式 -> 后缀表达式 -> 构造NFA.构造了NFA后,用之匹配字符串.一句话,写了个玩具的正则表达式引擎,支持concatenation.alternation以及*.?.+量词,不支持反向引用和转义符.测试了下与Ruby自带的正则表达式引擎的性能对比,慢了3倍.构造NFA没什么问题,主要是匹配运行写的烂,有空再改改. nfa.rb module NFA   class NFA     

《编译与反编译技术实战》——第3章 词法分析器的设计与实现 3.1 词法分析器的设计

第3章 词法分析器的设计与实现 词法分析是编译过程的第一步,也是编译过程必不可少的步骤.编译过程中执行词法分析的程序称为词法分析器.构造词法分析器有两种方法:一种是用手工方式,即根据识别语言的状态转换图,使用某种高级语言直接编写词法分析器:另一种是利用自动生成工具(如LEX)自动生成词法分析器.本章分别介绍如何手动和自动构造词法分析器. 3.1 词法分析器的设计 本节首先介绍词法分析器的功能及其输出的单词符号的表示方式,然后介绍其输入和处理. 3.1.1 词法分析器的功能 词法分析器又叫作扫描器

《编译与反编译技术实战》——第3章词法分析器的设计与实现

第3章词法分析器的设计与实现词法分析是编译过程的第一步,也是编译过程必不可少的步骤.编译过程中执行词法分析的程序称为词法分析器.构造词法分析器有两种方法:一种是用手工方式,即根据识别语言的状态转换图,使用某种高级语言直接编写词法分析器:另一种是利用自动生成工具(如LEX)自动生成词法分析器.本章分别介绍如何手动和自动构造词法分析器.

《编译与反编译技术》—第2章2.2词法分析器的设计

本节书摘来自华章出版社<编译与反编译技术>一书中的第2章,第2.2节词法分析器的设计,作者庞建民,陶红伟,刘晓楠,岳峰,更多章节内容可以访问"华章计算机"公众号查看. 2.2 词法分析器的设计 下面将词法分析器作为一个独立的子程序来考虑其设计.本节主要探讨实现词法分析器的关键技术和词法分析器的手工实现. 2.2.1 输入及其处理 词法分析器的结构如图2-3所示.词法分析器首先将源程序文本输入一个缓冲区中,该缓冲区称为输入缓冲区,单词符号的识别可以直接在输入缓冲区中进行.但在

《编译与反编译技术实战》——3.2 词法分析器的手工实现

3.2 词法分析器的手工实现 手工构造词法分析器首先需要将描述单词符号的正规文法或者正规式转化为状态转换图,然后再依据状态转换图进行词法分析器的构造.状态转换图是一个有限方向图,结点代表状态,用圆圈表示:状态之间用箭弧连接,箭弧上的标记(字符)代表射出结点状态下可能出现的输入字符或字符类.一张转换图只包含有限个状态,其中有一个为初态,至少要有一个终态(用双圈表示).大多数程序语言的单词符号都可以用状态转换图予以识别.具体过程如下: 1)从初始状态出发. 2)读入一个字符. 3)按当前字符转入下一

编译原理之正则表达式转NFA

本文转载自http://chriszz.sinaapp.com/?p=257 输入一个正则表达式,输出一个NFA. 我的做法:输入一个字符串表示正则,输出则是把输出到一个.dot文件中并将dot文件编译成pdf,fedora需要sudo yum install dot,然后evince XXX.pdf就可以查看生成的NFA了. 具体算法是按照龙书上的Tompson算法来的. 废话不多说,放码过来: /* Author:ChrisZZ(zchrissirhcz@gmail.com) Time:20