Source code for dae.backends.attributes_query_inheritance
# pylint: disable=too-few-public-methods
import operator
import functools
from lark import Lark, Transformer
from dae.variants.attributes import Inheritance
INHERITANCE_QUERY_GRAMMAR = r"""
reference: "reference"
mendelian: "mendelian"
denovo: "denovo"
possible_denovo: "possible_denovo"
omission: "omission"
possible_omission: "possible_omission"
other: "other"
missing: "missing"
unknown: "unknown"
?primitive: reference
| mendelian
| denovo
| possible_denovo
| omission
| possible_omission
| other
| missing
| unknown
negative_primitive: "not" primitive
atom: primitive
| negative_primitive
atomlist: (atom "," )* atom [","]
all: "all"i "(" atomlist ")"
any: "any"i "(" atomlist ")"
logical_or: atom ("or" atom)+
logical_and: atom ("and" atom)+
expression: atom
| all
| any
| logical_or
| logical_and
%import common.WS
%ignore WS
"""
inheritance_parser = Lark(INHERITANCE_QUERY_GRAMMAR, start="expression")
[docs]class Expression:
def __init__(self, expression):
self.expression = expression
def __str__(self):
return self.expression
[docs]class InheritanceTransformer(Transformer):
"""No idea what this class is supposed to do. If you know please edit."""
# pylint: disable=no-self-use,unused-argument
def __init__(self, attr_name, *args, **kwargs):
super().__init__(*args, **kwargs)
self.attr_name = attr_name
self.inheritance_mask = 16383
[docs] def primitive(self, items):
assert len(items) == 1
return Primitive(Inheritance.from_name(items[0]).value)
[docs] def negative_primitive(self, items):
assert len(items) == 1
assert isinstance(items[0], Primitive)
return NegPrimitive(items[0].value)
[docs] def atom(self, items):
assert len(items) == 1
assert isinstance(items[0], (Primitive, NegPrimitive))
return items[0]
[docs] def atomlist(self, items):
atom_values = [atom.value for atom in items]
mask = functools.reduce(operator.or_, atom_values, 0)
return Primitive(mask)
[docs] def all(self, items):
assert len(items) == 1
assert isinstance(items[0], Primitive)
mask = items[0].value
return Expression(
f"BITAND({mask}, {self.attr_name}) = {mask}")
[docs] def any(self, items):
assert len(items) == 1
assert isinstance(items[0], Primitive)
mask = items[0].value
return Expression(
f"BITAND({mask}, {self.attr_name}) != 0")
def _process_list(self, items):
expressions = []
for atom in items:
if isinstance(atom, Primitive):
expressions.append(
f"BITAND({atom.value}, {self.attr_name}) != 0")
elif isinstance(atom, NegPrimitive):
expressions.append(
f"BITAND({atom.value}, {self.attr_name}) = 0")
elif isinstance(atom, Expression):
expressions.append(atom)
else:
raise ValueError(f"unexpected expression {atom}")
return expressions
[docs] def logical_or(self, items):
expressions = self._process_list(items)
return Expression(" OR ".join(expressions))
[docs] def logical_and(self, items):
expressions = self._process_list(items)
return Expression(" AND ".join(expressions))
[docs] def expression(self, items):
"""Construct an Expression from items."""
if len(items) == 1 and isinstance(items[0], Primitive):
mask = items[0].value
return Expression(f"BITAND({mask}, {self.attr_name}) != 0")
if len(items) == 1 and isinstance(items[0], NegPrimitive):
mask = items[0].value
return Expression(f"BITAND({mask}, {self.attr_name}) = 0")
if len(items) == 1 and isinstance(items[0], Expression):
return items[0].expression
raise NotImplementedError()