tn是desert和tan共同开发的一种用于匹配,转写和抽取文本的语言。解释器使用Python实现,代码不超过1000行。

本文主要介绍tn的基本语法。高级内容可以参考其他篇章。使用这样的语法,是为了实现语言无关,从而方便地编写不同语言的解释器。

基本语法

引擎可以由一组规则构成,规则也可以被其他规则所组合。首先介绍最基本的元规则 。

1. 字符串StringEntity

Form2: ("Matched string" : "Rewritten string")

Form1是一种省略表达,即Rewritten==Matched

样例:

("" : " ") # 在指定的地方插入一个空格
("kg" : "kilogram") # 将 "kg" 或 "Kg" 扩展成 "kilogram"

2. 正则表达式RegexEntity

Form1: (/Matched expression/)
Form2: (/Matched expression/ : /Rewritten expression/)

样例:

(/\s+/ : / /) \#将一串连续的空格与换行符合并为一个空格
(/(\d+)\s?(-|~)\s?(\d+)/ : /$1 to $3/) #将 "15~20 dollars" 改写成 "15 to 20 dollars"

将用Matched匹配到字符串替换成Rewritten所表示的字符串。这里的正则表达式符合Perl正则规范。Form1只能作为匹配规则而不能作为转写规则,如果Rewritten为空,则只匹配不转写。Rewritten并不是真正的正则表达式,它仅支持普通字符串与$1, $2, ..., $99,$n 表示Matched expression匹配到的第n个Entity。

3. 脚本表达式 ScriptEntity

可以在文法中嵌入脚本,具体的语法规则由引擎所决定,目前可以嵌入Python。(详情可参考高级语法)


其他各类表达式,都是由这三类表达式进行组合得到的。它们的并(或操作),连接和差操作,构成了以下三类复合实体。这三种操作与正则表达式的三类基本操作一致。

表达式需要被其他表达式引用时,就需要为其命名,例如:

entity= (/\s+/ : / /) ;

这样就表达了一个名称为entity的字符串表达式。名称与c语言的变量命名规则一致。中间由=连接。最后由分号结束。

当引用其他表达式时,可以用$(RuleName)表达。


4. 或表达式 TableEntity

Form: Table_name =Entity1 | Entity2 | …

样例:

digit_0_to_9 = ("0" : "nol") | ("1" : "satu") | ("2" : "dua") | ("3" : "tiga") | ("4" : "empat") | ("5" : "lima") | ("6" : "enam") | ("7" : "tujuh") | ("8" : "delapan") | ("9" : "sembilan"); #印尼语数字 0~9 的Map 表
integer_int_extend = $(integer_int) | ("百" : "100") | ("千" : "1000") | ("万" : "10000") | ("亿" : "100000000");

integer_int_extend规则就是由integer_int和其他四个StringEntity构成的。

或表达式中间的分隔符有两种,竖线|和斜杠/。 以竖线分割的实体是平级的,会对每一个子表达式进行匹配,找出离字符串起始位置最近且匹配到的字符串最长的那个子表达式。而以斜杠分割的实体,被看做一组(Group),一旦匹配,就不会匹配之后的表达式。可以在表达式中指定多个组合平级实体。

看下面的例子:

grouptest= (/CD/) | (/ABC/) / (/AB/) | (/ABCD/);

该规则分成了两组,在匹配ABCD时,前一组已经匹配了ABC,因此就不会继续向后匹配到ABCD。因此该规则最终匹配的结果是ABC.

5. 序列表达式 SequenceEntity

序列表达式描述了表达式的连接。序列从左到右依次匹配,一旦出现不能匹配的情况,则整个序列匹配失败。注意,序列匹配的字符串必须是相邻的。

integer_0_to_99 = $(integer_0_to_9) | $(integer_teens)
| $(integer_decades) $(del_0)
| $(integer_decades) $(ins_space) $(integer_1_to_9) $(ins_space);

这个表达式实际上是一个TableEntity,后两个子表达式是SequenceEntity。该表达式可以转写0~99范围内的整数。

匹配211时它首先用第一个integer_0_to_9能匹配到 '2',再用第二个integer_teens能匹配到 "11",再用第三个表达式匹配失败,再用第四个Sequence能匹配到 "21",最终选择离起点最近且匹配到的字符串最长的那一个进行转写:

211 :twenty one

序列表达式可以完成转写和顺序调整。例如:

fraction = $(integer_int_extend) $(fraction_cnv_slash) $(integer_int) : $3 $2 $1

三分之一转写为1/3,integer_int_extend可以匹配‘三’, fraction_cnv_slash可匹配 '分之' , integer_int可匹配'一'。 $3 $2 $1 对其顺序进行了重排。

