【问题标题】:converting a treebank of vertical trees to s-expressions将垂直树的树库转换为 s 表达式
【发布时间】:2010-05-11 22:58:28
【问题描述】:

我有一个解析树的集合,它们在这个 ascii 表示中,缩进决定了结构(并且右括号是隐式的)。我需要将它们转换为 s 表达式,以便括号确定结构。这有点像 python 的重要空格与大括号。输入格式是树的垂直表示,如下所示:

STA:fcl
=S:np
==DN:pron-dem("tia" <*> <Dem> <Du> <dem> DET P NOM)     Tiaj
==H:n("akuzo" <act> <sd> P NOM) akuzoj
=fA:adv("certe")        certe
=P:v-fin("dauxri" <va+TEMP> <mv> FUT VFIN)      dauxros
.

应该变成:

(STA:fcl (S:np (DN:pron-dem Tiaj) (H:n akuzoj)) (fA:adv certe) (P:v-fin dauxros) .)

我的代码几乎可以做到,但并不完全。某处总是缺少父母;它变得非常令人沮丧。我应该使用适当的解析器,也许是 CFG?当前(混乱)代码在http://github.com/andreasvc/eodop/blob/master/arbobanko.py

【问题讨论】:

    标签: python corpus


    【解决方案1】:

    仅关注您在此 Q 中给出的示例,以及 Q 的关于将垂直树转换为 S 表达式的标题,例如...:

    import re
    import sys
    
    samp='''S
    =NP
    ==(DT +def) the
    == (N +ani) man
    =VP
    ==V walks'''.splitlines()
    
    relinelev = re.compile(r'(=*)(.*)')
    reclean = re.compile(r'\s*\((\S+)[^)]*\)')
    
    def clean(line):
      return reclean.sub(r'\1', line)
    
    def reparse(tree=samp):
      stack = [-1]
      for line in tree:
        equals, rest = relinelev.match(line).groups()
        linelev = len(equals)
        while linelev < stack[-1]:
          sys.stdout.softspace = False
          print ')',
          curlev = stack.pop()
        if linelev == stack[-1]:
          sys.stdout.softspace = False
          print ')',
        else:
          stack.append(linelev)
        print '(%s' % clean(rest),
      while stack[-1] >= 0:
        sys.stdout.softspace = False
        print ')',
        stack.pop()
      print
    
    reparse()
    

    似乎工作,并输出

    (S (NP (DT the) (N man)) (VP (V walks)))
    

    我意识到你正在尝试做比我在这里做的更多的“清理”,但这可以集中在clean 函数中,让reparse 处理 Q 的标题。如果您不想随时打印,而是将结果作为字符串返回,那么更改当然很小:

    def reparse(tree=samp):
      stack = [-1]
      result = []
      for line in tree:
        equals, rest = relinelev.match(line).groups()
        linelev = len(equals)
        while linelev < stack[-1]:
          result[-1] += ')'
          curlev = stack.pop()
        if linelev == stack[-1]:
          result[-1] += ')'
        else:
          stack.append(linelev)
        result.append('(%s' % clean(rest))
      while stack[-1] >= 0:
        result[-1] += ')'
        stack.pop()
      return ' '.join(result)
    

    【讨论】:

    • 非常感谢!我什至不知道splitlines()。如果我将您的代码添加到我的 git 存储库中可以吗?当然,我会 GPL 并给你荣誉。当树在根级别有尾叶时,您的代码将失败,我在代码的 x 次不正确迭代之一中也遇到了这个问题...我将更新 Q 以反映这一点。
    • 使用您当前的示例和稍微不同的clean 函数(删除括号部分和后面的空格)我的代码给出了(STA:fcl (S:np (DN:pron-dem Tiaj) (H:n akuzoj)) (fA:adv certe) (P:v-fin dauxros)),这似乎正是您需要的,所以我看不到在什么意义上它“当树在根部有尾叶时失败”,无论它是什么意思。请再次编辑您的 Q 以显示我的代码 失败 的示例,否则我该如何解决?当然,一旦代码是正确的(或者至少它的失败案例有据可查),你就可以使用它。
    • 如果你仔细看我的例子,你会明白我的意思:最后一行有一个句点,它应该成为树的一部分,就在最后一个结束括号之前。但是现在我想起来,这似乎很奇怪,因为如果它是根 STA:fcl 的子节点,那么它应该用一个等号缩进。也许我应该只使用临时修复来添加转换后的句点。
    • 是的,我绝对推荐一个临时修复,因为正如你所说,它不遵循与其他节点相同的规则——如果最后总是有一个句点,那么首先删除它,在上面运行我的代码,然后将最后一个关闭的括号更改为.) - 不太难。
    • 也许是因为句号不被认为是句子的一部分,句子和句号都是隐式根节点的子节点。期间并不总是存在,例如。在标题中它们不是(因为它们只是句子片段)。不管怎样,谢谢你的帮助,我认为问题已经解决了。
    猜你喜欢
    • 2012-01-15
    • 1970-01-01
    • 1970-01-01
    • 2011-01-08
    • 2018-03-05
    • 2011-04-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多