类自然语言程序设计.docx
《类自然语言程序设计.docx》由会员分享,可在线阅读,更多相关《类自然语言程序设计.docx(20页珍藏版)》请在冰豆网上搜索。
![类自然语言程序设计.docx](https://file1.bdocx.com/fileroot1/2023-2/13/179711fa-ee3e-483f-95c0-fdcbf500e26b/179711fa-ee3e-483f-95c0-fdcbf500e26b1.gif)
类自然语言程序设计
类自然语言程序设计
摘要:
本文提出接近自然语言的通用程序设计语言——类自然语言,并介绍实现该语言的一个原型系统——“开蒙”语言处理平台。
旨在构建一种在更高层次进行程序设计的语言,以摆脱传统计算机程序设计语言过于低级、过于细节的程序设计方式。
类自然语言象自然语言一样具有知识表达和处理的能力,可以适应更为复杂、更为抽象的程序设计任务,弥补传统程序设计语言不长于抽象设计,不长于复杂任务处理的不足。
类自然语言使用词汇作为语言基本单位,词汇的形式和内容接近自然语言。
类自然语言是开放的语言,语言的外延和内涵可以任意扩充,即语言中的词汇数量和每个词汇的涵义不受限制。
形式上可以用中文、英文或其它任何被计算机接受的文字,甚至多种文字混合。
本文中提出的所有语言特征都在作者开发的“开蒙”语言处理平台上实现。
关键字:
类自然语言程序设计,自然语言理解,知识表示
1.引论
传统程序设计语言(以下简称传统语言)在过去数十年取得了巨大成功,由此引发的信息革命将人类社会带到了前所未有的文明程度。
随着这个进程的逐步深入,需要处理越来越复杂的结构,越来越抽象的概念,传统语言也显得越来越捉襟见肘。
而自然语言表达复杂事物则表现得轻松自如,可以通过少量词语实现复杂事物的抽象概括,通过简单的句子表现极其复杂的过程。
如果实现自然语言程序设计,无疑具有重大意义。
但自然语言难以为机器接受,最大的困难在于如何将自然语言蕴含丰富的知识以计算机可以接受的形式表现出来。
因此研究语言的知识表示形式和利用知识的方式是自然语言编程的主要内容。
实现自然语言程序设计,可在四个方面影响信息科学:
一是给程序开发人员提供新的编程工具,以应付更为复杂、抽象的需求;二是编程方式更友好、更简易,有利于程序设计技术普及;三是可结合其它技术(如语音识别),提供新型人机交互界面,用户将具有远为丰富的手段操纵计算机;四是可能给自然语言理解提供可借鉴的语言处理方法。
计算机语言研究的早期就有很多学者对自然语言编程的意义和可行性进行了研究[1,2,3,4],肯定了其价值。
其可行性研究尽管流于粗浅,仍然一直有人不断进行尝试,对这个问题的认识也逐步深入。
如HugoLiu和HenryLieberman在其论文中指出“动作、非系动词的动词映射为函数,名词短语映射为类,形容词修饰映射为类的属性,副词修饰映射为函数的参数”,同时论述了对象继承,对象指称等一些自然语言编程中不可回避的重要问题[1]。
尽管目前尚难实现完全自由的自然语言编程,但只要进行一定的词法和语法限制,就能实现自然语言形式的计算机程序设计。
本文提出一个这样的语言体系模型,称为类自然语言,并开发了“开蒙”语言处理平台,验证了这个体系。
2.类自然语言与传统程序设计语言的区别
自然语言和传统语言最本质的区别在两方面:
其一是知识表示:
传统语言是过程描述的工具,本身几乎不包含知识,而自然语言的主要功能是知识表达,语言的词法和语法仅仅是自然语言中相对次要的因素;其二是语言开放性,自然语言是开放的语言,语言的内涵和外延随着人类认识的提高可自由增加与更新,而传统语言是封闭的语言,由有限的预定义命令组成,命令的内容和形式不可变更。
围绕这两个本质区别,类自然语言较传统程序设计语言表现出一些新的特征:
2.1.知识表示
自然语言蕴含知识。
如句子“请播放歌曲‘我的祖国’”,蕴含了关于什么是歌曲,如何播放,如何获得歌曲‘我的祖国’等信息,尽管这些信息并没有在句子中出现。
因此类自然语言的首要目标就是表示知识。
2.2.语言的开放性
自然语言是开放的。
人类知识始终处于进化之中,因此自然语言所表示的知识也必须是可编辑的,语言的外延和内涵都允许增减、修改,即语言的词汇量和词汇的内涵都可以任意改变,或者说语言是开放的。
类自然语言也同样是开放的。
2.3.语言的独立性
要实现语言的开放,语言处理平台和语言本身必须是两个相对独立的系统。
语言的进化不能以语言处理平台的重新设计为代价。
而传统语言处理平台和语言是同一的。
语言的编译器或解释器决定了语言的内容,即语言本身不具备扩充能力。
2.4.知识的可积累性
语言蕴含的知识可以由少到多,由浅入深积累。
知识积累必须由两个条件保证:
一是增加新的知识时,已有知识形式和内容保持有效,除非有意的更新;二是可以直接使用语言中已有的知识形成更高层次的新知,增加到语言中形成语言的一部分,与语言的原有部分同等使用,从而逐级抽象,以简单的方式表达复杂概念。
2.5.知识的继承性
继承是利用已有知识的一种有效方式,在面向对象程序设计方法(OOP)中得到充分体现。
类自然语言采纳这种方法。
2.6.近自然语言的表达形式
尽管不是必须,类自然语言采取接近自然语言的词法、语法和句型。
以减轻学习和使用类自然语言的负担。
语言的形式可以是汉语、英语等任意语言,甚至混合语言。
3.知识表示
类自然语言的知识表示主要体现在对目标对象数据结构的表示和其适用操作的表示。
语言中的知识都是以词汇的形式出现,如图表1。
每个词汇由词汇名和若干属性构成。
词汇的形式表示:
<词汇>→<词汇名><属性名><属性值>{<属性名><属性值>}
一个词汇可以有任意多属性。
所有词汇至少有“词性”属性,该属性决定词汇的语法角色,其它属性根据需要而定,可任意设置。
图表1
3.1.数据结构表示
对象数据结构以树型层次结构表示,图表2是.wav语音对象的数据结构知识表示。
左边的树型列表表示了对象的数据结构,中间列表框中显示的“RIFF”是对象“段标识”的数据值。
该对象是对象“语音头”的一个属性,而“语音头”又是对象“语音”的一个属性。
结构中每一个节点称为一个对象,用一个名词定义。
图表2
名词在“词性”属性的基础上还必须有“数据类型”属性,建立对象时按数据类型属性的定义建立指定类型的对象。
最简单的名词是不具有结构的基本数据类型。
“开蒙”语言有逻辑型、字节型、短整数型、整数型、浮点型、双精度型、长双精度型和字符型等基本数据类型。
如图表3,定义了词汇“段标识”的词性和数据类型。
由于这是基本数据类型,不再需要有其它属性。
图表3
如果名词具有更复杂的结构,则需用更多属性定义。
具有结构的名词之“数据类型”属性都定义为“复合型”。
如图表4,名词“语音头”有5个属性,其“词性”和“数据类型”属性是语法属性,决定词汇的语法成分,运行时无需为其建立对象。
其它3个属性是实体属性,运行时将按照定义建立可以访问的对象。
而这些属性都需要其它词汇进一步定义,如其“段标识”属性由图表3所示名词“段标识”进一步定义了其数据类型。
“文件长度”和“波形标识”也有相应的名词定义。
图表4
如果一个名词的实体属性也是“复合型”,运行时将形成多级层次结构。
如图表5中名词“语音”的各实体属性都是具有结构的复合数据类型,其各属性的表示方式类似图表4中表示“语音头”属性,建立“语音”对象时便形成图表2表示的树型结构。
图表5
此外,还允许“自定义型”数据类型,类自然语言不直接处理这种类型。
其处理方法由该类型的适用动词实现。
如图表6定义了“设备指针”,类自然语言不能直接操作“设备指针”对象,而必须由其适用的“建立动词”或“删除动词”间接操作。
图表6
3.2.适用操作的表示
对象的适用操作由动词和运算符体现。
类自然语言的动词由动态链接函数和可执行脚本两种形式实现。
动态链接函数是用其它语言按照类自然语言动词接口规范编写的可动态加载的dll函数,执行动词时将函数加载到内存直接执行;可执行脚本是用类自然语言编写的程序,执行动词时将其脚本提交类自然语言解释器解释执行。
图表7是动词“播放语音”的定义,该动词由动态链接函数_PlayWav()实现。
图表8是动词“文本对比”的定义,该动词由类自然语言脚本“文本对比.scr”实现。
动词函数一般具有一个或多个“引用对象”属性,该属性是检验一个动词是否适用宾语对象的判据。
类自然语言规定名词不可同名,而动词允许同名,语言解释器可能需要从多个同名动词中根据“引用对象”属性选择适用动词施加于指定对象。
此外,动词定义中还必须具备加载动词dll函数或执行类自然语言脚本所必须其它信息,如的“动词路径”、“动词文件名”等属性,如果是dll函数还必须有“动词函数名”属性。
对于需要返回执行结果的动词还有“生成对象”属性如图表9,动词“显示波形”执行后将产生波形显示窗口的指针。
图表7
图表8
图表9
3.3.知识的继承
类自然语言中知识的继承类似面向对象程序设计的继承,任何名词都可以通过定义一个“词汇类”属性继承另一个名词的所有属性,前者称为后代名词或实例名词,后者称为前辈名词或类名词。
用后代名词建立对象时首先按前辈名词的定义建立数据结构,称为前辈对象,然后按后代名词的定义增加或修改后代名词中定义的属性,形成后代对象。
如果后代名词中定义的属性与前辈对象的属性同名,后代名词的属性定义覆盖前辈对象的属性定义;如果后代名词中定义的属性没有在前辈对象的树型结构中出现,则在后代对象中增加这个属性。
图表10和图表11表现最简单的继承关系。
图表10是名词“语音格式”的定义,图表11是名
词“标准语音格式”的定义。
“标准语音格式”将“词汇类”属性值定义为“语音格式”从而继承“语音格式”的属性,按照“标准语音格式”生成对象时,名词“标准语音格式”中定义的实体实体属性值覆盖“语音格式”中的同名属性值(尽管本例中“语音格式”的各属性没有赋予具体值)。
名词“语音”定义如图表5,名词“我的祖国”定义如图表12。
图表13定义其文件标识。
属性通过定义“词汇类”属性,名词“我的祖国”继承“语音”的所有属性,而“我的祖国”中定义的其它实体属性覆盖“语音”下的同名属性。
尽管名词“语音”具有较复杂的数据结构,但名词“我的祖国”可以通过继承的方式直接沿用“语音”定义的知识,而无需重复繁琐的定义。
具有复合结构的属性也可以实现覆盖,“标准语音格式”覆盖先辈对象“语音”中“语音格式”的属性值,由于“语音格式”是复合型,实际上是“标准语音格式”的下级属性值覆盖原“语音格式”的同名下级属性值。
属性“文件标识”也实现相似的属性覆盖。
图表13
依照名词“我的祖国”建立对象,将形成图表13所示结构。
图表14
4.词汇分类
类自然语言由数量无限的词汇构成,因此不能象传统语言一样直接对文字进行形式化语法分析。
而是象自然语言一样,先将词汇按词性分类,然后再分析句子的语法结构。
词汇的“词性”属性定义了词汇语法成份,在“开蒙”语言词性有:
名词、动词、形容词、代词、连词、介词、数词、结构词以及各种运算符和标点符。
随语言研究的逐步深入,还将增加更多词性。
其中结构词用于语言执行的流程控制,不太符合自然语习惯,反而更接近传统程序设计语言,标点符用于标注一些特殊成分,其它词性的意义和自然语言相似。
(略去先验词有关论述)可以从存在形式和语言脚色两个角度对词汇分类,存在形式上区分词汇和语言解释器的关系,语言脚色则靠词性上区分词汇在句子中的作用。
尽管类自然语言的所有词汇均在字典中定义,但其中少量用以构成程序框架的词汇功能已经在语言解释器中设定,称为先验词;其余数量无限的词汇称为字典词,其意义和功能与语言解释器无关,完全由字典和动词库决定。
4.1.字典词
名词
名词中至少有“词性”和“数据类型”两个属性,这两个属性是先验词汇,只能选用语言处理平台预设的值。
名词可将“词汇类”属性值设为另一个名词,从而继承其类名词的所有属性。
代词
可以使用代词指称一个对象。
代词是脚本执行时临时建立的词汇,作用域是定义它的脚本及其下级脚本。
代词由引用动词或指代动词建立,脚本执行完毕失效。
一个脚本中不允许出现多个同名代词,后定义的代词覆盖先定义的同名代词。
动词
动词定义一个函数或一个类自然语言脚本,以及动词作用的对象和生成的对象等。
执行时语言处理平台调用定义的函数或脚本。
动词和名词是密切相关的,类似OOP中类的数据成员和方法成员,动词通过“引用对象”属性定义其引用的名词。
语言处理平台进行动词引用对象的检验保证动词调用的正确性。
形容词
定义词汇到数值的转换规则。
4.2.先验词
存在动词
引导一个存在句。
以用名词说明一个或多个对象并在现场中建立之。
命名词
作为存在句、更名句、计数句和建立句中的短语,命名现场中的对象。
可以为对象赋予一个不同于其原始名词的名称。
系动词
引导赋值句。
实现赋值操作。
类自然语言的赋值操作除类似传统语言将基本数据类型的值赋于一个变量(对象),还可以对一个具有复杂结构的对象赋值。
产生词
作为动词句中的短语,指出该动词句要生成新对象并对生成的对象命名。
建立动词
引导建立句,用名词说明一个或多个对象并建立之。
但建立的新对象不加入现场,而是作为独立对象供后续处理。
加入动词
引导加入句,将一个对象作为属性加入另一个对象。
删除动词
引导删除句,删除一个对象。
更名动词
引导更名句,更改一个对象的名称。
引用动词
引导引用句,在被调用脚本范围内为传入的对象赋予临时名称相当于形式变量。
类自然语言程序设计
作为动词的脚本被调用时解释器会根据动词中“引用对象”属性向脚本传入对象指针,引用动词为传入的对象指针命名。
输出动词
引导输出句。
作为动词的脚本可在屏幕上输出一个对象,输出动词在一个窗口中输出指针指定的对象。
指代动词
引导指代句,以为对象指定一代用名。
脚本中可以用代名词指称一个对象,指代动词为该对象指定代名词。
计数动词
引导计数句。
由于类自然语言允许现场存在多个同名对象,一个对象指称可能代表多个对象。
计数动词可计算一个对象指称代表的对象数。
结构词
引导结构句,以控制程序的流程。
类自然语言的流程控制由唯一一个结构句实现。
该句由<结构词如果>、<结构词否则>和<结构词重复>三个词汇构成。
范围词
引导范围描述子句。
类自然语言现场没有限定对象名不可重复,一个对象指称可能引用多个对象,<范围词>对所指称对象进一步修饰。
“开蒙”中使用<范围词所有>和<范围词任何>。
介词
引起对象定位操作。
由于现场是复杂的层次结构,建立新对象可能需要指定目标对象的路径。
<介词>表明路径描述开始。
从属词
定义对象间的从属关系。
描述路径时以<从属词>连接上下级对象。
连接词
指称多个对象。
句子中需要指称多个对象时用<连接词>分隔多个<对象指称>。
数词
常数形式的数字。
包括整数、长整数、浮点数、双精度数、逻辑数、字符串数。
运算词
各种运算符号。
包括算术四则运算、比较运算、逻辑运算、字符串运算、下属运算、筛选运算和下标运算。
5.“开蒙”的语法和语义
5.1.字符集
所有可打印字符。
包括中文和任何其它语言字符。
因此类自然语言可以使用中文、英文和其它任意文字,可以选择任意语种作为语言载体,甚至进行混合语言编程。
5.2.“开蒙”语法规则
“开蒙”的语法相当简单,由于只用于程序设计,除赋值语句外,其它句子不需要主语。
主要语法要素的形式表述如下:
脚本
<脚本>→<句子>{。
<句子>}
脚本即用符合“开蒙”语法规则的词汇组合写成的可执行文本。
是程序管理的基本单位。
脚本由若干普通句子组成的正文文本和链接组成。
句子
<句子>→<陈述句>|<结构句>|<链接>
组成脚本的基本单位。
有陈述句、结构句和链接三类,陈述句按顺序执行,结构句控制脚本流程走向,链接则指向另一个脚本。
链接
<链接>→<左链接符><链接名><右链接符>
是脚本中嵌入的一个可执行文本。
结构句
<结构句>→<结构词如果><逻辑表达式>,[<结构词重复>]<链接1>[;<结构词否则>[<结构词重复>]<链接2>]
作为一个概念验证的原型系统,“开蒙”目前只使用唯一一个结构句。
结构句实现脚本执行的流程控制,把选择结构和循环结构结合在一个句子中。
存在句
<存在句>→<存在动词>[<数词>[<量词>]]<名词>[,<目标介词><对象指称>][,<命名词><命名字符串>]
存在陈述句在现场中建立一个或多个对象,可指定建立对象的路径,可同时对对象命名。
建立句
<建立句>→<建立动词>[<数词>[<量词>]]<名词>[,<命名词><命名字符串>]建立一现场外的一个或多个独立对象,可同时对对象命名。
删除句
<删除句>→<删除动词><对象指称>
删除现场中的一个或多个对象
更名句
<更名句>→<更名动词><对象指称><命名词><命名字符串>
将现场中一个或多个对象更名。
加入句
<加入句>→<加入动词><对象指称><目标介词><对象指称>[,<命名词><命名字符串>]
将一个或多个对象作为属性加入另一个对象。
计数句
<计数句>→<计数动词><对象指称><目标介词><对象指称>
计算一个对象指称对应的对象数目,并将所得数字赋予指定对象。
赋值句
<赋值句>→<主语>[<系动词>]<表达式>
对一个已建立的对象赋值。
除对一个简单对象赋予基本数据类型值外,还可以对具有复杂结构的对象一次赋值,不必分别对其每个后代属性赋值。
动词句
<动词句>→<动词>[<对象指称>][,<介词><路径>][,<产生词><命名字符串>]
调用一个动词函数。
加载一个动词函数,并向该函数传递其所需的对象指针,最后执行该函数。
如果需要用其输出建立新对象,则同时实现新对象建立和命名。
语言处理平台不负责实现动词的功能,动词功能由字典中定义的动词函数或脚本实现。
引用句
<引用句>→<引用动词><命名字符串>
被调用脚本中为传入的对象指定代用名。
引用句执行顺序等于被传入对象顺序。
一个脚本段中不能有同名代名词,如果再次定义同名代名词,后者将取代前面的指代关系。
指代句
<指代句>→<指代动词><对象指称><命名词><命名字符串>
为指定对象指定一代用名。
代用名规定同引用句。
输出句
<输出句>→<输出动词><对象指称>
脚本中设置作为输出的对象。
主语
<主语>→<对象指称>{<连接词><对象指称>}
指称赋值陈述句作用的对象。
表达式
由运算词连接的对象指称或数词。
对象指称
<对象指称>→[<范围词>][<路径>]<节点描述>
指称一个或多个对象。
范围词
<范围词>→<范围词所有>|<范围词任何>
语言处理平台预设的词汇,目前使用“全部”和“任何”二词汇。
路径
<路径>→<节点描述>下[的]{<节点描述>下[的]}
指定一个或多个对象。
节点描述
<节点描述>→<名词>[[<逻辑表达式>]|&<数值表达式>]
指称一个或多个对象。
可以条件或下标的方式对指称对象作进一步限定。
&引导的数值表达式指称同名对象之第个对象。
而[]界定的逻辑表达式(注意此处的界定符[]是实际使用的算符,而不是语法说明)指称使为真的同名对象。
中对象指称的默认起点是本对象。
连接词
<连接词>→<连接词和>
语言处理平台预设的词汇,目前使用“和”及“或”二词汇。
命名字符串
不出现预定义标点符号的任意字符串。
语言执行器并不要求对象名不重复,其引用的正确性由程序员自己设计。
6.“开蒙”语言处理平台
6.1.“开蒙”的结构
“开蒙”主要由三个部分组成。
字典管理器
实现字典的管理和访问。
既是是交互方式字典编辑的工具,又是其它模块访问字典的界面。
类自然语言程序设计
现场管理器
实现现场的管理和访问。
包括建立初始现场,在现场中建立、修改、删除对象,撤销现场。
同时也是其它模块访问现场的界面。
语言执行器
执行用类自然语言编写的脚本。
对提交执行的脚本进行词法、语法和语义分析,最后执行脚本。
6.2.“开蒙”的几个特点
词汇为基础
语言的基础不再是语言编译器或解释器预设的少量命令,而是不受数量限制的词汇。
因此可以积累无限的知识。
知识的继承
任何名词可以通过定义“类词汇”继承其它名词,实现方式类似OOP,后代词汇的同名属性覆盖前代词汇的同名属性。
这种继承不但可继承类词汇的结构和数据,同时也继承类词汇的所有可用动词。
词汇可以多重继承。
现场管理
现场管理器提供一个统一的访问界面供语言执行器和动词函数访问现场的所有对象。
该界面接受若干命令实现增加对象、修改对象、删除对象、访问对象等操作。
流程控制
“开蒙”以唯一的一个结构句实现结构化流程控制。
<结构句>→<结构词如果><逻辑表达式>,[<结构词重复>]<链接1>[;<结构词否则>[<结构词重复>]<链接2>]
结构句根据逻辑表达式计算结果的真假分别执行<链接1>或<链接2>所代表的脚本。
如果执行的链接前有重复结构,执行完链接后继续执行结构句。
因此一个结构句可以囊括选择和循环两种结构。
7.应用实例
例子中的黑体字是类自然语言编写的可执行脚本。
7.1.简单循环
以下脚本实现1到9的阶乘运算。
正文:
有整数,称为p。
p是1。
有整数,称为i。
i是1。
如果i<10,重复{Link1}。
Link1:
p是p*i。
i是i+1。
各句语义如下
有整数,称为p:
建立一个整数型对象,对象命名为p。
p是1:
将p赋值1
有整数,称为i:
建立一个整数型对象,对象名为i。
i是1:
将i赋值1
如果i<10,重复{Link1}:
表达式i<10为真时反复执行{Link1}
{Link1}
p是p*i:
p赋值p*i
i是i+1:
i赋值i+1
很明显,类自然语言实现低层次的程序较传统程序设计语言没有任何优势。
7.2.利用语言知识的例子
以下文字实现录音,对语音滤波后播放。
正文:
有语音,称为原始语音。
原始语音下的语音格式是标准语音格式。
录音原始语音。
FFT原始语音,产生频谱。
滤波频谱和3000和200。
逆FFT频谱,产生滤波语音。
播放语音滤波语音。
各句语义如下
有语音,称为原始语音:
建立一语音对象,命名为“原始语音”
原始语音下的语音格式是标准语音格式:
将对象“原始语音”属性设置成“标准语音格式”
(“标准语音格式”是字典中的一个词汇,定义了语音格式的各个参数)
录音原始语音:
以动词“录音”作用于对象“原始语音”,实现录音操作。
“录音”操作采集的语音数据写入作为属性的文件中
FFT原始语音,产生频谱:
以动词“FFT”作用于对象“原始语音”,生成一新对象,命名为“频谱”
高通滤波频谱和3000和200:
以三目动词“滤波”作用于对象“频谱”和常量“3000”及“200”
逆FFT频谱,产生滤波语音:
以动词“逆FFT”作用于对象“频谱”,生成一新对象,命名为“滤波语音”
播放语音滤波语音:
以动词“播放语音”作用于对象“滤波语音”,实现滤波后的语音播放
第一例中类自然语言的一个句子和传统语言相似,这种情况下类自然语言并无优势。
第二个例子中,类自然语言的一个句子在传统程序设计语言中可能需要数千行命令实现,这是类自然语言优势所在。
8.结论
“开蒙”语言处理平台的开发证明,实现自然语言程序设计是可行的。
尽管“开蒙”语言的词法和语法还有一定限制,较自然语言仍有一定差别,仍然保留传统语言的痕迹,但“开蒙”语言实现了知识表示和语言开放,本质上已经具备自然语言特点。
类自然语言在既