6.重复表达式RepeatEntity

Form1: Repetition_name = $(an_entity)+;
Form2: Repetition_name = $(an_entity){m,n};

由一条需要重复的规则、要重复的次数以及结尾的分号组成。需要重复的规则有且仅有一条。所以不能写成

error_example= $(an_entity0) $(an_entity){m,n};

m到n次,m是≥0的整数,n是≥0的整数或-1,为-1时表示不限制重复次数。

这与正则表达式的规则基本一致。

7.差集表达式DiffEntity

Form1: Difference_name = $(Universe) - $(complement);
Form2: Difference_name = $(Universe) - $(complement1) - $(complement2) - …;

由一组Complement以及结尾的分号组成。有且仅有一个Universe,后面用减号可以跟多个表达式。

当Universe表达式能匹配且其他complement不能匹配时成立。例如:

integer_1_to_9 = $(integer_0_to_9) - ("0" : "nol"); # 整数1~9
integer_2_to_999 = $(integer_0_to_999) - $(digit_1) - $(digit_0); # 整数2~999

8. 元标签

可以为表达式增加标签,控制表达式的属性和功能。也可以引入规则等。

文件级元标签:

文件级元标签,不需要贴在任何规则之上。

#%Include% Rules/cnext

增加一个名称为cnext的外置文件。本文件中的规则即可引用该文件中的规则。支持双向引用。

#%Script% extends

增加一个名称为extends.py的外置Python脚本。该标签适合在嵌入Python代码时使用。嵌入的代码可以执行外置脚本中定义的函数。引擎会在内部执行import(extends)函数。因此extends.py需要放置在规则文件同一级目录中。

规则级元标签:

规则级元标签需要放在规则文本行之上,如:

#%Type% INT
#%Order% 180
int_0_4= $(int_0) | $(int_1) | $(int_2) | ("三" : "3") | ("四" : "4") ;

上面的两个标签意思分别为:

将int_0_4的类型标记为INT

将int_0_4的匹配优先级定义为140. 数字越大,优先级越低。

不是所有的规则都是有效规则,有些规则只是被其他规则引用。只有加上#%Order%标签的才是有效规则。规则可以手动编写优先级。也可以省略之后的数字,引擎会自动根据引用结构来制定优先级,被引用层级越高的优先级越高。

#%Parameter% 为规则赋值

这部分取决于引擎的设计,将在《高级话题》中描述。

属性级元标签

在信息抽取时,属性元标签非常重要,它指定了引擎如何将文本转换为字典。

案例1

#%Property% Denominator,,Numerator| Numerator ,, Denominator | Denominator ,, Numerator
fraction = $(integer_int_extend) $(fraction_cnv_slash) $(integer_int) : $3 $2 $1 | $(integer_int) $(fraction2) $(integer_int) | $(pure_decimal) ("" : "/") $(percent_transform);

属性标签为fraction的每一个引用实体增加了属性。 按照 '|' 分组,Denominator赋给integer_int_extend, Numerator赋给integer_int. 分别代表分子和分母。

案例2

当抽取类似JSON或XML的文本时,抽取的字典需要以键值对的形式标注,如下例子:

#%Property% ,$key,,$value
properties =$(space) $(name) $(equal) $(property) $(space);

则在抽取时,会以name为键,property为value, 插入抽取的字典中。


9.注意事项

注释

除了符合元标签格式的文本,以 # 开始的一行内容被认为是注释行被忽略。暂不支持在一行内容的中间或后面加注释,也不支持在某一规则的多行内容的中间插入一行注释。

换行

当Rule内容特别长时可以直接换行,中间插入的换行符/空格/制表符会被忽略,但不支持在中间插入注释行。

结束符

所有Rules都要以分号结束。

交叉引用

规则可以支持交叉引用,甚至可以引用自身,但被引用的表达式需要存在,否则会引发错误。引用时,需要保证文法不是左递归的,否则将会陷入死循环。

编码

由于文本处理引擎经常处理多国语言,因而要求使用UTF-8编码(no BOM)。

