Source code for fosf.parsers.taxonomy

#!/usr/bin/env python3

from collections import defaultdict

import networkx as nx
from lark import Lark

from fosf.parsers.base import BaseOSFParser, _BaseOSFTransformer
from fosf.syntax.base import Sort
from fosf.syntax.taxonomy import SortTaxonomy, FuzzySortTaxonomy


TAXONOMY_GRAMMAR = "grammars/taxonomy.lark"


class _GraphTransformer(_BaseOSFTransformer):

    def __init__(self):
        super().__init__()
        self.decs = []
        self.fuzzy = False

    def sorts(self, tree):
        return [t.value for t in tree]

    def fuzzysort(self, tree):
        "Handle a sort with an approximation degree."
        if len(tree) > 1:
            weight = float(tree[1].value)
            if weight < 1:
                self.fuzzy = True
            return (tree[0].value, weight)
        return (tree[0].value, 1.0)

    def fuzzysorts(self, tree):
        "Handle a list of sorts associated with an approximation degree."
        return tree

    def declaration(self, tree):
        self.decs.extend([(subsort, supersort[0], supersort[1])
                          for subsort in tree[0]
                          for supersort in tree[1]])

    def declarations(self, _):
        g = nx.DiGraph()
        for u, v, w in self.decs:
            g.add_edge(u, v, weight=w)
        return g

    def transform(self, parse_tree) -> nx.DiGraph:
        self.decs = []
        return super().transform(parse_tree)


[docs] class GraphParser(BaseOSFParser): def __init__(self): self.parser = Lark.open_from_package("fosf.parsers", TAXONOMY_GRAMMAR, parser="lalr") self.transformer = _GraphTransformer()
[docs] def parse(self, expression: str) -> nx.DiGraph: parse_tree = self.parser.parse(expression) return self.transformer.transform(parse_tree)
class _TaxonomyTransformer(_GraphTransformer): def __init__(self): super().__init__() self._instances = defaultdict(dict) def baseinstance(self, tree): return tree[0].value, 1.0 def fuzzyinstance(self, tree): degree = float(tree[0].value) instance = tree[1].value return instance, degree def instance(self, tree): return tree[0] def instances(self, tree): return tree def instance_dec(self, tree): instances = tree[0] sorts = tree[1] for instance, degree in instances: for sort in sorts: self._instances[instance][Sort(sort)] = degree def declarations(self, _) -> SortTaxonomy: if self.fuzzy: return FuzzySortTaxonomy(self.decs, instances=self._instances) return SortTaxonomy(self.decs, instances=self._instances) def transform(self, parse_tree): self.decs = [] self.fuzzy = False return super().transform(parse_tree)
[docs] class TaxonomyParser(BaseOSFParser): def __init__(self): self.parser = Lark.open_from_package("fosf.parsers", TAXONOMY_GRAMMAR, parser="lalr") self.transformer = _TaxonomyTransformer()
[docs] def parse(self, expression: str) -> SortTaxonomy: parse_tree = self.parser.parse(expression) return self.transformer.transform(parse_tree)