def makechunk(nameofchunk="", typename="", **dictionary): """ Create a chunk. Three values can be specified: (i) the name of the chunk (the name could be used if the chunk appears as a value of other chunks or production rules) (ii) its type (ii) slot-value pairs. For example: >>> makechunk(nameofchunk='example0', typename='chunktype_example0', value='one') chunktype_example0(value= one) This creates a chunk of type chunk1, which has one slot (value) and the value of that slot is one. """ if not nameofchunk: nameofchunk = "unnamedchunk" if not typename: typename = "undefined" + str(Chunk._undefinedchunktypecounter) Chunk._undefinedchunktypecounter += 1 for key in dictionary: if isinstance(dictionary[key], Chunk): pass elif isinstance(dictionary[key], utilities.VarvalClass): pass else: try: temp_dict = utilities.stringsplitting(str(dictionary[key])) except utilities.ACTRError as e: raise utilities.ACTRError( "The chunk value %s is not defined correctly; %s" % (dictionary[key], e)) loop_dict = temp_dict.copy() for x in loop_dict: if x == "negvariables" or x == "negvalues": val = tuple(temp_dict[x]) else: try: val = temp_dict[x].pop() except KeyError: val = None temp_dict[x] = val dictionary[key] = utilities.VarvalClass(**temp_dict) created_chunk = Chunk(typename, **dictionary) created_chunk._chunks[nameofchunk] = created_chunk return created_chunk
def __init__(self, typename, **dictionary): self.typename = typename self.boundvars = {} #dict of bound variables kwargs = {} for key in dictionary: #change values (and values in a tuple) into string, when possible (when the value is not another chunk) if isinstance(dictionary[key], Chunk): dictionary[key] = utilities.VarvalClass(variables=None, values=dictionary[key], negvariables=(), negvalues=()) elif isinstance(dictionary[key], utilities.VarvalClass): for x in dictionary[key]._fields: if x in {"values", "variables"} and not isinstance( getattr(dictionary[key], x), str) and getattr( dictionary[key], x) != self.__emptyvalue and not isinstance( getattr(dictionary[key], x), Chunk): raise TypeError( "Values and variables must be strings, chunks or empty (None)" ) elif x in { "negvariables", "negvalues" } and (not isinstance(getattr(dictionary[key], x), collections.abc.Sequence) or isinstance(getattr(dictionary[key], x), collections.abc.MutableSequence)): raise TypeError( "Negvalues and negvariables must be tuples") elif (isinstance(dictionary[key], collections.abc.Iterable) and not isinstance(dictionary[key], str)) or not isinstance( dictionary[key], collections.abc.Hashable): raise ValueError( "The value of a chunk slot must be hashable and not iterable; you are using an illegal type for the value of the chunk slot %s, namely %s" % (key, type(dictionary[key]))) else: #create namedtuple varval and split dictionary[key] into variables, values, negvariables, negvalues try: temp_dict = utilities.stringsplitting(str(dictionary[key])) except utilities.ACTRError as e: raise utilities.ACTRError( "The chunk %s is not defined correctly; %s" % (dictionary[key], e)) loop_dict = temp_dict.copy() for x in loop_dict: if x == "negvariables" or x == "negvalues": val = tuple(temp_dict[x]) else: try: val = temp_dict[x].pop() except KeyError: val = None temp_dict[x] = val dictionary[key] = utilities.VarvalClass(**temp_dict) #adding _ to minimize/avoid name clashes kwargs[key + "_"] = dictionary[key] try: for elem in self._chunktypes[typename]._fields: if elem not in kwargs: kwargs[ elem] = self.__emptyvalue #emptyvalues are explicitly added to attributes that were left out dictionary[ elem[: -1]] = self.__emptyvalue #emptyvalues are also added to attributes in the original dictionary (since this might be used for chunktype creation later) if set(self._chunktypes[typename]._fields) != set(kwargs.keys()): chunktype( typename, dictionary.keys() ) #If there are more args than in the original chunktype, chunktype has to be created again, with slots for new attributes warnings.warn("Chunk type %s is extended with new attributes" % typename) except KeyError: chunktype(typename, dictionary.keys() ) #If chunktype completely missing, it is created first warnings.warn( "Chunk type %s was not defined; added automatically" % typename) finally: self.actrchunk = self._chunktypes[typename](**kwargs) self.__empty = None #this will store what the chunk looks like without empty values (the values will be stored on the first call of the relevant function) self.__unused = None #this will store what the chunk looks like without unused values self.__hash = None, self.boundvars.copy( ) #this will store the hash along with variables (hash changes if some variables are resolved)
def createchunkdict(chunk): """ Create typename and chunkdict from pyparsed list. """ sp_dict = { utilities.ACTRVARIABLE: "variables", utilities.ACTRNEG: "negvalues", utilities.ACTRNEG + utilities.ACTRVARIABLE: "negvariables", utilities.ACTRVALUE: "values", utilities.ACTRNEG + utilities.ACTRVALUE: "negvalues" } chunk_dict = {} for elem in chunk: temp_dict = chunk_dict.get( elem[0], utilities.VarvalClass(variables=set(), values=set(), negvariables=set(), negvalues=set())._asdict()) for idx in range(1, len(elem)): try: if elem[idx][0][0] == utilities.VISIONGREATER or elem[idx][0][ 0] == utilities.VISIONSMALLER: #this checks special visual conditions on greater/smaller than if elem[idx][0][-1] == utilities.ACTRVARIABLE: temp_dict['variables'].add(elem[idx][1]) update_val = elem[idx][0][0] else: update_val = elem[idx][0] + elem[idx][1] #here fix updating = 'values' elif elem[idx][1][0] == "'" or elem[idx][1][0] == '"': updating = sp_dict[elem[idx][0]] update_val = elem[idx][1][1:-1] else: updating = sp_dict[elem[idx][0]] update_val = elem[idx][1] except ( KeyError, IndexError ) as err: #indexerror --> only a string is present; keyerror: the first element in elem[idx] is not a special symbol (in sp) if elem[idx][0] == "'" or elem[idx][0] == '"': update_val = elem[idx][1:-1] else: #check if the string is an existing chunk in the database of chunks try: update_val = Chunk._chunks[elem[idx]] #if not, save it as a string except KeyError: update_val = elem[idx] updating = 'values' finally: temp_dict[updating].add(update_val) chunk_dict[elem[0]] = temp_dict for key in chunk_dict: chunk_dict[key]["negvalues"] = tuple(chunk_dict[key]["negvalues"]) chunk_dict[key]["negvariables"] = tuple( chunk_dict[key]["negvariables"]) for x in ["values", "variables"]: if len(chunk_dict[key][x]) > 1: raise utilities.ACTRError( "Any slot must have fewer than two %s, there is more than one in this slot" % x) elif len(chunk_dict[key][x]) == 1: chunk_dict[key][x] = chunk_dict[key][x].pop() else: chunk_dict[key][x] = None chunk_dict[key] = utilities.VarvalClass(**chunk_dict[key]) type_chunk = "" try: type_chunk = chunk_dict.pop( "isa" ).values #change this - any combination of capital/small letters type_chunk = chunk_dict.pop("ISA").values type_chunk = chunk_dict.pop("Isa").values except KeyError: pass return type_chunk, chunk_dict