`
cwsot
  • 浏览: 14782 次
  • 性别: Icon_minigender_2
  • 来自: 大连
最近访客 更多访客>>
社区版块
存档分类
最新评论

有限状态机实现正则表达式

阅读更多

  最近在写语法分析东西。遇到了不是难题,也学到了不是东西。和大家分享一下
  1.语法分析最笨的办法就是对应位置的对应关键字匹配(模式匹配),这个东西最简单,也最容易实现,这个就是所谓的穷举发。
  今天我肯定不是来和大家说模式匹配,这个也没有必要说。
  今天,最成熟的语法分析利器还要算正则表达式了,用户只需要些一些简单的语法,就可以匹配和分析出自己需要的东西。
  但是,没有几人知道正则表达式的实现原理(在搜索的时候,基本没有发现将实现原理的)。
  在大学时代,只要你是学计算机的,应该知道有一门课叫编译原理的,主要就是将语法分析的(我自己也些过几次语法分析器,但时间太久了,全都忘了),我就猜测,正则表达式的实现原理是不是有限状态机。
  我查看c和java的源代码,发现他的解析器就是采用的有限状态机实现。
  所以我在网上找到一篇很不错的文章: 正则表达式可以用来:
  (1)验证字符串是否符合指定特征,比如验证是否是合法的邮件地址。
  (2)用来查找字符串,从一个长的文本中查找符合指定特征的字符串,比查找固定字符串更加灵活方便。
  (3)用来替换,比普通的替换更强大。
  对于一个正则表达式一般有2种方式,以JS为例
  其一为使用正则表达式文字常量:
  var re = /^[Jj]ava[Ss]cript/i;
  其二为使用RegExp构造函数:
  var re = new RegExp("^[Jj]ava[Ss]cript","i");
  而一个正则表达式解释器主要有3部分组成,分别是解析(parse)、编译(compile)与执行(execute)。
  1 解析
  正则的表达式的词法与语法比较简单,基本语法如下:
  A)普通字符和元字符
  普通字符是那些表示自身的字符,例如从a到z,A到Z,0到9等;
  元字符具有特殊意义,如'.',表示除了'\n'外的所有字符,其他具有此功能的有
  表1 元字符 元字符 特殊意义 ^ 匹配输入字符串的开始位置。要匹配 "^" 字符本身,请使用 "\^" $ 匹配输入字符串的结尾位置。要匹配 "$" 字符本身,请使用 "\$" . 匹配除了换行符(\n)以外的任意一个字符。要匹配小数点本身,请使用 "\." * 修饰匹配次数为 0 次或任意次。要匹配 "*" 字符本身,请使用 "\*" + 修饰匹配次数为至少 1 次。要匹配"+" 字符本身,请使用 "\+" ? 修饰匹配次数为 0 次或 1 次。要匹配 "?" 字符本身,请使用 "\?" = 用于前向引用或向后引用 ! 用于前向引用或向后引用 : 用于前向引用或向后引用 | 用于前向引用或向后引用 \ 转义用 / 用于前向引用或向后引用 () 标记一个子表达式的开始和结束位置。要匹配小括号,请使用 "\(" 和 "\)" [] 用来自定义能够匹配 '多种字符' 的表达式。要匹配中括号,请使用"\[" 和 "\]" {} 修饰匹配次数的符号。要匹配大括号,请使用 "\{" 和 "\}" 元数据如要表示自身,那么需要用'\'来辅助转义
  B)字符类
  单个的字符可以组成字符类,其语法为用'['与']'组成,例如[abcA-Z79]表示可以匹配a,b,c与A到Z,7,9的字符
  其中'-'为连字符,表示字符的跨度。
  '^'在"[]"间也是特殊字符,表示取反
  其他的特殊字符如下表:
  表2 字符类中的预定义字符类 预定义字符类 特殊意义 ^ 在紧跟'['表示取反,表示自身要转义 - 在字符间,表示连字符,如要表示自身,须紧接在'['或'[^'之后 . 小数点可以匹配除了换行符(\n)以外的任意一个字符 \d 可以匹配任何一个 0~9 数字字符 \D D大写,可以匹配任何一个非数字字符 \s 可以匹配空格、制表符、换页符等空白字符的其中任意一个 \S S大写,可以匹配任何一个空白字符以外的字符 \w 可以匹配任何一个字母或者数字或者下划线 \W W大写,可以匹配任何一个字母或者数字或者下划线以外的字符 JavaScript无POSIX格式
  C)限定符(重复)
  限定符有2种形式,分别为'*','+','?'与' {'与'}'来表示
  表3 限定符 限定符 特殊意义 * 表达式尽可能的多匹配,最少可以不匹配,相当于 {0, } + 表达式尽可能的多匹配,至少匹配1次,相当于 {1, } ? 表达式尽可能匹配1次,也可以不匹配,相当于 {0, 1} {m,n} 表达式尽可能重复n次,至少重复m次:"ba{1,3}"可以匹配 "ba"或"baa"或"baaa" {m} 表达式固定重m次,比如:"\w{2}" 相当于 "\w\w" {m,} 表达式尽可能的多匹配,至少重复m次:"\w\d{2,}"可以匹配 "a12","x456"...   在正则中有贪婪与非贪婪之分,默认的情况下,正则是贪婪的
  如果要把正则设置为非贪婪有2种方式,一种为设置在原先的限定符加上'?'就行,另一种在设置
  举例说明,/.+/ 将匹配"abdddd"中的所有字符,/.+?/ 只将匹配"abdddd"中的第一个a,也就是默认的尽可能多的匹配字符,而非贪婪重复则尽可能上的匹配。
  D)选择、分组和引用
  选择的语法就是设置'|',如a|bc,那么要么a或bc都可以匹配,如果(a|b)c则为匹配ac或bc。
  如果我们在上例中设置了"()",那么这就是分组,每个分组都可以被引用,如(a|b)c*(e|f)\1\2,\1与\2就是引用的语法,\1表示引用了(a|b),\2表示引用(e|f),以此类推。
  这里要说明的是(a|b)c*(e|f)\1\2与(a|b)c*(e|f)(a|b)(e|f)乍一看两者等同,但实际上,前一个不可以匹配acebf,而后一个可以。究其原因就是引用处的配平必须与被引用处一致,此例中与之匹配的可以是aceac。
  E)定位符(锚)和前向引用
  定位符如下表所示
  表4 定位符 限定符 特殊意义 ^ 匹配输入字符串的开始位置。要匹配 "^" 字符本身 $ 匹配输入字符串的结尾位置。要匹配 "$" 字符本身 ? 表达式尽可能匹配1次,也可以不匹配,相当于 {0, 1} \b 匹配单词边界,例如一个\w和\W的位置,或者一个\w与字符串的开始和结尾的位置 \B 和上面的想法,匹配一个非单词边界 如果正则表达式的匹配模式为 MULTILINE 模式,^ 可匹配一行文本的行首,$ 可匹配一行文本的行末。当 \b 被包含于字符集合中时,\b 代表退格符(ASCII码 = 8)。
  除了这些预定义的定位符,还可以自定义定位符,这种类型的定位符叫做前向引用(look-ahead anchor)和后向引用(look-behind anchor,JavaScript不支持)。
  前向引用使用(?=…)表示正的前向引用,(?!…)表示负的前向引用下面是一个前向引用的例子 /Java(?!Script)([A-Z]\w*)/ 其中(?!Script)匹配后面不跟Script的位置,而(?=Script)匹配后面是Script的位置。
  以上讲解了JavaScript的语法规则,下面我们来论述一下解析的过程。
  解析的过程是语法分析(Lexical Analysis)与词法分析(Grammar Analysis)。
  2 编译
  编译(Compile)阶段,主要的工作就是生成字节流(Emit Byte Code)。而生成Byte Code的算法(规则)JS中就是NFA。生成的Byte Code是归于执行(Execute)时做匹配利用。各个状态即为正则中的语义(OPCODE)的表示,各个OPCODE以一定的格式与关系住成了状态机,JS中是组成NFA的状态机。
  下面介绍下在流行的两种算法NFA(Nondeterministic Finite Automaton)与DFA(Deterministic Finite automaton),Perl,Python,JS等都是NFA的,而awk与grep等用的是DFA,两种算法的具体实现如下:
  1)有限状态机(Finite Automation)
  状态机是一个有一组不同状态的集合的系统。有一个特殊状态
分享到:
评论

相关推荐

    正则表达式转换为NFA(Regex to NFA).jar

    用JAVA写的一个将正则表达式转换为NFA的代码,基于Thompson算法的思想,...输出非确定有限自动状态机的有向图。如正则表达式: c(a|b)NFA为:0-c->1-ep->2-a->3-ep->7 ,0-c->1-ep->4-b->5-ep->7.其中 ep 表示 epsilon

    cpp-RE2一个正则表达式的软件库通过一个有限状态机使用自动机理论实现

    RE2 - 一个正则表达式的软件库,通过一个有限状态机使用自动机理论实现

    Regex:Java中简单,快速的正则表达式匹配器

    然后将后缀表示法解析为不确定的有限自动机(NFA),这是一种花哨的状态机,每个状态最多具有两个分支。 然后在状态机中模拟给定的字符串。 所有可能的下一个状态同时被“继续”。 在输入的末尾,如果我们处于的...

    FiniteAutomata:该项目提供了一种构建非确定性有限自动机的方法,应用正则表达式

    这是一个库,允许您构建、运行和查看表示基本正则表达式的有限状态机。 这绝对不是测试正则表达式的最有效方法,不应在实际项目中使用,但这更多的是一种理论练习,并提供了一种匹配正则表达式的强大方法。 该项目...

    re2-windows平台-DFA全状态匹配单模模式-GPU移植主机版

    正则表达式引擎re2。已进行windows平台移植,可以直接在windows上运行。匹配方式由原来的以便执行匹配以便建立对应的DFA状态,当匹配时就返回成功,而DFA并没有完全建立。改变为先建立完整的DFA转移矩阵,再进行匹配...

    编译原理(翻译版)

    2.2.3 程序设计语言记号的正则表达式 29 2.3 有穷自动机 32 2.3.1 确定性有穷自动机的定义 32 2.3.2 先行、回溯和非确定性自动机 36 2.3.3 用代码实现有穷自动机 41 2.4 从正则表达式到DFA 45 2.4.1 从正则...

    计 算 机 专 业 英 语

    计 算 机 专 业 英 语计 算 机 专 业 英 语

    编译原理及实践 Kenneth C.Louden 冯博琴

    32 2.3.2 先行、回溯和非确定性自动机 36 2.3.3 用代码实现有穷自动机 41 2.4 从正则表达式到DFA 45 2.4.1 从正则表达式到NFA 45 2.4.2 从NFA到DFA 48 2.4.3 利用子集构造模拟NFA 50 2.4.4 将DFA中的状态数最小化 ...

    Ragel有限状态机编译器 - win32bin

    Ragel是个有限状态机编译器,它将基于正则表达式的状态机编译成传统语言(C,C++,D,Java,Ruby等)的解析器。Ragel不仅仅可以用来解析字节流,它实际上可以解析任何可以用正则表达式表达出来的内容。而且可以很...

    Delphi算法与数据结构 源码(上)

    不仅如此,作者还介绍了散列和散列表、优先队列、状态机和正则表达式以及诸如哈夫曼和LZ77等数据压缩技术。 随附光盘中有作者所开发的一个相当成功的自由软件库EZDSL,另外还有可运行于各版本Delphi上和Kylix上的源...

    Delphi算法与数据结构 源码(下)

    不仅如此,作者还介绍了散列和散列表、优先队列、状态机和正则表达式以及诸如哈夫曼和LZ77等数据压缩技术。 随附光盘中有作者所开发的一个相当成功的自由软件库EZDSL,另外还有可运行于各版本Delphi上和Kylix上的源...

    rex:确定性有限状态机的DSL

    理论背景从数学的角度来看,正则表达式存在以下问题: 正则表达式很容易转换为非确定性有限自动机(NFA),而计算机只能执行确定性有限状态机(DFA)。 两者在数学上是等效的,可以相互转换,但要付出一定的代价:要...

    编译原理-词法分析-基于状态机的简单动态词法分析器

    简单的词法分析器,能够接收一系列不同的正则变量定义,通过正则表达式后缀式的构建、nfa的构建、dfa的构建及其最简化、dfa的合并等步骤实现动态词法分析。

    北航计组P0-Logisim简单部件与状态机

    使用Logisim搭建一个除数为四位,原数据帧为8位的CRC校验码计算电路;一个四位运算单元ALU;一个GRF;一个Melay型有限状态机 检测串行输入字符串中的能匹配正则表达式b{1,2}[ac]{2}的子串并输出。

    DFA.rar_DFA java

    用java语言实现有穷自动状态机,译码正则表达式。

    ragel 状态机

    Ragel是个有限状态机编译器,它将基于正则表达式的状态机编译成传统语言(C,C++,D,Java,Ruby等)的解析器。

    2020最新南开大学编译原理期末复习知识点总结

    吐血整理,老师上课的全部知识,34页全部罗列:程序设计语言,状态图,有限状态机,词法分析,正则表达式,Thompson构造法,上下文无关文法预测分析表,FIRST集:所有产生式右边的第一个终结符 FOLLOW集。。。若文法...

    lexerific:一个基于底层有限状态机的简单流标记器

    一个基于有限状态机简单流标记器。 它实现了 Node.js ,使处理文件和流水线变得容易(因此在 I/O 受限的环境中可以以高效率进行多个并行词法分析)。 词法分析器支持基于字符串的标记化(通过逐个字符处理模式)。 ...

    android智能电视软件测试

    针对智能电视黑盒测试,先构造状态机,生成正则表达式,据此生成测试用例。

    Ragel User Guide

    Ragel是个有限状态机编译器,它将基于正则表达式的状态机编译成传统语言(C,C++,D,Java,Ruby等)的解析器。Ragel不仅仅可以用来解析字节流,它实际上可以解析任何可以用正则表达式表达出来的内容。而且可以很...

Global site tag (gtag.js) - Google Analytics