la conversione di un Treebank di alberi verticali per s-espressioni
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
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)