#NEWLINE# def perform_search( fn_to_tagged_sents , onset = None , nucleus = None , coda = None , tone = None , initial = None , final = None , jyutping = None , character = None , pos = None , word_range = ( 0 , 0 ) , sent_range = ( 0 , 0 ) , tagged = True , sents = False ) : #NEWLINE# #INDENT# '\n    overall strategy: deal with jp (and all jp-related elements) first, and\n                      then the character\n\n    1. jp\n\n    hierarchy of jp and associated search elements:\n                      jp\n                 /     |          onset/initial  final  tone\n                     /                   nucleus  coda\n\n    lower search elements cannot be used together with dominating higher\n    elements\n    ' #NEWLINE# if ( not ( type ( word_range ) == type ( sent_range ) == tuple ) ) : #NEWLINE# #INDENT# raise ValueError ( 'word_range and sent_range must be tuples' ) #NEWLINE# #UNINDENT# ( words_left , words_right ) = word_range #NEWLINE# ( sents_left , sents_right ) = sent_range #NEWLINE# if ( not ( type ( words_left ) == type ( words_right ) == type ( sents_left ) == type ( sents_right ) == int ) ) : #NEWLINE# #INDENT# raise ValueError ( 'int required for {words, sents}_{left, right}' ) #NEWLINE# #UNINDENT# if ( ( sents_left > 0 ) or ( sents_right > 0 ) ) : #NEWLINE# #INDENT# sents = True #NEWLINE# #UNINDENT# character_search = False #NEWLINE# jp_search = False #NEWLINE# pos_search = False #NEWLINE# if character : #NEWLINE# #INDENT# character_search = True #NEWLINE# #UNINDENT# if ( onset or nucleus or coda or tone or final or jyutping ) : #NEWLINE# #INDENT# jp_search = True #NEWLINE# #UNINDENT# if pos : #NEWLINE# #INDENT# pos_search = True #NEWLINE# #UNINDENT# if ( not ( character_search or jp_search or pos_search ) ) : #NEWLINE# #INDENT# raise ValueError ( 'no search elements' ) #NEWLINE# #UNINDENT# jp_search_tuple = ( None , None , None , None ) #NEWLINE# if jp_search : #NEWLINE# #INDENT# if ( final and ( nucleus or coda ) ) : #NEWLINE# #INDENT# raise ValueError ( 'final cannot be used together with either nucleus or coda (or both)' ) #NEWLINE# #UNINDENT# if ( jyutping and ( onset or final or nucleus or coda or tone ) ) : #NEWLINE# #INDENT# raise ValueError ( 'jyutping cannot be used together with other Jyutping elements' ) #NEWLINE# #UNINDENT# if ( ( onset != initial ) and onset and initial ) : #NEWLINE# #INDENT# raise ValueError ( 'onset conflicts with initial' ) #NEWLINE# #UNINDENT# if initial : #NEWLINE# #INDENT# onset = initial #NEWLINE# #UNINDENT# if jyutping : #NEWLINE# #INDENT# try : #NEWLINE# #INDENT# jp_search_list = parse_jyutping ( jyutping ) #NEWLINE# #UNINDENT# except ValueError : #NEWLINE# #INDENT# raise ValueError ( ( 'invalid jyutping -- %s' % repr ( jyutping ) ) ) #NEWLINE# #UNINDENT# if ( len ( jp_search_list ) > 1 ) : #NEWLINE# #INDENT# raise ValueError ( 'only jyutping for one character is allowed' ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# jp_search_tuple = jp_search_list [ 0 ] #NEWLINE# #UNINDENT# #UNINDENT# else : #NEWLINE# #INDENT# if final : #NEWLINE# #INDENT# ( nucleus , coda ) = parse_final ( final ) #NEWLINE# #UNINDENT# jp_search_tuple = ( onset , nucleus , coda , tone ) #NEWLINE# #UNINDENT# #UNINDENT# fn_to_results = dict ( ) #NEWLINE# for ( fn , tagged_sents ) in fn_to_tagged_sents . items ( ) : #NEWLINE# #INDENT# sent_word_index_pairs = list ( ) #NEWLINE# for ( i_sent , tagged_sent ) in enumerate ( tagged_sents ) : #NEWLINE# #INDENT# for ( i_word , tagged_word ) in enumerate ( tagged_sent ) : #NEWLINE# #INDENT# ( c_characters , c_pos , c_mor , _ ) = tagged_word #NEWLINE# c_jyutping = get_jyutping_from_mor ( c_mor ) #NEWLINE# if character_search : #NEWLINE# #INDENT# character_match = ( character in c_characters ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# character_match = True #NEWLINE# #UNINDENT# if pos_search : #NEWLINE# #INDENT# pos_match = re . fullmatch ( pos , c_pos ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# pos_match = True #NEWLINE# #UNINDENT# if ( not ( character_match and pos_match ) ) : #NEWLINE# #INDENT# continue #NEWLINE# #UNINDENT# jyutping_match = False #NEWLINE# if ( ( not jp_search ) and ( not c_jyutping ) ) : #NEWLINE# #INDENT# jyutping_match = True #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# if ( not c_jyutping ) : #NEWLINE# #INDENT# pass #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# try : #NEWLINE# #INDENT# c_parsed_jyutpings = parse_jyutping ( c_jyutping ) #NEWLINE# #UNINDENT# except ValueError : #NEWLINE# #INDENT# continue #NEWLINE# #UNINDENT# for c_parsed_jyutping in c_parsed_jyutpings : #NEWLINE# #INDENT# booleans = [ _jp_element_match ( search_ , current_ ) for ( search_ , current_ ) in zip ( jp_search_tuple , tone ) ] #NEWLINE# if all ( booleans ) : #NEWLINE# #INDENT# jyutping_match = True #NEWLINE# #UNINDENT# break #NEWLINE# #UNINDENT# #UNINDENT# #UNINDENT# if jyutping_match : #NEWLINE# #INDENT# sent_word_index_pairs . append ( ( i_sent , i_word ) ) #NEWLINE# #UNINDENT# #UNINDENT# #UNINDENT# results_list = list ( ) #NEWLINE# for ( i_sent , i_word ) in sent_word_index_pairs : #NEWLINE# #INDENT# if ( not sents ) : #NEWLINE# #INDENT# tagged_sent = tagged_sents [ i_sent ] #NEWLINE# i_word_start = ( i_word - words_left ) #NEWLINE# i_word_end = ( ( i_word + words_right ) + 1 ) #NEWLINE# if ( i_word_start < 0 ) : #NEWLINE# #INDENT# i_word_start = 0 #NEWLINE# #UNINDENT# if ( i_word_end > len ( tagged_sent ) ) : #NEWLINE# #INDENT# i_word_end = len ( tagged_sent ) #NEWLINE# #UNINDENT# words_wanted = tagged_sent [ i_word_start : i_word_end ] #NEWLINE# if ( not tagged ) : #NEWLINE# #INDENT# words_wanted = [ x [ 0 ] for x in words_wanted ] #NEWLINE# #UNINDENT# if ( len ( words_wanted ) == 1 ) : #NEWLINE# #INDENT# words_wanted = words_wanted [ 0 ] #NEWLINE# #UNINDENT# results_list . append ( words_wanted ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# i_sent_start = ( i_sent - sents_left ) #NEWLINE# i_sent_end = ( ( i_sent + sents_right ) + 1 ) #NEWLINE# if ( i_sent_start < 0 ) : #NEWLINE# #INDENT# i_sent_start = 0 #NEWLINE# #UNINDENT# if ( i_sent_end > len ( tagged_sents ) ) : #NEWLINE# #INDENT# i_sent_end = len ( tagged_sents ) #NEWLINE# #UNINDENT# sents_wanted = tagged_sents [ i_sent_start : i_sent_end ] #NEWLINE# if ( not tagged ) : #NEWLINE# #INDENT# for ( i , sent ) in enumerate ( sents_wanted [ : ] ) : #NEWLINE# #INDENT# sents_wanted [ i ] = [ x [ 0 ] for x in sent ] #NEWLINE# #UNINDENT# #UNINDENT# if ( len ( sents_wanted ) == 1 ) : #NEWLINE# #INDENT# sents_wanted = sents_wanted [ 0 ] #NEWLINE# #UNINDENT# results_list . append ( sents_wanted ) #NEWLINE# #UNINDENT# #UNINDENT# fn_to_results [ fn ] = results_list #NEWLINE# #UNINDENT# return fn_to_results