Source code for ehn.parse.node.base

#!/usr/bin/env python
# -*- coding:utf-8 -*-

"""
Please refer the tutorial ":ref:`tutorial-parse_node`".
"""

__author__ = "Mu Yang <http://muyang.pro>"
__copyright__ = "2018-2021 CKIP Lab"
__license__ = "GPL-3.0"

# pylint: disable=protected-access


from abc import (
    ABCMeta,
    abstractmethod,
)

from collections.abc import (
    Sequence,
)

from treelib import (
    Tree,
)

################################################################################################################################
# Tree
#
[docs]class EhnParseTree(Tree):
[docs] def show(self, *args, data_property="_tree_label", **kwargs): # pylint: disable=arguments-differ """Print the tree structure.""" super().show(*args, data_property=data_property, **kwargs)
def to_str(self, *args, data_property="_tree_label", **kwargs): def write(line): nonlocal ret ret += line.decode() + "\n" ret = "" self.Tree__print_backend(*args, data_property=data_property, **kwargs, func=write) # pylint: disable=no-member return ret
################################################################################################################################ # Base #
[docs]class EhnParseNode(metaclass=ABCMeta): """E-HowNet Parsing: Base Node""" def __init__(self): self.__tree = None # pylint: disable=unused-private-member @property @abstractmethod def node_type(self): return NotImplemented @abstractmethod def dumps(self): return NotImplemented @property def _tree_label(self): _anchor = f" ${self.anchor.head}" if hasattr(self, "anchor") and self.anchor.head else "" # pylint: disable=no-member _text = f" {self._tree_label_text}" if hasattr(self, "_tree_label_text") else "" # pylint: disable=no-member return f"[{self.node_type}{_anchor}]{_text}" def __str__(self): return f"<{self.__class__.__name__} {self.head}>" # pylint: disable=no-member def __repr__(self): return str(self) ################################################################################# @abstractmethod def children(self): return NotImplemented def descendant(self): yield self for child in self.children(): yield from child.descendant() def tree(self): tree = EhnParseTree() self._create_tree(tree, None) return tree def _create_tree(self, tree, parent): idx = tree.create_node(parent=parent, data=self).identifier for child in self.children(): child._create_tree(tree, idx) ################################################################################# def get_features(self, key=None): res = getattr(self, "features", []) return res if not key else [feature for feature in res if feature.head == key] def get_arguments(self): return getattr(self, "arguments", []) def get_value(self): return getattr(self, "value", None) def get_function(self): return getattr(self, "function", None) def get_anchor(self): return getattr(self, "anchor", None) def get_coindex(self): return getattr(self.get_anchor(), "head", None)
################################################################################################################################ # Base Types #
[docs]class EhnParseEntityLike(EhnParseNode): # pylint: disable=abstract-method """E-HowNet Parsing: Entity Like Node"""
[docs]class EhnParseEntityBase(EhnParseEntityLike): # pylint: disable=abstract-method """E-HowNet Parsing: Base Entity Node"""
[docs]class EhnParseReferenceBase(EhnParseEntityLike): # pylint: disable=abstract-method """E-HowNet Parsing: Base Reference Node"""
[docs]class EhnParsePlaceholderBase(EhnParseEntityLike): # pylint: disable=abstract-method """E-HowNet Parsing: Base Placeholder Node"""
[docs]class EhnParseFeatureBase(EhnParseNode): # pylint: disable=abstract-method """E-HowNet Parsing: Base Feature Node"""
[docs]class EhnParseFunctionBase(EhnParseNode): # pylint: disable=abstract-method """E-HowNet Parsing: Base Function Node"""
[docs]class EhnParseSubjectBase(EhnParseNode): # pylint: disable=abstract-method """E-HowNet Parsing: Base Subject Node"""
################################################################################################################################ # Anchor #
[docs]class EhnParseAnchor: """E-HowNet Parsing: Node Anchor""" def __init__(self, head=None): self.head = head def __str__(self): return self.head if self.head else "" def __repr__(self): return str(self) def dumps(self): return f"_{self.head}" if self.head else ""
################################################################################################################################ # Heads #
[docs]class EhnParseStrHead(metaclass=ABCMeta): """E-HowNet Parsing: Base Node with String Head""" def __init__(self, head): self.head = head @property def head(self): return self._head @head.setter def head(self, head): assert isinstance(head, str), f"‘{head}’ is not a str!" self._head = head # pylint: disable=attribute-defined-outside-init @property def _tree_label_text(self): return self.head
################################################################
[docs]class EhnParseFunctionHead(metaclass=ABCMeta): """E-HowNet Parsing: Base Node with Function Head""" def __init__(self, function): self.function = function @property def head(self): return self.function.head @property def function(self): return self._function @function.setter def function(self, function): assert isinstance(function, EhnParseFunctionBase), f"‘{function}’ is not a Function!" self._function = function # pylint: disable=attribute-defined-outside-init
################################################################################################################################ # Bodies #
[docs]class EhnParseValueBody(metaclass=ABCMeta): """E-HowNet Parsing: Base Node with Value""" @property @abstractmethod def value_type(self): return NotImplemented def __init__(self, value): self.value = value @property def value(self): return self._value @value.setter def value(self, value): assert isinstance( # pylint: disable=isinstance-second-argument-not-valid-type value, self.value_type ), f"‘{value}’ is not a {self.value_type}!" self._value = value # pylint: disable=attribute-defined-outside-init
[docs]class EhnParseFeatureBody(Sequence, metaclass=ABCMeta): """E-HowNet Parsing: Base Node with Feature""" @property @abstractmethod def feature_type(self): return NotImplemented def __init__(self, *features): self.features = features @property def features(self): return self._features @features.setter def features(self, features): self._features = [] # pylint: disable=attribute-defined-outside-init for feature in features: self.add_feature(feature) def add_feature(self, feature): assert isinstance( # pylint: disable=isinstance-second-argument-not-valid-type feature, self.feature_type ), f"‘{feature}’ is not a {self.feature_type}!" self._features.append(feature) def __getitem__(self, key): return self._features[key] def __len__(self): return len(self._features)
[docs]class EhnParseArgumentBody(Sequence, metaclass=ABCMeta): """E-HowNet Parsing: Base Node with Argument""" @property @abstractmethod def argument_type(self): return NotImplemented def __init__(self, *arguments): self.arguments = arguments @property def arguments(self): return self._arguments @arguments.setter def arguments(self, arguments): self._arguments = [] # pylint: disable=attribute-defined-outside-init for argument in arguments: self.add_argument(argument) def add_argument(self, argument): assert isinstance( # pylint: disable=isinstance-second-argument-not-valid-type argument, self.argument_type ), f"‘{argument}’ is not a {self.argument_type}!" self._arguments.append(argument) def __getitem__(self, key): return self._arguments[key] def __len__(self): return len(self._arguments)
################################################################
[docs]class EhnParseAnchorBody(metaclass=ABCMeta): """E-HowNet Parsing: Base Node with Anchor""" def __init__(self, *, coindex=None, anchor=None): self.anchor = anchor or EhnParseAnchor(coindex) @property def anchor(self): return self._anchor @anchor.setter def anchor(self, anchor): assert isinstance(anchor, EhnParseAnchor), f"‘{anchor}’ is not an Anchor!" self._anchor = anchor # pylint: disable=attribute-defined-outside-init