Source code for fosf.parsers.clause

#!/usr/bin/env python3

from lark import Lark

from fosf.config import FOSF_GRAMMAR
from fosf.parsers.base import BaseOSFParser, _BaseOSFTransformer
from fosf.parsers.taxonomy import _TaxonomyTransformer
from fosf.syntax.base import Tag
from fosf.syntax.constraints import (
    Clause,
    EqualityConstraint,
    FeatureConstraint,
    RootedClause,
    RootedSolvedClause,
    SolvedClause,
    SortConstraint,
)


class _OsfConstraintTransformer(_BaseOSFTransformer):
    def __init__(self):
        super().__init__()
        self.osf_clause = Clause()
        self.root = None

    def clause(self, _):
        return self.osf_clause

    def sort_constraint(self, tree):
        X = Tag(tree[0].value)
        s = tree[1]
        return self.osf_clause.add(SortConstraint(X, s))

    def feature_constraint(self, tree):
        X = Tag(tree[0].value)
        f = tree[1]
        Y = Tag(tree[2].value)
        return self.osf_clause.add(FeatureConstraint(X, f, Y))

    def equality_constraint(self, tree):
        X = Tag(tree[0].value)
        Y = Tag(tree[1].value)
        return self.osf_clause.add(EqualityConstraint(X, Y))

    def prefixed_clause(self, tree):
        return tree[-1]

    def transform(self, parse_tree, create_using=None, root=None):
        if create_using is None:
            if root is None:
                self.osf_clause = Clause()
            else:
                self.osf_clause = RootedClause(root)
        elif root is None:
            if create_using in {RootedClause, RootedSolvedClause}:
                msg = f"A root must be specified for a clause of type {create_using}"
                raise TypeError(msg)
            self.osf_clause = create_using()
        else:
            if create_using in {Clause, SolvedClause}:
                msg = f"Clauses of type {create_using} do not require a root"
                raise TypeError(msg)
            if isinstance(root, str):
                root = Tag(root)
            self.osf_clause = create_using(root)
        return super().transform(parse_tree)


[docs] class OsfConstraintParser(BaseOSFParser): def __init__(self): self.parser = Lark.open_from_package( "fosf", FOSF_GRAMMAR, start="prefixed_clause" ) self.transformer = _OsfConstraintTransformer()
[docs] def parse(self, expression: str, create_using=None, root=None) -> Clause: parse_tree = self.parser.parse(expression) return self.transformer.transform(parse_tree, create_using, root)
class _QueryClauseTransformer(_OsfConstraintTransformer): def q_tag(self, tree): tag = Tag(tree[-1].value) if len(tree) == 2: self._query_tags.add(tag) return tag def query_clause(self, _): return self.osf_clause def sort_constraint(self, tree): X = tree[0] s = tree[1] return self.osf_clause.add(SortConstraint(X, s)) def feature_constraint(self, tree): X = tree[0] f = tree[1] Y = tree[2] return self.osf_clause.add(FeatureConstraint(X, f, Y)) def equality_constraint(self, tree): X = tree[0] Y = tree[1] return self.osf_clause.add(EqualityConstraint(X, Y)) def prefixed_query_clause(self, tree): return tree[-1] def transform(self, parse_tree, create_using=None, root=None): self._query_tags = set() clause = super().transform(parse_tree, create_using, root) return self._query_tags, clause
[docs] class QueryClauseParser(BaseOSFParser): def __init__(self): self.parser = Lark.open_from_package("fosf", FOSF_GRAMMAR, start="prefixed_query_clause") self.transformer = _QueryClauseTransformer()
[docs] def parse(self, expression: str, create_using=None, root=None) -> Clause: parse_tree = self.parser.parse(expression) return self.transformer.transform(parse_tree, create_using, root)
class _NormalizationTransformer(_TaxonomyTransformer, _OsfConstraintTransformer): def norm_program(self, tree): taxonomy = tree[0] clause = tree[1] return taxonomy, clause
[docs] class NormalizationParser(BaseOSFParser): def __init__(self): self.parser = Lark.open_from_package("fosf", FOSF_GRAMMAR, start="norm_program") self.transformer = _NormalizationTransformer()