概述
这是GF语法写作的实践入门。
GF的主要成分:
前提条件:
- 一些编程语言的一些经验
- 使用计算机的基本知识,例如文本编辑器的使用和文件的管理。
- 了解Unix命令很有用,但不是必需的
- 许多自然语言的知识可能会增加体验的乐趣
大纲
第1课:多语言“Hello World”语法。英语、芬兰语、意大利语。
第2课:食物领域的更大语法。英语和意大利语。
第3课:参数-形态和一致性。
第4课:使用资源语法库。
第5课:语义-依赖类型,变量绑定、和语义定义.
第6课:实现形式语言。
第7课:嵌入式语法应用程序。
第1课:GF入门
目标:
- 安装并运行GF
- 编写第一个GF语法:用三种语言编写的“Hello World”语法
- 使用GF进行翻译和多语言生成
GF是什么
我们将GF一词用于三个不同的方面:
- 一系统(计算机程序)用于处理语法
- 一程序设计语言在其中可以编写语法
- 一理论关于语法和语言
GF系统是GF编程语言的实现,而该语言又建立在GF理论的思想之上。
本教程的重点是使用GF编程语言。
同时,我们学习了GF理论中的思维方式。
我们使用GF系统使语法在计算机上运行。
GF语法和语言处理任务
GF程序称为语法.
语法定义了一种语言。
根据此定义,可以派生语言处理组件:
- 解析:分析语言
- 线性化:生成语言
- 翻译:分析一种语言并生成另一种语言
一般来说,GF语法是多语种的:
获取GF系统
开源免费软件,通过GF主页下载:
语法框架.org
你找到了
- Linux、Mac OS X和Windows的二进制文件
- 源代码和文档
- 语法库和示例
本教程中的许多示例包括联机.
通常你不需要自己编译GF。但是,如果您确实想从源代码编译GF,请遵循开发人员指南.
运行GF系统
类型玻璃纤维
在Unix(或Cygwin)shell中:
%玻璃纤维
您将看到GF的欢迎信息和提示>
.命令
>帮助
将为您提供可用命令的列表。
作为一种常见惯例,我们将使用
%
作为标记系统命令的提示
>
作为标记GF命令的提示
因此,您不应该键入这些提示,而应该只键入它们后面的字符。
“Hello World”语法
像大多数编程语言教程一样,我们从在终端上打印“Hello World”的程序开始。
其他功能:
- 计算机处理:信息以多种语言打印。
- 可逆性:除打印外,您还可以解析信息和翻译它与其他语言的连接。
程序:抽象语法和具体语法
一般来说,GF项目是多语言文法.其主要部件有
抽象语法定义了意思可以用语法表达
- 问候语,我们在那里迎接收件人,可以是世界或妈妈或朋友
抽象语法的GF代码:
--“Hello World”语法abstract你好={flags startcat=问候语;猫问候;收件人;乐趣您好:收件人->问候语;世界,妈妈,朋友:收件人;}
代码包含以下部分:
- 一评论(可选),说明模块正在执行的操作
- 一模块标题表示它是一个名为
你好
- 一模块主体在大括号中,包括
- 一startcat标志声明说明
招呼
是用于分析和生成的默认开始类别
- 类别声明介绍两类,即意义类型
- 函数声明介绍三种有意义的建筑功能
英语具体语法(从意义到字符串的映射):
Hello的具体HelloEng={lincat问候语,收件人={s:Str};林Hello recip={s=“Hello”++recip.s};世界={s=“世界”};妈妈={s=“妈妈”};朋友={s=“朋友”};}
该代码的主要部分包括:
- 表示它是抽象语法的具体语法的模块头
你好
,本身命名HelloEng公司
- 花括号中的模块主体,包括
- 线性化类型定义说明
招呼
和收件人
是记录用一个一串 秒
- 线性化定义告诉给抽象语法中定义的每个含义分配了哪些记录
请注意连接++
和记录投影.
.
芬兰和意大利的具体语法:
Hello的具体HelloFin={lincat问候语,收件人={s:Str};林Hello recip={s=“terve”++recip.s};世界={s=“maailma”};妈妈={s=“äiti”};朋友={s=“ystävät”};}Hello的具体HelloIta={lincat问候语,收件人={s:Str};林Hello recip={s=“ciao”++recip.s};世界={s=“mondo”};妈妈={s=“妈妈”};朋友={s=“朋友”};}
在GF系统中使用语法
为了在GF中编译语法,我们创建了四个文件,每个模块一个,命名为模块名称.gf(平方英尺)
:
Hello.gf HelloEng.gf HelloFin.gf Hello意大利.gf
第一个GF命令:进口语法。
>导入HelloEng.gf
所有命令都有短名称;在这里:
>i Hello工程.gf
GF系统将编译将语法转换为内部表示,并显示CPU时间消耗情况,然后显示新的提示:
>i Hello工程.gf-编译Hello.gf…写入文件Hello.gfo 8毫秒-编译HelloEng.gf…写入文件HelloEng.gfo 12毫秒12毫秒>
您可以使用GF解析(解析
=第页
)
>解析“hello world”你好,世界
解析需要一个一串到抽象语法树.
树的符号是功能应用程序:
函数参数1。..论据
括号仅用于分组。
解析不在语法中的内容将失败:
>解析“hello dad”解析程序在标记2处失败:“dad”>解析“world hello”找不到树
您还可以使用GF线性化(线性化=l
).它把树变成了线:
>线性化Hello World你好,世界
翻译:管线性化到解析:
>导入HelloEng.gf>导入HelloIta.gf>parse-lang=HelloEng“hello mum”|线性化-lang=HelloItaciao妈妈
语言标志的默认值(-朗
):最后导入的具体语法。
多语言生成:
>parse-lang=HelloEng“hello friends”|线性化特威夫·伊斯特·瓦特友爱委员会你好,朋友们
线性化默认为所有可用语言。
Hello World语法练习
用不同的语言组合测试上面显示的解析和翻译示例以及其他一些示例。
扩展语法Hello.gf公司
五个新的接受者和一个新的问候语形式的一些具体句法。
为您可能知道的其他一些语言添加具体语法。
添加一对问候语,用一种语言以一种相同的方式表达,用另一种语言的两种不同方式表达。例如,早上好和下午好在英语中都表示为早上好意大利语。测试翻译时会发生什么早上好在GF学习英语。
- 在中插入错误
你好
例如,语法省略了一些行,省略了林
规则,或在变量的一次出现中更改名称。检查GF生成的错误消息。
使用GF外部的语法
您可以使用玻璃纤维
Unix管道中的程序。
%echo“l你好世界”|gf HelloEng.gf Hello Fin.gf HelloIta.gf
您还可以编写脚本,一个包含行的文件
导入HelloEng.gf导入HelloFin.gf导入HelloIta.gf线性化Hello World
GF脚本
如果我们命名此脚本你好,gfs
,我们可以做到
$gf—运行<hello.gfs乔蒙多特尔夫·迈尔玛你好,世界
选项--运行
删除提示、CPU时间和其他消息。
请参见第7课对于不需要GF系统运行的独立程序。
练习(针对Unix黑客。)编写一个GF应用程序,从标准输入中读取英语字符串,并将意大利语翻译写入输出。
语法还能做什么
还将介绍其他一些功能:
- 形态分析:找出单词可能的屈折形式
- 形态合成:生成单词的所有屈折形式
- 随机生成:生成随机表达式
- 语料库生成:生成所有表达式
- 树库生成:生成树列表及其线性化
- 教学小测验:训练形态学和翻译
- 多语言创作:同时创建多种语言的文档
- 语音输入:针对语法优化语音识别系统
嵌入式语法应用程序
应用程序,使用来自的技术第7课:
- 将语法编译为新格式,例如语音识别语法
- 在Java和Haskell程序中嵌入语法
- 使用编译和嵌入构建应用程序:
- 语音命令
- 口语翻译人员
- 对话系统
- 用户界面
- 本地化:以不同语言呈现程序打印的消息
第2课:为复杂短语设计语法
目标:
- 建立更大的语法:英语和意大利语中关于食物的短语
- 学习编写可重用的库函数(“操作”)
- 学习GF模块系统的基础知识
抽象语法Food
用于谈论食物的短语:
- 开始类别是
短语
- 一
短语
可以通过指定质量
到项目
(例如。这奶酪是意大利的)
- 一个
项目
是从生成的种类
通过前缀这或那个(例如。这个葡萄酒)
- 一
种类
是其中之一原子的(例如。奶酪),或形成限定给定种类
用一个质量
(例如。意大利奶酪)
- 一
质量
是原子的(例如。意大利人,或通过修改给定的质量
用这个词非常(例如。非常温暖)
抽象语法:
抽象食物={flags startcat=短语;猫短语;项目;种类;质量;乐趣是:项目->质量->短语;这个,那个:种类->项目;QKind:质量->种类->种类;葡萄酒、奶酪、鱼:种类;非常:质量->质量;新鲜、温暖、意大利、昂贵、美味、无聊:质量;}
例子短语
Is(This(QKind Delicious,QKind Italian Wine))(非常(非常昂贵))这种美味的意大利葡萄酒非常非常昂贵
具体语法FoodEng
具体食品工程={林肯猫短语,项目,种类,质量={s:Str};林是项目质量={s=item.s++“Is”++quality.s};这种={s=“This”++kind.s};那种={s=“那种”++kind.s};QKind质量kind={s=quality.s++kind.s};葡萄酒={s=“葡萄酒”};奶酪={s=“奶酪”};鱼={s=“鱼”};非常质量={s=“非常”++quality.s};新鲜={s=“新鲜”};温暖={s=“温暖”};意大利语={s=“意大利语”};昂贵={s=“昂贵”};美味=“美味”;钻孔={s=“钻孔”};}
测试语法以进行分析:
>导入FoodEng.gf>解析“这款美味的葡萄酒非常意大利”Is(这款(QKind美味葡萄酒)(非常(非常意大利))
在其他类别中分析设置猫
标志:
p-cat=种类“非常意大利葡萄酒”QKind(非常意大利)葡萄酒
食物语法练习
扩展食物
通过十种新的食物种类和质量进行语法分析,并使用新种类的示例运行解析器。
添加启用表单问题短语的规则这是意大利奶酪吗.
- 启用带有单词“对不起,但是”的可选短语前缀。这样做时,前缀最多只能出现一次。
用于测试语法的命令
生成树和字符串
随机生成(generate_random=gr
):build根据抽象语法构建随机树:
>生成_随机(这(QKind意大利鱼)新鲜吗
通过使用管道,可以将随机生成输入线性化:
>generate_random|线性化这条意大利鱼很新鲜
使用数
生成多棵树的标志:
>gr-数字=4|l那酒很无聊那块新鲜的奶酪很新鲜那奶酪很无聊这奶酪是意大利的
要生成全部的语法可以产生、使用的短语generate_trees=gt
.
>generate_trees生成树那奶酪很意大利那个奶酪很无聊那奶酪很好吃...这酒很新鲜这酒很热
默认值深度为3;深度可以通过使用深度
标志:
>generate_trees-深度=2|l
命令有哪些选项可以通过帮助=小时
命令:
>帮助gr>帮助gt
生成练习
如果命令gt公司
生成了语法中的所有树,它永远不会终止。为什么?
- 测量语法给出的深度分别为4和5的树数。提示。您可以使用Unix字数命令
厕所
计算行数。
有关管道的详细信息:跟踪
将追踪选项-信托收据
要查看其输出的每个命令:
>gr-tr|l-tr|p(这奶酪)无聊吗这个奶酪很无聊(这奶酪)无聊吗
用于测试目的:上面的管道可以显示语法是否模棱两可的,即包含可以以多种方式解析的字符串。
练习.扩展食物
语法使其产生歧义字符串,并尝试歧义测试。
写入和读取文件
要将输出保存到文件中,请将其通过管道传输到write_file=wf
命令,
>gr-number=10|线性化|写入文件-文件=exx.tmp
要将文件读取到GF,请使用读取文件=射频
命令,
>read_file-file=exx.tmp-lines |解析
国旗-行
告诉GF分别读取文件的每一行。
带示例的文件可用于回归测试语法-最系统的方法是树库;请参见在这里.
可视化树
括号给出了树的线性表示,对计算机很有用。
人眼可能更喜欢看到可视化效果:visualize_tree=vt
:
>parse“这款美味的奶酪非常意大利”|visualize_tree
树是在postscript中生成的(.ps(磅)
)文件。这个-视图
选项用于告诉要使用哪个命令查看文件。
这适用于Mac OS X:
>parse“这个美味的奶酪很意大利”|visualize_tree-view=open
在Linux上,可以使用以下命令之一。
>parse“这款美味的奶酪非常意大利”|visualize_tree-view=eog>parse“这个美味的奶酪很意大利”|visualizetree-view=xdg-open

此命令使用程序格拉夫维兹,您可能没有,但可以在网上免费获得。
您可以保存临时文件_grph.dot(英文)
,该命令及物动词
生产。
然后可以使用点
程序(来自Graphviz包)。
%dot-Tpng _grph.dot>mytree.png
你也可以想象解析树,它显示类别和单词,而不是功能符号。命令是可视化解析=vp
:
>parse“这款美味的奶酪非常意大利”|visualize_parse

系统命令
你可以给系统命令不离开GF:!
然后是Unix命令,
>!dot-Tpng grphtmp.dot>mytree.png>!打开mytree.png
系统命令也可以从GF管道接收其参数。然后使用符号?
:
>generate_trees-深度=4 |?wc-l型
此命令示例返回生成的树的数量。
练习.测量语法中有多少棵树食品工程
深度分别为4和5。使用Unix字数命令厕所
计算行数,以及从GF命令到Unix命令的系统管道数。
意大利语的具体句法
只需(?)用字典中的对等词替换英语单词:
食物的混凝土食物={林肯猫短语,项目,种类,质量={s:Str};林是项目质量={s=item.s++“è”++质量.s};这种={s=“questo”++kind.s};那种={s=“quel”++kind.s};QKind质量kind={s=kind.s++quality.s};葡萄酒={s=“葡萄酒”};奶酪={s=“formaggio”};鱼={s=“佩斯”};非常质量={s=“molto”++quality.s};新鲜={s=“壁画”};温暖={s=“caldo”};意大利语={s=“italiano”};昂贵={s=“caro”};美味={s=“delizioso”};钻孔={s=“noioso”};}
不仅仅是替换单词:
质量的顺序及其修改的种类在
QKind质量kind={s=kind.s++quality.s};
意大利人这样说意大利酒
对于意大利葡萄酒
.
(一些意大利语形容词放在名词之前。这种区别可以由参数控制,这些参数在第3课.)
多语言语法还有另一个可视化选项:单词对齐,它显示了哪些单词相互对应。从技术上讲,这意味着在抽象语法中具有相同的最小生成子树的单词。命令是align_words=aw
:
>解析“这美味的奶酪很意大利”| align_words

多语种练习
写一个具体的语法食物
用于其他语言。你可能会以语法错误的线性化而告终,但现在不要担心。
- 如果你写了
食物
对于德语、瑞典语或其他语言,用随机或详尽的生成测试出哪些结构不正确,并准备一个列表,列出那些当前可用的GF片段无法帮助的结构。您可以在完成后返回列表第3课.
自由变化
语义上无法区分的表达方式。
这个变体GF结构表达自由变异。例如,
lin Delicious={s=“美味”|“精致”|“美味”};
默认情况下使线性化
命令仅显示此类列表中的第一个变量;要查看全部内容,请使用选项-全部
:
>p“这款精致的葡萄酒非常美味”这种美味的葡萄酒很美味这种美味的葡萄酒很精致...
变量的等效符号为
lin Delicious=变体{“美味”;“精致”;“美味”}};
这种符号也允许极限情况:空变量列表,
变体{}
例如,如果一个单词缺少某种屈折形式,就可以使用它。
自由变体适用于具体语法中的所有类型;变量列表中的所有术语必须是同一类型。
多语言文法的更多应用
多语言树库
多语言树库:一组树及其在不同语言中的线性化:
>gr-number=2 | l-树库是(那奶酪)(很无聊)quel formaggioèmolto noioso公司那奶酪很无聊(那奶酪)新鲜吗《壁画》那奶酪是新鲜的
翻译测验
翻译测验=tq
:生成随机句子,用一种语言显示,并检查用户用另一种语言给出的答案。
>translation_quish-from=FoodEng-to=FoodIta欢迎参加GF翻译测验。当你至少做了10个例子后,测验就结束了成功率至少为75%。您可以通过输入由点(“.”)组成的行来中断测验。这条鱼很热请求>是的。分数1/1这奶酪是意大利的探索formaggioènoioso>不,不是要求格式化noioso,但是意大利足球队得分1/2这条鱼很贵
无上下文语法与GF
语法食品工程
可以用BNF格式编写,如下所示:
Is.Phrase::=项“是”质量;那。项目::=“那”类;这个。项目::=“本”类;QKind公司。种类::=质量种类;奶酪。种类::=“奶酪”;鱼。种类::=“鱼”;葡萄酒。种类::=“葡萄酒”;意大利语。质量::=“意大利”;真无聊。质量::=“无聊”;美味可口。质量::=“美味”;价格昂贵。质量::=“昂贵”;新鲜。质量::=“新鲜”;非常。质量::=“非常”质量;温暖。质量::=“温暖”;
GF可以将BNF语法转换为GF。BNF文件由文件名后缀识别/cf
(用于无上下文的):
>导入食品.cf
编译器在内部创建独立的抽象模块和具体模块。
上下文无关文法的限制
将具体语法和抽象语法分开会导致与上下文无关语法的三种偏差:
- 置换:更改成分顺序
- 抑制:省略成分
- 重叠:重复成分
练习.定义非文本自由复制语言{x|x<-(a|b)*}
在GF中。
模块和文件
GF使用后缀识别不同的文件格式:
- 源文件:模块名称
.gf(平方英尺)
- 目标文件:模块名称
.gfo型
导入将从源生成目标:
>i食品工程.gf-编译Food.gf…写入文件Food.gfo 16毫秒-编译FoodEng.gf…写入文件FoodEng.gf 20毫秒
这个.gfo型
格式(=“GF对象”)是预编译的GF,加载速度比源GF快(.gf(平方英尺)
).
读取模块时,GF决定是否使用现有的.gfo型
文件或通过查看修改时间生成新文件。
练习。导入时会发生什么食品工程.gf
第二次?在不同的情况下尝试:
- 在第一次导入之后(模块保存在GF的内存中,无需重新加载)。
- 发出命令后
空的
(e(电子)
),清除GF的内存。
- 在做了一点改变之后
食品工程.gf
,虽然只是增加了空间。
- 在中进行更改后
食品.gf
.
使用操作和资源模块
操作定义
功能编程的黄金法则:
每当你发现自己是通过复制和粘贴来编程的时候,就写一个函数来代替。
使用关键字定义具体语法中的函数操作人员
(用于操作),不同于乐趣
为了清楚起见。
例子:
操作步骤:Str->{s:Str}=\x->{s=x};
操作可以是应用一场争论,GF会计算值:
ss“男孩”===>{s=“男孩”}
符号===>
将用于计算。
请注意λ抽象形式
内容如下:
对于具有多个参数的lambda抽象,我们有一个简写
\x、 y->t===\x->y->t
线性化规则实际上使用语法糖进行抽象:
lin f x=t==lin f=\x->t
``resource``模块类型
这个资源
模块类型用于打包操作人员
定义为可重用资源。
资源StringOper={操作人员SS:类型={s:Str};ss:Str->ss=\x->{s=x};抄送:SS->SS->SS=\x,y->SS(x.s++y.s);前缀:Str->SS->SS=\p,x->SS(p++x.s);}
打开资源
任意数量的资源
模块可以是打开a中的ed混凝土
语法。
混凝土FoodEng of Food=打开StringOper{林肯猫S、 项目、种类、质量=SS;林Is item quality=cc item(前缀“Is”quality);This k=前缀“This”k;k=前缀“That”k;QKind k q=cc k q;Wine=ss“葡萄酒”;奶酪=ss“奶酪”;Fish=ss“Fish”;Very=前缀“Very”;新鲜=ss“新鲜”;暖=ss“暖”;意大利语=ss“意大利语”;昂贵=ss“昂贵”;美味=ss“美味”;钻孔=ss“钻孔”;}
部分应用
规则
lin This k=前缀“This”k;
可以写得更简洁
lin This=前缀“This”;
函数编程的艺术之一:决定函数中参数的顺序,以便尽可能多地使用部分应用程序。
例如,前缀
通常应用于具有常量字符串的线性化变量。因此,我们将Str公司
参数之前的不锈钢
参数。
练习.定义操作中缀
类似于前缀
,这样你就可以写
lin Is=中缀“Is”;
测试资源模块
带标志导入-保留
,
>导入-保留StringOper.gf
使用计算值compute_concrete=立方厘米
,
>compute_concrete前缀“in”(ss“addition”){s:Str=“in”++“addition”}
语法体系结构
扩展语法
新模块可以延伸一个旧的:
abstract更多食物=食物**{猫问题;乐趣QIs:项目->质量->问题;披萨:种类;}
与抽象语法类似,可以为具体语法构建扩展:
混凝土MorefoodEng of Morefood=食品工程**{林肯猫问题={s:Str};林QIs项目质量={s=“is”++item.s++quality.s};披萨={s=“披萨”};}
扩展的效果:将扩展模块和扩展模块的所有内容放在一起。
换句话说:新模块继承旧模块的内容。
同时延伸和打开:
concrete MorefoodIta of Morefood=FoodIta**在中打开StringOper{林肯猫问题=SS;林QIs项目质量=ss(item.s++“è”++quality.s);披萨=ss“披萨”;}
资源模块可以扩展其他资源模块,因此可以构建资源层次结构。
多重继承
同时扩展多个语法:
abstract Foodmarket=食品、水果、蘑菇**{乐趣水果种类:水果->种类;蘑菇种类:蘑菇->种类;}
哪里
抽象水果={猫果;有趣的苹果,桃子:水果;}抽象蘑菇={猫蘑菇;fun Cep,木耳:蘑菇;}
练习.重构食物
通过拆开葡萄酒
变成特别的喝酒
模块。
第3课:带参数的语法
目标:
- 使用复杂的语言结构:
- 形态学:词的屈折变化
- 一致性:句法组合中单词形式的选择规则
可以跳过本章直接进入下一章,因为GF资源语法库的使用使得不必使用参数:它们可以留给库实现者。
问题是:单词必须有屈折变化
像这样的东西需要复数形式
这些意大利葡萄酒很美味
这需要两件事:
- 这个屈折名词和动词的单数和复数
- 这个协议动词对主语:动词必须与主语具有相同的数字
不同的语言有不同的屈折变化和一致性。
在多语言语法中,我们希望忽略抽象语法中的这种区别。
练习列出一些你知道的语言中名词、形容词和动词的可能形式。
参数和表格
我们定义参数类型用一种新的判断形式表示英语中的数字:
param编号=Sg|Pl;
该判断定义了参数类型编号
通过列出其两个施工人员,Sg公司
和Pl公司
(单数和复数)。
我们给予种类
具有桌子取决于数量:
lincat种类={s:Number=>Str};
这个肉用 数量=>Str
类似于函数类型(编号->Str
).
差异:参数必须是参数类型。然后,可以在有限表中列出参数-值对。
这里有一张桌子:
lin奶酪={s=表格{Sg=>“奶酪”;Pl=>“奶酪”}} ;
桌子上有分支,带有图案在箭头的左边=>
和a价值在右边。
表的应用程序由选择操作人员!
.
其计算公式为模式匹配:返回模式与参数匹配的第一个分支的值。例如,
表{Sg=>“奶酪”;Pl=>“芝士”}!Pl公司===>“奶酪”
Case表达式是语法糖:
{…}===表{…{的大小写e!e(电子)
由于Haskell和ML程序员都很熟悉它们,所以在编写GF程序时它们会很方便。
构造函数可以从其他参数类型获取参数。
示例:英语动词的形式(除是):
param VerbForm=VPresent编号|VPast|VPastPart|VPresPart;
事实表明:只有现在时才有数字变化。
示例表:动词的形式喝:
表格{VPresent Sg=>“饮料”;VPresent Pl=>“饮料”;VPast=>“喝了”;VPastPart=>“醉酒”;VPresPart=>“饮酒”}
练习在前面的练习(上一节)中,您列出了一些您知道的语言中名词、形容词和动词可能的形式。现在获取一些结果,并使用参数类型定义和表实现它们。将它们写入资源
模块,您可以使用命令对其进行测试计算机_混凝土
.
弯曲表和范例
形态学范式是一个公式,用来说明一类单词是如何屈折的。
从GF的观点来看,范式是一个需要引理(也称为字典形式,或引文格式)并返回一个变形表。
以下操作定义了英语的常规名词范式:
操作注册名:Str->{s:Number=>Str}=\dog->{s=表格{Sg=>狗;Pl=>狗+“s”}} ;
这个胶合操作人员+
将字符串粘贴到一个代币:
(regNoun“奶酪”).s!Pl===>“奶酪”+“s”====“奶酪”
一个更复杂的例子:正则动词,
操作regVerb:Str->{s:VerbForm=>Str}=\talk->{s=表格{VPresent Sg=>对话+“s”;VPresent Pl=>对话;VPresPart=>通话+“ing”;_=>谈话+“ed”}} ;
过去时态和过去分词的catch-all大小写使用通配符图案_
.
形态学练习
确定以下情况注册名称
范式不适用于英语,并实现了一些替代范式。
- 为您在前面的练习中考虑过的其他语言实现一些常规范例。
在具体语法中使用参数
目的:语言之间的一种更激进的变化,而不仅仅是使用不同的单词和词序。
我们增加了语法食物
构成复数项目的两个规则:
有趣的这些,那些:种类->项目;
我们还添加了一个在意大利语中具有女性格的名词:
趣味披萨:亲切;
这将迫使我们处理性别问题-
协议
在英语中,短语构成规则
乐趣在于:项目->质量->短语;
受数字影响的原因是主题-verb协议:句子的动词在主语的数量上必须有屈折变化,
(这个披萨)热吗===>“这个披萨热”(这些披萨)暖和吗===>“这些披萨暖和”
它是连接线(动词是)受影响的:
操作连接词:数字->字符串=\n->第n种情况,共种情况{Sg=>“是”;Pl=>“是”} ;
这个主题 项目
必须有这样一个数字以提供给copula:
lincat项={s:Str;n:Number};
现在我们可以写了
lin是item qual={s=item.s++连接词item.n++qual.s};
决定性因素
如何项目
受试者收到号码了吗?规则
有趣的是,这些:种类->项目;
添加限定词,或者这或这些,需要不同的这个披萨与。这些披萨.
因此种类
必须具有单数和复数形式:
lincat种类={s:Number=>Str};
我们可以写
lin这种={s=“this”++种类.s!Sg;n=Sg} ;lin这些种类={s=“这些”++种类.s!Pl;n=Pl} ;
为了避免复制和粘贴,我们可以找出决定的模式,
操作检测:Str->Number->{s:Number=>Str}->{s:Str;n:Number}=\det,n,种类->{s=det++kind.s!n;n=n} ;
现在我们可以写了
lin This=det Sg“This”;lin这些=det Pl“这些”;
在更多词汇化语法,限定词将是一个类别:
lincat Det={s:Str;n:Number};乐趣探测:探测->种类->物品;lin Det Det种类={s=det.s++种类.s!详细信息;n=测定值} ;
参数化与固有特征
种类
s的编号为参数化特征:可以构成单数和复数,
lincat种类={s:Number=>Str};
项目
s的编号为固有特征:它们本质上是单数或复数,
lincat项={s:Str;n:Number};
意大利人种类
将具有参数编号和固有性别:
lincat种类={s:Number=>Str;g:性别};
设计参数时要问的问题:
- 存在:通过形态学和其他手段可以建立什么形式?
- 需求:通过协议或政府预期有哪些功能?
字典给出了很好的建议:
uomo公司,邮政编码:。uomini公司,n.m.“男子”
告诉我们uomo公司是复数形式的阳性名词uomini公司因此,参数数和固有性别。
对于单词,固有特征通常作为词汇信息给出。
对于组合,它们是继承从结构的某些部分(通常称为头).意大利修改:
lin QKind等于种类=让gen=kind.g{s=表{n=>kind.s!n++等于s!gen!n};g=发电机} ;
通知
带参数的Foods的英语具体语法
我们使用库中的一些字符串操作前奏曲
使用。
concrete FoodsEng of Foods=开放式前奏曲{林肯猫S、 质量=SS;种类={s:Number=>Str};项目={s:Str;n:数字};林项目质量=ss(item.s++copula-item.n++quality.s);This=det Sg“This”;That=det Sg“That”;这些=det Pl“这些”;那些=det Pl“那些”;QKind质量kind={s=表{n=>quality.s++kind.s!n}};葡萄酒=regNoun“葡萄酒”;奶酪=regNoun“奶酪”;Fish=名词“Fish”;披萨=regNoun“披萨”;Very=前缀SS“Very”;新鲜=ss“新鲜”;暖=ss“暖”;意大利语=ss“意大利语”;昂贵=ss“昂贵”;美味=ss“美味”;钻孔=ss“钻孔”;
参数编号=Sg|Pl;操作人员det:编号->Str->{s:Number=>Str}->{s:Str;n:编号}=\n、 d,cn->{s=d++cn.s!n;n=n} ;名词:Str->Str->{s:Number=>Str}=\男,男->{s=表{Sg=>人;Pl=>男性}} ;regNoun:Str->{s:Number=>Str}=\car->名词car(car+“s”);连接词:数字->字符串=\n->第n种情况{Sg=>“是”;Pl=>“是”} ;}
关于屈折范式的更多信息
让我们扩展英语名词范式,以便我们能够处理所有名词,而不仅仅是常规名词。其目标是提供一个形态学模块,使向词典中添加单词变得容易。
最坏情况函数
我们执行数据抽象从名词的类型看写a最坏情况函数:
操作名词:类型={s:Number=>Str};操作mkNoun:Str->Str->Noun=\x,y->{s=表格{Sg=>x;Pl=>y}} ;操作regNoun:Str->Noun=\x->mkNoun x(x+“s”);
然后我们可以定义
lincat N=名词;lin Mouse=mkNoun“Mouse”“mices”;lin House=regNoun“House”;
其中看不到底层类型。
我们可以自由更改未定义的定义,例如添加案例(主格或属格)到名词的屈折变化:
param Case=Nom|Gen;操作名词:类型={s:Number=>Case=>Str};
现在我们必须重新定义最坏情况函数
操作mkNoun:Str->Str->Noun=\x,y->{s=表格{Sg=>表格{标称值=>x;Gen=>x+“s”} ;Pl=>表格{标称值=>y;Gen=>y+案例最后一个y{“s”=>“”;_=>“的”}}} ;
但从这个层面上来说,我们可以保留旧的定义
lin Mouse=mkNoun“Mouse”“mices”;操作regNoun:Str->Noun=\x->mkNoun x(x+“s”);
在最后一个定义中mk名称
,我们在复数的最后一个字符上使用了case表达式,以及前奏曲
操作
last:Str->Str;
返回由最后一个字符组成的字符串。
case表达式使用字符串上的模式匹配GF中支持,以及参数上的模式匹配。
聪明的范例
普通人狗-狗范式有可预测的变化:
- 以an结尾的名词年:飞-苍蝇,除非元音在年:男孩-男孩
- 以结尾的名词秒,中国,以及其他一些结尾:公共汽车-公共汽车,水蛭-水蛭
我们可以提供其他范例:
noun_y:Str->noun=\fly->mkNoun-fly(init-fly+“ies”);noun_s:Str->noun=\bus->mkNoun-bus(总线+“es”);
(前奏曲功能初始化
删除标记的最后一个字符。)
缺点:
更好的解决方案:a智能范式:
regNoun:Str->名词=\w->让ws:Str=案例w,共个{_+(“a”|“e”|“i”|“o”)+“o”=>w+“s”;——竹子_+(“s”|“x”|“sh”|“o”)=>w+“es”;——巴士,英雄_+“z”=>w+“zes”;--测验_+(“a”|“e”|“o”|“u”)+“y”=>w+“s”;--男孩x+“y”=>x+“ies”;--飞_=>w+“s”--汽车}在里面mkNoun与ws
GF有正则表达式模式:
- 析取模式 P(P)
|
问
- 串联模式 P(P)
+
问
模式的排序方式如下:例如,后缀“哦”
阻止竹子从匹配后缀“o”
.
规则模式练习
英语复数名词的构成规则同样适用于第三人称单数动词的构成。写一个使用这个想法的常规动词范例,但首先要重写注册名称
因此分析需要建立秒-表单被分解为单独的操作人员
,与共享regVerb(正则动词)
.
扩展动词范例,涵盖英语中的所有动词形式,特别注意后缀的变化预计起飞时间(例如。尝试-尝试,使用-习惯于).
- 实施德语乌姆劳特词干操作。该操作改变了重音干音节的元音,如下所示:一到ä,澳大利亚到阿乌,o个到ö、和u个到ü。您可以假设该操作仅将音节作为参数。测试操作以查看其是否正确更改阿尔茨到阿瓦尔扎特,鲍姆到Bäum村,顶部(Topf)到特普夫、和库赫到库赫.
带变量的函数类型
在第5课,相关函数类型需要一个将变量绑定到参数类型的符号,如
关闭:(k:种类)->操作k
函数类型没有变量实际上是一种简写:
预处理VP:NP->VP->S
方法
PredVP:(x:NP)->(y:VP)->S
或变量的任何其他命名。
有时变量会缩短代码,因为它们可以共享一个类型:
八元组:(x,y,z,u,v,w,s,t:Str)->Str
如果未使用绑定变量,可以用通配符替换:
八元组:(_,_,_
一个好的做法是指出参数的数量:
八倍:(x1,_,_,__,_,,_,x8:Str)->Str
对于屈折范式,使用启发式变量名很方便,看起来像预期的形式:
mkNoun:(鼠标,鼠标:Str)->名词
分离操作类型和定义
在库中,将类型签名与定义分开分组是很有用的。可以将操作人员
判断,
oper regNoun:Str->Noun;oper regNoun s=mkNoun s(s+“s”);
把零件放在不同的地方。
使用接口
和实例
模块类型(请参见在这里):零件甚至可以放在不同的文件中。
操作过载
超载:不同的函数可以使用相同的名称,例如在C++中。
编译器执行过载解决方案,只要函数具有不同的类型就可以工作。
在GF中,功能必须分组在一起超载
组。
示例:英语中定义名词的不同方式:
oper mkN:过载{mkN:(dog:Str)->名词;--正则名词mkN:(小鼠,小鼠:Str)->名词;--不规则名词}
查字典:如果单词是规则的,只需要一种形式。如果是不规则的,则给出更多形式。
定义可以单独给出,也可以与类型同时给出:
操作mkN=过载{mkN:(dog:Str)->名词=regNoun;mkN:(小鼠,小鼠:Str)->名词=mkNoun;}
练习设计一个由超载组呈现的英语动词范例系统。
形态学分析和形态学测验
命令morpho_analyse=ma
可用于阅读文本并返回每个单词的分析结果(在当前语法中):
>read_file bible.txt |形态分析
命令morpho_quiz=mq
生成屈折练习。
%gf所有时态/不规则Fre.gfo>morpho_quiz-类别=V欢迎参加GF形态学测验。...设备:VFin VCondit Pl P2简历>不,不是简历,但简历得分0/1
意大利食品语法
参数不仅包括数字,还包括性别。
混凝土食品Ita of Foods=开场前奏曲{参数编号=Sg|Pl;性别=Masc|Fem;
质量因性别和数量而发生变化,而种类有参数数字和固有性别。物品具有固有的数量和性别。
林肯猫Phr=不锈钢;质量={s:性别=>数量=>Str};种类={s:Number=>Str;g:性别};项目={s:Str;g:性别;n:数字};
Quality是一个形容词,每种性别数字组合都有一种形式。
操作人员形容词:(_,_,_:Str)->{s:性别=>数字=>Str}=\尼禄、尼拉、尼瑞、尼雷->{s=表格{马斯克=>表{Sg=>尼禄;Pl=>内里} ;Fem=>表格{Sg=>nera;Pl=>内尔}}} ;
正规形容词的作用是在词干上加上词尾。
regAdj:Str->{s:性别=>号码=>Str}=\nero->设ner=init-nero形容词nero(ner+“a”)(ner+”i”)(ner+”e”);
对于名词屈折变化,我们很乐意明确给出两种形式和性别:
名词:Str->Str->Gender->{s:Number=>Str;g:Gender}=\葡萄酒,葡萄酒,g->{s=表格{Sg=>葡萄酒;Pl=>葡萄酒} ;g=克} ;
我们只需要copula的数值变化。
连接词:数字->字符串=\n->第n种情况{Sg=>“è”;Pl=>“sono”} ;
由于性别的原因,决定比英语更复杂:
det:数字->字符串->字符串->{s:数字=>字符串;g:性别}->{s:Str;g:性别;n:数字}=\n、 m、f、cn->{s={Masc=>m的案例cn.g;Fem=>f}++cn.s!n;g=cn.g;n=n} ;
整套线性化规则:
林是否为项目质量=ss(item.s++连接词item.n++质量.s!item.g!item.n);这=确定Sg“questo”“questa”;那就是det Sg“quel”“quella”;这些=det Pl“questi”“queste”;这些=det Pl“quei”“quelle”;QKind质量种类={s=\\n=>种类.s!n++质量.s!好样的。g!n;g=种类.g} ;葡萄酒=名词“vino”“vini”Masc;奶酪=名词“formaggio”“formagji”Masc;Fish=名词“pesce”“pesci”Masc;Pizza=名词“Pizza”“pizze”Fem;非常相等={s=\\g,n=>“molto”++qual.s!g!n};新鲜=形容词“fresco”“fresca”“fresschi”“fresche”;暖=regAdj“caldo”;意大利语=regAdj“italiano”;昂贵=regAdj“caro”;美味=regAdj“delizioso”;钻孔=regAdj“noioso”;}
使用参数的练习
在食品
语法。
在语法中添加词条、性质和限定词,并尝试正确处理它们的屈折变化和固有特征。
写一个具体的语法食物
对于您选择的语言,现在的目标是通过使用参数实现完全的语法正确性。
- 测量对应于的上下文无关语法的大小
食品Ita
。您可以通过以无上下文格式打印语法来完成此操作(print_grammar-打印机=bnf
)并计算行数。
不连续成分
线性化记录可能包含多个字符串,并且这些字符串可以在线性化中分开。
例如:英语助词动词(关闭).对象可以出现在以下两者之间:
他把它关掉了
动词关闭称为不连续成分.
我们可以如下定义及物动词及其组合:
lincat V2={s:Number=>Str;部分:Str};有趣的AppV2:项目->V2->项目->短语;lin AppV2 subv v2对象={s=主题s++v2.s!主题n++obj.s++v1.part};
练习.定义语言a ^n b ^n c ^n
在GF中,即任何数量的一的后面跟相同数量的b条的和相同数量的c(c)的。这种语言不是无上下文的,但可以通过使用不连续成分在GF中定义。
编译时的字符串与运行时的字符串
令牌的创建方式如下:
- 带引号的字符串:
“foo”
- 涂胶:
t+秒
- 预定义操作
初始化、尾部、tk、dp
- 字符串上的模式匹配
自编译时必须知道标记,上述操作可能不适用于运行时变量(即在线性化规则中代表函数参数的变量)。
因此,书写是不合法的
猫名词;趣味复数:名词->名词;lin复数n={s=n.s+“s”};
因为n个
是一个运行时变量。阿尔索
lin复数n={s=(regNoun n).s!Pl};
与不正确注册名称
按定义在这里,因为运行时变量最终被发送到字符串模式匹配和粘合。
如何在没有空格的情况下将标记写在一起?
lin问题p={s=p+“?”};
不正确。
方法是使用未经授权的人这样可以在线性化后创建正确的间距。
相应地列克瑟例如分析“暖和吗?”
解析之前需要into到tokens。本主题将在中介绍在这里.
具体语法的补充结构
记录扩展名和子类型
符号**
用于记录类型和记录对象。
lincat V2=动词**{c:Case};lin Follow=regVerb“folgen”**{c=Dative};
第2版
(及物动词)变成子类型属于动词
.
如果T型是的子类型R(右),的对象T型可以在以下情况下使用R(右)是必需的。
协方差:返回记录的函数T型as值还可以用于返回超类型的值R(右).
矛盾:函数采用R(右)as参数也可以应用于子类型的任何对象T型.
元组和产品类型
产品类型和元组是记录类型和记录的语法糖:
T1*。..*Tn==={p1:T1;…;pn:Tn}<t1。..,tn>==={p1=T1;…;pn=tn}
因此,标签第1页、第2页、,。..
是硬编码的。
前缀相关选项
英语不定冠词:
操作artIndef:Str=预(pre){(“a”|“e”|“i”|“o”)=>“an”;_=>“a”} ;
因此
artIndef++“奶酪”--->“a”++“奶酪”artIndef++“苹果”--->“一个”++“苹果“
第4课:使用资源语法库
目标:
- 在GF资源语法库中导航并在应用程序中使用它
- 熟悉基本的语言类别
- 编写函子以实现多语言文法中代码的最大共享
图书馆的覆盖面
当前的16种资源语言(GF 3.2版,2010年12月)是
灯泡
加利亚人
猫
艾伦
丹
1.n.(ish)人名;(英)伊什
达特
中国
工程
英语
翅片
尼什
弗雷
英寸
德国
男人
意大利
连
也不是
挪威人
波尔
1.n.(ish)人名;(英)伊什
罗恩
,罗马尼亚语
俄罗斯
西安语
水疗生活馆
尼什
瑞典
盘
乌尔德
u个
前三个字母(工程
等)用于语法模块名称(ISO 639-3标准)。
图书馆的结构
语义语法(到目前为止在本教程中):语法定义了一个意义系统(抽象语法),并告诉它们是如何表达的(具体语法)。
资源语法(一如语言学传统):语法指定语法正确的单词组合,不管它们的含义是什么。
使用资源语法,我们可以实现比使用语义语法更广泛的覆盖范围。
词汇与短语规则
资源语法有两种类别和两种规则:
- 词汇:
- 词汇类别,用于对单词进行分类
词汇规则,用于定义单词及其属性
- 短语(组合,句法):
- 短语类别,用于对任意大小的短语进行分类
- 短语规则,将短语组合成较大的短语
通用电气没有对这两种产品进行正式区分。
但这是一个很好的纪律。
词汇类别
两种词汇类别:
词汇规则
封闭类:模块语法
。在食品
语法,我们需要
this_Det、that_Det、these_Det、those_Det:Det;very_AdA:广告;
命名约定:单词后跟类别(因此我们可以区分量词那个从连词那个).
打开的类中没有对象语法
。单词是根据应用程序的需要构建的:如果我们有
趣味葡萄酒:亲切;
我们将定义
lin Wine=mkN“葡萄酒”;
我们使用的位置mkN(百万牛顿)
从范例工程
:
资源词典
的替代具体语法
有趣的葡萄酒:种类;
是为了提供资源词典,其中包含以下定义
oper-wine_N:N=mkN“葡萄酒”;
这样我们就可以写了
lin Wine=葡萄酒_N;
优势:
- 我们积累了一个可重用的词典
- 我们可以使用在这里加快多语言语法实现
短语类别
在食品
,我们只需要四个短语类别:
氯;--子句,例如“这个披萨很好”NP;--名词短语,例如“this pizza”中国;--常见名词,例如“温暖的比萨饼”AP;--形容词短语,例如“非常温暖”
子句与句子相似(S公司
)但没有固定的时态和情绪;参见在这里了解它们之间的关系。
普通名词通过添加限定词而成为名词短语。
句法组合
我们需要以下组合:
mkCl:NP->AP->Cl;——例如“这个披萨很热”mkNP:Det->CN->NP;--例如“这个披萨”mkCN:亚太->中国->中国;--例如“热披萨”mkAP:AdA->AP->AP;--例如“非常温暖”
我们还需要词汇插入,用单个单词组成短语:
mkCN:N->CN;mkAP:A->AP;
命名约定:构造C类,使用函数百万
C类.
重载:当前库(1.2版)有23个名为mkNP公司
!
句法组合示例
这句话
这些非常暖和的披萨是意大利的
可以按如下方式构建:
mkCl公司(mkNP主题集(mkCN(mkAP very_AdA(mkAP warm_A))(mkCN pizza_N))(mkAP意大利语_AP)
现在的任务是:定义食品
因此,该语法树给出了将语义树线性化的值
这些(QKind(非常温暖)披萨)是意大利语吗
资源API
特定于语言和独立于语言的部分——大致来说,
- 语法API
语法
L(左)所有语言都具有相同的类型和功能L(左)
- 形态学API
范例
L(左)对于不同的语言有部分不同的类型和功能L(左)
在线完整API文档:资源概要,
语法框架.org/lib/doc/synopsis.html
微型资源API:类别
类别
解释
例子
氯
从句(句子),带所有时态
她看着这个
AP公司
形容词短语
非常温暖
中国
普通名词(无限定词)
红色房屋
NP公司
名词短语(主语或宾语)
红色的房子
AdA公司
形容词修饰副词,
非常
Det公司
测定器
这些
A类
一位形容词
温暖的
N个
普通名词
房子
小型资源API:规则
功能
类型
例子
mkCl公司
NP->AP->Cl
约翰很老了
mkNP公司
Det->CN->NP
这些老人
mkCN公司
N->中国
房子
mkCN公司
亚太地区->中国->中国
非常大的蓝色房子
mkAP公司
A->应付账款
古老的
mkAP公司
广告->AP->AP
非常非常古老
小型资源API:结构词
功能
类型
英语
this_Det(设置)
Det公司
这
那_Det
Det公司
那个
这些设置(_D)
Det公司
这
those_Det(设置)
Det公司
那个
每个_广告
AdA公司
非常
小型资源API:范例
发件人范例工程
:
功能
类型
mkN(百万牛顿)
(狗:Str)->N
mkN(百万牛顿)
(男,男:Str)->N
万卡
(冷:Str)->A
发件人范例ITA
:
功能
类型
mkN(百万牛顿)
(葡萄酒:Str)->N
万卡
(卡罗尔:斯特尔)->A
小型资源API:更多范例
发件人范式Ger
:
功能
类型
性别
类型
男性的
性别
女性的
性别
中性的
性别
mkN(百万牛顿)
(Stufe:Str)->N
mkN(百万牛顿)
(图片,Bilder:Str)->性别->N
万卡
(克莱因:Str)->A
万卡
(内脏、贝塞尔、贝斯特:Str)->A
发件人ParadigmsFin示例
:
功能
类型
mkN(百万牛顿)
(目录:Str)->N
mkA公司
(高度:Str)->A
练习
1.尝试不同语言中的形态范例。执行以下操作:
>i-path=所有时态-保留所有时态/ParadigmsGer.gfo>cc-表mkN“Farbe”>cc-表mkA“gut”“besser”“bester”
示例:英语
我们假设抽象语法食品
从第3课.
我们不需要考虑屈折变化和一致性,只需从资源语法库中选择函数即可。
我们需要一条
- 当前目录
.
- 目录
../食物
,其中食品.gf
驻留。
- 库目录
目前
,它相对于环境变量GF_LIB_PATH
因此,模块的开头是
--#-路径=。:../食物:存在concrete FoodsEng of Foods=开放语法Eng,ParadigmsEng in{
英文示例:线性化类型和组合规则
作为线性化类型,我们使用子句短语
,名词短语项目
,的常用名词种类
,和形容词短语质量
.
林肯猫短语=Cl;项目=NP;种类=CN;质量=AP;
现在,我们几乎需要自动编写组合规则:
林项目质量=mkCl项目质量;This kind=mkNP This_Det kind;That kind=mkNP That_Det kind;这些种类=mkNP These_Det种类;那些种类=mkNP Those_Det种类;QKind质量种类=mkCN质量种类;非常质量=mkAP Very_AdA质量;
英语示例:词汇规则
我们使用资源范式和词汇插入规则。
两位名词范式只需要一次,因为鱼-其他一切都是有规律的。
葡萄酒=mkCN(mkN“葡萄酒”);披萨=mkCN(mkN“披萨”);奶酪=mkCN(mkN“奶酪”);鱼=mkCN(mkN“鱼”“鱼”);新鲜=mkAP(mkA“新鲜”);暖=mkAP(mkA“暖”);意大利语=mkAP(mkA“意大利语”);昂贵=mkAP(mkA“昂贵”);美味=mkAP(mkA“美味”);钻孔=mkAP(mkA“钻孔”);}
英语示例:练习
1.编译语法食品工程
生成并解析一些句子。
2.写一个具体的语法食品
意大利语或资源库中包含的其他语言。您可以将结果与本教程前面介绍的手写语法进行比较。
多语言文法的函数实现
通过复制和粘贴实现新语言
如果你写一个具体的语法食品
对于其他语言,大部分代码看起来与英语完全相同。这是因为
- 这个
语法
所有语言的API都是相同的(因为资源包中的所有语言都实现了相同的语法结构)
- 语言倾向于以相似的方式使用句法结构
但词汇规则更依赖于语言。
因此,要将语法移植到新语言,您需要
- 复制给定语言的具体语法
- 改变单词(字符串和屈折变化模式)
我们可以通过复制和粘贴来避免这种编程吗?
函数:模块级的函数
函子熟悉函数式编程语言ML和OCaml,也称为参数化模块.
在GF中,函子是一个模打开
是一个或多个接口.
安接口
是类似于资源
,但它只包含类型属于操作人员
s、 不一定是他们的定义。
functors的语法:添加关键字不完整的
。我们将使用标题
不完整的具体食品I of Foods=开放语法,LexFoods in
哪里
接口语法——资源语法接口接口LexFoods——领域词典接口
此外,当我们
语法的实例语法——英语资源语法LexFoods的实例LexFood Eng——英语领域词典
我们可以写一个函子实例化,
食物的具体食物=食物(语法=SyntaxGer),(LexFoods=LexFoodesGer);
Foods函数的代码
--#-路径=。:../食物不完整的具体食品I of Foods=开放语法,LexFoods in{林肯猫短语=Cl;项目=NP;种类=CN;质量=AP;林项目质量=mkCl项目质量;This kind=mkNP This_Det kind;That kind=mkNP That_Det kind;这些种类=mkNP These_Det种类;那些种类=mkNP Those_Det种类;QKind质量种类=mkCN质量种类;非常质量=mkAP Very_AdA质量;葡萄酒=mkCN Wine_N;披萨=mkCN披萨_N;奶酪=mkCN奶酪_N;鱼类=mkCN鱼类_N;新鲜=mkAP新鲜_A;温暖=mkAP Warm_A;意大利语=mkAP意大利语_A;昂贵=mkAP昂贵_A;美味=mkAP美味_A;钻孔=mkAP钻孔_A;}
LexFoods接口的代码
interface LexFoods=中的开放语法{操作人员葡萄酒N:N;披萨_N:N;奶酪_N:N;鱼类编号:N;新鲜A:A;warm_A:A;意大利语_A:A;费用_A:A;美味_A:A;钻孔_A:A;}
词典德语实例的代码
instance LexFoodsGer of LexFood=打开SyntaxGer,ParadigmsGer in{操作人员wine_N=mkN“韦恩”;pizza_N=mkN“pizza”“Pizzen”女性化;cheese_N=mkN“Käse”“Kä)sen”阳性;fish_N=mkN“Fisch”;fresh_A=mkA“frisch”;warm_A=mkA“warm”“wärmer”“wärmste”;italian_A=mkA“italianisch”;expensive_A=mkA“teuer”;美味_A=mkA“köstlich”;boring_A=mkA“langweilig”;}
德国函子实例化的代码
--#-路径=。:../食物:存在食物的具体食物=食物(语法=SyntaxGer),(LexFoods=LexFoodesGer);
向函子实现添加语言
只需要两个模块:
函数实例化是完全机械化的。
领域词典实例需要对该语言的单词有一些了解:
示例:添加芬兰语
词典实例
例如LexFoods的LexFoodfin=打开SyntaxFin,ParadigmsFin{操作人员wine_N=mkN“viini”;pizza_N=mkN“披萨”;cheese_N=mkN“juusto”;fish_N=mkN“卡拉”;fresh_A=mkA“tuore”;warm_A=mkA“lämmin”;italian_A=mkA“italialainen”;expensive_A=mkA“kallis”;美味_A=mkA“herkullinen”;boring_A=mkA“tylsä”;}
函数实例化
--#-路径=。:../食物:存在混凝土食品Fin of Foods=食品I(语法=SyntaxFin),(LexFoods=LexFoodesFin);
设计模式
这可以看作是设计模式对于多语言语法:
混凝土领域L*实例LexDomainL实例SyntaxL*不完整混凝土领域I/ | \interface LexDomain抽象域接口语法*
标有的模块*
要么在库中给出,要么微不足道。
在手写模块中,只有LexDomainL公司
依赖于语言。
Functors:练习
1.编译和测试FoodsGer公司
.
2.重构食品工程
到函子实例化中。
3.实例化函子食品I
用你选择的语言。
4.设计一个可以用来控制MP3播放器的小语法。语法应该能够识别以下命令播放这首歌,具有以下变体:
- 动词:玩,去除
- 物体:歌曲,艺术家
- 限定符:这,上一个
- 不带参数的动词:停止,暂停
实施分为以下几个阶段:
- 抽象语法
- (可选:)基于字符串的原型具体语法
- 资源语法和词典接口上的函子
- 第一语言的词典实例
- 第一语言的函子实例化
- 第二语言的词典实例
- 第二语言的函子实例化
- ...
受限继承
函子的一个问题
问题:只有当所有语言都使用该资源时,函子才有效语法
以同样的方式。
示例(人为的):假设英语中没有单词表示披萨
,但必须使用意译意大利馅饼.这不再是名词N个
,但在类别中是一个复杂短语中国
.
可能的解决方案:更改接口LexFoods公司
具有
运营比萨饼_CN:CN;
此解决方案的问题:
- 我们最终可能会用每种新语言更改界面和功能
- 我们还必须每次更改旧语言的实例以保持类型正确性
限制继承:包括或排除
模块可能只继承选定的名称。
示例:食品市场
示例“Rsecarchitecture:
食品市场=食品、水果[桃]、蘑菇-[木耳]
这里,来自水果
我们包括桃
只有,并且来自蘑菇
我们排除在外木耳
.
的具体语法食品市场
必须做出类似的限制。
函子问题已解决
英语实例化继承了除常量之外的函子实现披萨
。此常量在正文中定义:
--#-路径=。:../食物:存在concrete FoodsEng of Foods=FoodsI-[Pizza]与(语法=SyntaxEng),(LexFoods=LexFoodesEng)**开放语法工程,范例工程{lin Pizza=mkCN(mkA“意大利语”)(mkN“馅饼”);}
语法重用
抽象语法模块可用作接口,具体语法可用作实例。
然后应用以下对应关系:
类别C操作C:类型乐趣f:A操作f:Alincat C=T操作C:类型=Tlin f=t操作f:A=t
图书馆练习
1.查找以下英语短语的资源语法术语(在类别中博士
).您可以首先尝试手动构建术语。
每个男人都爱一个女人
这个语法可以说十多种语言
哪些语言不在语法中
你想说哪种语言
然后把短语翻译成其他语言。
时态
在食品
语法,我们使用了路径
--#-路径=。:../食物
库子目录目前
是资源的受限版本,只有动词和句子的现在时态。
通过改变路径,我们可以得到所有时态:
--#-路径=。:../foods:所有时态
现在我们可以通过使用-全部
线性化中的标志:
>gr|l-全部这酒很好吃这酒好吃吗这酒不好吃这酒不好吃吗这酒不好吃这酒不好吃吗这酒很美味这酒好吃吗这酒不好吃这酒不是很好吃吗这酒不好吃这酒不好吃吗这酒很美味这酒好吃吗这酒不好吃这酒不是很好吃吗这酒不好吃这酒不好吃吗这酒很美味这酒好吃吗这酒不好吃这酒不是很好吃吗这酒不好吃如果这酒不好吃这酒会很美味的这酒好吃吗这酒不好吃这酒不好吃吗这酒不好吃这酒不好吃吗这酒一定很美味这酒好吃吗这酒不会很美味这酒不是很美味吗这酒不会很美味这酒不好吃吗这酒会很美味这酒好吃吗这酒不好吃这酒不是很美味吗这酒不好吃这酒不好吃吗这酒会很美味的这酒好吃吗这酒本来就不好吃这酒不是很美味吗这酒不会很美味这酒不好吃吗
我们也看到了
- 极性(正极与负极)
- 语序(直接与反向)
- 简约否定与完全否定之间的变异
在有更多时态和语气的语言中,这个列表甚至更长,例如浪漫主义语言。
第5课:精炼抽象语法中的语义
目标:
依赖类型
问题:表达语义完形的条件.
例如:“智能房屋”的语音命令系统希望消除无意义的命令。
因此,我们希望限制特定设备的特定操作-我们可以调暗灯光,但我们不能调暗风扇.
以下示例是从Regulus Book(Rayner&al.2006)中借来的。
一个简单的例子是“智能家居”系统,它定义了家用电器的语音命令。
依赖型系统
本体论:
- 有命令和设备类型
- 对于每种设备,都有设备和操作
- 命令涉及同类设备上的某种操作
将其形式化的抽象语法:
猫指挥;种类;设备种类;--参数类型Kind动作类型;乐趣C操作:(k:种类)->操作k->设备k->命令;
设备
和行动
都是依赖类型。
设备和操作示例
假设种类光
和风扇
,
灯、风扇:种类;dim:行动灯;
给一种,k,您可以形成设备k.
DKindOne:(k:种类)->设备k;--灯光
现在我们可以形成语法树
C行动灯暗淡(DKindOne灯)
但我们不能形成树
C操作灯暗淡(DKindOne风扇)C活动风扇暗淡(DKindOne灯)C活动风扇尺寸(DKindOne风扇)
依赖类型的线性化和解析
具体语法不知道类别是否是依赖类型。
lincat操作={s:Str};lin CAction_act-dev={s=act.s++dev.s};
请注意种类
线性化过程中抑制了参数。
使用依赖类型进行分析包括两个阶段:
- 上下文无关剖析
通过类型检查器过滤
分析type-correct命令的工作原理与预期一致:
>解析“调暗灯光”C行动灯暗淡(DKindOne灯)
但是,typecheck会拒绝输入正确的命令:
>解析“调暗风扇”分析成功,但类型检查失败,出现错误:无法匹配预期的类型设备指示灯相对于埋入式设备风扇表达式中:DKindOne fan
==多态性==
有时,可以在各种设备上执行操作。
这表示为一个接受种类
作为一个论点,并生成一个行动
为了那个种类
:
fun开关On,switchOff:(k:种类)->动作k;
这种函数称为多态的.
我们也可以在具体语法中使用这种多态性来表达Haskell类型库函数:
操作常数:(a,b:类型)->a->b->a=\_,_,c,_->c;操作翻转:(a,b,c:类型)->(a->b->c)->b->a->c=\_,_,_,f,x,y->f y x;
===依赖类型:练习===
1.用上述内容和适当的英语具体语法编写一个抽象语法模块。尝试解析命令调暗灯光和调暗风扇.
2.执行随机和详尽的生成。
3.在语法中添加一些设备类型和动作。
证明对象
咖喱-霍华德同构=命题作为类型原则命题是一种证明(即证明对象)。
示例:定义小于自然数命题,
猫Nat;乐趣零:Nat;有趣的成功:Nat->Nat;
归纳定义数字的含义x个成为小于一个数字年:
零
小于成功
年对于任何年.
- 如果x个小于年,然后
成功
x个小于成功
年.
用依赖类型表示类型理论中的这些公理减去
x年以及构建其对象的两个函数:
无猫Nat Nat;无趣Z:(y:Nat)->无趣(Succy);无趣S:(x,y:Nat)->少x y->少(Succ x)(Succy);
示例:2小于4这一事实具有证明对象
lessS(Succ-Zero)(Succ(Succ-Zero))(lessS-Zero(Succ(Succ-Zero))(lessZ(Succ-0ro)):减去(Succ(Succ-Zero))
证明文件
想法:为了在语义上完善,文档的抽象语法必须包含某些属性的证明,尽管具体文档中没有显示该证明。
示例:描述航班衔接的文件:
从哥德堡飞往布拉格,首先乘坐LH3043前往法兰克福,然后乘坐OK0537前往布拉格。
此文本的格式良好部分可以通过依赖键入来表达:
猫城市;飞行城市;乐趣哥德堡、法兰克福、布拉格:城市;LH3043:法兰克福哥德堡航班;OK0537:布拉格法兰克福航班;
为了将条件扩展到航班连接,我们引入了一类证明可能发生变化的证据:
cat IsPossible(x,y,z:城市)(航班x y)(航班y z);
法律联系由功能构成
fun连接:(x,y,z:城市)->(u:航班x y)->(v:航班y z)->IsPossible x y z u v->航班x z;
限制多态性
以上,所有操作都是
为了扩大新种类的规模,我们可以将其细化为限制多态性:为特定种类定义班
类的概念使用Curry-Howard同构,如下所示:
- 一个类是一个谓语种类——即取决于种类的类型
- 如果存在此类型的证明对象,则Kind位于类中
示例:开关和调光类
我们修改了智能房屋语法:
猫可切换类型;可调光类型;乐趣switchable_light:可切换灯光;switchable_fan:可切换风扇;dimmable_light:可调光;开关打开:(k:种类)->可切换k->动作k;dim:(k:种类)->可调光k->动作k;
可以增量添加新操作的类。
变量绑定
数学符号和编程语言的表达式绑定变量。
示例:通用量词公式
(全部x)B(x)
变量x个
有一个结合 (全部x)
,并发生跳跃在中身体 B(x)
.
非正式数学语言示例:
对于所有x,x等于x对于任何数字x和y,返回x+y的最大值的函数和x*y设x为自然数。假设x是偶数。那么x+3是奇数。
高阶抽象语法
抽象语法可以使用函数作为参数:
cat Ind公司;道具;全部乐趣:(Ind->Prop)->Prop
哪里印度
是指个人的类型和道具
命题的类型。
让我们添加一个等式谓词
趣味方程式:Ind->Ind->Prop
现在我们可以组成树了
全部(\x->等式x x)
我们想把它与普通符号联系起来
(全部x)(x=x)
在高阶抽象语法(HOAS),所有变量绑定都使用高阶语法构造函数来表示。
高阶抽象语法:线性化
HOAS已被证明在变量绑定表达式的语义和计算机实现中非常有用。
我们如何将HOAS与具体语法联系起来?
在GF中,我们写道
全部乐趣:(Ind->Prop)->Proplin全部B={s=“(”++“全部”++B.$0++“)”++B
一般规则:如果参数类型为乐趣
函数是函数类型A->C
,此参数的线性化类型为C类
加上一个新领域$0:Str(零美元)
.
争论B类
因此具有线性化类型
{s:Str;$0:Str},
如果有更多绑定,我们将添加$1
,$2
等。
Eta扩展
为了理解线性化,语法树必须eta-膨胀:对于任何类型的函数
A->B
eta-expanded语法树的形式如下
\x->b
哪里乙:乙
根据假设x:A
.
给定线性化规则
lin等式a b={s=“(”++a.s++“=”++b.s++“)”}
树的线性化
\x->等式x x
是记录
{$0=“x”,s=[“(x=x)”]}
然后我们可以计算公式的线性化,
全部(\x->等式x x)-->{s=“[(全部x)(x=x)]”}。
变量的线性化x个
是“自动”字符串“x”
.
分析变量绑定
GF可以将任何单字字符串视为变量符号。
>p-cat=道具“(全部x)(x=x)”全部(\x->等式x x)
如果使用变量,则必须对其进行绑定:
>p-cat=属性“(全部x)(x=y)”找不到树
变量绑定练习
1.写出整体的抽象语法谓词演算,使用连接词“和”、“或”、“暗示”和“不是”,以及量词“存在”和“所有人”。使用高阶函数确保不会出现无界变量。
2.为你最喜欢的谓词演算符号写一个具体的语法。如果你想要好的输出,请使用Latex作为目标语言。您还可以尝试生成某些编程语言的布尔表达式。根据需要使用尽可能多的括号,以确保无歧义性。
语义定义
这个乐趣
GF的判断是函数的声明,给出了它们的类型。
我们能不能计算 乐趣
功能?
大多数情况下,我们对此不感兴趣,因为函数被视为构造函数,即数据表单-与通常一样
乐趣零:Nat;有趣的成功:Nat->Nat;
但也可以给予语义定义到函数。关键词是定义
:
有趣的一个:Nat;def-one=成功归零;有趣的两次:Nat->Nat;def两倍x=加x x;趣味附加:Nat->Nat->Nat;定义加x零=x;加x(成功)=成功(总和x年);
计算树
计算:遵循定义链,直到无法应用定义,
加一个-->加号(Succ-Zero)(Succ Zero)-->成功(加上(成功零)零)-->成功(成功归零)
GF中的计算使用输入项(_T)
命令和计算
转换,例如。
>parse-tr“1+1”|put_term-transform=计算-tr |l加上一个成功(成功归零)秒(0)
定义上的平等
如果两棵树计算到同一棵树中,那么它们在定义上是相等的。
定义相等并不保证线性化的一致性:
加一==>1+1成功(成功归零)===>秒(s(0))
这个概念的主要用途是在类型检查中:类型的相同性。
因此,例如,以下类型是相等的
减去零一减零(Succ Zero)
所以一个物体也是另一个物体。
判决书数据
说明类别作为构造函数具有某些功能:
data Nat=成功|零;
构造函数的类型签名分别给出,
乐趣零:Nat;有趣的成功:Nat->Nat;
还有一个简写:
数据成功:Nat->Nat;===有趣成功:Nat->Nat;data Nat=成功;
注意:在定义
定义,标识符模式未标记为数据
将被视为变量。
语义定义练习
1.使用自然数、列表、对、lambdas等实现小型函数式编程语言的解释器。对语义定义使用高阶抽象语法。作为具体的语法,请使用您最喜欢的编程语言。
2.无终止检查定义
定义。构造一个使类型检查循环的示例。可以使用调用类型检查put_term-transform=求解
.
目标:
- 为形式语言编写语法(数学符号、编程语言)
- 形式语言与自然语言的接口
- 使用GF实现编译器
算术表达式
我们用整数的加法、减法、乘法和除法构造了一个计算器。
抽象计算器={标志startcat=Exp;cat Exp;乐趣EPlus、EMinus、ETimes、EDiv:Exp->Exp->Exp;EInt:内部->外部;}
类别国际
是内置的整数类别。它的语法树整数字面常数,即数字序列:
5457455814608954681:国际
这些是类型的唯一对象国际
:不允许使用语法声明函数国际
作为值类型。
具体语法:一种简单的方法
我们从一个具体的语法开始,它总是在二进制运算符应用程序周围使用括号:
具体计算器计算器的P=打开序曲{林肯猫Exp=不锈钢;林EPlus=中缀“+”;EMinus=中缀“-”;ETimes=中缀“*”;EDiv=中缀“/”;EInt i=i;操作人员中缀:Str->SS->SS->SS=\f,x,y->ss(“(”++x.s++f++y.s++“)”);}
现在我们有了
>线性化EPlus(EInt 2)(E时间(EInt 3)(EInt 4))( 2 + ( 3 * 4 ) )
首要问题:
除法和非除法
GF中解析的输入不仅仅是一个字符串,而是一个列表代币,由返回列克瑟.
GF中的默认lexer返回由空格分隔的块:
"(12 + (3 * 4))" ===> "(12", "+", "(3". "*". "4))"
正确的方法是
"(", "12", "+", "(", "3", "*", "4", ")", ")"
此外,代币"12"
,"3"
、和"4"
应该被识别为整型文字-它们在语法中找不到。
Lexer由命令的标志调用输入字符串=ps
.
>输入字符串-lexcode“(2+(3*4)”( 2 + ( 3 * 4 ) )
这可以像往常一样通过管道传输到解析器中:
>ps-lexcode“(2+(3*4))”|解析EPlus(EInt 2)(E时间(EInt 3)(EInt 4))
在线性化中,我们使用相应的未经授权的人:
>线性化EPlus(EInt 2)(ETimes(EInt 3)(EInt 4))|ps-无励磁(2 + (3 * 4))
最常见的词汇和非词汇
列克瑟
未经授权的人
描述
焦炭
无变化的
每个字符都是一个标记
词汇代码
无编码
程序代码约定(使用Haskell的lex)
词汇混合
未混合的
类似文本,但在$符号之间类似代码
文字
非文本
标点符号和大写字母的约定
话
解除武装
(默认)由空格字符分隔的标记
优先性和固定性
算术表达式应该是明确的。如果我们写
2 + 3 * 4
它应该被解析为一个,而不是两个
EPlus(EInt 2)(E时间(EInt 3)(EInt 4))E时间(EP+(EInt 2)(EInt 3))(EIint 4)
我们选择前一棵树,因为乘法较高优先级而不是添加。
要表示后一棵树,我们必须使用括号:
(2 + 3) * 4
通常的优先规则:
- 括号中的整型常量和表达式具有最高优先级。
- 乘法和除法具有同等的优先级,低于最高优先级,但高于同样相等的加法和减法。
- 所有四个二进制操作都是左联的:
1 + 2 + 3
表示与(1 + 2) + 3
.
作为参数的优先级
优先顺序可以成为表达式的固有特征:
操作人员Prec:PType=整数2;TermPrec:类型={s:Str;p:Prec};mkPrec:Prec->Str->TermPrec=\p,s->{s=s;p=p};林肯猫Exp=TermPrec;
通知积分2
:参数类型,其值为整数0,1,2
.
使用优先级:将表达式的固有优先级与预期优先级进行比较。
- 如果固有优先级低于预期优先级,请使用括号
- 否则,不需要括号
这个想法被编码在操作中
操作usePrec:TermPrec->Prec->Str=\x,p->case lessPrec x.p第页,共页{真=>“(”x.s“)”;假=>x.s} ;
(我们使用更少Prec
从lib/前奏曲/正式
.)
固定装置
我们可以定义左联中缀表达式:
中缀:Prec->Str->(_,_:TermPrec)->TermPrec=\p,f,x,y->mkPrec p(usePrec x p++f++usePrec-y(nextPrec p));
类常量表达式(最高级别):
常数:Str->TermPrec=mkPrec 2;
所有这些操作都可以在中找到lib/前奏曲/正式
,共有5个级别。
现在我们可以编写计算器
紧凑地:
计算器的具体计算器C=开放形式,序曲{flags lexer=码字;unlexer=代码;startcat=Exp;lincat Exp=TermPrec;林EPlus=中缀0“+”;EMinus=中缀0“-”;ETimes=中缀1“*”;EDiv=中缀1“/”;EInt i=常数i.s;}
优先级练习
1.定义非关联和右关联中缀操作,类似于中缀
.
2.添加一个构造函数,该构造函数在表达式周围放置括号以提高其优先级,但这被定义
定义。使用和不使用管道测试分析pt-transform=计算
.
作为线性化的代码生成
将算术(中缀)转换为JVM(后缀):
2 + 3 * 4===>图标2:图标3;图标4;imul;国际原子能机构
只需给出JVM的线性化规则:
林EPlus=后缀“iadd”;EMinus=后缀“isub”;ETimes=后缀“imul”;EDiv=后缀“idiv”;EInt i=ss(“iconst”++i.s);操作人员后缀:Str->SS->SS->SS=\op,x,y->ss(x.s++“;”++y.s++“;“++op);
带变量的程序
A类直接代码编程语言,使用初始化和作业:
int x=2+3;整数y=x+1;x=x+9*y;
我们通过以下构造函数定义程序:
乐趣PEmpty:程序;P单位:Exp->(Var->Prog)->Prog;PAss:Var->Exp->Prog->Prog;
P装置
使用高阶抽象语法使初始化变量在延续程序的。
上述代码的抽象语法树是
PInit(EP+(EInt 2)(EInt 3))(\x->PInit(EP+(EVar x)(EInt 1))(\y->PAss x(EP+(EVar x)(E时间(EInt 9)(EVar y))P空))
不允许未初始化的变量-没有的构造函数变量
!但我们有规则
趣味EVar:Var->Exp;
语法的其余部分与算术表达式相同在这里。实现它的最佳方法可能是编写一个扩展表达式模块的模块。扩展最自然的开始类别是掠夺
.
代码生成练习
1.定义直接代码语言的类C的具体语法。
2.将直接代码语言扩展到类型表达式浮动
。为了保证类型安全,可以定义类别类型
类型和品牌费用
和变量
依赖于类型
。基本浮点表达式可以由内置GF类型的文本构成浮子
。算术运算应该是多态的(如在这里).
3.使用另外两条指令将JVM生成扩展到直接代码语言
伊洛德
x个,它加载变量的值x个
晶闸管
x个将值存储到变量x个
因此,上一节中示例的代码是
图标2;图标3;iadd;历史学家x;iload x;图标1;iadd;历史;iload x;图标9;iload y;imul;iadd;历史学家x;
4.如果您尝试在语言中添加浮点数,那么现在可以利用类型检查的主要优势来生成代码:选择类型正确的JVM指令。浮点指令与整数指令完全相同,只是前缀是(f)
而不是我
,还有那个fconst公司
采用浮点文字作为参数。
第7课:嵌入式语法
目标:
- 使用语法作为用Haskell和JavaScript编写的程序的一部分
- 基于GF语法实现独立的问答系统和翻译人员
- 从GF语法生成语音识别的语言模型
GF语法可以用作用其他编程语言编写的程序的一部分,称为主机语言。该设施基于以下几个组件:
- PGF:多语言GF语法的可移植格式
- 用宿主语言编写的PGF口译员
- 支持调用解释器的宿主语言库
- 一种在宿主语言中操作抽象语法树的方法
可移植格式称为PGF,即“可移植语法格式”。
此格式是通过使用GF作为批处理编译器生成的,带有选项-制造
,来自操作系统外壳:
%gf-制作源.gf
PGF是推荐的分发最终语法产品的格式,因为它们被从多余的信息中剥离出来,并且可以比单独的模块组更快地启动和应用。
应用程序程序员从不需要读取或修改PGF文件。
因此,PGF在通用编程(或Java中的字节码)中扮演着与机器代码相同的角色。
Haskell:EmbedAPI模块
Haskell API包含(除其他外)以下类型和函数:
读取PGF::文件路径->IO PGF线性化::PGF->语言->树->字符串parse::PGF->语言->类别->字符串->[树]linearizeAll::PGF->Tree->[String]linearizeAllLang::PGF->Tree->[(Language,String)]parseAll::PGF->类别->字符串->[[Tree]]parseAllLang::PGF->Category->String->[(Language,[Tree])]语言::PGF->[语言]类别::PGF->[类别]startCat::PGF->类别
这是Haskell应用程序中唯一需要导入的模块。它是GF发行版的一部分,位于文件中src/PGF.hs
.
第一个应用程序:翻译
让我们首先构建一个独立的翻译器,它可以在语法中的任何语言之间翻译任何多语言语法。
模块Main,其中导入PGF导入系统。环境(getArgs)主::IO()main=做文件:_<-getArgsgr<-readPGF文件交互(translate gr)翻译::PGF->String->Stringtranslate gr s=案例parseAllLang gr(startCat gr)s of(lg,t:_):_->非线性[线性化gr l t | l<-语言gr,l/=lg]_->“无理由”
要运行转换器,首先通过以下方式编译它
%ghc-make-o trans转换器.hs
为此,您需要Haskell编译器GHC公司.
为翻译人员制作PGF
然后生成一个PGF文件。例如食物
语法集可以编译如下:
%gf-制作食品工程.gf食品Ita.gf
这将生成文件食品.pgf
(它的名字来自抽象语法)。
Haskell库函数相互作用
使反式
该程序的工作方式类似于Unix过滤器,它从标准输入读取数据并写入标准输出。因此,它可以是管道和读写文件的一部分。最简单的翻译方法是回声
程序输入:
%echo“这酒很好吃”。/反式食品.pgf美味葡萄酒
结果以输入语言以外的所有语言给出。
转换器循环
要避免反复启动翻译器:更改相互作用
在主函数中环
,定义如下:
循环::(字符串->字符串)->IO()回路传输=dos<-getLine如果s==“quit”,则putStrLn“bye”else doputStrLn$trans秒回路变压器
循环继续逐行转换,直到输入行退出
.
问答系统
下一个应用程序也是一个转换器,但它添加了一个转移组件-转换语法树的函数。
我们使用的传递函数是将问题计算为答案的函数。
该程序接受关于算术的简单问题,并用提出问题的语言回答“是”或“否”:
123是素数吗?不。77是否受损?乌伊。
我们通过提供翻译
将传输用作额外参数:
翻译::(树->树)->PGF->String->String
作为特殊情况的普通翻译,其中传递是身份功能(身份证件
哈斯克尔)。
要在中回复相同的作为问题的语言:
translate tr gr=案例parseAllLang gr(startCat gr)s of(lg,t:):->线性化gr-lg(trt)_->“无理由”
查询系统的抽象语法
输入:抽象语法判断
抽象查询={flags startcat=问题;猫答案;问题;对象;乐趣偶数:对象->问题;奇数:对象->问题;质数:宾语->问句;编号:Int->Object;是:回答;否:回答;}
将GF数据类型导出到Haskell
为了便于定义传递函数,我们将抽象语法导出到Haskell数据类型系统:
%gf-make--output-format=haskell查询工程.gf
结果是一个名为查询.hs
,包含名为查询
.
输出:Haskell定义
模块查询,其中导入PGF数据GAnswer=GYes公司|全球导航卫星组织data GObject=G编号GInt数据GQuestion=GPrime G对象|GOdd G对象|GEven G对象newtype GInt=GInt整数
所有类型和构造函数名称都以G公司
以防止冲突。
Haskell模块名称与抽象语法名称相同。
问答功能
Haskell的类型检查器确保函数对于GF也是类型良好的。
答案::GQuestion->GAnswer答案p=案例pGOdd x->测试奇数xGEven x->测试偶数xG素数x->测试素数x值::G对象->Int值e=的情况eG编号(GInt i)->来自整数i测试::(Int->Bool)->GObject->GAnswertest f x=如果f(值x),则GYes else GNo
在Haskell树和GF树之间转换
生成的Haskell模块还包含
类Gf a其中gf::a->树fg::树->a实例Gf GQuestion其中gf(GEven x1)=DTr[](AC(CId“偶数”))[gf x1]gf(GOdd x1)=DTr[](AC(CId“奇数”))[gf x1]gf(G素数x1)=DTr[](AC(CId“素数”))[gf x1]前景t=第t种情况DTr[](AC(CId“偶数”))[x1]->GEven(fg x1)DTr[](AC(CId“奇数”))[x1]->GOdd(fg x1)DTr[](AC(CId“基本”))[x1]->G基本(fg x1)_->错误(“无问题”++显示t)
对于程序员来说,只要知道:
- 所有GF名称都以Haskell为前缀
G公司
玻璃纤维
从Haskell对象转换为GF树
前景
从GF树转换为Haskell对象
总而言之:传输定义
模块TransferDef,其中导入PGF(树)导入查询--从GF生成传输::树->树转移=gf。回答。前景答案::GQuestion->GAnswer答案p=案例pGOdd x->测试奇数xGEven x->测试偶数xG素数x->测试素数x值::G对象->Int值e=的情况eG编号(GInt i)->来自整数i测试::(Int->Bool)->GObject->GAnswertest f x=如果f(值x),则GYes else GNo素数::Int->Bool素数x=元素x素数,其中底漆=筛子[2..x]筛子(p:xs)=p:sieve[n|n<-xs,n`mod`p>0]筛子[]=[]
总而言之:主模块
以下是Haskell文件中的完整代码传输环路
.
模块Main,其中导入PGF导入TransferDef(传输)主::IO()main=做gr<-readPGF“查询.pgf”循环(translate transfer gr)循环::(字符串->字符串)->IO()回路传输=dos<-getLine如果s==“quit”,则putStrLn“bye”else doputStrLn$trans秒回路变压器翻译::(树->树)->PGF->String->Stringtranslate tr gr s=case parseAllLang gr(startCat gr)s的(lg,t:):->线性化gr-lg(trt)_->“无理由”
把它们放在一起:Makefile
为了自动化系统的生产,我们编写了一个生成文件
如下:
全部:gf-make--output-format=haskell QueryEngghc—制造-o。/数学传输环路条形数学
(Makefile中开始命令行的空段必须是制表符。)现在,我们只需键入以下命令即可编译整个系统
制作
然后你可以输入
./数学
总而言之,应用程序的源代码由以下文件组成:
生成文件——生成文件Math.gf—抽象语法数学???.gf——混凝土合成TransferDef.hs——问答功能的定义TransferLoop.hs—Haskell主模块
Web服务器应用程序
PGF文件可以在web服务器中使用,其中包含一个Haskell库src/服务器/
。如何为翻译人员等任务构建服务器在自述文件
文件。
可以使用库轻松构建的服务器之一(无需任何编程)是冰箱诗歌磁铁它是一个使用增量解析器建议语法正确的下一个单词的应用程序。下面是它在食品
语法。

JavaScript应用程序
JavaScript是一种编程语言,在大多数web浏览器中都内置了解释器。因此,它可用于客户端web程序,这些程序甚至可以在不访问internet的情况下运行。下图显示了在iPhone上运行时从GF语法编译的JavaScript程序。

编译为JavaScript
JavaScript是GF批处理编译器的输出格式之一。因此,下面的命令从两个食物
语法。
%gf-make--输出格式=js FoodEng.gf FoodIta.gf
生成文件的名称为食品.js
,派生自最顶层的抽象语法名称。此文件包含作为JavaScript对象的多语言语法。
使用JavaScript语法
要执行解析和线性化,运行时库gflib.js
使用。它包含在/src/runtime/javascript/
以及其他一些JavaScript和HTML文件;这些文件可以用作构建应用程序的模板。
用法示例如下翻译.html
,它实际上是用指向Food语法的指针初始化的,因此它提供了英语和意大利语语法之间的翻译:

语法必须有名称语法.js
。中的抽象语法和开始类别名称翻译.html
必须与语法中的匹配。通过这些更改,翻译人员可以使用任何多语言语法。
语音识别的语言模型
在语音识别中使用GF的标准方法是基于语法的语言模型.
GF支持多种格式,包括GSLNuance语音识别器.
GSL由GF通过运行玻璃纤维
带着国旗--输出格式=gsl
.
示例:GSL生成自食品工程.gf
.
%gf-制造--输出格式=gsl FoodsEng.gf%更多FoodsEng.gsl;GSL2.0;用于FoodsEng的Nuance语音识别语法;由GF生成.主要短语_cat项目_1[(“that”Kind_1)(“this”Kind_)]第2项[(“这些”第2类)(“那些”第2种)]项目_状态[项目_1项目_2]种类_1[“奶酪”“鱼”“披萨”(质量_1种类_1)“葡萄酒”]种类2[“奶酪”“鱼”“披萨”(质量_1类_2)“葡萄酒”]金德_卡特[金德_1金德_2]短语_1[(项目_1为“质量_1”)(第2项“是”质量_1)]短语_cat短语_1质量_1[“无聊”“美味”“昂贵”“新鲜”“意大利语”(“非常”质量_1)“温暖”]质量_猫质量_ 1
其他格式可通过--输出格式
标志包括:
格式
描述
全球供应链
Nuance GSL语音识别语法
jsgf公司
Java语音语法格式(JSGF)
jsgf_sisr_old
带有SISR WD 20030401格式语义标记的JSGF
srgs_abnf公司
SRGS ABNF格式
srgs_xml文件
SRGS XML格式
srgs_xml_prob
SRGS XML格式,带权重
slf公司
HTK SLF格式的有限自动机
slf子
HTK SLF中带子自动机的有限自动机
可以使用查看所有当前可用的格式gf--帮助
.