def split_starps_text_per_gaps_and_hits(text_wc, gaps_ec, hits_ec): # Given the text {text_wc} of an SPS parag {P} with word # separators, and a macro-parsing {gaps_ec,hits_ec} of the EVA letters # of {P} into alternating gaps and hits, splits {text_wc} into # strings {gaps_wc,hits_wc} with the same EVA letters. # # Let {nh} be the number of hits in {hits_ec}, and {ng = nh+1} the # number of gaps in {gaps_ec}. Each element {gaps_ec[0..ng-1} or # {hits_ec[0..nh-1]} must be a strings of pure EVA letters [a-z?], # without word spaces or other characters. # # The string {text_wc} must consist of EVA letters [a-z?] possibly # interspersed with EVA punctuation only. # # The procedure returns a partition of {text_wc} into alternating # {gaps_wc[0..ng-1]} and {hits_wc[0..nh-1]} possibly with hyphenation # marks (see below). The concatenation of all the strings of {gaps_wc[0..ng-1]}, # minus the punctuation characters, will be equal to {gaps_ec[ig]}. # The same will be true of each list {hits_wc[ih]} and the string # {hits_ec[ih]}. # # If a string of {gaps_wc[ig]} or {hits_wc[ih]} is only part of a word # of text_wc, that fact is indicated by an appended or prepended # "hyphenation mark" '~'. debug = False nh = len(hits_ec); ng = len(gaps_ec); assert ng == nh + 1 # Just in case: text_wc = re.sub(r"<[a-z0-9.]+>", "", text_wc) text_wc = re.sub(r"[ <$%>]", "", text_wc) # Normalize word separators: text_wc = re.sub(r"^[,.-]", "", text_wc) text_wc = re.sub(r"[,.-]$", "", text_wc) text_wc = re.sub(r"[,.-]", ".", text_wc) items_wc = ( text_wc, ) # Make {text_wc} the single item to split. nt = len(items_wc); assert nt == 1 punct_wc = set(".") brack_wc = set() bites_wc_gaps = [] bites_wc_hits = [] rest_wc = "" # Leftover bit of prev item. it = 0 # Next unused item is {items_wc[it]}. for ig in range(ng): if ig > 0: # Collect a list {hbtsi} of bits of items (non-agressively) to match {hits_ec[ig]}: ih = ig - 1 bites_wc, rest_wc, \ bites_xx, rest_xx, \ bites_yy, rest_yy, \ it = gobble_up_bites_of_items \ ( rest_wc, items_wc, None, None, None, None, it, punct_wc, brack_wc, hits_ec[ih], '' ) assert len(bites_wc) == 1 assert bites_xx == None assert bites_yy == None bites_wc_hits.append(bites_wc[0]) if debug: err.write(f"!: {bites_wc = }\n") # Collect a list {gbtsi} of bits of items (agressively) to match {gaps_ec[ig]}: bites_wc, rest_wc, \ bites_xx, rest_xx, \ bites_yy, rest_yy, \ it = gobble_up_bites_of_items \ ( rest_wc, items_wc, None, None, None, None, it, punct_wc, brack_wc, gaps_ec[ig], '' ) assert len(bites_wc) == 1 assert bites_xx == None assert bites_yy == None bites_wc_gaps.append(bites_wc[0]) if debug: err.write(f"!: {bites_wc[0] = }\n") assert rest_wc == "" and it == nt # Add "hyphens" '~' between gaps and hits: for ig in range(ng): if ig > 0: # Check gap between prev hit and this gap: ih = ig - 1 char1 = '.' if bites_wc_hits[ih] == "" else bites_wc_hits[ih][-1] char2 = '.' if bites_wc_gaps[ig] == "" else bites_wc_gaps[ig][0] if char1 != '.' and char2 != '.': bites_wc_hits[ih] = bites_wc_hits[ih] + '~' bites_wc_gaps[ig] = '~' + bites_wc_gaps[ig] if ig < nh: # Check gap between this gap and next hit: ih = ig char1 = '.' if bites_wc_gaps[ig] == "" else bites_wc_gaps[ig][-1] char2 = '.' if bites_wc_hits[ih] == "" else bites_wc_hits[ih][0] if char1 != '.' and char2 != '.': bites_wc_gaps[ig] = bites_wc_gaps[ig] + '~' bites_wc_hits[ih] = '~' + bites_wc_hits[ih] return bites_wc_gaps, bites_wc_hits # ----------------------------------------------------------------------