#!/usr/bin/python # -*- coding: utf-8 -*- #Autor: Erickson Silva #Email: #LAViD - Laboratório de Aplicações de Vídeo Digital import platform import xml.etree.ElementTree as ET from os.path import expanduser from collections import deque from LerDicionarios import * from Iterator import * from StringAux import * from ConverteExtenso import * from nltk_tgrep import tgrep_positions, tgrep_nodes from nltk import ParentedTree, Tree, draw class AplicaRegras(object): # inicializa todos as variaveis def __init__(self): self.__root = self.get_root() self.dicionarios = LerDicionarios() self.__especificos = {"advt":self.verificar_adv_tempo, "v":self.verificar_vb_infinitivo, "x":self.verificar_preposicao, "c":self.verificar_subst_genero, "a":self.verificar_artigo, "l":self.verificar_vb_ligacao, "i":self.verificar_adv_intensidade, "vbi":"zero", "n":self.verificar_vb_muda_negacao, "abmn":"zero", "adji":"zero","adjn":"zero", "advi":"zero"} def get_root(self): if platform.system() == 'Windows': return ET.parse(expanduser("~")+'\\vlibras-translate\data\\regras.xml').getroot() return ET.parse(expanduser("~")+'/vlibras-translate/data/regras.xml').getroot() def aplicar_regras_morfo(self, lista, sint=False): self.lista = list(lista) self.quantidade_iter_pular = 0 self.lista_corrigida = [] it = Iterator() it.load(self.lista) while(it.has_next()): for morpho in self.__root.findall('morphological'): self.has_rule = False for rule in morpho.findall('rule'): # procura a tag rule if rule.find('active').text == "true" and rule.get('name').split("_")[0] == it.get_ticket(): count = int(rule.find('count').text) self.lista_iteracoes = [] if count == 1: self.lista_iteracoes = [it.get_token()] else: try: self.lista_iteracoes = it.get_interval(count) it.skip(count-1) except: continue self.nome_regra = self.gerar_nome_regra(self.lista_iteracoes) if rule.get('name') == self.nome_regra: # verifica se a regra é aplicavel e a mesma esta ativa self.has_rule = True self.lista_iteracao_regra = count * [None] self.count_iteracao_regra = -1 print "REGRA MORFOLÓGICA: " + rule.get('name') for classe in rule.iter('class'): # for nas tags class title = classe.find('title') newpos = classe.find('newpos') newprop = classe.find('newprop') newtoken = classe.find('newtoken') newtokenpos = classe.find('newtokenpos') self.specific = classe.find('specific') self.count_iteracao_regra += 1 tupla = self.lista_iteracoes[self.count_iteracao_regra] if self.specific is not None: self.specific = self.__especificos[self.specific.text](tupla[0]) if self.specific == False: self.has_rule = False self.quantidade_iter_pular = 0 break if newprop is not None and newtoken is not None: if newtokenpos is not None and newtokenpos.text == "0": self.lista_iteracao_regra[self.count_iteracao_regra] = (newtoken.text + "_" + self.specific, newprop.text) else: self.lista_iteracao_regra[self.count_iteracao_regra] = (self.specific + "_" + newtoken.text, newprop.text) continue elif newprop is not None: self.lista_iteracao_regra.append([self.specific,newprop.text]) if newtoken is not None and newpos is not None: if newtokenpos is not None: lista_merge = count * [None] lista_merge[int(newpos.text)] = tupla[0] lista_merge[int(newtokenpos.text)] = newtoken.text merge_tokens = "_".join(lista_merge) self.lista_iteracao_regra.append([merge_tokens, title.text]) else: self.lista_iteracao_regra.append([tupla[0] + "_" + newtoken.text, title.text]) elif newpos is not None: if newpos.text == "-1": self.lista_corrigida.append(None) continue else: self.lista_iteracao_regra[int(newpos.text)] = tupla elif newtoken is not None: token_anterior = self.lista_iteracao_regra[self.count_iteracao_regra][0] ticket_anterior = self.lista_iteracao_regra[self.count_iteracao_regra][1] if newtokenpos is not None and newtokenpos.text == "0": self.lista_iteracao_regra[self.count_iteracao_regra] = [newtoken.text + "_" + token_anterior, ticket_anterior] else: self.lista_iteracao_regra[self.count_iteracao_regra] = [token_anterior + "_" + newtoken.text, ticket_anterior] if self.has_rule: self.lista_corrigida.append(filter(None, self.lista_iteracao_regra)[0]) break if (self.has_rule == False): self.lista_corrigida.append(it.get_token()) #se nao achou regra, entao adiciona a tupla original if sint: return self.lista_corrigida return filter(None, self.lista_corrigida) def aplicar_regras_sint(self, lista, arvore): p_arvore = ParentedTree.convert(arvore) self.adaptar_regras_morfo_arvore(lista, p_arvore) for morpho in self.__root.findall('syntactic'): for rule in morpho.findall('rule'): # procura a tag rule nome_regra = self.corrigir_anotacao(rule.get('name')) regra = self.separar_regra(nome_regra) node_pai = tgrep_nodes(p_arvore, regra[0], search_leaves=False) if node_pai: node_regra = tgrep_nodes(node_pai[0], regra[1].replace('$', '>'), search_leaves=False) if node_regra: node_esq = tgrep_nodes(node_pai[0], regra[1], search_leaves=False) node_esq_pos = tgrep_positions(node_pai[0], regra[1], search_leaves=False) node_dir = tgrep_nodes(node_pai[0], regra[2], search_leaves=False) node_dir_pos = tgrep_positions(node_pai[0], regra[2], search_leaves=False) if node_esq and node_dir: print "REGRA SINTÁTICA: " + rule.get('name') subnodes = node_esq + node_dir for subnode in subnodes: self.has_rule = True self.alteracoes_nao_implementadas = [None,None] self.count_iteracao_regra = -1 self.specific = None for classe in rule.findall('class'): self.specific = classe.find('specific') if self.specific is not None: self.specific = self.__especificos[self.specific.text](subnode.leaves()[0]) if self.specific is False: self.has_rule = False break # modelo: [['node_esq', ['token', 'ticket']],['node_dir', ['token', 'ticket']]] for classe in rule.iter('class'): title = classe.find('title') if subnode.label() == title.text: newpos = classe.find('newpos') newprop = classe.find('newprop') newtoken = classe.find('newtoken') newtokenpos = classe.find('newtokenpos') self.count_iteracao_regra += 1 if self.specific is not None: self.specific = self.__especificos[self.specific.text](subnode.leaves()[0]) if self.specific is False: self.has_rule = False break if newprop is not None and newtoken is not None: if newtokenpos is not None and newtokenpos.text == "0": self.alteracoes_nao_implementadas[self.count_iteracao_regra].append([newtoken.text + "_" + self.specific, newprop.text]) else: self.alteracoes_nao_implementadas[self.count_iteracao_regra].append([self.specific + "_" + newtoken.text, newprop.text]) continue elif newprop is not None: self.alteracoes_nao_implementadas[self.count_iteracao_regra].append([self.specific,newprop.text]) if newtoken is not None and newpos is not None: if newtokenpos is not None: lista_merge = count * [None] lista_merge[int(newpos.text)] = subnode.leaves()[0] lista_merge[int(newtokenpos.text)] = newtoken.text merge_tokens = "_".join(lista_merge) self.alteracoes_nao_implementadas[self.count_iteracao_regra].append([merge_tokens, title.text]) else: self.alteracoes_nao_implementadas[self.count_iteracao_regra].append([subnode.leaves()[0] + "_" + newtoken.text, title.text]) elif newpos is not None: if newpos.text == "-1": alteracoes_nao_implementadas[self.count_iteracao_regra].append(None) continue else: #TODO if int(newpos.text) == 0: self.alteracoes_nao_implementadas[int(newpos.text)] = subnode elif newtoken is not None: token_anterior = self.lista_iteracao_regra[self.count_iteracao_regra][0] ticket_anterior = self.lista_iteracao_regra[self.count_iteracao_regra][1] if newtokenpos is not None and newtokenpos.text == "0": self.lista_iteracao_regra[self.count_iteracao_regra] = [newtoken.text + " " + token_anterior, ticket_anterior] else: self.lista_iteracao_regra[self.count_iteracao_regra] = [token_anterior + " " + newtoken.text, ticket_anterior] if self.has_rule: print self.alteracoes_nao_implementadas[0] self.lista_corrigida.append(filter(None, self.lista_iteracao_regra)[0]) break return self.converter_arv_para_lista(p_arvore) def adaptar_regras_morfo_arvore(self, lista, arvore): lista_pos_arv = [] for tupla in lista: string_grep = self.corrigir_anotacao(tupla[1]) + " < " + tupla[0].lower() node = tgrep_positions(arvore, string_grep) if node[0] in lista_pos_arv: node.reverse() lista_pos_arv.append(node[0]) morfo = self.aplicar_regras_morfo(lista, sint=True) for i in range(0, len(morfo)): arv_ticket = arvore[lista_pos_arv[i]].label() arv_token = arvore[lista_pos_arv[i]][0] if morfo[i] is None: arvore[lista_pos_arv[i][:-1]] = None elif arv_token != morfo[i][0] and arv_ticket != morfo[i][1]: arvore[lista_pos_arv[i]][0] = morfo[i][0] arvore[lista_pos_arv[i]].set_label(self.corrigir_anotacao(morfo[i][1])) elif arv_token != morfo[i][0]: arvore[lista_pos_arv[i]][0] = morfo[i][0] elif arv_ticket != morfo[i][1]: arvore[lista_pos_arv[i]].set_label(self.corrigir_anotacao(morfo[i][1])) else: continue nodes_none = tgrep_positions(arvore, 'None') for node in nodes_none: arvore[node[:-1]].remove(None) def converter_arv_para_lista(self, arvore): folhas = arvore.leaves() lista_nodes = [] for folha in folhas: pos = tgrep_positions(arvore, folha) node = arvore[pos[0][:-1]] #decode node[0] lista_nodes.append([node[0], self.corrigir_anotacao(node.label())]) return lista_nodes def criar_ptree(self, s): all_ptrees = [] ptree = ParentedTree.convert(Tree.fromstring(s)) all_ptrees.extend(t for t in ptree.subtrees() if isinstance(t, Tree)) return ptree def separar_new_tokens(self, lista): for index, tupla in enumerate(lista): if '_' in tupla[0]: if 'VB' in tupla[1]: token_split = tupla[0].split('_') tupla[0] = token_split[0] lista.append([token_split[1],'NTK']) else: token_split = tupla[0].split('_') tupla[0] = token_split[0] lista.insert(index+1, [token_split[1],'NTK']) def corrigir_anotacao(self, anotacao): split = anotacao.split('_') for i in range(0, len(split)): split[i] = split[i].replace('-','_') return "-".join(split).encode('utf-8') def separar_regra(self, regra): split = regra.split("(") split[1] = split[1].replace(")","").split("-") rev = list(split[1]) rev.reverse() split.append(rev) split[1] = ' $ '.join(split[1]) split[2] = ' $ '.join(split[2]) return split def gerar_nome_regra(self, lista): self.__nomeRegra = [] for t in lista: self.__nomeRegra.append(t[1]) return "_".join(self.__nomeRegra) def verificar_adv_tempo(self, token): for tupla in self.lista: if self.dicionarios.has_adverbio_tempo(tupla[0]): return self.verificar_vb_infinitivo(token) return False def verificar_vb_infinitivo(self, token): if self.dicionarios.has_verbo_infinitivo(token): return self.dicionarios.get_verbo_infinitivo(token) return False def verificar_preposicao(self, token): return self.dicionarios.has_preposicao(token) def verificar_subst_genero(self, token): return self.dicionarios.has_subst_2_generos(token) def verificar_artigo(self, token): return self.dicionarios.has_artigo(token) def verificar_vb_ligacao(self, token): return self.dicionarios.has_verbo_ligacao(token) def verificar_adv_intensidade(self, token): return self.dicionarios.has_adverbio_intensidade(token) def verificar_vb_muda_negacao(self, token): if self.dicionarios.has_verbo_muda_negacao(token): return self.dicionarios.get_verbo_muda_negacao(token) return False def simplificar_sentenca(self, lista): it = Iterator() it.load(lista) num = False nova_lista = [] while(it.has_next()): token = it.get_word() tag = it.get_ticket() if tag == "NUM": num = True if tag[-2:] == "-P": singular = self.analisar_plural(token) lista[it.get_count()][0] = singular if num: return self.converter_extenso(nova_lista) return nova_lista def analisar_plural(self, token): if(token[-3:] == "OES" or token[-2:] == "AES" or token[-2:] == "AOS"): return token[0:-3]+"AO" elif(token[-3:] == "RES" or token[-2:] == "ZES" or token[-2:] == "NES"): return token[0:-2] elif(token[-3:] == "SES"): #TODO: Algumas palavras possuem marcações gráficas na raiz singular. Ex: Gás – Gases return token[0:-2] elif(token[-2:] == "NS"): return token[0:-2]+"M" elif(token[-3:] == "EIS"): return token[0:-3]+"IL" elif(token[-2:] == "IS"): if(token[-3] == "A" or token[-3] == "E" or token[-3] == "O" or token[-3] == "U"): return token[0:-2]+"L" return token elif(token[-1] == "S"): #TODO: Palavras paroxítonas ou proparoxítonas terminadas em S. Ex: lápis, vírus, tagênis, ônibus, etc return token[0:-1] else: return token def converter_extenso(self, lista): lista_aux = [] index_deleted = [] count = 0 is_running = False for i in range(0, len(lista)): token = lista[i][0] tag = lista[i][1] if tag == "NUM": if (is_running is False and len(lista_aux) == count): lista_aux.append([i,[token]]) is_running = True else: lista_aux[count][1].append(token) index_deleted.append(i) elif (is_running): if ((lista[i-1][1] == "NUM") and (lista[i+1][1] == "NUM") and (tag == "CONJ")): index_deleted.append(i) else: is_running = False count += 1 for i in lista_aux: ext = extenso(' '.join(i[1])) lista[i[0]] = [ext, "NUM"] deque((list.pop(lista, i) for i in sorted(index_deleted, reverse=True)), maxlen=0) return lista