Source code for ahbicht.expressions.base_transformer
"""
This module implements the base class for the condition check Transformers
that evaluate trees build from the condition_expression_parser.
"""
from abc import ABC, abstractmethod
from typing import Generic, Mapping, TypeVar
from lark import Token, Transformer, v_args
# All non-abstract transformers obey the following generic type constraints:
# 1. The methods of each transformer all have the same accepted argument type ("TSupportedArgumentNodeType").
# This type is arbitrary but fixed per Transformer.
# 2. Also, all the methods of one transformer return objects of the same type ("TSupportedReturnType").
SupportedArgumentNode = TypeVar("SupportedArgumentNode") # bound=ConditionNode)
# bound does not work because:
# error: Type argument "ahbicht.expressions.condition_nodes.EvaluatedFormatConstraint" of "BaseTransformer" must be a
# subtype of "ahbicht.expressions.condition_nodes.ConditionNode" [type-var]
SupportedReturn = TypeVar("SupportedReturn")
[docs]
@v_args(inline=True) # Children are provided as *args instead of a list argument
class BaseTransformer(Transformer, ABC, Generic[SupportedArgumentNode, SupportedReturn]): # type: ignore[type-arg]
"""
Transformer that evaluates the trees built from the format constraint expressions.
The input are the evaluated format constraint conditions in the form of ConditionNodes.
After two nodes are evaluated in a composition, the resulting node has the node type EvalutatedComposition.
The return value is a ConditionNode whose attribute `format_constraint_fulfilled` describes whether
the format constraint expression is fulfilled or not.
"""
def __init__(self, input_values: Mapping[str, SupportedArgumentNode]) -> None:
"""
The input are the evaluated format constraint conditions in the form of ConditionNodes.
:param input_values: something that maps a condition key (str) onto an argument
"""
super().__init__()
self.input_values = input_values
[docs]
def condition(self, token: Token) -> SupportedArgumentNode:
"""Returns ConditionNode of rule 'condition'"""
try:
condition_key = self.input_values[token.value]
except KeyError as key_err:
raise ValueError(
"Please make sure that the input values contain all necessary condition_keys."
) from key_err
return condition_key
[docs]
def package(self, token: Token) -> SupportedArgumentNode:
"""Returns ConditionNode of rule package"""
try:
package_key = self.input_values[token.value]
except KeyError as key_err:
raise ValueError("Please make sure that the input values contain all necessary package_keys.") from key_err
return package_key
[docs]
@abstractmethod
def and_composition(self, left: SupportedArgumentNode, right: SupportedArgumentNode) -> SupportedReturn:
"""Evaluates logical and_composition"""
raise NotImplementedError("Has to be implemented by inheriting class.")
[docs]
@abstractmethod
def or_composition(self, left: SupportedArgumentNode, right: SupportedArgumentNode) -> SupportedReturn:
"""Evaluates logical (inclusive) or_composition"""
raise NotImplementedError("Has to be implemented by inheriting class.")
[docs]
@abstractmethod
def xor_composition(self, left: SupportedArgumentNode, right: SupportedArgumentNode) -> SupportedReturn:
"""Evaluates exclusive xor_composition"""
raise NotImplementedError("Has to be implemented by inheriting class.")