Skip to main content
 首页 » 编程设计

python之将垂直树的树库转换为 s 表达式

2025年05月04日7grandyang

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

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

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

请您参考如下方法:

仅关注您在此 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)