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

简介:

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

github地址:https://github.com/ferventdesert/tnpy

前言

本文将利用引擎实现一个自然语言计算器,支持加减乘除和平方的计算。如下面的测试样例:

三平方加上四平方
如果2乘以3大于4的平方且3>8,那么输出5+4,否则输出12
如果今天下雨,则发送微博
3.4的7次方加上五分之一
3.4*2.7
二百八十除以五分之一
三点五乘以三十七
二十七+15*15
十四点五的平方加上八十三除以三点五

基本的思路,是将整个文本,转换为一个Python的表达式,传递给Python的eval函数执行。这是一种取巧的办法,如果需要,可以修改引擎,实现自定义的脚本解析器。

运算符实现

下面的代码定义了计算符,非常容易理解:

#%Include% Rules/cnext
add  = (/加上?|\+|/ : /+/) ;
sub  = (/减去?|\-|/ : /-/);
mul = (/乘以?|\*|×/ : /*/);
div = (/除以?|/|÷/ : ///); 
pow2 = (/的?平方/ : /**2/);
pow3 = (/的?立方/ : /**3/);
pown=  (/的?/ : //) $(digit) (/次方/ : /**/) : $3 $2 $1; 
divpow = $(digit) $(divpow0) $(digit) ;
powx= $(pow2) | $(pow3) | $(pown);
pow = $(digit) $(powx); 

#%Include% Rules/cnext 引入了外部的一个规则文件,这个文件定义了中文和数字的表达方法。因此在本规则中,可直接引用cnext文件中定义的规则。
顺便指出,只要保证规则名称一致,通过更换为英语或其他语言的数字表达,就可以在不修改本脚本的情况下方便地让规则支持其他语言的计算功能

逻辑运算符

