Domanda

Ho una collezione di alberi di analisi, e sono in questa rappresentazione ASCII dove indentazione determina la struttura (e staffe di chiusura sono implicite). Ho bisogno di convertirli in s-espressioni in modo che le parentesi determinano la struttura. E 'un po' come significativi bretelle spazi bianchi contro di pitone. Il formato di ingresso è una rappresentazione verticale degli alberi, in questo modo:

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
.

Dovrebbe diventare:

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

Ho codice che quasi lo fa, ma non del tutto. C'è sempre una qualche parentesi mancante; si sta facendo molto frustrante. Dovrei usare un parser corretto, forse un CFG? L'(disordinato) il codice attuale è a http://github.com/andreasvc/ eodop / blob / master / arbobanko.py

È stato utile?

Soluzione

concentrandosi solo sul l'esempio si sta dando in questo Q, e il titolo del Q sulla conversione di alberi verticali per S-espressioni, qualcosa come ...:

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()

sembra funzionare, e le uscite

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

Mi rendo conto che stai cercando di fare molto di più "pulizia" di quello che sto facendo qui, ma che può essere concentrata nella funzione clean, lasciando reparse a che fare con il titolo del Q. Se non si desidera stampare, come si va, ma piuttosto restituire il risultato come una stringa, i cambiamenti sono ovviamente molto minore:

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)
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top