import re import copy import importlib as imp from comsdk.graph import Graph, Func, State from comsdk.edge import Edge class Params(): __slots__=( 'module', 'entry_func', 'predicate', 'selector', 'function', 'morphism', 'parallelism', 'comment', 'order' ) def __init__(self): for slot in self.__slots__: setattr(self, slot, None) def __str__(self): stri = "" for s in self.__slots__: stri += s+": {}, ".format(getattr(self, s)) return stri entities = {} class GraphFactory(): __slots__ = ( 'states', 'graph', 'tocpp', 'entities' ) def __init__(self, tocpp=False): self.states = {} self.tocpp = tocpp def add_state(self, statename, selectorname=None): if selectorname is not None: sp = entities[selectorname] if self.tocpp: sel_f = Func(sp.module, sp.entry_func, dummy=True) else: sel_f = Func(sp.module, sp.entry_func, getattr(imp.import_module(sp.module), sp.entry_func)) else: sel_f = Func() if statename not in self.states: newstate = State(statename, selector=sel_f) self.states[statename] = newstate def _create_morphism(self, morphname=None): if morphname is None: return Func(), Func() pred_f, func_f = Func(), Func() morph = entities[morphname] for m in morph.__slots__: if getattr(morph,m) != None: if m!="predicate" and m!="function": print("ERROR: Morphisms could not have any params exept predicate and function!\n{}".format(morphname)) exit(0) if m=="predicate": if getattr(morph,m) not in entities: print("\tERROR: Predicate {} is not defined!".format(getattr(morph, m))) exit(0) pred = entities[getattr(morph, m)] if self.tocpp: pred_f = Func(pred.module, pred.entry_func, dummy=True) else: pred_f = Func(pred.module, pred.entry_func) if m=="function": if getattr(morph,m) not in entities: print("\tERROR: Function: {} is not defined!".format(getattr(morph, m))) exit(0) fu = entities[getattr(morph, m)] if self.tocpp: func_f = Func(fu.module, fu.entry_func, dummy=True) else: func_f = Func(fu.module, fu.entry_func) return pred_f, func_f def add_connection(self, st1, st2, morphism=None): pred, entr = self._create_morphism(morphism) self.states[st1].connect_to(self.states[st2], edge=Edge(pred, entr)) # print("{} --{}-{}--> {}".format(st1, pred, entr, st2)) def build(self): self.graph = Graph(self.states["__BEGIN__"], self.states["__END__"]) self.graph.init_graph() return self.graph class Parser(): __slots__ = ( 'entities', 'fact' ) def __init__(self, tocpp=True): self.entities = {} self.fact = GraphFactory(tocpp=True) def _check_brackets(self, rawfile): br = 0 qu = 0 for char in rawfile: if char == "[": br+=1 elif char == "{": br+=1 elif char == "(": br+=1 elif char == "]": br-=1 elif char == "}": br-=1 elif char == ")": br-=1 elif char =="\"": qu+=1 if br!=0 or qu%2!=0: print("Brackets or quotes do not match! Check your file") exit(-1) def _split_multiple(self,param): res = [] first=True for s in param.__slots__: attr = getattr(param,s) if attr is not None and '\0' in attr: vals = attr.split('\0') for v in vals: par = copy.copy(param) setattr(par, s, v) res.append(par) return res #Props is line "[proFp=smth, ...]" def _param_from_props(self,props): parm = Params() props = props.replace("]", '') if '(' in props: mchs = [m for m in re.finditer(r'\((\w+,)*\w+\)', props)] for m in mchs: props=props[:m.span()[0]]+(props[m.span()[0]:m.span()[1]]).replace(',','\0')+props[m.span()[1]:] props = props.replace("(","") props = props.replace(")","") rs =props.split(r",") #.split(r", ") for r in rs: r=r.split(r"=", 1) if r[0] in parm.__slots__: setattr(parm, r[0], r[1]) else: print("\tERROR:Unknown parameter: "+ r[0]) exit(-1) print(parm) return parm def _param_from_entln(self, raw): res = re.split(r"\[", raw, 1) return res[0], self._param_from_props(res[1]) def _topology(self,raw): spl = re.split(r"\s*(=>|->|\[|\])\s*", raw) spl = list(filter(lambda x: x!="[" and x!="]" and x!="", spl)) left = spl[0].split(",") right = spl[2].split(",") if (len(left)>1) and (len(right)>1): print("ERROR:Ambigious multiple connection in line:\n\t{}".format(raw)) exit() # many to one conection elif len(left)>1: p = self._param_from_props(spl[3]) morphs = self._split_multiple(p) if len(morphs)!=len(left): print("\tERROR:Count of edges do not match to count of states in many to one connection!\n\t\t{}".format(raw)) exit() self.fact.add_state(right[0]) for i, st in enumerate(left): self.fact.add_state(st) self.fact.add_connection(st, right[0], morphs[i].morphism) # one to many connection, here could be selector elif len(right)>1: p = self._param_from_props(spl[3]) self.fact.add_state(left[0],selectorname=p.selector) morphs = self._split_multiple(p) for m in morphs: print(m) if len(morphs)!=len(right): print("\tERROR:Count of edges do not match to count of states in one to many connection!\n\t\t{}".format(raw)) exit() for i, st in enumerate(right): self.fact.add_state(st) self.fact.add_connection(left[0], st, morphs[i].morphism) # one to one connection else: self.fact.add_state(left[0]) self.fact.add_state(right[0]) if len(spl)==4: pr =self._param_from_props(spl[3]) self.fact.add_connection(left[0], right[0], pr.morphism) elif len(spl)==3: self.fact.add_connection(left[0], right[0], None) def parse_file(self, filename): file = open(filename, "r") dot = file.read() self._check_brackets(dot) dot = re.sub(r"[ \t\r]", "", dot) #deleting all spaces dot = re.sub(r"((digraph\w+\n?)|}|{)", "", dot) dot = re.sub(r"\/\/.*", "", dot) dot = re.sub(r"^\n$", "", dot) #print("Checking graph...") #graphcheck = re.search(r"\A(digraph)\w+\n?{((\/\/)*.*\n*)+}\Z", dot) #if graphcheck is None: # print("Incorrect graph, check syntax!") # exit() # #print("Graph id good, processing!") #dot = re.sub(r"//*$", "", dot) dotlines = dot.splitlines() dotlines = list(filter(None, dotlines)) # ent_re - regular expr for edges, states, functions properties ent_re = re.compile(r"^\w+\[.*\]$") # top_re - regular expr for topology properties, most time consuming one top_re = re.compile(r"^(\w+,?)+(->|=>)(\w+,?)+(\[(\w+=(\(?\w+,?\)?)+,?)+\])?") # (r"^\w[\w\s,]*(->|=>)\s*\w[\w\s,=\[\]()]*$") for i, ln in enumerate(dotlines): if ent_re.match(ln): name, parm = self._param_from_entln(ln) entities[name] = parm elif top_re.match(ln): self._topology(ln) self.entities = entities return self.fact.build() pars = Parser() graph = pars.parse_file("./test.adot")