Source code for segram.nlp.grammar.sent

from typing import Iterable
from abc import abstractmethod
from .grammar import GrammarNLP
from ..tokens import Span
from ...grammar import Phrase, Sent, PhraseGraph, Conjuncts
from ...symbols import Dep


[docs] class SentNLP(GrammarNLP, Sent): """Abstract base class for sentence elements with NLP backend methods. """ __slots__ = ()
[docs] @abstractmethod def find_conjs(self) -> Iterable[Conjuncts]: """Iterate over groups of conjoined components."""
[docs] @abstractmethod def add_subs(self) -> None: """Add free subtree tokens to components."""
# Methods -----------------------------------------------------------------
[docs] @classmethod def from_sent(cls, sent: Span) -> Sent: """Construct from a sentence span object.""" # pylint: disable=protected-access sent = cls(sent) for tok in sent.sent: for typ in ("Noun", "Verb", "Prep", "Desc"): try: cls.types[typ].from_tok(tok) except AttributeError: continue sent.add_subs() sent.graph = PhraseGraph.from_links(sent.find_links()) sent.conjs = { conj.lead.idx: conj for conj in sorted(sent.find_conjs()) } sent.make_mutable_children() sent.destroy_conjunct_links() sent.propagate_children_conjuncts() sent.propagate_subjects() sent.propagate_descriptions() sent.propagate_cdesc_subclauses() sent.freeze_children() return sent
[docs] def make_mutable_children(self) -> None: """Make children lists in ``self.graph`` mutable sets.""" for phrase, children in self.graph.items(): self.graph[phrase] = set(children)
[docs] def propagate_children_conjuncts(self) -> None: """Propagate conjuncts of children to their parents.""" for phrase in self.graph: for child in tuple(phrase.children): if not child.is_lead: continue for conj in child.conjuncts: if conj.dep & Dep.conj: self.graph[phrase].add(conj)
[docs] def propagate_subjects(self) -> None: """Propagete subjects to subject-free conjuncts.""" for phrase in self.graph: if phrase.is_lead and (conjs := phrase.conjuncts): for conj in conjs: if conj.subj: continue for child in phrase.children: if child.dep & Dep.subj: self.graph[conj].add(child)
[docs] def propagate_descriptions(self) -> None: """Propagate descriptions to description-free conjuncts.""" for phrase in self.graph: if phrase.is_lead and (conjs := phrase.conjuncts): for conj in conjs: if conj.desc: continue for child in phrase.children: if child.dep & Dep.desc: self.graph[conj].add(child)
[docs] def propagate_cdesc_subclauses(self) -> None: """Propagate subclauses between clausal descriptions.""" for phrase in self.graph: if phrase.dep & Dep.cdesc and phrase.is_lead \ and (conjs := phrase.conjuncts): for conj in conjs: if conj.subcl: continue for child in phrase.children: if child.dep & Dep.subcl: self.graph[conj].add(child)
[docs] def freeze_children(self) -> None: """Freeze children lists.""" for phrase, children in self.graph.items(): self.graph[phrase] = tuple(sorted(children)) self.graph.update_rev()