tn文本分析语言(二) 基本语法
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文本分析语言(二) 基本语法的更多相关文章
- tn文本分析语言(三):高级语法
标签(空格分隔): 未分类 高级操作 1.脚本表达式 用双引号包含的脚本被称为脚本表达式,目前支持嵌入Python. 脚本表达式只能在顺序表达式中使用.代码可以在三个位置存在: |位置|功能|例子| ...
- 重磅开源:TN文本分析语言
tn是desert(沙漠之鹰)和tan共同开发的一种用于匹配,转写和抽取文本的语言(DSL).并为其开发和优化了专用的编译器.基于递归下降方法和正则表达式,能解析自然文本并转换为树和字典,识别时间,地 ...
- tn文本分析语言(四) 实现自然语言计算器
tn是desert和tan共同开发的一种用于匹配,转写和抽取文本的语言.解释器使用Python实现,代码不超过1000行. github地址:https://github.com/ferventdes ...
- NetAnalyzer笔记 之 十一 打造自己的协议分析语言(1)初衷与语法构想
回头看看NetAnalyzer开发系文档上次一篇竟然是2016年,老脸一红.不过这几年墨云成功过的讨到一个温柔贤淑的老婆,有了一个幸福的家庭,去年9月又有了一个大胖儿子,想想也就释然了^_^ 其实这几 ...
- [Markdown]纯文本标记语言MarkdowPad2--MD语法知识
##1.标题 代码 注:# 后面保持空格 # h1 ## h2 ### h3 #### h4 ##### h5 ###### h6 ####### h7 // 错误代码 ######## h8 // ...
- linux 文本分析工具---awk命令(7/1)
awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大.简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各 ...
- Solr:文本分析
文本分析时搜索引擎的核心工作之一,对文本包含许多处理步骤,比如:分词.大写转小写.词干化.同义词转化等.简单的说,文本分析就说将一个文本字段的值转为一个一个的token,然后被保存到Lucene的索引 ...
- C语言-01-基本语法
一.学前需知 开发工具 windows平台:Visual C++6.0等 mac平台:Xcode6.0等 以下文章内容皆是以Xcode6.0为开发工具,clang编译器. Xcode的一些常用快捷键 ...
- 用R进行文本分析初探——以《红楼梦》为例
一.写在前面的话~ 刚吃饭的时候同学问我,你为什么要用R做文本分析,你不是应该用R建模么,在我和她解释了一会儿后,她嘱咐我好好写这篇博文,嗯为了娟儿同学,细细说一会儿文本分析. 文本数据挖掘(Text ...
随机推荐
- jquery 的3D Carousel插件参数说明
这个插件大家都很熟悉了,但是在网上找了很久找不到相关的资料,只有自己琢磨研究了一下.有些参数一眼都可以看出意思,在此我只说一下每个图片要想带一些扩展信息怎么处理. 1:首先需要创建一个ul对象,然后里 ...
- 出现了内部错误-网站中X509Certificate2加载证书时出错
今天给网站配置了加密证书文件,用类X509Certificate2加载证书文件时,一直报出现了内部错误,但是Demo中用控制台程序加载证书没任何问题 读取证书文件的语句: X509Certificat ...
- 如何对tableview进行自定义多选
前言: 很多入门不久的程序员或许都会遇到系统自带的tableview多选时cell选择时不能选择自己想要的点击时的颜色或者图片,这让初级开发者们很烦恼.今天,我试着花了几个小时的时间用了自己的想法,去 ...
- ATL封装IE内核启示:使用Win32/ATL建立窗口
开发大型GUI界面程序MFC当仁不让,但如果是开发图形应用程序,并不需要大规模界面控件,没有必要链接庞大的MFC库,直接使用platform sdk会很麻烦,这时ATL中的关于Windows的封装就是 ...
- Spark源码编译并在YARN上运行WordCount实例
在学习一门新语言时,想必我们都是"Hello World"程序开始,类似地,分布式计算框架的一个典型实例就是WordCount程序,接触过Hadoop的人肯定都知道用MapRedu ...
- setTimeout 学习闭包
@(技术笔记)[css] 学习参考网站 css 网站,可供参考 javascript学习网站 var create = function (i){ return function(){ console ...
- vs2012 打开解决方案崩溃或者点击项目崩溃
报错: 问题签名: 问题事件名称: CLR20r3 解决方案: 步骤1:开始-->所有程序-->Microsoft Visual Studio 2012-->Visual Stud ...
- 构建 Android 应用程序一定要绕过的 30 个坑
原文地址:Building Android Apps - 30 things that experience made me learn the hard way 原文作者:César Ferreir ...
- 报文解析及CRC类
/// <summary> /// 报文解析转换类 /// </summary> public class DatagramConvert { public static En ...
- ios 定位
ios 定位新功能----在程序中实现定位功能 Core Location是iOS SDK中一个提供设备位置的框架.可以使用三种技术来获取位置:GPS.蜂窝或WiFi.在这些技术中,GPS最为精准,如 ...