Source code for interpret

"""
    Copyright 2020 Simon Vandevelde, Bram Aerts, Joost Vennekens
    This code is licensed under GNU GPLv3 license (see LICENSE) for more
    information.
    This file is part of the cDMN solver.
"""

import re
from Levenshtein import distance
from cdmn.glossary import Glossary, Predicate
from cdmn.idpname import idp_name
from typing import Dict


[docs] class VariableInterpreter: """ TODO """ def __init__(self, glossary: Glossary): """ Initialises the VariableInterpreter. :arg glossary: a glossary object. :returns Object: """ self.glossary = glossary
[docs] def interpret_value(self, value: str, variables: Dict = {}, expected_type=None): """ Method to interpret a value of a cDMN notation. Here be dragons. :arg value: string which needs to be interpreted. :arg variables: list containing the variables. :arg expected_type: :returns str: the interpretation of the notation. """ # TODO: instead of string variables, make Variable class with existing # type to which can be referred. lu = self.glossary.lookup(str(value)) interpretations = [] # Length of lookup is zero if it is a variable, and not a relation or # function. Alternatively, we look if the value has already been # declared as a varibale before-hand. if len(lu) == 0 or value in variables: if str(value) == '__PLACEHOLDER__': pass elif not expected_type: expected_type = variables[str(value)] return Value(value, expected_type, variables) for l in lu: if (expected_type is not None and expected_type != l[0].is_function()): pass # TODO: fix this! try: interpretations.append( PredicateInterpretation(l[0], l[1], self, variables)) except ValueError: continue if len(interpretations) == 0: raise ValueError(f'The value of "{value}" could not be' f' interpreted.') if len(interpretations) == 1: return interpretations[0] if len(interpretations) > 1: # Find most likely interpretation by sorting them on Levenshtein # distance. This distance measures the number of operations needed # to transform one string in another, and should give a good # estimation of the "most likely" match. interpretations.sort(key=lambda interp: distance(value, interp.value)) print(f"Warning: Multiple possible interpretations for {value}." f" Selecting the most likely interpretation:" f" {interpretations[0].value}") return interpretations[0]
[docs] class Value: """ An object to represent a value. """ def __init__(self, value: str, valuetype, variables): """ Initialised a Value object. :arg value: a string containing the value. :arg valuetype: :arg variables: :returns Object: """ self.value = value self.type = valuetype self.check(variables)
[docs] def check(self, variables): """ TODO """ if re.match('.* (and|of) .*', str(self.value)): raise ValueError(f'The compiler does not know how to interpret' f' the following: "{self.value}".') return # TODO: reinclude below code. if self.value not in variables.keys() and \ self.value not in self.type.possible_values: raise ValueError(f'WARNING: {self.value} occurs in a position' f' of type {self.type.name}' f' but does not appear in possible values')
def __str__(self) -> str: """ Magic method to format a variable interpretation to string. :returns str: """ return f'{idp_name(self.value)}'
[docs] class PredicateInterpretation: """ TODO """ def __init__(self, pred: Predicate, arguments, inter: VariableInterpreter, variables): """ Initialises the PredicateInterpretation object. :arg pred: the predicate to interpret. :arg arguments: :arg inter: the variable interpreter. :arg variables: :returns Object: """ self.pred = pred self.args = [inter.interpret_value(arg, variables=variables, expected_type=t) for arg, t in zip(arguments, pred.args)] # if @property def type(self): """ Method to get the type of the predicate. :returns Type: supertrype of the predicate. """ return self.pred.super_type @property def value(self): """ TODO """ return self.pred.name def __str__(self): """ Magic method to return this object in string form. """ return '{}({})'.format(idp_name(self.pred.name), ', '.join([arg.__str__() for arg in self.args]))