tn文本分析语言(二) 基本语法的更多相关文章

  1. tn文本分析语言(三):高级语法

    标签(空格分隔): 未分类 高级操作 1.脚本表达式 用双引号包含的脚本被称为脚本表达式,目前支持嵌入Python. 脚本表达式只能在顺序表达式中使用.代码可以在三个位置存在: |位置|功能|例子| ...

  2. 重磅开源:TN文本分析语言

    tn是desert(沙漠之鹰)和tan共同开发的一种用于匹配,转写和抽取文本的语言(DSL).并为其开发和优化了专用的编译器.基于递归下降方法和正则表达式,能解析自然文本并转换为树和字典,识别时间,地 ...

  3. tn文本分析语言(四) 实现自然语言计算器

    tn是desert和tan共同开发的一种用于匹配,转写和抽取文本的语言.解释器使用Python实现,代码不超过1000行. github地址:https://github.com/ferventdes ...

  4. NetAnalyzer笔记 之 十一 打造自己的协议分析语言(1)初衷与语法构想

    回头看看NetAnalyzer开发系文档上次一篇竟然是2016年,老脸一红.不过这几年墨云成功过的讨到一个温柔贤淑的老婆,有了一个幸福的家庭,去年9月又有了一个大胖儿子,想想也就释然了^_^ 其实这几 ...

  5. [Markdown]纯文本标记语言MarkdowPad2--MD语法知识

    ##1.标题 代码 注:# 后面保持空格 # h1 ## h2 ### h3 #### h4 ##### h5 ###### h6 ####### h7 // 错误代码 ######## h8 // ...

  6. linux 文本分析工具---awk命令(7/1)

    awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大.简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各 ...

  7. Solr:文本分析

    文本分析时搜索引擎的核心工作之一,对文本包含许多处理步骤,比如:分词.大写转小写.词干化.同义词转化等.简单的说,文本分析就说将一个文本字段的值转为一个一个的token,然后被保存到Lucene的索引 ...

  8. C语言-01-基本语法

    一.学前需知 开发工具 windows平台:Visual C++6.0等 mac平台:Xcode6.0等 以下文章内容皆是以Xcode6.0为开发工具,clang编译器. Xcode的一些常用快捷键 ...

  9. 用R进行文本分析初探——以《红楼梦》为例

    一.写在前面的话~ 刚吃饭的时候同学问我,你为什么要用R做文本分析,你不是应该用R建模么,在我和她解释了一会儿后,她嘱咐我好好写这篇博文,嗯为了娟儿同学,细细说一会儿文本分析. 文本数据挖掘(Text ...

随机推荐

  1. jquery 的3D Carousel插件参数说明

    这个插件大家都很熟悉了,但是在网上找了很久找不到相关的资料,只有自己琢磨研究了一下.有些参数一眼都可以看出意思,在此我只说一下每个图片要想带一些扩展信息怎么处理. 1:首先需要创建一个ul对象,然后里 ...

  2. 出现了内部错误-网站中X509Certificate2加载证书时出错

    今天给网站配置了加密证书文件,用类X509Certificate2加载证书文件时,一直报出现了内部错误,但是Demo中用控制台程序加载证书没任何问题 读取证书文件的语句: X509Certificat ...

  3. 如何对tableview进行自定义多选

    前言: 很多入门不久的程序员或许都会遇到系统自带的tableview多选时cell选择时不能选择自己想要的点击时的颜色或者图片,这让初级开发者们很烦恼.今天,我试着花了几个小时的时间用了自己的想法,去 ...

  4. ATL封装IE内核启示:使用Win32/ATL建立窗口

    开发大型GUI界面程序MFC当仁不让,但如果是开发图形应用程序,并不需要大规模界面控件,没有必要链接庞大的MFC库,直接使用platform sdk会很麻烦,这时ATL中的关于Windows的封装就是 ...

  5. Spark源码编译并在YARN上运行WordCount实例

    在学习一门新语言时,想必我们都是"Hello World"程序开始,类似地,分布式计算框架的一个典型实例就是WordCount程序,接触过Hadoop的人肯定都知道用MapRedu ...

  6. setTimeout 学习闭包

    @(技术笔记)[css] 学习参考网站 css 网站,可供参考 javascript学习网站 var create = function (i){ return function(){ console ...

  7. vs2012 打开解决方案崩溃或者点击项目崩溃

    报错: 问题签名:  问题事件名称: CLR20r3 解决方案: 步骤1:开始-->所有程序-->Microsoft Visual Studio 2012-->Visual Stud ...

  8. 构建 Android 应用程序一定要绕过的 30 个坑

    原文地址:Building Android Apps - 30 things that experience made me learn the hard way 原文作者:César Ferreir ...

  9. 报文解析及CRC类

    /// <summary> /// 报文解析转换类 /// </summary> public class DatagramConvert { public static En ...

  10. ios 定位

    ios 定位新功能----在程序中实现定位功能 Core Location是iOS SDK中一个提供设备位置的框架.可以使用三种技术来获取位置:GPS.蜂窝或WiFi.在这些技术中,GPS最为精准,如 ...