微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

尝试在 GF 中使用依赖类型时出现语法错误 修正语法错误后的完整语法解析 VP:添加 linref元变量添加 linref 并包含 Clude 的空字符串后的完整语法抽象语法具体语法

如何解决尝试在 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 有一个奇怪的要求,即每个参数都需要提供一个字符串(甚至是一个空字符串!),否则解析时无法识别。即使没有歧义,也会发生这种情况。

我们已经用空字符串对 IncludeExclude 进行了线性化——无论如何,它们必须有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 举报,一经查实,本站将立刻删除。