Source code for fosf.parsers.rdf

#!/usr/bin/env python3

from lark import Lark, Transformer
from rdflib import XSD, Graph, Namespace

from fosf.config import FOSF_GRAMMAR
from fosf.syntax.base import LiteralSort, URISort


class _RDFTransformer(Transformer):
    def __init__(self):
        super().__init__()
        self.prefix: dict
        self.triples: set[tuple]

    def prefix_dec(self, tree):
        if len(tree) == 1:
            prefix = ""
            uriref = URISort(tree[0])
        else:
            prefix = tree[0].value
            uriref = URISort(tree[1])
        self.prefix[prefix] = uriref

    def literal(self, tree):
        return tree[0]

    def decimal_literal(self, tree):
        if len(tree) == 2:
            value = tree[0].value + tree[1].value.strip('"')
        else:
            value = tree[0].value.strip('"')
        return LiteralSort(value, datatype=XSD.decimal)

    def integer_literal(self, tree):
        if len(tree) == 2:
            value = tree[0].value + tree[1].value.strip('"')
        else:
            value = tree[0].value.strip('"')
        return LiteralSort(value, datatype=XSD.integer)

    def simple_literal(self, tree):
        return LiteralSort(tree[0].value.strip('"'))

    def language_literal(self, tree):
        return LiteralSort(tree[0].value.strip('"'), lang=tree[1].value)

    def datatype_literal(self, tree):
        return LiteralSort(tree[0].value.strip('"'), datatype=tree[1])

    def uriref(self, tree):
        return URISort(tree[0].strip("<|>"))

    def qname(self, tree):
        prefix = tree[0].value if tree[0] is not None else ""
        if prefix not in self.prefix:
            raise KeyError(f"Prefix '{prefix}' not defined")
        prefix = self.prefix[prefix]
        local_name = tree[1].value
        uri = URISort(prefix + local_name)
        return uri

    def triple(self, tree):
        s, p, o = tree[0], tree[1], tree[2]
        self._rdf_graph.add((s, p, o))

    def rdf_graph(self, tree):
        return self._rdf_graph

    def subject(self, tree):
        return tree[0]

    def predicate(self, tree):
        return tree[0]

    def object(self, tree):
        o = tree[0]
        if isinstance(o, LiteralSort):
            return o
        return o

    def base_dec(self, tree):
        if self.base is None:
            self.base = Namespace(tree[0].value.strip("<|>"))
        else:
            new_base = Namespace(tree[0].value.strip("<|>"))
            if self.base != new_base:
                msg = (
                    "At most one base URI must be specified. "
                    f"Current base: {self.base}. Found: {new_base}"
                )
                raise RuntimeError(msg)

    def transform(self, tree):
        self.base: Namespace | None = None
        self.prefix = dict()
        self.triples = set()
        self._rdf_graph = Graph()
        return super().transform(tree)


[docs] class RDFParser: def __init__(self): self.parser = Lark.open_from_package("fosf", FOSF_GRAMMAR, start="rdf_graph") self.transformer = _RDFTransformer()
[docs] def parse(self, expression: str, **kwargs): parse_tree = self.parser.parse(expression) return self.transformer.transform(parse_tree, **kwargs)