From 927ebcc797090e26403841646309c762c75c87ce Mon Sep 17 00:00:00 2001 From: Erickson Silva Date: Thu, 26 Mar 2015 18:01:43 -0300 Subject: [PATCH] Define nova versão do tradutor como default --- src/AplicaRegras.py | 446 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/AplicaSinonimos.py | 33 +++++++++++++++++++++++++++++++++ src/AplicadorRegras.py | 67 ------------------------------------------------------------------- src/Classificador.py | 44 -------------------------------------------- src/ConverteExtenso.py | 154 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/Iterator.py | 58 ++++++++++++++++++++++++++++++++-------------------------- src/LerDicionarios.py | 212 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/ModuleTranslate.py | 14 -------------- src/Output.py | 24 ------------------------ src/PortGlosa.py | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/Simplificador.py | 164 -------------------------------------------------------------------------------------------------------------------------------------------------------------------- src/StringAux.py | 83 ----------------------------------------------------------------------------------- src/Tradutor.py | 38 -------------------------------------- src/TraduzSentencas.py | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/WorkCSV.py | 115 ------------------------------------------------------------------------------------------------------------------- src/alexp.py | 135 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/new/AplicaRegras.py | 446 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- src/new/AplicaSinonimos.py | 33 --------------------------------- src/new/ConverteExtenso.py | 154 ---------------------------------------------------------------------------------------------------------------------------------------------------------- src/new/Iterator.py | 64 ---------------------------------------------------------------- src/new/LerDicionarios.py | 212 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- src/new/PortGlosa.py | 50 -------------------------------------------------- src/new/TraduzSentencas.py | 52 ---------------------------------------------------- src/new/alexp.py | 135 --------------------------------------------------------------------------------------------------------------------------------------- 24 files changed, 1114 insertions(+), 1721 deletions(-) create mode 100644 src/AplicaRegras.py create mode 100644 src/AplicaSinonimos.py delete mode 100644 src/AplicadorRegras.py delete mode 100644 src/Classificador.py create mode 100644 src/ConverteExtenso.py create mode 100644 src/LerDicionarios.py delete mode 100644 src/ModuleTranslate.py delete mode 100644 src/Output.py create mode 100644 src/PortGlosa.py delete mode 100644 src/Simplificador.py delete mode 100644 src/StringAux.py delete mode 100644 src/Tradutor.py create mode 100644 src/TraduzSentencas.py delete mode 100644 src/WorkCSV.py create mode 100644 src/alexp.py delete mode 100644 src/new/AplicaRegras.py delete mode 100644 src/new/AplicaSinonimos.py delete mode 100644 src/new/ConverteExtenso.py delete mode 100644 src/new/Iterator.py delete mode 100644 src/new/LerDicionarios.py delete mode 100644 src/new/PortGlosa.py delete mode 100644 src/new/TraduzSentencas.py delete mode 100644 src/new/alexp.py diff --git a/src/AplicaRegras.py b/src/AplicaRegras.py new file mode 100644 index 0000000..f08c2a5 --- /dev/null +++ b/src/AplicaRegras.py @@ -0,0 +1,446 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +#Autor: Erickson Silva +#Email: + +#LAViD - Laboratório de Aplicações de Vídeo Digital + +import platform +import re +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): + + def __init__(self): + self.__root = self.get_root() + self.dicionarios = LerDicionarios() + # Dicionário de funcões do campo specific do arquivo de regras + 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"} + + self.__acoes = {"change_vb":self.get_vb_infinitivo, "concate_intens":self.get_token_intensidade} + + # Gera arvore a partir do arquivos regras.xml + 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() + + # Aplica regras morfológicas apartir do arquivo regras.xml + def aplicar_regras_morfo(self, lista, sint=False): + self.lista = list(lista) # Nova cópia da lista morfológica + self.lista_corrigida =[] # Lista morfológica após a aplicação das regras + + it = Iterator() + it.load(self.lista) + + while(it.has_next()): + for morpho in self.__root.findall('morphological'): + self.has_rule = False # Boolean caso encontre encontre regra compativel + for rule in morpho.findall('rule'): + # Verifica se a regra está ativa e se o nome da regra, ou o ínicio, é igual a tag de classificação do token atual + if rule.find('active').text == "true" and rule.get('name').split("_")[0] == it.get_ticket(): + count = int(rule.find('count').text) + self.lista_iteracoes = [] # Lista que conterá todas tuplas referentes a quantidade de classes da regra + + # Obtém o intervalo de tuplas de acordo com o número de classes da regra + try: + self.lista_iteracoes = it.get_interval(count) + print '# LISTA DA ITERAÇÂO: ' + print self.lista_iteracoes + except: + continue + + # Gera o nome da regra do intervalo de tuplas e verifica se é igual ao nome da regra em si + self.nome_regra = self.gerar_nome_regra(self.lista_iteracoes) + if rule.get('name') == self.nome_regra: + self.has_rule = True + self.count_iteracao_regra = -1 + + print "REGRA MORFOLÓGICA ENCONTRADA: " + rule.get('name') + + self.lista_iteracao_regra = [] # Lista temporária | Insere tokens após a aplicação das regras + + for classe in rule.iter('class'): # for nas tags class + action = classe.find('action') + newprop = classe.find('newprop') + newtoken = classe.find('newtoken') + newtokenpos = classe.find('newtokenpos') + specific = classe.find('specific') + + self.count_iteracao_regra += 1 + tupla = self.lista_iteracoes[self.count_iteracao_regra] + + if specific is not None: + result_specific = self.__especificos[specific.text](tupla[0]) + if result_specific is False: + print "REGRA MORFOLÓGICA " + rule.get('name') + " INVÁLIDA. PROCURANDO OUTRA..." + self.has_rule = False + break + + if action is not None: + action_text = action.text + if action_text == "remove": + self.lista_iteracao_regra.append(None) + continue + elif action_text == "invert": + self.lista_iteracao_regra.reverse() + elif self.__acoes.has_key(action_text): + result_action = self.__acoes[action_text](tupla[0]).lower() + self.lista_iteracao_regra.append([result_action, tupla[1]]) + else: + self.lista_iteracao_regra.append(tupla) + + if newprop is not None: + self.lista_iteracao_regra[self.count_iteracao_regra][1] = newprop.text + + if newtoken is not None: + if newtokenpos.text == "next": + self.lista_iteracao_regra.append([newtoken.text.lower(), "NTK"]) + elif newtokenpos.text == "previous": + self.lista_iteracao_regra.append(self.lista_iteracao_regra[-1]) + self.lista_iteracao_regra[-2] = [newtoken.text.lower(), "NTK"] + elif newtokenpos.text == "end": + print "TODO" + + if self.has_rule: + it.skip(count-1) + self.lista_corrigida.extend(self.lista_iteracao_regra) + break + + if self.has_rule is False: + print 'NÃO ACHOU REGRA - ' + it.get_word().encode('utf-8') + 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_nome_regra(rule.get('name')) + regra = self.separar_regra(nome_regra) + node_pai = tgrep_nodes(p_arvore, regra[0], search_leaves=False) + if node_pai and rule.find('active').text == "true": + node_pai = node_pai[0] + node_regra = tgrep_nodes(node_pai, regra[1].replace('$', '..'), search_leaves=False) + if node_regra: + node_esq_pos = tgrep_positions(node_pai, regra[1], search_leaves=False) + node_dir_pos = tgrep_positions(node_pai, regra[2], search_leaves=False) + if node_esq_pos and node_dir_pos: + print "REGRA SINTÁTICA ENCONTRADA: " + rule.get('name') + nodes_positions = node_esq_pos + node_dir_pos + self.count = -1 + self.has_rule = True + + count_temp = -1 + for classe in rule.findall('class'): + count_temp += 1 + leaves = node_pai[nodes_positions[count_temp]].leaves() + token = filter(None, leaves)[0] + specific = classe.find('specific') + if specific is not None: + result_specific = self.__especificos[specific.text](token) + if result_specific is False: + self.has_rule = False + + if self.has_rule is False: + print "REGRA SINTÁTICA " + rule.get('name') + " INVÁLIDA. PROCURANDO OUTRA..." + break + + nodes_deleted = [] + + for classe in rule.iter('class'): + action = classe.find('action') + newprop = classe.find('newprop') + + self.count += 1 + + if action is not None: + action_text = action.text + + if action_text == "remove": + pos_del = nodes_positions[self.count] + nodes_deleted.append(node_pai[pos_del]) + node_pai[pos_del] = None + continue + + elif action_text == "invert": + aux1 = node_pai[nodes_positions[self.count]] + aux2 = node_pai[nodes_positions[self.count+1]] + node_pai[nodes_positions[self.count]] = None + node_pai[nodes_positions[self.count+1]] = None + node_pai[nodes_positions[self.count]] = aux2 + node_pai[nodes_positions[self.count+1]] = aux1 + + ''' + elif self.__acoes.has_key(action_text): + leaves = node_pai[nodes_positions[self.count]].leaves() + token = filter(None, leaves)[0] + result_action = self.__acoes[action_text](token) + + #self.lista_iteracao_regra.append([result_action, tupla[1]]) + nodes_positions[self.count] = 'TODO' + + if action_text == "concate_intens": + leaves_prev = node_pai[nodes_positions[self.count-1]].leaves() + token_prev = filter(None, leaves_prev)[0] + title_text = classe.find('title').text + if title_text == "ADV-R": + node_prev = nodes_deleted.pop() + label_prev = node_prev[0][0].label() + token_prev = filter(None, node_pai[nodes_positions[count_temp-1]].leaves())[0] + token = filter(None, node_pai[nodes_positions[count_temp]].leaves())[0] + token_concate = token_prev + "_" + token + node_pai[nodes_positions[count_temp-1]][0][0][0] = token_concate + newprop = "" + if label_prev[:-2] == "VB": + newprop = "VBi" + elif label_prev[:-3] == "ADJ": + newprop = "ADJi" + + # TODO: Verifica qual newprop adicionada e remove o nó corrente + node_pai[nodes_positions[count_temp-1]][0][0].set_label(newprop) + pos_del = nodes_positions[self.count] + node_pai[pos_del] = None + + else: + token_prev = filter(None, nodes_deleted.pop().leaves())[0] + token = filter(None, node_pai[nodes_positions[count_temp]].leaves())[0] + token_concate = token + "_" + token_prev + node_pai[nodes_positions[count_temp]][0][0][0] = token_concate + + elif action_text == "concate_neg": + print "TODO" + ''' + + if newprop is not None: + node_pai[nodes_positions[self.count]].set_label(newprop.text) + + break + + return self.converter_arv_para_lista(p_arvore) + + + # Aplica regras morfológicas na árvore sintática + def adaptar_regras_morfo_arvore(self, lista, arvore): + lista_pos_arv = [] + # Pega as posições das classificações morfológicas dos tokens na arvore sintática + for tupla in lista: + string_grep = self.corrigir_nome_regra(tupla[1]) + " < " + tupla[0].lower() + node = tgrep_positions(arvore, string_grep) + if not node: + string_grep = self.corrigir_nome_regra(tupla[1]) + " < " + self.remover_acento(tupla[0].lower()) + node = tgrep_positions(arvore, string_grep) + if node[0] in lista_pos_arv: + node.reverse() + lista_pos_arv.append(node[0]) + + # Aplica regras morfológicas na lista + morfo = self.aplicar_regras_morfo(lista, sint=True) + + # Corrige arvore de acordo com a lista após aplicar as regras morfológicas + for i in range(0, len(morfo)): + if morfo[i] is not None and morfo[i][1] == "NTK": + new_node = self.gerar_no(morfo[i]) + arvore[lista_pos_arv[i-1][:-2]].insert(2, new_node) + try: + lista_pos_arv.insert(i,lista_pos_arv[i]) + except: + continue + + 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]] = 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(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(morfo[i][1]) + + # Converte árvore sintática para uma lista de tuplas (igual a lista morfológica) + def converter_arv_para_lista(self, arvore): + folhas = filter(None, 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_nome_regra(node.label())]) + return lista_nodes + + def remover_acento(self, texto): + return normalize('NFKD', texto.encode('utf-8').decode('utf-8')).encode('ascii', 'ignore') + + # Gera um ParentedTree do NLTK apartir da string recebida + def gerar_no(self, s): + all_ptrees = [] + t_string = '('+s[1] + ' ' + s[0]+')' + ptree = ParentedTree.convert(Tree.fromstring(t_string)) + all_ptrees.extend(t for t in ptree.subtrees() + if isinstance(t, Tree)) + return ptree + + # Corrige nome da regra descrita no arquivo de regras para como está na árvore sintática + def corrigir_nome_regra(self, anotacao): + split = anotacao.split('_') + for i in range(0, len(split)): + split[i] = re.sub(r"[-+]","_", split[i]) + split[i] = re.sub(r"\$","_S",split[i]) + return "-".join(split).encode('utf-8') + + # Separa a regra por nó pai e seus filhos + 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 + + # Gera nome de regra apartir de uma lista + def gerar_nome_regra(self, lista): + nome_regra = [] + for t in lista: + nome_regra.append(t[1]) + return "_".join(nome_regra) + + def verificar_adv_tempo(self, token): + for tupla in self.lista: + if self.dicionarios.has_adverbio_tempo(tupla[0]): + return True + return False + + def verificar_excecao_plural(self, token): + return self.dicionarios.has_excecao_plural(token) + + def verificar_vb_infinitivo(self, token): + return self.dicionarios.has_verbo_infinitivo(token) + + 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): + return self.dicionarios.has_verbo_muda_negacao(token) + + def get_vb_infinitivo(self, token): + if self.dicionarios.has_verbo_infinitivo(token): + return self.dicionarios.get_verbo_infinitivo(token) + return token + + def get_token_intensidade(self, token): + print 'TODO' + + + # Simplifica a sentença para que possa evitar a ditalogia + def simplificar_sentenca(self, lista): + lista_simplificada = list(lista) + it = Iterator() + it.load(lista_simplificada) + num = False + while(it.has_next()): + tag = it.get_ticket() + + if tag == "NUM": + num = True + + if tag[-2:] == "-P" and self.verificar_excecao_plural(it.get_word()): + singular = self.analisar_plural(it.get_word()) + lista_simplificada[it.get_count()][0] = singular + + if num: + return self.converter_extenso(lista_simplificada) + return lista_simplificada + + # Alterar uma palavra do plural para o singular + 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 + + # Converter número por extenso para numeral + def converter_extenso(self, lista): + lista_extensos = [] + indices_deletar = [] + count = 0 + is_sequence = False + + for i in range(0, len(lista)): + token = lista[i][0] + tag = lista[i][1] + if tag == "NUM": + # Verifico se não há sequência de obtenção de extenso em andamento para começar a obter um nova sequência + if (is_sequence is False): # and len(lista_extensos) == count (???) + lista_extensos.append([i,[token]]) # i = Posição do primeiro extenso encontrado, token = número por extenso + is_sequence = True + else: + lista_extensos[count][1].append(token) # Pego número por extenso que está na sequência e adiciona na lista + indices_deletar.append(i) # Insiro indice na lista para ser removido depois + elif (is_sequence): + # Se o token anterior e o próximo foram classificados como número, e o token atual como conjunção, significa que podemos remove-lo + if ((lista[i-1][1] == "NUM") and (lista[i+1][1] == "NUM") and (tag == "CONJ")): + indices_deletar.append(i) + else: + # A sequência foi quebrada, o que significa que selecionamos o extenso do número por completo + # Podemos agora procurar por outra sequencia de número por extenso na lista + is_sequence = False + count += 1 + + for extenso in lista_extensos: + ext = convert_extenso(' '.join(extenso[1])) + lista[extenso[0]] = [ext, "NUM"] + + deque((list.pop(lista, i) for i in sorted(indices_deletar, reverse=True)), maxlen=0) + return lista \ No newline at end of file diff --git a/src/AplicaSinonimos.py b/src/AplicaSinonimos.py new file mode 100644 index 0000000..f2f1030 --- /dev/null +++ b/src/AplicaSinonimos.py @@ -0,0 +1,33 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +#Autor: Erickson Silva +#Email: + +#LAViD - Laboratório de Aplicações de Vídeo Digital + +import os +import csv +import sys +from nltk.tree import Tree +from LerDicionarios import * + +class AplicaSinonimos(object): + """Classe para aplicar sinonimos após a aplicação de regras morfológicas/sintáticas""" + + def __init__(self): + self.dicionarios = LerDicionarios() + + # Itera sobre os tokens obtendo os sinonimos + def aplicar_sinonimos(self, lista_anotada): + lista_corrigida = [] + for tupla in lista_anotada: + sinonimo = self.verificar_sinonimo(tupla[0]) + lista_corrigida.append(sinonimo) + return " ".join(lista_corrigida) + + # Verifica se há sinonimo do token + def verificar_sinonimo(self, token): + if self.dicionarios.has_sinonimo(token): + return self.dicionarios.get_sinonimo(token) + return token \ No newline at end of file diff --git a/src/AplicadorRegras.py b/src/AplicadorRegras.py deleted file mode 100644 index 019d250..0000000 --- a/src/AplicadorRegras.py +++ /dev/null @@ -1,67 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -#Autor: Erickson Silva - -import xml.etree.ElementTree as ET -from os.path import expanduser -import platform - -class AplicadorRegras(object): - - # inicializacao das variaves - def __init__(self): - - so = platform.system() - if so == 'Windows': - self.__tree = ET.parse(expanduser("~")+'\\vlibras-translate\data\\regras.xml') - else: - self.__tree = ET.parse(expanduser("~")+'/vlibras-translate/data/regras.xml') - - self.__root = self.__tree.getroot() - self.__tAux = [] - self.__dAux = {} - - # aplica as regras - def aplicarRegras(self, ts): - self.__n = len(ts) # quantidade de tokens - for i in range(0,self.__n): - self.__tAux.append(self.__n) - self.__name = self.getNameRule(ts) # todos os etiquetadores numa so string (ver linha 35) - for morpho in self.__root: - for rule in morpho.findall('rule'): # procura a tag rule - if rule.get('name') == self.__name: # procura o atributo name na tag rule (ver linha 17) - if rule.find('active').text == "true": # verifica se a regra esta ativa - self.__c = 0 - for classe in rule.iter('class'): # for nas tags class - self.__dAux[self.__c] = int(classe.find('newpos').text) # preenche dicionario com a ordem atual e futura das palavras - self.__c += 1 - self.__c = 0 - for w,t in ts: - i = self.__dAux.get(self.__c) # pega o indice de onde ficara a palavra - self.__tAux[i] = ([w,t]) # preenche a lista com a palavra+etiqueta na posicao correta (segundo o arquivo regras.xml) - self.__c += 1 - return self.__tAux # retorna nova lista (ordenada) - return ts # retorna a lista sem alteracoes (nao existe regra) - - def getNameRule(self, ts): - self.__name = "" - for w,t in ts: - if t[:2] != "VB": - self.__name += t - else: - self.__name += t[:2] - return self.__name - - - - - - - - - - - - - diff --git a/src/Classificador.py b/src/Classificador.py deleted file mode 100644 index 4d5bc60..0000000 --- a/src/Classificador.py +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -#Autor: Erickson Silva - -from Aelius import AnotaCorpus, Toqueniza, Extras - -class Classificador(object): - - # inicializacao das variaveis - def __init__(self): - self.__h = Extras.carrega("AeliusHunPos") # carrega o modelo de idioma (passado por parametro ao instanciar) - - def anotaSentencas(self, str): - self.__t = "" - self.__tokens = "" - #try: - # tokenizae - self.__tokens = Toqueniza.TOK_PORT.tokenize(str) - - # realiza a classificacao morfologica - self.__t = AnotaCorpus.anota_sentencas([self.__tokens],self.__h,'hunpos') - - return self.listClean(self.__t) - #except: - # print "Erro ao efetuar a classificação morfologica." - - - def listClean(self, l): - lClean = [] - for w,t in l[0]: - lClean.append([w,t]) - return lClean - - # faz a impressao (usado apenas pra testes) - def imprimeSentencas(self): - for w,t in self.t[0]: - print "%s_%s " % (w,t), - - - - - - diff --git a/src/ConverteExtenso.py b/src/ConverteExtenso.py new file mode 100644 index 0000000..bb729ed --- /dev/null +++ b/src/ConverteExtenso.py @@ -0,0 +1,154 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +#Autor: Erickson Silva +#Email: + +#LAViD - Laboratório de Aplicações de Vídeo Digital + +import sys +from unicodedata import normalize +from Iterator import * + +num = {"zero":0, "um":1, "dois":2, "tres":3, "quatro":4, "cinco":5, "seis":6, +"sete":7, "oito":8, "nove":9} + +ext = [{"um":"1", "dois":"2", "tres":"3", "quatro":"4", "cinco":"5", "seis":"6", +"sete":"7", "oito":"8", "nove":"9", "dez":"10", "onze":"11", "doze":"12", +"treze":"13", "quatorze":"14", "quinze":"15", "dezesseis":"16", +"dezessete":"17", "dezoito":"18", "dezenove":"19"}, {"vinte":"2", "trinta":"3", +"quarenta":"4", "cinquenta":"5", "sessenta":"6", "setenta":"7", "oitenta":"8", +"noventa":"9"}, {"cento":"1", "cem":"1", "duzentos":"2", "trezentos":"3", +"quatrocentos":"4", "quinhentos":"5", "seissentos":"6", "setessentos":"7", +"oitocentos":"8", "novecentos":"9"}] + +und = {"mil":1000, "milhao":1000000, "bilhao":1000000000, "trilhao":1000000000000} +unds = {"mil":"000", "milhao":"000000","milhoes":"000000", "bilhao":"000000000","bilhoes":"000000000", "trilhao":"000000000000", "trilhoes":"000000000000"} + + + +def oneDigit(x): + return ext[0][x] + +def twoDigit(x): + try: + return ext[1][x[0]]+ext[0][x[1]] + except: + return ext[1][x[0]]+"0" + +def threeDigit(x): + return ext[2][x[0]]+ext[1][x[1]]+ext[0][x[2]] + +# Não faço mais a minima idéia de como fiz isso, só sei que funciona! +def extensoUnit(n): + sn = n.split(",") + size = len(sn) + firstWord = sn[0] + endWord = "" + numExt = "" + + if(unds.has_key(sn[size-1])): + size -= 1 + endWord = sn[size] + del sn[size] + + if(ext[0].has_key(firstWord)): + numExt = oneDigit(firstWord) + + elif (ext[1].has_key(firstWord)): + numExt = twoDigit(sn) + + elif (ext[2].has_key(firstWord)): + if(size == 1): + numExt = ext[2][firstWord]+"00" + elif (size == 2): + if(sn[1] == "dez"): + numExt = ext[2][firstWord]+oneDigit(sn[1]) + try: + numExt = ext[2][firstWord]+"0"+oneDigit(sn[1]) + except: + numExt = ext[2][firstWord]+twoDigit([sn[1]]) + else: + numExt = threeDigit(sn) + + if(endWord != ""): + numExt = numExt+unds[endWord] + + return numExt + + +''' +Comece com uma lista vazia. Itere pelas palavras da string da esquerda +para direita. Ao encontrar um numeral, adicione o número à lista se a +última palavra foi uma escala, ou some ao último numero da lista se a +última palavra foi um numeral. Ao encontrar uma escala, multiplique o +último número da lista de acordo. Quando terminar, some tudo e retorne +o resultado. +''' + +# TODO: Refatorar para nao usar mais o extensoUnit +def convert_extenso(extenso): + global newToken, auxToken + extensoQuebrado = extenso.lower().split(" ") + nums = [] + it = Iterator() + it.load(extensoQuebrado) + while(it.has_next()): + token = simplifica(it.get_token()) + tokenAnterior = simplifica(it.get_token(-1)) + if (und.has_key(token)): + if(it.get_count() == 0): + nums.append(und[token]) + else: + newToken = und[token] * int(nums[-1]) + nums[-1] = newToken + else: + if (num.has_key(token)): + auxToken = num[token] + elif (not und.has_key(token)): + auxToken = extensoUnit(token) + + if((not und.has_key(tokenAnterior)) and it.get_count() > 0): + newToken = int(auxToken) + int(nums[-1]) + nums[-1] = newToken + else: + nums.append(auxToken) + return soma(nums) + +def soma(lista): + soma = 0 + for i in lista: + soma += int(i) + return soma + +def simplifica(txt): + newToken = "" + try: + newToken = normalize('NFKD', txt.decode('utf-8')).encode('ASCII','ignore') + except: + newToken = normalize('NFKD', txt.decode('iso-8859-1')).encode('ASCII','ignore') + + if(newToken[-3:] == "oes"): + return newToken[:-3] + "ao" + + return newToken + +# Test +''' +if __name__ == '__main__': + n = sys.argv[1] + return extenso(n) + arquivoExts = open('exts', 'r') + listaExts = arquivoExts.readlines() + arquivoNums = open('nums', 'r') + listaNums = arquivoNums.readlines() + for i in range(0,500): + n = listaNums[i].replace("\n","") + e = listaExts[i].replace("\n","") + numNew = extenso(e) + if (str(numNew) != n): + print n + " != " + str(numNew) + #else: + # print "OK: " + n + " == " + str(numNew) +''' + diff --git a/src/Iterator.py b/src/Iterator.py index d900bae..c2fbe03 100644 --- a/src/Iterator.py +++ b/src/Iterator.py @@ -1,57 +1,63 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -#Autor: Erickson Silva +#Autor: Erickson Silva +#Email: -from StringAux import * +#LAViD - Laboratório de Aplicações de Vídeo Digital class Iterator(object): + """Classe para iterar sobre as tuplas (palavra,etiqueta) após análise morfologica""" - # inicializacao das variaveis - def __init__(self): + def init(self): self.count = -1 def load(self, lista): - self.__list = list(lista); + self.reset() + self.list = list(lista); self.size = len(lista) def reset(self): self.count = -1 - def getSize(self): + def get_size(self): return self.size - def getCount(self): + def get_count(self): return self.count - def getToken(self, i=None): - if(i == "+"): - return self.__list[self.count+1] + def get_token(self, i=None): + if(i != None): + return self.list[self.count+(i)] + return self.list[self.count] - elif(i == "-"): - return self.__list[self.count-1] + def get_word(self): + return self.get_token()[0] - return self.__list[self.count] + def get_ticket(self): + return self.get_token()[1] - def getAtualW(self): - return remover_acentos(self.getToken(0)[0].upper().encode('utf-8')) + def get_next_word(self): + return self.get_token(1)[0] - def getAtualT(self): - return self.getToken(0)[1].upper().encode('utf-8') + def get_next_ticket(self): + return self.get_token(1)[1] - def getProxW(self): - return remover_acentos(self.getToken("+")[0].upper().encode('utf-8')) + def get_prev_word(self): + return self.get_token(-1)[0] - def getProxT(self): - return self.getToken("+")[1].upper().encode('utf-8') + def get_prev_ticket(self): + return self.get_token(-1)[1] - def getAntW(self): - return remover_acentos(self.getToken("-")[0].upper().encode('utf-8')) + def get_interval(self, n): + if self.count+n > self.size: + raise IndexError + return self.list[self.count:self.count+n] - def getAntT(self): - return self.getToken("-")[1].upper().encode('utf-8') + def skip(self, n): + self.count += n - def hasNext(self): + def has_next(self): if(self.count < self.size-1): self.count += 1 return True diff --git a/src/LerDicionarios.py b/src/LerDicionarios.py new file mode 100644 index 0000000..7be223c --- /dev/null +++ b/src/LerDicionarios.py @@ -0,0 +1,212 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +#Autor: Erickson Silva +#Email: + +#LAViD - Laboratório de Aplicações de Vídeo Digital + +from os.path import expanduser +from os import environ +import csv +import platform + +class LerDicionarios(object): + + def __init__(self): + self.path = self.get_path() + self.set_exc_plural = [] + self.dic_adv_intensidade = {} + self.set_adv_tempo = [] + self.set_art = [] + self.set_prep = [] + self.dic_sin = {} + self.set_sb_2_gen = [] + self.dic_vb_infinitivo = {} + self.set_vb_ligacao = [] + self.dic_vb_muda_negacao = [] + self.file = '' + self.carregar_dicionarios() + + def get_path(self): + if platform.system() == 'Windows': + return os.environ.get("HOMEDRIVE") + "\\vlibras-libs\\vlibras-translate\data\\" + return expanduser("~") + "/vlibras-translate/data/" + + def carregar_dicionarios(self): + self.carregar_excecoes_plural() + self.carregar_adverbios_intensidade() + self.carregar_adverbios_tempo() + self.carregar_artigos() + self.carregar_preposicoes() + self.carregar_sinonimos() + self.carregar_subs_2_generos() + self.carregar_verbos_infinitivo() + self.carregar_verbos_ligacao() + self.carregar_verbos_muda_negacao + + + def carregar_excecoes_plural(self): + try: + self.file = csv.reader(open(self.path+"excecoesPlural.csv")) + except IOError, (errno, strerror): + print "I/O error(%s): %s" % (errno, strerror) + print "carregar_excecoes_plural" + + rows = [] + for row in self.file: + rows.append(row[0].decode("utf-8")) + self.set_exc_plural = set(rows) + + def carregar_adverbios_intensidade(self): + try: + self.file = csv.reader(open(self.path+"adverbiosIntensidade.csv"), delimiter=";") + except IOError, (errno, strerror): + print "I/O error(%s): %s" % (errno, strerror) + print "carregar_adverbios_intensidade" + + for row in self.file: + if row[1] != "": + self.dic_adv_intensidade[row[0].decode("utf-8")] = row[1].decode("utf-8") + + def carregar_adverbios_tempo(self): + try: + self.file = csv.reader(open(self.path+"adverbiosTempo.csv")) + except IOError, (errno, strerror): + print "I/O error(%s): %s" % (errno, strerror) + print "carregar_adverbios_tempo" + + rows = [] + for row in self.file: + rows.append(row[0].decode("utf-8")) + self.set_adv_tempo = set(rows) + + def carregar_artigos(self): + try: + self.file = csv.reader(open(self.path+"artigos.csv")) + except IOError, (errno, strerror): + print "I/O error(%s): %s" % (errno, strerror) + print "carregar_artigos" + + rows = [] + for row in self.file: + rows.append(row[0].decode("utf-8")) + self.set_art = set(rows) + + def carregar_preposicoes(self): + try: + self.file = csv.reader(open(self.path+"preposicoes.csv")) + except IOError, (errno, strerror): + print "I/O error(%s): %s" % (errno, strerror) + print "carregar_preposicoes" + + rows = [] + for row in self.file: + rows.append(row[0].decode("utf-8")) + self.set_prep = set(rows) + + def carregar_sinonimos(self): + try: + self.file = csv.reader(open(self.path+"sinonimos.csv"), delimiter=";") + except IOError, (errno, strerror): + print "I/O error(%s): %s" % (errno, strerror) + print "carregar_sinonimos" + + for row in self.file: + if row[1] != "": + try: + self.dic_sin[row[0].decode("utf-8")] = row[1].decode("utf-8") + except UnicodeDecodeError: + self.dic_sin[row[0].decode('iso8859-1').encode('utf-8').decode('utf-8')] = row[1].decode('iso8859-1').encode('utf-8').decode('utf-8') + + def carregar_subs_2_generos(self): + try: + self.file = csv.reader(open(self.path+"subs2Generos.csv")) + except IOError, (errno, strerror): + print "I/O error(%s): %s" % (errno, strerror) + print "carregar_subs_2_generos" + + rows = [] + for row in self.file: + rows.append(row[0].decode('iso8859-1').encode('utf-8').decode('utf-8')) + self.set_sb_2_gen = set(rows) + + def carregar_verbos_infinitivo(self): + try: + self.file = csv.reader(open(self.path+"verbosInfinitivo.csv"), delimiter=";") + except IOError, (errno, strerror): + print "I/O error(%s): %s" % (errno, strerror) + print "carregar_verbos_infinitivo" + + for row in self.file: + if row[1] != "": + try: + self.dic_vb_infinitivo[row[0].decode("utf-8")] = row[1].decode("utf-8") + except UnicodeDecodeError: + self.dic_vb_infinitivo[row[0].decode('iso8859-1').encode('utf-8').decode('utf-8')] = row[1].decode('iso8859-1').encode('utf-8').decode('utf-8') + + def carregar_verbos_ligacao(self): + try: + self.file = csv.reader(open(self.path+"verbosLigacao.csv")) + except IOError, (errno, strerror): + print "I/O error(%s): %s" % (errno, strerror) + print "carregar_verbos_ligacao" + + rows = [] + for row in self.file: + rows.append(row[0].decode("utf-8")) + self.set_vb_ligacao = set(rows) + + + def carregar_verbos_muda_negacao(self): + try: + self.file = csv.reader(open(self.path+"verbosMudaNegacao.csv"), delimiter=";") + except IOError, (errno, strerror): + print "I/O error(%s): %s" % (errno, strerror) + print "carregar_verbos_muda_negacao" + + for row in self.file: + if row[1] != "": + self.dic_vb_muda_negacao[row[0].decode("utf-8")] = row[1].decode("utf-8") + + def has_excecao_plural(self, token): + return token not in self.set_exc_plural + + def has_adverbio_intensidade(self, token): + return self.dic_adv_intensidade.has_key(token) + + def has_adverbio_tempo(self, token): + return token in self.set_adv_tempo + + def has_artigo(self, token): + return token in self.set_art + + def has_preposicao(self, token): + return token in self.set_prep + + def has_sinonimo(self, token): + return self.dic_sin.has_key(token) + + def has_subst_2_generos (self, token): + return token in self.set_sb_2_gen + + def has_verbo_infinitivo(self, token): + return self.dic_vb_infinitivo.has_key(token) + + def has_verbo_ligacao(self, token): + return token in self.set_vb_ligacao + + def has_verbo_muda_negacao(self, token): + return self.dic_vb_muda_negacao.has_key(token) + + def get_adverbio_intensidade(self, token): + return self.dic_adv_intensidade[token] + + def get_sinonimo(self, token): + return self.dic_sin[token] + + def get_verbo_infinitivo(self, token): + return self.dic_vb_infinitivo[token] + + def get_verbo_muda_negacao(self, token): + return self.dic_vb_muda_negacao[token] \ No newline at end of file diff --git a/src/ModuleTranslate.py b/src/ModuleTranslate.py deleted file mode 100644 index c9e72f7..0000000 --- a/src/ModuleTranslate.py +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -from Tradutor import * - -tradutor = Tradutor() - -def iniciar(x): - try: - text = x.decode("utf-8") - except: - text = x.decode("iso-8859-1") - - return tradutor.traduzir(text) diff --git a/src/Output.py b/src/Output.py deleted file mode 100644 index 3259d3c..0000000 --- a/src/Output.py +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -#Autor: Erickson Silva - -import sys -from Iterator import * -from StringAux import * - -class Output(object): - - # inicializa a variavel com o valor passado por paramentro ao instanciar - def __init__(self): - self.it = Iterator() - - # executa a saida - def executeOut(self, ts): - self.__glosa = [] - self.it.load(ts) - while(self.it.hasNext()): - self.__glosa.append(self.it.getAtualW()) - self.it.reset() - return ' '.join(self.__glosa) - diff --git a/src/PortGlosa.py b/src/PortGlosa.py new file mode 100644 index 0000000..a8f70ba --- /dev/null +++ b/src/PortGlosa.py @@ -0,0 +1,50 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +#Autor: Erickson Silva +#Email: + +#LAViD - Laboratório de Aplicações de Vídeo Digital + +from TraduzSentencas import * + +def traduzir(texto): + glosa = iniciar_traducao(texto) + if glosa: + return glosa + return "selecione_texto" + +def iniciar_traducao(texto): + texto_quebrado = quebrar_texto(texto) + num_threads = len(texto_quebrado) + texto_traduzido = [] + threads = [] + + for i in range(num_threads): + if texto_quebrado[i] > 0 and texto_quebrado[i] != " ": + threads.insert(i, TraduzSentencas(texto_quebrado[i])) + threads[i].start() + for i in range(num_threads): + threads[i].join() + texto_traduzido.append(threads[i].obter_glosa()) + + try: + return " ".join(texto_traduzido) + except: + return None + +def quebrar_texto(texto): + quantidade_pontos = texto.count('. ') + sentencas = [] + for i in range(quantidade_pontos): + posicao_ponto = texto.find('.') + if texto[posicao_ponto+2].isupper(): + sentencas.append(texto[:posicao_ponto]) + texto = texto[posicao_ponto+2:] + if len(texto) > 0: + sentencas.append(texto) + return sentencas + +def ajuda(): + #TODO: Adicionar um pequeno tuto aqui + print "Help" \ No newline at end of file diff --git a/src/Simplificador.py b/src/Simplificador.py deleted file mode 100644 index fefbe76..0000000 --- a/src/Simplificador.py +++ /dev/null @@ -1,164 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -#Autor: Erickson Silva - -from WorkCSV import * -from Iterator import * -from StringAux import * - -class Simplificador(object): - - # inicializa todos as variaveis - def __init__(self): - self.it = Iterator() - self.__csv = WorkCSV() - self.__dicInf = {} - self.__dicSin = {} - self.__dicWords = {} - self.__dic2Gen = {} - self.__dicTemVerbs = {} - self.executeWorkCSV() - - # retira artigos e preposicoes; passa verbos para infinitivo e verificar se há sinonimos - def simplificar(self, texto): - self.__ts = [] - self.it.load(texto) - self.__verb = False - self.__adv = False; - self.__countVerb = 0 - self.__countAdv = 0 - countWords = 0 - while(self.it.hasNext()): - w = self.auxConvert(self.it.getAtualW()) - t = self.it.getAtualT() - self.__b = False - if self.__dicWords.has_key(t) == False: # verifica se nao eh artigo/preposicao - wu = str(w).upper() # deixa o token maiusculo - #if t[:2] == "VB": - if t[-2:] == "-P": - wu = self.pluralAnalysis(w) - if t == "VB-P" or t == "VB-D" or t == "VB-R": - self.__verb = True - self.__countVerb += 1 - if t[:3] == "ADV": - self.__adv = True - self.__countAdv += 1 - if self.__dicInf.has_key(wu): # verifica se ha um verbo infinitivo desse token - sAux = self.__dicInf[wu] # se sim, adiciona numa string aux - if self.__dicSin.has_key(sAux): # verifica se ha um sinonimo para esse verbo infinitivo - self.__ts.append([self.__dicSin[sAux],t]) # se sim, entao adiciona na lista - self.__b = True - else: - self.__ts.append([sAux,t]) # caso contrario, adiciona so o verbo infinitivo msm - self.__b = True - if self.__b == False and self.__dicSin.has_key(wu): # verifica se nao foi encontrado verbo infinitivo e se ha sinonimo - self.__ts.append([self.__dicSin[wu],t]) # adiciona na o sinonimo lista - self.__b = True - - if self.__dic2Gen.has_key(wu): - del self.__ts[-1] - lenTicket = len(self.it.getAntT()) - if ((self.__dicWords.has_key(self.it.getAntT())) and (self.it.getAntT()[lenTicket-1:] == "F") or (self.it.getAntT()[lenTicket-3:] == "F-P")): - self.__ts.append(["MULHER " + wu,t]) - else: - self.__ts.append(["HOMEM " + wu,t]) - self.__b = True - if self.__b == False: # verifica se nao encontrou nem verbo infinito ou sinonimo - self.__ts.append([wu,t]) - countWords += 1 - self.it.reset() - if self.__verb == True: - return self.verbalAnalysis(self.__ts) - return self.__ts - - # cria e recupera todos os dicionarios (verbos inf., sinonimos e artigos/preposicoes) - def executeWorkCSV(self): - self.__dicInf = self.__csv.getDicInf() - self.__dicSin = self.__csv.getDicSin() - self.__dicWords = self.__csv.getDicWords() - self.__dic2Gen = self.__csv.getDic2Gen() - self.__dicTemVerbs = self.__csv.getDicTemVerbs() - - # converte romano para numero - def auxConvert(self, t): - try: - return roman_to_int(t) - except: - return t - - - def verbalAnalysis(self, lista): - lv = [] - self.it.load(lista) - hasFut = False - hasPas = False - count = 0 - while(self.it.hasNext()): - w = self.it.getAtualW().upper() - t = self.it.getAtualT() - - if(t[:3] == "ADV"): - if (self.__dicTemVerbs.has_key(w)): - self.it.reset() - #print "ADV: retornou lista original" - return lista - - if(t == "VB-P"): - if (self.__countVerb > 1): - count += 1 - #print "VB-P: Incrementou" - if(count == self.__countVerb): - #print "VB-P Adicionou " + w - lv.append([w,t]) - else: - #print "VB-P: retornou lista original" - self.it.reset() - return lista - elif(t == "VB-D"): - count += 1 - hasPas = True - #print "VB-D: Incrementou" - if(count == self.__countVerb): - #print "VB-D Adicionou " + w - lv.append([w,t]) - elif(t == "VB-R"): - count += 1 - hasFut = True - #print "VB-R: Incrementou" - if(count == self.__countVerb): - #print "VB-R Adicionou " + w - lv.append([w,t]) - else: - lv.append([w,t]) - if (hasFut): - lv.append(["FUTURO", "TVB"]) - elif (hasPas): - lv.append(["PASSADO", "TVB"]) - self.it.reset() - return lv - - - def pluralAnalysis(self, word): - - if(word[-3:] == "OES" or word[-2:] == "AES" or word[-2:] == "AOS"): - return word[0:-3]+"AO" - elif(word[-3:] == "RES" or word[-2:] == "ZES" or word[-2:] == "NES"): - return word[0:-2] - elif(word[-3:] == "SES"): - #TODO: Algumas palavras possuem marcações gráficas na raiz singular. Ex: Gás – Gases - return word[0:-2] - elif(word[-2:] == "NS"): - return word[0:-2]+"M" - elif(word[-3:] == "EIS"): - return word[0:-3]+"IL" - elif(word[-2:] == "IS"): - if(word[-3] == "A" or word[-3] == "E" or word[-3] == "O" or word[-3] == "U"): - return word[0:-2]+"L" - else: - return word - elif(word[-1] == "S"): - #TODO: Palavras paroxítonas ou proparoxítonas terminadas em S. Ex: lápis, vírus, tênis, ônibus, etc - return word[0:-1] - else: - return word \ No newline at end of file diff --git a/src/StringAux.py b/src/StringAux.py deleted file mode 100644 index e690a6b..0000000 --- a/src/StringAux.py +++ /dev/null @@ -1,83 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -from unicodedata import normalize - -ext = {1:"um", 2:"dois", 3:"três", 4:"quatro", 5:"cinco", 6:"seis", 7:"sete", 8:"oito", 9:"nove", 0:"zero"} - -def extenso(n): - strn = str(n) - sizen = len(strn) - tokens = [] - for i in range (0, sizen): - x = int(strn[i]) - tokens.append(ext[x]) - return ' '.join(tokens) - -""" -def extenso(n): - strn = str(n) - sizen = len(strn) - tokens = [] - for i in range (0, sizen): - tokens.append(strn[i]) - return ' '.join(tokens) -""" - -def remover_acentos(txt): - - """ Devolve cópia de uma str substituindo os caracteres - acentuados pelos seus equivalentes não acentuados. - - ATENÇÃO: carateres gráficos não ASCII e não alfa-numéricos, - tais como bullets, travessões, aspas assimétricas, etc. - são simplesmente removidos! - - >>> remover_acentos('[ACENTUAÇÃO] ç: áàãâä! éèêë? íìĩîï, óòõôö; úùũûü.') - '[ACENTUACAO] c: aaaaa! eeee? iiiii, ooooo; uuuuu.' - - """ - try: - return normalize('NFKD', txt.decode('utf-8')).encode('ASCII','ignore') - except: - return normalize('NFKD', txt.decode('iso-8859-1')).encode('ASCII','ignore') - - -def roman_to_int(input): - if not isinstance(input, type("")): - raise TypeError, "expected string, got %s" % type(input) - input = input.upper( ) - nums = {'M':1000, - 'D':500, - 'C':100, - 'L':50, - 'X':10, - 'V':5, - 'I':1} - sum = 0 - for i in range(len(input)): - try: - value = nums[input[i]] - if i+1 < len(input) and nums[input[i+1]] > value: - sum -= value - else: sum += value - except KeyError: - raise ValueError, 'input is not a valid Roman numeral: %s' % input - - if int_to_roman(sum) == input: return sum - else: raise ValueError, 'input is not a valid Roman numeral: %s' % input - -def int_to_roman(input): - if not isinstance(input, type(1)): - raise TypeError, "expected integer, got %s" % type(input) - if not 0 < input < 4000: - raise ValueError, "Argument must be between 1 and 3999" - ints = (1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1) - nums = ('M', 'CM', 'D', 'CD','C', 'XC','L','XL','X','IX','V','IV','I') - result = [] - - for i in range(len(ints)): - count = int(input / ints[i]) - result.append(nums[i] * count) - input -= ints[i] * count - return ''.join(result) \ No newline at end of file diff --git a/src/Tradutor.py b/src/Tradutor.py deleted file mode 100644 index 47b43d4..0000000 --- a/src/Tradutor.py +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -#Autor: Erickson Silva - -from Classificador import * -from Simplificador import * -#from AplicadorRegras import * -from Output import * -from StringAux import * - - -class Tradutor(object): - - def __init__(self): - #instanciando os objetos - self.__classificador = Classificador() - self.__simplificador = Simplificador() - #self.__regras = AplicadorRegras() - self.__out = Output() - - - def traduzir(self, txt): - self.__tr = None - - #faz a tokenizacao e a classificacao - self.__t = self.__classificador.anotaSentencas(txt) - - #retira artigos e preposicoes - self.__ts = self.__simplificador.simplificar(self.__t) - self.__t = None - - #aplica as regras - #self.__tr = self.__regras.aplicarRegras(self.__ts) - #self.__ts = None - - #executa a saida - return self.__out.executeOut(self.__ts).encode("utf-8") diff --git a/src/TraduzSentencas.py b/src/TraduzSentencas.py new file mode 100644 index 0000000..f5e1c86 --- /dev/null +++ b/src/TraduzSentencas.py @@ -0,0 +1,52 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +#Autor: Erickson Silva +#Email: + +#LAViD - Laboratório de Aplicações de Vídeo Digital + +from threading import Thread +import alexp +from AplicaSinonimos import * +from AplicaRegras import * +import logging + +class TraduzSentencas(Thread): + + def __init__(self, sentenca): + Thread.__init__(self) + self.sentenca = sentenca + self.glosa = "" + self.aplic_sinonimos = AplicaSinonimos() + self.aplic_regras = AplicaRegras() + logging.basicConfig(filename='translate.log', + format='%(asctime)s - %(levelname)s:\n%(message)s\n\n\n##############################################\n\n', + level=logging.ERROR) + + + def run(self): + try: + analise_sintatica = alexp.run(self.sentenca) + except Exception as ex: + self.salvar_log(str(ex)) + analise_sintatica = None + + analise_morfologica = alexp.getAnaliseMorfologica() + + if (isinstance(analise_sintatica,type(None))): + print "# ANÁLISE MORFOLÓGICA" + regras_aplicadas = self.aplic_regras.aplicar_regras_morfo(analise_morfologica) + else: + print "# ANÁLISE SINTÁTICA" + regras_aplicadas = self.aplic_regras.aplicar_regras_sint(analise_morfologica, analise_sintatica) + + sentenca_corrigida = self.aplic_regras.simplificar_sentenca(regras_aplicadas) + sinonimos_aplicados = self.aplic_sinonimos.aplicar_sinonimos(sentenca_corrigida) + self.glosa = sinonimos_aplicados.upper().encode('utf-8') + + def obter_glosa(self): + return self.glosa + + def salvar_log(self, erro): + logging.error(erro) \ No newline at end of file diff --git a/src/WorkCSV.py b/src/WorkCSV.py deleted file mode 100644 index c5eb2f8..0000000 --- a/src/WorkCSV.py +++ /dev/null @@ -1,115 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -#Autor: Erickson Silva - -import csv, platform -from os.path import expanduser - -class WorkCSV(object): - - # Define e inicializa os atributos - def __init__(self): - - so = platform.system() - if so == 'Windows': - self.__path = expanduser("~") + "\\vlibras-translate\data\\" - else: - self.__path = expanduser("~") + "/vlibras-translate/data/" - - self.__fileInf = '' - self.__dicInf = {} - self.__fileSin = '' - self.__dicSin = {} - self.__fileWords = '' - self.__dicWords = {} - self.__file2Gen = '' - self.__dic2Gen = {} - self.__fileTemVerbs = '' - self.__dicTemVerbs = {} - self.createDicInf() - self.createDicSin() - self.createDicWords() - self.createDic2Gen() - self.createDicTemVerbs() - - # Abre o arquivo que contem os verbos no infinitivo e preenche o dicionario com os mesmos - def createDicInf(self): - try: - self.__fileInf = csv.reader(open(self.__path+"dicPortGlosa.csv"), delimiter=";") - except IOError, (errno, strerror): - print "I/O error(%s): %s" % (errno, strerror) - print "createDicInf" - - for row in self.__fileInf: - if row[1] != "": - try: - self.__dicInf[row[0].decode("utf-8")] = row[1].decode("utf-8") - except UnicodeDecodeError: - self.__dicInf[row[0].decode('iso8859-1').encode('utf-8')] = row[1].decode('iso8859-1').encode('utf-8') - - # Abre o arquivo que contem os sinonimos e preenche o dicionario com os mesmos - def createDicSin(self): - try: - self.__fileSin = csv.reader(open(self.__path+"portuguesGlosa.csv"), delimiter=";") - except IOError, (errno, strerror): - print "I/O error(%s): %s" % (errno, strerror) - print "createDicSin" - - for row in self.__fileSin: - if row[1] != "": - self.__dicSin[row[0].decode("utf-8")] = row[1].decode("utf-8") - - - # Abre o arquivo que contem os tempos verbais - def createDicTemVerbs(self): - try: - self.__fileTemVerbs = csv.reader(open(self.__path+"temposVerbais.csv"), delimiter=";") - except IOError, (errno, strerror): - print "I/O error(%s): %s" % (errno, strerror) - print "createDicTemVerbs" - - for row in self.__fileTemVerbs: - self.__dicTemVerbs[row[0].decode("utf-8")] = row[0].decode("utf-8") - - # Abre o arquivo que contem os artigos e preposicoes de acordo com o modelo de idioma passado na chamada e preenche o dicionario com os mesmos - def createDicWords(self): - try: - self.__fileWords = csv.reader(open(self.__path+"hWordsRemove.csv"), delimiter=";") - except IOError, (errno, strerror): - print "I/O error(%s): %s" % (errno, strerror) - print "createDicWords" - - for row in self.__fileWords: - self.__dicWords[row[0].decode("utf-8")] = row[0].decode("utf-8") - - # Abre o arquivo que contem os substantivos que sao comuns dos 2 generos e preenche o dicionario com os mesmos - def createDic2Gen(self): - try: - self.__file2Gen = csv.reader(open(self.__path+"subs2Generos.csv"), delimiter=";") - except IOError, (errno, strerror): - print "I/O error(%s): %s" % (errno, strerror) - print "createDic2Gen" - - for row in self.__file2Gen: - self.__dic2Gen[row[0].decode("utf-8")] = row[0].decode("utf-8") - - # Retorna o dicionario dos verbos no infinitivo - def getDicInf(self): - return self.__dicInf - - # Retorna o dicionario dos sinonimos - def getDicSin(self): - return self.__dicSin - - # Retorna o dicionario dos artigos e preposicoes a serem removidos pelo simplificador - def getDicWords(self): - return self.__dicWords - - # Retorna o dicionario dos substantivos a serem analisados pelo simplificador - def getDic2Gen(self): - return self.__dic2Gen - - # Retorna o dicionario dos tempos verbais - def getDicTemVerbs(self): - return self.__dicTemVerbs \ No newline at end of file diff --git a/src/alexp.py b/src/alexp.py new file mode 100644 index 0000000..a3430ee --- /dev/null +++ b/src/alexp.py @@ -0,0 +1,135 @@ +#! /usr/bin/env python2.6 +# -*- coding: utf-8 -*- + +#--------------------------------- + +# Editado: + +#Autor: Erickson Silva +#Email: + +#LAViD - Laboratório de Aplicações de Vídeo Digital + +#--------------------------------- + + +# Donatus Brazilian Portuguese Parser +# +# Copyright (C) 2010-2013 Leonel F. de Alencar +# +# Author: Leonel F. de Alencar +# Homepage: +# +# Project's URL: +# For license information, see LICENSE.TXT +# +# $Id: alexp.py $ + +"""Este módulo contém funções que permitem utilizar o Aelius para etiquetar uma sentença, construindo entradas lexicais com base nas etiquetas atribuídas às palavras da sentença. Essas entradas lexicais são integradas em uma gramática CFG dada, que é transformada em um parser, utilizado para gerar uma árvore de estrutura sintagmática da sentença. +""" +import re,nltk,platform, time, random +from os.path import expanduser +from os import environ +from Aelius.Extras import carrega +from Aelius import AnotaCorpus +from unicodedata import normalize + + +sentenca_anotada="" +sleep_times=[0.1,0.2] + +def toqueniza(s): + """Decodifica string utilizando utf-8, retornando uma lista de tokens em unicode. + """ + decodificada=s.decode("utf-8") + return AnotaCorpus.TOK_PORT.tokenize(decodificada) + +def getAnaliseMorfologica(): + return sentenca_anotada + #return [list(x) for x in sentenca_anotada] + +def etiquetaSentenca(s): + """Aplica um dos etiquetadores do Aelius na etiquetagem da sentença dada como lista de tokens. + """ + etiquetador = carrega("AeliusHunPos") + anotada = AnotaCorpus.anota_sentencas([s],etiquetador,"hunpos")[0] + while (anotada[0][1] is None): + time.sleep(random.choice(sleep_times)) + anotada = AnotaCorpus.anota_sentencas([s],etiquetador,"hunpos")[0] + #anotada[0] = (anotada[0][0].lower(), anotada[0][1]) + #return anotada + return [[x[0].lower(),x[1]] for x in anotada] + +def geraEntradasLexicais(lista): + """Gera entradas lexicais no formato CFG do NLTK a partir de lista de pares constituídos de tokens e suas etiquetas. + """ + entradas=[] + for e in lista: + # é necessário substituir símbolos como "-" e "+" do CHPTB + # que não são aceitos pelo NLTK como símbolos não terminais + c=re.sub(r"[-+]","_",e[1]) + c=re.sub(r"\$","_S",c) + entradas.append("%s -> '%s'" % (c, removeAcento(e[0]))) + return entradas + +def corrigeAnotacao(lista): + """Esta função deverá corrigir alguns dos erros de anotação mais comuns do Aelius. No momento, apenas é corrigida VB-AN depois de TR. + """ + i=1 + while i < len(lista): + if lista[i][1] == "VB-AN" and lista[i-1][1].startswith("TR"): + lista[i]=(lista[i][0],"VB-PP") + i+=1 + +def encontraArquivo(): + """Encontra arquivo na pasta vlibras-translate. + """ + so = platform.system() + if so == 'Windows': + return os.environ.get("HOMEDRIVE") + "\\vlibras-libs\\vlibras-translate\data\cfg.syn.nltk" + else: + return expanduser("~") + "/vlibras-translate/data/cfg.syn.nltk" + +def extraiSintaxe(): + """Extrai gramática armazenada em arquivo cujo caminho é definido relativamente ao diretório nltk_data. + """ + arquivo=encontraArquivo() + if arquivo: + f=open(arquivo,"rU") + sintaxe=f.read() + f.close() + return sintaxe + else: + print "Arquivo %s não encontrado em nenhum dos diretórios de dados do NLTK:\n%s" % (caminho,"\n".join(nltk.data.path)) + +def analisaSentenca(sentenca): + """Retorna lista de árvores de estrutura sintagmática para a sentença dada sob a forma de uma lista de tokens, com base na gramática CFG cujo caminho é especificado como segundo argumento da função. Esse caminho é relativo à pasta nltk_data da instalação local do NLTK. A partir da etiquetagem morfossintática da sentença são geradas entradas lexicais que passam a integrar a gramática CFG. O caminho da gramática e o parser gerado são armazenados como tupla na variável ANALISADORES. + """ + parser=constroiAnalisador(sentenca) + codificada=[removeAcento(w).encode("utf-8") for w in sentenca] + trees=parser.parse_one(codificada) + return trees + +def constroiAnalisador(s): + """Constrói analisador a partir de uma única sentença não anotada, dada como lista de tokens, e uma lista de regras sintáticas no formato CFG, armazenadas em arquivo. Esta função tem um bug, causado pela maneira como o Aelius etiqueta sentenças usando o módulo ProcessaNomesProprios: quando a sentença se inicia por paravra com inicial minúscula, essa palavra não é incorporada ao léxico, mas a versão com inicial maiúscula. + """ + global sentenca_anotada + sentenca_anotada=etiquetaSentenca(s) + corrigeAnotacao(sentenca_anotada) + entradas=geraEntradasLexicais(sentenca_anotada) + lexico="\n".join(entradas) + gramatica="%s\n%s" % (extraiSintaxe().strip(),lexico) + cfg=nltk.CFG.fromstring(gramatica) + return nltk.ChartParser(cfg) + +def removeAcento(texto): + return normalize('NFKD', texto.encode('utf-8').decode('utf-8')).encode('ascii', 'ignore') + +def exibeArvores(arvores): + """Função 'wrapper' para a função de exibição de árvores do NLTK""" + nltk.draw.draw_trees(*arvores) + +def run(sentenca): + tokens=toqueniza(sentenca) + tree=analisaSentenca(tokens) + return tree \ No newline at end of file diff --git a/src/new/AplicaRegras.py b/src/new/AplicaRegras.py deleted file mode 100644 index f08c2a5..0000000 --- a/src/new/AplicaRegras.py +++ /dev/null @@ -1,446 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -#Autor: Erickson Silva -#Email: - -#LAViD - Laboratório de Aplicações de Vídeo Digital - -import platform -import re -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): - - def __init__(self): - self.__root = self.get_root() - self.dicionarios = LerDicionarios() - # Dicionário de funcões do campo specific do arquivo de regras - 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"} - - self.__acoes = {"change_vb":self.get_vb_infinitivo, "concate_intens":self.get_token_intensidade} - - # Gera arvore a partir do arquivos regras.xml - 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() - - # Aplica regras morfológicas apartir do arquivo regras.xml - def aplicar_regras_morfo(self, lista, sint=False): - self.lista = list(lista) # Nova cópia da lista morfológica - self.lista_corrigida =[] # Lista morfológica após a aplicação das regras - - it = Iterator() - it.load(self.lista) - - while(it.has_next()): - for morpho in self.__root.findall('morphological'): - self.has_rule = False # Boolean caso encontre encontre regra compativel - for rule in morpho.findall('rule'): - # Verifica se a regra está ativa e se o nome da regra, ou o ínicio, é igual a tag de classificação do token atual - if rule.find('active').text == "true" and rule.get('name').split("_")[0] == it.get_ticket(): - count = int(rule.find('count').text) - self.lista_iteracoes = [] # Lista que conterá todas tuplas referentes a quantidade de classes da regra - - # Obtém o intervalo de tuplas de acordo com o número de classes da regra - try: - self.lista_iteracoes = it.get_interval(count) - print '# LISTA DA ITERAÇÂO: ' - print self.lista_iteracoes - except: - continue - - # Gera o nome da regra do intervalo de tuplas e verifica se é igual ao nome da regra em si - self.nome_regra = self.gerar_nome_regra(self.lista_iteracoes) - if rule.get('name') == self.nome_regra: - self.has_rule = True - self.count_iteracao_regra = -1 - - print "REGRA MORFOLÓGICA ENCONTRADA: " + rule.get('name') - - self.lista_iteracao_regra = [] # Lista temporária | Insere tokens após a aplicação das regras - - for classe in rule.iter('class'): # for nas tags class - action = classe.find('action') - newprop = classe.find('newprop') - newtoken = classe.find('newtoken') - newtokenpos = classe.find('newtokenpos') - specific = classe.find('specific') - - self.count_iteracao_regra += 1 - tupla = self.lista_iteracoes[self.count_iteracao_regra] - - if specific is not None: - result_specific = self.__especificos[specific.text](tupla[0]) - if result_specific is False: - print "REGRA MORFOLÓGICA " + rule.get('name') + " INVÁLIDA. PROCURANDO OUTRA..." - self.has_rule = False - break - - if action is not None: - action_text = action.text - if action_text == "remove": - self.lista_iteracao_regra.append(None) - continue - elif action_text == "invert": - self.lista_iteracao_regra.reverse() - elif self.__acoes.has_key(action_text): - result_action = self.__acoes[action_text](tupla[0]).lower() - self.lista_iteracao_regra.append([result_action, tupla[1]]) - else: - self.lista_iteracao_regra.append(tupla) - - if newprop is not None: - self.lista_iteracao_regra[self.count_iteracao_regra][1] = newprop.text - - if newtoken is not None: - if newtokenpos.text == "next": - self.lista_iteracao_regra.append([newtoken.text.lower(), "NTK"]) - elif newtokenpos.text == "previous": - self.lista_iteracao_regra.append(self.lista_iteracao_regra[-1]) - self.lista_iteracao_regra[-2] = [newtoken.text.lower(), "NTK"] - elif newtokenpos.text == "end": - print "TODO" - - if self.has_rule: - it.skip(count-1) - self.lista_corrigida.extend(self.lista_iteracao_regra) - break - - if self.has_rule is False: - print 'NÃO ACHOU REGRA - ' + it.get_word().encode('utf-8') - 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_nome_regra(rule.get('name')) - regra = self.separar_regra(nome_regra) - node_pai = tgrep_nodes(p_arvore, regra[0], search_leaves=False) - if node_pai and rule.find('active').text == "true": - node_pai = node_pai[0] - node_regra = tgrep_nodes(node_pai, regra[1].replace('$', '..'), search_leaves=False) - if node_regra: - node_esq_pos = tgrep_positions(node_pai, regra[1], search_leaves=False) - node_dir_pos = tgrep_positions(node_pai, regra[2], search_leaves=False) - if node_esq_pos and node_dir_pos: - print "REGRA SINTÁTICA ENCONTRADA: " + rule.get('name') - nodes_positions = node_esq_pos + node_dir_pos - self.count = -1 - self.has_rule = True - - count_temp = -1 - for classe in rule.findall('class'): - count_temp += 1 - leaves = node_pai[nodes_positions[count_temp]].leaves() - token = filter(None, leaves)[0] - specific = classe.find('specific') - if specific is not None: - result_specific = self.__especificos[specific.text](token) - if result_specific is False: - self.has_rule = False - - if self.has_rule is False: - print "REGRA SINTÁTICA " + rule.get('name') + " INVÁLIDA. PROCURANDO OUTRA..." - break - - nodes_deleted = [] - - for classe in rule.iter('class'): - action = classe.find('action') - newprop = classe.find('newprop') - - self.count += 1 - - if action is not None: - action_text = action.text - - if action_text == "remove": - pos_del = nodes_positions[self.count] - nodes_deleted.append(node_pai[pos_del]) - node_pai[pos_del] = None - continue - - elif action_text == "invert": - aux1 = node_pai[nodes_positions[self.count]] - aux2 = node_pai[nodes_positions[self.count+1]] - node_pai[nodes_positions[self.count]] = None - node_pai[nodes_positions[self.count+1]] = None - node_pai[nodes_positions[self.count]] = aux2 - node_pai[nodes_positions[self.count+1]] = aux1 - - ''' - elif self.__acoes.has_key(action_text): - leaves = node_pai[nodes_positions[self.count]].leaves() - token = filter(None, leaves)[0] - result_action = self.__acoes[action_text](token) - - #self.lista_iteracao_regra.append([result_action, tupla[1]]) - nodes_positions[self.count] = 'TODO' - - if action_text == "concate_intens": - leaves_prev = node_pai[nodes_positions[self.count-1]].leaves() - token_prev = filter(None, leaves_prev)[0] - title_text = classe.find('title').text - if title_text == "ADV-R": - node_prev = nodes_deleted.pop() - label_prev = node_prev[0][0].label() - token_prev = filter(None, node_pai[nodes_positions[count_temp-1]].leaves())[0] - token = filter(None, node_pai[nodes_positions[count_temp]].leaves())[0] - token_concate = token_prev + "_" + token - node_pai[nodes_positions[count_temp-1]][0][0][0] = token_concate - newprop = "" - if label_prev[:-2] == "VB": - newprop = "VBi" - elif label_prev[:-3] == "ADJ": - newprop = "ADJi" - - # TODO: Verifica qual newprop adicionada e remove o nó corrente - node_pai[nodes_positions[count_temp-1]][0][0].set_label(newprop) - pos_del = nodes_positions[self.count] - node_pai[pos_del] = None - - else: - token_prev = filter(None, nodes_deleted.pop().leaves())[0] - token = filter(None, node_pai[nodes_positions[count_temp]].leaves())[0] - token_concate = token + "_" + token_prev - node_pai[nodes_positions[count_temp]][0][0][0] = token_concate - - elif action_text == "concate_neg": - print "TODO" - ''' - - if newprop is not None: - node_pai[nodes_positions[self.count]].set_label(newprop.text) - - break - - return self.converter_arv_para_lista(p_arvore) - - - # Aplica regras morfológicas na árvore sintática - def adaptar_regras_morfo_arvore(self, lista, arvore): - lista_pos_arv = [] - # Pega as posições das classificações morfológicas dos tokens na arvore sintática - for tupla in lista: - string_grep = self.corrigir_nome_regra(tupla[1]) + " < " + tupla[0].lower() - node = tgrep_positions(arvore, string_grep) - if not node: - string_grep = self.corrigir_nome_regra(tupla[1]) + " < " + self.remover_acento(tupla[0].lower()) - node = tgrep_positions(arvore, string_grep) - if node[0] in lista_pos_arv: - node.reverse() - lista_pos_arv.append(node[0]) - - # Aplica regras morfológicas na lista - morfo = self.aplicar_regras_morfo(lista, sint=True) - - # Corrige arvore de acordo com a lista após aplicar as regras morfológicas - for i in range(0, len(morfo)): - if morfo[i] is not None and morfo[i][1] == "NTK": - new_node = self.gerar_no(morfo[i]) - arvore[lista_pos_arv[i-1][:-2]].insert(2, new_node) - try: - lista_pos_arv.insert(i,lista_pos_arv[i]) - except: - continue - - 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]] = 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(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(morfo[i][1]) - - # Converte árvore sintática para uma lista de tuplas (igual a lista morfológica) - def converter_arv_para_lista(self, arvore): - folhas = filter(None, 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_nome_regra(node.label())]) - return lista_nodes - - def remover_acento(self, texto): - return normalize('NFKD', texto.encode('utf-8').decode('utf-8')).encode('ascii', 'ignore') - - # Gera um ParentedTree do NLTK apartir da string recebida - def gerar_no(self, s): - all_ptrees = [] - t_string = '('+s[1] + ' ' + s[0]+')' - ptree = ParentedTree.convert(Tree.fromstring(t_string)) - all_ptrees.extend(t for t in ptree.subtrees() - if isinstance(t, Tree)) - return ptree - - # Corrige nome da regra descrita no arquivo de regras para como está na árvore sintática - def corrigir_nome_regra(self, anotacao): - split = anotacao.split('_') - for i in range(0, len(split)): - split[i] = re.sub(r"[-+]","_", split[i]) - split[i] = re.sub(r"\$","_S",split[i]) - return "-".join(split).encode('utf-8') - - # Separa a regra por nó pai e seus filhos - 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 - - # Gera nome de regra apartir de uma lista - def gerar_nome_regra(self, lista): - nome_regra = [] - for t in lista: - nome_regra.append(t[1]) - return "_".join(nome_regra) - - def verificar_adv_tempo(self, token): - for tupla in self.lista: - if self.dicionarios.has_adverbio_tempo(tupla[0]): - return True - return False - - def verificar_excecao_plural(self, token): - return self.dicionarios.has_excecao_plural(token) - - def verificar_vb_infinitivo(self, token): - return self.dicionarios.has_verbo_infinitivo(token) - - 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): - return self.dicionarios.has_verbo_muda_negacao(token) - - def get_vb_infinitivo(self, token): - if self.dicionarios.has_verbo_infinitivo(token): - return self.dicionarios.get_verbo_infinitivo(token) - return token - - def get_token_intensidade(self, token): - print 'TODO' - - - # Simplifica a sentença para que possa evitar a ditalogia - def simplificar_sentenca(self, lista): - lista_simplificada = list(lista) - it = Iterator() - it.load(lista_simplificada) - num = False - while(it.has_next()): - tag = it.get_ticket() - - if tag == "NUM": - num = True - - if tag[-2:] == "-P" and self.verificar_excecao_plural(it.get_word()): - singular = self.analisar_plural(it.get_word()) - lista_simplificada[it.get_count()][0] = singular - - if num: - return self.converter_extenso(lista_simplificada) - return lista_simplificada - - # Alterar uma palavra do plural para o singular - 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 - - # Converter número por extenso para numeral - def converter_extenso(self, lista): - lista_extensos = [] - indices_deletar = [] - count = 0 - is_sequence = False - - for i in range(0, len(lista)): - token = lista[i][0] - tag = lista[i][1] - if tag == "NUM": - # Verifico se não há sequência de obtenção de extenso em andamento para começar a obter um nova sequência - if (is_sequence is False): # and len(lista_extensos) == count (???) - lista_extensos.append([i,[token]]) # i = Posição do primeiro extenso encontrado, token = número por extenso - is_sequence = True - else: - lista_extensos[count][1].append(token) # Pego número por extenso que está na sequência e adiciona na lista - indices_deletar.append(i) # Insiro indice na lista para ser removido depois - elif (is_sequence): - # Se o token anterior e o próximo foram classificados como número, e o token atual como conjunção, significa que podemos remove-lo - if ((lista[i-1][1] == "NUM") and (lista[i+1][1] == "NUM") and (tag == "CONJ")): - indices_deletar.append(i) - else: - # A sequência foi quebrada, o que significa que selecionamos o extenso do número por completo - # Podemos agora procurar por outra sequencia de número por extenso na lista - is_sequence = False - count += 1 - - for extenso in lista_extensos: - ext = convert_extenso(' '.join(extenso[1])) - lista[extenso[0]] = [ext, "NUM"] - - deque((list.pop(lista, i) for i in sorted(indices_deletar, reverse=True)), maxlen=0) - return lista \ No newline at end of file diff --git a/src/new/AplicaSinonimos.py b/src/new/AplicaSinonimos.py deleted file mode 100644 index f2f1030..0000000 --- a/src/new/AplicaSinonimos.py +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -#Autor: Erickson Silva -#Email: - -#LAViD - Laboratório de Aplicações de Vídeo Digital - -import os -import csv -import sys -from nltk.tree import Tree -from LerDicionarios import * - -class AplicaSinonimos(object): - """Classe para aplicar sinonimos após a aplicação de regras morfológicas/sintáticas""" - - def __init__(self): - self.dicionarios = LerDicionarios() - - # Itera sobre os tokens obtendo os sinonimos - def aplicar_sinonimos(self, lista_anotada): - lista_corrigida = [] - for tupla in lista_anotada: - sinonimo = self.verificar_sinonimo(tupla[0]) - lista_corrigida.append(sinonimo) - return " ".join(lista_corrigida) - - # Verifica se há sinonimo do token - def verificar_sinonimo(self, token): - if self.dicionarios.has_sinonimo(token): - return self.dicionarios.get_sinonimo(token) - return token \ No newline at end of file diff --git a/src/new/ConverteExtenso.py b/src/new/ConverteExtenso.py deleted file mode 100644 index bb729ed..0000000 --- a/src/new/ConverteExtenso.py +++ /dev/null @@ -1,154 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -#Autor: Erickson Silva -#Email: - -#LAViD - Laboratório de Aplicações de Vídeo Digital - -import sys -from unicodedata import normalize -from Iterator import * - -num = {"zero":0, "um":1, "dois":2, "tres":3, "quatro":4, "cinco":5, "seis":6, -"sete":7, "oito":8, "nove":9} - -ext = [{"um":"1", "dois":"2", "tres":"3", "quatro":"4", "cinco":"5", "seis":"6", -"sete":"7", "oito":"8", "nove":"9", "dez":"10", "onze":"11", "doze":"12", -"treze":"13", "quatorze":"14", "quinze":"15", "dezesseis":"16", -"dezessete":"17", "dezoito":"18", "dezenove":"19"}, {"vinte":"2", "trinta":"3", -"quarenta":"4", "cinquenta":"5", "sessenta":"6", "setenta":"7", "oitenta":"8", -"noventa":"9"}, {"cento":"1", "cem":"1", "duzentos":"2", "trezentos":"3", -"quatrocentos":"4", "quinhentos":"5", "seissentos":"6", "setessentos":"7", -"oitocentos":"8", "novecentos":"9"}] - -und = {"mil":1000, "milhao":1000000, "bilhao":1000000000, "trilhao":1000000000000} -unds = {"mil":"000", "milhao":"000000","milhoes":"000000", "bilhao":"000000000","bilhoes":"000000000", "trilhao":"000000000000", "trilhoes":"000000000000"} - - - -def oneDigit(x): - return ext[0][x] - -def twoDigit(x): - try: - return ext[1][x[0]]+ext[0][x[1]] - except: - return ext[1][x[0]]+"0" - -def threeDigit(x): - return ext[2][x[0]]+ext[1][x[1]]+ext[0][x[2]] - -# Não faço mais a minima idéia de como fiz isso, só sei que funciona! -def extensoUnit(n): - sn = n.split(",") - size = len(sn) - firstWord = sn[0] - endWord = "" - numExt = "" - - if(unds.has_key(sn[size-1])): - size -= 1 - endWord = sn[size] - del sn[size] - - if(ext[0].has_key(firstWord)): - numExt = oneDigit(firstWord) - - elif (ext[1].has_key(firstWord)): - numExt = twoDigit(sn) - - elif (ext[2].has_key(firstWord)): - if(size == 1): - numExt = ext[2][firstWord]+"00" - elif (size == 2): - if(sn[1] == "dez"): - numExt = ext[2][firstWord]+oneDigit(sn[1]) - try: - numExt = ext[2][firstWord]+"0"+oneDigit(sn[1]) - except: - numExt = ext[2][firstWord]+twoDigit([sn[1]]) - else: - numExt = threeDigit(sn) - - if(endWord != ""): - numExt = numExt+unds[endWord] - - return numExt - - -''' -Comece com uma lista vazia. Itere pelas palavras da string da esquerda -para direita. Ao encontrar um numeral, adicione o número à lista se a -última palavra foi uma escala, ou some ao último numero da lista se a -última palavra foi um numeral. Ao encontrar uma escala, multiplique o -último número da lista de acordo. Quando terminar, some tudo e retorne -o resultado. -''' - -# TODO: Refatorar para nao usar mais o extensoUnit -def convert_extenso(extenso): - global newToken, auxToken - extensoQuebrado = extenso.lower().split(" ") - nums = [] - it = Iterator() - it.load(extensoQuebrado) - while(it.has_next()): - token = simplifica(it.get_token()) - tokenAnterior = simplifica(it.get_token(-1)) - if (und.has_key(token)): - if(it.get_count() == 0): - nums.append(und[token]) - else: - newToken = und[token] * int(nums[-1]) - nums[-1] = newToken - else: - if (num.has_key(token)): - auxToken = num[token] - elif (not und.has_key(token)): - auxToken = extensoUnit(token) - - if((not und.has_key(tokenAnterior)) and it.get_count() > 0): - newToken = int(auxToken) + int(nums[-1]) - nums[-1] = newToken - else: - nums.append(auxToken) - return soma(nums) - -def soma(lista): - soma = 0 - for i in lista: - soma += int(i) - return soma - -def simplifica(txt): - newToken = "" - try: - newToken = normalize('NFKD', txt.decode('utf-8')).encode('ASCII','ignore') - except: - newToken = normalize('NFKD', txt.decode('iso-8859-1')).encode('ASCII','ignore') - - if(newToken[-3:] == "oes"): - return newToken[:-3] + "ao" - - return newToken - -# Test -''' -if __name__ == '__main__': - n = sys.argv[1] - return extenso(n) - arquivoExts = open('exts', 'r') - listaExts = arquivoExts.readlines() - arquivoNums = open('nums', 'r') - listaNums = arquivoNums.readlines() - for i in range(0,500): - n = listaNums[i].replace("\n","") - e = listaExts[i].replace("\n","") - numNew = extenso(e) - if (str(numNew) != n): - print n + " != " + str(numNew) - #else: - # print "OK: " + n + " == " + str(numNew) -''' - diff --git a/src/new/Iterator.py b/src/new/Iterator.py deleted file mode 100644 index c2fbe03..0000000 --- a/src/new/Iterator.py +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -#Autor: Erickson Silva -#Email: - -#LAViD - Laboratório de Aplicações de Vídeo Digital - -class Iterator(object): - """Classe para iterar sobre as tuplas (palavra,etiqueta) após análise morfologica""" - - def init(self): - self.count = -1 - - def load(self, lista): - self.reset() - self.list = list(lista); - self.size = len(lista) - - def reset(self): - self.count = -1 - - def get_size(self): - return self.size - - def get_count(self): - return self.count - - def get_token(self, i=None): - if(i != None): - return self.list[self.count+(i)] - return self.list[self.count] - - def get_word(self): - return self.get_token()[0] - - def get_ticket(self): - return self.get_token()[1] - - def get_next_word(self): - return self.get_token(1)[0] - - def get_next_ticket(self): - return self.get_token(1)[1] - - def get_prev_word(self): - return self.get_token(-1)[0] - - def get_prev_ticket(self): - return self.get_token(-1)[1] - - def get_interval(self, n): - if self.count+n > self.size: - raise IndexError - return self.list[self.count:self.count+n] - - def skip(self, n): - self.count += n - - def has_next(self): - if(self.count < self.size-1): - self.count += 1 - return True - return False \ No newline at end of file diff --git a/src/new/LerDicionarios.py b/src/new/LerDicionarios.py deleted file mode 100644 index 7be223c..0000000 --- a/src/new/LerDicionarios.py +++ /dev/null @@ -1,212 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -#Autor: Erickson Silva -#Email: - -#LAViD - Laboratório de Aplicações de Vídeo Digital - -from os.path import expanduser -from os import environ -import csv -import platform - -class LerDicionarios(object): - - def __init__(self): - self.path = self.get_path() - self.set_exc_plural = [] - self.dic_adv_intensidade = {} - self.set_adv_tempo = [] - self.set_art = [] - self.set_prep = [] - self.dic_sin = {} - self.set_sb_2_gen = [] - self.dic_vb_infinitivo = {} - self.set_vb_ligacao = [] - self.dic_vb_muda_negacao = [] - self.file = '' - self.carregar_dicionarios() - - def get_path(self): - if platform.system() == 'Windows': - return os.environ.get("HOMEDRIVE") + "\\vlibras-libs\\vlibras-translate\data\\" - return expanduser("~") + "/vlibras-translate/data/" - - def carregar_dicionarios(self): - self.carregar_excecoes_plural() - self.carregar_adverbios_intensidade() - self.carregar_adverbios_tempo() - self.carregar_artigos() - self.carregar_preposicoes() - self.carregar_sinonimos() - self.carregar_subs_2_generos() - self.carregar_verbos_infinitivo() - self.carregar_verbos_ligacao() - self.carregar_verbos_muda_negacao - - - def carregar_excecoes_plural(self): - try: - self.file = csv.reader(open(self.path+"excecoesPlural.csv")) - except IOError, (errno, strerror): - print "I/O error(%s): %s" % (errno, strerror) - print "carregar_excecoes_plural" - - rows = [] - for row in self.file: - rows.append(row[0].decode("utf-8")) - self.set_exc_plural = set(rows) - - def carregar_adverbios_intensidade(self): - try: - self.file = csv.reader(open(self.path+"adverbiosIntensidade.csv"), delimiter=";") - except IOError, (errno, strerror): - print "I/O error(%s): %s" % (errno, strerror) - print "carregar_adverbios_intensidade" - - for row in self.file: - if row[1] != "": - self.dic_adv_intensidade[row[0].decode("utf-8")] = row[1].decode("utf-8") - - def carregar_adverbios_tempo(self): - try: - self.file = csv.reader(open(self.path+"adverbiosTempo.csv")) - except IOError, (errno, strerror): - print "I/O error(%s): %s" % (errno, strerror) - print "carregar_adverbios_tempo" - - rows = [] - for row in self.file: - rows.append(row[0].decode("utf-8")) - self.set_adv_tempo = set(rows) - - def carregar_artigos(self): - try: - self.file = csv.reader(open(self.path+"artigos.csv")) - except IOError, (errno, strerror): - print "I/O error(%s): %s" % (errno, strerror) - print "carregar_artigos" - - rows = [] - for row in self.file: - rows.append(row[0].decode("utf-8")) - self.set_art = set(rows) - - def carregar_preposicoes(self): - try: - self.file = csv.reader(open(self.path+"preposicoes.csv")) - except IOError, (errno, strerror): - print "I/O error(%s): %s" % (errno, strerror) - print "carregar_preposicoes" - - rows = [] - for row in self.file: - rows.append(row[0].decode("utf-8")) - self.set_prep = set(rows) - - def carregar_sinonimos(self): - try: - self.file = csv.reader(open(self.path+"sinonimos.csv"), delimiter=";") - except IOError, (errno, strerror): - print "I/O error(%s): %s" % (errno, strerror) - print "carregar_sinonimos" - - for row in self.file: - if row[1] != "": - try: - self.dic_sin[row[0].decode("utf-8")] = row[1].decode("utf-8") - except UnicodeDecodeError: - self.dic_sin[row[0].decode('iso8859-1').encode('utf-8').decode('utf-8')] = row[1].decode('iso8859-1').encode('utf-8').decode('utf-8') - - def carregar_subs_2_generos(self): - try: - self.file = csv.reader(open(self.path+"subs2Generos.csv")) - except IOError, (errno, strerror): - print "I/O error(%s): %s" % (errno, strerror) - print "carregar_subs_2_generos" - - rows = [] - for row in self.file: - rows.append(row[0].decode('iso8859-1').encode('utf-8').decode('utf-8')) - self.set_sb_2_gen = set(rows) - - def carregar_verbos_infinitivo(self): - try: - self.file = csv.reader(open(self.path+"verbosInfinitivo.csv"), delimiter=";") - except IOError, (errno, strerror): - print "I/O error(%s): %s" % (errno, strerror) - print "carregar_verbos_infinitivo" - - for row in self.file: - if row[1] != "": - try: - self.dic_vb_infinitivo[row[0].decode("utf-8")] = row[1].decode("utf-8") - except UnicodeDecodeError: - self.dic_vb_infinitivo[row[0].decode('iso8859-1').encode('utf-8').decode('utf-8')] = row[1].decode('iso8859-1').encode('utf-8').decode('utf-8') - - def carregar_verbos_ligacao(self): - try: - self.file = csv.reader(open(self.path+"verbosLigacao.csv")) - except IOError, (errno, strerror): - print "I/O error(%s): %s" % (errno, strerror) - print "carregar_verbos_ligacao" - - rows = [] - for row in self.file: - rows.append(row[0].decode("utf-8")) - self.set_vb_ligacao = set(rows) - - - def carregar_verbos_muda_negacao(self): - try: - self.file = csv.reader(open(self.path+"verbosMudaNegacao.csv"), delimiter=";") - except IOError, (errno, strerror): - print "I/O error(%s): %s" % (errno, strerror) - print "carregar_verbos_muda_negacao" - - for row in self.file: - if row[1] != "": - self.dic_vb_muda_negacao[row[0].decode("utf-8")] = row[1].decode("utf-8") - - def has_excecao_plural(self, token): - return token not in self.set_exc_plural - - def has_adverbio_intensidade(self, token): - return self.dic_adv_intensidade.has_key(token) - - def has_adverbio_tempo(self, token): - return token in self.set_adv_tempo - - def has_artigo(self, token): - return token in self.set_art - - def has_preposicao(self, token): - return token in self.set_prep - - def has_sinonimo(self, token): - return self.dic_sin.has_key(token) - - def has_subst_2_generos (self, token): - return token in self.set_sb_2_gen - - def has_verbo_infinitivo(self, token): - return self.dic_vb_infinitivo.has_key(token) - - def has_verbo_ligacao(self, token): - return token in self.set_vb_ligacao - - def has_verbo_muda_negacao(self, token): - return self.dic_vb_muda_negacao.has_key(token) - - def get_adverbio_intensidade(self, token): - return self.dic_adv_intensidade[token] - - def get_sinonimo(self, token): - return self.dic_sin[token] - - def get_verbo_infinitivo(self, token): - return self.dic_vb_infinitivo[token] - - def get_verbo_muda_negacao(self, token): - return self.dic_vb_muda_negacao[token] \ No newline at end of file diff --git a/src/new/PortGlosa.py b/src/new/PortGlosa.py deleted file mode 100644 index a8f70ba..0000000 --- a/src/new/PortGlosa.py +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -#Autor: Erickson Silva -#Email: - -#LAViD - Laboratório de Aplicações de Vídeo Digital - -from TraduzSentencas import * - -def traduzir(texto): - glosa = iniciar_traducao(texto) - if glosa: - return glosa - return "selecione_texto" - -def iniciar_traducao(texto): - texto_quebrado = quebrar_texto(texto) - num_threads = len(texto_quebrado) - texto_traduzido = [] - threads = [] - - for i in range(num_threads): - if texto_quebrado[i] > 0 and texto_quebrado[i] != " ": - threads.insert(i, TraduzSentencas(texto_quebrado[i])) - threads[i].start() - for i in range(num_threads): - threads[i].join() - texto_traduzido.append(threads[i].obter_glosa()) - - try: - return " ".join(texto_traduzido) - except: - return None - -def quebrar_texto(texto): - quantidade_pontos = texto.count('. ') - sentencas = [] - for i in range(quantidade_pontos): - posicao_ponto = texto.find('.') - if texto[posicao_ponto+2].isupper(): - sentencas.append(texto[:posicao_ponto]) - texto = texto[posicao_ponto+2:] - if len(texto) > 0: - sentencas.append(texto) - return sentencas - -def ajuda(): - #TODO: Adicionar um pequeno tuto aqui - print "Help" \ No newline at end of file diff --git a/src/new/TraduzSentencas.py b/src/new/TraduzSentencas.py deleted file mode 100644 index f5e1c86..0000000 --- a/src/new/TraduzSentencas.py +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -#Autor: Erickson Silva -#Email: - -#LAViD - Laboratório de Aplicações de Vídeo Digital - -from threading import Thread -import alexp -from AplicaSinonimos import * -from AplicaRegras import * -import logging - -class TraduzSentencas(Thread): - - def __init__(self, sentenca): - Thread.__init__(self) - self.sentenca = sentenca - self.glosa = "" - self.aplic_sinonimos = AplicaSinonimos() - self.aplic_regras = AplicaRegras() - logging.basicConfig(filename='translate.log', - format='%(asctime)s - %(levelname)s:\n%(message)s\n\n\n##############################################\n\n', - level=logging.ERROR) - - - def run(self): - try: - analise_sintatica = alexp.run(self.sentenca) - except Exception as ex: - self.salvar_log(str(ex)) - analise_sintatica = None - - analise_morfologica = alexp.getAnaliseMorfologica() - - if (isinstance(analise_sintatica,type(None))): - print "# ANÁLISE MORFOLÓGICA" - regras_aplicadas = self.aplic_regras.aplicar_regras_morfo(analise_morfologica) - else: - print "# ANÁLISE SINTÁTICA" - regras_aplicadas = self.aplic_regras.aplicar_regras_sint(analise_morfologica, analise_sintatica) - - sentenca_corrigida = self.aplic_regras.simplificar_sentenca(regras_aplicadas) - sinonimos_aplicados = self.aplic_sinonimos.aplicar_sinonimos(sentenca_corrigida) - self.glosa = sinonimos_aplicados.upper().encode('utf-8') - - def obter_glosa(self): - return self.glosa - - def salvar_log(self, erro): - logging.error(erro) \ No newline at end of file diff --git a/src/new/alexp.py b/src/new/alexp.py deleted file mode 100644 index a3430ee..0000000 --- a/src/new/alexp.py +++ /dev/null @@ -1,135 +0,0 @@ -#! /usr/bin/env python2.6 -# -*- coding: utf-8 -*- - -#--------------------------------- - -# Editado: - -#Autor: Erickson Silva -#Email: - -#LAViD - Laboratório de Aplicações de Vídeo Digital - -#--------------------------------- - - -# Donatus Brazilian Portuguese Parser -# -# Copyright (C) 2010-2013 Leonel F. de Alencar -# -# Author: Leonel F. de Alencar -# Homepage: -# -# Project's URL: -# For license information, see LICENSE.TXT -# -# $Id: alexp.py $ - -"""Este módulo contém funções que permitem utilizar o Aelius para etiquetar uma sentença, construindo entradas lexicais com base nas etiquetas atribuídas às palavras da sentença. Essas entradas lexicais são integradas em uma gramática CFG dada, que é transformada em um parser, utilizado para gerar uma árvore de estrutura sintagmática da sentença. -""" -import re,nltk,platform, time, random -from os.path import expanduser -from os import environ -from Aelius.Extras import carrega -from Aelius import AnotaCorpus -from unicodedata import normalize - - -sentenca_anotada="" -sleep_times=[0.1,0.2] - -def toqueniza(s): - """Decodifica string utilizando utf-8, retornando uma lista de tokens em unicode. - """ - decodificada=s.decode("utf-8") - return AnotaCorpus.TOK_PORT.tokenize(decodificada) - -def getAnaliseMorfologica(): - return sentenca_anotada - #return [list(x) for x in sentenca_anotada] - -def etiquetaSentenca(s): - """Aplica um dos etiquetadores do Aelius na etiquetagem da sentença dada como lista de tokens. - """ - etiquetador = carrega("AeliusHunPos") - anotada = AnotaCorpus.anota_sentencas([s],etiquetador,"hunpos")[0] - while (anotada[0][1] is None): - time.sleep(random.choice(sleep_times)) - anotada = AnotaCorpus.anota_sentencas([s],etiquetador,"hunpos")[0] - #anotada[0] = (anotada[0][0].lower(), anotada[0][1]) - #return anotada - return [[x[0].lower(),x[1]] for x in anotada] - -def geraEntradasLexicais(lista): - """Gera entradas lexicais no formato CFG do NLTK a partir de lista de pares constituídos de tokens e suas etiquetas. - """ - entradas=[] - for e in lista: - # é necessário substituir símbolos como "-" e "+" do CHPTB - # que não são aceitos pelo NLTK como símbolos não terminais - c=re.sub(r"[-+]","_",e[1]) - c=re.sub(r"\$","_S",c) - entradas.append("%s -> '%s'" % (c, removeAcento(e[0]))) - return entradas - -def corrigeAnotacao(lista): - """Esta função deverá corrigir alguns dos erros de anotação mais comuns do Aelius. No momento, apenas é corrigida VB-AN depois de TR. - """ - i=1 - while i < len(lista): - if lista[i][1] == "VB-AN" and lista[i-1][1].startswith("TR"): - lista[i]=(lista[i][0],"VB-PP") - i+=1 - -def encontraArquivo(): - """Encontra arquivo na pasta vlibras-translate. - """ - so = platform.system() - if so == 'Windows': - return os.environ.get("HOMEDRIVE") + "\\vlibras-libs\\vlibras-translate\data\cfg.syn.nltk" - else: - return expanduser("~") + "/vlibras-translate/data/cfg.syn.nltk" - -def extraiSintaxe(): - """Extrai gramática armazenada em arquivo cujo caminho é definido relativamente ao diretório nltk_data. - """ - arquivo=encontraArquivo() - if arquivo: - f=open(arquivo,"rU") - sintaxe=f.read() - f.close() - return sintaxe - else: - print "Arquivo %s não encontrado em nenhum dos diretórios de dados do NLTK:\n%s" % (caminho,"\n".join(nltk.data.path)) - -def analisaSentenca(sentenca): - """Retorna lista de árvores de estrutura sintagmática para a sentença dada sob a forma de uma lista de tokens, com base na gramática CFG cujo caminho é especificado como segundo argumento da função. Esse caminho é relativo à pasta nltk_data da instalação local do NLTK. A partir da etiquetagem morfossintática da sentença são geradas entradas lexicais que passam a integrar a gramática CFG. O caminho da gramática e o parser gerado são armazenados como tupla na variável ANALISADORES. - """ - parser=constroiAnalisador(sentenca) - codificada=[removeAcento(w).encode("utf-8") for w in sentenca] - trees=parser.parse_one(codificada) - return trees - -def constroiAnalisador(s): - """Constrói analisador a partir de uma única sentença não anotada, dada como lista de tokens, e uma lista de regras sintáticas no formato CFG, armazenadas em arquivo. Esta função tem um bug, causado pela maneira como o Aelius etiqueta sentenças usando o módulo ProcessaNomesProprios: quando a sentença se inicia por paravra com inicial minúscula, essa palavra não é incorporada ao léxico, mas a versão com inicial maiúscula. - """ - global sentenca_anotada - sentenca_anotada=etiquetaSentenca(s) - corrigeAnotacao(sentenca_anotada) - entradas=geraEntradasLexicais(sentenca_anotada) - lexico="\n".join(entradas) - gramatica="%s\n%s" % (extraiSintaxe().strip(),lexico) - cfg=nltk.CFG.fromstring(gramatica) - return nltk.ChartParser(cfg) - -def removeAcento(texto): - return normalize('NFKD', texto.encode('utf-8').decode('utf-8')).encode('ascii', 'ignore') - -def exibeArvores(arvores): - """Função 'wrapper' para a função de exibição de árvores do NLTK""" - nltk.draw.draw_trees(*arvores) - -def run(sentenca): - tokens=toqueniza(sentenca) - tree=analisaSentenca(tokens) - return tree \ No newline at end of file -- libgit2 0.21.2