Source code for discopy.grammar.ccg
# -*- coding: utf-8 -*-
"""
Implements combinatory categorial grammars.
"""
import re
from discopy.grammar import cfg
from discopy.biclosed import Ty, Box, Id, FA, BA, FC
[docs]class Word(cfg.Word, Box):
""" Word with a :class:`discopy.biclosed.Ty` as codomain. """
[docs]def cat2ty(string):
"""
Takes the string repr of a CCG category,
returns a :class:`discopy.biclosed.Ty`. """
def unbracket(string):
return string[1:-1] if string[0] == '(' else string
def remove_modifier(string):
return re.sub(r'\[[^]]*\]', '', string)
def split(string):
par_count = 0
for i, char in enumerate(string):
if char == "(":
par_count += 1
elif char == ")":
par_count -= 1
elif char in ["\\", "/"] and par_count == 0:
return unbracket(string[:i]), char, unbracket(string[i + 1:])
return remove_modifier(string), None, None
left, slash, right = split(string)
if slash == '\\':
return cat2ty(right) >> cat2ty(left)
if slash == '/':
return cat2ty(left) << cat2ty(right)
return Ty(left)
[docs]def tree2diagram(tree, dom=Ty()):
"""
Takes a depccg.Tree in JSON format,
returns a :class:`discopy.biclosed.Diagram`.
"""
if 'word' in tree:
return Word(tree['word'], cat2ty(tree['cat']), dom=dom)
children = list(map(tree2diagram, tree['children']))
dom = Ty().tensor(*[child.cod for child in children])
cod = cat2ty(tree['cat'])
if tree['type'] == 'ba':
box = BA(dom[1:])
elif tree['type'] == 'fa':
box = FA(dom[:1])
elif tree['type'] == 'fc':
box = FC(dom[:1], dom[1:])
else:
box = Box(tree['type'], dom, cod)
return Id(Ty()).tensor(*children) >> box