如何解决尝试在 GF 中使用依赖类型时出现语法错误 修正语法错误后的完整语法解析 VP:添加 linref元变量添加 linref 并包含 Clude 的空字符串后的完整语法抽象语法具体语法
我正在尝试使用依赖类型,但我遇到了一个语法错误,我似乎无法找到原因。这是我在具体语法中的第一个 lin 定义。
关于上下文,我一直在阅读 Inari 的嵌入式语法教程,我对制作可以从外部调用但实际上不会用于线性化的函数感兴趣,除非我从 Haskell 手动执行。如果您知道实现这一目标的更好方法,请告诉我。
我的抽象语法:
cat
S;
Pre_S Clude ;
VP Clude ;
NP Clude ;
V2 ;
N ;
Clude ;
fun
Include,Exclude : Clude ;
To_S : Pre_S Include -> S ;
Pred : (c : Clude) -> NP c -> VP c -> Pre_S c ;
Compl : (c : Clude) -> V2 -> NP c -> VP c ;
-- I'd like to call this one from Haskell
Scramble : (c : Clude) -> VP c -> VP Exclude ;
To_NP : (c : Clude) -> N -> NP c ;
Bob,Billy,John,Mary,Lisa : N ;
Liked,loved,Hated : V2 ;
混凝土:
lincat
Pre_S,S,V2,NP,N = {s : Str} ;
VP = {fst : Str ; snd : Str} ;
lin
To_S pre = {s = pre.s} ;
Pred _ sub vp = {s = sub ++ vp.fst ++ vp.snd} ;
Compl _ ver obj = {fst = ver ; snd = obj} ;
Scramble _ vp = {fst = vp.snd ; snd = vp.fst } ;
To_NP _ n = {s = n.s} ;
Bob = {s = "Bob"} ; --and seven more like this
是因为这种方式是不可能的,还是我做错了什么,我只是没能找到?
解决方法
1。修复语法错误
您代码中的所有错误都不是由依赖类型引起的。第一个问题,实际的语法错误是这样的:
To_S pre = {s = pre.s} ;
pre
是 GF 中的保留字,不能用作变量名。你可以写例如
To_S pr = {s = pr.s} ;
或更短——因为 To_S
看起来像一个强制函数,你可以这样做:
To_S pr = pr ;
修复后,您会收到新的错误消息:
Happened in linearization of Pred
type of sub
expected: Str
inferred: {s : Str}
Happened in linearization of Compl
type of ver
expected: Str
inferred: {s : Str}
Happened in linearization of Compl
type of obj
expected: Str
inferred: {s : Str}
这些固定如下。您不能将 {s : Str}
放入应该包含 Str 的字段中,因此您需要访问 sub.s、ver.s 和obj.s.
Pred _ sub vp = {s = sub.s ++ vp.fst ++ vp.snd} ;
Compl _ ver obj = {fst = ver.s ; snd = obj.s} ;
修正语法错误后的完整语法
这对我有用。
lin
To_S pr = pr ;
Pred _ sub vp = {s = sub.s ++ vp.fst ++ vp.snd} ;
Compl _ ver obj = {fst = ver.s ; snd = obj.s} ;
Scramble _ vp = {fst = vp.snd ; snd = vp.fst } ;
To_NP _ n = {s = n.s} ;
Bob = {s = "Bob"} ;
Loved = {s = "loved"} ; -- just add rest of the lexicon
Include,Exclude = {s = ""} ; -- these need to have a linearisation,otherwise nothing works!
2.使用语法的提示和技巧
使用 Bob 和 Loved 的词典,它正好生成了一棵树。当我使用命令 gt
(generate_trees) 时,如果我不给出类别标志,它会自动使用开始类别,即 S。
> gt | l -treebank
To_S (Pred Include (To_NP Include Bob) (Compl Include Loved (To_NP Include Bob)))
Bob loved Bob
S 中的解析也有效:
p "Bob loved Bob"
To_S (Pred Include (To_NP Include Bob) (Compl Include Loved (To_NP Include Bob)))
解析 VP:添加 linref
使用当前的语法,我们无法解析任何 VP:
> p -cat="VP ?" "Bob loved"
The parser failed at token 2: "loved"
> p -cat="VP ?" "loved Bob"
The parser failed at token 2: "Bob"
那是因为 VP 的 lincat 是不连续的,并且没有一个 s
字段。但是,如果您还想解析 VP,则可以为 VP 的类别添加 linref,如下所示:
linref
VP = \vp -> vp.fst ++ vp.snd ;
现在它甚至可以解析 VP,有点:
Cl> p -cat="VP ?" "loved Bob"
Compl ?3 Loved (To_NP ?3 Bob)
这些奇怪的问号是元变量,我们接下来会修复它。
元变量
如果您读过我的博客,您可能已经看过有关元变量的一些内容:https://inariksit.github.io/gf/2018/08/28/gf-gotchas.html#metavariables-or-those-question-marks-that-appear-when-parsing
GF 有一个奇怪的要求,即每个参数都需要提供一个字符串(甚至是一个空字符串!),否则解析时无法识别。即使没有歧义,也会发生这种情况。
我们已经用空字符串对 Include
和 Exclude
进行了线性化——无论如何,它们必须有some 线性化,否则整个语法都不起作用。所以我们需要将 Clude
的空字符串添加到所有的线性化中,否则 GF 解析器会混淆。
在您刚刚用下划线标记 Clude
参数的所有线性化中,我们现在这样做。不管我们将它添加到哪个字段,它只是一个空字符串,对输出没有影响。
Pred _clu sub vp = {s = sub.s ++ vp.fst ++ vp.snd ++ _clu.s} ;
Compl _clu ver obj = {fst = ver.s ; snd = obj.s ++ _clu.s} ;
Scramble _clu vp = {fst = vp.snd ; snd = vp.fst ++ _clu.s} ;
To_NP _clu n = {s = n.s ++ _clu.s} ;
在此之后,VP 中的解析工作没有问号:
Cl> p -cat="VP ?" "loved Bob"
Compl Exclude Loved (To_NP Exclude Bob)
Compl Include Loved (To_NP Include Bob)
Cl> p -cat="VP ?" "Bob loved"
Scramble Exclude (Compl Exclude Loved (To_NP Exclude Bob))
我仍然得到元变量????
所以我们修复了它,但是为什么当我 gt
并获得使用 Scramble
的树时我仍然会得到问号?
> gt -cat="VP Exclude"
Compl Exclude Loved (To_NP Exclude Bob)
Scramble ?3 (Compl ?3 Loved (To_NP ?3 Bob))
Scramble Exclude (Scramble ?4 (Compl ?4 Loved (To_NP ?4 Bob)))
> gt -cat="VP Include"
Compl Include Loved (To_NP Include Bob)
那是因为 Scramble
操作确实抑制了它的参数。这不仅仅是 GF 编译器愚蠢并拒绝合作的情况,即使很明显存在哪个参数,在这种情况下也无法检索它是哪个参数:Scramble 使所有内容都变成了 VP Exclude
。>
添加 linref 并包含 Clude 的空字符串后的完整语法
为了完整起见,这里是所有更改。
lin
To_S pr = pr ;
Pred _clu sub vp = {s = sub.s ++ vp.fst ++ vp.snd ++ _clu.s} ;
Compl _clu ver obj = {fst = ver.s ; snd = obj.s ++ _clu.s} ;
Scramble _clu vp = {fst = vp.snd ; snd = vp.fst ++ _clu.s} ;
To_NP _clu n = {s = n.s ++ _clu.s} ;
Bob = {s = "Bob"} ;
Loved = {s = "loved"} ;
Include,Exclude = {s = ""} ;
linref
VP = \vp -> vp.fst ++ vp.snd ;
3.使此文法没有依赖类型的替代方法
如果您想在 C 运行时使用 Python 中的语法或 Haskell 绑定,那么您就不走运了:C 运行时不支持依赖类型。因此,这是您的语法版本,我们使用具体语法中的参数和 nonExist
标记(请参阅 https://inariksit.github.io/gf/2018/08/28/gf-gotchas.html#raise-an-exception)来模拟行为。
我将文档保持在最少(因为这个答案已经很长了?),但是如果您对此解决方案的某些部分有任何疑问,请提出!
抽象语法
cat
S ; VP ; NP ; V2 ; N ;
fun
Pred : NP -> VP -> S ;
Compl : V2 -> NP -> VP ;
Scramble : VP -> VP ;
To_NPIncl,ToNPExcl : N -> NP ;
Bob,Billy,John,Mary,Lisa : N ;
Liked,Loved,Hated : V2 ;
具体语法
param
Clude = Include | Exclude ;
lincat
-- To mimic your categories VP Clude and NP Clude,-- we add a parameter in VP and NP
VP = {fst,snd : Str ; clude : Clude} ;
NP = {s : Str ; clude : Clude} ;
-- The rest are like in your grammar
S,V2,N = {s : Str} ;
lin
-- No need for Pre_S,we can match NP's and VP's Clude in Pred
-- Only make a sentence if both's Clude is Include
Pred np vp = case <np.clude,vp.clude> of {
<Include,Include> => {s = np.s ++ vp.fst ++ vp.snd} ;
_ => {s = Predef.nonExist}
} ;
-- As per your grammar,V2 has no inherent Clude,but NP does
Compl v2 np = {
fst = v2.s ;
snd = np.s ;
clude = np.clude ;
} ;
-- Scramble doesn't look at it's argument VP's clude,-- just makes it into Exclude automatically.
Scramble vp = {
fst = vp.snd ;
snd = vp.fst ;
clude = Exclude ;
} ;
-- Your grammar has the function To_NP : (c : Clude) -> N -> NP c ;
-- We translate it into two functions.
To_NPIncl n = n ** {clude = Include} ;
To_NPExcl n = n ** {clude = Exclude} ;
-- Finally,lexicon.
Bob = {s = "Bob"} ;
Loved = {s = "loved"} ;
现在,当我们生成类别 S 中的所有树时,有一个使用了 Scramble,但它没有线性化。
> gt | l -treebank
ClParam: Pred (To_NPIncl Bob) (Compl Loved (To_NPIncl Bob))
ClParamEng: Bob loved Bob
ClParam: Pred (To_NPIncl Bob) (Scramble (Compl Loved (To_NPIncl Bob)))
ClParamEng:
可能没有你的版本那么优雅,其中树甚至没有生成,但这只是为了演示不同的方法。如果您正在使用 Haskell 并且不需要使用 C 运行时,请继续使用您的方法!
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。