or = (// : / or /);
and = (// : / and /);
not = (/不是/ : / not /);
equal = (/等于|=/ : /=/);
bigger = (/大于|>/ : />/);
less = (/小于|</ :/</);
noequal = (/不等于/: /!=/);

值得一提的是,我们将逻辑转换成了or and 和not, 这是为了能够转写

运算符组合

addsub0=  $(add) | $(sub) ; 
logic0 =$(or) | $(and)  ;
divpow0 = $(mul) | $(div);
equalcheck = $(bigger) |$(less) | $(noequal);
operator= $(addsub0) | $(equalcheck) | $(logic0);

非终结符和终结符

低优先级的表达式可以表示如下:
addsub= $(noterminator) $(operator) $(noterminator);
由于乘除和n次方的的优先级比加减和逻辑运算符优先级高,所以我们将运算符分为两类:
终结符

terminator   = $(digit) | $(ifelse) | $(pow) | $(divpow);

非终结符

#%Order% 28
noterminator = $(terminator) : "eval(m.rstr)" |  $(addsub) : "eval(m.rstr)";

此处需要解释脚本的含义,

  • m在此处代指前面匹配的实体
  • m.rstr为m的转写后的字符串
  • m.mstr为m匹配的字符串
    eval是引擎内置的函数,代指对转写后的字符串求值。

例子

三平方加上四平方
匹配路径如下
TODO
最后eval(32+42),结果为5

无法消除的左递归

如果希望支持计算类似'3加5的和乘以3'的表达式,那么terminator表达式需要这样写:

terminator   = $(digit) | $(ifelse) | $(pow) | $(divpow) | $(function)
|   $(noterminator)  $(add) $(noterminator)  $(addresult)
|   $(noterminator) $(sub) $(noterminator)  $(subresult);

但是,注意第二条子表达式
$(noterminator) $(add) $(noterminator) $(addresult)
$(noterminator)又引用了terminator,因此会导致无穷递归。
目前还没有找到合适的方法解决这个问题。

完整的代码

#计算引擎
#尝试解决 三点五乘以八点三的功能

#%Include% Rules/cnext
add  = (/加上?|\+|/ : /+/) ;
sub  = (/减去?|\-|/ : /-/);
mul = (/乘以?|\*|×/ : /*/);
div = (/除以?|/|÷/ : ///); 
pow2 = (/的?平方/ : /**2/);
pow3 = (/的?立方/ : /**3/);
pown=  (/的?/ : //) $(digit) (/次方/ : /**/) : $3 $2 $1; 


result= (/的?结果/);
addresult0= (/的?和/);
subresult0= (/的?差/);
addresult = $(result) $(addresult0);
subresult = $(result) $(subresult0);
addsub0=  $(add) | $(sub) ; 
logic0 =$(or) | $(and)  ;
divpow0 = $(mul) | $(div);
equalcheck = $(bigger) |$(less) | $(noequal);

operator= $(addsub0) | $(equalcheck) | $(logic0);

divpow = $(digit) $(divpow0) $(digit) ;
powx= $(pow2) | $(pow3) | $(pown);
pow = $(digit) $(powx); 

#functions
print = (/打印/ : /print/);
send = (/发送/ : /send/);
functions = $(print) | $(send);
function = $(functions) $(noterminator) : "invoke(m[0].rstr,m[1].rstr)";


addsub= $(not) $(noterminator)
    | $(noterminator) $(operator) $(noterminator);
    
terminator   = $(digit) | $(ifelse) | $(pow) | $(divpow) | $(function);



#暂时无法分析 3加5的和乘以3,因为会造成循环递归,从左向右推导不可行
#   | ) $(add) $(noterminator)  $(addresult)
#   | $(noterminator) $(sub) $(noterminator)  $(subresult);

#%Order% 28
noterminator = $(terminator) : "eval(m.rstr)" |  $(addsub) : "eval(m.rstr)";


or = (// : / or /);
and = (// : / and /);
not = (/不是/ : / not /);
equal = (/等于|=/ : /=/);
bigger = (/大于|>/ : />/);
less = (/小于|</ :/</);
noequal = (/不等于/: /!=/);

ifelse =  (/如果/) $(vu) (/,那么/) $(noterminator) (/,否则/) $(noterminator) : "check(m[1].rstr,m[3].rstr,m[5].rstr)";


作者:热情的沙漠
出处:http://www.cnblogs.com/buptzym/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。


本文转自FerventDesert博客园博客,原文链接:http://www.cnblogs.com/buptzym/p/5361121.html,如需转载请自行联系原作者
目录
相关文章
|
4月前
|
机器学习/深度学习 人工智能 自然语言处理
【Python机器学习】文本特征提取及文本向量化讲解和实战(图文解释 附源码)
【Python机器学习】文本特征提取及文本向量化讲解和实战(图文解释 附源码)
95 0
|
14天前
|
测试技术 索引
MindOpt APL向量化建模语法的介绍与应用(2)
在数据科学、工程优化和其他科学计算领域中,向量和矩阵的运算是核心组成部分。MAPL作为一种数学规划语言,为这些领域的专业人员提供了强大的工具,通过向量式和矩阵式变量声明以及丰富的内置数学运算支持,大大简化了数学建模和优化问题的处理。在本文中,我们将探索MAPL的这些特性,并且通过示例来展示如何有效使用这些工具。
|
30天前
|
机器学习/深度学习 算法 测试技术
MindOpt APL向量化建模语法的介绍与应用(1)
向量化建模是一种高效的数学建模和编程技术,它涉及到对向量、矩阵和更高维数组进行操作,以实现操作的同时性和批量处理。在优化和数据分析等领域,向量化建模可以极大地提高计算效率,特别是当涉及到大量的重复计算时。由于向量化建模具有表述优势、操作优势、计算性能、可扩展性等优势,使得其适合于解决很大一类实际问题
|
4月前
|
机器学习/深度学习 自然语言处理 算法
【Python自然语言处理】概率上下文无关文法(PCFG)及神经网络句法分析讲解(图文解释 超详细)
【Python自然语言处理】概率上下文无关文法(PCFG)及神经网络句法分析讲解(图文解释 超详细)
76 0
|
5月前
|
机器学习/深度学习 文字识别 自然语言处理
机器学习模型的变音符号
机器学习模型的变音符号
|
10月前
|
机器学习/深度学习 JSON 自然语言处理
LLM 系列 | 07:ChatGPT Prompt实践:文本推断
今天这篇小作文主要介绍如何通过构建ChatGPT Prompt以解决文本推断任务。
|
11月前
|
机器学习/深度学习 人工智能 自然语言处理
解决通用LLM「偏科」问题,数学大模型MathGPT要来了!
解决通用LLM「偏科」问题,数学大模型MathGPT要来了!
203 0
|
机器学习/深度学习 算法
基于机器学习knn算法的手写拼音识别
基于机器学习knn算法的手写拼音识别
93 0
基于机器学习knn算法的手写拼音识别
|
索引
HDLBits练习汇总-02-Verilog语言--向量部分(一)
HDLBits练习汇总-02-Verilog语言--向量部分
162 0
HDLBits练习汇总-02-Verilog语言--向量部分(一)
HDLBits练习汇总-02-Verilog语言--向量部分(二)
HDLBits练习汇总-02-Verilog语言--向量部分
114 0
HDLBits练习汇总-02-Verilog语言--向量部分(二)