преобразование дерева вертикальных деревьев в s-выражения - PullRequest
2 голосов
/ 12 мая 2010

У меня есть коллекция деревьев разбора, и они находятся в этом представлении ascii, где отступ определяет структуру (и закрывающие скобки неявны). Мне нужно преобразовать их в s-выражения, чтобы скобки определяли структуру. Это немного похоже на значительные пробелы в питоне против скобок. Формат ввода представляет собой вертикальное представление деревьев, например:

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

1 Ответ

1 голос
/ 12 мая 2010

Сосредоточение только на примере, который вы даете в этом 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)
...