def out(self, model, heads, tails): #output head and tail outside for merging if self.head != None: self.next_path() #generate place for every input #skip if explicit place at the begining or end for e in self.final_heads: if util.is_explicit_place(model, e) == False: place_begin = t.TreePlace() place_begin.name = util.gen_place_label(model) place_begin.children += [e] model.elements += [place_begin] heads += [place_begin] for e in self.final_tails: if util.is_explicit_place(model, e) == False: place_end = t.TreePlace() place_end.name = util.gen_place_label(model) e.children += [place_end] model.elements += [place_end] tails += [place_end] if len(heads) < 2: raise Exception( 'Expected parallel block to have at least two paths')
def out(self, model, heads, tails): #output head and tail outside for merging if self.head != None: self.next_path() place_begin = t.TreePlace() model.elements += [place_begin] heads += [place_begin] place_begin.name = util.gen_place_label(model) #NOTE: Implementation propetrty. If the segment in confusion has chain with multiple children # at the time of processing the block the central place is attached to the children. # This functionality allows for implementation of gated confusion. #To achieve regular confusion block use fragment within the selectgion list # Might need improvement in next versions #place on second child if more than one exist in path for i in range(len(self.final_heads)): fh = self.final_heads[i] e = self.final_tails[i] if util.is_explicit_place(model, e) == False: tails += [e] place_begin.children += [e] if util.is_explicit_place(model, fh) == False and fh != e: heads += [fh] if len(place_begin.children) < 2: raise Exception( 'Expected confusion block to have at least two paths')
def apply_markings(model): for m in model.meta.markings: place = util.match_strictly(model, m.input, m.output, t.TreePlace) if len(place) == 0: #attempt to find one to one transition #many to many without place are invalid if (len(m.input) == 1) and (len(m.output) == 1): place = util.find_transition_one_to_one( model, m.input[0], m.output[0]) if len(place) == 1: p = t.TreePlace() p.name = util.gen_place_label(model) p.marking = True model.elements += [p] s = place[0][0] d = place[0][1] s.children.remove(d) s.children += [p] p.children += [d] elif len(place) == 0: raise Exception('Could not locate marking [%s]->[%s]' % (m.input, m.output)) elif len(place) > 1: raise Exception( 'Multiple candidates marking inconclusive [%s]->[%s]' % (m.input, m.output)) else: raise Exception('Invalid marking without place [%s]->[%s]' % (m.input, m.output)) elif len(place) > 1: raise Exception( 'Multiple candidates marking inconclusive [%s]->[%s]' % (m.input, m.output)) else: place[0].marking = True
def apply_loop_places(model): #extract all loop fragments loop_fragment_begin_array = [] for p in model.elements: if type(p) is t.TreeLoopFragmentBegin: loop_fragment_begin_array += [p] #remove all loop fragments from the main array for p in loop_fragment_begin_array: model.elements.remove(p) model.elements.remove(p.ref_end) #For all begin loop places, if there exist child place remove it and assign all its children to loop place for p in loop_fragment_begin_array: for c in p.children: if type(c) is t.TreePlace: p.children += c.children p.children.remove(c) model.elements.remove(c) #For all end loop places, if there exist a parent place remove it and assign its parents to the loop place for p in loop_fragment_begin_array: p_parents = util.get_parents(model, p.ref_end) for c in p_parents: if type(c) is t.TreePlace: for cp in util.get_parents(model, c): cp.children.remove(c) cp.children += [p.ref_end] model.elements.remove(c) #start processing loop places for meta_lp in model.meta.loop_place: #throw exception of still false at the end of nested loop applied = False for lpb in loop_fragment_begin_array: #check if possible duplicate was already satisfied duplicate = False for dupl in lpb.satisfied: if util.loop_place_equiv(dupl, meta_lp) == True: duplicate = True if duplicate == False: #Obtain candidate transitions lists end_array = lpb.children begin_array = util.get_parents(model, lpb.ref_end) #check if current loop place contains required transitions end_match = util.have_all(end_array, meta_lp.output) begin_match = util.have_all(begin_array, meta_lp.input) if begin_match == True and end_match == True: #Create loop place lp = t.TreePlace() lp.name = util.gen_place_label(model) #inherit parents of the loop begin place(if any) for p in util.get_parents(model, lpb): p.children += [lp] #assign postset for e in end_array: if e.name in meta_lp.output: lp.children += [e] #assign preset for b in begin_array: if b.name in meta_lp.input: b.children += [lp] #insert into main array model.elements += [lp] #assign loop place to satisfied list lpb.satisfied += [meta_lp] applied = True break #exception of not applied!!! if applied == False: raise Exception('Missing place for [%s]->[%s]' % (meta_lp.input, meta_lp.output)) #remove any references to loop places for e in model.elements: for lpb in loop_fragment_begin_array: if lpb in e.children: e.children.remove(lpb) if lpb.ref_end in e.children: e.children.remove(lpb.ref_end)
def parse_segment(model, head, tail, src): #process series of tokens in a segment i = 0 last = len(src) #Default segment seg = SegmentSequential() while (i < last): #iterate through every token elem = src[i] token = syntax.decode_token(elem) if token == syntax.Token.SQR_BR_R or token == syntax.Token.PAR_R: #unexpected closing bracket without opening bracket raise Exception( 'Unexpected closing bracket %s without opening bracket' % elem) elif token == syntax.Token.LOOP: #loop token detected #extract internal sorurce block_src = util.extract_block_subarray(i, src) tree_fragment = t.TreeFragment() tree_fragment.src = block_src[1] model.elements += [tree_fragment] #create loop fragment loop_fragment_end = t.TreeLoopFragmentEnd() loop_fragment_begin = t.TreeLoopFragmentBegin() loop_fragment_begin.children += [tree_fragment] loop_fragment_begin.ref_end = loop_fragment_end tree_fragment.children += [loop_fragment_end] model.elements += [loop_fragment_begin, loop_fragment_end] if seg.head: #something is already in segment #uncommon potentially modeling initialization #followed by infinite loop seg.tail.children += [loop_fragment_begin] seg.tail = loop_fragment_end else: seg.head = loop_fragment_begin seg.tail = loop_fragment_end i = block_src[0] elif token == syntax.Token.SQR_BR_L or token == syntax.Token.PAR_L: #opening bracket detected #extract source fragment until matching closing bracket #and place as source fragment block_src = util.extract_block_subarray(i, src) tree_fragment = t.TreeFragment() tree_fragment.src = block_src[1] model.elements += [tree_fragment] if seg.head: seg.tail.children += [tree_fragment] seg.tail = tree_fragment else: seg.head = tree_fragment seg.tail = tree_fragment i = block_src[0] elif token == syntax.Token.CONFUSION or token == syntax.Token.CONFUSION_ARB: #confusion token encountered if type(seg) is not SegmentSequential and type( seg) is not SegmentConfusion: raise Exception('Unexpected current segment type %s' % type(seg)) #transform existing sequential path to confusion block #and start new path for further tokens if type(seg) is SegmentSequential: tmp = SegmentConfusion() tmp.transfer(seg) seg = tmp seg.next_path() i = i + 1 elif token == syntax.Token.SEQ or token == syntax.Token.ACT: # sequential (;) or (->) #add place to the path place = t.TreePlace() place.name = util.gen_place_label(model) model.elements += [place] if seg.head: seg.tail.children += [place] seg.tail = place else: seg.head = place seg.tail = place i = i + 1 elif token == syntax.Token.EPL: # (=>) token #do nothing i = i + 1 elif token == syntax.Token.PARALLEL: #parallel token if type(seg) is not SegmentSequential and type( seg) is not SegmentParallel: raise Exception('Unexpected current segment type %s' % type(seg)) #transform existing sequential path to parallel block (if applicable) #and start new path for further tokens if type(seg) is SegmentSequential: tmp = SegmentParallel() tmp.transfer(seg) seg = tmp seg.next_path() i = i + 1 elif token == syntax.Token.SEP: #Create a source fragment without any parent child connections #Absorb the remainder of tokens for the new fragment i = i + 1 block_src = [] while (i < last): block_src += [src[i]] i = i + 1 tree_fragment = t.TreeFragment() tree_fragment.src = block_src model.elements += [tree_fragment] elif token == syntax.Token.UNKNOWN: #other type of token #WARNING: this version does not do the sanity check!!! if util.is_explicit_place(model, elem): #1 test for explicit place token #if place then either detached or no tail #no tail if sequential not empty or parallel #OBSOLETE: assuming correct syntax meaning no a+; P0; b+ but parallel allowed #find if there is already an explicit place present place = util.get_place(model, elem) if place == None: #if no create one place = t.TreePlace() place.name = elem model.elements += [place] #look one before and one after element if there is -> operator #if present then attach a place without modifying regular flow #NOTE: Limitation, only transition allowed after and before -> operator #otherwise thrown an exception pre_arrow_present = False post_arrow_present = False inflow_present = False if i > 0: prev = src[i - 1] prev_token = syntax.decode_token(prev) if prev_token == syntax.Token.EPL: pre_arrow_present = True if i < (last - 1): nxt = src[i + 1] nxt_token = syntax.decode_token(nxt) if nxt_token == syntax.Token.EPL: post_arrow_present = True if pre_arrow_present == True: #add created place as a child of preceding transition if type(seg.tail) is not t.TreeTransition: raise Exception( 'Syntax error, preceding element must be a transition' ) seg.tail.children += [place] if post_arrow_present == True: #get element past the arrow, verify that is is a transition and add both # the explicit place and the transition nxt = src[i + 2] if util.is_transition(model, nxt) == False: raise Exception( 'Syntax error, following element must be a transition' ) #process transition tran = t.TreeTransition() tran.name = nxt model.elements += [tran] if seg.head: seg.tail.children += [tran] seg.tail = tran else: seg.head = tran seg.tail = tran place.children += [tran] elif pre_arrow_present == False: inflow_present = True if seg.head: seg.tail.children += [place] seg.tail = place else: seg.head = place seg.tail = place if pre_arrow_present == True or inflow_present == True: i = i + 1 else: #must be post i = i + 3 elif util.is_transition(model, elem): #2 test for transition tran = t.TreeTransition() tran.name = elem model.elements += [tran] if seg.head: seg.tail.children += [tran] seg.tail = tran else: seg.head = tran seg.tail = tran i = i + 1 elif util.is_fragment(model, elem): #3 test for source fragment frag = t.TreeFragment() frag.label = elem model.elements += [frag] if seg.head: seg.tail.children += [frag] seg.tail = frag else: seg.head = frag seg.tail = frag i = i + 1 else: raise Exception('Unknown token %s' % elem) else: raise Exception('DEBUG POINT 0') #Obtain final heads and tails seg.out(model, head, tail) return SegmentParseStatus.DEFAULT